Stacking on NFS. Wrapfs has been tested with LTP, racer, fsx, parallel
compile, and more. It's been tested on top of ext2, ext3, xfs, reiserfs,
and tmpfs -- and passed all tests. However, on top of nfs3, wrapfs has to
-treat silly-deleted files as if they don't exist; the VFS also has special
-handling for silly-deleted files, so this isn't unusual. Even so, there are
-sometimes races between readdir and lower files which may have gotten
-unlinked: an "rm -fr" may return ENOENT for entries which show up in
-readdir, but were already unlinked on NFS below. It's mainly harmless.
-This could be solved easily if the VFS were to pass an "unlink/rmdir" namei
-intent to the file system: then wrapfs could detect that the intent was to
-remove the lower object, and ignore ENOENT errors from the lower file
-system.
+treat silly-deleted files as if they don't exist: in ->unlink, if we try to
+vfs_unlink an NFS silly-deleted file, NFS returns EBUSY; so we simply ignore
+it and return 0 (success) to the VFS. NFS will delete this file later on
+anyway. As the VFS also has special handling for silly-deleted files, this
+isn't unusual. A cleaner way to handle this in the future is if the VFS
+were to handle silly-deleted (aka "delayed-delete") files entirely at the
+VFS.
------------------------------------------------------------------------------
HISTORY:
dget(lower_dentry);
lower_dir_dentry = lock_parent(lower_dentry);
- /*
- * If the lower dentry is already silly-renamed (NFS), then we treat
- * this unlink operation as if it already succeeded, and don't
- * actually call vfs_unlink on the lower dentry (NFS may return
- * EBUSY). Note: VFS also has special handling for silly-renamed
- * files, so this treatment isn't unusual.
- */
- if (lower_dentry->d_flags & DCACHE_NFSFS_RENAMED) {
- err = 0;
- goto out_unlock;
- }
err = mnt_want_write(lower_path.mnt);
if (err)
goto out_unlock;
err = vfs_unlink(lower_dir_inode, lower_dentry);
- /* Note: unlinking on top of NFS can cause silly-renamed files */
+
+ /*
+ * Note: unlinking on top of NFS can cause silly-renamed files.
+ * Trying to delete such files results in EBUSY from NFS
+ * below. Silly-renamed files will get deleted by NFS later on, so
+ * we just need to detect them here and treat such EBUSY errors as
+ * if the upper file was successfully deleted.
+ */
+ if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED)
+ err = 0;
if (err)
goto out;
fsstack_copy_attr_times(dir, lower_dir_inode);
lower_dentry = lower_path.dentry;
lower_dir_dentry = lock_parent(lower_dentry);
- /* see comment about silly-renamed files in wrapfs_unlink */
- if (lower_dentry->d_flags & DCACHE_NFSFS_RENAMED) {
- err = 0;
- goto out_unlock;
- }
err = mnt_want_write(lower_path.mnt);
if (err)
goto out_unlock;