int do_rmdir (struct inode *inode, const char *name, int len) { #if POST_20_KERNEL_F struct dentry *tmp_dent; #endif int ret_code; DOWN(&(inode->i_sem)); #if POST_20_KERNEL_F /* Grab a dentry for the directory being removed. */ ret_code = ovlfs_inode_get_child_dentry(inode, name, len, &tmp_dent, OVLFS_DENT_GET_POSITIVE); if ( ret_code == 0 ) { /* Use the vfs_rmdir function to do the dirty work. */ ret_code = vfs_rmdir(inode, tmp_dent); dput(tmp_dent); } #else IMARK(inode); ret = inode->i_op->rmdir(inode, name, len); #endif UP(&(inode->i_sem)); return ret_code; }
static int wrapfs_rmdir(struct inode *dir, struct dentry *dentry) { struct dentry *lower_dentry; struct dentry *lower_dir_dentry; int err; struct path lower_path; wrapfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; lower_dir_dentry = lock_parent(lower_dentry); err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); if (err) goto out; d_drop(dentry); /* drop our dentry on success (why not VFS's job?) */ if (dentry->d_inode) clear_nlink(dentry->d_inode); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); out: unlock_dir(lower_dir_dentry); wrapfs_put_lower_path(dentry, &lower_path); #ifdef NEKTECH_LOGGER /*NEKTECH LOGGING*/ nektech_logger (dir, dentry, NEKTECH_RMDIR); #endif /*NEKTECH LOGGING*/ return err; }
static int ccfs_rmdir(struct inode *dir, struct dentry *dentry) { struct dentry *lower_dentry; struct dentry *lower_dir_dentry; int rc; lower_dentry = ccfs_get_nested_dentry(dentry); mdbg(INFO3,"RMDIR w/ lower_dentry->d_name.name = [%s]", lower_dentry->d_name.name); dget(dentry); lower_dir_dentry = lock_parent(lower_dentry); dget(lower_dentry); rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); dput(lower_dentry); if (!rc) d_delete(lower_dentry); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); //Fix for kernel 3.7.1 use function set_nlink by Jiri Rakosnik unlock_dir(lower_dir_dentry); if (!rc) d_drop(dentry); dput(dentry); return rc; }
static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry, struct unionfs_dir_state *namelist) { int err; struct dentry *hidden_dentry; struct dentry *hidden_dir_dentry = NULL; /* Here we need to remove whiteout entries. */ err = delete_whiteouts(dentry, dbstart(dentry), namelist); if (err) goto out; hidden_dentry = unionfs_lower_dentry(dentry); hidden_dir_dentry = lock_parent(hidden_dentry); /* avoid destroying the hidden inode if the file is in use */ dget(hidden_dentry); if (!(err = is_robranch(dentry))) err = vfs_rmdir(hidden_dir_dentry->d_inode, hidden_dentry); dput(hidden_dentry); fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode); /* propagate number of hard-links */ dentry->d_inode->i_nlink = unionfs_get_nlinks(dentry->d_inode); out: if (hidden_dir_dentry) unlock_dir(hidden_dir_dentry); return err; }
static int diaryfs_rmdir(struct inode * dir, struct dentry * dentry) { int err; struct dentry * lower_dentry; struct dentry * lower_dir_dentry; struct path lower_path; diaryfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; lower_dir_dentry = lock_parent(lower_dentry); err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); if (err) goto out; d_drop(dentry); if (dentry->d_inode) clear_nlink(dentry->d_inode); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); out: unlock_dir(lower_dir_dentry); diaryfs_put_lower_path(dentry, &lower_path); return err; }
static int dev_rmdir(const char *name) { struct nameidata nd; struct dentry *dentry; int err; err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, name, LOOKUP_PARENT, &nd); if (err) return err; mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); if (!IS_ERR(dentry)) { if (dentry->d_inode) { if (dentry->d_inode->i_private == &dev_mnt) err = vfs_rmdir(nd.path.dentry->d_inode, dentry); else err = -EPERM; } else { err = -ENOENT; } dput(dentry); } else { err = PTR_ERR(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); return err; }
static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) { struct dentry *lower_dentry; struct dentry *lower_dir_dentry; int rc; #ifdef CONFIG_SDP if(IS_CHAMBER_DENTRY(dentry)) { printk("You're removing chamber directory. I/O error\n"); return -EIO; } #endif lower_dentry = ecryptfs_dentry_to_lower(dentry); dget(dentry); lower_dir_dentry = lock_parent(lower_dentry); dget(lower_dentry); rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); dput(lower_dentry); if (!rc && dentry->d_inode) clear_nlink(dentry->d_inode); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); unlock_dir(lower_dir_dentry); if (!rc) d_drop(dentry); dput(dentry); return rc; }
static void cmd_rmd(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) { vfs_stat_t st; if (arg == NULL) { send_msg(pcb, fsm, msg501); return; } if (*arg == '\0') { send_msg(pcb, fsm, msg501); return; } if (vfs_stat(fsm->vfs, arg, &st) != 0) { send_msg(pcb, fsm, msg550); return; } if (!VFS_ISDIR(st.st_mode)) { send_msg(pcb, fsm, msg550); return; } if (vfs_rmdir(fsm->vfs, arg) != 0) { send_msg(pcb, fsm, msg550); } else { send_msg(pcb, fsm, msg250); } }
static int wrapfs_rmdir(struct inode *dir, struct dentry *dentry) { struct dentry *lower_dentry; struct dentry *lower_dir_dentry; int err; struct path lower_path; wrapfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; lower_dir_dentry = lock_parent(lower_dentry); err = mnt_want_write(lower_path.mnt); if (err) goto out_unlock; err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); if (err) goto out; d_drop(dentry); /* drop our dentry on success (why not VFS's job?) */ if (dentry->d_inode) clear_nlink(dentry->d_inode); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); out: mnt_drop_write(lower_path.mnt); out_unlock: unlock_dir(lower_dir_dentry); wrapfs_put_lower_path(dentry, &lower_path); return err; }
/* sys_rmdir * Copies the given path into the kernel space, and call vfs_rmdir. */ int sys_rmdir(userptr_t path) { char *p; int result; if ((p = (char *)kmalloc(__PATH_MAX)) == NULL) { return ENOMEM; } /* Copy in the path */ result = copyinstr(path, p, __PATH_MAX, NULL); if (result) { kfree(p); return result; } /* Check that given path of directory is valid */ if (strcmp(p, ".") == 0 || strcmp(p, "..") == 0) { kfree(p); return EINVAL; } result = vfs_rmdir(p); kfree(p); return result; }
static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry) { struct dentry *lower_dentry; struct dentry *lower_dir_dentry; int err; struct path lower_path; struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); const struct cred *saved_cred = NULL; //char *path_s = NULL; int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive); if(!check_caller_access_to_name(dir, dentry->d_name.name, sbi->options.derive, 1, has_rw)) { printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" " dentry: %s, task:%s\n", __func__, dentry->d_name.name, current->comm); err = -EACCES; goto out_eacces; } /* save current_cred and override it */ OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred); /* sdcardfs_get_real_lower(): in case of remove an user's obb dentry * the dentry on the original path should be deleted. */ sdcardfs_get_real_lower(dentry, &lower_path); lower_dentry = lower_path.dentry; lower_dir_dentry = lock_parent(lower_dentry); sdcardfs_drop_shared_icache(dir->i_sb, lower_dentry->d_inode); err = mnt_want_write(lower_path.mnt); if (err) goto out_unlock; err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); if (err) goto out; d_drop(dentry); /* drop our dentry on success (why not VFS's job?) */ if (dentry->d_inode) clear_nlink(dentry->d_inode); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); out: mnt_drop_write(lower_path.mnt); out_unlock: unlock_dir(lower_dir_dentry); sdcardfs_put_real_lower(dentry, &lower_path); REVERT_CRED(saved_cred); out_eacces: return err; }
void hwgfs_unregister( hwgfs_handle_t de) { struct inode *parent_inode = de->d_parent->d_inode; if (S_ISDIR(de->d_inode->i_mode)) vfs_rmdir(parent_inode, de); else vfs_unlink(parent_inode, de); }
static int u2fs_rmdir(struct inode *dir, struct dentry *dentry) { struct dentry *lower_dentry; struct dentry *lower_dir_dentry; int err; struct path lower_path; /* creating whiteout if directory was in read-only */ if((U2FS_D(dentry)->lower_path[LEFT].dentry) == NULL && (U2FS_D(dentry)->lower_path[LEFT].mnt) == NULL){ err = create_whiteout(dentry); if(err) err = -EIO; goto out_whiteout; } u2fs_get_lower_path(dentry, &lower_path, LEFT); lower_dentry = lower_path.dentry; lower_dir_dentry = lock_parent(lower_dentry); err = mnt_want_write(lower_path.mnt); if (err) goto out_unlock; err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); if (err) goto out; if (dentry->d_inode) clear_nlink(dentry->d_inode); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); out: mnt_drop_write(lower_path.mnt); out_unlock: unlock_dir(lower_dir_dentry); u2fs_put_lower_path(dentry, &lower_path); /* creating whiteout if file as existing in both branches */ if((U2FS_D(dentry)->lower_path[RIGHT].dentry) != NULL && (U2FS_D(dentry)->lower_path[RIGHT].mnt) != NULL){ err = create_whiteout(dentry); if(err) err = -EIO; } d_drop(dentry); out_whiteout: return err; }
static int nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry) { int status; /* For now this directory should already be empty, but we empty it of * any regular files anyway, just in case the directory was created by * a kernel from the future.... */ nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); status = vfs_rmdir(dir->d_inode, dentry); mutex_unlock(&dir->d_inode->i_mutex); return status; }
int remove_physical_dir (struct file *file) { struct dentry *dentry; struct inode *dir; int res = 0; dentry = file->f_dentry; dir = dentry->d_parent->d_inode; res = vfs_rmdir (dir, dentry); dput (dentry); put_filp (file); return res; }
int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry) { int err; LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry)); IMustLock(dir); lockdep_off(); err = vfs_rmdir(dir, dentry); lockdep_on(); /* dir inode is locked */ if (!err) au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/ return err; }
static int rmdir(int argc, char *argv[]) { if(argc != 2) { printf("Usage: %s dir\n", argv[0]); return 1; } char *path = vfs_path_mkabsolute(cwd, argv[1]); errval_t err = vfs_rmdir(path); free(path); if (err_is_fail(err)) { printf("%s\n", err_getstring(err)); return 1; } else { return 0; } }
int vfsub_rmdir(struct inode *dir, struct path *path) { int err; struct dentry *d; IMustLock(dir); d = path->dentry; path->dentry = d->d_parent; err = security_path_rmdir(path, d); path->dentry = d; if (unlikely(err)) goto out; lockdep_off(); err = vfs_rmdir(dir, path->dentry); lockdep_on(); if (!err) { struct path tmp = { .dentry = path->dentry->d_parent, .mnt = path->mnt }; vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ } out: return err; } /* ---------------------------------------------------------------------- */ /* todo: support mmap_sem? */ ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { ssize_t err; lockdep_off(); err = vfs_read(file, ubuf, count, ppos); lockdep_on(); if (err >= 0) vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ return err; }
static int cmd_vfs_rmdir(struct vmm_chardev *cdev, const char *path) { int rc; struct stat st; rc = vfs_stat(path, &st); if (rc) { vmm_cprintf(cdev, "Path %s does not exist.\n", path); return rc; } if (!(st.st_mode & S_IFDIR)) { vmm_cprintf(cdev, "Path %s should be directory.\n", path); return VMM_EINVALID; } return vfs_rmdir(path); }
/* * scfs_mkdir * * Parameters: * @*dir: inode of the dir to create * @*scfs_dentry: dentry of the dir to create * @mode: * * Return: * SCFS_SUCCESS if success, otherwise if error * * Description: * mkdir() for SCFS. */ static int scfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { struct dentry *lower_dir_dentry; struct dentry *lower_parent_dentry; int ret; SCFS_DEBUG_START; lower_dir_dentry = scfs_lower_dentry(dentry); lower_parent_dentry = lock_parent(lower_dir_dentry); ret = vfs_mkdir(lower_parent_dentry->d_inode, lower_dir_dentry, mode); if (ret || !lower_dir_dentry->d_inode) { SCFS_PRINT_ERROR("dir %s vfs_mkdir failed, " "lower_dir %s lower_parent %s mode %x\n", dentry->d_name.name, lower_dir_dentry->d_name.name, lower_parent_dentry->d_name.name, mode); goto out; } ret = scfs_interpose(lower_dir_dentry, dentry, dir->i_sb); if (ret) { SCFS_PRINT_ERROR("dir %s interpose failed, " "lower_dir %s lower_parent %s mode %x\n", dentry->d_name.name, lower_dir_dentry->d_name.name, lower_parent_dentry->d_name.name, mode); vfs_rmdir(lower_parent_dentry->d_inode, lower_dir_dentry); goto out; } fsstack_copy_attr_times(dir, lower_parent_dentry->d_inode); fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode); set_nlink(dir, lower_parent_dentry->d_inode->i_nlink); out: unlock_dir(lower_parent_dentry); if (!dentry->d_inode) d_drop(dentry); SCFS_DEBUG_END; return ret; }
static int esdfs_rmdir(struct inode *dir, struct dentry *dentry) { struct dentry *lower_dentry; struct dentry *lower_dir_dentry; int err; struct path lower_path; const struct cred *creds = esdfs_override_creds(ESDFS_SB(dir->i_sb), NULL); if (!creds) return -ENOMEM; /* Never remove a pseudo link target. Only the source. */ if (ESDFS_DENTRY_HAS_STUB(dentry)) esdfs_get_lower_stub_path(dentry, &lower_path); else esdfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; lower_dir_dentry = lock_parent(lower_dentry); err = mnt_want_write(lower_path.mnt); if (err) goto out_unlock; err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); if (err) goto out; d_drop(dentry); /* drop our dentry on success (why not VFS's job?) */ if (dentry->d_inode) clear_nlink(dentry->d_inode); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); out: mnt_drop_write(lower_path.mnt); out_unlock: unlock_dir(lower_dir_dentry); esdfs_put_lower_path(dentry, &lower_path); esdfs_revert_creds(creds, NULL); return err; }
static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry, struct unionfs_dir_state *namelist) { int err; struct dentry *hidden_dentry; struct dentry *hidden_dir_dentry = NULL; print_entry_location(); fist_print_dentry("IN unionfs_rmdir_first: ", dentry); /* Here we need to remove whiteout entries. */ err = delete_whiteouts(dentry, dbstart(dentry), namelist); if (err) { goto out; } hidden_dentry = dtohd(dentry); PASSERT(hidden_dentry); hidden_dir_dentry = lock_parent(hidden_dentry); /* avoid destroying the hidden inode if the file is in use */ DGET(hidden_dentry); if (!(err = is_robranch(dentry))) { err = vfs_rmdir(hidden_dir_dentry->d_inode, hidden_dentry); } DPUT(hidden_dentry); fist_copy_attr_times(dir, hidden_dir_dentry->d_inode); /* propagate number of hard-links */ dentry->d_inode->i_nlink = get_nlinks(dentry->d_inode); out: if (hidden_dir_dentry) { unlock_dir(hidden_dir_dentry); } fist_print_dentry("OUT unionfs_rmdir_first: ", dentry); print_exit_status(err); return err; }
static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) { struct dentry *lower_dentry; struct dentry *lower_dir_dentry; int rc; lower_dentry = ecryptfs_dentry_to_lower(dentry); dget(dentry); lower_dir_dentry = lock_parent(lower_dentry); dget(lower_dentry); rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); dput(lower_dentry); if (!rc && dentry->d_inode) clear_nlink(dentry->d_inode); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); unlock_dir(lower_dir_dentry); if (!rc) d_drop(dentry); dput(dentry); return rc; }
static int dev_rmdir(const char *name) { struct path parent; struct dentry *dentry; int err; dentry = kern_path_locked(name, &parent); if (IS_ERR(dentry)) return PTR_ERR(dentry); if (dentry->d_inode) { if (dentry->d_inode->i_private == &thread) err = vfs_rmdir(parent.dentry->d_inode, dentry); else err = -EPERM; } else { err = -ENOENT; } dput(dentry); mutex_unlock(&parent.dentry->d_inode->i_mutex); path_put(&parent); return err; }
//==================================================================== // Delete the given device directory. Returns 0 on success and // non-zero on failure. static int delete_dev_dir(const char *dev_dir_path) { int err = 0; struct path path; unsigned int lookup_flags = LOOKUP_REVAL; // Look up the path for this directory. if ((err = kern_path(dev_dir_path, lookup_flags, &path)) != 0) { return err; } if (!path.dentry || !path.dentry->d_parent) { ALERT("Undelete device directory entry has no parent"); return -EINVAL; } if ((err = vfs_rmdir(path.dentry->d_parent->d_inode, path.dentry)) != 0) { return err; } return err; }
int main(int argc, char *argv[]) { errval_t err; // initialization vfs_init(); bench_init(); // mount nfs err = vfs_mkdir("/nfs"); assert(err_is_ok(err)); err = vfs_mount("/nfs", "nfs://10.110.4.4/local/nfs"); assert(err_is_ok(err)); // argument processing if (argc == 3) { printf("Started vfs_bench in command-line mode\n"); int32_t chunksize = atol(argv[1]); int32_t repetitions = atol(argv[2]); single_run(chunksize, repetitions); } else { printf("Started vfs_bench.\n"); for (int32_t i = 1; i < 20; i++) { single_run(4096, i * 2000); } } //err = vfs_unmount("/nfs"); // unmount is NYI //assert(err_is_ok(err)); err = vfs_rmdir("/nfs"); assert(err_is_ok(err)); return 0; }
static int do_rmdir(int argc, char ** argv) { char fpath[VFS_MAX_PATH]; int ret = 0; int i; if(argc < 2) { usage(); return -1; } for(i = 1; i < argc; i++) { if(shell_realpath(argv[i], fpath) < 0) continue; if(vfs_rmdir(fpath) != 0) { ret = -1; printf("mkdir: failed to remove directory %s\r\n", fpath); } } return ret; }
static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) { struct dentry *lower_dentry; struct vfsmount *lower_mnt; struct dentry *lower_dir_dentry; int rc; lower_dentry = ecryptfs_dentry_to_lower(dentry); lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); dget(dentry); lower_dir_dentry = lock_parent(lower_dentry); dget(lower_dentry); rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt); dput(lower_dentry); if (!rc) d_delete(lower_dentry); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; unlock_dir(lower_dir_dentry); if (!rc) d_drop(dentry); dput(dentry); return rc; }
static int unionfs_rmdir_all(struct inode *dir, struct dentry *dentry, struct unionfs_dir_state *namelist) { struct dentry *hidden_dentry; struct dentry *hidden_dir_dentry; int bstart, bend, bindex; int err = 0; int global_err = 0; print_entry_location(); fist_print_dentry("IN unionfs_rmdir_all: ", dentry); bstart = dbstart(dentry); bend = dbend(dentry); for (bindex = bend; bindex >= bstart; bindex--) { hidden_dentry = dtohd_index(dentry, bindex); if (!hidden_dentry) continue; hidden_dir_dentry = lock_parent(hidden_dentry); if (S_ISDIR(hidden_dentry->d_inode->i_mode)) { delete_whiteouts(dentry, bindex, namelist); if (!(err = is_robranch_super(dentry->d_sb, bindex))) { err = vfs_rmdir(hidden_dir_dentry->d_inode, hidden_dentry); } } else { err = -EISDIR; } fist_copy_attr_times(dir, hidden_dir_dentry->d_inode); unlock_dir(hidden_dir_dentry); if (err) { int local_err = unionfs_refresh_hidden_dentry(dentry, bindex); if (local_err) { err = local_err; goto out; } if (!IS_COPYUP_ERR(err) && err != -ENOTEMPTY && err != -EISDIR) goto out; global_err = err; } } /* check if encountered error in the above loop */ if (global_err) { /* If we failed in the leftmost branch, then err will be set and we should * move one over to create the whiteout. Otherwise, we should try in the * leftmost branch. */ if (err) { if (dbstart(dentry) == 0) { goto out; } err = create_whiteout(dentry, dbstart(dentry) - 1); } else { err = create_whiteout(dentry, dbstart(dentry)); } } else { err = create_whiteout(dentry, dbstart(dentry)); } out: /* propagate number of hard-links */ dentry->d_inode->i_nlink = get_nlinks(dentry->d_inode); fist_print_dentry("OUT unionfs_rmdir_all: ", dentry); print_exit_status(err); return err; }
/* * Unlink a file or directory * N.B. After this call fhp needs an fh_put */ int nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, char *fname, int flen) { struct dentry *dentry, *rdentry; struct inode *dirp; int err; /* N.B. We shouldn't need this test ... handled by dentry layer */ err = nfserr_acces; if (!flen || isdotent(fname, flen)) goto out; err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE); if (err) goto out; dentry = fhp->fh_dentry; dirp = dentry->d_inode; rdentry = lookup_dentry(fname, dget(dentry), 0); err = PTR_ERR(rdentry); if (IS_ERR(rdentry)) goto out_nfserr; if (!rdentry->d_inode) { dput(rdentry); err = nfserr_noent; goto out; } if (type != S_IFDIR) { /* It's UNLINK */ err = fh_lock_parent(fhp, rdentry); if (err) goto out; err = vfs_unlink(dirp, rdentry); DQUOT_DROP(dirp); fh_unlock(fhp); dput(rdentry); } else { /* It's RMDIR */ /* See comments in fs/namei.c:do_rmdir */ rdentry->d_count++; nfsd_double_down(&dirp->i_sem, &rdentry->d_inode->i_sem); if (!fhp->fh_pre_mtime) fhp->fh_pre_mtime = dirp->i_mtime; fhp->fh_locked = 1; err = -ENOENT; if (check_parent(dirp, rdentry)) err = vfs_rmdir(dirp, rdentry); rdentry->d_count--; DQUOT_DROP(dirp); if (!fhp->fh_post_version) fhp->fh_post_version = dirp->i_version; fhp->fh_locked = 0; nfsd_double_up(&dirp->i_sem, &rdentry->d_inode->i_sem); dput(rdentry); } if (err) goto out_nfserr; if (EX_ISSYNC(fhp->fh_export)) write_inode_now(dirp); out: return err; out_nfserr: err = nfserrno(-err); goto out; }