/* * union_rmdir(struct vnode *a_dvp, struct vnode *a_vp, * struct componentname *a_cnp) */ static int union_rmdir(struct vop_old_rmdir_args *ap) { struct union_node *dun = VTOUNION(ap->a_dvp); struct union_node *un = VTOUNION(ap->a_vp); struct componentname *cnp = ap->a_cnp; struct thread *td = cnp->cn_td; struct vnode *upperdvp; struct vnode *uppervp; int error; if ((upperdvp = union_lock_upper(dun, td)) == NULLVP) panic("union rmdir: null upper vnode"); if ((uppervp = union_lock_upper(un, td)) != NULLVP) { if (union_dowhiteout(un, cnp->cn_cred, td)) cnp->cn_flags |= CNP_DOWHITEOUT; error = VOP_RMDIR(upperdvp, uppervp, ap->a_cnp); union_unlock_upper(uppervp, td); } else { error = union_mkwhiteout( MOUNTTOUNIONMOUNT(ap->a_dvp->v_mount), dun->un_uppervp, ap->a_cnp, un->un_path); } union_unlock_upper(upperdvp, td); return (error); }
static int zfs_replay_remove(void *arg1, char *arg2, boolean_t byteswap) { zfsvfs_t *zfsvfs = (zfsvfs_t *)arg1; lr_remove_t *lr = (lr_remove_t *)arg2; char *name = (char *)(lr + 1); /* name follows lr_remove_t */ znode_t *dzp; int error; int vflg = 0; if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) return (error); if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; switch ((int)lr->lr_common.lrc_txtype) { case TX_REMOVE: error = VOP_REMOVE(ZTOV(dzp), name, kcred, NULL, vflg); break; case TX_RMDIR: error = VOP_RMDIR(ZTOV(dzp), name, NULL, kcred, NULL, vflg); break; default: error = ENOTSUP; } VN_RELE(ZTOV(dzp)); return (error); }
static int auto_rmdir( vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cred, caller_context_t *ct, int flags) { vnode_t *newvp; int error; AUTOFS_DPRINT((4, "auto_rmdir: vp=%p nm=%s\n", (void *)dvp, nm)); if (error = auto_trigger_mount(dvp, cred, &newvp)) goto done; if (newvp != NULL) { /* * Node is now mounted on. */ if (vn_is_readonly(newvp)) error = EROFS; else error = VOP_RMDIR(newvp, nm, cdir, cred, ct, flags); VN_RELE(newvp); } else error = ENOSYS; done: AUTOFS_DPRINT((5, "auto_rmdir: error=%d\n", error)); return (error); }
static int zfs_replay_remove(zfsvfs_t *zfsvfs, void *data, boolean_t byteswap) { #ifndef TODO_OSV kprintf("TX_REMOVE\n"); return EOPNOTSUPP; #else lr_remove_t *lr = data; char *name = (char *)(lr + 1); /* name follows lr_remove_t */ znode_t *dzp; struct componentname cn; vnode_t *vp; int error; int vflg = 0; if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) return (error); if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; cn.cn_nameptr = name; cn.cn_namelen = strlen(name); cn.cn_nameiop = DELETE; cn.cn_flags = ISLASTCN | SAVENAME; cn.cn_lkflags = LK_EXCLUSIVE | LK_RETRY; cn.cn_cred = kcred; cn.cn_thread = curthread; vn_lock(ZTOV(dzp), LK_EXCLUSIVE | LK_RETRY); error = VOP_LOOKUP(ZTOV(dzp), &vp, &cn); if (error != 0) { VOP_UNLOCK(ZTOV(dzp), 0); goto fail; } switch ((int)lr->lr_common.lrc_txtype) { case TX_REMOVE: error = VOP_REMOVE(ZTOV(dzp), vp, &cn /*,vflg*/); break; case TX_RMDIR: error = VOP_RMDIR(ZTOV(dzp), vp, &cn /*,vflg*/); break; default: error = ENOTSUP; } vput(vp); VOP_UNLOCK(ZTOV(dzp), 0); fail: VN_RELE(ZTOV(dzp)); return (error); #endif }
static int unionfs_rmdir(void *v) { struct vop_rmdir_args *ap = v; int error; struct unionfs_node *dunp; struct unionfs_node *unp; struct unionfs_mount *ump; struct componentname *cnp; struct vnode *udvp; struct vnode *uvp; struct vnode *lvp; UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: enter\n"); error = 0; dunp = VTOUNIONFS(ap->a_dvp); unp = VTOUNIONFS(ap->a_vp); cnp = ap->a_cnp; udvp = dunp->un_uppervp; uvp = unp->un_uppervp; lvp = unp->un_lowervp; if (udvp == NULLVP) return (EROFS); if (udvp == uvp) return (EOPNOTSUPP); if (uvp != NULLVP) { if (lvp != NULLVP) { error = unionfs_check_rmdir(ap->a_vp, cnp->cn_cred); if (error != 0) return (error); } ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULLVP) cnp->cn_flags |= DOWHITEOUT; error = VOP_RMDIR(udvp, uvp, cnp); } else if (lvp != NULLVP) error = unionfs_mkwhiteout(udvp, cnp, unp->un_path); if (error == 0) { cache_purge(ap->a_dvp); cache_purge(ap->a_vp); } UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: leave (%d)\n", error); return (error); }
int RUMP_VOP_RMDIR(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { int error; rump_schedule(); error = VOP_RMDIR(dvp, vp, cnp); rump_unschedule(); return error; }
STATIC int linvfs_rmdir( struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; vnode_t *dvp = LINVFS_GET_VP(dir); int error; VOP_RMDIR(dvp, dentry, NULL, error); if (!error) { validate_fields(inode); validate_fields(dir); } return -error; }
/* * smb_vop_rmdir() * * Only simple rmdir supported, consistent with NT semantics * (can only remove an empty directory). * * The third argument to VOP_RMDIR is the current directory of * the process. It allows rmdir wants to EINVAL if one tries to * remove ".". Since SMB servers do not know what their clients' * current directories are, we fake it by supplying a vnode known * to exist and illegal to remove (rootdir). */ int smb_vop_rmdir(vnode_t *dvp, char *name, int flags, cred_t *cr) { int error; int option_flags = 0; char *np = name; char namebuf[MAXNAMELEN]; if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; if (flags & SMB_CATIA) np = smb_vop_catia_v5tov4(name, namebuf, sizeof (namebuf)); error = VOP_RMDIR(dvp, np, rootdir, cr, &smb_ct, option_flags); return (error); }
/* * Does most of the work for rmdir. */ int vfs_rmdir(char *path) { struct vnode *parent; char name[NAME_MAX+1]; int result; result = vfs_lookparent(path, &parent, name, sizeof(name)); if (result) { return result; } result = VOP_RMDIR(parent, name); VOP_DECREF(parent); return result; }
static int zfsfuse_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name) { if(strlen(name) >= MAXNAMELEN) return ENAMETOOLONG; vfs_t *vfs = (vfs_t *) fuse_req_userdata(req); zfsvfs_t *zfsvfs = vfs->vfs_data; ZFS_ENTER(zfsvfs); znode_t *znode; int error = zfs_zget(zfsvfs, parent, &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(znode != NULL); vnode_t *dvp = ZTOV(znode); ASSERT(dvp != NULL); cred_t cred; zfsfuse_getcred(req, &cred); /* FUSE doesn't care if we remove the current working directory so we just pass NULL as the cwd parameter (no problem for ZFS) */ error = VOP_RMDIR(dvp, (char *) name, NULL, &cred, NULL, 0); /* Linux uses ENOTEMPTY when trying to remove a non-empty directory */ if(error == EEXIST) error = ENOTEMPTY; VN_RELE(dvp); ZFS_EXIT(zfsvfs); return error; }
STATIC inline void cleanup_inode( vnode_t *dvp, vnode_t *vp, struct dentry *dentry, int mode) { struct dentry teardown = {}; int err2; /* Oh, the horror. * If we can't add the ACL or we fail in * linvfs_init_security we must back out. * ENOSPC can hit here, among other things. */ teardown.d_inode = LINVFS_GET_IP(vp); teardown.d_name = dentry->d_name; if (S_ISDIR(mode)) VOP_RMDIR(dvp, &teardown, NULL, err2); else VOP_REMOVE(dvp, &teardown, NULL, err2); VN_RELE(vp); }
STATIC int linvfs_mknod( struct inode *dir, struct dentry *dentry, int mode, int rdev) { struct inode *ip; vattr_t va; vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir); xfs_acl_t *default_acl = NULL; attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; int error; if (test_default_acl && test_default_acl(dvp)) { if (!_ACL_ALLOC(default_acl)) return -ENOMEM; if (!_ACL_GET_DEFAULT(dvp, default_acl)) { _ACL_FREE(default_acl); default_acl = NULL; } } #ifdef CONFIG_XFS_POSIX_ACL /* * Conditionally compiled so that the ACL base kernel changes can be * split out into separate patches - remove this once MS_POSIXACL is * accepted, or some other way to implement this exists. */ if (IS_POSIXACL(dir) && !default_acl && has_fs_struct(current)) mode &= ~current->fs->umask; #endif memset(&va, 0, sizeof(va)); va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; va.va_type = IFTOVT(mode); va.va_mode = mode; switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: va.va_rdev = XFS_MKDEV(MAJOR(rdev), MINOR(rdev)); va.va_mask |= XFS_AT_RDEV; /*FALLTHROUGH*/ case S_IFREG: VOP_CREATE(dvp, dentry, &va, &vp, NULL, error); break; case S_IFDIR: VOP_MKDIR(dvp, dentry, &va, &vp, NULL, error); break; default: error = EINVAL; break; } if (default_acl) { if (!error) { error = _ACL_INHERIT(vp, &va, default_acl); if (!error) { VMODIFY(vp); } else { struct dentry teardown = {}; int err2; /* Oh, the horror. * If we can't add the ACL we must back out. * ENOSPC can hit here, among other things. */ teardown.d_inode = ip = LINVFS_GET_IP(vp); teardown.d_name = dentry->d_name; vn_mark_bad(vp); if (S_ISDIR(mode)) VOP_RMDIR(dvp, &teardown, NULL, err2); else VOP_REMOVE(dvp, &teardown, NULL, err2); VN_RELE(vp); } } _ACL_FREE(default_acl); } if (!error) { ASSERT(vp); ip = LINVFS_GET_IP(vp); if (S_ISCHR(mode) || S_ISBLK(mode)) ip->i_rdev = to_kdev_t(rdev); else if (S_ISDIR(mode)) validate_fields(ip); d_instantiate(dentry, ip); validate_fields(dir); } return -error; }