Annotation of sys/xfs/xfs_node-bsd.c, Revision 1.1
1.1 ! nbrk 1: /*
! 2: * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
! 3: * (Royal Institute of Technology, Stockholm, Sweden).
! 4: * All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: *
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: *
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: *
! 17: * 3. Neither the name of the Institute nor the names of its contributors
! 18: * may be used to endorse or promote products derived from this software
! 19: * without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 31: * SUCH DAMAGE.
! 32: */
! 33:
! 34: #include <sys/queue.h>
! 35: #include <xfs/xfs_locl.h>
! 36: #include <xfs/xfs_common.h>
! 37: #include <xfs/xfs_fs.h>
! 38: #include <xfs/xfs_deb.h>
! 39: #include <xfs/xfs_vnodeops.h>
! 40:
! 41: RCSID("$arla: xfs_node-bsd.c,v 1.70 2003/02/28 02:01:06 lha Exp $");
! 42:
! 43: extern vop_t **xfs_vnodeop_p;
! 44:
! 45: #ifndef LK_NOPAUSE
! 46: #define LK_NOPAUSE 0
! 47: #endif
! 48:
! 49: /*
! 50: * Allocate a new vnode with handle `handle' in `mp' and return it in
! 51: * `vpp'. Return 0 or error.
! 52: */
! 53:
! 54: int
! 55: xfs_getnewvnode(struct xfs *xfsp, struct vnode **vpp,
! 56: struct xfs_handle *handle)
! 57: {
! 58: struct xfs_node *result, *check;
! 59: int error;
! 60:
! 61: error = getnewvnode(VT_XFS, NNPFS_TO_VFS(xfsp), xfs_vnodeop_p, vpp);
! 62: if (error)
! 63: return error;
! 64:
! 65: result = xfs_alloc(sizeof(*result), M_NNPFS_NODE);
! 66: bzero(result, sizeof(*result));
! 67:
! 68: (*vpp)->v_data = result;
! 69: result->vn = *vpp;
! 70:
! 71: result->handle = *handle;
! 72: result->flags = 0;
! 73: result->tokens = 0;
! 74: result->offset = 0;
! 75: #if defined(HAVE_KERNEL_LOCKMGR) || defined(HAVE_KERNEL_DEBUGLOCKMGR)
! 76: lockinit (&result->lock, PVFS, "xfs_lock", 0, LK_NOPAUSE);
! 77: #else
! 78: result->vnlocks = 0;
! 79: #endif
! 80: result->anonrights = 0;
! 81: result->rd_cred = NULL;
! 82: result->wr_cred = NULL;
! 83:
! 84: #if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105280000
! 85: genfs_node_init(*vpp, &xfs_genfsops);
! 86: #endif
! 87:
! 88: check = xfs_node_find(&xfsp->nodehead, handle);
! 89: if (check) {
! 90: vput(*vpp);
! 91: *vpp = result->vn;
! 92: return 0;
! 93: }
! 94:
! 95: xfs_insert(&xfs->nodehead, result);
! 96:
! 97: return 0;
! 98: }
! 99:
! 100: /*
! 101: * Create a new xfs_node and make a vget
! 102: *
! 103: * Also prevents creation of duplicates. This happens
! 104: * whenever there are more than one name to a file,
! 105: * "." and ".." are common cases. */
! 106:
! 107: int
! 108: new_xfs_node(struct xfs *xfsp,
! 109: struct xfs_msg_node *node,
! 110: struct xfs_node **xpp,
! 111: d_thread_t *p)
! 112: {
! 113: struct xfs_node *result;
! 114:
! 115: NNPFSDEB(XDEBNODE, ("new_xfs_node (%d,%d,%d,%d)\n",
! 116: node->handle.a,
! 117: node->handle.b,
! 118: node->handle.c,
! 119: node->handle.d));
! 120:
! 121: retry:
! 122: /* Does not allow duplicates */
! 123: result = xfs_node_find(&xfsp->nodehead, &node->handle);
! 124: if (result == 0) {
! 125: int error;
! 126: struct vnode *v;
! 127:
! 128: error = xfs_getnewvnode(xfsp, &v, &node->handle);
! 129: if (error)
! 130: return error;
! 131:
! 132: result = VNODE_TO_XNODE(v);
! 133: result->anonrights = node->anonrights;
! 134:
! 135: xfsp->nnodes++;
! 136: } else {
! 137: /* Node is already cached */
! 138: if(xfs_do_vget(XNODE_TO_VNODE(result), 0, p))
! 139: goto retry;
! 140: }
! 141:
! 142: /* Init other fields */
! 143: xfs_attr2vattr(&node->attr, &result->attr, 1);
! 144: result->vn->v_type = result->attr.va_type;
! 145: result->tokens = node->tokens;
! 146: bcopy(node->id, result->id, sizeof(result->id));
! 147: bcopy(node->rights, result->rights, sizeof(result->rights));
! 148:
! 149: #ifdef __APPLE__
! 150: if (result->vn->v_type == VREG && (!UBCINFOEXISTS(result->vn)))
! 151: ubc_info_init(result->vn);
! 152: #endif
! 153:
! 154: *xpp = result;
! 155: NNPFSDEB(XDEBNODE, ("return: new_xfs_node\n"));
! 156: return 0;
! 157: }
! 158:
! 159: void
! 160: free_xfs_node(struct xfs_node *node)
! 161: {
! 162: struct xfs *xfsp = NNPFS_FROM_XNODE(node);
! 163:
! 164: NNPFSDEB(XDEBNODE, ("free_xfs_node(%lx) (%d,%d,%d,%d)\n",
! 165: (unsigned long)node,
! 166: node->handle.a,
! 167: node->handle.b,
! 168: node->handle.c,
! 169: node->handle.d));
! 170:
! 171: /* XXX Really need to put back dirty data first. */
! 172:
! 173: if (DATA_FROM_XNODE(node)) {
! 174: vrele(DATA_FROM_XNODE(node));
! 175: DATA_FROM_XNODE(node) = NULL;
! 176: }
! 177: xfsp->nnodes--;
! 178: XNODE_TO_VNODE(node)->v_data = NULL;
! 179: if (node->rd_cred) {
! 180: crfree (node->rd_cred);
! 181: node->rd_cred = NULL;
! 182: }
! 183: if (node->wr_cred) {
! 184: crfree (node->wr_cred);
! 185: node->wr_cred = NULL;
! 186: }
! 187:
! 188: xfs_free(node, sizeof(*node), M_NNPFS_NODE);
! 189:
! 190: NNPFSDEB(XDEBNODE, ("free_xfs_node done\n"));
! 191: }
! 192:
! 193: /*
! 194: * FreeBSD 4.4 and newer changed to API to vflush around June 2001
! 195: */
! 196:
! 197: static int
! 198: xfs_vflush(struct mount *mp, int flags)
! 199: {
! 200: #if __FreeBSD__ && __FreeBSD_version > 430000
! 201: return vflush(mp, 0, flags);
! 202: #else
! 203: return vflush(mp, NULL, flags);
! 204: #endif
! 205: }
! 206:
! 207: int
! 208: free_all_xfs_nodes(struct xfs *xfsp, int flags, int unmountp)
! 209: {
! 210: int error = 0;
! 211: struct mount *mp = NNPFS_TO_VFS(xfsp);
! 212:
! 213: if (mp == NULL) {
! 214: NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes already freed\n"));
! 215: return 0;
! 216: }
! 217:
! 218: NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes starting\n"));
! 219:
! 220: xfs_dnlc_purge_mp(mp);
! 221:
! 222: if (xfsp->root) {
! 223: NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes now removing root\n"));
! 224:
! 225: vgone(XNODE_TO_VNODE(xfsp->root));
! 226: xfsp->root = NULL;
! 227: }
! 228:
! 229: NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes root removed\n"));
! 230: NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes now killing all remaining nodes\n"));
! 231:
! 232: /*
! 233: * If we have a syncer vnode, release it (to emulate dounmount)
! 234: * and the create it again when if we are going to need it.
! 235: */
! 236:
! 237: #ifdef HAVE_STRUCT_MOUNT_MNT_SYNCER
! 238: if (!unmountp) {
! 239: if (mp->mnt_syncer != NULL) {
! 240: #ifdef HAVE_KERNEL_VFS_DEALLOCATE_SYNCVNODE
! 241: vfs_deallocate_syncvnode(mp);
! 242: #else
! 243: /*
! 244: * FreeBSD and OpenBSD uses different semantics,
! 245: * FreeBSD does vrele, and OpenBSD does vgone.
! 246: */
! 247: #if defined(__OpenBSD__)
! 248: vgone(mp->mnt_syncer);
! 249: #elif defined(__FreeBSD__)
! 250: vrele(mp->mnt_syncer);
! 251: #else
! 252: #error what os do you use ?
! 253: #endif
! 254: mp->mnt_syncer = NULL;
! 255: #endif
! 256: }
! 257: }
! 258: #endif
! 259: error = xfs_vflush(mp, flags);
! 260: #ifdef HAVE_STRUCT_MOUNT_MNT_SYNCER
! 261: if (!unmountp) {
! 262: NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes not flushing syncer vnode\n"));
! 263: if (mp->mnt_syncer == NULL)
! 264: if (vfs_allocate_syncvnode(mp))
! 265: panic("failed to allocate syncer node when xfs daemon died");
! 266: }
! 267: #endif
! 268:
! 269: if (error) {
! 270: NNPFSDEB(XDEBNODE, ("xfree_all_xfs_nodes: vflush() error == %d\n",
! 271: error));
! 272: return error;
! 273: }
! 274:
! 275: NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes done\n"));
! 276: return error;
! 277: }
! 278:
! 279: void
! 280: vattr2xfs_attr(const struct vattr *va, struct xfs_attr *xa)
! 281: {
! 282: bzero(xa, sizeof(*xa));
! 283: if (va->va_mode != (mode_t)VNOVAL)
! 284: XA_SET_MODE(xa, va->va_mode);
! 285: if (va->va_nlink != VNOVAL)
! 286: XA_SET_NLINK(xa, va->va_nlink);
! 287: if (va->va_size != VNOVAL)
! 288: XA_SET_SIZE(xa, va->va_size);
! 289: if (va->va_uid != VNOVAL)
! 290: XA_SET_UID(xa, va->va_uid);
! 291: if (va->va_gid != VNOVAL)
! 292: XA_SET_GID(xa, va->va_gid);
! 293: if (va->va_atime.tv_sec != VNOVAL)
! 294: XA_SET_ATIME(xa, va->va_atime.tv_sec);
! 295: if (va->va_mtime.tv_sec != VNOVAL)
! 296: XA_SET_MTIME(xa, va->va_mtime.tv_sec);
! 297: if (va->va_ctime.tv_sec != VNOVAL)
! 298: XA_SET_CTIME(xa, va->va_ctime.tv_sec);
! 299: if (va->va_fileid != VNOVAL)
! 300: XA_SET_FILEID(xa, va->va_fileid);
! 301: switch (va->va_type) {
! 302: case VNON:
! 303: xa->xa_type = NNPFS_FILE_NON;
! 304: break;
! 305: case VREG:
! 306: xa->xa_type = NNPFS_FILE_REG;
! 307: break;
! 308: case VDIR:
! 309: xa->xa_type = NNPFS_FILE_DIR;
! 310: break;
! 311: case VBLK:
! 312: xa->xa_type = NNPFS_FILE_BLK;
! 313: break;
! 314: case VCHR:
! 315: xa->xa_type = NNPFS_FILE_CHR;
! 316: break;
! 317: case VLNK:
! 318: xa->xa_type = NNPFS_FILE_LNK;
! 319: break;
! 320: case VSOCK:
! 321: xa->xa_type = NNPFS_FILE_SOCK;
! 322: break;
! 323: case VFIFO:
! 324: xa->xa_type = NNPFS_FILE_FIFO;
! 325: break;
! 326: case VBAD:
! 327: xa->xa_type = NNPFS_FILE_BAD;
! 328: break;
! 329: default:
! 330: panic("xfs_attr2attr: bad value");
! 331: }
! 332: }
! 333:
! 334: #define SET_TIMEVAL(X, S, N) do { (X)->tv_sec = (S); (X)->tv_nsec = (N); } while(0)
! 335:
! 336: void
! 337: xfs_attr2vattr(const struct xfs_attr *xa, struct vattr *va, int clear_node)
! 338: {
! 339: if (clear_node)
! 340: VATTR_NULL(va);
! 341: if (XA_VALID_MODE(xa))
! 342: va->va_mode = xa->xa_mode;
! 343: if (XA_VALID_NLINK(xa))
! 344: va->va_nlink = xa->xa_nlink;
! 345: if (XA_VALID_SIZE(xa)) {
! 346: va->va_size = xa->xa_size;
! 347: va->va_bytes = va->va_size;
! 348: }
! 349: if (XA_VALID_UID(xa))
! 350: va->va_uid = xa->xa_uid;
! 351: if (XA_VALID_GID(xa))
! 352: va->va_gid = xa->xa_gid;
! 353: if (XA_VALID_ATIME(xa)) {
! 354: SET_TIMEVAL(&va->va_atime, xa->xa_atime, 0);
! 355: }
! 356: if (XA_VALID_MTIME(xa)) {
! 357: SET_TIMEVAL(&va->va_mtime, xa->xa_mtime, 0);
! 358: }
! 359: if (XA_VALID_CTIME(xa)) {
! 360: SET_TIMEVAL(&va->va_ctime, xa->xa_ctime, 0);
! 361: }
! 362: if (XA_VALID_FILEID(xa)) {
! 363: va->va_fileid = xa->xa_fileid;
! 364: }
! 365: if (XA_VALID_TYPE(xa)) {
! 366: switch (xa->xa_type) {
! 367: case NNPFS_FILE_NON:
! 368: va->va_type = VNON;
! 369: break;
! 370: case NNPFS_FILE_REG:
! 371: va->va_type = VREG;
! 372: break;
! 373: case NNPFS_FILE_DIR:
! 374: va->va_type = VDIR;
! 375: break;
! 376: case NNPFS_FILE_BLK:
! 377: va->va_type = VBLK;
! 378: break;
! 379: case NNPFS_FILE_CHR:
! 380: va->va_type = VCHR;
! 381: break;
! 382: case NNPFS_FILE_LNK:
! 383: va->va_type = VLNK;
! 384: break;
! 385: case NNPFS_FILE_SOCK:
! 386: va->va_type = VSOCK;
! 387: break;
! 388: case NNPFS_FILE_FIFO:
! 389: va->va_type = VFIFO;
! 390: break;
! 391: case NNPFS_FILE_BAD:
! 392: va->va_type = VBAD;
! 393: break;
! 394: default:
! 395: panic("xfs_attr2vattr: bad value");
! 396: }
! 397: }
! 398: va->va_flags = 0;
! 399: va->va_blocksize = 8192;
! 400: }
! 401:
! 402: /*
! 403: * A single entry DNLC for systems for handling long names that don't
! 404: * get put into the system DNLC.
! 405: */
! 406:
! 407: struct long_entry {
! 408: struct vnode *dvp, *vp;
! 409: char name[MAXNAMLEN + 1];
! 410: size_t len;
! 411: u_long dvpid, vpid;
! 412: };
! 413:
! 414: static struct long_entry tbl;
! 415:
! 416: /*
! 417: * Nuke the `tbl'
! 418: */
! 419:
! 420: static void
! 421: tbl_clear (void)
! 422: {
! 423: tbl.dvp = tbl.vp = NULL;
! 424: tbl.name[0] = '\0';
! 425: tbl.len = 0;
! 426: tbl.dvpid = tbl.vpid = 0;
! 427: }
! 428:
! 429: /*
! 430: * Set the entry in the `tbl'
! 431: */
! 432:
! 433: static void
! 434: tbl_enter (size_t len, const char *name, struct vnode *dvp, struct vnode *vp)
! 435: {
! 436: tbl.len = len;
! 437: bcopy(name, tbl.name, len);
! 438: tbl.dvp = dvp;
! 439: tbl.vp = vp;
! 440: tbl.dvpid = dvp->v_id;
! 441: tbl.vpid = vp->v_id;
! 442: }
! 443:
! 444: /*
! 445: * Lookup in tbl (`dvp', `name', `len') and return result in `res'.
! 446: * Return -1 if successful, otherwise 0.
! 447: */
! 448:
! 449: static int
! 450: tbl_lookup (struct componentname *cnp,
! 451: struct vnode *dvp,
! 452: struct vnode **res)
! 453: {
! 454: if (tbl.dvp == dvp
! 455: && tbl.len == cnp->cn_namelen
! 456: && strncmp(tbl.name, cnp->cn_nameptr, tbl.len) == 0
! 457: && tbl.dvpid == tbl.dvp->v_id
! 458: && tbl.vpid == tbl.vp->v_id) {
! 459:
! 460: *res = tbl.vp;
! 461: return -1;
! 462: } else
! 463: return 0;
! 464: }
! 465:
! 466: /*
! 467: * Store a componentname in the DNLC
! 468: */
! 469:
! 470: int
! 471: xfs_dnlc_enter(struct vnode *dvp,
! 472: xfs_componentname *cnp,
! 473: struct vnode *vp)
! 474: {
! 475: NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter_cnp(%lx, %lx, %lx)\n",
! 476: (unsigned long)dvp,
! 477: (unsigned long)cnp,
! 478: (unsigned long)vp));
! 479: NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter: v_id = %lu\n", (u_long)dvp->v_id));
! 480:
! 481: NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter: calling cache_enter:"
! 482: "dvp = %lx, vp = %lx, cnp = (%s, %ld), "
! 483: "nameiop = %lu, flags = %lx\n",
! 484: (unsigned long)dvp,
! 485: (unsigned long)vp,
! 486: cnp->cn_nameptr, cnp->cn_namelen,
! 487: cnp->cn_nameiop, cnp->cn_flags));
! 488:
! 489: #ifdef NCHNAMLEN
! 490: if (cnp->cn_namelen <= NCHNAMLEN)
! 491: #endif
! 492: {
! 493: /*
! 494: * This is to make sure there's no negative entry already in the dnlc
! 495: */
! 496: u_long save_nameiop;
! 497: u_long save_flags;
! 498: struct vnode *dummy;
! 499:
! 500: save_nameiop = cnp->cn_nameiop;
! 501: save_flags = cnp->cn_flags;
! 502: cnp->cn_nameiop = CREATE;
! 503: cnp->cn_flags &= ~MAKEENTRY;
! 504:
! 505: /*
! 506: * The version number here is not entirely correct, but it's conservative.
! 507: * The real change is sys/kern/vfs_cache:1.20
! 508: */
! 509:
! 510: #if __NetBSD_Version__ >= 104120000 || OpenBSD > 200211
! 511: if (cache_lookup(dvp, &dummy, cnp) != -1) {
! 512: xfs_vfs_unlock(dummy, xfs_cnp_to_proc(cnp));
! 513: printf ("NNPFS PANIC WARNING! xfs_dnlc_enter: %s already in cache\n",
! 514: cnp->cn_nameptr);
! 515: }
! 516: #else
! 517: if (cache_lookup(dvp, &dummy, cnp) != 0) {
! 518: printf ("NNPFS PANIC WARNING! xfs_dnlc_enter: %s already in cache\n",
! 519: cnp->cn_nameptr);
! 520: }
! 521: #endif
! 522:
! 523:
! 524: cnp->cn_nameiop = save_nameiop;
! 525: cnp->cn_flags = save_flags;
! 526: cache_enter(dvp, vp, cnp);
! 527: }
! 528:
! 529: if (vp != NULL)
! 530: tbl_enter (cnp->cn_namelen, cnp->cn_nameptr, dvp, vp);
! 531:
! 532: return 0;
! 533: }
! 534:
! 535:
! 536: static void
! 537: xfs_cnp_init (struct componentname *cn,
! 538: const char *name,
! 539: d_thread_t *proc, struct ucred *cred,
! 540: int nameiop)
! 541: {
! 542: bzero(cn, sizeof(*cn));
! 543: cn->cn_nameptr = (char *)name;
! 544: cn->cn_namelen = strlen(name);
! 545: cn->cn_flags = 0;
! 546: #if __APPLE__
! 547: {
! 548: const unsigned char *p;
! 549: int i;
! 550:
! 551: cn->cn_hash = 0;
! 552: for (p = cn->cn_nameptr, i = 1; *p; ++p, ++i)
! 553: cn->cn_hash += *p * i;
! 554: }
! 555: #elif defined(HAVE_KERNEL_NAMEI_HASH)
! 556: {
! 557: const char *cp = name + cn->cn_namelen;
! 558: cn->cn_hash = namei_hash(name, &cp);
! 559: }
! 560: #elif defined(HAVE_STRUCT_COMPONENTNAME_CN_HASH)
! 561: {
! 562: const unsigned char *p;
! 563:
! 564: cn->cn_hash = 0;
! 565: for (p = cn->cn_nameptr; *p; ++p)
! 566: cn->cn_hash += *p;
! 567: }
! 568: #endif
! 569: cn->cn_nameiop = nameiop;
! 570: #ifdef HAVE_FREEBSD_THREAD
! 571: cn->cn_thread = proc;
! 572: #else
! 573: cn->cn_proc = proc;
! 574: #endif
! 575: cn->cn_cred = cred;
! 576: }
! 577:
! 578:
! 579: /*
! 580: * Store (dvp, name, vp) in the DNLC
! 581: */
! 582:
! 583: int
! 584: xfs_dnlc_enter_name(struct vnode *dvp,
! 585: const char *name,
! 586: struct vnode *vp)
! 587: {
! 588: struct componentname cn;
! 589:
! 590: NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter_name(%lx, \"%s\", %lx)\n",
! 591: (unsigned long)dvp,
! 592: name,
! 593: (unsigned long)vp));
! 594:
! 595: xfs_cnp_init (&cn, name, NULL, NULL, LOOKUP);
! 596: return xfs_dnlc_enter (dvp, &cn, vp);
! 597: }
! 598:
! 599: /*
! 600: * Lookup (dvp, cnp) in the DNLC and return the result in `res'.
! 601: * Return the result from cache_lookup.
! 602: */
! 603:
! 604: static int
! 605: xfs_dnlc_lookup_int(struct vnode *dvp,
! 606: xfs_componentname *cnp,
! 607: struct vnode **res)
! 608: {
! 609: int error;
! 610: u_long saved_flags;
! 611:
! 612: NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup(%lx, \"%s\")\n",
! 613: (unsigned long)dvp, cnp->cn_nameptr));
! 614:
! 615: NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup: v_id = %lu\n", (u_long)dvp->v_id));
! 616:
! 617: NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup: calling cache_lookup:"
! 618: "dvp = %lx, cnp = (%s, %ld), flags = %lx\n",
! 619: (unsigned long)dvp,
! 620: cnp->cn_nameptr, cnp->cn_namelen,
! 621: cnp->cn_flags));
! 622:
! 623: saved_flags = cnp->cn_flags;
! 624: cnp->cn_flags |= MAKEENTRY | LOCKPARENT | ISLASTCN;
! 625:
! 626: error = cache_lookup(dvp, res, cnp);
! 627:
! 628: cnp->cn_flags = saved_flags;
! 629:
! 630: NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup: cache_lookup returned. "
! 631: "error = %d, *res = %lx\n", error,
! 632: (unsigned long)*res));
! 633: return error;
! 634: }
! 635:
! 636: /*
! 637: * do the last (and locking protocol) portion of xnlc_lookup
! 638: *
! 639: * return:
! 640: * -1 for successful
! 641: * 0 for failed
! 642: */
! 643:
! 644: static int
! 645: xfs_dnlc_lock(struct vnode *dvp,
! 646: xfs_componentname *cnp,
! 647: struct vnode **res)
! 648: {
! 649: int error = 0;
! 650:
! 651: /*
! 652: * Try to handle the (complex) BSD locking protocol.
! 653: */
! 654:
! 655: if (*res == dvp) { /* "." */
! 656: VREF(dvp);
! 657: } else if (cnp->cn_flags & ISDOTDOT) { /* ".." */
! 658: u_long vpid = dvp->v_id;
! 659:
! 660: #ifdef HAVE_FREEBSD_THREAD
! 661: xfs_vfs_unlock(dvp, xfs_cnp_to_thread(cnp));
! 662: error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_thread(cnp));
! 663: xfs_vfs_writelock(dvp, xfs_cnp_to_thread(cnp));
! 664: #else
! 665: xfs_vfs_unlock(dvp, xfs_cnp_to_proc(cnp));
! 666: error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_proc(cnp));
! 667: xfs_vfs_writelock(dvp, xfs_cnp_to_proc(cnp));
! 668: #endif
! 669:
! 670: if (error == 0 && dvp->v_id != vpid) {
! 671: vput(*res);
! 672: return 0;
! 673: }
! 674: } else {
! 675: #ifdef HAVE_FREEBSD_THREAD
! 676: error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_thread(cnp));
! 677: #else
! 678: error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_proc(cnp));
! 679: #endif
! 680: }
! 681:
! 682: if (error == 0)
! 683: return -1;
! 684: else
! 685: return 0;
! 686: }
! 687:
! 688: /*
! 689: * Lookup (`dvp', `cnp') in the DNLC (and the local cache).
! 690: *
! 691: * Return -1 if successful, 0 if not and ENOENT if the entry is known
! 692: * not to exist.
! 693: *
! 694: * On modern NetBSD, cache_lookup has been changed to return 0 for
! 695: * successful and -1 for not.
! 696: * (see the comment above for version information).
! 697: */
! 698:
! 699: #if __NetBSD_Version__ >= 104120000 || defined(__OpenBSD__)
! 700:
! 701: int
! 702: xfs_dnlc_lookup(struct vnode *dvp,
! 703: xfs_componentname *cnp,
! 704: struct vnode **res)
! 705: {
! 706: int error = xfs_dnlc_lookup_int (dvp, cnp, res);
! 707:
! 708: if (error == 0)
! 709: return -1;
! 710: else if (error == ENOENT)
! 711: return error;
! 712:
! 713: error = tbl_lookup (cnp, dvp, res);
! 714:
! 715: if (error != -1)
! 716: return error;
! 717:
! 718: return xfs_dnlc_lock (dvp, cnp, res);
! 719: }
! 720:
! 721: #else /* ! __NetBSD_Version__ >= 104120000 && ! OpenBSD > 200211 */
! 722:
! 723: int
! 724: xfs_dnlc_lookup(struct vnode *dvp,
! 725: xfs_componentname *cnp,
! 726: struct vnode **res)
! 727: {
! 728: int error = xfs_dnlc_lookup_int (dvp, cnp, res);
! 729:
! 730: if (error == 0)
! 731: error = tbl_lookup (cnp, dvp, res);
! 732:
! 733: if (error != -1)
! 734: return error;
! 735:
! 736: return xfs_dnlc_lock (dvp, cnp, res);
! 737: }
! 738:
! 739: #endif /* __NetBSD_Version__ >= 104120000 || OpenBSD > 200211 */
! 740:
! 741: /*
! 742: * Remove one entry from the DNLC
! 743: */
! 744:
! 745: void
! 746: xfs_dnlc_purge (struct vnode *vp)
! 747: {
! 748: NNPFSDEB(XDEBDNLC, ("xfs_dnlc_purge\n"));
! 749:
! 750: if (tbl.dvp == vp || tbl.vp == vp)
! 751: tbl_clear ();
! 752:
! 753: cache_purge(vp);
! 754: }
! 755:
! 756: /*
! 757: * Remove all entries belong to `mp' from the DNLC
! 758: */
! 759:
! 760: void
! 761: xfs_dnlc_purge_mp(struct mount *mp)
! 762: {
! 763: NNPFSDEB(XDEBDNLC, ("xfs_dnlc_purge_mp()\n"));
! 764:
! 765: tbl_clear ();
! 766: cache_purgevfs(mp);
! 767: }
! 768:
! 769: /*
! 770: * Returns 1 if pag has any rights set in the node
! 771: */
! 772:
! 773: int
! 774: xfs_has_pag(const struct xfs_node *xn, xfs_pag_t pag)
! 775: {
! 776: int i;
! 777:
! 778: for (i = 0; i < MAXRIGHTS; i++)
! 779: if (xn->id[i] == pag)
! 780: return 1;
! 781:
! 782: return 0;
! 783: }
! 784:
! 785: void
! 786: xfs_update_write_cred(struct xfs_node *xn, struct ucred *cred)
! 787: {
! 788: if (xn->wr_cred)
! 789: crfree (xn->wr_cred);
! 790: crhold (cred);
! 791: xn->wr_cred = cred;
! 792: }
! 793:
! 794: void
! 795: xfs_update_read_cred(struct xfs_node *xn, struct ucred *cred)
! 796: {
! 797: if (xn->rd_cred)
! 798: crfree (xn->rd_cred);
! 799: crhold (cred);
! 800: xn->rd_cred = cred;
! 801: }
CVSweb