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 * Compare with nfs_clnt.h 46 */ 47 48 #include <sys/avl.h> 49 #include <sys/list.h> 50 51 #ifdef __cplusplus 52 extern "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 */ 68 typedef 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 */ 81 typedef 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 */ 114 typedef 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 */ 132 typedef 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 213 typedef 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 * Other attributes, not carried in smbfattr_t 279 */ 280 u_longlong_t n_ino; 281 uid_t n_uid; 282 gid_t n_gid; 283 mode_t n_mode; 284 } smbnode_t; 285 286 /* 287 * Flag bits in: smbnode_t .n_flag 288 */ 289 #define NFLUSHINPROG 0x00001 290 #define NFLUSHWANT 0x00002 /* they should gone ... */ 291 #define NMODIFIED 0x00004 /* bogus, until async IO implemented */ 292 #define NREFPARENT 0x00010 /* node holds parent from recycling */ 293 #define NGOTIDS 0x00020 294 #define NRDIRSERIAL 0x00080 /* serialize readdir operation */ 295 #define NISMAPPED 0x00800 296 #define NFLUSHWIRE 0x01000 297 #define NATTRCHANGED 0x02000 /* kill cached attributes at close */ 298 #define NALLOC 0x04000 /* being created */ 299 #define NWALLOC 0x08000 /* awaiting creation */ 300 #define N_XATTR 0x10000 /* extended attribute (dir or file) */ 301 302 /* 303 * Flag bits in: smbnode_t .r_flags 304 */ 305 #define RREADDIRPLUS 0x1 /* issue a READDIRPLUS instead of READDIR */ 306 #define RDIRTY 0x2 /* dirty pages from write operation */ 307 #define RSTALE 0x4 /* file handle is stale */ 308 #define RMODINPROGRESS 0x8 /* page modification happening */ 309 #define RTRUNCATE 0x10 /* truncating, don't commit */ 310 #define RHAVEVERF 0x20 /* have a write verifier to compare against */ 311 #define RCOMMIT 0x40 /* commit in progress */ 312 #define RCOMMITWAIT 0x80 /* someone is waiting to do a commit */ 313 #define RHASHED 0x100 /* smbnode is in the "hash" AVL tree */ 314 #define ROUTOFSPACE 0x200 /* an out of space error has happened */ 315 #define RDIRECTIO 0x400 /* bypass the buffer cache */ 316 #define RLOOKUP 0x800 /* a lookup has been performed */ 317 #define RWRITEATTR 0x1000 /* attributes came from WRITE */ 318 #define RINDNLCPURGE 0x2000 /* in the process of purging DNLC references */ 319 #define RDELMAPLIST 0x4000 /* delmap callers tracking for as callback */ 320 321 /* 322 * Convert between vnode and smbnode 323 */ 324 #define VTOSMB(vp) ((smbnode_t *)((vp)->v_data)) 325 #define SMBTOV(np) ((np)->r_vnode) 326 327 /* 328 * A macro to compute the separator that should be used for 329 * names under some directory. See smbfs_fullpath(). 330 */ 331 #define SMBFS_DNP_SEP(dnp) \ 332 (((dnp->n_flag & N_XATTR) == 0 && dnp->n_rplen > 1) ? '\\' : '\0') 333 334 #ifdef __cplusplus 335 } 336 #endif 337 338 #endif /* _FS_SMBFS_NODE_H_ */ 339