From: Valerie Aurora <vaurora@redhat.com>
To: Jan Blunck <jblunck@suse.de>,
Alexander Viro <viro@zeniv.linux.org.uk>,
Christoph Hellwig <hch@infradead.org>,
Andy Whitcroft <apw@canonical.com>,
Scott James Remnant <scott@canonica
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
Jan Blunck <jblunck@suse.de>,
David Woodhouse <dwmw2@infradead.org>
Subject: [PATCH 13/41] whiteout: tmpfs whiteout support
Date: Wed, 21 Oct 2009 12:19:11 -0700 [thread overview]
Message-ID: <1256152779-10054-14-git-send-email-vaurora@redhat.com> (raw)
In-Reply-To: <1256152779-10054-13-git-send-email-vaurora@redhat.com>
From: Jan Blunck <jblunck@suse.de>
Add support for whiteout dentries to tmpfs.
XXX - Not sure this is the right patch to put the code for supporting
whiteouts in d_genocide().
Signed-off-by: Jan Blunck <jblunck@suse.de>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Valerie Aurora <vaurora@redhat.com>
---
fs/dcache.c | 3 +-
mm/shmem.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 137 insertions(+), 15 deletions(-)
diff --git a/fs/dcache.c b/fs/dcache.c
index 0fcae4b..1fae1df 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2280,7 +2280,8 @@ resume:
struct list_head *tmp = next;
struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
next = tmp->next;
- if (d_unhashed(dentry)||!dentry->d_inode)
+ if (d_unhashed(dentry)||(!dentry->d_inode &&
+ !d_is_whiteout(dentry)))
continue;
if (!list_empty(&dentry->d_subdirs)) {
this_parent = dentry;
diff --git a/mm/shmem.c b/mm/shmem.c
index d713239..2faa14b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1794,6 +1794,76 @@ static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
return 0;
}
+static int shmem_rmdir(struct inode *dir, struct dentry *dentry);
+static int shmem_unlink(struct inode *dir, struct dentry *dentry);
+
+/*
+ * This is the whiteout support for tmpfs. It uses one singleton whiteout
+ * inode per superblock thus it is very similar to shmem_link().
+ */
+static int shmem_whiteout(struct inode *dir, struct dentry *old_dentry,
+ struct dentry *new_dentry)
+{
+ struct shmem_sb_info *sbinfo = SHMEM_SB(dir->i_sb);
+ struct dentry *dentry;
+
+ if (!(dir->i_sb->s_flags & MS_WHITEOUT))
+ return -EPERM;
+
+ /* This gives us a proper initialized negative dentry */
+ dentry = simple_lookup(dir, new_dentry, NULL);
+ if (dentry && IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ /*
+ * No ordinary (disk based) filesystem counts whiteouts as inodes;
+ * but each new link needs a new dentry, pinning lowmem, and
+ * tmpfs dentries cannot be pruned until they are unlinked.
+ */
+ if (sbinfo->max_inodes) {
+ spin_lock(&sbinfo->stat_lock);
+ if (!sbinfo->free_inodes) {
+ spin_unlock(&sbinfo->stat_lock);
+ return -ENOSPC;
+ }
+ sbinfo->free_inodes--;
+ spin_unlock(&sbinfo->stat_lock);
+ }
+
+ if (old_dentry->d_inode) {
+ if (S_ISDIR(old_dentry->d_inode->i_mode))
+ shmem_rmdir(dir, old_dentry);
+ else
+ shmem_unlink(dir, old_dentry);
+ }
+
+ dir->i_size += BOGO_DIRENT_SIZE;
+ dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ /* Extra pinning count for the created dentry */
+ dget(new_dentry);
+ spin_lock(&new_dentry->d_lock);
+ new_dentry->d_flags |= DCACHE_WHITEOUT;
+ spin_unlock(&new_dentry->d_lock);
+ return 0;
+}
+
+static void shmem_d_instantiate(struct inode *dir, struct dentry *dentry,
+ struct inode *inode)
+{
+ if (d_is_whiteout(dentry)) {
+ /* Re-using an existing whiteout */
+ shmem_free_inode(dir->i_sb);
+ if (S_ISDIR(inode->i_mode))
+ inode->i_mode |= S_OPAQUE;
+ } else {
+ /* New dentry */
+ dir->i_size += BOGO_DIRENT_SIZE;
+ dget(dentry); /* Extra count - pin the dentry in core */
+ }
+ /* Will clear DCACHE_WHITEOUT flag */
+ d_instantiate(dentry, inode);
+
+}
/*
* File creation. Allocate an inode, and we're done..
*/
@@ -1823,10 +1893,10 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
if (S_ISDIR(mode))
inode->i_mode |= S_ISGID;
}
- dir->i_size += BOGO_DIRENT_SIZE;
+
+ shmem_d_instantiate(dir, dentry, inode);
+
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- d_instantiate(dentry, inode);
- dget(dentry); /* Extra count - pin the dentry in core */
}
return error;
}
@@ -1864,12 +1934,11 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr
if (ret)
goto out;
- dir->i_size += BOGO_DIRENT_SIZE;
+ shmem_d_instantiate(dir, dentry, inode);
+
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
inc_nlink(inode);
atomic_inc(&inode->i_count); /* New dentry reference */
- dget(dentry); /* Extra pinning count for the created dentry */
- d_instantiate(dentry, inode);
out:
return ret;
}
@@ -1878,21 +1947,61 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode))
- shmem_free_inode(inode->i_sb);
+ if (d_is_whiteout(dentry) || (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)))
+ shmem_free_inode(dir->i_sb);
+ if (inode) {
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ drop_nlink(inode);
+ }
dir->i_size -= BOGO_DIRENT_SIZE;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- drop_nlink(inode);
dput(dentry); /* Undo the count from "create" - this does all the work */
return 0;
}
+static void shmem_dir_unlink_whiteouts(struct inode *dir, struct dentry *dentry)
+{
+ if (!dentry->d_inode)
+ return;
+
+ /* Remove whiteouts from logical empty directory */
+ if (S_ISDIR(dentry->d_inode->i_mode) &&
+ dentry->d_inode->i_sb->s_flags & MS_WHITEOUT) {
+ struct dentry *child, *next;
+ LIST_HEAD(list);
+
+ spin_lock(&dcache_lock);
+ list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) {
+ spin_lock(&child->d_lock);
+ if (d_is_whiteout(child)) {
+ __d_drop(child);
+ if (!list_empty(&child->d_lru)) {
+ list_del(&child->d_lru);
+ dentry_stat.nr_unused--;
+ }
+ list_add(&child->d_lru, &list);
+ }
+ spin_unlock(&child->d_lock);
+ }
+ spin_unlock(&dcache_lock);
+
+ list_for_each_entry_safe(child, next, &list, d_lru) {
+ spin_lock(&child->d_lock);
+ list_del_init(&child->d_lru);
+ spin_unlock(&child->d_lock);
+
+ shmem_unlink(dentry->d_inode, child);
+ }
+ }
+}
+
static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
{
if (!simple_empty(dentry))
return -ENOTEMPTY;
+ /* Remove whiteouts from logical empty directory */
+ shmem_dir_unlink_whiteouts(dir, dentry);
drop_nlink(dentry->d_inode);
drop_nlink(dir);
return shmem_unlink(dir, dentry);
@@ -1901,7 +2010,7 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
/*
* The VFS layer already does all the dentry stuff for rename,
* we just have to decrement the usage count for the target if
- * it exists so that the VFS layer correctly free's it when it
+ * it exists so that the VFS layer correctly frees it when it
* gets overwritten.
*/
static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
@@ -1912,7 +2021,12 @@ static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct
if (!simple_empty(new_dentry))
return -ENOTEMPTY;
+ if (d_is_whiteout(new_dentry))
+ shmem_unlink(new_dir, new_dentry);
+
if (new_dentry->d_inode) {
+ /* Remove whiteouts from logical empty directory */
+ shmem_dir_unlink_whiteouts(new_dir, new_dentry);
(void) shmem_unlink(new_dir, new_dentry);
if (they_are_dirs)
drop_nlink(old_dir);
@@ -1977,12 +2091,12 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
set_page_dirty(page);
page_cache_release(page);
}
+
+ shmem_d_instantiate(dir, dentry, inode);
+
if (dir->i_mode & S_ISGID)
inode->i_gid = dir->i_gid;
- dir->i_size += BOGO_DIRENT_SIZE;
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- d_instantiate(dentry, inode);
- dget(dentry);
return 0;
}
@@ -2363,6 +2477,12 @@ static int shmem_fill_super(struct super_block *sb,
if (!root)
goto failed_iput;
sb->s_root = root;
+
+#ifdef CONFIG_TMPFS
+ if (!(sb->s_flags & MS_NOUSER))
+ sb->s_flags |= MS_WHITEOUT;
+#endif
+
return 0;
failed_iput:
@@ -2462,6 +2582,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
.rmdir = shmem_rmdir,
.mknod = shmem_mknod,
.rename = shmem_rename,
+ .whiteout = shmem_whiteout,
#endif
#ifdef CONFIG_TMPFS_POSIX_ACL
.setattr = shmem_notify_change,
--
1.6.3.3
next prev parent reply other threads:[~2009-10-21 19:19 UTC|newest]
Thread overview: 100+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-21 19:18 [RFC PATCH 00/40] Writable overlays (union mounts) Valerie Aurora
2009-10-21 19:18 ` [PATCH 01/41] VFS: BUG() if somebody tries to rehash an already hashed dentry Valerie Aurora
2009-10-21 19:19 ` [PATCH 02/41] VFS: propagate mnt_flags into do_loopback Valerie Aurora
2009-10-21 19:19 ` [PATCH 03/41] VFS: Make lookup_hash() return a struct path Valerie Aurora
2009-10-21 19:19 ` [PATCH 04/41] VFS: Remove unnecessary micro-optimization in cached_lookup() Valerie Aurora
2009-10-21 19:19 ` [PATCH 05/41] VFS: Make real_lookup() return a struct path Valerie Aurora
2009-10-21 19:19 ` [PATCH 06/41] VFS: Introduce dput() variant that maintains a kill-list Valerie Aurora
2009-10-21 19:19 ` [PATCH 07/41] VFS: Add read-only users count to superblock Valerie Aurora
2009-10-21 19:19 ` [PATCH 08/41] Don't replace nameidata path when following links Valerie Aurora
2009-10-21 19:19 ` [PATCH 09/41] whiteout: Don't return information about whiteouts to userspace Valerie Aurora
2009-10-21 19:19 ` [PATCH 10/41] whiteout: Add vfs_whiteout() and whiteout inode operation Valerie Aurora
2009-10-21 19:19 ` [PATCH 11/41] whiteout: Set S_OPAQUE inode flag when creating directories Valerie Aurora
2009-10-21 19:19 ` [PATCH 12/41] union-mount: Allow removal of a directory Valerie Aurora
2009-10-21 19:19 ` Valerie Aurora [this message]
2009-10-21 19:19 ` [PATCH 14/41] whiteout: Split of ext2_append_link() from ext2_add_link() Valerie Aurora
2009-10-21 19:19 ` [PATCH 15/41] whiteout: ext2 whiteout support Valerie Aurora
2009-10-21 19:19 ` [PATCH 16/41] whiteout: jffs2 " Valerie Aurora
2009-10-21 19:19 ` [PATCH 17/41] whiteout: Add path_whiteout() helper Valerie Aurora
2009-10-21 19:19 ` [PATCH 18/41] union-mount: Documentation Valerie Aurora
2009-10-21 19:19 ` [PATCH 19/41] union-mount: Introduce MNT_UNION and MS_UNION flags Valerie Aurora
2009-10-21 19:19 ` [PATCH 20/41] union-mount: Introduce union_mount structure Valerie Aurora
2009-10-21 19:19 ` [PATCH 21/41] union-mount: Drive the union cache via dcache Valerie Aurora
2009-10-21 19:19 ` [PATCH 22/41] union-mount: Some checks during namespace changes Valerie Aurora
2009-10-21 19:19 ` [PATCH 23/41] union-mount: Changes to the namespace handling Valerie Aurora
2009-10-21 19:19 ` [PATCH 24/41] union-mount: Make lookup work for union-mounted file systems Valerie Aurora
2009-10-21 19:19 ` [PATCH 25/41] union-mount: stop lookup when directory has S_OPAQUE flag set Valerie Aurora
2009-10-21 19:19 ` [PATCH 26/41] union-mount: stop lookup when finding a whiteout Valerie Aurora
2009-10-21 19:19 ` [PATCH 27/41] union-mount: in-kernel file copy between union mounted filesystems Valerie Aurora
2009-10-21 19:19 ` [PATCH 28/41] union-mount: call do_whiteout() on unlink and rmdir Valerie Aurora
2009-10-21 19:19 ` [PATCH 29/41] union-mount: Always create topmost directory on open Valerie Aurora
2009-10-21 19:19 ` [PATCH 30/41] fallthru: Basic fallthru definitions Valerie Aurora
2009-10-21 19:19 ` [PATCH 31/41] fallthru: Support for fallthru entries in union mount lookup Valerie Aurora
2009-10-21 19:19 ` [PATCH 32/41] fallthru: ext2 fallthru support Valerie Aurora
2009-10-21 19:19 ` [PATCH 33/41] fallthru: jffs2 " Valerie Aurora
2009-10-21 19:19 ` [PATCH 34/41] fallthru: tmpfs " Valerie Aurora
2009-10-21 19:19 ` [PATCH 35/41] union-mount: Copy up directory entries on first readdir() Valerie Aurora
2009-10-21 19:19 ` [PATCH 36/41] union-mount: Increment read-only users count for read-only layer Valerie Aurora
2009-10-21 19:19 ` [PATCH 37/41] union-mount: Check read-only/read-write status of layers Valerie Aurora
2009-10-21 19:19 ` [PATCH 38/41] union-mount: Make pivot_root work with union mounts Valerie Aurora
2009-10-21 19:19 ` [PATCH 39/41] union-mount: Ignore read-only file system in permission checks Valerie Aurora
2009-10-21 19:19 ` [PATCH 40/41] union-mount: Make truncate work in all its glorious UNIX variations Valerie Aurora
2009-10-21 19:19 ` [PATCH 41/41] union-mount: Add support for rename by __union_copyup() Valerie Aurora
2009-12-01 4:57 ` Erez Zadok
2009-12-01 4:50 ` [PATCH 40/41] union-mount: Make truncate work in all its glorious UNIX variations Erez Zadok
2009-12-01 4:34 ` [PATCH 39/41] union-mount: Ignore read-only file system in permission checks Erez Zadok
2009-12-01 4:26 ` [PATCH 38/41] union-mount: Make pivot_root work with union mounts Erez Zadok
2009-12-01 4:18 ` [PATCH 35/41] union-mount: Copy up directory entries on first readdir() Erez Zadok
2009-12-01 4:17 ` [PATCH 34/41] fallthru: tmpfs fallthru support Erez Zadok
2009-12-01 4:17 ` [PATCH 33/41] fallthru: jffs2 " Erez Zadok
2009-12-01 4:17 ` [PATCH 32/41] fallthru: ext2 " Erez Zadok
2009-12-01 4:15 ` [PATCH 31/41] fallthru: Support for fallthru entries in union mount lookup Erez Zadok
2009-12-01 4:14 ` [PATCH 30/41] fallthru: Basic fallthru definitions Erez Zadok
2009-12-01 4:14 ` [PATCH 29/41] union-mount: Always create topmost directory on open Erez Zadok
2009-12-01 4:13 ` [PATCH 27/41] union-mount: in-kernel file copy between union mounted filesystems Erez Zadok
2009-12-01 4:11 ` [PATCH 26/41] union-mount: stop lookup when finding a whiteout Erez Zadok
2009-12-01 4:10 ` [PATCH 25/41] union-mount: stop lookup when directory has S_OPAQUE flag set Erez Zadok
2009-12-01 4:10 ` [PATCH 24/41] union-mount: Make lookup work for union-mounted file systems Erez Zadok
2009-11-30 9:15 ` [PATCH 23/41] union-mount: Changes to the namespace handling Erez Zadok
2009-11-30 9:04 ` [PATCH 22/41] union-mount: Some checks during namespace changes Erez Zadok
2009-11-30 8:57 ` [PATCH 21/41] union-mount: Drive the union cache via dcache Erez Zadok
2009-11-30 8:46 ` [PATCH 20/41] union-mount: Introduce union_mount structure Erez Zadok
2010-01-26 22:38 ` Valerie Aurora
2009-11-30 8:02 ` [PATCH 19/41] union-mount: Introduce MNT_UNION and MS_UNION flags Erez Zadok
2010-01-26 20:03 ` Valerie Aurora
2009-12-01 5:37 ` [PATCH 18/41] union-mount: Documentation Erez Zadok
2009-11-30 7:57 ` [PATCH 17/41] whiteout: Add path_whiteout() helper Erez Zadok
2010-01-26 20:02 ` Valerie Aurora
2009-10-21 22:50 ` [PATCH 16/41] whiteout: jffs2 whiteout support David Woodhouse
2009-10-27 2:21 ` Valerie Aurora
2009-11-30 7:51 ` Erez Zadok
2010-01-26 19:52 ` Valerie Aurora
2009-10-21 21:17 ` [PATCH 15/41] whiteout: ext2 " Andreas Dilger
2009-10-27 2:14 ` Valerie Aurora
2009-11-30 7:45 ` Erez Zadok
2009-11-30 6:32 ` [PATCH 14/41] whiteout: Split of ext2_append_link() from ext2_add_link() Erez Zadok
2009-11-30 6:26 ` [PATCH 13/41] whiteout: tmpfs whiteout support Erez Zadok
2010-01-21 2:02 ` Valerie Aurora
2009-11-30 6:13 ` [PATCH 12/41] union-mount: Allow removal of a directory Erez Zadok
2010-01-21 0:52 ` Valerie Aurora
2009-10-27 14:36 ` [PATCH 10/41] whiteout: Add vfs_whiteout() and whiteout inode operation Eric Paris
2009-10-27 21:22 ` Valerie Aurora
2009-11-30 3:04 ` Erez Zadok
2010-01-21 0:35 ` Valerie Aurora
2009-11-30 2:53 ` [PATCH 09/41] whiteout: Don't return information about whiteouts to userspace Erez Zadok
2010-01-21 0:19 ` Valerie Aurora
2009-11-30 2:44 ` [PATCH 08/41] Don't replace nameidata path when following links Erez Zadok
2009-11-30 2:33 ` [PATCH 07/41] VFS: Add read-only users count to superblock Erez Zadok
2009-11-30 2:28 ` [PATCH 06/41] VFS: Introduce dput() variant that maintains a kill-list Erez Zadok
2010-01-20 23:31 ` Valerie Aurora
2009-11-30 2:11 ` [PATCH 05/41] VFS: Make real_lookup() return a struct path Erez Zadok
2009-11-30 2:07 ` [PATCH 04/41] VFS: Remove unnecessary micro-optimization in cached_lookup() Erez Zadok
2009-12-10 21:25 ` Valerie Aurora
2009-11-30 2:02 ` [PATCH 03/41] VFS: Make lookup_hash() return a struct path Erez Zadok
2009-12-10 21:23 ` Valerie Aurora
2009-11-30 6:04 ` Erez Zadok
2009-12-10 21:24 ` Valerie Aurora
2009-11-30 1:43 ` [PATCH 01/41] VFS: BUG() if somebody tries to rehash an already hashed dentry Erez Zadok
2009-12-10 20:20 ` Valerie Aurora
2009-10-22 2:44 ` [RFC PATCH 00/40] Writable overlays (union mounts) hooanon05
2009-10-27 2:23 ` Valerie Aurora
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=1256152779-10054-14-git-send-email-vaurora@redhat.com \
--to=vaurora@redhat.com \
--cc=apw@canonical.com \
--cc=dwmw2@infradead.org \
--cc=hch@infradead.org \
--cc=jblunck@suse.de \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=scott@canonica \
--cc=viro@zeniv.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;
as well as URLs for NNTP newsgroup(s).