53#include <fs/smbfs/smbfs.h> 54#include <fs/smbfs/smbfs_node.h> 55#include <fs/smbfs/smbfs_subr.h> 56 57#define SMBFS_NOHASH(smp, hval) (&(smp)->sm_hash[(hval) & (smp)->sm_hashlen]) 58#define smbfs_hash_lock(smp, p) lockmgr(&smp->sm_hashlock, LK_EXCLUSIVE, NULL, p) 59#define smbfs_hash_unlock(smp, p) lockmgr(&smp->sm_hashlock, LK_RELEASE, NULL, p) 60 61 62extern vop_t **smbfs_vnodeop_p; 63 64MALLOC_DEFINE(M_SMBNODE, "SMBFS node", "SMBFS vnode private part"); 65static MALLOC_DEFINE(M_SMBNODENAME, "SMBFS nname", "SMBFS node name"); 66 67int smbfs_hashprint(struct mount *mp); 68 69#if 0 70extern struct linker_set sysctl_vfs_smbfs; 71#ifdef SYSCTL_DECL 72SYSCTL_DECL(_vfs_smbfs); 73#endif 74SYSCTL_PROC(_vfs_smbfs, OID_AUTO, vnprint, CTLFLAG_WR|CTLTYPE_OPAQUE, 75 NULL, 0, smbfs_hashprint, "S,vnlist", "vnode hash"); 76#endif 77 78#define FNV_32_PRIME ((u_int32_t) 0x01000193UL) 79#define FNV1_32_INIT ((u_int32_t) 33554467UL) 80 81u_int32_t 82smbfs_hash(const u_char *name, int nmlen) 83{ 84 u_int32_t v; 85 86 for (v = FNV1_32_INIT; nmlen; name++, nmlen--) { 87 v *= FNV_32_PRIME; 88 v ^= (u_int32_t)*name; 89 } 90 return v; 91} 92 93int 94smbfs_hashprint(struct mount *mp) 95{ 96 struct smbmount *smp = VFSTOSMBFS(mp); 97 struct smbnode_hashhead *nhpp; 98 struct smbnode *np; 99 int i; 100 101 for(i = 0; i <= smp->sm_hashlen; i++) { 102 nhpp = &smp->sm_hash[i]; 103 LIST_FOREACH(np, nhpp, n_hash) 104 vprint(NULL, SMBTOV(np)); 105 } 106 return 0; 107} 108 109static char * 110smbfs_name_alloc(const u_char *name, int nmlen) 111{ 112 u_char *cp; 113 114 nmlen++; 115#ifdef SMBFS_NAME_DEBUG 116 cp = malloc(nmlen + 2 + sizeof(int), M_SMBNODENAME, M_WAITOK); 117 *(int*)cp = nmlen; 118 cp += sizeof(int); 119 cp[0] = 0xfc; 120 cp++; 121 bcopy(name, cp, nmlen - 1); 122 cp[nmlen] = 0xfe; 123#else 124 cp = malloc(nmlen, M_SMBNODENAME, M_WAITOK); 125 bcopy(name, cp, nmlen - 1); 126#endif 127 cp[nmlen - 1] = 0; 128 return cp; 129} 130 131static void 132smbfs_name_free(u_char *name) 133{ 134#ifdef SMBFS_NAME_DEBUG 135 int nmlen, slen; 136 u_char *cp; 137 138 cp = name; 139 cp--; 140 if (*cp != 0xfc) { 141 printf("First byte of name entry '%s' corrupted\n", name); 142 Debugger("ditto"); 143 } 144 cp -= sizeof(int); 145 nmlen = *(int*)cp; 146 slen = strlen(name) + 1; 147 if (nmlen != slen) { 148 printf("Name length mismatch: was %d, now %d name '%s'\n", 149 nmlen, slen, name); 150 Debugger("ditto"); 151 } 152 if (name[nmlen] != 0xfe) { 153 printf("Last byte of name entry '%s' corrupted\n", name); 154 Debugger("ditto"); 155 } 156 free(cp, M_SMBNODENAME); 157#else 158 free(name, M_SMBNODENAME); 159#endif 160} 161 162static int 163smbfs_node_alloc(struct mount *mp, struct vnode *dvp, 164 const char *name, int nmlen, struct smbfattr *fap, struct vnode **vpp) 165{ 166 struct proc *p = curproc; /* XXX */ 167 struct smbmount *smp = VFSTOSMBFS(mp); 168 struct smbnode_hashhead *nhpp; 169 struct smbnode *np, *np2, *dnp; 170 struct vnode *vp; 171 u_long hashval; 172 int error; 173 174 *vpp = NULL; 175 if (smp->sm_root != NULL && dvp == NULL) { 176 SMBERROR("do not allocate root vnode twice!\n"); 177 return EINVAL; 178 } 179 if (nmlen == 2 && bcmp(name, "..", 2) == 0) { 180 if (dvp == NULL) 181 return EINVAL; 182 vp = VTOSMB(dvp)->n_parent->n_vnode; 183 error = vget(vp, LK_EXCLUSIVE, p); 184 if (error == 0) 185 *vpp = vp; 186 return error; 187 } else if (nmlen == 1 && name[0] == '.') { 188 SMBERROR("do not call me with dot!\n"); 189 return EINVAL; 190 } 191 dnp = dvp ? VTOSMB(dvp) : NULL; 192 if (dnp == NULL && dvp != NULL) { 193 vprint("smbfs_node_alloc: dead parent vnode", dvp); 194 return EINVAL; 195 } 196 hashval = smbfs_hash(name, nmlen); 197retry: 198 smbfs_hash_lock(smp, p); 199loop: 200 nhpp = SMBFS_NOHASH(smp, hashval); 201 LIST_FOREACH(np, nhpp, n_hash) { 202 vp = SMBTOV(np); 203 if (np->n_parent != dnp || 204 np->n_nmlen != nmlen || bcmp(name, np->n_name, nmlen) != 0) 205 continue; 206 VI_LOCK(vp); 207 smbfs_hash_unlock(smp, p); 208 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) != 0) 209 goto retry; 210 *vpp = vp; 211 return 0; 212 } 213 smbfs_hash_unlock(smp, p); 214 /* 215 * If we don't have node attributes, then it is an explicit lookup 216 * for an existing vnode. 217 */ 218 if (fap == NULL) 219 return ENOENT; 220 221 MALLOC(np, struct smbnode *, sizeof *np, M_SMBNODE, M_WAITOK); 222 error = getnewvnode(VT_SMBFS, mp, smbfs_vnodeop_p, &vp); 223 if (error) { 224 FREE(np, M_SMBNODE); 225 return error; 226 } 227 vp->v_type = fap->fa_attr & SMB_FA_DIR ? VDIR : VREG; 228 bzero(np, sizeof(*np)); 229 vp->v_data = np; 230 np->n_vnode = vp; 231 np->n_mount = VFSTOSMBFS(mp); 232 np->n_nmlen = nmlen; 233 np->n_name = smbfs_name_alloc(name, nmlen); 234 np->n_ino = fap->fa_ino; 235 236 if (dvp) { 237 np->n_parent = dnp; 238 if (/*vp->v_type == VDIR &&*/ (dvp->v_flag & VROOT) == 0) { 239 vref(dvp); 240 np->n_flag |= NREFPARENT; 241 } 242 } else if (vp->v_type == VREG) 243 SMBERROR("new vnode '%s' born without parent ?\n", np->n_name); 244 245 lockinit(&vp->v_lock, PINOD, "smbnode", 0, LK_CANRECURSE); 246 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 247 248 smbfs_hash_lock(smp, p); 249 LIST_FOREACH(np2, nhpp, n_hash) { 250 if (np2->n_parent != dnp || 251 np2->n_nmlen != nmlen || bcmp(name, np2->n_name, nmlen) != 0) 252 continue; 253 vput(vp); 254/* smb_name_free(np->n_name); 255 FREE(np, M_SMBNODE);*/ 256 goto loop; 257 } 258 LIST_INSERT_HEAD(nhpp, np, n_hash); 259 smbfs_hash_unlock(smp, p); 260 *vpp = vp; 261 return 0; 262} 263 264int 265smbfs_nget(struct mount *mp, struct vnode *dvp, const char *name, int nmlen, 266 struct smbfattr *fap, struct vnode **vpp) 267{ 268 struct smbnode *np; 269 struct vnode *vp; 270 int error; 271 272 *vpp = NULL; 273 error = smbfs_node_alloc(mp, dvp, name, nmlen, fap, &vp); 274 if (error) 275 return error; 276 np = VTOSMB(vp); 277 if (fap) 278 smbfs_attr_cacheenter(vp, fap); 279 *vpp = vp; 280 return 0; 281} 282 283/* 284 * Free smbnode, and give vnode back to system 285 */ 286int 287smbfs_reclaim(ap) 288 struct vop_reclaim_args /* { 289 struct vnode *a_vp; 290 struct proc *a_p; 291 } */ *ap; 292{ 293 struct vnode *vp = ap->a_vp; 294 struct proc *p = ap->a_p; 295 struct vnode *dvp; 296 struct smbnode *np = VTOSMB(vp); 297 struct smbmount *smp = VTOSMBFS(vp); 298 299 SMBVDEBUG("%s,%d\n", np->n_name, vp->v_usecount); 300 301 smbfs_hash_lock(smp, p); 302 303 dvp = (np->n_parent && (np->n_flag & NREFPARENT)) ? 304 np->n_parent->n_vnode : NULL; 305 306 if (np->n_hash.le_prev) 307 LIST_REMOVE(np, n_hash); 308 cache_purge(vp); 309 if (smp->sm_root == np) { 310 SMBVDEBUG("root vnode\n"); 311 smp->sm_root = NULL; 312 } 313 vp->v_data = NULL; 314 smbfs_hash_unlock(smp, p); 315 if (np->n_name) 316 smbfs_name_free(np->n_name); 317 FREE(np, M_SMBNODE); 318 if (dvp) { 319 VI_LOCK(dvp); 320 if (dvp->v_usecount >= 1) { 321 VI_UNLOCK(dvp); 322 vrele(dvp); 323 } else { 324 VI_UNLOCK(dvp); 325 SMBERROR("BUG: negative use count for parent!\n"); 326 } 327 } 328 return 0; 329} 330 331int 332smbfs_inactive(ap) 333 struct vop_inactive_args /* { 334 struct vnode *a_vp; 335 struct proc *a_p; 336 } */ *ap; 337{ 338 struct proc *p = ap->a_p; 339 struct ucred *cred = p->p_ucred; 340 struct vnode *vp = ap->a_vp; 341 struct smbnode *np = VTOSMB(vp); 342 struct smb_cred scred; 343 int error; 344 345 SMBVDEBUG("%s: %d\n", VTOSMB(vp)->n_name, vp->v_usecount); 346 if (np->n_opencount) { 347 error = smbfs_vinvalbuf(vp, V_SAVE, cred, p, 1); 348 smb_makescred(&scred, p, cred); 349 error = smbfs_smb_close(np->n_mount->sm_share, np->n_fid, 350 &np->n_mtime, &scred); 351 np->n_opencount = 0; 352 } 353 VOP_UNLOCK(vp, 0, p); 354 return (0); 355} 356/* 357 * routines to maintain vnode attributes cache 358 * smbfs_attr_cacheenter: unpack np.i to vattr structure 359 */ 360void 361smbfs_attr_cacheenter(struct vnode *vp, struct smbfattr *fap) 362{ 363 struct smbnode *np = VTOSMB(vp); 364 365 if (vp->v_type == VREG) { 366 if (np->n_size != fap->fa_size) { 367 np->n_size = fap->fa_size; 368 vnode_pager_setsize(vp, np->n_size); 369 } 370 } else if (vp->v_type == VDIR) { 371 np->n_size = 16384; /* should be a better way ... */ 372 } else 373 return; 374 np->n_mtime = fap->fa_mtime; 375 np->n_dosattr = fap->fa_attr; 376 np->n_attrage = time_second; 377 return; 378} 379 380int 381smbfs_attr_cachelookup(struct vnode *vp, struct vattr *va) 382{ 383 struct smbnode *np = VTOSMB(vp); 384 struct smbmount *smp = VTOSMBFS(vp); 385 int diff; 386 387 diff = time_second - np->n_attrage; 388 if (diff > 2) /* XXX should be configurable */ 389 return ENOENT; 390 va->va_type = vp->v_type; /* vnode type (for create) */ 391 if (vp->v_type == VREG) { 392 va->va_mode = smp->sm_args.file_mode; /* files access mode and type */ 393 } else if (vp->v_type == VDIR) { 394 va->va_mode = smp->sm_args.dir_mode; /* files access mode and type */ 395 } else 396 return EINVAL; 397 va->va_size = np->n_size; 398 va->va_nlink = 1; /* number of references to file */ 399 va->va_uid = smp->sm_args.uid; /* owner user id */ 400 va->va_gid = smp->sm_args.gid; /* owner group id */ 401 va->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 402 va->va_fileid = np->n_ino; /* file id */ 403 if (va->va_fileid == 0) 404 va->va_fileid = 2; 405 va->va_blocksize = SSTOVC(smp->sm_share)->vc_txmax; 406 va->va_mtime = np->n_mtime; 407 va->va_atime = va->va_ctime = va->va_mtime; /* time file changed */ 408 va->va_gen = VNOVAL; /* generation number of file */ 409 va->va_flags = 0; /* flags defined for file */ 410 va->va_rdev = VNOVAL; /* device the special file represents */ 411 va->va_bytes = va->va_size; /* bytes of disk space held by file */ 412 va->va_filerev = 0; /* file modification number */ 413 va->va_vaflags = 0; /* operations flags */ 414 return 0; 415}
| 55#include <fs/smbfs/smbfs.h> 56#include <fs/smbfs/smbfs_node.h> 57#include <fs/smbfs/smbfs_subr.h> 58 59#define SMBFS_NOHASH(smp, hval) (&(smp)->sm_hash[(hval) & (smp)->sm_hashlen]) 60#define smbfs_hash_lock(smp, p) lockmgr(&smp->sm_hashlock, LK_EXCLUSIVE, NULL, p) 61#define smbfs_hash_unlock(smp, p) lockmgr(&smp->sm_hashlock, LK_RELEASE, NULL, p) 62 63 64extern vop_t **smbfs_vnodeop_p; 65 66MALLOC_DEFINE(M_SMBNODE, "SMBFS node", "SMBFS vnode private part"); 67static MALLOC_DEFINE(M_SMBNODENAME, "SMBFS nname", "SMBFS node name"); 68 69int smbfs_hashprint(struct mount *mp); 70 71#if 0 72extern struct linker_set sysctl_vfs_smbfs; 73#ifdef SYSCTL_DECL 74SYSCTL_DECL(_vfs_smbfs); 75#endif 76SYSCTL_PROC(_vfs_smbfs, OID_AUTO, vnprint, CTLFLAG_WR|CTLTYPE_OPAQUE, 77 NULL, 0, smbfs_hashprint, "S,vnlist", "vnode hash"); 78#endif 79 80#define FNV_32_PRIME ((u_int32_t) 0x01000193UL) 81#define FNV1_32_INIT ((u_int32_t) 33554467UL) 82 83u_int32_t 84smbfs_hash(const u_char *name, int nmlen) 85{ 86 u_int32_t v; 87 88 for (v = FNV1_32_INIT; nmlen; name++, nmlen--) { 89 v *= FNV_32_PRIME; 90 v ^= (u_int32_t)*name; 91 } 92 return v; 93} 94 95int 96smbfs_hashprint(struct mount *mp) 97{ 98 struct smbmount *smp = VFSTOSMBFS(mp); 99 struct smbnode_hashhead *nhpp; 100 struct smbnode *np; 101 int i; 102 103 for(i = 0; i <= smp->sm_hashlen; i++) { 104 nhpp = &smp->sm_hash[i]; 105 LIST_FOREACH(np, nhpp, n_hash) 106 vprint(NULL, SMBTOV(np)); 107 } 108 return 0; 109} 110 111static char * 112smbfs_name_alloc(const u_char *name, int nmlen) 113{ 114 u_char *cp; 115 116 nmlen++; 117#ifdef SMBFS_NAME_DEBUG 118 cp = malloc(nmlen + 2 + sizeof(int), M_SMBNODENAME, M_WAITOK); 119 *(int*)cp = nmlen; 120 cp += sizeof(int); 121 cp[0] = 0xfc; 122 cp++; 123 bcopy(name, cp, nmlen - 1); 124 cp[nmlen] = 0xfe; 125#else 126 cp = malloc(nmlen, M_SMBNODENAME, M_WAITOK); 127 bcopy(name, cp, nmlen - 1); 128#endif 129 cp[nmlen - 1] = 0; 130 return cp; 131} 132 133static void 134smbfs_name_free(u_char *name) 135{ 136#ifdef SMBFS_NAME_DEBUG 137 int nmlen, slen; 138 u_char *cp; 139 140 cp = name; 141 cp--; 142 if (*cp != 0xfc) { 143 printf("First byte of name entry '%s' corrupted\n", name); 144 Debugger("ditto"); 145 } 146 cp -= sizeof(int); 147 nmlen = *(int*)cp; 148 slen = strlen(name) + 1; 149 if (nmlen != slen) { 150 printf("Name length mismatch: was %d, now %d name '%s'\n", 151 nmlen, slen, name); 152 Debugger("ditto"); 153 } 154 if (name[nmlen] != 0xfe) { 155 printf("Last byte of name entry '%s' corrupted\n", name); 156 Debugger("ditto"); 157 } 158 free(cp, M_SMBNODENAME); 159#else 160 free(name, M_SMBNODENAME); 161#endif 162} 163 164static int 165smbfs_node_alloc(struct mount *mp, struct vnode *dvp, 166 const char *name, int nmlen, struct smbfattr *fap, struct vnode **vpp) 167{ 168 struct proc *p = curproc; /* XXX */ 169 struct smbmount *smp = VFSTOSMBFS(mp); 170 struct smbnode_hashhead *nhpp; 171 struct smbnode *np, *np2, *dnp; 172 struct vnode *vp; 173 u_long hashval; 174 int error; 175 176 *vpp = NULL; 177 if (smp->sm_root != NULL && dvp == NULL) { 178 SMBERROR("do not allocate root vnode twice!\n"); 179 return EINVAL; 180 } 181 if (nmlen == 2 && bcmp(name, "..", 2) == 0) { 182 if (dvp == NULL) 183 return EINVAL; 184 vp = VTOSMB(dvp)->n_parent->n_vnode; 185 error = vget(vp, LK_EXCLUSIVE, p); 186 if (error == 0) 187 *vpp = vp; 188 return error; 189 } else if (nmlen == 1 && name[0] == '.') { 190 SMBERROR("do not call me with dot!\n"); 191 return EINVAL; 192 } 193 dnp = dvp ? VTOSMB(dvp) : NULL; 194 if (dnp == NULL && dvp != NULL) { 195 vprint("smbfs_node_alloc: dead parent vnode", dvp); 196 return EINVAL; 197 } 198 hashval = smbfs_hash(name, nmlen); 199retry: 200 smbfs_hash_lock(smp, p); 201loop: 202 nhpp = SMBFS_NOHASH(smp, hashval); 203 LIST_FOREACH(np, nhpp, n_hash) { 204 vp = SMBTOV(np); 205 if (np->n_parent != dnp || 206 np->n_nmlen != nmlen || bcmp(name, np->n_name, nmlen) != 0) 207 continue; 208 VI_LOCK(vp); 209 smbfs_hash_unlock(smp, p); 210 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) != 0) 211 goto retry; 212 *vpp = vp; 213 return 0; 214 } 215 smbfs_hash_unlock(smp, p); 216 /* 217 * If we don't have node attributes, then it is an explicit lookup 218 * for an existing vnode. 219 */ 220 if (fap == NULL) 221 return ENOENT; 222 223 MALLOC(np, struct smbnode *, sizeof *np, M_SMBNODE, M_WAITOK); 224 error = getnewvnode(VT_SMBFS, mp, smbfs_vnodeop_p, &vp); 225 if (error) { 226 FREE(np, M_SMBNODE); 227 return error; 228 } 229 vp->v_type = fap->fa_attr & SMB_FA_DIR ? VDIR : VREG; 230 bzero(np, sizeof(*np)); 231 vp->v_data = np; 232 np->n_vnode = vp; 233 np->n_mount = VFSTOSMBFS(mp); 234 np->n_nmlen = nmlen; 235 np->n_name = smbfs_name_alloc(name, nmlen); 236 np->n_ino = fap->fa_ino; 237 238 if (dvp) { 239 np->n_parent = dnp; 240 if (/*vp->v_type == VDIR &&*/ (dvp->v_flag & VROOT) == 0) { 241 vref(dvp); 242 np->n_flag |= NREFPARENT; 243 } 244 } else if (vp->v_type == VREG) 245 SMBERROR("new vnode '%s' born without parent ?\n", np->n_name); 246 247 lockinit(&vp->v_lock, PINOD, "smbnode", 0, LK_CANRECURSE); 248 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 249 250 smbfs_hash_lock(smp, p); 251 LIST_FOREACH(np2, nhpp, n_hash) { 252 if (np2->n_parent != dnp || 253 np2->n_nmlen != nmlen || bcmp(name, np2->n_name, nmlen) != 0) 254 continue; 255 vput(vp); 256/* smb_name_free(np->n_name); 257 FREE(np, M_SMBNODE);*/ 258 goto loop; 259 } 260 LIST_INSERT_HEAD(nhpp, np, n_hash); 261 smbfs_hash_unlock(smp, p); 262 *vpp = vp; 263 return 0; 264} 265 266int 267smbfs_nget(struct mount *mp, struct vnode *dvp, const char *name, int nmlen, 268 struct smbfattr *fap, struct vnode **vpp) 269{ 270 struct smbnode *np; 271 struct vnode *vp; 272 int error; 273 274 *vpp = NULL; 275 error = smbfs_node_alloc(mp, dvp, name, nmlen, fap, &vp); 276 if (error) 277 return error; 278 np = VTOSMB(vp); 279 if (fap) 280 smbfs_attr_cacheenter(vp, fap); 281 *vpp = vp; 282 return 0; 283} 284 285/* 286 * Free smbnode, and give vnode back to system 287 */ 288int 289smbfs_reclaim(ap) 290 struct vop_reclaim_args /* { 291 struct vnode *a_vp; 292 struct proc *a_p; 293 } */ *ap; 294{ 295 struct vnode *vp = ap->a_vp; 296 struct proc *p = ap->a_p; 297 struct vnode *dvp; 298 struct smbnode *np = VTOSMB(vp); 299 struct smbmount *smp = VTOSMBFS(vp); 300 301 SMBVDEBUG("%s,%d\n", np->n_name, vp->v_usecount); 302 303 smbfs_hash_lock(smp, p); 304 305 dvp = (np->n_parent && (np->n_flag & NREFPARENT)) ? 306 np->n_parent->n_vnode : NULL; 307 308 if (np->n_hash.le_prev) 309 LIST_REMOVE(np, n_hash); 310 cache_purge(vp); 311 if (smp->sm_root == np) { 312 SMBVDEBUG("root vnode\n"); 313 smp->sm_root = NULL; 314 } 315 vp->v_data = NULL; 316 smbfs_hash_unlock(smp, p); 317 if (np->n_name) 318 smbfs_name_free(np->n_name); 319 FREE(np, M_SMBNODE); 320 if (dvp) { 321 VI_LOCK(dvp); 322 if (dvp->v_usecount >= 1) { 323 VI_UNLOCK(dvp); 324 vrele(dvp); 325 } else { 326 VI_UNLOCK(dvp); 327 SMBERROR("BUG: negative use count for parent!\n"); 328 } 329 } 330 return 0; 331} 332 333int 334smbfs_inactive(ap) 335 struct vop_inactive_args /* { 336 struct vnode *a_vp; 337 struct proc *a_p; 338 } */ *ap; 339{ 340 struct proc *p = ap->a_p; 341 struct ucred *cred = p->p_ucred; 342 struct vnode *vp = ap->a_vp; 343 struct smbnode *np = VTOSMB(vp); 344 struct smb_cred scred; 345 int error; 346 347 SMBVDEBUG("%s: %d\n", VTOSMB(vp)->n_name, vp->v_usecount); 348 if (np->n_opencount) { 349 error = smbfs_vinvalbuf(vp, V_SAVE, cred, p, 1); 350 smb_makescred(&scred, p, cred); 351 error = smbfs_smb_close(np->n_mount->sm_share, np->n_fid, 352 &np->n_mtime, &scred); 353 np->n_opencount = 0; 354 } 355 VOP_UNLOCK(vp, 0, p); 356 return (0); 357} 358/* 359 * routines to maintain vnode attributes cache 360 * smbfs_attr_cacheenter: unpack np.i to vattr structure 361 */ 362void 363smbfs_attr_cacheenter(struct vnode *vp, struct smbfattr *fap) 364{ 365 struct smbnode *np = VTOSMB(vp); 366 367 if (vp->v_type == VREG) { 368 if (np->n_size != fap->fa_size) { 369 np->n_size = fap->fa_size; 370 vnode_pager_setsize(vp, np->n_size); 371 } 372 } else if (vp->v_type == VDIR) { 373 np->n_size = 16384; /* should be a better way ... */ 374 } else 375 return; 376 np->n_mtime = fap->fa_mtime; 377 np->n_dosattr = fap->fa_attr; 378 np->n_attrage = time_second; 379 return; 380} 381 382int 383smbfs_attr_cachelookup(struct vnode *vp, struct vattr *va) 384{ 385 struct smbnode *np = VTOSMB(vp); 386 struct smbmount *smp = VTOSMBFS(vp); 387 int diff; 388 389 diff = time_second - np->n_attrage; 390 if (diff > 2) /* XXX should be configurable */ 391 return ENOENT; 392 va->va_type = vp->v_type; /* vnode type (for create) */ 393 if (vp->v_type == VREG) { 394 va->va_mode = smp->sm_args.file_mode; /* files access mode and type */ 395 } else if (vp->v_type == VDIR) { 396 va->va_mode = smp->sm_args.dir_mode; /* files access mode and type */ 397 } else 398 return EINVAL; 399 va->va_size = np->n_size; 400 va->va_nlink = 1; /* number of references to file */ 401 va->va_uid = smp->sm_args.uid; /* owner user id */ 402 va->va_gid = smp->sm_args.gid; /* owner group id */ 403 va->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 404 va->va_fileid = np->n_ino; /* file id */ 405 if (va->va_fileid == 0) 406 va->va_fileid = 2; 407 va->va_blocksize = SSTOVC(smp->sm_share)->vc_txmax; 408 va->va_mtime = np->n_mtime; 409 va->va_atime = va->va_ctime = va->va_mtime; /* time file changed */ 410 va->va_gen = VNOVAL; /* generation number of file */ 411 va->va_flags = 0; /* flags defined for file */ 412 va->va_rdev = VNOVAL; /* device the special file represents */ 413 va->va_bytes = va->va_size; /* bytes of disk space held by file */ 414 va->va_filerev = 0; /* file modification number */ 415 va->va_vaflags = 0; /* operations flags */ 416 return 0; 417}
|