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