/* * smb_vop_rename() * * The rename is for files in the same tree (identical TID) only. */ int smb_vop_rename(vnode_t *from_dvp, char *from_name, vnode_t *to_dvp, char *to_name, int flags, cred_t *cr) { int error; int option_flags = 0; char *from, *to, *fbuf, *tbuf; if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; if (flags & SMB_CATIA) { tbuf = kmem_zalloc(MAXNAMELEN, KM_SLEEP); to = smb_vop_catia_v5tov4(to_name, tbuf, MAXNAMELEN); if (strchr(to, '/') != NULL) { kmem_free(tbuf, MAXNAMELEN); return (EILSEQ); } fbuf = kmem_zalloc(MAXNAMELEN, KM_SLEEP); from = smb_vop_catia_v5tov4(from_name, fbuf, MAXNAMELEN); error = VOP_RENAME(from_dvp, from, to_dvp, to, cr, &smb_ct, option_flags); kmem_free(tbuf, MAXNAMELEN); kmem_free(fbuf, MAXNAMELEN); return (error); } error = VOP_RENAME(from_dvp, from_name, to_dvp, to_name, cr, &smb_ct, option_flags); return (error); }
STATIC int linvfs_rename( struct inode *odir, struct dentry *odentry, struct inode *ndir, struct dentry *ndentry) { struct inode *new_inode = ndentry->d_inode; vnode_t *fvp; /* from directory */ vnode_t *tvp; /* target directory */ int error; fvp = LINVFS_GET_VP(odir); tvp = LINVFS_GET_VP(ndir); VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error); if (error) return -error; if (new_inode) validate_fields(new_inode); validate_fields(odir); if (ndir != odir) validate_fields(ndir); return 0; }
static int zfs_replay_rename(void *arg1, char *arg2, boolean_t byteswap) { zfsvfs_t *zfsvfs = (zfsvfs_t *)arg1; lr_rename_t *lr = (lr_rename_t *)arg2; char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */ char *tname = sname + strlen(sname) + 1; znode_t *sdzp, *tdzp; int error; int vflg = 0; if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); if ((error = zfs_zget(zfsvfs, lr->lr_sdoid, &sdzp)) != 0) return (error); if ((error = zfs_zget(zfsvfs, lr->lr_tdoid, &tdzp)) != 0) { VN_RELE(ZTOV(sdzp)); return (error); } if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; error = VOP_RENAME(ZTOV(sdzp), sname, ZTOV(tdzp), tname, kcred, NULL, vflg); VN_RELE(ZTOV(tdzp)); VN_RELE(ZTOV(sdzp)); return (error); }
/* Does most of the work for rename(). */ int vfs_rename(char *oldpath, char *newpath) { struct vnode *olddir; char oldname[NAME_MAX+1]; struct vnode *newdir; char newname[NAME_MAX+1]; int result; result = vfs_lookparent(oldpath, &olddir, oldname, sizeof(oldname)); if (result) { return result; } result = vfs_lookparent(newpath, &newdir, newname, sizeof(newname)); if (result) { VOP_DECREF(olddir); return result; } if (olddir->vn_fs==NULL || newdir->vn_fs==NULL || olddir->vn_fs != newdir->vn_fs) { VOP_DECREF(newdir); VOP_DECREF(olddir); return EXDEV; } result = VOP_RENAME(olddir, oldname, newdir, newname); VOP_DECREF(newdir); VOP_DECREF(olddir); return result; }
static int zfsfuse_rename(fuse_req_t req, fuse_ino_t parent, const char *name, fuse_ino_t newparent, const char *newname) { if(strlen(name) >= MAXNAMELEN) return ENAMETOOLONG; if(strlen(newname) >= MAXNAMELEN) return ENAMETOOLONG; vfs_t *vfs = (vfs_t *) fuse_req_userdata(req); zfsvfs_t *zfsvfs = vfs->vfs_data; ZFS_ENTER(zfsvfs); znode_t *p_znode, *np_znode; int error = zfs_zget(zfsvfs, parent, &p_znode, B_FALSE); if(error) { ZFS_EXIT(zfsvfs); /* If the inode we are trying to get was recently deleted dnode_hold_impl will return EEXIST instead of ENOENT */ return error == EEXIST ? ENOENT : error; } ASSERT(p_znode != NULL); error = zfs_zget(zfsvfs, newparent, &np_znode, B_FALSE); if(error) { VN_RELE(ZTOV(p_znode)); ZFS_EXIT(zfsvfs); /* If the inode we are trying to get was recently deleted dnode_hold_impl will return EEXIST instead of ENOENT */ return error == EEXIST ? ENOENT : error; } ASSERT(np_znode != NULL); vnode_t *p_vp = ZTOV(p_znode); vnode_t *np_vp = ZTOV(np_znode); ASSERT(p_vp != NULL); ASSERT(np_vp != NULL); cred_t cred; zfsfuse_getcred(req, &cred); error = VOP_RENAME(p_vp, (char *) name, np_vp, (char *) newname, &cred, NULL, 0); VN_RELE(p_vp); VN_RELE(np_vp); ZFS_EXIT(zfsvfs); return error; }
int RUMP_VOP_RENAME(struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp, struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp) { int error; rump_schedule(); error = VOP_RENAME(fdvp, fvp, fcnp, tdvp, tvp, tcnp); rump_unschedule(); return error; }
static int xattr_dir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr, caller_context_t *ct, int flags) { vnode_t *spvp, *tpvp; int error; if (is_sattr_name(snm) || is_sattr_name(tnm)) return (xattr_copy(sdvp, snm, tdvp, tnm, cr, ct)); /* * We know that sdvp is a GFS dir, or we wouldn't be here. * Get the real unnamed directory. */ error = xattr_dir_realdir(sdvp, &spvp, LOOKUP_XATTR, cr, ct); if (error) { return (error); } if (sdvp == tdvp) { /* * If the source and target are the same GFS directory, the * underlying unnamed source and target dir will be the same. */ tpvp = spvp; } else if (tdvp->v_flag & V_SYSATTR) { /* * If the target dir is a different GFS directory, * find its underlying unnamed dir. */ error = xattr_dir_realdir(tdvp, &tpvp, LOOKUP_XATTR, cr, ct); if (error) { return (error); } } else { /* * Target dir is outside of GFS, pass it on through. */ tpvp = tdvp; } error = VOP_RENAME(spvp, snm, tpvp, tnm, cr, ct, flags); return (error); }
static int zfs_replay_rename(zfsvfs_t *zfsvfs, lr_rename_t *lr, boolean_t byteswap) { char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */ char *tname = sname + strlen(sname) + 1; znode_t *sdzp, *tdzp; struct componentname scn, tcn; vnode_t *svp, *tvp; kthread_t *td = curthread; int error; int vflg = 0; if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); if ((error = zfs_zget(zfsvfs, lr->lr_sdoid, &sdzp)) != 0) return (error); if ((error = zfs_zget(zfsvfs, lr->lr_tdoid, &tdzp)) != 0) { VN_RELE(ZTOV(sdzp)); return (error); } if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; svp = tvp = NULL; scn.cn_nameptr = sname; scn.cn_namelen = strlen(sname); scn.cn_nameiop = DELETE; scn.cn_flags = ISLASTCN | SAVENAME; scn.cn_lkflags = LK_EXCLUSIVE | LK_RETRY; scn.cn_cred = kcred; scn.cn_thread = td; vn_lock(ZTOV(sdzp), LK_EXCLUSIVE | LK_RETRY); error = VOP_LOOKUP(ZTOV(sdzp), &svp, &scn); VOP_UNLOCK(ZTOV(sdzp), 0); if (error != 0) goto fail; VOP_UNLOCK(svp, 0); tcn.cn_nameptr = tname; tcn.cn_namelen = strlen(tname); tcn.cn_nameiop = RENAME; tcn.cn_flags = ISLASTCN | SAVENAME; tcn.cn_lkflags = LK_EXCLUSIVE | LK_RETRY; tcn.cn_cred = kcred; tcn.cn_thread = td; vn_lock(ZTOV(tdzp), LK_EXCLUSIVE | LK_RETRY); error = VOP_LOOKUP(ZTOV(tdzp), &tvp, &tcn); if (error == EJUSTRETURN) tvp = NULL; else if (error != 0) { VOP_UNLOCK(ZTOV(tdzp), 0); goto fail; } error = VOP_RENAME(ZTOV(sdzp), svp, &scn, ZTOV(tdzp), tvp, &tcn /*,vflg*/); return (error); fail: if (svp != NULL) vrele(svp); if (tvp != NULL) vrele(tvp); VN_RELE(ZTOV(tdzp)); VN_RELE(ZTOV(sdzp)); return (error); }
static int unionfs_rename(void *v) { struct vop_rename_args *ap = v; int error; struct vnode *fdvp; struct vnode *fvp; struct componentname *fcnp; struct vnode *tdvp; struct vnode *tvp; struct componentname *tcnp; struct vnode *ltdvp; struct vnode *ltvp; /* rename target vnodes */ struct vnode *rfdvp; struct vnode *rfvp; struct vnode *rtdvp; struct vnode *rtvp; int needrelookup; struct unionfs_mount *ump; struct unionfs_node *unp; UNIONFS_INTERNAL_DEBUG("unionfs_rename: enter\n"); error = 0; fdvp = ap->a_fdvp; fvp = ap->a_fvp; fcnp = ap->a_fcnp; tdvp = ap->a_tdvp; tvp = ap->a_tvp; tcnp = ap->a_tcnp; ltdvp = NULLVP; ltvp = NULLVP; rfdvp = fdvp; rfvp = fvp; rtdvp = tdvp; rtvp = tvp; needrelookup = 0; /* check for cross device rename */ if (fvp->v_mount != tdvp->v_mount || (tvp != NULLVP && fvp->v_mount != tvp->v_mount)) { error = EXDEV; goto unionfs_rename_abort; } /* Renaming a file to itself has no effect. */ if (fvp == tvp) goto unionfs_rename_abort; /* * from/to vnode is unionfs node. */ unp = VTOUNIONFS(fdvp); #ifdef UNIONFS_IDBG_RENAME UNIONFS_INTERNAL_DEBUG("fdvp=%p, ufdvp=%p, lfdvp=%p\n", fdvp, unp->un_uppervp, unp->un_lowervp); #endif if (unp->un_uppervp == NULLVP) { error = ENODEV; goto unionfs_rename_abort; } rfdvp = unp->un_uppervp; vref(rfdvp); unp = VTOUNIONFS(fvp); #ifdef UNIONFS_IDBG_RENAME UNIONFS_INTERNAL_DEBUG("fvp=%p, ufvp=%p, lfvp=%p\n", fvp, unp->un_uppervp, unp->un_lowervp); #endif ump = MOUNTTOUNIONFSMOUNT(fvp->v_mount); if (unp->un_uppervp == NULLVP) { switch (fvp->v_type) { case VREG: if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) goto unionfs_rename_abort; error = unionfs_copyfile(unp, 1, fcnp->cn_cred); VOP_UNLOCK(fvp); if (error != 0) goto unionfs_rename_abort; break; case VDIR: if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) goto unionfs_rename_abort; error = unionfs_mkshadowdir(ump, rfdvp, unp, fcnp); VOP_UNLOCK(fvp); if (error != 0) goto unionfs_rename_abort; break; default: error = ENODEV; goto unionfs_rename_abort; } needrelookup = 1; } if (unp->un_lowervp != NULLVP) fcnp->cn_flags |= DOWHITEOUT; rfvp = unp->un_uppervp; vref(rfvp); unp = VTOUNIONFS(tdvp); #ifdef UNIONFS_IDBG_RENAME UNIONFS_INTERNAL_DEBUG("tdvp=%p, utdvp=%p, ltdvp=%p\n", tdvp, unp->un_uppervp, unp->un_lowervp); #endif if (unp->un_uppervp == NULLVP) { error = ENODEV; goto unionfs_rename_abort; } rtdvp = unp->un_uppervp; ltdvp = unp->un_lowervp; vref(rtdvp); if (tdvp == tvp) { rtvp = rtdvp; vref(rtvp); } else if (tvp != NULLVP) { unp = VTOUNIONFS(tvp); #ifdef UNIONFS_IDBG_RENAME UNIONFS_INTERNAL_DEBUG("tvp=%p, utvp=%p, ltvp=%p\n", tvp, unp->un_uppervp, unp->un_lowervp); #endif if (unp->un_uppervp == NULLVP) rtvp = NULLVP; else { if (tvp->v_type == VDIR) { error = EINVAL; goto unionfs_rename_abort; } rtvp = unp->un_uppervp; ltvp = unp->un_lowervp; vref(rtvp); } } if (needrelookup != 0) { if ((error = vn_lock(fdvp, LK_EXCLUSIVE)) != 0) goto unionfs_rename_abort; error = unionfs_relookup_for_delete(fdvp, fcnp); VOP_UNLOCK(fdvp); if (error != 0) goto unionfs_rename_abort; /* Locke of tvp is canceled in order to avoid recursive lock. */ if (tvp != NULLVP && tvp != tdvp) VOP_UNLOCK(tvp); error = unionfs_relookup_for_rename(tdvp, tcnp); if (tvp != NULLVP && tvp != tdvp) vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); if (error != 0) goto unionfs_rename_abort; } error = VOP_RENAME(rfdvp, rfvp, fcnp, rtdvp, rtvp, tcnp); if (error == 0) { if (rtvp != NULLVP && rtvp->v_type == VDIR) cache_purge(tdvp); if (fvp->v_type == VDIR && fdvp != tdvp) cache_purge(fdvp); } if (fdvp != rfdvp) vrele(fdvp); if (fvp != rfvp) vrele(fvp); if (ltdvp != NULLVP) VOP_UNLOCK(ltdvp); if (tdvp != rtdvp) vrele(tdvp); if (ltvp != NULLVP) VOP_UNLOCK(ltvp); if (tvp != rtvp && tvp != NULLVP) { if (rtvp == NULLVP) vput(tvp); else vrele(tvp); } UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error); return (error); unionfs_rename_abort: if (fdvp != rfdvp) vrele(rfdvp); if (fvp != rfvp) vrele(rfvp); if (tdvp != rtdvp) vrele(rtdvp); vput(tdvp); if (tvp != rtvp && rtvp != NULLVP) vrele(rtvp); if (tvp != NULLVP) { if (tdvp != tvp) vput(tvp); else vrele(tvp); } vrele(fdvp); vrele(fvp); UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error); return (error); }
static int auto_rename( vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr, caller_context_t *ct, int flags) { vnode_t *o_newvp, *n_newvp; int error; AUTOFS_DPRINT((4, "auto_rename odvp %p onm %s to ndvp %p nnm %s\n", (void *)odvp, onm, (void *)ndvp, nnm)); /* * we know odvp is an autonode, otherwise this function * could not have ever been called. */ ASSERT(vn_matchops(odvp, auto_vnodeops)); if (error = auto_trigger_mount(odvp, cr, &o_newvp)) goto done; if (o_newvp == NULL) { /* * can't rename an autonode */ error = ENOSYS; goto done; } if (vn_matchops(ndvp, auto_vnodeops)) { /* * directory is AUTOFS, need to trigger the * mount of the real filesystem. */ if (error = auto_trigger_mount(ndvp, cr, &n_newvp)) { VN_RELE(o_newvp); goto done; } if (n_newvp == NULL) { /* * target can't be an autonode */ error = ENOSYS; VN_RELE(o_newvp); goto done; } } else { /* * destination directory mount had been * triggered prior to the call to this function. */ n_newvp = ndvp; } ASSERT(!vn_matchops(n_newvp, auto_vnodeops)); if (vn_is_readonly(n_newvp)) { error = EROFS; VN_RELE(o_newvp); if (n_newvp != ndvp) VN_RELE(n_newvp); goto done; } error = VOP_RENAME(o_newvp, onm, n_newvp, nnm, cr, ct, flags); VN_RELE(o_newvp); if (n_newvp != ndvp) VN_RELE(n_newvp); done: AUTOFS_DPRINT((5, "auto_rename error=%d\n", error)); return (error); }
/* * union_rename(struct vnode *a_fdvp, struct vnode *a_fvp, * struct componentname *a_fcnp, struct vnode *a_tdvp, * struct vnode *a_tvp, struct componentname *a_tcnp) */ static int union_rename(struct vop_old_rename_args *ap) { int error; struct vnode *fdvp = ap->a_fdvp; struct vnode *fvp = ap->a_fvp; struct vnode *tdvp = ap->a_tdvp; struct vnode *tvp = ap->a_tvp; /* * Figure out what fdvp to pass to our upper or lower vnode. If we * replace the fdvp, release the original one and ref the new one. */ if (fdvp->v_tag == VT_UNION) { /* always true */ struct union_node *un = VTOUNION(fdvp); if (un->un_uppervp == NULLVP) { /* * this should never happen in normal * operation but might if there was * a problem creating the top-level shadow * directory. */ error = EXDEV; goto bad; } fdvp = un->un_uppervp; vref(fdvp); vrele(ap->a_fdvp); } /* * Figure out what fvp to pass to our upper or lower vnode. If we * replace the fvp, release the original one and ref the new one. */ if (fvp->v_tag == VT_UNION) { /* always true */ struct union_node *un = VTOUNION(fvp); #if 0 struct union_mount *um = MOUNTTOUNIONMOUNT(fvp->v_mount); #endif if (un->un_uppervp == NULLVP) { switch(fvp->v_type) { case VREG: vn_lock(un->un_vnode, LK_EXCLUSIVE | LK_RETRY); error = union_copyup(un, 1, ap->a_fcnp->cn_cred, ap->a_fcnp->cn_td); vn_unlock(un->un_vnode); if (error) goto bad; break; case VDIR: /* * XXX not yet. * * There is only one way to rename a directory * based in the lowervp, and that is to copy * the entire directory hierarchy. Otherwise * it would not last across a reboot. */ #if 0 vrele(fvp); fvp = NULL; vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY); error = union_mkshadow(um, fdvp, ap->a_fcnp, &un->un_uppervp); vn_unlock(fdvp); if (un->un_uppervp) vn_unlock(un->un_uppervp); if (error) goto bad; break; #endif default: error = EXDEV; goto bad; } } if (un->un_lowervp != NULLVP) ap->a_fcnp->cn_flags |= CNP_DOWHITEOUT; fvp = un->un_uppervp; vref(fvp); vrele(ap->a_fvp); } /* * Figure out what tdvp (destination directory) to pass to the * lower level. If we replace it with uppervp, we need to vput the * old one. The exclusive lock is transfered to what we will pass * down in the VOP_RENAME and we replace uppervp with a simple * reference. */ if (tdvp->v_tag == VT_UNION) { struct union_node *un = VTOUNION(tdvp); if (un->un_uppervp == NULLVP) { /* * this should never happen in normal * operation but might if there was * a problem creating the top-level shadow * directory. */ error = EXDEV; goto bad; } /* * new tdvp is a lock and reference on uppervp, put away * the old tdvp. */ tdvp = union_lock_upper(un, ap->a_tcnp->cn_td); vput(ap->a_tdvp); } /* * Figure out what tvp (destination file) to pass to the * lower level. * * If the uppervp file does not exist put away the (wrong) * file and change tvp to NULL. */ if (tvp != NULLVP && tvp->v_tag == VT_UNION) { struct union_node *un = VTOUNION(tvp); tvp = union_lock_upper(un, ap->a_tcnp->cn_td); vput(ap->a_tvp); /* note: tvp may be NULL */ } /* * VOP_RENAME releases/vputs prior to returning, so we have no * cleanup to do. */ return (VOP_RENAME(fdvp, fvp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp)); /* * Error. We still have to release / vput the various elements. */ bad: vrele(fdvp); if (fvp) vrele(fvp); vput(tdvp); if (tvp != NULLVP) { if (tvp != tdvp) vput(tvp); else vrele(tvp); } return (error); }
/* * Creates the fs cache directory. * The directory name is the ascii version of the fsid. * Also makes a symlink to the directory using the specified name. */ int fscdir_create(cachefscache_t *cachep, char *namep, fscache_t *fscp) { int error; vnode_t *fscdirvp = NULL; vnode_t *infovp = NULL; vnode_t *attrvp = NULL; struct vattr *attrp = (struct vattr *)NULL; char name[CFS_FRONTFILE_NAME_SIZE]; int files; int blocks = 0; cfs_cid_t cid; ino64_t fsid; ASSERT(MUTEX_HELD(&cachep->c_fslistlock)); ASSERT(fscp->fs_infovp == NULL); ASSERT(fscp->fs_fscdirvp == NULL); ASSERT(fscp->fs_fsattrdir == NULL); /* directory, symlink and options file + attrcache dir */ files = 0; while (files < 4) { error = cachefs_allocfile(cachep); if (error) goto out; files++; } error = cachefs_allocblocks(cachep, 4, CACHEFS_RL_NONE); if (error) goto out; blocks = 4; attrp = cachefs_kmem_alloc(sizeof (struct vattr), KM_SLEEP); attrp->va_mode = S_IFDIR | 0777; attrp->va_uid = 0; attrp->va_gid = 0; attrp->va_type = VDIR; attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; error = VOP_MKDIR(cachep->c_dirvp, namep, attrp, &fscdirvp, kcred, NULL, 0, NULL); if (error) { cmn_err(CE_WARN, "Can't create fs cache directory"); goto out; } /* * Created the directory. Get the fileno. That'll be the cachefs_fsid. */ attrp->va_mask = AT_NODEID; error = VOP_GETATTR(fscdirvp, attrp, 0, kcred, NULL); if (error) { goto out; } fsid = attrp->va_nodeid; attrp->va_mode = S_IFREG | 0666; attrp->va_uid = 0; attrp->va_gid = 0; attrp->va_type = VREG; attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; error = VOP_CREATE(fscdirvp, CACHEFS_FSINFO, attrp, EXCL, 0600, &infovp, kcred, 0, NULL, NULL); if (error) { cmn_err(CE_WARN, "Can't create fs option file"); goto out; } attrp->va_size = MAXBSIZE; attrp->va_mask = AT_SIZE; error = VOP_SETATTR(infovp, attrp, 0, kcred, NULL); if (error) { cmn_err(CE_WARN, "Can't set size of fsinfo file"); goto out; } /* write out the info file */ fscp->fs_flags |= CFS_FS_DIRTYINFO; error = fscache_info_sync(fscp); if (error) goto out; /* * Install the symlink from cachefs_fsid -> directory. */ cid.cid_flags = 0; cid.cid_fileno = fsid; make_ascii_name(&cid, name); error = VOP_RENAME(cachep->c_dirvp, namep, cachep->c_dirvp, name, kcred, NULL, 0); if (error) { cmn_err(CE_WARN, "Can't rename cache directory"); goto out; } attrp->va_mask = AT_MODE | AT_TYPE; attrp->va_mode = 0777; attrp->va_type = VLNK; error = VOP_SYMLINK(cachep->c_dirvp, namep, attrp, name, kcred, NULL, 0); if (error) { cmn_err(CE_WARN, "Can't create cache directory symlink"); goto out; } /* * Finally, make the attrcache directory */ attrp->va_mode = S_IFDIR | 0777; attrp->va_uid = 0; attrp->va_gid = 0; attrp->va_type = VDIR; attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; error = VOP_MKDIR(fscdirvp, ATTRCACHE_NAME, attrp, &attrvp, kcred, NULL, 0, NULL); if (error) { cmn_err(CE_WARN, "Can't create attrcache dir for fscache"); goto out; } mutex_enter(&fscp->fs_fslock); fscp->fs_cfsid = fsid; fscp->fs_fscdirvp = fscdirvp; fscp->fs_fsattrdir = attrvp; fscp->fs_infovp = infovp; mutex_exit(&fscp->fs_fslock); out: if (error) { while (files-- > 0) cachefs_freefile(cachep); if (fscdirvp) VN_RELE(fscdirvp); if (blocks) cachefs_freeblocks(cachep, blocks, CACHEFS_RL_NONE); if (attrvp) VN_RELE(attrvp); if (infovp) VN_RELE(infovp); } if (attrp) cachefs_kmem_free(attrp, sizeof (struct vattr)); return (error); }