1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
|
/*
* Copyright (c) 2000-2001, Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Boris Popov.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: smbfs_node.h,v 1.31.52.1 2005/05/27 02:35:28 lindak Exp $
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright 2018 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _FS_SMBFS_NODE_H_
#define _FS_SMBFS_NODE_H_
/*
* Much code copied into here from Sun NFS.
* Compare with nfs_clnt.h
*/
#include <sys/avl.h>
#include <sys/list.h>
#include <netsmb/smb_subr.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Cache whole directories (not yet)
*/
typedef struct rddir_cache {
lloff_t _cookie; /* cookie used to find this cache entry */
lloff_t _ncookie; /* cookie used to find the next cache entry */
char *entries; /* buffer containing dirent entries */
int eof; /* EOF reached after this request */
int entlen; /* size of dirent entries in buf */
int buflen; /* size of the buffer used to store entries */
int flags; /* control flags, see below */
kcondvar_t cv; /* cv for blocking */
int error; /* error from RPC operation */
kmutex_t lock;
uint_t count; /* reference count */
avl_node_t tree; /* AVL tree links */
} rddir_cache;
#define smbfs_cookie _cookie._p._l
#define smbfs_ncookie _ncookie._p._l
#define smbfs3_cookie _cookie._f
#define smbfs3_ncookie _ncookie._f
#define RDDIR 0x1 /* readdir operation in progress */
#define RDDIRWAIT 0x2 /* waiting on readdir in progress */
#define RDDIRREQ 0x4 /* a new readdir is required */
#define RDDIRCACHED 0x8 /* entry is in the cache */
#define HAVE_RDDIR_CACHE(rp) (avl_numnodes(&(rp)->r_dir) > 0)
/*
* A homegrown reader/writer lock implementation. It addresses
* two requirements not addressed by the system primitives. They
* are that the `enter" operation is optionally interruptible and
* that that they can be re`enter'ed by writers without deadlock.
*/
typedef struct smbfs_rwlock {
int count;
int waiters;
kthread_t *owner;
kmutex_t lock;
kcondvar_t cv;
} smbfs_rwlock_t;
/*
* The format of the smbfs node header, which contains the
* fields used to link nodes in the AVL tree, and those
* fields needed by the AVL node comparison functions.
* It's a separate struct so we can call avl_find with
* this relatively small struct as a stack local.
*
* The AVL tree is mntinfo.smi_hash_avl,
* and its lock is mntinfo.smi_hash_lk.
*/
typedef struct smbfs_node_hdr {
/*
* Our linkage in the node cache AVL tree.
*/
avl_node_t hdr_avl_node;
/*
* Identity of this node: The full path name,
* in server form, relative to the share root.
*/
char *hdr_n_rpath;
int hdr_n_rplen;
} smbfs_node_hdr_t;
/*
* Below is the SMBFS-specific representation of a "node".
* This struct is a mixture of Sun NFS and Darwin code.
* Fields starting with "r_" came from NFS struct "rnode"
* and fields starting with "n_" came from Darwin, or
* were added during the Solaris port. We have avoided
* renaming fields so we would not cause excessive
* changes in the code using this struct.
*
* Now using an AVL tree instead of hash lists, but kept the
* "hash" in some member names and functions to reduce churn.
* One AVL tree per mount replaces the global hash buckets.
*
* Notes carried over from the NFS code:
*
* The smbnode is the "inode" for remote files. It contains all the
* information necessary to handle remote file on the client side.
*
* Note on file sizes: we keep two file sizes in the smbnode: the size
* according to the client (r_size) and the size according to the server
* (r_attr.fa_size). They can differ because we modify r_size during a
* write system call (smbfs_rdwr), before the write request goes over the
* wire (before the file is actually modified on the server). If an OTW
* request occurs before the cached data is written to the server the file
* size returned from the server (r_attr.fa_size) may not match r_size.
* r_size is the one we use, in general. r_attr.fa_size is only used to
* determine whether or not our cached data is valid.
*
* Each smbnode has 3 locks associated with it (not including the smbnode
* "hash" AVL tree and free list locks):
*
* r_rwlock: Serializes smbfs_write and smbfs_setattr requests
* and allows smbfs_read requests to proceed in parallel.
* Serializes reads/updates to directories.
*
* r_lkserlock: Serializes lock requests with map, write, and
* readahead operations.
*
* r_statelock: Protects all fields in the smbnode except for
* those listed below. This lock is intented
* to be held for relatively short periods of
* time (not accross entire putpage operations,
* for example).
*
* The following members are protected by the mutex smbfreelist_lock:
* r_freef
* r_freeb
*
* The following members are protected by the AVL tree rwlock:
* r_avl_node (r__hdr.hdr_avl_node)
*
* Note: r_modaddr is only accessed when the r_statelock mutex is held.
* Its value is also controlled via r_rwlock. It is assumed that
* there will be only 1 writer active at a time, so it safe to
* set r_modaddr and release r_statelock as long as the r_rwlock
* writer lock is held.
*
* 64-bit offsets: the code formerly assumed that atomic reads of
* r_size were safe and reliable; on 32-bit architectures, this is
* not true since an intervening bus cycle from another processor
* could update half of the size field. The r_statelock must now
* be held whenever any kind of access of r_size is made.
*
* Lock ordering:
* r_rwlock > r_lkserlock > r_statelock
*/
typedef struct smbnode {
/* Our linkage in the node cache AVL tree (see above). */
smbfs_node_hdr_t r__hdr;
/* short-hand names for r__hdr members */
#define r_avl_node r__hdr.hdr_avl_node
#define n_rpath r__hdr.hdr_n_rpath
#define n_rplen r__hdr.hdr_n_rplen
smbmntinfo_t *n_mount; /* VFS data */
vnode_t *r_vnode; /* associated vnode */
/*
* Linkage in smbfreelist, for reclaiming nodes.
* Lock for the free list is: smbfreelist_lock
*/
struct smbnode *r_freef; /* free list forward pointer */
struct smbnode *r_freeb; /* free list back pointer */
smbfs_rwlock_t r_rwlock; /* serialize write/setattr requests */
smbfs_rwlock_t r_lkserlock; /* serialize lock with other ops */
kmutex_t r_statelock; /* protect (most) smbnode fields */
/*
* File handle, directory search handle,
* and reference counts for them, etc.
* Lock for these is: r_lkserlock
*/
int n_dirrefs;
struct smbfs_fctx *n_dirseq; /* ff context */
int n_dirofs; /* last ff offset */
int n_fidrefs;
smb_fh_t *n_fid; /* file handle */
enum vtype n_ovtype; /* vnode type opened */
/*
* Misc. bookkeeping
*/
cred_t *r_cred; /* current credentials */
u_offset_t r_nextr; /* next read offset (read-ahead) */
long r_mapcnt; /* count of mmapped pages */
uint_t r_inmap; /* to serialize read/write and mmap */
uint_t r_count; /* # of refs not reflect in v_count */
uint_t r_awcount; /* # of outstanding async write */
uint_t r_gcount; /* getattrs waiting to flush pages */
uint_t r_flags; /* flags, see below */
uint32_t n_flag; /* N--- flags below */
uint_t r_error; /* async write error */
kcondvar_t r_cv; /* condvar for blocked threads */
avl_tree_t r_dir; /* cache of readdir responses */
rddir_cache *r_direof; /* pointer to the EOF entry */
u_offset_t r_modaddr; /* address for page in writenp */
kthread_t *r_serial; /* id of purging thread */
list_t r_indelmap; /* list of delmap callers */
/*
* Attributes: local, and as last seen on the server.
* See notes above re: r_size vs r_attr.fa_size, etc.
*/
smbfattr_t r_attr; /* attributes from the server */
hrtime_t r_attrtime; /* time attributes become invalid */
hrtime_t r_mtime; /* client time file last modified */
len_t r_size; /* client's view of file size */
/*
* Security attributes.
*/
vsecattr_t r_secattr;
hrtime_t r_sectime;
/*
* Other attributes, not carried in smbfattr_t
*/
u_longlong_t n_ino;
uid_t n_uid;
gid_t n_gid;
mode_t n_mode;
} smbnode_t;
/*
* Flag bits in: smbnode_t .n_flag
*/
#define NFLUSHINPROG 0x00001
#define NFLUSHWANT 0x00002 /* they should gone ... */
#define NMODIFIED 0x00004 /* bogus, until async IO implemented */
#define NREFPARENT 0x00010 /* node holds parent from recycling */
#define NGOTIDS 0x00020
#define NRDIRSERIAL 0x00080 /* serialize readdir operation */
#define NISMAPPED 0x00800
#define NFLUSHWIRE 0x01000
#define NATTRCHANGED 0x02000 /* kill cached attributes at close */
#define NALLOC 0x04000 /* being created */
#define NWALLOC 0x08000 /* awaiting creation */
#define N_XATTR 0x10000 /* extended attribute (dir or file) */
/*
* Flag bits in: smbnode_t .r_flags
*/
#define RREADDIRPLUS 0x1 /* issue a READDIRPLUS instead of READDIR */
#define RDIRTY 0x2 /* dirty pages from write operation */
#define RSTALE 0x4 /* file handle is stale */
#define RMODINPROGRESS 0x8 /* page modification happening */
#define RTRUNCATE 0x10 /* truncating, don't commit */
#define RHAVEVERF 0x20 /* have a write verifier to compare against */
#define RCOMMIT 0x40 /* commit in progress */
#define RCOMMITWAIT 0x80 /* someone is waiting to do a commit */
#define RHASHED 0x100 /* smbnode is in the "hash" AVL tree */
#define ROUTOFSPACE 0x200 /* an out of space error has happened */
#define RDIRECTIO 0x400 /* bypass the buffer cache */
#define RLOOKUP 0x800 /* a lookup has been performed */
#define RWRITEATTR 0x1000 /* attributes came from WRITE */
#define RINDNLCPURGE 0x2000 /* in the process of purging DNLC references */
#define RDELMAPLIST 0x4000 /* delmap callers tracking for as callback */
/*
* Convert between vnode and smbnode
*/
#define VTOSMB(vp) ((smbnode_t *)((vp)->v_data))
#define SMBTOV(np) ((np)->r_vnode)
/*
* A macro to compute the separator that should be used for
* names under some directory. See smbfs_fullpath().
*/
#define SMBFS_DNP_SEP(dnp) \
(((dnp->n_flag & N_XATTR) == 0 && dnp->n_rplen > 1) ? '\\' : '\0')
#ifdef __cplusplus
}
#endif
#endif /* _FS_SMBFS_NODE_H_ */
|