diff options
Diffstat (limited to 'libdiskfs/dir-rmdir.c')
-rw-r--r-- | libdiskfs/dir-rmdir.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/libdiskfs/dir-rmdir.c b/libdiskfs/dir-rmdir.c index 959864e4..5dc6a854 100644 --- a/libdiskfs/dir-rmdir.c +++ b/libdiskfs/dir-rmdir.c @@ -17,6 +17,7 @@ #include "priv.h" #include "fs_S.h" +#include <hurd/fsys.h> /* Implement dir_rmdir as described in <hurd/fs.defs>. */ kern_return_t @@ -35,6 +36,8 @@ diskfs_S_dir_rmdir (struct protid *dircred, if (diskfs_readonly) return EROFS; + retry: + mutex_lock (&dnp->lock); error = diskfs_lookup (dnp, name, REMOVE, &np, ds, dircred); @@ -56,6 +59,41 @@ diskfs_S_dir_rmdir (struct protid *dircred, return EINVAL; } + mutex_lock (&np->translator.lock); + if (np->translator.control != MACH_PORT_NULL) + { + mach_port_t control; + + /* There is a running active translator here. Give it a push. + If it squeaks, then return an error. If it consents, then + clear the active translator spec (unless it's been changed + in the interim) and repeat the lookup above. */ + + control = np->translator.control; + mach_port_mod_refs (mach_task_self (), control, MACH_PORT_RIGHT_SEND, 1); + + mutex_unlock (&np->translator.lock); + diskfs_drop_dirstat (dnp, ds); + mutex_unlock (&dnp->lock); + mutex_unlock (&np->lock); + + error = fsys_goaway (control, FSYS_GOAWAY_UNLINK); + if (error) + return error; + + mutex_lock (&np->lock); + mutex_lock (&np->translator.lock); + if (np->translator.control == control) + fshelp_translator_drop (&np->translator); + mutex_unlock (&np->translator.lock); + diskfs_nput (np); + + mach_port_deallocate (mach_task_self (), control); + + goto retry; + } + mutex_unlock (&np->translator.lock); + /* Verify the directory is empty (and valid). (Rmdir ".." won't be valid since ".." will contain a reference to the current directory and thus be non-empty). */ |