From: "Josef 'Jeff' Sipek" <jsipek@cs.sunysb.edu>
To: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org
Cc: akpm@linux-foundation.org, Erez Zadok <ezk@cs.sunysb.edu>,
"Josef 'Jeff' Sipek" <jsipek@cs.sunysb.edu>
Subject: [PATCH 08/21] Unionfs: Introduce branch-id code
Date: Mon, 9 Apr 2007 10:53:59 -0400 [thread overview]
Message-ID: <11761304543898-git-send-email-jsipek@cs.sunysb.edu> (raw)
In-Reply-To: <11761304521844-git-send-email-jsipek@cs.sunysb.edu>
From: Erez Zadok <ezk@cs.sunysb.edu>
Each branch gets a unique ID, which helps during branch additions,
deletions, and changes, to locate where branches were moved to, and perform
proper reference-counting. This is useful even if the same directory was
added more than once to union.
Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
Signed-off-by: Josef 'Jeff' Sipek <jsipek@cs.sunysb.edu>
---
fs/unionfs/commonfops.c | 62 +++++++++++++++++++++++++++++++++++++++++++++-
fs/unionfs/fanout.h | 22 ++++++++++++++++-
fs/unionfs/main.c | 1 +
fs/unionfs/union.h | 4 ++-
4 files changed, 85 insertions(+), 4 deletions(-)
diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index aa7c75d..8d0f8d1 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -86,6 +86,31 @@ out:
return err;
}
+/*
+ * Find new index of matching branch with an open file, since branches could
+ * have been added/deleted causing the one with open files to shift.
+ *
+ * @file: current file whose branches may have changed
+ * @bindex: index of branch within current file (could be old branch)
+ * @new_sb: the new superblock which may have new branch IDs
+ * Returns index of newly found branch (0 or greater), -1 otherwise.
+ */
+static int find_new_branch_index(struct file *file, int bindex,
+ struct super_block *new_sb)
+{
+ int old_branch_id = UNIONFS_F(file)->saved_branch_ids[bindex];
+ int i;
+
+ for (i = 0; i < sbmax(new_sb); i++)
+ if (old_branch_id == branch_id(new_sb, i))
+ return i;
+ /*
+ * XXX: maybe we should BUG_ON if not found new branch index?
+ * (really that should never happen).
+ */
+ return -1;
+}
+
/* put all references held by upper struct file and free lower file pointer
* array
*/
@@ -93,6 +118,7 @@ static void cleanup_file(struct file *file)
{
int bindex, bstart, bend;
struct file **lf;
+ struct super_block *sb = file->f_dentry->d_sb;
lf = UNIONFS_F(file)->lower_files;
bstart = fbstart(file);
@@ -100,13 +126,29 @@ static void cleanup_file(struct file *file)
for (bindex = bstart; bindex <= bend; bindex++) {
if (unionfs_lower_file_idx(file, bindex)) {
- branchput(file->f_dentry->d_sb, bindex);
+ int i; /* holds (possibly) updated branch index */
+ i = find_new_branch_index(file, bindex, sb);
+ if (i < 0)
+ printk(KERN_ERR "unionfs: no supberlock for file %p\n",
+ file);
+ else {
+ unionfs_read_lock(sb);
+ branchput(sb, i);
+ unionfs_read_unlock(sb);
+ /* XXX: is it correct to use sb->s_root here? */
+ unionfs_mntput(sb->s_root, i);
+ /* XXX: mntget b/c fput below will call mntput */
+ unionfs_mntget(sb->s_root, bindex);
+ }
fput(unionfs_lower_file_idx(file, bindex));
}
}
UNIONFS_F(file)->lower_files = NULL;
kfree(lf);
+ kfree(UNIONFS_F(file)->saved_branch_ids);
+ /* set to NULL because caller needs to know if to kfree on error */
+ UNIONFS_F(file)->saved_branch_ids = NULL;
}
/* open all lower files for a given file */
@@ -270,6 +312,12 @@ int unionfs_file_revalidate(struct file *file, int willwrite)
err = -ENOMEM;
goto out;
}
+ size = sizeof(int) * sbmax(sb);
+ UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
+ if (!UNIONFS_F(file)->saved_branch_ids) {
+ err = -ENOMEM;
+ goto out;
+ }
if (S_ISDIR(dentry->d_inode->i_mode)) {
/* We need to open all the files. */
@@ -297,8 +345,10 @@ int unionfs_file_revalidate(struct file *file, int willwrite)
}
out:
- if (err)
+ if (err) {
kfree(UNIONFS_F(file)->lower_files);
+ kfree(UNIONFS_F(file)->saved_branch_ids);
+ }
out_nofree:
unionfs_unlock_dentry(dentry);
unionfs_read_unlock(dentry->d_sb);
@@ -418,6 +468,12 @@ int unionfs_open(struct inode *inode, struct file *file)
err = -ENOMEM;
goto out;
}
+ size = sizeof(int) * sbmax(inode->i_sb);
+ UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
+ if (!UNIONFS_F(file)->saved_branch_ids) {
+ err = -ENOMEM;
+ goto out;
+ }
dentry = file->f_dentry;
unionfs_lock_dentry(dentry);
@@ -456,6 +512,7 @@ int unionfs_open(struct inode *inode, struct file *file)
out:
if (err) {
kfree(UNIONFS_F(file)->lower_files);
+ kfree(UNIONFS_F(file)->saved_branch_ids);
kfree(UNIONFS_F(file));
}
out_nofree:
@@ -487,6 +544,7 @@ int unionfs_file_release(struct inode *inode, struct file *file)
}
}
kfree(fileinfo->lower_files);
+ kfree(fileinfo->saved_branch_ids);
if (fileinfo->rdstate) {
fileinfo->rdstate->access = jiffies;
diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
index e8c0fee..9e4a35f 100644
--- a/fs/unionfs/fanout.h
+++ b/fs/unionfs/fanout.h
@@ -32,12 +32,29 @@ static inline struct unionfs_inode_info *UNIONFS_I(const struct inode *inode)
#define sbstart(sb) 0
#define sbend(sb) (UNIONFS_SB(sb)->bend)
#define sbmax(sb) (UNIONFS_SB(sb)->bend + 1)
+#define sbhbid(sb) (UNIONFS_SB(sb)->high_branch_id)
/* File to private Data */
#define UNIONFS_F(file) ((struct unionfs_file_info *)((file)->private_data))
#define fbstart(file) (UNIONFS_F(file)->bstart)
#define fbend(file) (UNIONFS_F(file)->bend)
+/* macros to manipulate branch IDs in stored in our superblock */
+static inline int branch_id(struct super_block *sb, int index)
+{
+ return UNIONFS_SB(sb)->data[index].branch_id;
+}
+
+static inline void set_branch_id(struct super_block *sb, int index, int val)
+{
+ UNIONFS_SB(sb)->data[index].branch_id = val;
+}
+
+static inline void new_branch_id(struct super_block *sb, int index)
+{
+ set_branch_id(sb, index, ++UNIONFS_SB(sb)->high_branch_id);
+}
+
/* File to lower file. */
static inline struct file *unionfs_lower_file(const struct file *f)
{
@@ -52,11 +69,14 @@ static inline struct file *unionfs_lower_file_idx(const struct file *f, int inde
static inline void unionfs_set_lower_file_idx(struct file *f, int index, struct file *val)
{
UNIONFS_F(f)->lower_files[index] = val;
+ /* save branch ID (may be redundant?) */
+ UNIONFS_F(f)->saved_branch_ids[index] =
+ branch_id((f)->f_dentry->d_sb, index);
}
static inline void unionfs_set_lower_file(struct file *f, struct file *val)
{
- UNIONFS_F(f)->lower_files[fbstart(f)] = val;
+ unionfs_set_lower_file_idx((f), fbstart(f), (val));
}
/* Inode to lower inode. */
diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index a37916d..ed264c7 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -515,6 +515,7 @@ static int unionfs_read_super(struct super_block *sb, void *raw_data,
UNIONFS_SB(sb)->bend = -1;
atomic_set(&UNIONFS_SB(sb)->generation, 1);
init_rwsem(&UNIONFS_SB(sb)->rwsem);
+ UNIONFS_SB(sb)->high_branch_id = -1; /* -1 == invalid branch ID */
hidden_root_info = unionfs_parse_options(sb, raw_data);
if (IS_ERR(hidden_root_info)) {
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index df9b8c0..7bd6306 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -80,6 +80,7 @@ struct unionfs_file_info {
struct unionfs_dir_state *rdstate;
struct file **lower_files;
+ int *saved_branch_ids; /* IDs of branches when file was opened */
};
/* unionfs inode data in memory */
@@ -123,6 +124,7 @@ struct unionfs_data {
struct super_block *sb;
atomic_t open_files; /* number of open files on branch */
int branchperms;
+ int branch_id; /* unique branch ID at re/mount time */
};
/* unionfs super-block data in memory */
@@ -131,7 +133,7 @@ struct unionfs_sb_info {
atomic_t generation;
struct rw_semaphore rwsem; /* protects access to data+id fields */
-
+ int high_branch_id; /* last unique branch ID given */
struct unionfs_data *data;
};
--
1.5.0.3.268.g3dda
next prev parent reply other threads:[~2007-04-09 15:00 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-09 14:53 [GIT PULL -mm] Unionfs branch management code Josef 'Jeff' Sipek
2007-04-09 14:53 ` [PATCH 01/21] fs: Introduce path{get,put} Josef 'Jeff' Sipek
2007-04-09 14:53 ` [PATCH 02/21] fs: Export drop_pagecache_sb symbol Josef 'Jeff' Sipek
2007-04-09 14:53 ` [PATCH 03/21] Unionfs: Documentation updates for branch-management Josef 'Jeff' Sipek
2007-04-09 14:53 ` [PATCH 04/21] Unionfs: Proper comment on rwsem field Josef 'Jeff' Sipek
2007-04-09 14:53 ` [PATCH 05/21] Unionfs: Rename unionfs_data sbcount field to more appropriate open_files Josef 'Jeff' Sipek
2007-04-09 14:53 ` [PATCH 06/21] Unionfs: Provide more helpful info on branch leaks during unmount Josef 'Jeff' Sipek
2007-04-09 14:53 ` [PATCH 07/21] Unionfs: Actually verify if dentry's info node is locked Josef 'Jeff' Sipek
2007-04-09 14:53 ` Josef 'Jeff' Sipek [this message]
2007-04-09 14:54 ` [PATCH 09/21] Unionfs: Bulk of branch-management remount code Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 10/21] Unionfs: Introduce unionfs_mnt{get,put} Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 11/21] Unionfs: Rewrite unionfs_d_revalidate Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 12/21] Unionfs: Grab the unionfs sb private data lock around branch info users Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 13/21] Unionfs: Remove the older incgen ioctl Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 14/21] Unionfs: Document unionfs_d_release locking Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 15/21] Unionfs: Decrement totalopens counter on error in unionfs_open Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 16/21] Unionfs: unionfs_create needs to revalidate the dentry Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 17/21] Unionfs: vfsmount reference counting fixes Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 18/21] Unionfs: Pass lowernd to lower ->revalidate function Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 19/21] Unionfs: Properly handle stale inodes passed to unionfs_permission Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 20/21] Unionfs: Added several BUG_ONs to assert dentry validity Josef 'Jeff' Sipek
2007-04-09 14:54 ` [PATCH 21/21] Unionfs: Don't inline do_remount_{add,del,mode}_option Josef 'Jeff' Sipek
2007-04-09 17:49 ` [GIT PULL -mm] Unionfs branch management code Andrew Morton
2007-04-09 22:47 ` Josef Sipek
2007-04-10 17:22 ` Shaya Potter
2007-04-10 17:35 ` Josef Sipek
2007-04-09 19:52 ` Jan Engelhardt
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=11761304543898-git-send-email-jsipek@cs.sunysb.edu \
--to=jsipek@cs.sunysb.edu \
--cc=akpm@linux-foundation.org \
--cc=ezk@cs.sunysb.edu \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.