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 2010 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 * Compare with nfs_clnt.h
46 */
47
48#include <sys/avl.h>
49#include <sys/list.h>
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54
55/*
56 * These are the attributes we can get from the server via
57 * SMB commands such as TRANS2_QUERY_FILE_INFORMATION
58 * with info level SMB_QFILEINFO_ALL_INFO, and directory
59 * FindFirst/FindNext info. levels FIND_DIRECTORY_INFO
60 * and FIND_BOTH_DIRECTORY_INFO, etc.
61 *
62 * Values in this struct are always native endian,
63 * and times are converted converted to Unix form.
64 * Note: zero in any of the times means "unknown".
65 *
66 * XXX: Later, move this to nsmb
67 */
68typedef struct smbfattr {
69	timespec_t	fa_createtime;	/* Note, != ctime */
70	timespec_t	fa_atime;	/* these 3 are like unix */
71	timespec_t	fa_mtime;
72	timespec_t	fa_ctime;
73	u_offset_t	fa_size;	/* EOF position */
74	u_offset_t	fa_allocsz;	/* Allocated size. */
75	uint32_t	fa_attr;	/* Ext. file (DOS) attr */
76} smbfattr_t;
77
78/*
79 * Cache whole directories (not yet)
80 */
81typedef struct rddir_cache {
82	lloff_t _cookie;	/* cookie used to find this cache entry */
83	lloff_t _ncookie;	/* cookie used to find the next cache entry */
84	char *entries;		/* buffer containing dirent entries */
85	int eof;		/* EOF reached after this request */
86	int entlen;		/* size of dirent entries in buf */
87	int buflen;		/* size of the buffer used to store entries */
88	int flags;		/* control flags, see below */
89	kcondvar_t cv;		/* cv for blocking */
90	int error;		/* error from RPC operation */
91	kmutex_t lock;
92	uint_t count;		/* reference count */
93	avl_node_t tree;	/* AVL tree links */
94} rddir_cache;
95
96#define	smbfs_cookie	_cookie._p._l
97#define	smbfs_ncookie	_ncookie._p._l
98#define	smbfs3_cookie	_cookie._f
99#define	smbfs3_ncookie	_ncookie._f
100
101#define	RDDIR		0x1	/* readdir operation in progress */
102#define	RDDIRWAIT	0x2	/* waiting on readdir in progress */
103#define	RDDIRREQ	0x4	/* a new readdir is required */
104#define	RDDIRCACHED	0x8	/* entry is in the cache */
105
106#define	HAVE_RDDIR_CACHE(rp)	(avl_numnodes(&(rp)->r_dir) > 0)
107
108/*
109 * A homegrown reader/writer lock implementation.  It addresses
110 * two requirements not addressed by the system primitives.  They
111 * are that the `enter" operation is optionally interruptible and
112 * that that they can be re`enter'ed by writers without deadlock.
113 */
114typedef struct smbfs_rwlock {
115	int count;
116	int waiters;
117	kthread_t *owner;
118	kmutex_t lock;
119	kcondvar_t cv;
120} smbfs_rwlock_t;
121
122/*
123 * The format of the smbfs node header, which contains the
124 * fields used to link nodes in the AVL tree, and those
125 * fields needed by the AVL node comparison functions.
126 * It's a separate struct so we can call avl_find with
127 * this relatively small struct as a stack local.
128 *
129 * The AVL tree is mntinfo.smi_hash_avl,
130 * and its lock is mntinfo.smi_hash_lk.
131 */
132typedef struct smbfs_node_hdr {
133	/*
134	 * Our linkage in the node cache AVL tree.
135	 */
136	avl_node_t	hdr_avl_node;
137
138	/*
139	 * Identity of this node:  The full path name,
140	 * in server form, relative to the share root.
141	 */
142	char		*hdr_n_rpath;
143	int		hdr_n_rplen;
144} smbfs_node_hdr_t;
145
146/*
147 * Below is the SMBFS-specific representation of a "node".
148 * This struct is a mixture of Sun NFS and Darwin code.
149 * Fields starting with "r_" came from NFS struct "rnode"
150 * and fields starting with "n_" came from Darwin, or
151 * were added during the Solaris port.  We have avoided
152 * renaming fields so we would not cause excessive
153 * changes in the code using this struct.
154 *
155 * Now using an AVL tree instead of hash lists, but kept the
156 * "hash" in some member names and functions to reduce churn.
157 * One AVL tree per mount replaces the global hash buckets.
158 *
159 * Notes carried over from the NFS code:
160 *
161 * The smbnode is the "inode" for remote files.  It contains all the
162 * information necessary to handle remote file on the client side.
163 *
164 * Note on file sizes:  we keep two file sizes in the smbnode: the size
165 * according to the client (r_size) and the size according to the server
166 * (r_attr.fa_size).  They can differ because we modify r_size during a
167 * write system call (smbfs_rdwr), before the write request goes over the
168 * wire (before the file is actually modified on the server).  If an OTW
169 * request occurs before the cached data is written to the server the file
170 * size returned from the server (r_attr.fa_size) may not match r_size.
171 * r_size is the one we use, in general.  r_attr.fa_size is only used to
172 * determine whether or not our cached data is valid.
173 *
174 * Each smbnode has 3 locks associated with it (not including the smbnode
175 * "hash" AVL tree and free list locks):
176 *
177 *	r_rwlock:	Serializes smbfs_write and smbfs_setattr requests
178 *			and allows smbfs_read requests to proceed in parallel.
179 *			Serializes reads/updates to directories.
180 *
181 *	r_lkserlock:	Serializes lock requests with map, write, and
182 *			readahead operations.
183 *
184 *	r_statelock:	Protects all fields in the smbnode except for
185 *			those listed below.  This lock is intented
186 *			to be held for relatively short periods of
187 *			time (not accross entire putpage operations,
188 *			for example).
189 *
190 * The following members are protected by the mutex smbfreelist_lock:
191 *	r_freef
192 *	r_freeb
193 *
194 * The following members are protected by the AVL tree rwlock:
195 *	r_avl_node	(r__hdr.hdr_avl_node)
196 *
197 * Note: r_modaddr is only accessed when the r_statelock mutex is held.
198 *	Its value is also controlled via r_rwlock.  It is assumed that
199 *	there will be only 1 writer active at a time, so it safe to
200 *	set r_modaddr and release r_statelock as long as the r_rwlock
201 *	writer lock is held.
202 *
203 * 64-bit offsets: the code formerly assumed that atomic reads of
204 * r_size were safe and reliable; on 32-bit architectures, this is
205 * not true since an intervening bus cycle from another processor
206 * could update half of the size field.  The r_statelock must now
207 * be held whenever any kind of access of r_size is made.
208 *
209 * Lock ordering:
210 * 	r_rwlock > r_lkserlock > r_statelock
211 */
212
213typedef struct smbnode {
214	/* Our linkage in the node cache AVL tree (see above). */
215	smbfs_node_hdr_t	r__hdr;
216
217	/* short-hand names for r__hdr members */
218#define	r_avl_node	r__hdr.hdr_avl_node
219#define	n_rpath		r__hdr.hdr_n_rpath
220#define	n_rplen		r__hdr.hdr_n_rplen
221
222	smbmntinfo_t	*n_mount;	/* VFS data */
223	vnode_t		*r_vnode;	/* associated vnode */
224
225	/*
226	 * Linkage in smbfreelist, for reclaiming nodes.
227	 * Lock for the free list is: smbfreelist_lock
228	 */
229	struct smbnode	*r_freef;	/* free list forward pointer */
230	struct smbnode	*r_freeb;	/* free list back pointer */
231
232	smbfs_rwlock_t	r_rwlock;	/* serialize write/setattr requests */
233	smbfs_rwlock_t	r_lkserlock;	/* serialize lock with other ops */
234	kmutex_t	r_statelock;	/* protect (most) smbnode fields */
235
236	/*
237	 * File handle, directory search handle,
238	 * and reference counts for them, etc.
239	 * Lock for these is: r_lkserlock
240	 */
241	int		n_dirrefs;
242	struct smbfs_fctx	*n_dirseq;	/* ff context */
243	int		n_dirofs;	/* last ff offset */
244	int		n_fidrefs;
245	uint16_t	n_fid;		/* file handle */
246	enum vtype	n_ovtype;	/* vnode type opened */
247	uint32_t	n_rights;	/* granted rights */
248	int		n_vcgenid;	/* gereration no. (reconnect) */
249
250	/*
251	 * Misc. bookkeeping
252	 */
253	cred_t		*r_cred;	/* current credentials */
254	u_offset_t	r_nextr;	/* next read offset (read-ahead) */
255	long		r_mapcnt;	/* count of mmapped pages */
256	uint_t		r_count;	/* # of refs not reflect in v_count */
257	uint_t		r_awcount;	/* # of outstanding async write */
258	uint_t		r_gcount;	/* getattrs waiting to flush pages */
259	uint_t		r_flags;	/* flags, see below */
260	uint32_t	n_flag;		/* NXXX flags below */
261	uint_t		r_error;	/* async write error */
262	kcondvar_t	r_cv;		/* condvar for blocked threads */
263	avl_tree_t	r_dir;		/* cache of readdir responses */
264	rddir_cache	*r_direof;	/* pointer to the EOF entry */
265	kthread_t	*r_serial;	/* id of purging thread */
266	list_t		r_indelmap;	/* list of delmap callers */
267
268	/*
269	 * Attributes: local, and as last seen on the server.
270	 * See notes above re: r_size vs r_attr.fa_size, etc.
271	 */
272	smbfattr_t	r_attr;		/* attributes from the server */
273	hrtime_t	r_attrtime;	/* time attributes become invalid */
274	hrtime_t	r_mtime;	/* client time file last modified */
275	len_t		r_size;		/* client's view of file size */
276
277	/*
278	 * Security attributes.
279	 */
280	vsecattr_t	r_secattr;
281	hrtime_t	r_sectime;
282
283	/*
284	 * Other attributes, not carried in smbfattr_t
285	 */
286	u_longlong_t	n_ino;
287	uid_t		n_uid;
288	gid_t		n_gid;
289	mode_t		n_mode;
290} smbnode_t;
291
292/*
293 * Flag bits in: smbnode_t .n_flag
294 */
295#define	NFLUSHINPROG	0x00001
296#define	NFLUSHWANT	0x00002 /* they should gone ... */
297#define	NMODIFIED	0x00004 /* bogus, until async IO implemented */
298#define	NREFPARENT	0x00010 /* node holds parent from recycling */
299#define	NGOTIDS		0x00020
300#define	NRDIRSERIAL	0x00080	/* serialize readdir operation */
301#define	NISMAPPED	0x00800
302#define	NFLUSHWIRE	0x01000
303#define	NATTRCHANGED	0x02000 /* kill cached attributes at close */
304#define	NALLOC		0x04000 /* being created */
305#define	NWALLOC		0x08000 /* awaiting creation */
306#define	N_XATTR 	0x10000 /* extended attribute (dir or file) */
307
308/*
309 * Flag bits in: smbnode_t .r_flags
310 */
311#define	RREADDIRPLUS	0x1	/* issue a READDIRPLUS instead of READDIR */
312#define	RDIRTY		0x2	/* dirty pages from write operation */
313#define	RSTALE		0x4	/* file handle is stale */
314#define	RMODINPROGRESS	0x8	/* page modification happening */
315#define	RTRUNCATE	0x10	/* truncating, don't commit */
316#define	RHAVEVERF	0x20	/* have a write verifier to compare against */
317#define	RCOMMIT		0x40	/* commit in progress */
318#define	RCOMMITWAIT	0x80	/* someone is waiting to do a commit */
319#define	RHASHED		0x100	/* smbnode is in the "hash" AVL tree */
320#define	ROUTOFSPACE	0x200	/* an out of space error has happened */
321#define	RDIRECTIO	0x400	/* bypass the buffer cache */
322#define	RLOOKUP		0x800	/* a lookup has been performed */
323#define	RWRITEATTR	0x1000	/* attributes came from WRITE */
324#define	RINDNLCPURGE	0x2000	/* in the process of purging DNLC references */
325#define	RDELMAPLIST	0x4000	/* delmap callers tracking for as callback */
326
327/*
328 * Convert between vnode and smbnode
329 */
330#define	VTOSMB(vp)	((smbnode_t *)((vp)->v_data))
331#define	SMBTOV(np)	((np)->r_vnode)
332
333/*
334 * A macro to compute the separator that should be used for
335 * names under some directory.  See smbfs_fullpath().
336 */
337#define	SMBFS_DNP_SEP(dnp) \
338	(((dnp->n_flag & N_XATTR) == 0 && dnp->n_rplen > 1) ? '\\' : '\0')
339
340#ifdef __cplusplus
341}
342#endif
343
344#endif /* _FS_SMBFS_NODE_H_ */
345