int unionfs_rmdir(struct inode *dir, struct dentry *dentry) { int err = 0; struct unionfs_dir_state *namelist = NULL; print_entry_location(); lock_dentry(dentry); fist_print_dentry("IN unionfs_rmdir: ", dentry); /* check if this unionfs directory is empty or not */ err = check_empty(dentry, &namelist); if (err) { goto out; } if (IS_SET(dir->i_sb, DELETE_WHITEOUT)) { /* Delete the first directory. */ err = unionfs_rmdir_first(dir, dentry, namelist); /* create whiteout */ if (!err) { err = create_whiteout(dentry, dbstart(dentry)); } else { int new_err; if (dbstart(dentry) == 0) goto out; /* exit if the error returned was NOT -EROFS */ if (!IS_COPYUP_ERR(err)) goto out; new_err = create_whiteout(dentry, dbstart(dentry) - 1); if (new_err != -EEXIST) err = new_err; } } else { /* delete all. */ err = unionfs_rmdir_all(dir, dentry, namelist); } out: /* call d_drop so the system "forgets" about us */ if (!err) d_drop(dentry); if (namelist) free_rdstate(namelist); unlock_dentry(dentry); print_exit_status(err); return err; }
int unionfs_rmdir(struct inode *dir, struct dentry *dentry) { int err = 0; struct unionfs_dir_state *namelist = NULL; unionfs_lock_dentry(dentry); /* check if this unionfs directory is empty or not */ err = check_empty(dentry, &namelist); if (err) goto out; err = unionfs_rmdir_first(dir, dentry, namelist); /* create whiteout */ if (!err) err = create_whiteout(dentry, dbstart(dentry)); else { int new_err; if (dbstart(dentry) == 0) goto out; /* exit if the error returned was NOT -EROFS */ if (!IS_COPYUP_ERR(err)) goto out; new_err = create_whiteout(dentry, dbstart(dentry) - 1); if (new_err != -EEXIST) err = new_err; } out: /* call d_drop so the system "forgets" about us */ if (!err) d_drop(dentry); if (namelist) free_rdstate(namelist); unionfs_unlock_dentry(dentry); return err; }
int unionfs_rmdir(struct inode *dir, struct dentry *dentry) { int err = 0; struct unionfs_dir_state *namelist = NULL; print_entry_location(); lock_dentry(dentry); fist_print_dentry("IN unionfs_rmdir: ", dentry); /* check if this unionfs directory is empty or not */ err = check_empty(dentry, &namelist); if (err) { #if 0 /* vfs_rmdir(our caller) unhashed the dentry. This will recover * the Unionfs inode number for the directory itself, but the * children are already lost. It seems that tmpfs manages its * way around this by upping the refcount on everything. * * Even if we do this, we still lose the inode numbers of the * children. The best way to fix this is to fix the VFS (or * use persistent inode maps). */ if (d_unhashed(dentry)) d_rehash(dentry); #endif goto out; } #ifdef UNIONFS_DELETE_ALL if (IS_SET(dir->i_sb, DELETE_ALL)) { /* delete all. */ err = unionfs_rmdir_all(dir, dentry, namelist); } else { /* Delete the first directory. */ #endif err = unionfs_rmdir_first(dir, dentry, namelist); /* create whiteout */ if (!err) { err = create_whiteout(dentry, dbstart(dentry)); } else { int new_err; if (dbstart(dentry) == 0) goto out; /* exit if the error returned was NOT -EROFS */ if (!IS_COPYUP_ERR(err)) goto out; new_err = create_whiteout(dentry, dbstart(dentry) - 1); if (new_err != -EEXIST) err = new_err; } #ifdef UNIONFS_DELETE_ALL } #endif out: /* call d_drop so the system "forgets" about us */ if (!err) d_drop(dentry); if (namelist) free_rdstate(namelist); unlock_dentry(dentry); print_exit_status(err); return err; }