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