linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jan Blunck <jblunck@suse.de>
To: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org
Cc: viro@zeniv.linux.org.uk, bharata@in.ibm.com, dwmw2@infradead.org,
	mszeredi@suse.cz, vaurora@redhat.com
Subject: [PATCH 30/32] union mount: ext2 fallthru support
Date: Mon, 18 May 2009 18:09:26 +0200	[thread overview]
Message-ID: <1242662968-11684-31-git-send-email-jblunck@suse.de> (raw)
In-Reply-To: <1242662968-11684-1-git-send-email-jblunck@suse.de>

From: Valerie Aurora (Henson) <vaurora@redhat.com>

Add support for fallthru directory entries to ext2.

Signed-off-by: Valerie Aurora (Henson) <vaurora@redhat.com>
Signed-off-by: Jan Blunck <jblunck@suse.de>
---
 fs/ext2/dir.c           |   86 ++++++++++++++++++++++++++++++++++++++++++++--
 fs/ext2/ext2.h          |    1 +
 fs/ext2/namei.c         |   20 +++++++++++
 include/linux/ext2_fs.h |    1 +
 4 files changed, 104 insertions(+), 4 deletions(-)

diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 5b499ad..b9380fe 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -219,7 +219,8 @@ static inline int ext2_match (int len, const char * const name,
 {
 	if (len != de->name_len)
 		return 0;
-	if (!de->inode && (de->file_type != EXT2_FT_WHT))
+	if (!de->inode && ((de->file_type != EXT2_FT_WHT) &&
+			   (de->file_type != EXT2_FT_FALLTHRU)))
 		return 0;
 	return !memcmp(name, de->name, len);
 }
@@ -256,6 +257,7 @@ static unsigned char ext2_filetype_table[EXT2_FT_MAX] = {
 	[EXT2_FT_SOCK]		= DT_SOCK,
 	[EXT2_FT_SYMLINK]	= DT_LNK,
 	[EXT2_FT_WHT]		= DT_WHT,
+	[EXT2_FT_FALLTHRU]	= DT_UNKNOWN,
 };
 
 #define S_SHIFT 12
@@ -342,6 +344,18 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
 					ext2_put_page(page);
 					return 0;
 				}
+			} else if (de->file_type == EXT2_FT_FALLTHRU) {
+				int over;
+				unsigned char d_type = DT_UNKNOWN;
+
+				offset = (char *)de - kaddr;
+				over = filldir(dirent, de->name, de->name_len,
+						(n<<PAGE_CACHE_SHIFT) | offset,
+						123, d_type);
+				if (over) {
+					ext2_put_page(page);
+					return 0;
+				}
 			}
 			filp->f_pos += ext2_rec_len_from_disk(de->rec_len);
 		}
@@ -463,6 +477,10 @@ ino_t ext2_inode_by_dentry(struct inode *dir, struct dentry *dentry)
 			spin_lock(&dentry->d_lock);
 			dentry->d_flags |= DCACHE_WHITEOUT;
 			spin_unlock(&dentry->d_lock);
+		} else if(!res && de->file_type == EXT2_FT_FALLTHRU) {
+			spin_lock(&dentry->d_lock);
+			dentry->d_flags |= DCACHE_FALLTHRU;
+			spin_unlock(&dentry->d_lock);
 		}
 		ext2_put_page(page);
 	}
@@ -531,6 +549,7 @@ static ext2_dirent * ext2_append_entry(struct dentry * dentry,
 				de->name_len = 0;
 				de->rec_len = ext2_rec_len_to_disk(chunk_size);
 				de->inode = 0;
+				de->file_type = 0;
 				goto got_it;
 			}
 			if (de->rec_len == 0) {
@@ -544,6 +563,7 @@ static ext2_dirent * ext2_append_entry(struct dentry * dentry,
 			name_len = EXT2_DIR_REC_LEN(de->name_len);
 			rec_len = ext2_rec_len_from_disk(de->rec_len);
 			if (!de->inode && (de->file_type != EXT2_FT_WHT) &&
+			    (de->file_type != EXT2_FT_FALLTHRU) &&
 			    (rec_len >= reclen))
 				goto got_it;
 			if (rec_len >= name_len + reclen)
@@ -586,7 +606,8 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
 
 	err = -EEXIST;
 	if (ext2_match (namelen, name, de)) {
-		if (de->file_type == EXT2_FT_WHT)
+		if ((de->file_type == EXT2_FT_WHT) ||
+		    (de->file_type == EXT2_FT_FALLTHRU))
 			goto got_it;
 		goto out_unlock;
 	}
@@ -601,7 +622,8 @@ got_it:
 							&page, NULL);
 	if (err)
 		goto out_unlock;
-	if (de->inode || ((de->file_type == EXT2_FT_WHT) &&
+	if (de->inode || (((de->file_type == EXT2_FT_WHT) ||
+			   (de->file_type == EXT2_FT_FALLTHRU)) &&
 			  !ext2_match (namelen, name, de))) {
 		ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len);
 		de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len);
@@ -626,6 +648,60 @@ out_unlock:
 }
 
 /*
+ * Create a fallthru entry.
+ */
+int ext2_fallthru_entry (struct inode *dir, struct dentry *dentry)
+{
+	const char *name = dentry->d_name.name;
+	int namelen = dentry->d_name.len;
+	unsigned short rec_len, name_len;
+	ext2_dirent * de;
+	struct page *page;
+	loff_t pos;
+	int err;
+
+	de = ext2_append_entry(dentry, &page);
+	if (IS_ERR(de))
+		return PTR_ERR(de);
+
+	err = -EEXIST;
+	if (ext2_match (namelen, name, de))
+		goto out_unlock;
+
+	name_len = EXT2_DIR_REC_LEN(de->name_len);
+	rec_len = ext2_rec_len_from_disk(de->rec_len);
+
+	pos = page_offset(page) +
+		(char*)de - (char*)page_address(page);
+	err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0,
+							&page, NULL);
+	if (err)
+		goto out_unlock;
+	if (de->inode || (de->file_type == EXT2_FT_WHT) ||
+	    (de->file_type == EXT2_FT_FALLTHRU)) {
+		ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len);
+		de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len);
+		de->rec_len = ext2_rec_len_to_disk(name_len);
+		de = de1;
+	}
+	de->name_len = namelen;
+	memcpy(de->name, name, namelen);
+	de->inode = 0;
+	de->file_type = EXT2_FT_FALLTHRU;
+	err = ext2_commit_chunk(page, pos, rec_len);
+	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+	EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
+	mark_inode_dirty(dir);
+	/* OFFSET_CACHE */
+out_put:
+	ext2_put_page(page);
+	return err;
+out_unlock:
+	unlock_page(page);
+	goto out_put;
+}
+
+/*
  * ext2_delete_entry deletes a directory entry by merging it with the
  * previous entry. Page is up-to-date. Releases the page.
  */
@@ -710,7 +786,9 @@ int ext2_whiteout_entry (struct inode * dir, struct dentry * dentry,
 	 */
 	if (ext2_match (namelen, name, de))
 		de->inode = 0;
-	if (de->inode || (de->file_type == EXT2_FT_WHT)) {
+	if (de->inode || (((de->file_type == EXT2_FT_WHT) ||
+			   (de->file_type == EXT2_FT_FALLTHRU)) &&
+			  !ext2_match (namelen, name, de))) {
 		ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len);
 		de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len);
 		de->rec_len = ext2_rec_len_to_disk(name_len);
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index ec9a0bd..363b0fa 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -112,6 +112,7 @@ extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,struct qstr *,
 extern int ext2_delete_entry (struct ext2_dir_entry_2 *, struct page *);
 extern int ext2_whiteout_entry (struct inode *, struct dentry *,
 				struct ext2_dir_entry_2 *, struct page *);
+extern int ext2_fallthru_entry (struct inode *, struct dentry *);
 extern int ext2_empty_dir (struct inode *);
 extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **);
 extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *);
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 58107ff..5bdf990 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -325,6 +325,7 @@ static int ext2_whiteout(struct inode *dir, struct dentry *dentry,
 		goto out;
 
 	spin_lock(&new_dentry->d_lock);
+	new_dentry->d_flags &= ~DCACHE_FALLTHRU;
 	new_dentry->d_flags |= DCACHE_WHITEOUT;
 	spin_unlock(&new_dentry->d_lock);
 	d_add(new_dentry, NULL);
@@ -343,6 +344,24 @@ out:
 	return err;
 }
 
+/*
+ * Create a fallthru entry.
+ */
+static int ext2_fallthru (struct inode *dir, struct dentry *dentry)
+{
+	int err;
+
+	err = ext2_fallthru_entry(dir, dentry);
+	if (err)
+		return err;
+
+	d_instantiate(dentry, NULL);
+	spin_lock(&dentry->d_lock);
+	dentry->d_flags |= DCACHE_FALLTHRU;
+	spin_unlock(&dentry->d_lock);
+	return 0;
+}
+
 static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
 	struct inode * new_dir,	struct dentry * new_dentry )
 {
@@ -438,6 +457,7 @@ const struct inode_operations ext2_dir_inode_operations = {
 	.rmdir		= ext2_rmdir,
 	.mknod		= ext2_mknod,
 	.whiteout	= ext2_whiteout,
+	.fallthru	= ext2_fallthru,
 	.rename		= ext2_rename,
 #ifdef CONFIG_EXT2_FS_XATTR
 	.setxattr	= generic_setxattr,
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index bd10826..f6b68ec 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -577,6 +577,7 @@ enum {
 	EXT2_FT_SOCK,
 	EXT2_FT_SYMLINK,
 	EXT2_FT_WHT,
+	EXT2_FT_FALLTHRU,
 	EXT2_FT_MAX
 };
 
-- 
1.6.1.3


  parent reply	other threads:[~2009-05-18 16:09 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-18 16:08 [PATCH 00/32] VFS based Union Mount (V3) Jan Blunck
2009-05-18 16:08 ` [PATCH 01/32] atomic: Only take lock when the counter drops to zero on UP as well Jan Blunck
2009-05-18 16:08 ` [PATCH 02/32] VFS: BUG() if somebody tries to rehash an already hashed dentry Jan Blunck
2009-05-18 16:08 ` [PATCH 03/32] VFS: propagate mnt_flags into do_loopback Jan Blunck
2009-05-18 16:09 ` [PATCH 04/32] VFS: Make lookup_hash() return a struct path Jan Blunck
2009-05-18 16:09 ` [PATCH 05/32] VFS: Remove unnecessary micro-optimization in cached_lookup() Jan Blunck
2009-05-18 16:09 ` [PATCH 06/32] VFS: Make real_lookup() return a struct path Jan Blunck
2009-05-18 16:09 ` [PATCH 07/32] VFS: Introduce dput() variant that maintains a kill-list Jan Blunck
2009-05-18 16:09 ` [PATCH 08/32] whiteout: Don't return information about whiteouts to userspace Jan Blunck
2009-05-18 16:09 ` [PATCH 09/32] whiteout: Add vfs_whiteout() and whiteout inode operation Jan Blunck
2009-05-18 16:09 ` [PATCH 10/32] whiteout: Set S_OPAQUE inode flag when creating directories Jan Blunck
2009-05-18 16:09 ` [PATCH 11/32] whiteout: Add whiteout support to tmpfs Jan Blunck
2009-05-18 16:09 ` [PATCH 12/32] whiteout: Split of ext2_append_link() from ext2_add_link() Jan Blunck
2009-05-18 16:09 ` [PATCH 13/32] whiteout: Add whiteout support to ext2 Jan Blunck
2009-05-18 16:09 ` [PATCH 14/32] whiteout: Add path_whiteout() helper Jan Blunck
2009-05-18 16:09 ` [PATCH 15/32] union-mount: Documentation Jan Blunck
2009-05-25  6:25   ` hooanon05
2009-05-25  8:03     ` Arnd Bergmann
2009-05-25  8:43       ` hooanon05
2009-06-18 19:05         ` Valerie Aurora
2009-06-19  1:53           ` hooanon05
2009-05-18 16:09 ` [PATCH 16/32] union-mount: Introduce MNT_UNION and MS_UNION flags Jan Blunck
2009-05-18 16:09 ` [PATCH 17/32] union-mount: Introduce union_mount structure Jan Blunck
2009-05-18 16:09 ` [PATCH 18/32] union-mount: Drive the union cache via dcache Jan Blunck
2009-05-18 16:09 ` [PATCH 19/32] union-mount: Some checks during namespace changes Jan Blunck
2009-05-18 16:09 ` [PATCH 20/32] union-mount: Changes to the namespace handling Jan Blunck
2009-05-18 16:09 ` [PATCH 21/32] union-mount: Make lookup work for union-mounted file systems Jan Blunck
2009-05-19 16:15   ` Miklos Szeredi
2009-05-19 17:30     ` Valerie Aurora
2009-05-20 10:21       ` Miklos Szeredi
2009-05-18 16:09 ` [PATCH 22/32] union-mount: stop lookup when directory has S_OPAQUE flag set Jan Blunck
2009-05-18 16:09 ` [PATCH 23/32] union-mount: stop lookup when finding a whiteout Jan Blunck
2009-05-18 16:09 ` [PATCH 24/32] union-mount: in-kernel file copy between union mounted filesystems Jan Blunck
2009-05-18 16:09 ` [PATCH 25/32] union-mount: check for logically empty directory (FIXME) Jan Blunck
2009-05-18 16:09 ` [PATCH 26/32] union-mount: call do_whiteout() on unlink and rmdir Jan Blunck
2009-05-18 16:09 ` [PATCH 27/32] union-mount: Always create topmost directory on open Jan Blunck
2009-05-18 16:09 ` [PATCH 28/32] union-mount: Basic fallthru definitions Jan Blunck
2009-05-18 16:09 ` [PATCH 29/32] union mount: Support for fallthru entries in union mount lookup Jan Blunck
2009-05-18 16:09 ` Jan Blunck [this message]
2009-05-18 16:32   ` [PATCH 30/32] union mount: ext2 fallthru support Andreas Dilger
2009-05-19  9:42     ` Jan Blunck
2009-05-19 14:05       ` Andreas Dilger
2009-05-19 16:13         ` Jan Blunck
2009-05-18 16:09 ` [PATCH 31/32] union-mount: tmpfs " Jan Blunck
2009-05-18 16:09 ` [PATCH 32/32] union-mount: Copy up directory entries on first readdir() Jan Blunck
2009-05-18 20:40 ` [PATCH] Userland for VFS based Union Mount (V3) Valerie Aurora
2009-05-21 13:53   ` Andreas Dilger
2009-06-18  3:22     ` Valerie Aurora
2009-05-19  9:48 ` [PATCH 00/32] " Miklos Szeredi
2009-05-19 10:29   ` Jan Blunck
2009-05-19 10:35     ` Miklos Szeredi
2009-05-19 10:39       ` Jan Blunck
2009-05-19 11:54         ` Arnd Bergmann
2009-05-19 12:15           ` Jan Blunck
2009-05-19 12:21             ` Arnd Bergmann
2009-05-19 13:10               ` Jan Blunck
2009-05-19 17:23   ` Valerie Aurora
2009-05-20  9:05     ` Miklos Szeredi
2009-06-08 19:44       ` Valerie Aurora
2009-06-16 15:19         ` Miklos Szeredi
2009-05-21 12:54 ` Jan Rekorajski
2009-06-08 19:57   ` Valerie Aurora
2009-06-08 22:44     ` Jan Rekorajski
2009-06-08 22:48       ` Valerie Aurora
2009-06-15  9:55         ` Jan Rekorajski
2009-06-18  3:23           ` Valerie Aurora
2009-06-04 11:38 ` Scott James Remnant
2009-06-09 22:15   ` 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=1242662968-11684-31-git-send-email-jblunck@suse.de \
    --to=jblunck@suse.de \
    --cc=bharata@in.ibm.com \
    --cc=dwmw2@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mszeredi@suse.cz \
    --cc=vaurora@redhat.com \
    --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).