From: Erez Zadok <ezk@cs.sunysb.edu>
To: akpm@linux-foundation.org
Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
viro@ftp.linux.org.uk, hch@infradead.org,
Erez Zadok <ezk@cs.sunysb.edu>
Subject: [PATCH 07/30] Unionfs: create new special files only in first branch
Date: Fri, 28 Dec 2007 15:42:41 -0500 [thread overview]
Message-ID: <1198874589339-git-send-email-ezk@cs.sunysb.edu> (raw)
In-Reply-To: <11988745841003-git-send-email-ezk@cs.sunysb.edu>
When creating a new special file, always create it in the first branch,
which is always writeable, not in the branch which may have a whiteout in
it. This makes the policy for the creation of new special files consistent
with that of new files/directories, as well as improves efficiency a bit.
Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
---
fs/unionfs/inode.c | 174 +++++++++++++++++++++++++++------------------------
1 files changed, 92 insertions(+), 82 deletions(-)
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 63ff3d3..8076d0b 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -686,15 +686,15 @@ out:
return err;
}
-static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+static int unionfs_mknod(struct inode *parent, struct dentry *dentry, int mode,
dev_t dev)
{
int err = 0;
- struct dentry *lower_dentry = NULL, *whiteout_dentry = NULL;
+ struct dentry *lower_dentry = NULL;
+ struct dentry *wh_dentry = NULL;
struct dentry *lower_parent_dentry = NULL;
- int bindex = 0, bstart;
char *name = NULL;
- int whiteout_unlinked = 0;
+ int valid = 0;
unionfs_read_lock(dentry->d_sb);
unionfs_lock_dentry(dentry);
@@ -705,115 +705,125 @@ static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
goto out;
}
- bstart = dbstart(dentry);
-
- lower_dentry = unionfs_lower_dentry(dentry);
+ /*
+ * It's only a bug if this dentry was not negative and couldn't be
+ * revalidated (shouldn't happen).
+ */
+ BUG_ON(!valid && dentry->d_inode);
/*
- * check if whiteout exists in this branch, i.e. lookup .wh.foo
- * first.
+ * We shouldn't create things in a read-only branch; this check is a
+ * bit redundant as we don't allow branch 0 to be read-only at the
+ * moment
*/
- name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
- if (unlikely(IS_ERR(name))) {
- err = PTR_ERR(name);
+ err = is_robranch_super(dentry->d_sb, 0);
+ if (err) {
+ err = -EROFS;
goto out;
}
- whiteout_dentry = lookup_one_len(name, lower_dentry->d_parent,
- dentry->d_name.len + UNIONFS_WHLEN);
- if (IS_ERR(whiteout_dentry)) {
- err = PTR_ERR(whiteout_dentry);
- goto out;
- }
+ /*
+ * We _always_ create on branch 0
+ */
+ lower_dentry = unionfs_lower_dentry_idx(dentry, 0);
+ if (lower_dentry) {
+ /*
+ * check if whiteout exists in this branch, i.e. lookup .wh.foo
+ * first.
+ */
+ name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+ if (unlikely(IS_ERR(name))) {
+ err = PTR_ERR(name);
+ goto out;
+ }
- if (!whiteout_dentry->d_inode) {
- dput(whiteout_dentry);
- whiteout_dentry = NULL;
- } else {
- /* found .wh.foo, unlink it */
- lower_parent_dentry = lock_parent(whiteout_dentry);
+ wh_dentry = lookup_one_len(name, lower_dentry->d_parent,
+ dentry->d_name.len + UNIONFS_WHLEN);
+ if (IS_ERR(wh_dentry)) {
+ err = PTR_ERR(wh_dentry);
+ wh_dentry = NULL;
+ goto out;
+ }
- /* found a.wh.foo entry, remove it then do vfs_mkdir */
- err = is_robranch_super(dentry->d_sb, bstart);
- if (!err)
- err = vfs_unlink(lower_parent_dentry->d_inode,
- whiteout_dentry);
- dput(whiteout_dentry);
+ if (wh_dentry->d_inode) {
+ /*
+ * .wh.foo has been found, so let's unlink it
+ */
+ struct dentry *lower_dir_dentry;
- unlock_dir(lower_parent_dentry);
+ lower_dir_dentry = lock_parent(wh_dentry);
+ err = vfs_unlink(lower_dir_dentry->d_inode, wh_dentry);
+ unlock_dir(lower_dir_dentry);
- if (err) {
- if (!IS_COPYUP_ERR(err))
+ /*
+ * Whiteouts are special files and should be deleted
+ * no matter what (as if they never existed), in
+ * order to allow this create operation to succeed.
+ * This is especially important in sticky
+ * directories: a whiteout may have been created by
+ * one user, but the newly created file may be
+ * created by another user. Therefore, in order to
+ * maintain Unix semantics, if the vfs_unlink above
+ * ailed, then we have to try to directly unlink the
+ * whiteout. Note: in the ODF version of unionfs,
+ * whiteout are handled much more cleanly.
+ */
+ if (err == -EPERM) {
+ struct inode *inode = lower_dir_dentry->d_inode;
+ err = inode->i_op->unlink(inode, wh_dentry);
+ }
+ if (err) {
+ printk(KERN_ERR "unionfs: mknod: could not "
+ "unlink whiteout, err = %d\n", err);
goto out;
- bstart--;
- } else {
- whiteout_unlinked = 1;
- }
- }
-
- for (bindex = bstart; bindex >= 0; bindex--) {
- if (is_robranch_super(dentry->d_sb, bindex))
- continue;
-
- lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
- if (!lower_dentry) {
- lower_dentry = create_parents(dir, dentry,
- dentry->d_name.name,
- bindex);
- if (IS_ERR(lower_dentry)) {
- printk(KERN_ERR "unionfs: failed to create "
- "parents on %d, err = %ld\n",
- bindex, PTR_ERR(lower_dentry));
- continue;
}
}
-
- lower_parent_dentry = lock_parent(lower_dentry);
- if (IS_ERR(lower_parent_dentry)) {
- err = PTR_ERR(lower_parent_dentry);
+ } else {
+ /*
+ * if lower_dentry is NULL, create the entire
+ * dentry directory structure in branch 0.
+ */
+ lower_dentry = create_parents(parent, dentry,
+ dentry->d_name.name, 0);
+ if (IS_ERR(lower_dentry)) {
+ err = PTR_ERR(lower_dentry);
goto out;
}
+ }
- err = vfs_mknod(lower_parent_dentry->d_inode,
- lower_dentry, mode, dev);
-
- if (err) {
- unlock_dir(lower_parent_dentry);
- break;
- }
+ lower_parent_dentry = lock_parent(lower_dentry);
+ if (IS_ERR(lower_parent_dentry)) {
+ err = PTR_ERR(lower_parent_dentry);
+ goto out;
+ }
- /*
- * Only INTERPOSE_LOOKUP can return a value other than 0 on
- * err.
- */
- err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
+ err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
+ if (!err) {
+ err = PTR_ERR(unionfs_interpose(dentry, parent->i_sb, 0));
if (!err) {
- fsstack_copy_attr_times(dir,
- lower_parent_dentry->d_inode);
- fsstack_copy_inode_size(dir,
+ unionfs_copy_attr_times(parent);
+ fsstack_copy_inode_size(parent,
lower_parent_dentry->d_inode);
- /* update number of links on parent directory */
- dir->i_nlink = unionfs_get_nlinks(dir);
+ /* update no. of links on parent directory */
+ parent->i_nlink = unionfs_get_nlinks(parent);
}
- unlock_dir(lower_parent_dentry);
-
- break;
}
-out:
- if (!dentry->d_inode)
- d_drop(dentry);
+ unlock_dir(lower_parent_dentry);
+out:
+ dput(wh_dentry);
kfree(name);
if (!err)
unionfs_postcopyup_setmnt(dentry);
- unionfs_check_inode(dir);
+ unionfs_check_inode(parent);
+ if (!err)
+ unionfs_check_dentry(dentry->d_parent);
unionfs_check_dentry(dentry);
unionfs_unlock_dentry(dentry);
unionfs_read_unlock(dentry->d_sb);
-
return err;
}
--
1.5.2.2
next prev parent reply other threads:[~2007-12-28 20:46 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-12-28 20:42 [GIT PULL -mm] 00/30 Unionfs+fsstack updates/fixes/cleanups Erez Zadok
2007-12-28 20:42 ` [PATCH 01/30] VFS/fs_stack: drop cast on inode passed to i_size_read Erez Zadok
2007-12-28 20:42 ` [PATCH 02/30] VFS/fs_stack: use locking around i_size_write in 32-bit systems Erez Zadok
2007-12-28 20:42 ` [PATCH 03/30] Unionfs: " Erez Zadok
2007-12-28 20:42 ` [PATCH 04/30] Unionfs: clarify usage.txt read/write behavior Erez Zadok
2007-12-28 20:42 ` [PATCH 05/30] Unionfs: interpose cleanup and fix for spliced dentries Erez Zadok
2007-12-28 20:42 ` [PATCH 06/30] Unionfs: initialize inode times for reused inodes Erez Zadok
2007-12-28 20:42 ` Erez Zadok [this message]
2007-12-28 20:42 ` [PATCH 08/30] Unionfs: create new symlinks only in first branch Erez Zadok
2007-12-28 20:42 ` [PATCH 09/30] Unionfs: release special files on copyup Erez Zadok
2007-12-28 20:42 ` [PATCH 10/30] Unionfs: mmap fixes Erez Zadok
2007-12-28 20:42 ` [PATCH 11/30] Unionfs: restructure unionfs_setattr and fix truncation order Erez Zadok
2007-12-28 20:42 ` [PATCH 12/30] Unionfs: remove custom read/write methods Erez Zadok
2007-12-28 20:42 ` [PATCH 13/30] Unionfs: prevent deadlock in cache coherency Erez Zadok
2007-12-28 20:42 ` [PATCH 14/30] Unionfs: remove unnecessary conditional inode lock Erez Zadok
2007-12-28 20:42 ` [PATCH 15/30] Unionfs: remove unnecessary lock when deleting whiteouts Erez Zadok
2007-12-28 20:42 ` [PATCH 16/30] Unionfs: remove unnecessary lock in read_inode Erez Zadok
2007-12-28 20:42 ` [PATCH 17/30] Unionfs: remove unnecessary locking in follow-link Erez Zadok
2007-12-28 20:42 ` [PATCH 18/30] Unionfs: remove unnecessary parent lock in create Erez Zadok
2007-12-28 20:42 ` [PATCH 19/30] Unionfs: prevent false lockdep warnings in stacking Erez Zadok
2007-12-28 20:42 ` [PATCH 20/30] Unionfs: implement lockdep classes Erez Zadok
2007-12-28 20:42 ` [PATCH 21/30] Unionfs: minor code rearrangement in rename Erez Zadok
2007-12-28 20:42 ` [PATCH 22/30] Unionfs: handle on lower inodes in lookup Erez Zadok
2007-12-28 20:42 ` [PATCH 23/30] Unionfs: set our superblock a/m/ctime granularity Erez Zadok
2007-12-28 20:42 ` [PATCH 24/30] Unionfs: update inode times after a successful open Erez Zadok
2007-12-28 20:42 ` [PATCH 25/30] Unionfs: minor cleanup in check_empty Erez Zadok
2007-12-28 20:43 ` [PATCH 26/30] Unionfs: initialize namelist variable in rename Erez Zadok
2007-12-28 20:43 ` [PATCH 27/30] Unionfs: cleanup lower inodes after successful unlink Erez Zadok
2007-12-28 20:43 ` [PATCH 28/30] Unionfs: don't check dentry on error Erez Zadok
2007-12-28 20:43 ` [PATCH 29/30] Unionfs: implement d_iput method Erez Zadok
2007-12-28 20:43 ` [PATCH 30/30] Unionfs: don't check parent dentries Erez Zadok
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1198874589339-git-send-email-ezk@cs.sunysb.edu \
--to=ezk@cs.sunysb.edu \
--cc=akpm@linux-foundation.org \
--cc=hch@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=viro@ftp.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®