Re: [PATCH 1/1] Taint kernel after WARN_ON(condition)

2008-02-11 Thread Josef 'Jeff' Sipek
On Tue, Feb 12, 2008 at 03:52:22AM +0800, Nur Hussein wrote:
> This patch will taint the kernel with a new flag, 'W', whenever a
> warning is issued with WARN_ON(condition). Whenever a warning occurs, it
> is helpful to record this within the kernel state as a taint. When a BUG
> happens, it'd be useful to know if it was also preceded by a WARN.

Any architecture that has it's own WARN_ON will not taint the kernel.

Speaking of WARN_ON...

$ git-grep "[^A-Za-z_0-9]WARN_ON(1)" | wc -l
180

Maybe making a WARN() (similar to BUG) that does an unconditional warning
(and sets the taint flag) and having a simple wrapper around it for the
conditional WARN_ON would be worth it? Hm...looks like some of the USB folks
have a #define'd WARN to something quite a bit more complex (format string,
etc.)

Josef 'Jeff' Sipek.

-- 
Linux, n.:
  Generous programmers from around the world all join forces to help
  you shoot yourself in the foot for free. 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] Taint kernel after WARN_ON(condition)

2008-02-11 Thread Josef 'Jeff' Sipek
On Tue, Feb 12, 2008 at 03:52:22AM +0800, Nur Hussein wrote:
 This patch will taint the kernel with a new flag, 'W', whenever a
 warning is issued with WARN_ON(condition). Whenever a warning occurs, it
 is helpful to record this within the kernel state as a taint. When a BUG
 happens, it'd be useful to know if it was also preceded by a WARN.

Any architecture that has it's own WARN_ON will not taint the kernel.

Speaking of WARN_ON...

$ git-grep [^A-Za-z_0-9]WARN_ON(1) | wc -l
180

Maybe making a WARN() (similar to BUG) that does an unconditional warning
(and sets the taint flag) and having a simple wrapper around it for the
conditional WARN_ON would be worth it? Hm...looks like some of the USB folks
have a #define'd WARN to something quite a bit more complex (format string,
etc.)

Josef 'Jeff' Sipek.

-- 
Linux, n.:
  Generous programmers from around the world all join forces to help
  you shoot yourself in the foot for free. 
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/1] arch: Ignore arch/i386 and arch/x86_64

2008-01-19 Thread Josef 'Jeff' Sipek
The i386 and x86_64 arch directories contain nothing but a generated symlink
to arch/x86/boot/bzImage when a tree a built.

Cc: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 arch/.gitignore |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
 create mode 100644 arch/.gitignore

diff --git a/arch/.gitignore b/arch/.gitignore
new file mode 100644
index 000..7414689
--- /dev/null
+++ b/arch/.gitignore
@@ -0,0 +1,2 @@
+i386
+x86_64
-- 
1.5.4.rc2.85.g9de45-dirty

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/1] arch: Ignore arch/i386 and arch/x86_64

2008-01-19 Thread Josef 'Jeff' Sipek
The i386 and x86_64 arch directories contain nothing but a generated symlink
to arch/x86/boot/bzImage when a tree a built.

Cc: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 arch/.gitignore |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
 create mode 100644 arch/.gitignore

diff --git a/arch/.gitignore b/arch/.gitignore
new file mode 100644
index 000..7414689
--- /dev/null
+++ b/arch/.gitignore
@@ -0,0 +1,2 @@
+i386
+x86_64
-- 
1.5.4.rc2.85.g9de45-dirty

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] Unionfs: move poison #define into poison.h

2007-09-25 Thread Josef 'Jeff' Sipek
On Tue, Sep 25, 2007 at 01:45:19PM -0400, Josef 'Jeff' Sipek wrote:
> This also fixes a compile warning on 64-bit systems.
 
Ok, I had a brain-fart...ignore this patch.

Jeff.

-- 
We have joy, we have fun, we have Linux on a Sun...
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/1] Unionfs: move poison #define into poison.h

2007-09-25 Thread Josef 'Jeff' Sipek
This also fixes a compile warning on 64-bit systems.

Cc: [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/debug.c |   12 ++--
 fs/unionfs/union.h |1 +
 include/linux/poison.h |3 +++
 3 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c
index f678534..aa6a76a 100644
--- a/fs/unionfs/debug.c
+++ b/fs/unionfs/debug.c
@@ -25,14 +25,6 @@
}   \
} while (0)
 
-#if BITS_PER_LONG == 32
-#define POISONED_PTR   ((void*) 0x5a5a5a5a)
-#elif BITS_PER_LONG == 64
-#define POISONED_PTR   ((void*) 0x5a5a5a5a5a5a5a5a)
-#else
-#error Unknown BITS_PER_LONG value
-#endif /* BITS_PER_LONG != known */
-
 /*
  * __unionfs_check_{inode,dentry,file} perform exhaustive sanity checking on
  * the fan-out of various Unionfs objects.  We check that no lower objects
@@ -93,7 +85,7 @@ void __unionfs_check_inode(const struct inode *inode,
printk(" Ci5: inode/linode=%p:%p bindex=%d "
   "istart/end=%d:%d\n", inode,
   lower_inode, bindex, istart, iend);
-   } else if (lower_inode == POISONED_PTR) {
+   } else if (lower_inode == UNIONFS_POISONED_PTR) {
/* freed inode! */
PRINT_CALLER(fname, fxn, line);
printk(" Ci6: inode/linode=%p:%p bindex=%d "
@@ -261,7 +253,7 @@ void __unionfs_check_dentry(const struct dentry *dentry,
printk(" CI5: dentry/linode=%p:%p bindex=%d "
   "istart/end=%d:%d\n", dentry,
   lower_inode, bindex, istart, iend);
-   } else if (lower_inode == POISONED_PTR) {
+   } else if (lower_inode == UNIONFS_POISONED_PTR) {
/* freed inode! */
PRINT_CALLER(fname, fxn, line);
printk(" CI6: dentry/linode=%p:%p bindex=%d "
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 9ec5f82..3b6881a 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
diff --git a/include/linux/poison.h b/include/linux/poison.h
index d93c300..c81118b 100644
--- a/include/linux/poison.h
+++ b/include/linux/poison.h
@@ -38,6 +38,9 @@
 /** fs/jbd/journal.c **/
 #define JBD_POISON_FREE0x5b
 
+/** fs/unionfs/debug.c **/
+#define UNIONFS_POISONED_PTR   ((void *) 0x75757575)
+
 /** drivers/base/dmapool.c **/
 #definePOOL_POISON_FREED   0xa7/* !inuse */
 #definePOOL_POISON_ALLOCATED   0xa9/* !initted */
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/1] Unionfs: move poison #define into poison.h

2007-09-25 Thread Josef 'Jeff' Sipek
This also fixes a compile warning on 64-bit systems.

Cc: [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/debug.c |   12 ++--
 fs/unionfs/union.h |1 +
 include/linux/poison.h |3 +++
 3 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c
index f678534..aa6a76a 100644
--- a/fs/unionfs/debug.c
+++ b/fs/unionfs/debug.c
@@ -25,14 +25,6 @@
}   \
} while (0)
 
-#if BITS_PER_LONG == 32
-#define POISONED_PTR   ((void*) 0x5a5a5a5a)
-#elif BITS_PER_LONG == 64
-#define POISONED_PTR   ((void*) 0x5a5a5a5a5a5a5a5a)
-#else
-#error Unknown BITS_PER_LONG value
-#endif /* BITS_PER_LONG != known */
-
 /*
  * __unionfs_check_{inode,dentry,file} perform exhaustive sanity checking on
  * the fan-out of various Unionfs objects.  We check that no lower objects
@@ -93,7 +85,7 @@ void __unionfs_check_inode(const struct inode *inode,
printk( Ci5: inode/linode=%p:%p bindex=%d 
   istart/end=%d:%d\n, inode,
   lower_inode, bindex, istart, iend);
-   } else if (lower_inode == POISONED_PTR) {
+   } else if (lower_inode == UNIONFS_POISONED_PTR) {
/* freed inode! */
PRINT_CALLER(fname, fxn, line);
printk( Ci6: inode/linode=%p:%p bindex=%d 
@@ -261,7 +253,7 @@ void __unionfs_check_dentry(const struct dentry *dentry,
printk( CI5: dentry/linode=%p:%p bindex=%d 
   istart/end=%d:%d\n, dentry,
   lower_inode, bindex, istart, iend);
-   } else if (lower_inode == POISONED_PTR) {
+   } else if (lower_inode == UNIONFS_POISONED_PTR) {
/* freed inode! */
PRINT_CALLER(fname, fxn, line);
printk( CI6: dentry/linode=%p:%p bindex=%d 
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 9ec5f82..3b6881a 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -43,6 +43,7 @@
 #include linux/fs_stack.h
 #include linux/magic.h
 #include linux/log2.h
+#include linux/poison.h
 
 #include asm/mman.h
 #include asm/system.h
diff --git a/include/linux/poison.h b/include/linux/poison.h
index d93c300..c81118b 100644
--- a/include/linux/poison.h
+++ b/include/linux/poison.h
@@ -38,6 +38,9 @@
 /** fs/jbd/journal.c **/
 #define JBD_POISON_FREE0x5b
 
+/** fs/unionfs/debug.c **/
+#define UNIONFS_POISONED_PTR   ((void *) 0x75757575)
+
 /** drivers/base/dmapool.c **/
 #definePOOL_POISON_FREED   0xa7/* !inuse */
 #definePOOL_POISON_ALLOCATED   0xa9/* !initted */
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] Unionfs: move poison #define into poison.h

2007-09-25 Thread Josef 'Jeff' Sipek
On Tue, Sep 25, 2007 at 01:45:19PM -0400, Josef 'Jeff' Sipek wrote:
 This also fixes a compile warning on 64-bit systems.
 
Ok, I had a brain-fart...ignore this patch.

Jeff.

-- 
We have joy, we have fun, we have Linux on a Sun...
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] Union Mount: Readdir approaches

2007-09-07 Thread Josef 'Jeff' Sipek
On Fri, Sep 07, 2007 at 01:28:55PM +0530, Bharata B Rao wrote:
> On Fri, Sep 07, 2007 at 04:31:26PM +0900, [EMAIL PROTECTED] wrote:
> > 
> > When the first readdir is issued:
> > - call vfs_readdir for every underlying opened dir (file) object.
> > - store every entry to either the hash table for the result or the
> >   whiteout, when the same-named entry didn't exist in the tables.
> > - to improvement the performance, the allocated memory for the hash
> >   tables are managed in a pointer array. and the elements are
> >   concatinated logically by the pointer.
> > - the pointer for the result-table, the version, and the currect jiffies
> >   are set to vdir, which is a cache in an inode.
> > - all cache are copied to a member in a file object.
> > - the index of the cache memory block and the offset in an array is
> >   handled as the seek position.
> 
> Ok, interesting approach. So you define the seek behaviour on your
> directory cache rather than allowing the underlying filesystems to
> interpret the seek. I guess we can do something similar with Union
> Mounts also.

Unless I missunderstood something, Unionfs uses the same approach. Even
Unionfs's ODF branch does the same thing. The major difference is that we
keep the cache in a file on a disk.

Josef 'Jeff' Sipek. 

-- 
Evolution, n.:
  A hypothetical process whereby infinitely improbable events occur with
  alarming frequency, order arises from chaos, and no one is given credit.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] Union Mount: Readdir approaches

2007-09-07 Thread Josef 'Jeff' Sipek
On Fri, Sep 07, 2007 at 01:28:55PM +0530, Bharata B Rao wrote:
 On Fri, Sep 07, 2007 at 04:31:26PM +0900, [EMAIL PROTECTED] wrote:
  
  When the first readdir is issued:
  - call vfs_readdir for every underlying opened dir (file) object.
  - store every entry to either the hash table for the result or the
whiteout, when the same-named entry didn't exist in the tables.
  - to improvement the performance, the allocated memory for the hash
tables are managed in a pointer array. and the elements are
concatinated logically by the pointer.
  - the pointer for the result-table, the version, and the currect jiffies
are set to vdir, which is a cache in an inode.
  - all cache are copied to a member in a file object.
  - the index of the cache memory block and the offset in an array is
handled as the seek position.
 
 Ok, interesting approach. So you define the seek behaviour on your
 directory cache rather than allowing the underlying filesystems to
 interpret the seek. I guess we can do something similar with Union
 Mounts also.

Unless I missunderstood something, Unionfs uses the same approach. Even
Unionfs's ODF branch does the same thing. The major difference is that we
keep the cache in a file on a disk.

Josef 'Jeff' Sipek. 

-- 
Evolution, n.:
  A hypothetical process whereby infinitely improbable events occur with
  alarming frequency, order arises from chaos, and no one is given credit.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/1] Unionfs: cache-coherency - dentries

2007-09-06 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Utility functions to check if lower dentries/inodes are newer than upper
ones, and purging cached data if lower objects are newer.  Also passed flag
to our d_revalidate_chain, to tell it if the caller may be writing data or
just reading it.

[jsipek: changed purge_inode_data to take a struct inode]
Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/commonfops.c |2 +-
 fs/unionfs/dentry.c |  143 ++-
 fs/unionfs/inode.c  |   24 +---
 fs/unionfs/rename.c |4 +-
 fs/unionfs/super.c  |2 +-
 fs/unionfs/union.h  |5 +-
 fs/unionfs/unlink.c |   12 +++-
 fs/unionfs/xattr.c  |8 +-
 8 files changed, 164 insertions(+), 36 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 28cb4e9..0dc7492 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -287,7 +287,7 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
 * but not unhashed dentries.
 */
if (!d_deleted(dentry) &&
-   !__unionfs_d_revalidate_chain(dentry, NULL)) {
+   !__unionfs_d_revalidate_chain(dentry, NULL, willwrite)) {
err = -ESTALE;
goto out_nofree;
}
diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
index 4a3c479..647a347 100644
--- a/fs/unionfs/dentry.c
+++ b/fs/unionfs/dentry.c
@@ -23,19 +23,18 @@
  * Assume that dentry's info node is locked.
  * Assume that parent(s) are all valid already, but
  * the child may not yet be valid.
- * Returns 1 if valid, 0 otherwise.
+ * Returns true if valid, false otherwise.
  */
-static int __unionfs_d_revalidate_one(struct dentry *dentry,
+static bool __unionfs_d_revalidate_one(struct dentry *dentry,
  struct nameidata *nd)
 {
-   int valid = 1;  /* default is valid (1); invalid is 0. */
+   bool valid = true;  /* default is valid */
struct dentry *lower_dentry;
int bindex, bstart, bend;
int sbgen, dgen;
int positive = 0;
int locked = 0;
int interpose_flag;
-
struct nameidata lowernd; /* TODO: be gentler to the stack */
 
if (nd)
@@ -128,7 +127,7 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
interpose_flag);
if (result) {
if (IS_ERR(result)) {
-   valid = 0;
+   valid = false;
goto out;
}
/*
@@ -142,7 +141,7 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
if (positive && UNIONFS_I(dentry->d_inode)->stale) {
make_bad_inode(dentry->d_inode);
d_drop(dentry);
-   valid = 0;
+   valid = false;
goto out;
}
goto out;
@@ -158,12 +157,12 @@ static int __unionfs_d_revalidate_one(struct dentry 
*dentry,
|| !lower_dentry->d_op->d_revalidate)
continue;
if (!lower_dentry->d_op->d_revalidate(lower_dentry,
-  ))
-   valid = 0;
+ ))
+   valid = false;
}
 
if (!dentry->d_inode)
-   valid = 0;
+   valid = false;
 
if (valid) {
/*
@@ -184,12 +183,94 @@ out:
 }
 
 /*
+ * Determine if the lower inode objects have changed from below the unionfs
+ * inode.  Return true if changed, false otherwise.
+ */
+bool is_newer_lower(const struct dentry *dentry)
+{
+   int bindex;
+   struct inode *inode;
+   struct inode *lower_inode;
+
+   /* ignore if we're called on semi-initialized dentries/inodes */
+   if (!dentry || !UNIONFS_D(dentry))
+   return false;
+   inode = dentry->d_inode;
+   if (!inode || !UNIONFS_I(inode) ||
+   ibstart(inode) < 0 || ibend(inode) < 0)
+   return false;
+
+   for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
+   lower_inode = unionfs_lower_inode_idx(inode, bindex);
+   if (!lower_inode)
+   continue;
+   /*
+* We may want to apply other tests to determine if the
+* lower inode's data has changed, but checking for changed
+* ctime and mtime on the lower inode should be enough.
+*/
+   if (timespec_compare(>i_mtime,
+_inode->i_mtime) < 0) {
+   prin

Re: [PATCH 1/1] Unionfs: cache-coherency - dentries

2007-09-06 Thread Josef 'Jeff' Sipek
On Mon, Sep 03, 2007 at 07:39:48PM -0400, Josef 'Jeff' Sipek wrote:
...
>  /*
> + * Determine if the lower inode objects have changed from below the unionfs
> + * inode.  Return 1 if changed, 0 otherwise.
> + */
> +bool is_newer_lower(const struct dentry *dentry)
> +{
> + int bindex;
> + struct inode *inode;
> + struct inode *lower_inode;
> +
> + /* ignore if we're called on semi-initialized dentries/inodes */
> + if (!dentry || !UNIONFS_D(dentry))
> + return false;
> + inode = dentry->d_inode;
> + if (!inode || !UNIONFS_I(inode) ||
> + ibstart(inode) < 0 || ibend(inode) < 0)
> + return false;
> +
> + for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
> + lower_inode = unionfs_lower_inode_idx(inode, bindex);
> + if (!lower_inode)
> + continue;
> + /*
> +  * We may want to apply other tests to determine if the
> +  * lower inode's data has changed, but checking for changed
> +  * ctime and mtime on the lower inode should be enough.
> +  */
> + if (timespec_compare(>i_mtime,
> +  _inode->i_mtime) < 0) {
> + printk("unionfs: new lower inode mtime "
> +"(bindex=%d, name=%s)\n", bindex,
> +dentry->d_name.name);
> + return true; /* mtime changed! */
> + }
> + if (timespec_compare(>i_ctime,
> +  _inode->i_ctime) < 0) {
> + printk("unionfs: new lower inode ctime "
> +"(bindex=%d, name=%s)\n", bindex,
> +dentry->d_name.name);
> + return true; /* ctime changed! */
> +     }
> + }
> + return true;/* default: lower is not newer */

This was a thinko, it should have returned false. I'll send an updated
patch for completeness.

Josef 'Jeff' Sipek.

-- 
Only two things are infinite, the universe and human stupidity, and I'm not
sure about the former.
- Albert Einstein
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] Unionfs: cache-coherency - dentries

2007-09-06 Thread Josef 'Jeff' Sipek
On Mon, Sep 03, 2007 at 07:39:48PM -0400, Josef 'Jeff' Sipek wrote:
...
  /*
 + * Determine if the lower inode objects have changed from below the unionfs
 + * inode.  Return 1 if changed, 0 otherwise.
 + */
 +bool is_newer_lower(const struct dentry *dentry)
 +{
 + int bindex;
 + struct inode *inode;
 + struct inode *lower_inode;
 +
 + /* ignore if we're called on semi-initialized dentries/inodes */
 + if (!dentry || !UNIONFS_D(dentry))
 + return false;
 + inode = dentry-d_inode;
 + if (!inode || !UNIONFS_I(inode) ||
 + ibstart(inode)  0 || ibend(inode)  0)
 + return false;
 +
 + for (bindex = ibstart(inode); bindex = ibend(inode); bindex++) {
 + lower_inode = unionfs_lower_inode_idx(inode, bindex);
 + if (!lower_inode)
 + continue;
 + /*
 +  * We may want to apply other tests to determine if the
 +  * lower inode's data has changed, but checking for changed
 +  * ctime and mtime on the lower inode should be enough.
 +  */
 + if (timespec_compare(inode-i_mtime,
 +  lower_inode-i_mtime)  0) {
 + printk(unionfs: new lower inode mtime 
 +(bindex=%d, name=%s)\n, bindex,
 +dentry-d_name.name);
 + return true; /* mtime changed! */
 + }
 + if (timespec_compare(inode-i_ctime,
 +  lower_inode-i_ctime)  0) {
 + printk(unionfs: new lower inode ctime 
 +(bindex=%d, name=%s)\n, bindex,
 +dentry-d_name.name);
 + return true; /* ctime changed! */
 + }
 + }
 + return true;/* default: lower is not newer */

This was a thinko, it should have returned false. I'll send an updated
patch for completeness.

Josef 'Jeff' Sipek.

-- 
Only two things are infinite, the universe and human stupidity, and I'm not
sure about the former.
- Albert Einstein
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/1] Unionfs: cache-coherency - dentries

2007-09-06 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Utility functions to check if lower dentries/inodes are newer than upper
ones, and purging cached data if lower objects are newer.  Also passed flag
to our d_revalidate_chain, to tell it if the caller may be writing data or
just reading it.

[jsipek: changed purge_inode_data to take a struct inode]
Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/commonfops.c |2 +-
 fs/unionfs/dentry.c |  143 ++-
 fs/unionfs/inode.c  |   24 +---
 fs/unionfs/rename.c |4 +-
 fs/unionfs/super.c  |2 +-
 fs/unionfs/union.h  |5 +-
 fs/unionfs/unlink.c |   12 +++-
 fs/unionfs/xattr.c  |8 +-
 8 files changed, 164 insertions(+), 36 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 28cb4e9..0dc7492 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -287,7 +287,7 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
 * but not unhashed dentries.
 */
if (!d_deleted(dentry) 
-   !__unionfs_d_revalidate_chain(dentry, NULL)) {
+   !__unionfs_d_revalidate_chain(dentry, NULL, willwrite)) {
err = -ESTALE;
goto out_nofree;
}
diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
index 4a3c479..647a347 100644
--- a/fs/unionfs/dentry.c
+++ b/fs/unionfs/dentry.c
@@ -23,19 +23,18 @@
  * Assume that dentry's info node is locked.
  * Assume that parent(s) are all valid already, but
  * the child may not yet be valid.
- * Returns 1 if valid, 0 otherwise.
+ * Returns true if valid, false otherwise.
  */
-static int __unionfs_d_revalidate_one(struct dentry *dentry,
+static bool __unionfs_d_revalidate_one(struct dentry *dentry,
  struct nameidata *nd)
 {
-   int valid = 1;  /* default is valid (1); invalid is 0. */
+   bool valid = true;  /* default is valid */
struct dentry *lower_dentry;
int bindex, bstart, bend;
int sbgen, dgen;
int positive = 0;
int locked = 0;
int interpose_flag;
-
struct nameidata lowernd; /* TODO: be gentler to the stack */
 
if (nd)
@@ -128,7 +127,7 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
interpose_flag);
if (result) {
if (IS_ERR(result)) {
-   valid = 0;
+   valid = false;
goto out;
}
/*
@@ -142,7 +141,7 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
if (positive  UNIONFS_I(dentry-d_inode)-stale) {
make_bad_inode(dentry-d_inode);
d_drop(dentry);
-   valid = 0;
+   valid = false;
goto out;
}
goto out;
@@ -158,12 +157,12 @@ static int __unionfs_d_revalidate_one(struct dentry 
*dentry,
|| !lower_dentry-d_op-d_revalidate)
continue;
if (!lower_dentry-d_op-d_revalidate(lower_dentry,
-  lowernd))
-   valid = 0;
+ lowernd))
+   valid = false;
}
 
if (!dentry-d_inode)
-   valid = 0;
+   valid = false;
 
if (valid) {
/*
@@ -184,12 +183,94 @@ out:
 }
 
 /*
+ * Determine if the lower inode objects have changed from below the unionfs
+ * inode.  Return true if changed, false otherwise.
+ */
+bool is_newer_lower(const struct dentry *dentry)
+{
+   int bindex;
+   struct inode *inode;
+   struct inode *lower_inode;
+
+   /* ignore if we're called on semi-initialized dentries/inodes */
+   if (!dentry || !UNIONFS_D(dentry))
+   return false;
+   inode = dentry-d_inode;
+   if (!inode || !UNIONFS_I(inode) ||
+   ibstart(inode)  0 || ibend(inode)  0)
+   return false;
+
+   for (bindex = ibstart(inode); bindex = ibend(inode); bindex++) {
+   lower_inode = unionfs_lower_inode_idx(inode, bindex);
+   if (!lower_inode)
+   continue;
+   /*
+* We may want to apply other tests to determine if the
+* lower inode's data has changed, but checking for changed
+* ctime and mtime on the lower inode should be enough.
+*/
+   if (timespec_compare(inode-i_mtime,
+lower_inode-i_mtime)  0) {
+   printk(unionfs: new lower inode mtime 
+  (bindex=%d, name

[PATCH 1/1] Unionfs: cache-coherency - dentries

2007-09-03 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Utility functions to check if lower dentries/inodes are newer than upper
ones, and purging cached data if lower objects are newer.  Also passed flag
to our d_revalidate_chain, to tell it if the caller may be writing data or
just reading it.

[jsipek: changed purge_inode_data to take a struct inode]
Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/commonfops.c |2 +-
 fs/unionfs/dentry.c |  143 ++-
 fs/unionfs/inode.c  |   24 +---
 fs/unionfs/rename.c |4 +-
 fs/unionfs/super.c  |2 +-
 fs/unionfs/union.h  |5 +-
 fs/unionfs/unlink.c |   12 +++-
 fs/unionfs/xattr.c  |8 +-
 8 files changed, 164 insertions(+), 36 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 28cb4e9..0dc7492 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -287,7 +287,7 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
 * but not unhashed dentries.
 */
if (!d_deleted(dentry) &&
-   !__unionfs_d_revalidate_chain(dentry, NULL)) {
+   !__unionfs_d_revalidate_chain(dentry, NULL, willwrite)) {
err = -ESTALE;
goto out_nofree;
}
diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
index 4a3c479..d937329 100644
--- a/fs/unionfs/dentry.c
+++ b/fs/unionfs/dentry.c
@@ -23,19 +23,18 @@
  * Assume that dentry's info node is locked.
  * Assume that parent(s) are all valid already, but
  * the child may not yet be valid.
- * Returns 1 if valid, 0 otherwise.
+ * Returns true if valid, false otherwise.
  */
-static int __unionfs_d_revalidate_one(struct dentry *dentry,
+static bool __unionfs_d_revalidate_one(struct dentry *dentry,
  struct nameidata *nd)
 {
-   int valid = 1;  /* default is valid (1); invalid is 0. */
+   bool valid = true;  /* default is valid */
struct dentry *lower_dentry;
int bindex, bstart, bend;
int sbgen, dgen;
int positive = 0;
int locked = 0;
int interpose_flag;
-
struct nameidata lowernd; /* TODO: be gentler to the stack */
 
if (nd)
@@ -128,7 +127,7 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
interpose_flag);
if (result) {
if (IS_ERR(result)) {
-   valid = 0;
+   valid = false;
goto out;
}
/*
@@ -142,7 +141,7 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
if (positive && UNIONFS_I(dentry->d_inode)->stale) {
make_bad_inode(dentry->d_inode);
d_drop(dentry);
-   valid = 0;
+   valid = false;
goto out;
}
goto out;
@@ -158,12 +157,12 @@ static int __unionfs_d_revalidate_one(struct dentry 
*dentry,
|| !lower_dentry->d_op->d_revalidate)
continue;
if (!lower_dentry->d_op->d_revalidate(lower_dentry,
-  ))
-   valid = 0;
+ ))
+   valid = false;
}
 
if (!dentry->d_inode)
-   valid = 0;
+   valid = false;
 
if (valid) {
/*
@@ -184,12 +183,94 @@ out:
 }
 
 /*
+ * Determine if the lower inode objects have changed from below the unionfs
+ * inode.  Return 1 if changed, 0 otherwise.
+ */
+bool is_newer_lower(const struct dentry *dentry)
+{
+   int bindex;
+   struct inode *inode;
+   struct inode *lower_inode;
+
+   /* ignore if we're called on semi-initialized dentries/inodes */
+   if (!dentry || !UNIONFS_D(dentry))
+   return false;
+   inode = dentry->d_inode;
+   if (!inode || !UNIONFS_I(inode) ||
+   ibstart(inode) < 0 || ibend(inode) < 0)
+   return false;
+
+   for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
+   lower_inode = unionfs_lower_inode_idx(inode, bindex);
+   if (!lower_inode)
+   continue;
+   /*
+* We may want to apply other tests to determine if the
+* lower inode's data has changed, but checking for changed
+* ctime and mtime on the lower inode should be enough.
+*/
+   if (timespec_compare(>i_mtime,
+_inode->i_mtime) < 0) {
+   printk("

Re: [PATCH 03/32] VFS/fsstack: cpp endif comments

2007-09-03 Thread Josef 'Jeff' Sipek
On Mon, Sep 03, 2007 at 08:39:27AM +0200, Jan Engelhardt wrote:
> 
> On Sep 2 2007 22:20, Josef 'Jeff' Sipek wrote:
> >diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
> >index 6b52faf..28543ad 100644
> >--- a/include/linux/fs_stack.h
> >+++ b/include/linux/fs_stack.h
> >@@ -39,4 +39,4 @@ static inline void fsstack_copy_attr_times(struct inode 
> >*dest,
> > dest->i_ctime = src->i_ctime;
> > }
> > 
> >-#endif /* _LINUX_FS_STACK_H */
> >+#endif /* not _LINUX_FS_STACK_H */
> 
> I hardly think this changes a thing, and it even goes against
> the de-facto standard of a lot of other files.

Fair enough. I'm going to drop it.

Jeff.

-- 
My public GPG key can be found at
http://www.josefsipek.net/gpg/public-0xC7958FFE.txt
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 01/32] VFS: export release_open_intent symbol

2007-09-03 Thread Josef 'Jeff' Sipek
On Mon, Sep 03, 2007 at 09:59:15PM +0530, Satyam Sharma wrote:
> 
> 
> On Sun, 2 Sep 2007, Josef 'Jeff' Sipek wrote:
> > 
> > diff --git a/fs/namei.c b/fs/namei.c
> > index a83160a..b2b7c8e 100644
> > --- a/fs/namei.c
> > +++ b/fs/namei.c
> > @@ -374,6 +374,7 @@ void release_open_intent(struct nameidata *nd)
> > else
> > fput(nd->intent.open.file);
> >  }
> > +EXPORT_SYMBOL(release_open_intent);
> 
> Hmm, why is this being pushed into mainline? This also looks like an
> -mm only patch to me, there are no modular users of release_open_intent()
> in mainline, and the next patch doesn't add one either.

Err...a thinko. Good catch.

Josef 'Jeff' Sipek.

-- 
I abhor a system designed for the "user", if that word is a coded pejorative
meaning "stupid and unsophisticated."
- Ken Thompson
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 09/32] Unionfs: cache-coherency - dentries

2007-09-03 Thread Josef 'Jeff' Sipek
On Mon, Sep 03, 2007 at 08:52:17AM +0200, Jan Engelhardt wrote:
> 
> On Sep 2 2007 22:20, Josef 'Jeff' Sipek wrote:
> >@@ -184,10 +183,92 @@ out:
> > }
> > 
> > /*
> >+ * Determine if the lower inode objects have changed from below the unionfs
> >+ * inode.  Return 1 if changed, 0 otherwise.
> >+ */
> >+int is_newer_lower(const struct dentry *dentry)
> 
> Could use bool and true/false as return value.
 
I remember that way back when there was a discussion about the bool type.
What how did that end? Is bool preferred?

> >-int __unionfs_d_revalidate_chain(struct dentry *dentry, struct nameidata 
> >*nd)
> >+int __unionfs_d_revalidate_chain(struct dentry *dentry, struct nameidata 
> >*nd,
> >+ int willwrite)
> 
> also looks like a bool (willwrite)

Right.

> >-if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
> >+if (!__unionfs_d_revalidate_chain(dentry, NULL, 0)) {
> 
> (Are there any callers with ,1?)

Indirectly yes. There are callers that pass a value they get. Very large
majority is 0.

Jeff.

-- 
Bad pun of the week: The formula 1 control computer suffered from a race
condition

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 12/32] Unionfs: documentation updates

2007-09-03 Thread Josef 'Jeff' Sipek
On Mon, Sep 03, 2007 at 08:59:02AM +0200, Jan Engelhardt wrote:
> 
> On Sep 2 2007 22:20, Josef 'Jeff' Sipek wrote:
> >+
> >+While rebuilding Unionfs's objects, we also purge any page mappings and
> >+truncate inode pages (see fs/Unionfs/dentry.c:purge_inode_data).  This is to
> 
> fs/unionfs/dentry.c
> 
> >+Unionfs maintains the following important invariant regarding mtime's,
> >+ctime's, and atime's: the upper inode object's times are the max() of all of
> 
> utimes, ctimes and atimes.
> 
> >+2. Lockdep (a debugging feature) isn't aware of stacking, and so it
> >+   incorrectly complains about locking problems.  The problem boils down to
> >+   this: Lockdep considers all objects of a certain type to be in the same
> >+   class, for example, all inodes.  Lockdep doesn't like to see a lock held
> >+   on two inodes within the same task, and warns that it could lead to a
> >+   deadlock.  However, stackable file systems do precisely that: they lock
> >+   an upper object, and then a lower object, in a strict order to avoid
> >+   locking problems; in addition, Unionfs, as a fan-out file system, may
> >+   have to lock several lower inodes.  We are currently looking into Lockdep
> >+   to see how to make it aware of stackable file systems.  In the mean time,
> 
> meantime
> 
> >@@ -86,5 +86,12 @@ command:
> > 
> > # mount -t unionfs -o remount,incgen none MOUNTPOINT
> > 
> >+Note that the older way of incrementing the generation number using an
> >+ioctl, is no longer supported in Unionfs 2.0.  Ioctls in general are not
> 
> 2.1?

Thanks.

Jeff.

-- 
Penguin : Linux version 2.4.20-46.9.legacysmp on an i386 machine (2778.72 
BogoMips).
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 12/32] Unionfs: documentation updates

2007-09-03 Thread Josef 'Jeff' Sipek
On Mon, Sep 03, 2007 at 08:59:02AM +0200, Jan Engelhardt wrote:
 
 On Sep 2 2007 22:20, Josef 'Jeff' Sipek wrote:
 +
 +While rebuilding Unionfs's objects, we also purge any page mappings and
 +truncate inode pages (see fs/Unionfs/dentry.c:purge_inode_data).  This is to
 
 fs/unionfs/dentry.c
 
 +Unionfs maintains the following important invariant regarding mtime's,
 +ctime's, and atime's: the upper inode object's times are the max() of all of
 
 utimes, ctimes and atimes.
 
 +2. Lockdep (a debugging feature) isn't aware of stacking, and so it
 +   incorrectly complains about locking problems.  The problem boils down to
 +   this: Lockdep considers all objects of a certain type to be in the same
 +   class, for example, all inodes.  Lockdep doesn't like to see a lock held
 +   on two inodes within the same task, and warns that it could lead to a
 +   deadlock.  However, stackable file systems do precisely that: they lock
 +   an upper object, and then a lower object, in a strict order to avoid
 +   locking problems; in addition, Unionfs, as a fan-out file system, may
 +   have to lock several lower inodes.  We are currently looking into Lockdep
 +   to see how to make it aware of stackable file systems.  In the mean time,
 
 meantime
 
 @@ -86,5 +86,12 @@ command:
  
  # mount -t unionfs -o remount,incgen none MOUNTPOINT
  
 +Note that the older way of incrementing the generation number using an
 +ioctl, is no longer supported in Unionfs 2.0.  Ioctls in general are not
 
 2.1?

Thanks.

Jeff.

-- 
Penguin : Linux version 2.4.20-46.9.legacysmp on an i386 machine (2778.72 
BogoMips).
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 09/32] Unionfs: cache-coherency - dentries

2007-09-03 Thread Josef 'Jeff' Sipek
On Mon, Sep 03, 2007 at 08:52:17AM +0200, Jan Engelhardt wrote:
 
 On Sep 2 2007 22:20, Josef 'Jeff' Sipek wrote:
 @@ -184,10 +183,92 @@ out:
  }
  
  /*
 + * Determine if the lower inode objects have changed from below the unionfs
 + * inode.  Return 1 if changed, 0 otherwise.
 + */
 +int is_newer_lower(const struct dentry *dentry)
 
 Could use bool and true/false as return value.
 
I remember that way back when there was a discussion about the bool type.
What how did that end? Is bool preferred?

 -int __unionfs_d_revalidate_chain(struct dentry *dentry, struct nameidata 
 *nd)
 +int __unionfs_d_revalidate_chain(struct dentry *dentry, struct nameidata 
 *nd,
 + int willwrite)
 
 also looks like a bool (willwrite)

Right.

 -if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
 +if (!__unionfs_d_revalidate_chain(dentry, NULL, 0)) {
 
 (Are there any callers with ,1?)

Indirectly yes. There are callers that pass a value they get. Very large
majority is 0.

Jeff.

-- 
Bad pun of the week: The formula 1 control computer suffered from a race
condition

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 01/32] VFS: export release_open_intent symbol

2007-09-03 Thread Josef 'Jeff' Sipek
On Mon, Sep 03, 2007 at 09:59:15PM +0530, Satyam Sharma wrote:
 
 
 On Sun, 2 Sep 2007, Josef 'Jeff' Sipek wrote:
  
  diff --git a/fs/namei.c b/fs/namei.c
  index a83160a..b2b7c8e 100644
  --- a/fs/namei.c
  +++ b/fs/namei.c
  @@ -374,6 +374,7 @@ void release_open_intent(struct nameidata *nd)
  else
  fput(nd-intent.open.file);
   }
  +EXPORT_SYMBOL(release_open_intent);
 
 Hmm, why is this being pushed into mainline? This also looks like an
 -mm only patch to me, there are no modular users of release_open_intent()
 in mainline, and the next patch doesn't add one either.

Err...a thinko. Good catch.

Josef 'Jeff' Sipek.

-- 
I abhor a system designed for the user, if that word is a coded pejorative
meaning stupid and unsophisticated.
- Ken Thompson
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 03/32] VFS/fsstack: cpp endif comments

2007-09-03 Thread Josef 'Jeff' Sipek
On Mon, Sep 03, 2007 at 08:39:27AM +0200, Jan Engelhardt wrote:
 
 On Sep 2 2007 22:20, Josef 'Jeff' Sipek wrote:
 diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
 index 6b52faf..28543ad 100644
 --- a/include/linux/fs_stack.h
 +++ b/include/linux/fs_stack.h
 @@ -39,4 +39,4 @@ static inline void fsstack_copy_attr_times(struct inode 
 *dest,
  dest-i_ctime = src-i_ctime;
  }
  
 -#endif /* _LINUX_FS_STACK_H */
 +#endif /* not _LINUX_FS_STACK_H */
 
 I hardly think this changes a thing, and it even goes against
 the de-facto standard of a lot of other files.

Fair enough. I'm going to drop it.

Jeff.

-- 
My public GPG key can be found at
http://www.josefsipek.net/gpg/public-0xC7958FFE.txt
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/1] Unionfs: cache-coherency - dentries

2007-09-03 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Utility functions to check if lower dentries/inodes are newer than upper
ones, and purging cached data if lower objects are newer.  Also passed flag
to our d_revalidate_chain, to tell it if the caller may be writing data or
just reading it.

[jsipek: changed purge_inode_data to take a struct inode]
Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/commonfops.c |2 +-
 fs/unionfs/dentry.c |  143 ++-
 fs/unionfs/inode.c  |   24 +---
 fs/unionfs/rename.c |4 +-
 fs/unionfs/super.c  |2 +-
 fs/unionfs/union.h  |5 +-
 fs/unionfs/unlink.c |   12 +++-
 fs/unionfs/xattr.c  |8 +-
 8 files changed, 164 insertions(+), 36 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 28cb4e9..0dc7492 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -287,7 +287,7 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
 * but not unhashed dentries.
 */
if (!d_deleted(dentry) 
-   !__unionfs_d_revalidate_chain(dentry, NULL)) {
+   !__unionfs_d_revalidate_chain(dentry, NULL, willwrite)) {
err = -ESTALE;
goto out_nofree;
}
diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
index 4a3c479..d937329 100644
--- a/fs/unionfs/dentry.c
+++ b/fs/unionfs/dentry.c
@@ -23,19 +23,18 @@
  * Assume that dentry's info node is locked.
  * Assume that parent(s) are all valid already, but
  * the child may not yet be valid.
- * Returns 1 if valid, 0 otherwise.
+ * Returns true if valid, false otherwise.
  */
-static int __unionfs_d_revalidate_one(struct dentry *dentry,
+static bool __unionfs_d_revalidate_one(struct dentry *dentry,
  struct nameidata *nd)
 {
-   int valid = 1;  /* default is valid (1); invalid is 0. */
+   bool valid = true;  /* default is valid */
struct dentry *lower_dentry;
int bindex, bstart, bend;
int sbgen, dgen;
int positive = 0;
int locked = 0;
int interpose_flag;
-
struct nameidata lowernd; /* TODO: be gentler to the stack */
 
if (nd)
@@ -128,7 +127,7 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
interpose_flag);
if (result) {
if (IS_ERR(result)) {
-   valid = 0;
+   valid = false;
goto out;
}
/*
@@ -142,7 +141,7 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
if (positive  UNIONFS_I(dentry-d_inode)-stale) {
make_bad_inode(dentry-d_inode);
d_drop(dentry);
-   valid = 0;
+   valid = false;
goto out;
}
goto out;
@@ -158,12 +157,12 @@ static int __unionfs_d_revalidate_one(struct dentry 
*dentry,
|| !lower_dentry-d_op-d_revalidate)
continue;
if (!lower_dentry-d_op-d_revalidate(lower_dentry,
-  lowernd))
-   valid = 0;
+ lowernd))
+   valid = false;
}
 
if (!dentry-d_inode)
-   valid = 0;
+   valid = false;
 
if (valid) {
/*
@@ -184,12 +183,94 @@ out:
 }
 
 /*
+ * Determine if the lower inode objects have changed from below the unionfs
+ * inode.  Return 1 if changed, 0 otherwise.
+ */
+bool is_newer_lower(const struct dentry *dentry)
+{
+   int bindex;
+   struct inode *inode;
+   struct inode *lower_inode;
+
+   /* ignore if we're called on semi-initialized dentries/inodes */
+   if (!dentry || !UNIONFS_D(dentry))
+   return false;
+   inode = dentry-d_inode;
+   if (!inode || !UNIONFS_I(inode) ||
+   ibstart(inode)  0 || ibend(inode)  0)
+   return false;
+
+   for (bindex = ibstart(inode); bindex = ibend(inode); bindex++) {
+   lower_inode = unionfs_lower_inode_idx(inode, bindex);
+   if (!lower_inode)
+   continue;
+   /*
+* We may want to apply other tests to determine if the
+* lower inode's data has changed, but checking for changed
+* ctime and mtime on the lower inode should be enough.
+*/
+   if (timespec_compare(inode-i_mtime,
+lower_inode-i_mtime)  0) {
+   printk(unionfs: new lower inode mtime 
+  (bindex=%d, name=%s)\n

[PATCH 29/32] Unionfs: assorted comment and style updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/dirhelper.c |2 --
 fs/unionfs/fanout.h|9 +++--
 fs/unionfs/file.c  |6 --
 fs/unionfs/inode.c |2 +-
 fs/unionfs/lookup.c|2 +-
 fs/unionfs/main.c  |7 +++
 fs/unionfs/rename.c|8 
 fs/unionfs/super.c |7 ++-
 fs/unionfs/union.h |   14 +++---
 fs/unionfs/unlink.c|1 -
 10 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index 24bd327..a72f711 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -31,7 +31,6 @@ int do_delete_whiteouts(struct dentry *dentry, int bindex,
struct dentry *lower_dentry;
char *name = NULL, *p;
struct inode *lower_dir;
-
int i;
struct list_head *pos;
struct filldir_node *cursor;
@@ -95,7 +94,6 @@ int delete_whiteouts(struct dentry *dentry, int bindex,
struct super_block *sb;
struct dentry *lower_dir_dentry;
struct inode *lower_dir;
-
struct sioq_args args;
 
sb = dentry->d_sb;
diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
index 5908bc7..c5bf454 100644
--- a/fs/unionfs/fanout.h
+++ b/fs/unionfs/fanout.h
@@ -65,9 +65,9 @@ static inline void new_branch_id(struct super_block *sb, int 
index)
 }
 
 /*
- * Find new index of matching branch with an existing superblock a a known
+ * Find new index of matching branch with an existing superblock of a known
  * (possibly old) id.  This is needed because branches could have been
- * added/deleted causing the branchs of any open files to shift.
+ * added/deleted causing the branches of any open files to shift.
  *
  * @sb: the new superblock which may have new/different branch IDs
  * @id: the old/existing id we're looking for
@@ -80,10 +80,7 @@ static inline int branch_id_to_idx(struct super_block *sb, 
int id)
if (branch_id(sb, i) == id)
return i;
}
-   /*
-* XXX: maybe we should BUG_ON if not found new branch index?
-* (really that should never happen).
-*/
+   /* in the non-ODF code, this should really never happen */
printk(KERN_WARNING "unionfs: cannot find branch with id %d\n", id);
return -1;
 }
diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
index b55da4f..b33f44f 100644
--- a/fs/unionfs/file.c
+++ b/fs/unionfs/file.c
@@ -18,17 +18,12 @@
 
 #include "union.h"
 
-/***
- * File Operations *
- ***/
-
 static ssize_t unionfs_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
 {
int err;
 
unionfs_read_lock(file->f_path.dentry->d_sb);
-
if ((err = unionfs_file_revalidate(file, 0)))
goto out;
 
@@ -50,7 +45,6 @@ static ssize_t unionfs_aio_read(struct kiocb *iocb, const 
struct iovec *iov,
struct file *file = iocb->ki_filp;
 
unionfs_read_lock(file->f_path.dentry->d_sb);
-
if ((err = unionfs_file_revalidate(file, 0)))
goto out;
 
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 4574fbe..218320e 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -781,7 +781,6 @@ static int unionfs_mknod(struct inode *dir, struct dentry 
*dentry, int mode,
if (err) {
if (!IS_COPYUP_ERR(err))
goto out;
-
bstart--;
} else
whiteout_unlinked = 1;
@@ -882,6 +881,7 @@ static int unionfs_readlink(struct dentry *dentry, char 
__user *buf,
 out:
unionfs_unlock_dentry(dentry);
unionfs_read_unlock(dentry->d_sb);
+
return err;
 }
 
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index 38ee21f..7fa6310 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -197,7 +197,7 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry,
 
/* check if whiteout exists in this branch: lookup .wh.foo */
wh_lower_dentry = lookup_one_len(whname, lower_dir_dentry,
- namelen + UNIONFS_WHLEN);
+namelen + UNIONFS_WHLEN);
if (IS_ERR(wh_lower_dentry)) {
dput(first_lower_dentry);
unionfs_mntput(first_dentry, first_dentry_offset);
diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index ce08d96..4faae44 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -226,6 +226,7 @@ void unionfs_reinterpose(struct dentry *dentry)
  */
 int check_branch(struct nameidata *nd)
 {
+   /* XXX: remove in ODF code -- stacking unions allowed there */
if (!strcmp(nd->dentry-&

[PATCH 17/32] Unionfs: interpose updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Update unionfs_interpose to handle spliced dentries, which is important for
NFS exporting.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/inode.c  |   40 +++
 fs/unionfs/lookup.c |   22 +++-
 fs/unionfs/main.c   |  138 +--
 fs/unionfs/union.h  |4 +-
 4 files changed, 141 insertions(+), 63 deletions(-)

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 6cec564..a219a40 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -152,7 +152,12 @@ static int unionfs_create(struct inode *parent, struct 
dentry *dentry,
 wh_dentry);
wh_dentry = NULL;
 
-   err = unionfs_interpose(dentry, parent->i_sb, 0);
+   /*
+* Only INTERPOSE_LOOKUP can return a value other
+* than 0 on err.
+*/
+   err = PTR_ERR(unionfs_interpose(dentry,
+   parent->i_sb, 0));
goto out;
}
}
@@ -194,11 +199,14 @@ static int unionfs_create(struct inode *parent, struct 
dentry *dentry,
if (!IS_COPYUP_ERR(err))
break;
} else {
-   err = unionfs_interpose(dentry, parent->i_sb, 0);
+   /*
+* Only INTERPOSE_LOOKUP can return a value other
+* than 0 on err.
+*/
+   err = PTR_ERR(unionfs_interpose(dentry,
+   parent->i_sb, 0));
if (!err) {
-   fsstack_copy_attr_times(parent,
-   lower_parent_dentry->
-   d_inode);
+   unionfs_copy_attr_times(parent);
fsstack_copy_inode_size(parent,
lower_parent_dentry->
d_inode);
@@ -527,7 +535,12 @@ static int unionfs_symlink(struct inode *dir, struct 
dentry *dentry,
if (!IS_COPYUP_ERR(err))
break;
} else {
-   err = unionfs_interpose(dentry, dir->i_sb, 0);
+   /*
+* Only INTERPOSE_LOOKUP can return a value other
+* than 0 on err.
+*/
+   err = PTR_ERR(unionfs_interpose(dentry,
+   dir->i_sb, 0));
if (!err) {
fsstack_copy_attr_times(dir,
lower_dir_dentry->
@@ -664,10 +677,13 @@ static int unionfs_mkdir(struct inode *parent, struct 
dentry *dentry, int mode)
}
set_dbend(dentry, bindex);
 
-   err = unionfs_interpose(dentry, parent->i_sb, 0);
+   /*
+* Only INTERPOSE_LOOKUP can return a value other than 0 on
+* err.
+*/
+   err = PTR_ERR(unionfs_interpose(dentry, parent->i_sb, 0));
if (!err) {
-   fsstack_copy_attr_times(parent,
-   lower_parent_dentry->d_inode);
+   unionfs_copy_attr_times(parent);
fsstack_copy_inode_size(parent,
lower_parent_dentry->d_inode);
 
@@ -795,7 +811,11 @@ static int unionfs_mknod(struct inode *dir, struct dentry 
*dentry, int mode,
break;
}
 
-   err = unionfs_interpose(dentry, dir->i_sb, 0);
+   /*
+* Only INTERPOSE_LOOKUP can return a value other than 0 on
+* err.
+*/
+   err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
if (!err) {
fsstack_copy_attr_times(dir,
lower_parent_dentry->d_inode);
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index 61ee50d..e4e8470 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -72,7 +72,12 @@ out:
return err;
 }
 
-/* main (and complex) driver function for Unionfs's lookup */
+/*
+ * Main (and complex) driver function for Unionfs's lookup
+ *
+ * Returns: NULL (ok), ERR_PTR if an error occurred, or a non-null non-error
+ * PTR if d_splice return

[PATCH 21/32] Unionfs: mmap fixes

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Most important fixes prevent deadlocks especially under low-memory
conditions, when one is not supposed to cause more memory pressure; also
handle AOP_WRITEPAGE_ACTIVATE from lower file systems.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/file.c |6 +-
 fs/unionfs/mmap.c |  132 ++---
 2 files changed, 98 insertions(+), 40 deletions(-)

diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
index 0555b6c..b55da4f 100644
--- a/fs/unionfs/file.c
+++ b/fs/unionfs/file.c
@@ -101,9 +101,6 @@ static int unionfs_mmap(struct file *file, struct 
vm_area_struct *vma)
 
unionfs_read_lock(file->f_path.dentry->d_sb);
 
-   if ((err = unionfs_file_revalidate(file, 1)))
-   goto out;
-
/* This might be deferred to mmap's writepage */
willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
if ((err = unionfs_file_revalidate(file, willwrite)))
@@ -132,6 +129,9 @@ static int unionfs_mmap(struct file *file, struct 
vm_area_struct *vma)
 
 out:
unionfs_read_unlock(file->f_path.dentry->d_sb);
+   if (!err)
+   /* copyup could cause parent dir times to change */
+   unionfs_copy_attr_times(file->f_path.dentry->d_parent->d_inode);
return err;
 }
 
diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c
index 969fd16..d26b572 100644
--- a/fs/unionfs/mmap.c
+++ b/fs/unionfs/mmap.c
@@ -21,7 +21,7 @@
 
 /*
  * Unionfs doesn't implement ->writepages, which is OK with the VFS and
- * nkeeps our code simpler and smaller.  Nevertheless, somehow, our own
+ * keeps our code simpler and smaller.  Nevertheless, somehow, our own
  * ->writepage must be called so we can sync the upper pages with the lower
  * pages: otherwise data changed at the upper layer won't get written to the
  * lower layer.
@@ -64,10 +64,31 @@ static int unionfs_writepage(struct page *page, struct 
writeback_control *wbc)
inode = page->mapping->host;
lower_inode = unionfs_lower_inode(inode);
 
-   /* find lower page (returns a locked page) */
-   lower_page = grab_cache_page(lower_inode->i_mapping, page->index);
-   if (!lower_page)
+   /*
+* find lower page (returns a locked page)
+*
+* NOTE: we used to call grab_cache_page(), but that was unnecessary
+* as it would have tried to create a new lower page if it didn't
+* exist, leading to deadlocks (esp. under memory-pressure
+* conditions, when it is really a bad idea to *consume* more
+* memory).  Instead, we assume the lower page exists, and if we can
+* find it, then we ->writepage on it; if we can't find it, then it
+* couldn't have disappeared unless the kernel already flushed it,
+* in which case we're still OK.  This is especially correct if
+* wbc->sync_mode is WB_SYNC_NONE (as per
+* Documentation/filesystems/vfs.txt).  If we can't flush our page
+* because we can't find a lower page, then at least we re-mark our
+* page as dirty, and return AOP_WRITEPAGE_ACTIVATE as the VFS
+* expects us to.  (Note, if in the future it'd turn out that we
+* have to find a lower page no matter what, then we'd have to
+* resort to RAIF's page pointer flipping trick.)
+*/
+   lower_page = find_lock_page(lower_inode->i_mapping, page->index);
+   if (!lower_page) {
+   err = AOP_WRITEPAGE_ACTIVATE;
+   set_page_dirty(page);
goto out;
+   }
 
/* get page address, and encode it */
kaddr = kmap(page);
@@ -85,24 +106,41 @@ static int unionfs_writepage(struct page *page, struct 
writeback_control *wbc)
wbc->for_writepages = 0;
 
/* call lower writepage (expects locked page) */
+   clear_page_dirty_for_io(lower_page); /* emulate VFS behavior */
err = lower_inode->i_mapping->a_ops->writepage(lower_page, wbc);
wbc->for_writepages = saved_for_writepages; /* restore value */
 
-   /*
-* update mtime and ctime of lower level file system
-* unionfs' mtime and ctime are updated by generic_file_write
-*/
-   lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
-
-   page_cache_release(lower_page); /* b/c grab_cache_page increased refcnt 
*/
-
+   /* b/c find_lock_page locked it and ->writepage unlocks on success */
if (err)
+   unlock_page(lower_page);
+   /* b/c grab_cache_page increased refcnt */
+   page_cache_release(lower_page);
+
+   if (err < 0) {
ClearPageUptodate(page);
-   else
-   SetPageUptodate(page);
+   goto out;
+   }
+   if (err == AOP_WRITEPAGE_AC

[PATCH 03/32] VFS/fsstack: cpp endif comments

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Add comments to #endif's to help clarify code.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 include/linux/fs_stack.h |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
index 6b52faf..28543ad 100644
--- a/include/linux/fs_stack.h
+++ b/include/linux/fs_stack.h
@@ -39,4 +39,4 @@ static inline void fsstack_copy_attr_times(struct inode *dest,
dest->i_ctime = src->i_ctime;
 }
 
-#endif /* _LINUX_FS_STACK_H */
+#endif /* not _LINUX_FS_STACK_H */
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 12/32] Unionfs: documentation updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Details of cache-coherency implementation (as per OLS'07 talk).
Also explain new incgen support via remount, not ioctl.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 Documentation/filesystems/unionfs/concepts.txt |  106 
 Documentation/filesystems/unionfs/issues.txt   |   53 
 Documentation/filesystems/unionfs/usage.txt|   11 ++-
 3 files changed, 134 insertions(+), 36 deletions(-)

diff --git a/Documentation/filesystems/unionfs/concepts.txt 
b/Documentation/filesystems/unionfs/concepts.txt
index 83d45b9..74b5bdc 100644
--- a/Documentation/filesystems/unionfs/concepts.txt
+++ b/Documentation/filesystems/unionfs/concepts.txt
@@ -4,6 +4,7 @@ Unionfs 2.0 CONCEPTS:
 This file describes the concepts needed by a namespace unification file
 system.
 
+
 Branch Priority:
 
 
@@ -72,4 +73,109 @@ that lookup and readdir return this newer "version" of the 
file rather than
 the original (see duplicate elimination).
 
 
+Cache Coherency:
+
+
+Unionfs users often want to be able to modify files and directories directly
+on the lower branches, and have those changes be visible at the Unionfs
+level.  This means that data (e.g., pages) and meta-data (dentries, inodes,
+open files, etc.) have to be synchronized between the upper and lower
+layers.  In other words, the newest changes from a layer below have to be
+propagated to the Unionfs layer above.  If the two layers are not in sync, a
+cache incoherency ensues, which could lead to application failures and even
+oopses.  The Linux kernel, however, has a rather limited set of mechanisms
+to ensure this inter-layer cache coherency---so Unionfs has to do most of
+the hard work on its own.
+
+Maintaining Invariants:
+
+The way Unionfs ensures cache coherency is as follows.  At each entry point
+to a Unionfs file system method, we call a utility function to validate the
+primary objects of this method.  Generally, we call unionfs_file_revalidate
+on open files, and __unionfs_d_revalidate_chain on dentries (which also
+validates inodes).  These utility functions check to see whether the upper
+Unionfs object is in sync with any of the lower objects that it represents.
+The checks we perform include whether the Unionfs superblock has a newer
+generation number, or if any of the lower objects mtime's or ctime's are
+newer.  (Note: generation numbers change when branch-management commands are
+issued, so in a way, maintaining cache coherency is also very important for
+branch-management.)  If indeed we determine that any Unionfs object is no
+longer in sync with its lower counterparts, then we rebuild that object
+similarly to how we do so for branch-management.
+
+While rebuilding Unionfs's objects, we also purge any page mappings and
+truncate inode pages (see fs/Unionfs/dentry.c:purge_inode_data).  This is to
+ensure that Unionfs will re-get the newer data from the lower branches.  We
+perform this purging only if the Unionfs operation in question is a reading
+operation; if Unionfs is performing a data writing operation (e.g., ->write,
+->commit_write, etc.) then we do NOT flush the lower mappings/pages: this is
+because (1) a self-deadlock could occur and (2) the upper Unionfs pages are
+considered more authoritative anyway, as they are newer and will overwrite
+any lower pages.
+
+Unionfs maintains the following important invariant regarding mtime's,
+ctime's, and atime's: the upper inode object's times are the max() of all of
+the lower ones.  For non-directory objects, there's only one object below,
+so the mapping is simple; for directory objects, there could me multiple
+lower objects and we have to sync up with the newest one of all the lower
+ones.  This invariant is important to maintain, especially for directories
+(besides, we need this to be POSIX compliant).  A union could comprise
+multiple writable branches, each of which could change.  If we don't reflect
+the newest possible mtime/ctime, some applications could fail.  For example,
+NFSv2/v3 exports check for newer directory mtimes on the server to determine
+if the client-side attribute cache should be purged.
+
+To maintain these important invariants, of course, Unionfs carefully
+synchronizes upper and lower times in various places.  For example, if we
+copy-up a file to a top-level branch, the parent directory where the file
+was copied up to will now have a new mtime: so after a successful copy-up,
+we sync up with the new top-level branch's parent directory mtime.
+
+Implementation:
+
+This cache-coherency implementation is efficient because it defers any
+synchronizing between the upper and lower layers until absolutely needed.
+Consider the example a common situation where users perform a lot of lower
+changes, such as untarring a whole package.  While these take place,
+typically the user doesn't 

[PATCH 19/32] Unionfs: partial_lookup update

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Handle new semantics of lookup_backend.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/lookup.c |   22 --
 1 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index e4e8470..d05daa5 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -425,20 +425,30 @@ out:
return ERR_PTR(err);
 }
 
-/* This is a utility function that fills in a unionfs dentry */
+/*
+ * This is a utility function that fills in a unionfs dentry.
+ *
+ * Returns: 0 (ok), or -ERRNO if an error occurred.
+ */
 int unionfs_partial_lookup(struct dentry *dentry)
 {
struct dentry *tmp;
struct nameidata nd = { .flags = 0 };
+   int err = -ENOSYS;
 
tmp = unionfs_lookup_backend(dentry, , INTERPOSE_PARTIAL);
-   if (!tmp)
-   return 0;
-   if (IS_ERR(tmp))
-   return PTR_ERR(tmp);
+   if (!tmp) {
+   err = 0;
+   goto out;
+   }
+   if (IS_ERR(tmp)) {
+   err = PTR_ERR(tmp);
+   goto out;
+   }
/* need to change the interface */
BUG_ON(tmp != dentry);
-   return -ENOSYS;
+out:
+   return err;
 }
 
 /* The dentry cache is just so we have properly sized dentries. */
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 10/32] Unionfs: cache-coherency - file flush

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Update our inode's time after flush.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/commonfops.c |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 0dc7492..edb52c0 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -742,6 +742,11 @@ int unionfs_flush(struct file *file, fl_owner_t id)
 
}
 
+   /* on success, update our times */
+   unionfs_copy_attr_times(dentry->d_inode);
+   /* parent time could have changed too (async) */
+   unionfs_copy_attr_times(dentry->d_parent->d_inode);
+
 out_lock:
unionfs_unlock_dentry(dentry);
 out:
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 32/32] Unionfs: unionfs_create rewrite

2007-09-02 Thread Josef 'Jeff' Sipek
The code was hard to follow and violated some invariants (e.g., never modify
a read only branch, and always create on branch 0).

Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/inode.c |  207 +++-
 1 files changed, 58 insertions(+), 149 deletions(-)

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 9adf272..08c1ae0 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -24,9 +24,7 @@ static int unionfs_create(struct inode *parent, struct dentry 
*dentry,
int err = 0;
struct dentry *lower_dentry = NULL;
struct dentry *wh_dentry = NULL;
-   struct dentry *new_lower_dentry;
struct dentry *lower_parent_dentry = NULL;
-   int bindex = 0, bstart;
char *name = NULL;
int valid = 0;
 
@@ -47,177 +45,88 @@ static int unionfs_create(struct inode *parent, struct 
dentry *dentry,
 */
BUG_ON(!valid && dentry->d_inode);
 
-   /* We start out in the leftmost branch. */
-   bstart = dbstart(dentry);
-   lower_dentry = unionfs_lower_dentry(dentry);
-
/*
-* 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 (IS_ERR(name)) {
-   err = PTR_ERR(name);
-   goto out;
-   }
-
-   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;
+   if ((err = is_robranch_super(dentry->d_sb, 0))) {
+   err = -EROFS;
goto out;
}
 
-   if (wh_dentry->d_inode) {
+   /*
+* We _always_ create on branch 0
+*/
+   lower_dentry = unionfs_lower_dentry_idx(dentry, 0);
+   if (lower_dentry) {
/*
-* .wh.foo has been found.
-* First truncate it and then rename it to foo (hence having
-* the same overall effect as a normal create.
+* check if whiteout exists in this branch, i.e. lookup .wh.foo
+* first.
 */
-   struct dentry *lower_dir_dentry;
-   struct iattr newattrs;
-
-   mutex_lock(_dentry->d_inode->i_mutex);
-   newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_ATIME
-   | ATTR_MTIME | ATTR_UID | ATTR_GID | ATTR_FORCE
-   | ATTR_KILL_SUID | ATTR_KILL_SGID;
-
-   newattrs.ia_mode = mode & ~current->fs->umask;
-   newattrs.ia_uid = current->fsuid;
-   newattrs.ia_gid = current->fsgid;
-
-   if (wh_dentry->d_inode->i_size != 0) {
-   newattrs.ia_valid |= ATTR_SIZE;
-   newattrs.ia_size = 0;
-   }
-
-   err = notify_change(wh_dentry, );
-
-   mutex_unlock(_dentry->d_inode->i_mutex);
-
-   if (err)
-   printk(KERN_WARNING "unionfs: %s:%d: notify_change "
-  "failed: %d, ignoring..\n",
-  __FILE__, __LINE__, err);
-
-   new_lower_dentry = unionfs_lower_dentry(dentry);
-   dget(new_lower_dentry);
-
-   lower_dir_dentry = dget_parent(wh_dentry);
-   lock_rename(lower_dir_dentry, lower_dir_dentry);
-
-   if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
-   err = vfs_rename(lower_dir_dentry->d_inode,
-wh_dentry,
-lower_dir_dentry->d_inode,
-new_lower_dentry);
-   }
-   if (!err) {
-   fsstack_copy_attr_times(parent,
-   new_lower_dentry->d_parent->
-   d_inode);
-   fsstack_copy_inode_size(parent,
-   new_lower_dentry->d_parent->
-   d_inode);
-   parent->i_nlink = unionfs_get_nlinks(parent);
+   name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+   if (IS_ERR(name)) {
+   err = PTR_ERR(name);
+   goto out;
}
 
-   unlock_rename(lower_dir_dentry, lower_dir_dentry);
-   dput(lower_dir_dentry);
-
-   dp

[PATCH 05/32] Unionfs: do not use fsstack_copy_attr_all

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Unionfs needs a special fan-out version of fsstack_copy_attr_all, which is
called unionfs_copy_attr_all.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/dentry.c |   12 +---
 fs/unionfs/fanout.h |   50 +-
 fs/unionfs/inode.c  |   13 -
 fs/unionfs/main.c   |2 +-
 fs/unionfs/subr.c   |2 +-
 fs/unionfs/union.h  |5 +++--
 6 files changed, 71 insertions(+), 13 deletions(-)

diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
index f88a285..4a3c479 100644
--- a/fs/unionfs/dentry.c
+++ b/fs/unionfs/dentry.c
@@ -166,9 +166,15 @@ static int __unionfs_d_revalidate_one(struct dentry 
*dentry,
valid = 0;
 
if (valid) {
-   fsstack_copy_attr_all(dentry->d_inode,
- unionfs_lower_inode(dentry->d_inode),
- unionfs_get_nlinks);
+   /*
+* If we get here, and we copy the meta-data from the lower
+* inode to our inode, then it is vital that we have already
+* purged all unionfs-level file data.  We do that in the
+* caller (__unionfs_d_revalidate_chain) by calling
+* purge_inode_data.
+*/
+   unionfs_copy_attr_all(dentry->d_inode,
+ unionfs_lower_inode(dentry->d_inode));
fsstack_copy_inode_size(dentry->d_inode,
unionfs_lower_inode(dentry->d_inode));
}
diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
index 4da34c6..5908bc7 100644
--- a/fs/unionfs/fanout.h
+++ b/fs/unionfs/fanout.h
@@ -305,4 +305,52 @@ static inline void verify_locked(struct dentry *d)
BUG_ON(!mutex_is_locked(_D(d)->lock));
 }
 
-#endif /* _FANOUT_H */
+/* copy a/m/ctime from the lower branch with the newest times */
+static inline void unionfs_copy_attr_times(struct inode *upper)
+{
+   int bindex;
+   struct inode *lower;
+
+   if (!upper)
+   return;
+   for (bindex=ibstart(upper); bindex <= ibend(upper); bindex++) {
+   lower = unionfs_lower_inode_idx(upper, bindex);
+   if (!lower)
+   continue; /* not all lower dir objects may exist */
+   if (timespec_compare(>i_mtime, >i_mtime) < 0)
+   upper->i_mtime = lower->i_mtime;
+   if (timespec_compare(>i_ctime, >i_ctime) < 0)
+   upper->i_ctime = lower->i_ctime;
+   if (timespec_compare(>i_atime, >i_atime) < 0)
+   upper->i_atime = lower->i_atime;
+   /* XXX: should we notify_change on our upper inode? */
+   }
+}
+
+/*
+ * A unionfs/fanout version of fsstack_copy_attr_all.  Uses a
+ * unionfs_get_nlinks to properly calcluate the number of links to a file.
+ * Also, copies the max() of all a/m/ctimes for all lower inodes (which is
+ * important if the lower inode is a directory type)
+ */
+static inline void unionfs_copy_attr_all(struct inode *dest,
+const struct inode *src)
+{
+   dest->i_mode = src->i_mode;
+   dest->i_uid = src->i_uid;
+   dest->i_gid = src->i_gid;
+   dest->i_rdev = src->i_rdev;
+
+   unionfs_copy_attr_times(dest);
+
+   dest->i_blkbits = src->i_blkbits;
+   dest->i_flags = src->i_flags;
+
+   /*
+* Update the nlinks AFTER updating the above fields, because the
+* get_links callback may depend on them.
+*/
+   dest->i_nlink = unionfs_get_nlinks(dest);
+}
+
+#endif /* not _FANOUT_H */
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 59bb418..cbbde6f 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -369,12 +369,13 @@ check_link:
/* Its a hard link, so use the same inode */
new_dentry->d_inode = igrab(old_dentry->d_inode);
d_instantiate(new_dentry, new_dentry->d_inode);
-   fsstack_copy_attr_all(dir, lower_new_dentry->d_parent->d_inode,
- unionfs_get_nlinks);
+   unionfs_copy_attr_all(dir, lower_new_dentry->d_parent->d_inode);
fsstack_copy_inode_size(dir, lower_new_dentry->d_parent->d_inode);
 
/* propagate number of hard-links */
old_dentry->d_inode->i_nlink = unionfs_get_nlinks(old_dentry->d_inode);
+   /* new dentry's ctime may have changed due to hard-link counts */
+   unionfs_copy_attr_times(new_dentry->d_inode);
 
 out:
if (!new_dentry->d_inode)
@@ -1084,13 +1085,15 @@ static int unionfs_setattr(struct dentry *dentry, 
struct iattr *ia)
}
 
/* get the size from the fir

[PATCH 30/32] Unionfs: update unionfs version number

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Update version number from 2.0 to 2.1 to reflect the amount of work that had
gone in since 2.0 was first released, and also to sync up with Unionfs 2.x
releases for earlier kernels.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 include/linux/union_fs.h |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/include/linux/union_fs.h b/include/linux/union_fs.h
index 9bc4e3b..7f8dcc3 100644
--- a/include/linux/union_fs.h
+++ b/include/linux/union_fs.h
@@ -12,7 +12,8 @@
 #ifndef _LINUX_UNION_FS_H
 #define _LINUX_UNION_FS_H
 
-#define UNIONFS_VERSION  "2.0"
+#define UNIONFS_VERSION  "2.1-mm"
+
 /*
  * DEFINITIONS FOR USER AND KERNEL CODE:
  */
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 27/32] Unionfs: extended attributes fixes

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/copyup.c |   43 +++
 fs/unionfs/union.h  |6 --
 fs/unionfs/xattr.c  |   16 ++--
 3 files changed, 37 insertions(+), 28 deletions(-)

diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
index 4c45790..36f751e 100644
--- a/fs/unionfs/copyup.c
+++ b/fs/unionfs/copyup.c
@@ -32,27 +32,39 @@ static int copyup_xattrs(struct dentry *old_lower_dentry,
ssize_t list_size = -1;
char *name_list = NULL;
char *attr_value = NULL;
-   char *name_list_orig = NULL;
+   char *name_list_buf = NULL;
 
+   /* query the actual size of the xattr list */
list_size = vfs_listxattr(old_lower_dentry, NULL, 0);
-
if (list_size <= 0) {
err = list_size;
goto out;
}
 
+   /* allocate space for the actual list */
name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX);
if (!name_list || IS_ERR(name_list)) {
err = PTR_ERR(name_list);
goto out;
}
+
+   name_list_buf = name_list; /* save for kfree at end */
+
+   /* now get the actual xattr list of the source file */
list_size = vfs_listxattr(old_lower_dentry, name_list, list_size);
+   if (list_size <= 0) {
+   err = list_size;
+   goto out;
+   }
+
+   /* allocate space to hold each xattr's value */
attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
if (!attr_value || IS_ERR(attr_value)) {
err = PTR_ERR(name_list);
goto out;
}
-   name_list_orig = name_list;
+
+   /* in a loop, get and set each xattr from src to dst file */
while (*name_list) {
ssize_t size;
 
@@ -65,7 +77,6 @@ static int copyup_xattrs(struct dentry *old_lower_dentry,
err = size;
goto out;
}
-
if (size > XATTR_SIZE_MAX) {
err = -E2BIG;
goto out;
@@ -73,19 +84,27 @@ static int copyup_xattrs(struct dentry *old_lower_dentry,
/* Don't lock here since vfs_setxattr does it for us. */
err = vfs_setxattr(new_lower_dentry, name_list, attr_value,
   size, 0);
-
+   /*
+* Selinux depends on "security.*" xattrs, so to maintain
+* the security of copied-up files, if Selinux is active,
+* then we must copy these xattrs as well.  So we need to
+* temporarily get FOWNER privileges.
+* XXX: move entire copyup code to SIOQ.
+*/
+   if (err == -EPERM && !capable(CAP_FOWNER)) {
+   cap_raise(current->cap_effective, CAP_FOWNER);
+   err = vfs_setxattr(new_lower_dentry, name_list,
+  attr_value, size, 0);
+   cap_lower(current->cap_effective, CAP_FOWNER);
+   }
if (err < 0)
goto out;
name_list += strlen(name_list) + 1;
}
 out:
-   name_list = name_list_orig;
-
-   if (name_list)
-   unionfs_xattr_free(name_list, list_size + 1);
-   if (attr_value)
-   unionfs_xattr_free(attr_value, XATTR_SIZE_MAX);
-   /* It is no big deal if this fails, we just roll with the punches. */
+   unionfs_xattr_kfree(name_list_buf);
+   unionfs_xattr_kfree(attr_value);
+   /* Ignore if xattr isn't supported */
if (err == -ENOTSUPP || err == -EOPNOTSUPP)
err = 0;
return err;
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 26d886e..d1232ac 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -341,8 +341,10 @@ extern struct dentry *unionfs_interpose(struct dentry 
*this_dentry,
 #ifdef CONFIG_UNION_FS_XATTR
 /* Extended attribute functions. */
 extern void *unionfs_xattr_alloc(size_t size, size_t limit);
-extern void unionfs_xattr_free(void *ptr, size_t size);
-
+static inline void unionfs_xattr_kfree(const void *p)
+{
+   kfree(p);
+}
 extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name,
void *value, size_t size);
 extern int unionfs_removexattr(struct dentry *dentry, const char *name);
diff --git a/fs/unionfs/xattr.c b/fs/unionfs/xattr.c
index 46f3d4e..6ab92f3 100644
--- a/fs/unionfs/xattr.c
+++ b/fs/unionfs/xattr.c
@@ -28,25 +28,13 @@ void *unionfs_xattr_alloc(size_t size, size_t limit)
 
if (!size)  /* size request, no buffer is needed */
return NULL;
-   else if (size <= PAGE_SIZE)
-   ptr = kmalloc(size

[PATCH 18/32] Unionfs: unionfs_ioctl bug fixes

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Properly update lower objects, and release lower mnts upon ioctl success or
failure.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/commonfops.c |   25 +++--
 1 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 1050c49..eee68b8 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -684,12 +684,15 @@ static int unionfs_ioctl_queryfile(struct file *file, 
unsigned int cmd,
 {
int err = 0;
fd_set branchlist;
-
int bstart = 0, bend = 0, bindex = 0;
+   int orig_bstart, orig_bend;
struct dentry *dentry, *lower_dentry;
+   struct vfsmount *mnt;
 
-   dentry = file->f_dentry;
+   dentry = file->f_path.dentry;
unionfs_lock_dentry(dentry);
+   orig_bstart = dbstart(dentry);
+   orig_bend = dbend(dentry);
if ((err = unionfs_partial_lookup(dentry)))
goto out;
bstart = dbstart(dentry);
@@ -703,7 +706,25 @@ static int unionfs_ioctl_queryfile(struct file *file, 
unsigned int cmd,
continue;
if (lower_dentry->d_inode)
FD_SET(bindex, );
+   /* purge any lower objects after partial_lookup */
+   if (bindex < orig_bstart || bindex > orig_bend) {
+   dput(lower_dentry);
+   unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
+   iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
+   unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
+   NULL);
+   mnt = unionfs_lower_mnt_idx(dentry, bindex);
+   if (!mnt)
+   continue;
+   unionfs_mntput(dentry, bindex);
+   unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
+   }
}
+   /* restore original dentry's offsets */
+   set_dbstart(dentry, orig_bstart);
+   set_dbend(dentry, orig_bend);
+   ibstart(dentry->d_inode) = orig_bstart;
+   ibend(dentry->d_inode) = orig_bend;
 
err = copy_to_user((void __user *)arg, , sizeof(fd_set));
if (err)
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 15/32] Unionfs: implement f/async

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Unionfs needs its own fsync and fasync instead of calling the generic
file_fsync, because it may have to sync multiple writable lower branches
(not just one).  This also allows Unionfs to compile with CONFIG_BLOCK=n.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/dirfops.c |2 +
 fs/unionfs/file.c|   91 +-
 fs/unionfs/union.h   |3 ++
 3 files changed, 95 insertions(+), 1 deletions(-)

diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
index 8503411..0e93bd7 100644
--- a/fs/unionfs/dirfops.c
+++ b/fs/unionfs/dirfops.c
@@ -273,4 +273,6 @@ struct file_operations unionfs_dir_fops = {
.open   = unionfs_open,
.release= unionfs_file_release,
.flush  = unionfs_flush,
+   .fsync  = unionfs_fsync,
+   .fasync = unionfs_fasync,
 };
diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
index 47b63f3..0555b6c 100644
--- a/fs/unionfs/file.c
+++ b/fs/unionfs/file.c
@@ -135,6 +135,94 @@ out:
return err;
 }
 
+int unionfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+   int bindex, bstart, bend;
+   struct file *lower_file;
+   struct dentry *lower_dentry;
+   struct inode *lower_inode, *inode;
+   int err = -EINVAL;
+
+   unionfs_read_lock(file->f_path.dentry->d_sb);
+   if ((err = unionfs_file_revalidate(file, 1)))
+   goto out;
+
+   bstart = fbstart(file);
+   bend = fbend(file);
+   if (bstart < 0 || bend < 0)
+   goto out;
+
+   inode = dentry->d_inode;
+   if (!inode) {
+   printk(KERN_ERR
+  "unionfs: null lower inode in unionfs_fsync\n");
+   goto out;
+   }
+   for (bindex = bstart; bindex <= bend; bindex++) {
+   lower_inode = unionfs_lower_inode_idx(inode, bindex);
+   if (!lower_inode || !lower_inode->i_fop->fsync)
+   continue;
+   lower_file = unionfs_lower_file_idx(file, bindex);
+   lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+   mutex_lock(_inode->i_mutex);
+   err = lower_inode->i_fop->fsync(lower_file,
+   lower_dentry,
+   datasync);
+   mutex_unlock(_inode->i_mutex);
+   if (err)
+   goto out;
+   }
+
+   unionfs_copy_attr_times(inode);
+
+out:
+   unionfs_read_unlock(file->f_path.dentry->d_sb);
+   return err;
+}
+
+int unionfs_fasync(int fd, struct file *file, int flag)
+{
+   int bindex, bstart, bend;
+   struct file *lower_file;
+   struct dentry *dentry;
+   struct inode *lower_inode, *inode;
+   int err = 0;
+
+   unionfs_read_lock(file->f_path.dentry->d_sb);
+   if ((err = unionfs_file_revalidate(file, 1)))
+   goto out;
+
+   bstart = fbstart(file);
+   bend = fbend(file);
+   if (bstart < 0 || bend < 0)
+   goto out;
+
+   dentry = file->f_path.dentry;
+   inode = dentry->d_inode;
+   if (!inode) {
+   printk(KERN_ERR
+  "unionfs: null lower inode in unionfs_fasync\n");
+   goto out;
+   }
+   for (bindex = bstart; bindex <= bend; bindex++) {
+   lower_inode = unionfs_lower_inode_idx(inode, bindex);
+   if (!lower_inode || !lower_inode->i_fop->fasync)
+   continue;
+   lower_file = unionfs_lower_file_idx(file, bindex);
+   mutex_lock(_inode->i_mutex);
+   err = lower_inode->i_fop->fasync(fd, lower_file, flag);
+   mutex_unlock(_inode->i_mutex);
+   if (err)
+   goto out;
+   }
+
+   unionfs_copy_attr_times(inode);
+
+out:
+   unionfs_read_unlock(file->f_path.dentry->d_sb);
+   return err;
+}
+
 struct file_operations unionfs_main_fops = {
.llseek = generic_file_llseek,
.read   = unionfs_read,
@@ -147,6 +235,7 @@ struct file_operations unionfs_main_fops = {
.open   = unionfs_open,
.flush  = unionfs_flush,
.release= unionfs_file_release,
-   .fsync  = file_fsync,
+   .fsync  = unionfs_fsync,
+   .fasync = unionfs_fasync,
.splice_read= generic_file_splice_read,
 };
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index f8a9cd2..ec33155 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -312,6 +312,9 @@ extern int unionfs_file_release(struct inode *inode, struct 
file *file);
 extern int unionfs_flush(struct file *file, fl_owner_t i

[PATCH 23/32] Unionfs: mount-time option parsing fix

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/main.c |9 ++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index bc5c105..ce08d96 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -337,8 +337,12 @@ static int parse_dirs_option(struct super_block *sb, 
struct unionfs_dentry_info
int perms;
char *mode = strchr(name, '=');
 
-   if (!name || !*name)
+   if (!name)
continue;
+   if (!*name) {   /* bad use of ':' (extra colons) */
+   err = -EINVAL;
+   goto out;
+   }
 
branches++;
 
@@ -404,10 +408,9 @@ static int parse_dirs_option(struct super_block *sb, 
struct unionfs_dentry_info
 * branch-overlapping test.
 */
for (i = 0; i < branches; i++) {
+   dent1 = lower_root_info->lower_paths[i].dentry;
for (j = i + 1; j < branches; j++) {
-   dent1 = lower_root_info->lower_paths[i].dentry;
dent2 = lower_root_info->lower_paths[j].dentry;
-
if (is_branch_overlap(dent1, dent2)) {
printk(KERN_WARNING "unionfs: branches %d and "
   "%d overlap\n", i, j);
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 07/32] Unionfs: cpp endif comments

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Add comments to #endif's to help clarify code.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/copyup.c |2 +-
 fs/unionfs/inode.c  |4 ++--
 fs/unionfs/sioq.h   |2 +-
 fs/unionfs/union.h  |2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
index cc7a816..410ce07 100644
--- a/fs/unionfs/copyup.c
+++ b/fs/unionfs/copyup.c
@@ -433,7 +433,7 @@ static int copyup_named_dentry(struct inode *dir, struct 
dentry *dentry,
/* Selinux uses extended attributes for permissions. */
if ((err = copyup_xattrs(old_lower_dentry, new_lower_dentry)))
goto out_unlink;
-#endif
+#endif /* CONFIG_UNION_FS_XATTR */
 
/* do not allow files getting deleted to be re-interposed */
if (!d_deleted(dentry))
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index cbbde6f..9261bed 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -1122,7 +1122,7 @@ struct inode_operations unionfs_dir_iops = {
.getxattr   = unionfs_getxattr,
.removexattr= unionfs_removexattr,
.listxattr  = unionfs_listxattr,
-#endif
+#endif /* CONFIG_UNION_FS_XATTR */
 };
 
 struct inode_operations unionfs_main_iops = {
@@ -1133,5 +1133,5 @@ struct inode_operations unionfs_main_iops = {
.getxattr   = unionfs_getxattr,
.removexattr= unionfs_removexattr,
.listxattr  = unionfs_listxattr,
-#endif
+#endif /* CONFIG_UNION_FS_XATTR */
 };
diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
index bedd7af..afb71ee 100644
--- a/fs/unionfs/sioq.h
+++ b/fs/unionfs/sioq.h
@@ -89,4 +89,4 @@ extern void __unionfs_unlink(struct work_struct *work);
 extern void __delete_whiteouts(struct work_struct *work);
 extern void __is_opaque_dir(struct work_struct *work);
 
-#endif /* _SIOQ_H */
+#endif /* not _SIOQ_H */
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 2a8f763..b7e5a93 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -419,7 +419,7 @@ static inline int is_robranch(const struct dentry *dentry)
 
 #ifndef DEFAULT_POLLMASK
 #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
-#endif
+#endif /* not DEFAULT_POLLMASK */
 
 /*
  * EXTERNALS:
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 14/32] Unionfs: file_revalidate updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Correctly revalidate a file and account for lower mnts, even when branches
are updated or inserted.  Better info upon file copyup.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/commonfops.c |   25 +
 1 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 64bd0bd..612207a 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -333,6 +333,9 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
 */
if (!d_deleted(dentry) &&
(sbgen > fgen || dbstart(dentry) != fbstart(file))) {
+   /* save orig branch ID */
+   int orig_brid = 
UNIONFS_F(file)->saved_branch_ids[fbstart(file)];
+
/* First we throw out the existing files. */
cleanup_file(file);
 
@@ -359,22 +362,36 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
if (err)
goto out;
} else {
+   int new_brid;
/* We only open the highest priority branch. */
err = open_highest_file(file, willwrite);
if (err)
goto out;
+   new_brid = UNIONFS_F(file)->
+ saved_branch_ids[fbstart(file)];
+   if (new_brid != orig_brid && sbgen > fgen) {
+   /*
+* If we re-opened the file on a different
+* branch than the original one, and this
+* was due to a new branch inserted, then
+* update the mnt counts of the old and new
+* branches accordingly.
+*/
+   unionfs_mntget(dentry, bstart);
+   unionfs_mntput(sb->s_root,
+  branch_id_to_idx(sb, orig_brid));
+   }
}
atomic_set(_F(file)->generation,
-  atomic_read(_I(dentry->d_inode)->
-  generation));
+  
atomic_read(_I(dentry->d_inode)->generation));
}
 
/* Copyup on the first write to a file on a readonly branch. */
if (willwrite && IS_WRITE_FLAG(file->f_flags) &&
!IS_WRITE_FLAG(unionfs_lower_file(file)->f_flags) &&
is_robranch(dentry)) {
-   printk(KERN_DEBUG "unionfs: Doing delayed copyup of a "
-  "read-write file on a read-only branch.\n");
+   printk(KERN_DEBUG "unionfs: do delay copyup of \"%s\"\n",
+  dentry->d_name.name);
err = do_delayed_copyup(file);
}
 
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 28/32] Unionfs: use file f_path field

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Start using file->f_path.dentry instead of file->f_dentry

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/commonfops.c |   42 --
 fs/unionfs/dirfops.c|6 +++---
 fs/unionfs/mmap.c   |5 ++---
 fs/unionfs/rdstate.c|2 +-
 4 files changed, 26 insertions(+), 29 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index eee68b8..341b6f2 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -158,7 +158,7 @@ static int open_all_files(struct file *file)
int bindex, bstart, bend, err = 0;
struct file *lower_file;
struct dentry *lower_dentry;
-   struct dentry *dentry = file->f_dentry;
+   struct dentry *dentry = file->f_path.dentry;
struct super_block *sb = dentry->d_sb;
 
bstart = dbstart(dentry);
@@ -193,8 +193,7 @@ static int open_highest_file(struct file *file, int 
willwrite)
int bindex, bstart, bend, err = 0;
struct file *lower_file;
struct dentry *lower_dentry;
-
-   struct dentry *dentry = file->f_dentry;
+   struct dentry *dentry = file->f_path.dentry;
struct inode *parent_inode = dentry->d_parent->d_inode;
struct super_block *sb = dentry->d_sb;
size_t inode_size = dentry->d_inode->i_size;
@@ -302,10 +301,9 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
int sbgen, fgen, dgen;
int bstart, bend;
int size;
-
int err = 0;
 
-   dentry = file->f_dentry;
+   dentry = file->f_path.dentry;
unionfs_lock_dentry(dentry);
sb = dentry->d_sb;
 
@@ -412,20 +410,20 @@ static int __open_dir(struct inode *inode, struct file 
*file)
struct file *lower_file;
int bindex, bstart, bend;
 
-   bstart = fbstart(file) = dbstart(file->f_dentry);
-   bend = fbend(file) = dbend(file->f_dentry);
+   bstart = fbstart(file) = dbstart(file->f_path.dentry);
+   bend = fbend(file) = dbend(file->f_path.dentry);
 
for (bindex = bstart; bindex <= bend; bindex++) {
lower_dentry =
-   unionfs_lower_dentry_idx(file->f_dentry, bindex);
+   unionfs_lower_dentry_idx(file->f_path.dentry, bindex);
if (!lower_dentry)
continue;
 
dget(lower_dentry);
-   unionfs_mntget(file->f_dentry, bindex);
+   unionfs_mntget(file->f_path.dentry, bindex);
lower_file = dentry_open(lower_dentry,
-unionfs_lower_mnt_idx(file->f_dentry,
-   bindex),
+
unionfs_lower_mnt_idx(file->f_path.dentry,
+  bindex),
 file->f_flags);
if (IS_ERR(lower_file))
return PTR_ERR(lower_file);
@@ -450,17 +448,17 @@ static int __open_file(struct inode *inode, struct file 
*file)
int lower_flags;
int bindex, bstart, bend;
 
-   lower_dentry = unionfs_lower_dentry(file->f_dentry);
+   lower_dentry = unionfs_lower_dentry(file->f_path.dentry);
lower_flags = file->f_flags;
 
-   bstart = fbstart(file) = dbstart(file->f_dentry);
-   bend = fbend(file) = dbend(file->f_dentry);
+   bstart = fbstart(file) = dbstart(file->f_path.dentry);
+   bend = fbend(file) = dbend(file->f_path.dentry);
 
/*
 * check for the permission for lower file.  If the error is
 * COPYUP_ERR, copyup the file.
 */
-   if (lower_dentry->d_inode && is_robranch(file->f_dentry)) {
+   if (lower_dentry->d_inode && is_robranch(file->f_path.dentry)) {
/*
 * if the open will change the file, copy it up otherwise
 * defer it.
@@ -472,7 +470,7 @@ static int __open_file(struct inode *inode, struct file 
*file)
/* copyup the file */
for (bindex = bstart - 1; bindex >= 0; bindex--) {
err = copyup_file(
-   file->f_dentry->d_parent->d_inode,
+   file->f_path.dentry->d_parent->d_inode,
file, bstart, bindex, size);
if (!err)
break;
@@ -488,10 +486,10 @@ static int __open_file(struct inode *inode, struct file 
*file)
 * dentry_open will decrement mnt refcnt if err.
 * otherwise fput() will do an mntput() for us upon file

[PATCH 13/32] Unionfs: copyup updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Fixes, updates, and better documentation for the file-copyup functionality.
Include two additional utility functions useful for copyup code callers.
Parent directory copyup updates: create_parents now takes a string name
instead of the whole dentry.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/commonfops.c |  135 +++
 fs/unionfs/copyup.c |  348 +++---
 fs/unionfs/inode.c  |   33 --
 fs/unionfs/rename.c |   26 +++--
 fs/unionfs/subr.c   |4 +-
 fs/unionfs/union.h  |   11 +-
 fs/unionfs/unlink.c |2 +
 7 files changed, 338 insertions(+), 221 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index edb52c0..64bd0bd 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -31,7 +31,6 @@ static int copyup_deleted_file(struct file *file, struct 
dentry *dentry,
const int countersize = sizeof(counter) * 2;
const int nlen = sizeof(".unionfs") + i_inosize + countersize - 1;
char name[nlen + 1];
-
int err;
struct dentry *tmp_dentry = NULL;
struct dentry *lower_dentry;
@@ -42,7 +41,6 @@ static int copyup_deleted_file(struct file *file, struct 
dentry *dentry,
sprintf(name, ".unionfs%*.*lx",
i_inosize, i_inosize, lower_dentry->d_inode->i_ino);
 
-retry:
/*
 * Loop, looking for an unused temp name to copyup to.
 *
@@ -52,6 +50,7 @@ retry:
 * the name exists in the dest branch, but it'd be nice to catch it
 * sooner than later.
 */
+retry:
tmp_dentry = NULL;
do {
char *suffix = name + nlen - countersize;
@@ -73,14 +72,20 @@ retry:
dput(tmp_dentry);
 
err = copyup_named_file(dentry->d_parent->d_inode, file, name, bstart,
-   bindex, file->f_dentry->d_inode->i_size);
-   if (err == -EEXIST)
-   goto retry;
-   else if (err)
+   bindex, file->f_path.dentry->d_inode->i_size);
+   if (err) {
+   if (err == -EEXIST)
+   goto retry;
goto out;
+   }
 
/* bring it to the same state as an unlinked file */
lower_dentry = unionfs_lower_dentry_idx(dentry, dbstart(dentry));
+   if (!unionfs_lower_inode_idx(dentry->d_inode, bindex)) {
+   atomic_inc(_dentry->d_inode->i_count);
+   unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
+   lower_dentry->d_inode);
+   }
lower_dir_dentry = lock_parent(lower_dentry);
err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
unlock_dir(lower_dir_dentry);
@@ -96,48 +101,52 @@ out:
 static void cleanup_file(struct file *file)
 {
int bindex, bstart, bend;
-   struct file **lf;
-   struct super_block *sb = file->f_dentry->d_sb;
+   struct file **lower_files;
+   struct file *lower_file;
+   struct super_block *sb = file->f_path.dentry->d_sb;
 
-   lf = UNIONFS_F(file)->lower_files;
+   lower_files = UNIONFS_F(file)->lower_files;
bstart = fbstart(file);
bend = fbend(file);
 
for (bindex = bstart; bindex <= bend; bindex++) {
-   if (unionfs_lower_file_idx(file, bindex)) {
-   /*
-* Find new index of matching branch with an open
-* file, since branches could have been added or
-* deleted causing the one with open files to shift.
-*/
-   int i;  /* holds (possibly) updated branch index */
-   int old_bid;
-
-   old_bid = UNIONFS_F(file)->saved_branch_ids[bindex];
-   i = branch_id_to_idx(sb, old_bid);
-   if (i < 0)
-   printk(KERN_ERR "unionfs: no superblock for "
-  "file %p\n", file);
-   else {
-   /* decrement count of open files */
-   branchput(sb, i);
-   /*
-* fput will perform an mntput for us on the
-* correct branch.  Although we're using the
-* file's old branch configuration, bindex,
-* which is the old index, correctly points
-* to the right branch in the file's branch
-* list.  In other words, we're going to
-  

[PATCH 31/32] Unionfs: debugging and validation of fan-out invariants

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Introduce debugging functionality, Makefile support to turn it on at compile
time, and hooks in the main code to verify fan-out invariants.  This is very
similar to how other file systems provide debugging functionality.  This
code has been very useful in detecting and fixing problems, especially when
stacking on top of assorted file systems.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/Kconfig  |6 +
 fs/unionfs/Makefile |2 +
 fs/unionfs/commonfops.c |   17 ++
 fs/unionfs/copyup.c |2 +
 fs/unionfs/debug.c  |  502 +++
 fs/unionfs/dentry.c |4 +
 fs/unionfs/file.c   |   19 ++-
 fs/unionfs/inode.c  |   22 ++
 fs/unionfs/mmap.c   |5 +
 fs/unionfs/rename.c |4 +
 fs/unionfs/super.c  |3 +
 fs/unionfs/union.h  |  105 +++---
 fs/unionfs/unlink.c |6 +
 fs/unionfs/xattr.c  |4 +
 14 files changed, 668 insertions(+), 33 deletions(-)
 create mode 100644 fs/unionfs/debug.c

diff --git a/fs/Kconfig b/fs/Kconfig
index d53d8ca..0c58d02 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1063,6 +1063,12 @@ config UNION_FS_XATTR
 
  If unsure, say N.
 
+config UNION_FS_DEBUG
+   bool "Debug Unionfs"
+   depends on UNION_FS
+   help
+ If you say Y here, you can turn on debugging output from Unionfs.
+
 endmenu
 
 menu "Miscellaneous filesystems"
diff --git a/fs/unionfs/Makefile b/fs/unionfs/Makefile
index 78be3e7..38fed90 100644
--- a/fs/unionfs/Makefile
+++ b/fs/unionfs/Makefile
@@ -5,3 +5,5 @@ unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \
lookup.o commonfops.o dirfops.o sioq.o mmap.o
 
 unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o
+
+unionfs-$(CONFIG_UNION_FS_DEBUG) += debug.o
diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 341b6f2..724128d 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -91,6 +91,8 @@ retry:
unlock_dir(lower_dir_dentry);
 
 out:
+   if (!err)
+   unionfs_check_dentry(dentry);
return err;
 }
 
@@ -247,6 +249,8 @@ static int do_delayed_copyup(struct file *file)
 
BUG_ON(!S_ISREG(dentry->d_inode->i_mode));
 
+   unionfs_check_file(file);
+   unionfs_check_dentry(dentry);
for (bindex = bstart - 1; bindex >= 0; bindex--) {
if (!d_deleted(dentry))
err = copyup_file(parent_inode, file, bstart,
@@ -286,6 +290,8 @@ static int do_delayed_copyup(struct file *file)
ibend(dentry->d_inode) = ibstart(dentry->d_inode);
 
 out:
+   unionfs_check_file(file);
+   unionfs_check_dentry(dentry);
return err;
 }
 
@@ -399,6 +405,8 @@ out:
kfree(UNIONFS_F(file)->saved_branch_ids);
}
 out_nofree:
+   if (!err)
+   unionfs_check_file(file);
unionfs_unlock_dentry(dentry);
return err;
 }
@@ -576,6 +584,11 @@ out:
}
 out_nofree:
unionfs_read_unlock(inode->i_sb);
+   unionfs_check_inode(inode);
+   if (!err) {
+   unionfs_check_file(file);
+   unionfs_check_dentry(file->f_path.dentry->d_parent);
+   }
return err;
 }
 
@@ -601,6 +614,7 @@ int unionfs_file_release(struct inode *inode, struct file 
*file)
 */
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
+   unionfs_check_file(file);
fileinfo = UNIONFS_F(file);
BUG_ON(file->f_path.dentry->d_inode != inode);
inodeinfo = UNIONFS_I(inode);
@@ -764,6 +778,7 @@ long unionfs_ioctl(struct file *file, unsigned int cmd, 
unsigned long arg)
 
 out:
unionfs_read_unlock(file->f_path.dentry->d_sb);
+   unionfs_check_file(file);
return err;
 }
 
@@ -778,6 +793,7 @@ int unionfs_flush(struct file *file, fl_owner_t id)
 
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
+   unionfs_check_file(file);
 
if (!atomic_dec_and_test(_I(dentry->d_inode)->totalopens))
goto out;
@@ -814,5 +830,6 @@ out_lock:
unionfs_unlock_dentry(dentry);
 out:
unionfs_read_unlock(dentry->d_sb);
+   unionfs_check_file(file);
return err;
 }
diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
index 36f751e..23ac4c8 100644
--- a/fs/unionfs/copyup.c
+++ b/fs/unionfs/copyup.c
@@ -532,6 +532,8 @@ out_free:
unionfs_postcopyup_setmnt(dentry);
/* sync inode times from copied-up inode to our inode */
unionfs_copy_attr_times(dentry->d_inode);
+   unionfs_check_inode(dir);
+   unionfs_check_dentry(dentry);
 out:
return err;
 }
diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c
new file mode 100644
index 000..f678534
--- /dev/null
+++ b/fs/unionfs/debug.c
@@ -0,0 +1,502 @@

[PATCH 24/32] Unionfs: remove old nfsro option

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Ensure that a branch set as 'ro' behaves like a real readonly mounted lower
file system.  This allows us to remove the old 'nfsro' option.  Now unionfs
handles even an readonly exported NFS file system, which was mounted on the
client in readwrite mode.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/inode.c   |   48 ++---
 include/linux/union_fs.h |3 --
 2 files changed, 23 insertions(+), 28 deletions(-)

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index d6a79d5..4574fbe 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -948,47 +948,44 @@ static void unionfs_put_link(struct dentry *dentry, 
struct nameidata *nd,
  * Basically copied from the kernel vfs permission(), but we've changed
  * the following:
  *   (1) the IS_RDONLY check is skipped, and
- *   (2) if you set the mount option `mode=nfsro', we assume that -EACCES
- *   means that the export is read-only and we should check standard Unix
- *   permissions.  This means that NFS ACL checks (or other advanced
- *   permission features) are bypassed. Note however, that we do call
- *   security_inode_permission, and therefore security inside SELinux, etc.
- *   are performed.
+ *   (2) We return 0 (success) if the non-leftmost branch is mounted
+ *   readonly, to allow copyup to work.
+ *   (3) we do call security_inode_permission, and therefore security inside
+ *   SELinux, etc. are performed.
  */
-static int inode_permission(struct inode *inode, int mask,
+static int inode_permission(struct super_block *sb, struct inode *inode, int 
mask,
struct nameidata *nd, int bindex)
 {
int retval, submask;
 
if (mask & MAY_WRITE) {
+   umode_t mode = inode->i_mode;
/* The first branch is allowed to be really readonly. */
-   if (bindex == 0) {
-   umode_t mode = inode->i_mode;
-   if (IS_RDONLY(inode) &&
-   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
-   return -EROFS;
-   }
+   if (bindex == 0 &&
+   IS_RDONLY(inode) &&
+   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+   return -EROFS;
/*
 * Nobody gets write access to an immutable file.
 */
if (IS_IMMUTABLE(inode))
return -EACCES;
+   /*
+* For all other branches than the first one, we ignore
+* EROFS or if the branch is mounted as readonly, to let
+* copyup take place.
+*/
+   if (bindex > 0 &&
+   is_robranch_super(sb, bindex) &&
+   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+   return 0;
}
 
/* Ordinary permission routines do not understand MAY_APPEND. */
submask = mask & ~MAY_APPEND;
-   if (inode->i_op && inode->i_op->permission) {
+   if (inode->i_op && inode->i_op->permission)
retval = inode->i_op->permission(inode, submask, nd);
-   if ((retval == -EACCES) && (submask & MAY_WRITE) &&
-   (!strcmp("nfs", (inode)->i_sb->s_type->name)) &&
-   (nd) && (nd->mnt) && (nd->mnt->mnt_sb)) {
-   int perms;
-   perms = branchperms(nd->mnt->mnt_sb, bindex);
-   if (perms & MAY_NFSRO)
-   retval = generic_permission(inode, submask,
-   NULL);
-   }
-   } else
+   else
retval = generic_permission(inode, submask, NULL);
 
if (retval && retval != -EROFS) /* ignore EROFS */
@@ -1046,7 +1043,8 @@ static int unionfs_permission(struct inode *inode, int 
mask,
 * We use our own special version of permission, such that
 * only the first branch returns -EROFS.
 */
-   err = inode_permission(lower_inode, mask, nd, bindex);
+   err = inode_permission(inode->i_sb, lower_inode, mask, nd,
+  bindex);
 
/*
 * The permissions are an intersection of the overall directory
diff --git a/include/linux/union_fs.h b/include/linux/union_fs.h
index 223ccab..9bc4e3b 100644
--- a/include/linux/union_fs.h
+++ b/include/linux/union_fs.h
@@ -22,8 +22,5 @@
 /* We don't support normal remount, but unionctl uses it. */
 # define UNIONFS_REMOUNT_MAGIC   

[PATCH 06/32] Unionfs: copyright corrections and updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/mmap.c |2 +-
 fs/unionfs/sioq.c |   13 +++--
 fs/unionfs/sioq.h |   13 +++--
 3 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c
index e03ca00..969fd16 100644
--- a/fs/unionfs/mmap.c
+++ b/fs/unionfs/mmap.c
@@ -10,7 +10,7 @@
  * Copyright (c) 2003  Puja Gupta
  * Copyright (c) 2003  Harikesavan Krishnan
  * Copyright (c) 2003-2007 Stony Brook University
- * Copyright (c) 2003-2007 The Research Foundation of State University of New 
York
+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/fs/unionfs/sioq.c b/fs/unionfs/sioq.c
index 575f08d..2a8c88e 100644
--- a/fs/unionfs/sioq.c
+++ b/fs/unionfs/sioq.c
@@ -1,10 +1,11 @@
 /*
- * Copyright (c) 2003-2007 Erez Zadok
- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
- * Copyright (c) 2005-2006 Junjiro Okajima
- * Copyright (c) 2004-2006 David P. Quigley
- * Copyright (c) 2003-2007 Stony Brook University
- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+ * Copyright (c) 2006-2007 Erez Zadok
+ * Copyright (c) 2006  Charles P. Wright
+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
+ * Copyright (c) 2006  Junjiro Okajima
+ * Copyright (c) 2006  David P. Quigley
+ * Copyright (c) 2006-2007 Stony Brook University
+ * Copyright (c) 2006-2007 The Research Foundation of SUNY
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
index 6d0d01f..bedd7af 100644
--- a/fs/unionfs/sioq.h
+++ b/fs/unionfs/sioq.h
@@ -1,10 +1,11 @@
 /*
- * Copyright (c) 2003-2007 Erez Zadok
- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
- * Copyright (c) 2005-2006 Junjiro Okajima
- * Copyright (c) 2004-2006 David P. Quigley
- * Copyright (c) 2003-2007 Stony Brook University
- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+ * Copyright (c) 2006-2007 Erez Zadok
+ * Copyright (c) 2006  Charles P. Wright
+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
+ * Copyright (c) 2006  Junjiro Okajima
+ * Copyright (c) 2006  David P. Quigley
+ * Copyright (c) 2006-2007 Stony Brook University
+ * Copyright (c) 2006-2007 The Research Foundation of SUNY
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 25/32] Unionfs: readonly branch test fix

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Bug fix to test if a lower branch is readonly, even when given negative
dentries.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/union.h |   19 ++-
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 33c2137..26d886e 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -396,14 +396,23 @@ static inline int is_robranch_super(const struct 
super_block *sb, int index)
 /* Is this file on a read-only branch? */
 static inline int is_robranch_idx(const struct dentry *dentry, int index)
 {
-   int err = 0;
+   struct super_block *lower_sb;
 
BUG_ON(index < 0);
 
-   if ((!(branchperms(dentry->d_sb, index) & MAY_WRITE)) ||
-   IS_RDONLY(unionfs_lower_dentry_idx(dentry, index)->d_inode))
-   err = -EROFS;
-   return err;
+   if (!(branchperms(dentry->d_sb, index) & MAY_WRITE))
+   return -EROFS;
+
+   lower_sb = unionfs_lower_super_idx(dentry->d_sb, index);
+   BUG_ON(lower_sb == NULL);
+   /*
+* test sb flags directly, not IS_RDONLY(lower_inode) because the
+* lower_dentry could be a negative.
+*/
+   if (lower_sb->s_flags & MS_RDONLY)
+   return -EROFS;
+
+   return 0;
 }
 
 static inline int is_robranch(const struct dentry *dentry)
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 20/32] Unionfs: lower nameidata support

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Create and free custom nameidata structures, and pass them to lower file
systems when needed via vfs_create.  (This code will get updated when/if
nameidata is split into an intent structure and a VFS-level only structure.)

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/copyup.c |8 ++-
 fs/unionfs/lookup.c |   58 +++
 fs/unionfs/rename.c |   15 +++-
 fs/unionfs/subr.c   |   14 ++-
 fs/unionfs/union.h  |2 +
 5 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
index 9c476cd..4c45790 100644
--- a/fs/unionfs/copyup.c
+++ b/fs/unionfs/copyup.c
@@ -177,19 +177,25 @@ static int __copyup_ndentry(struct dentry 
*old_lower_dentry,
run_sioq(__unionfs_mknod, );
err = args.err;
} else if (S_ISREG(old_mode)) {
+   struct nameidata nd;
+   err = init_lower_nd(, LOOKUP_CREATE);
+   if (err < 0)
+   goto out;
+   args.create.nd = 
args.create.parent = new_lower_parent_dentry->d_inode;
args.create.dentry = new_lower_dentry;
args.create.mode = old_mode;
-   args.create.nd = NULL;
 
run_sioq(__unionfs_create, );
err = args.err;
+   release_lower_nd(, err);
} else {
printk(KERN_ERR "unionfs: unknown inode type %d\n",
   old_mode);
BUG();
}
 
+out:
return err;
 }
 
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index d05daa5..152d421 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -564,3 +564,61 @@ void update_bstart(struct dentry *dentry)
unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
}
 }
+
+
+/*
+ * Initialize a nameidata structure (the intent part) we can pass to a lower
+ * file system.  Returns 0 on success or -error (only -ENOMEM possible).
+ * Inside that nd structure, this function may also return an allocated
+ * struct file (for open intents).  The caller, when done with this nd, must
+ * kfree the intent file (using release_lower_nd).
+ */
+int init_lower_nd(struct nameidata *nd, unsigned int flags)
+{
+   int err = 0;
+#ifdef ALLOC_LOWER_ND_FILE
+   /*
+* XXX: one day we may need to have the lower return an open file
+* for us.  It is not needed in 2.6.23-rc1 for nfs2/nfs3, but may
+* very well be needed for nfs4.
+*/
+   struct file *file;
+#endif /* ALLOC_LOWER_ND_FILE */
+
+   memset(nd, 0, sizeof(struct nameidata));
+
+   switch (flags) {
+   case LOOKUP_CREATE:
+   nd->flags = LOOKUP_CREATE;
+   nd->intent.open.flags = FMODE_READ | FMODE_WRITE | O_CREAT;
+#ifdef ALLOC_LOWER_ND_FILE
+   file = kzalloc(sizeof(struct file), GFP_KERNEL);
+   if (!file) {
+   err = -ENOMEM;
+   break; /* exit switch statement and thus return */
+   }
+   nd->intent.open.file = file;
+#endif /* ALLOC_LOWER_ND_FILE */
+   break;
+   default:
+   /*
+* We should never get here, for now.
+* We can add new cases here later on.
+*/
+   BUG();
+   break;
+   }
+
+   return err;
+}
+
+void release_lower_nd(struct nameidata *nd, int err)
+{
+   if (!nd->intent.open.file)
+   return;
+   if (!err)
+   release_open_intent(nd);
+#ifdef ALLOC_LOWER_ND_FILE
+   kfree(nd->intent.open.file);
+#endif /* ALLOC_LOWER_ND_FILE */
+}
diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
index acf829a..a02d678 100644
--- a/fs/unionfs/rename.c
+++ b/fs/unionfs/rename.c
@@ -256,10 +256,20 @@ static int do_unionfs_rename(struct inode *old_dir,
 */
if ((old_bstart != old_bend) || (do_copyup != -1)) {
struct dentry *lower_parent;
-   BUG_ON(!wh_old || wh_old->d_inode || bwh_old < 0);
+   struct nameidata nd;
+   if (!wh_old || wh_old->d_inode || bwh_old < 0) {
+   printk(KERN_ERR "unionfs: rename error "
+  "(wh_old=%p/%p bwh_old=%d)\n", wh_old,
+  (wh_old ? wh_old->d_inode : NULL), bwh_old);
+   err = -EIO;
+   goto out;
+   }
+   err = init_lower_nd(, LOOKUP_CREATE);
+   if (err < 0)
+   goto out;
lower_parent = lock_parent(wh_old);
local_err = vfs_create(lower_parent->d_inode, wh_old, S_IRUGO,
-   

[PATCH 01/32] VFS: export release_open_intent symbol

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/namei.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index a83160a..b2b7c8e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -374,6 +374,7 @@ void release_open_intent(struct nameidata *nd)
else
fput(nd->intent.open.file);
 }
+EXPORT_SYMBOL(release_open_intent);
 
 static inline struct dentry *
 do_revalidate(struct dentry *dentry, struct nameidata *nd)
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 09/32] Unionfs: cache-coherency - dentries

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Utility functions to check if lower dentries/inodes are newer than upper
ones, and purging cached data if lower objects are newer.  Also passed flag
to our d_revalidate_chain, to tell it if the caller may be writing data or
just reading it.

[jsipek: changed purge_inode_data to take a struct inode]
Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/commonfops.c |2 +-
 fs/unionfs/dentry.c |  127 --
 fs/unionfs/inode.c  |   24 ++---
 fs/unionfs/rename.c |4 +-
 fs/unionfs/super.c  |2 +-
 fs/unionfs/union.h  |3 +-
 fs/unionfs/unlink.c |   12 +++-
 fs/unionfs/xattr.c  |8 ++--
 8 files changed, 155 insertions(+), 27 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 28cb4e9..0dc7492 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -287,7 +287,7 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
 * but not unhashed dentries.
 */
if (!d_deleted(dentry) &&
-   !__unionfs_d_revalidate_chain(dentry, NULL)) {
+   !__unionfs_d_revalidate_chain(dentry, NULL, willwrite)) {
err = -ESTALE;
goto out_nofree;
}
diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
index 4a3c479..c7bbeca 100644
--- a/fs/unionfs/dentry.c
+++ b/fs/unionfs/dentry.c
@@ -35,7 +35,6 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
int positive = 0;
int locked = 0;
int interpose_flag;
-
struct nameidata lowernd; /* TODO: be gentler to the stack */
 
if (nd)
@@ -158,7 +157,7 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
|| !lower_dentry->d_op->d_revalidate)
continue;
if (!lower_dentry->d_op->d_revalidate(lower_dentry,
-  ))
+ ))
valid = 0;
}
 
@@ -184,10 +183,92 @@ out:
 }
 
 /*
+ * Determine if the lower inode objects have changed from below the unionfs
+ * inode.  Return 1 if changed, 0 otherwise.
+ */
+int is_newer_lower(const struct dentry *dentry)
+{
+   int bindex;
+   struct inode *inode;
+   struct inode *lower_inode;
+
+   /* ignore if we're called on semi-initialized dentries/inodes */
+   if (!dentry || !UNIONFS_D(dentry))
+   return 0;
+   inode = dentry->d_inode;
+   if (!inode || !UNIONFS_I(inode) ||
+   ibstart(inode) < 0 || ibend(inode) < 0)
+   return 0;
+
+   for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
+   lower_inode = unionfs_lower_inode_idx(inode, bindex);
+   if (!lower_inode)
+   continue;
+   /*
+* We may want to apply other tests to determine if the
+* lower inode's data has changed, but checking for changed
+* ctime and mtime on the lower inode should be enough.
+*/
+   if (timespec_compare(>i_mtime,
+_inode->i_mtime) < 0) {
+   printk("unionfs: new lower inode mtime "
+  "(bindex=%d, name=%s)\n", bindex,
+  dentry->d_name.name);
+   return 1; /* mtime changed! */
+   }
+   if (timespec_compare(>i_ctime,
+_inode->i_ctime) < 0) {
+   printk("unionfs: new lower inode ctime "
+  "(bindex=%d, name=%s)\n", bindex,
+  dentry->d_name.name);
+   return 1; /* ctime changed! */
+   }
+   }
+   return 0;   /* default: lower is not newer */
+}
+
+/*
+ * Purge/remove/unmap all date pages of a unionfs inode.  This is called
+ * when the lower inode has changed, and we have to force processes to get
+ * the new data.
+ *
+ * XXX: Our implementation works in that as long as a user process will have
+ * caused Unionfs to be called, directly or indirectly, even to just do
+ * ->d_revalidate; then we will have purged the current Unionfs data and the
+ * process will see the new data.  For example, a process that continually
+ * re-reads the same file's data will see the NEW data as soon as the lower
+ * file had changed, upon the next read(2) syscall (even if the file is
+ * still open!)  However, this doesn't work when the process re-reads the
+ * open file's data via mmap(2) (unless the user unmaps/closes the file and
+ * remaps/reopens it).  Once we respond to ->readpage(s), then th

[PATCH 08/32] Unionfs: cache-coherency - update inode times

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Part of cache-coherency support (as per OLS'07 talk and
Documentation/filesystems/unionfs/concepts.txt): update our inode time if
lower had changed.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/file.c   |7 +--
 fs/unionfs/inode.c  |   11 +++
 fs/unionfs/unlink.c |3 +++
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
index ad6821c..47b63f3 100644
--- a/fs/unionfs/file.c
+++ b/fs/unionfs/file.c
@@ -67,17 +67,20 @@ out:
unionfs_read_unlock(file->f_path.dentry->d_sb);
return err;
 }
-static ssize_t unionfs_write(struct file * file, const char __user * buf,
+
+static ssize_t unionfs_write(struct file *file, const char __user *buf,
 size_t count, loff_t *ppos)
 {
int err = 0;
 
unionfs_read_lock(file->f_path.dentry->d_sb);
-
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
 
err = do_sync_write(file, buf, count, ppos);
+   /* update our inode times upon a successful lower write */
+   if (err >= 0)
+   unionfs_copy_attr_times(file->f_path.dentry->d_inode);
 
 out:
unionfs_read_unlock(file->f_path.dentry->d_sb);
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 9261bed..66614e3 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -245,6 +245,12 @@ static struct dentry *unionfs_lookup(struct inode *parent,
nd->dentry = path_save.dentry;
nd->mnt = path_save.mnt;
}
+   if (!IS_ERR(ret)) {
+   if (ret)
+   dentry = ret;
+   /* parent times may have changed */
+   unionfs_copy_attr_times(dentry->d_parent->d_inode);
+   }
 
unionfs_read_unlock(dentry->d_sb);
 
@@ -675,8 +681,11 @@ out:
 
kfree(name);
 
+   if (!err)
+   unionfs_copy_attr_times(dentry->d_inode);
unionfs_unlock_dentry(dentry);
unionfs_read_unlock(dentry->d_sb);
+
return err;
 }
 
@@ -1006,6 +1015,8 @@ static int unionfs_permission(struct inode *inode, int 
mask,
break;
}
}
+   /* sync times which may have changed (asynchronously) below */
+   unionfs_copy_attr_times(inode);
 
 out:
return err;
diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
index 822bffe..7ad19ec 100644
--- a/fs/unionfs/unlink.c
+++ b/fs/unionfs/unlink.c
@@ -41,6 +41,9 @@ static int unionfs_unlink_whiteout(struct inode *dir, struct 
dentry *dentry)
dget(lower_dentry);
if (!(err = is_robranch_super(dentry->d_sb, bindex)))
err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
+   /* if vfs_unlink succeeded, update our inode's times */
+   if (!err)
+   unionfs_copy_attr_times(dentry->d_inode);
dput(lower_dentry);
fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
unlock_dir(lower_dir_dentry);
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 04/32] Unionfs: fixed compilation error

2007-09-02 Thread Josef 'Jeff' Sipek
From: Andrew Morton <[EMAIL PROTECTED]>

Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 include/linux/mm.h |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index d823db0..aee99b6 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -20,6 +20,7 @@ struct anon_vma;
 struct file_ra_state;
 struct user_struct;
 struct writeback_control;
+struct super_block;
 
 #ifndef CONFIG_DISCONTIGMEM  /* Don't use mapnrs, do it properly */
 extern unsigned long max_mapnr;
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 26/32] Unionfs: minor remount fixes

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/super.c |8 
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
index 1de41ea..339afab 100644
--- a/fs/unionfs/super.c
+++ b/fs/unionfs/super.c
@@ -736,7 +736,7 @@ out_no_change:
for (i=dbstart(sb->s_root); i<=dbend(sb->s_root); i++) {
struct dentry *lower_dentry =
unionfs_lower_dentry_idx(sb->s_root, i);
-   atomic_inc(_dentry->d_inode->i_count);
+   igrab(lower_dentry->d_inode);
new_lower_inodes[i] = lower_dentry->d_inode;
}
/* 2. release reference on all older lower inodes */
@@ -758,11 +758,11 @@ out_no_change:
i = atomic_inc_return(_SB(sb)->generation);
atomic_set(_D(sb->s_root)->generation, i);
atomic_set(_I(sb->s_root->d_inode)->generation, i);
-
-   err = 0;/* reset to success */
-
if (!(*flags & MS_SILENT))
printk("unionfs: new generation number %d\n", i);
+   /* finally, update the root dentry's times */
+   unionfs_copy_attr_times(sb->s_root->d_inode);
+   err = 0;/* reset to success */
 
/*
 * The code above falls through to the next label, and releases the
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 11/32] Unionfs: cache-coherency and fixes for unionfs_rename

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/rename.c |   30 --
 1 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
index 4de984e..f8ea37a 100644
--- a/fs/unionfs/rename.c
+++ b/fs/unionfs/rename.c
@@ -457,18 +457,44 @@ int unionfs_rename(struct inode *old_dir, struct dentry 
*old_dentry,
}
}
err = do_unionfs_rename(old_dir, old_dentry, new_dir, new_dentry);
-
 out:
if (err)
/* clear the new_dentry stuff created */
d_drop(new_dentry);
-   else
+   else {
/*
 * force re-lookup since the dir on ro branch is not renamed,
 * and lower dentries still indicate the un-renamed ones.
 */
if (S_ISDIR(old_dentry->d_inode->i_mode))
atomic_dec(_D(old_dentry)->generation);
+   if (new_dentry->d_inode &&
+   !S_ISDIR(new_dentry->d_inode->i_mode)) {
+   if (!unionfs_lower_inode(new_dentry->d_inode)) {
+   /*
+* If we get here, it means that no copyup
+* was needed, and that a file by the old
+* name already existing on the destination
+* branch; that file got renamed earlier in
+* this function, so all we need to do here
+* is set the lower inode.
+*/
+   struct inode *inode;
+   inode = unionfs_lower_inode(
+   old_dentry->d_inode);
+   igrab(inode);
+   unionfs_set_lower_inode_idx(
+   new_dentry->d_inode,
+   dbstart(new_dentry), inode);
+   }
+
+   }
+   /* if all of this renaming succeeded, update our times */
+   unionfs_copy_attr_times(old_dir);
+   unionfs_copy_attr_times(new_dir);
+   unionfs_copy_attr_times(old_dentry->d_inode);
+   unionfs_copy_attr_times(new_dentry->d_inode);
+   }
 
unionfs_unlock_dentry(new_dentry);
unionfs_unlock_dentry(old_dentry);
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 02/32] VFS/fsstack: remove 3rd argument to fsstack_copy_attr_all

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Unionfs needs a special fan-out version of fsstack_copy_attr_all. A
single-level stackable file systems such as eCryptfs can therefore use a
simplified fsstack_copy_attr_all function; remove its 3rd argument, which
was never used by eCryptfs and was only used by Unionfs.

Acked-by: Michael Halcrow <[EMAIL PROTECTED]>
Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/ecryptfs/dentry.c |2 +-
 fs/ecryptfs/inode.c  |6 +++---
 fs/ecryptfs/main.c   |2 +-
 fs/stack.c   |   13 ++---
 include/linux/fs_stack.h |4 +---
 5 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
index cb20b96..a8c1686 100644
--- a/fs/ecryptfs/dentry.c
+++ b/fs/ecryptfs/dentry.c
@@ -62,7 +62,7 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, 
struct nameidata *nd)
struct inode *lower_inode =
ecryptfs_inode_to_lower(dentry->d_inode);
 
-   fsstack_copy_attr_all(dentry->d_inode, lower_inode, NULL);
+   fsstack_copy_attr_all(dentry->d_inode, lower_inode);
}
 out:
return rc;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 131954b..fc4c6cb 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -601,9 +601,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry 
*old_dentry,
lower_new_dir_dentry->d_inode, lower_new_dentry);
if (rc)
goto out_lock;
-   fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
+   fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
if (new_dir != old_dir)
-   fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode, 
NULL);
+   fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
 out_lock:
unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
dput(lower_new_dentry->d_parent);
@@ -961,7 +961,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct 
iattr *ia)
}
rc = notify_change(lower_dentry, ia);
 out:
-   fsstack_copy_attr_all(inode, lower_inode, NULL);
+   fsstack_copy_attr_all(inode, lower_inode);
return rc;
 }
 
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index a984972..cb349a4 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -151,7 +151,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct 
dentry *dentry,
d_add(dentry, inode);
else
d_instantiate(dentry, inode);
-   fsstack_copy_attr_all(inode, lower_inode, NULL);
+   fsstack_copy_attr_all(inode, lower_inode);
/* This size will be overwritten for real files w/ headers and
 * other metadata */
fsstack_copy_inode_size(inode, lower_inode);
diff --git a/fs/stack.c b/fs/stack.c
index 4368d4b..a548aac 100644
--- a/fs/stack.c
+++ b/fs/stack.c
@@ -30,8 +30,7 @@ EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
  * copy all attributes; get_nlinks is optional way to override the i_nlink
  * copying
  */
-void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
-  int (*get_nlinks)(struct inode *))
+void fsstack_copy_attr_all(struct inode *dest, const struct inode *src)
 {
dest->i_mode = src->i_mode;
dest->i_uid = src->i_uid;
@@ -42,14 +41,6 @@ void fsstack_copy_attr_all(struct inode *dest, const struct 
inode *src,
dest->i_ctime = src->i_ctime;
dest->i_blkbits = src->i_blkbits;
dest->i_flags = src->i_flags;
-
-   /*
-* Update the nlinks AFTER updating the above fields, because the
-* get_links callback may depend on them.
-*/
-   if (!get_nlinks)
-   dest->i_nlink = src->i_nlink;
-   else
-   dest->i_nlink = (*get_nlinks)(dest);
+   dest->i_nlink = src->i_nlink;
 }
 EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
index f3cd7f4..6b52faf 100644
--- a/include/linux/fs_stack.h
+++ b/include/linux/fs_stack.h
@@ -20,9 +20,7 @@
 #include 
 
 /* externs for fs/stack.c */
-extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
- int (*get_nlinks)(struct inode *));
-
+extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src);
 extern void fsstack_copy_inode_size(struct inode *dst,
const struct inode *src);
 
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 22/32] Unionfs: handling lower vfsmount fixes

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Properly increase/release lower vfsmounts.
Validate proper use of unionfs mntget/put.

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/dentry.c |6 --
 fs/unionfs/inode.c  |   11 +++
 fs/unionfs/lookup.c |   11 ++-
 fs/unionfs/union.h  |   47 +++
 4 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
index c7bbeca..0be958f 100644
--- a/fs/unionfs/dentry.c
+++ b/fs/unionfs/dentry.c
@@ -450,9 +450,11 @@ static void unionfs_d_release(struct dentry *dentry)
bend = dbend(dentry);
for (bindex = bstart; bindex <= bend; bindex++) {
dput(unionfs_lower_dentry_idx(dentry, bindex));
-   unionfs_mntput(dentry, bindex);
-
unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
+   /* NULL lower mnt is ok if this is a negative dentry */
+   if (!dentry->d_inode && !unionfs_lower_mnt_idx(dentry,bindex))
+   continue;
+   unionfs_mntput(dentry, bindex);
unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
}
/* free private data (unionfs_dentry_info) here */
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index a219a40..d6a79d5 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -222,8 +222,11 @@ out:
dput(wh_dentry);
kfree(name);
 
+   if (!err)
+   unionfs_postcopyup_setmnt(dentry);
unionfs_unlock_dentry(dentry);
unionfs_read_unlock(dentry->d_sb);
+
return err;
 }
 
@@ -563,8 +566,12 @@ out:
d_drop(dentry);
 
kfree(name);
+   if (!err)
+   unionfs_postcopyup_setmnt(dentry);
unionfs_unlock_dentry(dentry);
+
unionfs_read_unlock(dentry->d_sb);
+
return err;
 }
 
@@ -835,8 +842,12 @@ out:
 
kfree(name);
 
+   if (!err)
+   unionfs_postcopyup_setmnt(dentry);
unionfs_unlock_dentry(dentry);
+
unionfs_read_unlock(dentry->d_sb);
+
return err;
 }
 
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index 152d421..38ee21f 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -314,24 +314,25 @@ out_negative:
if (lookupmode == INTERPOSE_REVAL) {
if (dentry->d_inode)
UNIONFS_I(dentry->d_inode)->stale = 1;
-
goto out;
}
/* This should only happen if we found a whiteout. */
if (first_dentry_offset == -1) {
first_lower_dentry = lookup_one_len(name, lower_dir_dentry,
-namelen);
+   namelen);
first_dentry_offset = bindex;
if (IS_ERR(first_lower_dentry)) {
err = PTR_ERR(first_lower_dentry);
goto out;
}
-   
-   /* FIXME: the following line needs to be changed to allow
+
+   /*
+* FIXME: the following line needs to be changed to allow
 * mount-point crossing
 */
first_dentry = dentry;
-   first_lower_mnt = unionfs_mntget(dentry, bindex);
+   first_lower_mnt = unionfs_mntget(dentry->d_sb->s_root,
+bindex);
}
unionfs_set_lower_dentry_idx(dentry, first_dentry_offset,
 first_lower_dentry);
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 9f3e68a..33c2137 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -459,18 +459,49 @@ static inline void unlock_dir(struct dentry *dir)
 static inline struct vfsmount *unionfs_mntget(struct dentry *dentry,
  int bindex)
 {
-   BUG_ON(!dentry || bindex < 0);
-
-   return mntget(unionfs_lower_mnt_idx(dentry, bindex));
+   struct vfsmount *mnt;
+
+   if (!dentry) {
+   if (bindex < 0)
+   return NULL;
+   if (!dentry && bindex >= 0) {
+   return NULL;
+   }
+   }
+   mnt = unionfs_lower_mnt_idx(dentry, bindex);
+   if (!mnt) {
+   if (bindex < 0)
+   return NULL;
+   if (!mnt && bindex >= 0) {
+   return NULL;
+   }
+   }
+   mnt = mntget(mnt);
+   return mnt;
 }
 
 static inline void unionfs_mntput(struct dentry *dentry, int bindex)
 {
-   if (!dentry)
-   return;
+   struct vfsmount *mnt;
+
+   if (!dentry) {
+   if (bindex < 0)
+ 

[PATCH 16/32] Unionfs: minor file_release updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/commonfops.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 612207a..1050c49 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -593,8 +593,7 @@ int unionfs_file_release(struct inode *inode, struct file 
*file)
struct unionfs_inode_info *inodeinfo;
struct super_block *sb = inode->i_sb;
int bindex, bstart, bend;
-   int fgen;
-   int err;
+   int fgen, err = 0;
 
unionfs_read_lock(sb);
/*
@@ -618,7 +617,7 @@ int unionfs_file_release(struct inode *inode, struct file 
*file)
 
if (lower_file) {
fput(lower_file);
-   branchput(inode->i_sb, bindex);
+   branchput(sb, bindex);
}
}
kfree(fileinfo->lower_files);
@@ -640,6 +639,7 @@ int unionfs_file_release(struct inode *inode, struct file 
*file)
fileinfo->rdstate = NULL;
}
kfree(fileinfo);
+
 out:
unionfs_read_unlock(sb);
return err;
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[GIT PULL -mm] Unionfs/fsstack/eCryptfs updates/cleanups/fixes

2007-09-02 Thread Josef 'Jeff' Sipek
The following is a series of patches related to Unionfs, which include three
small VFS/fsstack patches and one eCryptfs patch; the rest are Unionfs
patches.  The patches here represent several months of work and testing
under various conditions, especially low-memory, SMP, and preemption
situations with an assortment of lower systems: ext2/3/4, xfs, reiserfs,
nfs, jffs2, ramfs, tmpfs, cramfs, and squashfs.

You can pull from 'master' branch of
git://git.kernel.org/pub/scm/linux/kernel/git/jsipek/unionfs.git

As I already mentioned to Andrew, some of these patches should go into
Linus's tree, but the remainder depends on them.

Additionally, as Andrew said earlier today, let's figure out whether or not
Unionfs gets merged.


For Linus:
  VFS: export release_open_intent symbol
  VFS/fsstack: remove 3rd argument to fsstack_copy_attr_all
  VFS/fsstack: cpp endif comments

For Andrew:
  Unionfs: fixed compilation error
  Unionfs: do not use fsstack_copy_attr_all
  Unionfs: copyright corrections and updates
  Unionfs: cpp endif comments
  Unionfs: cache-coherency - update inode times
  Unionfs: cache-coherency - dentries
  Unionfs: cache-coherency - file flush
  Unionfs: cache-coherency and fixes for unionfs_rename
  Unionfs: documentation updates
  Unionfs: copyup updates
  Unionfs: file_revalidate updates
  Unionfs: implement f/async
  Unionfs: minor file_release updates
  Unionfs: interpose updates
  Unionfs: unionfs_ioctl bug fixes
  Unionfs: partial_lookup update
  Unionfs: lower nameidata support
  Unionfs: mmap fixes
  Unionfs: handling lower vfsmount fixes
  Unionfs: mount-time option parsing fix
  Unionfs: remove old nfsro option
  Unionfs: readonly branch test fix
  Unionfs: minor remount fixes
  Unionfs: extended attributes fixes
  Unionfs: use file f_path field
  Unionfs: assorted comment and style updates
  Unionfs: update unionfs version number
  Unionfs: debugging and validation of fan-out invariants
  Unionfs: unionfs_create rewrite


Josef 'Jeff' Sipek, on behalf of the Unionfs team.

[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Fw: 2.6.23-rc3-mm1 UnionFS "BUG: atomic counter underflow"

2007-09-02 Thread Josef 'Jeff' Sipek
On Sun, Sep 02, 2007 at 01:59:57PM -0700, Andrew Morton wrote:
> > On Sun, 2 Sep 2007 12:48:35 -0400 "Josef 'Jeff' Sipek" <[EMAIL PROTECTED]> 
> > wrote:
> > On Sun, Sep 02, 2007 at 04:56:34AM -0700, Andrew Morton wrote:
> > > 
> > > fyi..
> >  
> > I got a bunch of patches queued up that should fix a few things - quite
> > possibly this one too.
> > 
> > I want to push the patches to korg, but in the mix is a fs/stack.c change &
> > corresponding ecryptfs fix that should go to Linus's tree. The rest of the
> > patches depend on this change.
> > 
> > How do you want me to do this? I guess I'll just send all of them to lkml,
> > and say which ones should go where in the 00/xx mail.
> 
> Let's do that as a starting point. 

Alright, I'll try to spam the lists later today.

> Perhaps we can fast-track the ecryptfs fix into mainline if it fixes
> something there.  
 
Not necessary, they aren't bugfixes for fsstack/ecryptfs.

> I don't want to kep the unionfs tree hanging around forever.  We need to
> work out whether we want to merge it.

Agreed.

Josef 'Jeff' Sipek.

-- 
Reality is merely an illusion, albeit a very persistent one.
- Albert Einstein
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Fw: 2.6.23-rc3-mm1 UnionFS BUG: atomic counter underflow

2007-09-02 Thread Josef 'Jeff' Sipek
On Sun, Sep 02, 2007 at 01:59:57PM -0700, Andrew Morton wrote:
  On Sun, 2 Sep 2007 12:48:35 -0400 Josef 'Jeff' Sipek [EMAIL PROTECTED] 
  wrote:
  On Sun, Sep 02, 2007 at 04:56:34AM -0700, Andrew Morton wrote:
   
   fyi..
   
  I got a bunch of patches queued up that should fix a few things - quite
  possibly this one too.
  
  I want to push the patches to korg, but in the mix is a fs/stack.c change 
  corresponding ecryptfs fix that should go to Linus's tree. The rest of the
  patches depend on this change.
  
  How do you want me to do this? I guess I'll just send all of them to lkml,
  and say which ones should go where in the 00/xx mail.
 
 Let's do that as a starting point. 

Alright, I'll try to spam the lists later today.

 Perhaps we can fast-track the ecryptfs fix into mainline if it fixes
 something there.  
 
Not necessary, they aren't bugfixes for fsstack/ecryptfs.

 I don't want to kep the unionfs tree hanging around forever.  We need to
 work out whether we want to merge it.

Agreed.

Josef 'Jeff' Sipek.

-- 
Reality is merely an illusion, albeit a very persistent one.
- Albert Einstein
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[GIT PULL -mm] Unionfs/fsstack/eCryptfs updates/cleanups/fixes

2007-09-02 Thread Josef 'Jeff' Sipek
The following is a series of patches related to Unionfs, which include three
small VFS/fsstack patches and one eCryptfs patch; the rest are Unionfs
patches.  The patches here represent several months of work and testing
under various conditions, especially low-memory, SMP, and preemption
situations with an assortment of lower systems: ext2/3/4, xfs, reiserfs,
nfs, jffs2, ramfs, tmpfs, cramfs, and squashfs.

You can pull from 'master' branch of
git://git.kernel.org/pub/scm/linux/kernel/git/jsipek/unionfs.git

As I already mentioned to Andrew, some of these patches should go into
Linus's tree, but the remainder depends on them.

Additionally, as Andrew said earlier today, let's figure out whether or not
Unionfs gets merged.


For Linus:
  VFS: export release_open_intent symbol
  VFS/fsstack: remove 3rd argument to fsstack_copy_attr_all
  VFS/fsstack: cpp endif comments

For Andrew:
  Unionfs: fixed compilation error
  Unionfs: do not use fsstack_copy_attr_all
  Unionfs: copyright corrections and updates
  Unionfs: cpp endif comments
  Unionfs: cache-coherency - update inode times
  Unionfs: cache-coherency - dentries
  Unionfs: cache-coherency - file flush
  Unionfs: cache-coherency and fixes for unionfs_rename
  Unionfs: documentation updates
  Unionfs: copyup updates
  Unionfs: file_revalidate updates
  Unionfs: implement f/async
  Unionfs: minor file_release updates
  Unionfs: interpose updates
  Unionfs: unionfs_ioctl bug fixes
  Unionfs: partial_lookup update
  Unionfs: lower nameidata support
  Unionfs: mmap fixes
  Unionfs: handling lower vfsmount fixes
  Unionfs: mount-time option parsing fix
  Unionfs: remove old nfsro option
  Unionfs: readonly branch test fix
  Unionfs: minor remount fixes
  Unionfs: extended attributes fixes
  Unionfs: use file f_path field
  Unionfs: assorted comment and style updates
  Unionfs: update unionfs version number
  Unionfs: debugging and validation of fan-out invariants
  Unionfs: unionfs_create rewrite


Josef 'Jeff' Sipek, on behalf of the Unionfs team.

[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 16/32] Unionfs: minor file_release updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/commonfops.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 612207a..1050c49 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -593,8 +593,7 @@ int unionfs_file_release(struct inode *inode, struct file 
*file)
struct unionfs_inode_info *inodeinfo;
struct super_block *sb = inode-i_sb;
int bindex, bstart, bend;
-   int fgen;
-   int err;
+   int fgen, err = 0;
 
unionfs_read_lock(sb);
/*
@@ -618,7 +617,7 @@ int unionfs_file_release(struct inode *inode, struct file 
*file)
 
if (lower_file) {
fput(lower_file);
-   branchput(inode-i_sb, bindex);
+   branchput(sb, bindex);
}
}
kfree(fileinfo-lower_files);
@@ -640,6 +639,7 @@ int unionfs_file_release(struct inode *inode, struct file 
*file)
fileinfo-rdstate = NULL;
}
kfree(fileinfo);
+
 out:
unionfs_read_unlock(sb);
return err;
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 22/32] Unionfs: handling lower vfsmount fixes

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Properly increase/release lower vfsmounts.
Validate proper use of unionfs mntget/put.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/dentry.c |6 --
 fs/unionfs/inode.c  |   11 +++
 fs/unionfs/lookup.c |   11 ++-
 fs/unionfs/union.h  |   47 +++
 4 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
index c7bbeca..0be958f 100644
--- a/fs/unionfs/dentry.c
+++ b/fs/unionfs/dentry.c
@@ -450,9 +450,11 @@ static void unionfs_d_release(struct dentry *dentry)
bend = dbend(dentry);
for (bindex = bstart; bindex = bend; bindex++) {
dput(unionfs_lower_dentry_idx(dentry, bindex));
-   unionfs_mntput(dentry, bindex);
-
unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
+   /* NULL lower mnt is ok if this is a negative dentry */
+   if (!dentry-d_inode  !unionfs_lower_mnt_idx(dentry,bindex))
+   continue;
+   unionfs_mntput(dentry, bindex);
unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
}
/* free private data (unionfs_dentry_info) here */
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index a219a40..d6a79d5 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -222,8 +222,11 @@ out:
dput(wh_dentry);
kfree(name);
 
+   if (!err)
+   unionfs_postcopyup_setmnt(dentry);
unionfs_unlock_dentry(dentry);
unionfs_read_unlock(dentry-d_sb);
+
return err;
 }
 
@@ -563,8 +566,12 @@ out:
d_drop(dentry);
 
kfree(name);
+   if (!err)
+   unionfs_postcopyup_setmnt(dentry);
unionfs_unlock_dentry(dentry);
+
unionfs_read_unlock(dentry-d_sb);
+
return err;
 }
 
@@ -835,8 +842,12 @@ out:
 
kfree(name);
 
+   if (!err)
+   unionfs_postcopyup_setmnt(dentry);
unionfs_unlock_dentry(dentry);
+
unionfs_read_unlock(dentry-d_sb);
+
return err;
 }
 
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index 152d421..38ee21f 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -314,24 +314,25 @@ out_negative:
if (lookupmode == INTERPOSE_REVAL) {
if (dentry-d_inode)
UNIONFS_I(dentry-d_inode)-stale = 1;
-
goto out;
}
/* This should only happen if we found a whiteout. */
if (first_dentry_offset == -1) {
first_lower_dentry = lookup_one_len(name, lower_dir_dentry,
-namelen);
+   namelen);
first_dentry_offset = bindex;
if (IS_ERR(first_lower_dentry)) {
err = PTR_ERR(first_lower_dentry);
goto out;
}
-   
-   /* FIXME: the following line needs to be changed to allow
+
+   /*
+* FIXME: the following line needs to be changed to allow
 * mount-point crossing
 */
first_dentry = dentry;
-   first_lower_mnt = unionfs_mntget(dentry, bindex);
+   first_lower_mnt = unionfs_mntget(dentry-d_sb-s_root,
+bindex);
}
unionfs_set_lower_dentry_idx(dentry, first_dentry_offset,
 first_lower_dentry);
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 9f3e68a..33c2137 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -459,18 +459,49 @@ static inline void unlock_dir(struct dentry *dir)
 static inline struct vfsmount *unionfs_mntget(struct dentry *dentry,
  int bindex)
 {
-   BUG_ON(!dentry || bindex  0);
-
-   return mntget(unionfs_lower_mnt_idx(dentry, bindex));
+   struct vfsmount *mnt;
+
+   if (!dentry) {
+   if (bindex  0)
+   return NULL;
+   if (!dentry  bindex = 0) {
+   return NULL;
+   }
+   }
+   mnt = unionfs_lower_mnt_idx(dentry, bindex);
+   if (!mnt) {
+   if (bindex  0)
+   return NULL;
+   if (!mnt  bindex = 0) {
+   return NULL;
+   }
+   }
+   mnt = mntget(mnt);
+   return mnt;
 }
 
 static inline void unionfs_mntput(struct dentry *dentry, int bindex)
 {
-   if (!dentry)
-   return;
+   struct vfsmount *mnt;
+
+   if (!dentry) {
+   if (bindex  0)
+   return;
+   if (!dentry  bindex = 0) {
+   return;
+   }
+   }
+   mnt

[PATCH 02/32] VFS/fsstack: remove 3rd argument to fsstack_copy_attr_all

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Unionfs needs a special fan-out version of fsstack_copy_attr_all. A
single-level stackable file systems such as eCryptfs can therefore use a
simplified fsstack_copy_attr_all function; remove its 3rd argument, which
was never used by eCryptfs and was only used by Unionfs.

Acked-by: Michael Halcrow [EMAIL PROTECTED]
Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/ecryptfs/dentry.c |2 +-
 fs/ecryptfs/inode.c  |6 +++---
 fs/ecryptfs/main.c   |2 +-
 fs/stack.c   |   13 ++---
 include/linux/fs_stack.h |4 +---
 5 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
index cb20b96..a8c1686 100644
--- a/fs/ecryptfs/dentry.c
+++ b/fs/ecryptfs/dentry.c
@@ -62,7 +62,7 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, 
struct nameidata *nd)
struct inode *lower_inode =
ecryptfs_inode_to_lower(dentry-d_inode);
 
-   fsstack_copy_attr_all(dentry-d_inode, lower_inode, NULL);
+   fsstack_copy_attr_all(dentry-d_inode, lower_inode);
}
 out:
return rc;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 131954b..fc4c6cb 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -601,9 +601,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry 
*old_dentry,
lower_new_dir_dentry-d_inode, lower_new_dentry);
if (rc)
goto out_lock;
-   fsstack_copy_attr_all(new_dir, lower_new_dir_dentry-d_inode, NULL);
+   fsstack_copy_attr_all(new_dir, lower_new_dir_dentry-d_inode);
if (new_dir != old_dir)
-   fsstack_copy_attr_all(old_dir, lower_old_dir_dentry-d_inode, 
NULL);
+   fsstack_copy_attr_all(old_dir, lower_old_dir_dentry-d_inode);
 out_lock:
unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
dput(lower_new_dentry-d_parent);
@@ -961,7 +961,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct 
iattr *ia)
}
rc = notify_change(lower_dentry, ia);
 out:
-   fsstack_copy_attr_all(inode, lower_inode, NULL);
+   fsstack_copy_attr_all(inode, lower_inode);
return rc;
 }
 
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index a984972..cb349a4 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -151,7 +151,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct 
dentry *dentry,
d_add(dentry, inode);
else
d_instantiate(dentry, inode);
-   fsstack_copy_attr_all(inode, lower_inode, NULL);
+   fsstack_copy_attr_all(inode, lower_inode);
/* This size will be overwritten for real files w/ headers and
 * other metadata */
fsstack_copy_inode_size(inode, lower_inode);
diff --git a/fs/stack.c b/fs/stack.c
index 4368d4b..a548aac 100644
--- a/fs/stack.c
+++ b/fs/stack.c
@@ -30,8 +30,7 @@ EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
  * copy all attributes; get_nlinks is optional way to override the i_nlink
  * copying
  */
-void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
-  int (*get_nlinks)(struct inode *))
+void fsstack_copy_attr_all(struct inode *dest, const struct inode *src)
 {
dest-i_mode = src-i_mode;
dest-i_uid = src-i_uid;
@@ -42,14 +41,6 @@ void fsstack_copy_attr_all(struct inode *dest, const struct 
inode *src,
dest-i_ctime = src-i_ctime;
dest-i_blkbits = src-i_blkbits;
dest-i_flags = src-i_flags;
-
-   /*
-* Update the nlinks AFTER updating the above fields, because the
-* get_links callback may depend on them.
-*/
-   if (!get_nlinks)
-   dest-i_nlink = src-i_nlink;
-   else
-   dest-i_nlink = (*get_nlinks)(dest);
+   dest-i_nlink = src-i_nlink;
 }
 EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
index f3cd7f4..6b52faf 100644
--- a/include/linux/fs_stack.h
+++ b/include/linux/fs_stack.h
@@ -20,9 +20,7 @@
 #include linux/fs.h
 
 /* externs for fs/stack.c */
-extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
- int (*get_nlinks)(struct inode *));
-
+extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src);
 extern void fsstack_copy_inode_size(struct inode *dst,
const struct inode *src);
 
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 26/32] Unionfs: minor remount fixes

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/super.c |8 
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
index 1de41ea..339afab 100644
--- a/fs/unionfs/super.c
+++ b/fs/unionfs/super.c
@@ -736,7 +736,7 @@ out_no_change:
for (i=dbstart(sb-s_root); i=dbend(sb-s_root); i++) {
struct dentry *lower_dentry =
unionfs_lower_dentry_idx(sb-s_root, i);
-   atomic_inc(lower_dentry-d_inode-i_count);
+   igrab(lower_dentry-d_inode);
new_lower_inodes[i] = lower_dentry-d_inode;
}
/* 2. release reference on all older lower inodes */
@@ -758,11 +758,11 @@ out_no_change:
i = atomic_inc_return(UNIONFS_SB(sb)-generation);
atomic_set(UNIONFS_D(sb-s_root)-generation, i);
atomic_set(UNIONFS_I(sb-s_root-d_inode)-generation, i);
-
-   err = 0;/* reset to success */
-
if (!(*flags  MS_SILENT))
printk(unionfs: new generation number %d\n, i);
+   /* finally, update the root dentry's times */
+   unionfs_copy_attr_times(sb-s_root-d_inode);
+   err = 0;/* reset to success */
 
/*
 * The code above falls through to the next label, and releases the
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 11/32] Unionfs: cache-coherency and fixes for unionfs_rename

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/rename.c |   30 --
 1 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
index 4de984e..f8ea37a 100644
--- a/fs/unionfs/rename.c
+++ b/fs/unionfs/rename.c
@@ -457,18 +457,44 @@ int unionfs_rename(struct inode *old_dir, struct dentry 
*old_dentry,
}
}
err = do_unionfs_rename(old_dir, old_dentry, new_dir, new_dentry);
-
 out:
if (err)
/* clear the new_dentry stuff created */
d_drop(new_dentry);
-   else
+   else {
/*
 * force re-lookup since the dir on ro branch is not renamed,
 * and lower dentries still indicate the un-renamed ones.
 */
if (S_ISDIR(old_dentry-d_inode-i_mode))
atomic_dec(UNIONFS_D(old_dentry)-generation);
+   if (new_dentry-d_inode 
+   !S_ISDIR(new_dentry-d_inode-i_mode)) {
+   if (!unionfs_lower_inode(new_dentry-d_inode)) {
+   /*
+* If we get here, it means that no copyup
+* was needed, and that a file by the old
+* name already existing on the destination
+* branch; that file got renamed earlier in
+* this function, so all we need to do here
+* is set the lower inode.
+*/
+   struct inode *inode;
+   inode = unionfs_lower_inode(
+   old_dentry-d_inode);
+   igrab(inode);
+   unionfs_set_lower_inode_idx(
+   new_dentry-d_inode,
+   dbstart(new_dentry), inode);
+   }
+
+   }
+   /* if all of this renaming succeeded, update our times */
+   unionfs_copy_attr_times(old_dir);
+   unionfs_copy_attr_times(new_dir);
+   unionfs_copy_attr_times(old_dentry-d_inode);
+   unionfs_copy_attr_times(new_dentry-d_inode);
+   }
 
unionfs_unlock_dentry(new_dentry);
unionfs_unlock_dentry(old_dentry);
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 04/32] Unionfs: fixed compilation error

2007-09-02 Thread Josef 'Jeff' Sipek
From: Andrew Morton [EMAIL PROTECTED]

Signed-off-by: Andrew Morton [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 include/linux/mm.h |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index d823db0..aee99b6 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -20,6 +20,7 @@ struct anon_vma;
 struct file_ra_state;
 struct user_struct;
 struct writeback_control;
+struct super_block;
 
 #ifndef CONFIG_DISCONTIGMEM  /* Don't use mapnrs, do it properly */
 extern unsigned long max_mapnr;
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 08/32] Unionfs: cache-coherency - update inode times

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Part of cache-coherency support (as per OLS'07 talk and
Documentation/filesystems/unionfs/concepts.txt): update our inode time if
lower had changed.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/file.c   |7 +--
 fs/unionfs/inode.c  |   11 +++
 fs/unionfs/unlink.c |3 +++
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
index ad6821c..47b63f3 100644
--- a/fs/unionfs/file.c
+++ b/fs/unionfs/file.c
@@ -67,17 +67,20 @@ out:
unionfs_read_unlock(file-f_path.dentry-d_sb);
return err;
 }
-static ssize_t unionfs_write(struct file * file, const char __user * buf,
+
+static ssize_t unionfs_write(struct file *file, const char __user *buf,
 size_t count, loff_t *ppos)
 {
int err = 0;
 
unionfs_read_lock(file-f_path.dentry-d_sb);
-
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
 
err = do_sync_write(file, buf, count, ppos);
+   /* update our inode times upon a successful lower write */
+   if (err = 0)
+   unionfs_copy_attr_times(file-f_path.dentry-d_inode);
 
 out:
unionfs_read_unlock(file-f_path.dentry-d_sb);
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 9261bed..66614e3 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -245,6 +245,12 @@ static struct dentry *unionfs_lookup(struct inode *parent,
nd-dentry = path_save.dentry;
nd-mnt = path_save.mnt;
}
+   if (!IS_ERR(ret)) {
+   if (ret)
+   dentry = ret;
+   /* parent times may have changed */
+   unionfs_copy_attr_times(dentry-d_parent-d_inode);
+   }
 
unionfs_read_unlock(dentry-d_sb);
 
@@ -675,8 +681,11 @@ out:
 
kfree(name);
 
+   if (!err)
+   unionfs_copy_attr_times(dentry-d_inode);
unionfs_unlock_dentry(dentry);
unionfs_read_unlock(dentry-d_sb);
+
return err;
 }
 
@@ -1006,6 +1015,8 @@ static int unionfs_permission(struct inode *inode, int 
mask,
break;
}
}
+   /* sync times which may have changed (asynchronously) below */
+   unionfs_copy_attr_times(inode);
 
 out:
return err;
diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
index 822bffe..7ad19ec 100644
--- a/fs/unionfs/unlink.c
+++ b/fs/unionfs/unlink.c
@@ -41,6 +41,9 @@ static int unionfs_unlink_whiteout(struct inode *dir, struct 
dentry *dentry)
dget(lower_dentry);
if (!(err = is_robranch_super(dentry-d_sb, bindex)))
err = vfs_unlink(lower_dir_dentry-d_inode, lower_dentry);
+   /* if vfs_unlink succeeded, update our inode's times */
+   if (!err)
+   unionfs_copy_attr_times(dentry-d_inode);
dput(lower_dentry);
fsstack_copy_attr_times(dir, lower_dir_dentry-d_inode);
unlock_dir(lower_dir_dentry);
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 09/32] Unionfs: cache-coherency - dentries

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Utility functions to check if lower dentries/inodes are newer than upper
ones, and purging cached data if lower objects are newer.  Also passed flag
to our d_revalidate_chain, to tell it if the caller may be writing data or
just reading it.

[jsipek: changed purge_inode_data to take a struct inode]
Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/commonfops.c |2 +-
 fs/unionfs/dentry.c |  127 --
 fs/unionfs/inode.c  |   24 ++---
 fs/unionfs/rename.c |4 +-
 fs/unionfs/super.c  |2 +-
 fs/unionfs/union.h  |3 +-
 fs/unionfs/unlink.c |   12 +++-
 fs/unionfs/xattr.c  |8 ++--
 8 files changed, 155 insertions(+), 27 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 28cb4e9..0dc7492 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -287,7 +287,7 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
 * but not unhashed dentries.
 */
if (!d_deleted(dentry) 
-   !__unionfs_d_revalidate_chain(dentry, NULL)) {
+   !__unionfs_d_revalidate_chain(dentry, NULL, willwrite)) {
err = -ESTALE;
goto out_nofree;
}
diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
index 4a3c479..c7bbeca 100644
--- a/fs/unionfs/dentry.c
+++ b/fs/unionfs/dentry.c
@@ -35,7 +35,6 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
int positive = 0;
int locked = 0;
int interpose_flag;
-
struct nameidata lowernd; /* TODO: be gentler to the stack */
 
if (nd)
@@ -158,7 +157,7 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry,
|| !lower_dentry-d_op-d_revalidate)
continue;
if (!lower_dentry-d_op-d_revalidate(lower_dentry,
-  lowernd))
+ lowernd))
valid = 0;
}
 
@@ -184,10 +183,92 @@ out:
 }
 
 /*
+ * Determine if the lower inode objects have changed from below the unionfs
+ * inode.  Return 1 if changed, 0 otherwise.
+ */
+int is_newer_lower(const struct dentry *dentry)
+{
+   int bindex;
+   struct inode *inode;
+   struct inode *lower_inode;
+
+   /* ignore if we're called on semi-initialized dentries/inodes */
+   if (!dentry || !UNIONFS_D(dentry))
+   return 0;
+   inode = dentry-d_inode;
+   if (!inode || !UNIONFS_I(inode) ||
+   ibstart(inode)  0 || ibend(inode)  0)
+   return 0;
+
+   for (bindex = ibstart(inode); bindex = ibend(inode); bindex++) {
+   lower_inode = unionfs_lower_inode_idx(inode, bindex);
+   if (!lower_inode)
+   continue;
+   /*
+* We may want to apply other tests to determine if the
+* lower inode's data has changed, but checking for changed
+* ctime and mtime on the lower inode should be enough.
+*/
+   if (timespec_compare(inode-i_mtime,
+lower_inode-i_mtime)  0) {
+   printk(unionfs: new lower inode mtime 
+  (bindex=%d, name=%s)\n, bindex,
+  dentry-d_name.name);
+   return 1; /* mtime changed! */
+   }
+   if (timespec_compare(inode-i_ctime,
+lower_inode-i_ctime)  0) {
+   printk(unionfs: new lower inode ctime 
+  (bindex=%d, name=%s)\n, bindex,
+  dentry-d_name.name);
+   return 1; /* ctime changed! */
+   }
+   }
+   return 0;   /* default: lower is not newer */
+}
+
+/*
+ * Purge/remove/unmap all date pages of a unionfs inode.  This is called
+ * when the lower inode has changed, and we have to force processes to get
+ * the new data.
+ *
+ * XXX: Our implementation works in that as long as a user process will have
+ * caused Unionfs to be called, directly or indirectly, even to just do
+ * -d_revalidate; then we will have purged the current Unionfs data and the
+ * process will see the new data.  For example, a process that continually
+ * re-reads the same file's data will see the NEW data as soon as the lower
+ * file had changed, upon the next read(2) syscall (even if the file is
+ * still open!)  However, this doesn't work when the process re-reads the
+ * open file's data via mmap(2) (unless the user unmaps/closes the file and
+ * remaps/reopens it).  Once we respond to -readpage(s), then the kernel
+ * maps the page into the process's address space and there doesn't appear
+ * to be a way to force the kernel

[PATCH 20/32] Unionfs: lower nameidata support

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Create and free custom nameidata structures, and pass them to lower file
systems when needed via vfs_create.  (This code will get updated when/if
nameidata is split into an intent structure and a VFS-level only structure.)

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/copyup.c |8 ++-
 fs/unionfs/lookup.c |   58 +++
 fs/unionfs/rename.c |   15 +++-
 fs/unionfs/subr.c   |   14 ++-
 fs/unionfs/union.h  |2 +
 5 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
index 9c476cd..4c45790 100644
--- a/fs/unionfs/copyup.c
+++ b/fs/unionfs/copyup.c
@@ -177,19 +177,25 @@ static int __copyup_ndentry(struct dentry 
*old_lower_dentry,
run_sioq(__unionfs_mknod, args);
err = args.err;
} else if (S_ISREG(old_mode)) {
+   struct nameidata nd;
+   err = init_lower_nd(nd, LOOKUP_CREATE);
+   if (err  0)
+   goto out;
+   args.create.nd = nd;
args.create.parent = new_lower_parent_dentry-d_inode;
args.create.dentry = new_lower_dentry;
args.create.mode = old_mode;
-   args.create.nd = NULL;
 
run_sioq(__unionfs_create, args);
err = args.err;
+   release_lower_nd(nd, err);
} else {
printk(KERN_ERR unionfs: unknown inode type %d\n,
   old_mode);
BUG();
}
 
+out:
return err;
 }
 
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index d05daa5..152d421 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -564,3 +564,61 @@ void update_bstart(struct dentry *dentry)
unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
}
 }
+
+
+/*
+ * Initialize a nameidata structure (the intent part) we can pass to a lower
+ * file system.  Returns 0 on success or -error (only -ENOMEM possible).
+ * Inside that nd structure, this function may also return an allocated
+ * struct file (for open intents).  The caller, when done with this nd, must
+ * kfree the intent file (using release_lower_nd).
+ */
+int init_lower_nd(struct nameidata *nd, unsigned int flags)
+{
+   int err = 0;
+#ifdef ALLOC_LOWER_ND_FILE
+   /*
+* XXX: one day we may need to have the lower return an open file
+* for us.  It is not needed in 2.6.23-rc1 for nfs2/nfs3, but may
+* very well be needed for nfs4.
+*/
+   struct file *file;
+#endif /* ALLOC_LOWER_ND_FILE */
+
+   memset(nd, 0, sizeof(struct nameidata));
+
+   switch (flags) {
+   case LOOKUP_CREATE:
+   nd-flags = LOOKUP_CREATE;
+   nd-intent.open.flags = FMODE_READ | FMODE_WRITE | O_CREAT;
+#ifdef ALLOC_LOWER_ND_FILE
+   file = kzalloc(sizeof(struct file), GFP_KERNEL);
+   if (!file) {
+   err = -ENOMEM;
+   break; /* exit switch statement and thus return */
+   }
+   nd-intent.open.file = file;
+#endif /* ALLOC_LOWER_ND_FILE */
+   break;
+   default:
+   /*
+* We should never get here, for now.
+* We can add new cases here later on.
+*/
+   BUG();
+   break;
+   }
+
+   return err;
+}
+
+void release_lower_nd(struct nameidata *nd, int err)
+{
+   if (!nd-intent.open.file)
+   return;
+   if (!err)
+   release_open_intent(nd);
+#ifdef ALLOC_LOWER_ND_FILE
+   kfree(nd-intent.open.file);
+#endif /* ALLOC_LOWER_ND_FILE */
+}
diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
index acf829a..a02d678 100644
--- a/fs/unionfs/rename.c
+++ b/fs/unionfs/rename.c
@@ -256,10 +256,20 @@ static int do_unionfs_rename(struct inode *old_dir,
 */
if ((old_bstart != old_bend) || (do_copyup != -1)) {
struct dentry *lower_parent;
-   BUG_ON(!wh_old || wh_old-d_inode || bwh_old  0);
+   struct nameidata nd;
+   if (!wh_old || wh_old-d_inode || bwh_old  0) {
+   printk(KERN_ERR unionfs: rename error 
+  (wh_old=%p/%p bwh_old=%d)\n, wh_old,
+  (wh_old ? wh_old-d_inode : NULL), bwh_old);
+   err = -EIO;
+   goto out;
+   }
+   err = init_lower_nd(nd, LOOKUP_CREATE);
+   if (err  0)
+   goto out;
lower_parent = lock_parent(wh_old);
local_err = vfs_create(lower_parent-d_inode, wh_old, S_IRUGO,
-  NULL);
+  nd);
unlock_dir(lower_parent

[PATCH 01/32] VFS: export release_open_intent symbol

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/namei.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index a83160a..b2b7c8e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -374,6 +374,7 @@ void release_open_intent(struct nameidata *nd)
else
fput(nd-intent.open.file);
 }
+EXPORT_SYMBOL(release_open_intent);
 
 static inline struct dentry *
 do_revalidate(struct dentry *dentry, struct nameidata *nd)
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 06/32] Unionfs: copyright corrections and updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/mmap.c |2 +-
 fs/unionfs/sioq.c |   13 +++--
 fs/unionfs/sioq.h |   13 +++--
 3 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c
index e03ca00..969fd16 100644
--- a/fs/unionfs/mmap.c
+++ b/fs/unionfs/mmap.c
@@ -10,7 +10,7 @@
  * Copyright (c) 2003  Puja Gupta
  * Copyright (c) 2003  Harikesavan Krishnan
  * Copyright (c) 2003-2007 Stony Brook University
- * Copyright (c) 2003-2007 The Research Foundation of State University of New 
York
+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/fs/unionfs/sioq.c b/fs/unionfs/sioq.c
index 575f08d..2a8c88e 100644
--- a/fs/unionfs/sioq.c
+++ b/fs/unionfs/sioq.c
@@ -1,10 +1,11 @@
 /*
- * Copyright (c) 2003-2007 Erez Zadok
- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
- * Copyright (c) 2005-2006 Junjiro Okajima
- * Copyright (c) 2004-2006 David P. Quigley
- * Copyright (c) 2003-2007 Stony Brook University
- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+ * Copyright (c) 2006-2007 Erez Zadok
+ * Copyright (c) 2006  Charles P. Wright
+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
+ * Copyright (c) 2006  Junjiro Okajima
+ * Copyright (c) 2006  David P. Quigley
+ * Copyright (c) 2006-2007 Stony Brook University
+ * Copyright (c) 2006-2007 The Research Foundation of SUNY
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
index 6d0d01f..bedd7af 100644
--- a/fs/unionfs/sioq.h
+++ b/fs/unionfs/sioq.h
@@ -1,10 +1,11 @@
 /*
- * Copyright (c) 2003-2007 Erez Zadok
- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
- * Copyright (c) 2005-2006 Junjiro Okajima
- * Copyright (c) 2004-2006 David P. Quigley
- * Copyright (c) 2003-2007 Stony Brook University
- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+ * Copyright (c) 2006-2007 Erez Zadok
+ * Copyright (c) 2006  Charles P. Wright
+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
+ * Copyright (c) 2006  Junjiro Okajima
+ * Copyright (c) 2006  David P. Quigley
+ * Copyright (c) 2006-2007 Stony Brook University
+ * Copyright (c) 2006-2007 The Research Foundation of SUNY
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 25/32] Unionfs: readonly branch test fix

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Bug fix to test if a lower branch is readonly, even when given negative
dentries.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/union.h |   19 ++-
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 33c2137..26d886e 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -396,14 +396,23 @@ static inline int is_robranch_super(const struct 
super_block *sb, int index)
 /* Is this file on a read-only branch? */
 static inline int is_robranch_idx(const struct dentry *dentry, int index)
 {
-   int err = 0;
+   struct super_block *lower_sb;
 
BUG_ON(index  0);
 
-   if ((!(branchperms(dentry-d_sb, index)  MAY_WRITE)) ||
-   IS_RDONLY(unionfs_lower_dentry_idx(dentry, index)-d_inode))
-   err = -EROFS;
-   return err;
+   if (!(branchperms(dentry-d_sb, index)  MAY_WRITE))
+   return -EROFS;
+
+   lower_sb = unionfs_lower_super_idx(dentry-d_sb, index);
+   BUG_ON(lower_sb == NULL);
+   /*
+* test sb flags directly, not IS_RDONLY(lower_inode) because the
+* lower_dentry could be a negative.
+*/
+   if (lower_sb-s_flags  MS_RDONLY)
+   return -EROFS;
+
+   return 0;
 }
 
 static inline int is_robranch(const struct dentry *dentry)
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 31/32] Unionfs: debugging and validation of fan-out invariants

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Introduce debugging functionality, Makefile support to turn it on at compile
time, and hooks in the main code to verify fan-out invariants.  This is very
similar to how other file systems provide debugging functionality.  This
code has been very useful in detecting and fixing problems, especially when
stacking on top of assorted file systems.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/Kconfig  |6 +
 fs/unionfs/Makefile |2 +
 fs/unionfs/commonfops.c |   17 ++
 fs/unionfs/copyup.c |2 +
 fs/unionfs/debug.c  |  502 +++
 fs/unionfs/dentry.c |4 +
 fs/unionfs/file.c   |   19 ++-
 fs/unionfs/inode.c  |   22 ++
 fs/unionfs/mmap.c   |5 +
 fs/unionfs/rename.c |4 +
 fs/unionfs/super.c  |3 +
 fs/unionfs/union.h  |  105 +++---
 fs/unionfs/unlink.c |6 +
 fs/unionfs/xattr.c  |4 +
 14 files changed, 668 insertions(+), 33 deletions(-)
 create mode 100644 fs/unionfs/debug.c

diff --git a/fs/Kconfig b/fs/Kconfig
index d53d8ca..0c58d02 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1063,6 +1063,12 @@ config UNION_FS_XATTR
 
  If unsure, say N.
 
+config UNION_FS_DEBUG
+   bool Debug Unionfs
+   depends on UNION_FS
+   help
+ If you say Y here, you can turn on debugging output from Unionfs.
+
 endmenu
 
 menu Miscellaneous filesystems
diff --git a/fs/unionfs/Makefile b/fs/unionfs/Makefile
index 78be3e7..38fed90 100644
--- a/fs/unionfs/Makefile
+++ b/fs/unionfs/Makefile
@@ -5,3 +5,5 @@ unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \
lookup.o commonfops.o dirfops.o sioq.o mmap.o
 
 unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o
+
+unionfs-$(CONFIG_UNION_FS_DEBUG) += debug.o
diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 341b6f2..724128d 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -91,6 +91,8 @@ retry:
unlock_dir(lower_dir_dentry);
 
 out:
+   if (!err)
+   unionfs_check_dentry(dentry);
return err;
 }
 
@@ -247,6 +249,8 @@ static int do_delayed_copyup(struct file *file)
 
BUG_ON(!S_ISREG(dentry-d_inode-i_mode));
 
+   unionfs_check_file(file);
+   unionfs_check_dentry(dentry);
for (bindex = bstart - 1; bindex = 0; bindex--) {
if (!d_deleted(dentry))
err = copyup_file(parent_inode, file, bstart,
@@ -286,6 +290,8 @@ static int do_delayed_copyup(struct file *file)
ibend(dentry-d_inode) = ibstart(dentry-d_inode);
 
 out:
+   unionfs_check_file(file);
+   unionfs_check_dentry(dentry);
return err;
 }
 
@@ -399,6 +405,8 @@ out:
kfree(UNIONFS_F(file)-saved_branch_ids);
}
 out_nofree:
+   if (!err)
+   unionfs_check_file(file);
unionfs_unlock_dentry(dentry);
return err;
 }
@@ -576,6 +584,11 @@ out:
}
 out_nofree:
unionfs_read_unlock(inode-i_sb);
+   unionfs_check_inode(inode);
+   if (!err) {
+   unionfs_check_file(file);
+   unionfs_check_dentry(file-f_path.dentry-d_parent);
+   }
return err;
 }
 
@@ -601,6 +614,7 @@ int unionfs_file_release(struct inode *inode, struct file 
*file)
 */
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
+   unionfs_check_file(file);
fileinfo = UNIONFS_F(file);
BUG_ON(file-f_path.dentry-d_inode != inode);
inodeinfo = UNIONFS_I(inode);
@@ -764,6 +778,7 @@ long unionfs_ioctl(struct file *file, unsigned int cmd, 
unsigned long arg)
 
 out:
unionfs_read_unlock(file-f_path.dentry-d_sb);
+   unionfs_check_file(file);
return err;
 }
 
@@ -778,6 +793,7 @@ int unionfs_flush(struct file *file, fl_owner_t id)
 
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
+   unionfs_check_file(file);
 
if (!atomic_dec_and_test(UNIONFS_I(dentry-d_inode)-totalopens))
goto out;
@@ -814,5 +830,6 @@ out_lock:
unionfs_unlock_dentry(dentry);
 out:
unionfs_read_unlock(dentry-d_sb);
+   unionfs_check_file(file);
return err;
 }
diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
index 36f751e..23ac4c8 100644
--- a/fs/unionfs/copyup.c
+++ b/fs/unionfs/copyup.c
@@ -532,6 +532,8 @@ out_free:
unionfs_postcopyup_setmnt(dentry);
/* sync inode times from copied-up inode to our inode */
unionfs_copy_attr_times(dentry-d_inode);
+   unionfs_check_inode(dir);
+   unionfs_check_dentry(dentry);
 out:
return err;
 }
diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c
new file mode 100644
index 000..f678534
--- /dev/null
+++ b/fs/unionfs/debug.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 2003-2007 Erez Zadok
+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+ * Copyright (c) 2003-2007

[PATCH 24/32] Unionfs: remove old nfsro option

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Ensure that a branch set as 'ro' behaves like a real readonly mounted lower
file system.  This allows us to remove the old 'nfsro' option.  Now unionfs
handles even an readonly exported NFS file system, which was mounted on the
client in readwrite mode.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/inode.c   |   48 ++---
 include/linux/union_fs.h |3 --
 2 files changed, 23 insertions(+), 28 deletions(-)

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index d6a79d5..4574fbe 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -948,47 +948,44 @@ static void unionfs_put_link(struct dentry *dentry, 
struct nameidata *nd,
  * Basically copied from the kernel vfs permission(), but we've changed
  * the following:
  *   (1) the IS_RDONLY check is skipped, and
- *   (2) if you set the mount option `mode=nfsro', we assume that -EACCES
- *   means that the export is read-only and we should check standard Unix
- *   permissions.  This means that NFS ACL checks (or other advanced
- *   permission features) are bypassed. Note however, that we do call
- *   security_inode_permission, and therefore security inside SELinux, etc.
- *   are performed.
+ *   (2) We return 0 (success) if the non-leftmost branch is mounted
+ *   readonly, to allow copyup to work.
+ *   (3) we do call security_inode_permission, and therefore security inside
+ *   SELinux, etc. are performed.
  */
-static int inode_permission(struct inode *inode, int mask,
+static int inode_permission(struct super_block *sb, struct inode *inode, int 
mask,
struct nameidata *nd, int bindex)
 {
int retval, submask;
 
if (mask  MAY_WRITE) {
+   umode_t mode = inode-i_mode;
/* The first branch is allowed to be really readonly. */
-   if (bindex == 0) {
-   umode_t mode = inode-i_mode;
-   if (IS_RDONLY(inode) 
-   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
-   return -EROFS;
-   }
+   if (bindex == 0 
+   IS_RDONLY(inode) 
+   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+   return -EROFS;
/*
 * Nobody gets write access to an immutable file.
 */
if (IS_IMMUTABLE(inode))
return -EACCES;
+   /*
+* For all other branches than the first one, we ignore
+* EROFS or if the branch is mounted as readonly, to let
+* copyup take place.
+*/
+   if (bindex  0 
+   is_robranch_super(sb, bindex) 
+   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+   return 0;
}
 
/* Ordinary permission routines do not understand MAY_APPEND. */
submask = mask  ~MAY_APPEND;
-   if (inode-i_op  inode-i_op-permission) {
+   if (inode-i_op  inode-i_op-permission)
retval = inode-i_op-permission(inode, submask, nd);
-   if ((retval == -EACCES)  (submask  MAY_WRITE) 
-   (!strcmp(nfs, (inode)-i_sb-s_type-name)) 
-   (nd)  (nd-mnt)  (nd-mnt-mnt_sb)) {
-   int perms;
-   perms = branchperms(nd-mnt-mnt_sb, bindex);
-   if (perms  MAY_NFSRO)
-   retval = generic_permission(inode, submask,
-   NULL);
-   }
-   } else
+   else
retval = generic_permission(inode, submask, NULL);
 
if (retval  retval != -EROFS) /* ignore EROFS */
@@ -1046,7 +1043,8 @@ static int unionfs_permission(struct inode *inode, int 
mask,
 * We use our own special version of permission, such that
 * only the first branch returns -EROFS.
 */
-   err = inode_permission(lower_inode, mask, nd, bindex);
+   err = inode_permission(inode-i_sb, lower_inode, mask, nd,
+  bindex);
 
/*
 * The permissions are an intersection of the overall directory
diff --git a/include/linux/union_fs.h b/include/linux/union_fs.h
index 223ccab..9bc4e3b 100644
--- a/include/linux/union_fs.h
+++ b/include/linux/union_fs.h
@@ -22,8 +22,5 @@
 /* We don't support normal remount, but unionctl uses it. */
 # define UNIONFS_REMOUNT_MAGIC 0x4a5a4380
 
-/* should be at least LAST_USED_UNIONFS_PERMISSION1 */
-#define MAY_NFSRO  16
-
 #endif /* _LINUX_UNIONFS_H */
 
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body

[PATCH 28/32] Unionfs: use file f_path field

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Start using file-f_path.dentry instead of file-f_dentry

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/commonfops.c |   42 --
 fs/unionfs/dirfops.c|6 +++---
 fs/unionfs/mmap.c   |5 ++---
 fs/unionfs/rdstate.c|2 +-
 4 files changed, 26 insertions(+), 29 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index eee68b8..341b6f2 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -158,7 +158,7 @@ static int open_all_files(struct file *file)
int bindex, bstart, bend, err = 0;
struct file *lower_file;
struct dentry *lower_dentry;
-   struct dentry *dentry = file-f_dentry;
+   struct dentry *dentry = file-f_path.dentry;
struct super_block *sb = dentry-d_sb;
 
bstart = dbstart(dentry);
@@ -193,8 +193,7 @@ static int open_highest_file(struct file *file, int 
willwrite)
int bindex, bstart, bend, err = 0;
struct file *lower_file;
struct dentry *lower_dentry;
-
-   struct dentry *dentry = file-f_dentry;
+   struct dentry *dentry = file-f_path.dentry;
struct inode *parent_inode = dentry-d_parent-d_inode;
struct super_block *sb = dentry-d_sb;
size_t inode_size = dentry-d_inode-i_size;
@@ -302,10 +301,9 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
int sbgen, fgen, dgen;
int bstart, bend;
int size;
-
int err = 0;
 
-   dentry = file-f_dentry;
+   dentry = file-f_path.dentry;
unionfs_lock_dentry(dentry);
sb = dentry-d_sb;
 
@@ -412,20 +410,20 @@ static int __open_dir(struct inode *inode, struct file 
*file)
struct file *lower_file;
int bindex, bstart, bend;
 
-   bstart = fbstart(file) = dbstart(file-f_dentry);
-   bend = fbend(file) = dbend(file-f_dentry);
+   bstart = fbstart(file) = dbstart(file-f_path.dentry);
+   bend = fbend(file) = dbend(file-f_path.dentry);
 
for (bindex = bstart; bindex = bend; bindex++) {
lower_dentry =
-   unionfs_lower_dentry_idx(file-f_dentry, bindex);
+   unionfs_lower_dentry_idx(file-f_path.dentry, bindex);
if (!lower_dentry)
continue;
 
dget(lower_dentry);
-   unionfs_mntget(file-f_dentry, bindex);
+   unionfs_mntget(file-f_path.dentry, bindex);
lower_file = dentry_open(lower_dentry,
-unionfs_lower_mnt_idx(file-f_dentry,
-   bindex),
+
unionfs_lower_mnt_idx(file-f_path.dentry,
+  bindex),
 file-f_flags);
if (IS_ERR(lower_file))
return PTR_ERR(lower_file);
@@ -450,17 +448,17 @@ static int __open_file(struct inode *inode, struct file 
*file)
int lower_flags;
int bindex, bstart, bend;
 
-   lower_dentry = unionfs_lower_dentry(file-f_dentry);
+   lower_dentry = unionfs_lower_dentry(file-f_path.dentry);
lower_flags = file-f_flags;
 
-   bstart = fbstart(file) = dbstart(file-f_dentry);
-   bend = fbend(file) = dbend(file-f_dentry);
+   bstart = fbstart(file) = dbstart(file-f_path.dentry);
+   bend = fbend(file) = dbend(file-f_path.dentry);
 
/*
 * check for the permission for lower file.  If the error is
 * COPYUP_ERR, copyup the file.
 */
-   if (lower_dentry-d_inode  is_robranch(file-f_dentry)) {
+   if (lower_dentry-d_inode  is_robranch(file-f_path.dentry)) {
/*
 * if the open will change the file, copy it up otherwise
 * defer it.
@@ -472,7 +470,7 @@ static int __open_file(struct inode *inode, struct file 
*file)
/* copyup the file */
for (bindex = bstart - 1; bindex = 0; bindex--) {
err = copyup_file(
-   file-f_dentry-d_parent-d_inode,
+   file-f_path.dentry-d_parent-d_inode,
file, bstart, bindex, size);
if (!err)
break;
@@ -488,10 +486,10 @@ static int __open_file(struct inode *inode, struct file 
*file)
 * dentry_open will decrement mnt refcnt if err.
 * otherwise fput() will do an mntput() for us upon file close.
 */
-   unionfs_mntget(file-f_dentry, bstart);
+   unionfs_mntget(file-f_path.dentry, bstart);
lower_file =
dentry_open(lower_dentry,
-   unionfs_lower_mnt_idx

[PATCH 13/32] Unionfs: copyup updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Fixes, updates, and better documentation for the file-copyup functionality.
Include two additional utility functions useful for copyup code callers.
Parent directory copyup updates: create_parents now takes a string name
instead of the whole dentry.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/commonfops.c |  135 +++
 fs/unionfs/copyup.c |  348 +++---
 fs/unionfs/inode.c  |   33 --
 fs/unionfs/rename.c |   26 +++--
 fs/unionfs/subr.c   |4 +-
 fs/unionfs/union.h  |   11 +-
 fs/unionfs/unlink.c |2 +
 7 files changed, 338 insertions(+), 221 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index edb52c0..64bd0bd 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -31,7 +31,6 @@ static int copyup_deleted_file(struct file *file, struct 
dentry *dentry,
const int countersize = sizeof(counter) * 2;
const int nlen = sizeof(.unionfs) + i_inosize + countersize - 1;
char name[nlen + 1];
-
int err;
struct dentry *tmp_dentry = NULL;
struct dentry *lower_dentry;
@@ -42,7 +41,6 @@ static int copyup_deleted_file(struct file *file, struct 
dentry *dentry,
sprintf(name, .unionfs%*.*lx,
i_inosize, i_inosize, lower_dentry-d_inode-i_ino);
 
-retry:
/*
 * Loop, looking for an unused temp name to copyup to.
 *
@@ -52,6 +50,7 @@ retry:
 * the name exists in the dest branch, but it'd be nice to catch it
 * sooner than later.
 */
+retry:
tmp_dentry = NULL;
do {
char *suffix = name + nlen - countersize;
@@ -73,14 +72,20 @@ retry:
dput(tmp_dentry);
 
err = copyup_named_file(dentry-d_parent-d_inode, file, name, bstart,
-   bindex, file-f_dentry-d_inode-i_size);
-   if (err == -EEXIST)
-   goto retry;
-   else if (err)
+   bindex, file-f_path.dentry-d_inode-i_size);
+   if (err) {
+   if (err == -EEXIST)
+   goto retry;
goto out;
+   }
 
/* bring it to the same state as an unlinked file */
lower_dentry = unionfs_lower_dentry_idx(dentry, dbstart(dentry));
+   if (!unionfs_lower_inode_idx(dentry-d_inode, bindex)) {
+   atomic_inc(lower_dentry-d_inode-i_count);
+   unionfs_set_lower_inode_idx(dentry-d_inode, bindex,
+   lower_dentry-d_inode);
+   }
lower_dir_dentry = lock_parent(lower_dentry);
err = vfs_unlink(lower_dir_dentry-d_inode, lower_dentry);
unlock_dir(lower_dir_dentry);
@@ -96,48 +101,52 @@ out:
 static void cleanup_file(struct file *file)
 {
int bindex, bstart, bend;
-   struct file **lf;
-   struct super_block *sb = file-f_dentry-d_sb;
+   struct file **lower_files;
+   struct file *lower_file;
+   struct super_block *sb = file-f_path.dentry-d_sb;
 
-   lf = UNIONFS_F(file)-lower_files;
+   lower_files = UNIONFS_F(file)-lower_files;
bstart = fbstart(file);
bend = fbend(file);
 
for (bindex = bstart; bindex = bend; bindex++) {
-   if (unionfs_lower_file_idx(file, bindex)) {
-   /*
-* Find new index of matching branch with an open
-* file, since branches could have been added or
-* deleted causing the one with open files to shift.
-*/
-   int i;  /* holds (possibly) updated branch index */
-   int old_bid;
-
-   old_bid = UNIONFS_F(file)-saved_branch_ids[bindex];
-   i = branch_id_to_idx(sb, old_bid);
-   if (i  0)
-   printk(KERN_ERR unionfs: no superblock for 
-  file %p\n, file);
-   else {
-   /* decrement count of open files */
-   branchput(sb, i);
-   /*
-* fput will perform an mntput for us on the
-* correct branch.  Although we're using the
-* file's old branch configuration, bindex,
-* which is the old index, correctly points
-* to the right branch in the file's branch
-* list.  In other words, we're going to
-* mntput the correct branch even if
-* branches have been added/removed.
-*/
-   fput(unionfs_lower_file_idx

[PATCH 07/32] Unionfs: cpp endif comments

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Add comments to #endif's to help clarify code.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/copyup.c |2 +-
 fs/unionfs/inode.c  |4 ++--
 fs/unionfs/sioq.h   |2 +-
 fs/unionfs/union.h  |2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
index cc7a816..410ce07 100644
--- a/fs/unionfs/copyup.c
+++ b/fs/unionfs/copyup.c
@@ -433,7 +433,7 @@ static int copyup_named_dentry(struct inode *dir, struct 
dentry *dentry,
/* Selinux uses extended attributes for permissions. */
if ((err = copyup_xattrs(old_lower_dentry, new_lower_dentry)))
goto out_unlink;
-#endif
+#endif /* CONFIG_UNION_FS_XATTR */
 
/* do not allow files getting deleted to be re-interposed */
if (!d_deleted(dentry))
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index cbbde6f..9261bed 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -1122,7 +1122,7 @@ struct inode_operations unionfs_dir_iops = {
.getxattr   = unionfs_getxattr,
.removexattr= unionfs_removexattr,
.listxattr  = unionfs_listxattr,
-#endif
+#endif /* CONFIG_UNION_FS_XATTR */
 };
 
 struct inode_operations unionfs_main_iops = {
@@ -1133,5 +1133,5 @@ struct inode_operations unionfs_main_iops = {
.getxattr   = unionfs_getxattr,
.removexattr= unionfs_removexattr,
.listxattr  = unionfs_listxattr,
-#endif
+#endif /* CONFIG_UNION_FS_XATTR */
 };
diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
index bedd7af..afb71ee 100644
--- a/fs/unionfs/sioq.h
+++ b/fs/unionfs/sioq.h
@@ -89,4 +89,4 @@ extern void __unionfs_unlink(struct work_struct *work);
 extern void __delete_whiteouts(struct work_struct *work);
 extern void __is_opaque_dir(struct work_struct *work);
 
-#endif /* _SIOQ_H */
+#endif /* not _SIOQ_H */
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 2a8f763..b7e5a93 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -419,7 +419,7 @@ static inline int is_robranch(const struct dentry *dentry)
 
 #ifndef DEFAULT_POLLMASK
 #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
-#endif
+#endif /* not DEFAULT_POLLMASK */
 
 /*
  * EXTERNALS:
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 14/32] Unionfs: file_revalidate updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Correctly revalidate a file and account for lower mnts, even when branches
are updated or inserted.  Better info upon file copyup.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/commonfops.c |   25 +
 1 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 64bd0bd..612207a 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -333,6 +333,9 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
 */
if (!d_deleted(dentry) 
(sbgen  fgen || dbstart(dentry) != fbstart(file))) {
+   /* save orig branch ID */
+   int orig_brid = 
UNIONFS_F(file)-saved_branch_ids[fbstart(file)];
+
/* First we throw out the existing files. */
cleanup_file(file);
 
@@ -359,22 +362,36 @@ int unionfs_file_revalidate(struct file *file, int 
willwrite)
if (err)
goto out;
} else {
+   int new_brid;
/* We only open the highest priority branch. */
err = open_highest_file(file, willwrite);
if (err)
goto out;
+   new_brid = UNIONFS_F(file)-
+ saved_branch_ids[fbstart(file)];
+   if (new_brid != orig_brid  sbgen  fgen) {
+   /*
+* If we re-opened the file on a different
+* branch than the original one, and this
+* was due to a new branch inserted, then
+* update the mnt counts of the old and new
+* branches accordingly.
+*/
+   unionfs_mntget(dentry, bstart);
+   unionfs_mntput(sb-s_root,
+  branch_id_to_idx(sb, orig_brid));
+   }
}
atomic_set(UNIONFS_F(file)-generation,
-  atomic_read(UNIONFS_I(dentry-d_inode)-
-  generation));
+  
atomic_read(UNIONFS_I(dentry-d_inode)-generation));
}
 
/* Copyup on the first write to a file on a readonly branch. */
if (willwrite  IS_WRITE_FLAG(file-f_flags) 
!IS_WRITE_FLAG(unionfs_lower_file(file)-f_flags) 
is_robranch(dentry)) {
-   printk(KERN_DEBUG unionfs: Doing delayed copyup of a 
-  read-write file on a read-only branch.\n);
+   printk(KERN_DEBUG unionfs: do delay copyup of \%s\\n,
+  dentry-d_name.name);
err = do_delayed_copyup(file);
}
 
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 23/32] Unionfs: mount-time option parsing fix

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/main.c |9 ++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index bc5c105..ce08d96 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -337,8 +337,12 @@ static int parse_dirs_option(struct super_block *sb, 
struct unionfs_dentry_info
int perms;
char *mode = strchr(name, '=');
 
-   if (!name || !*name)
+   if (!name)
continue;
+   if (!*name) {   /* bad use of ':' (extra colons) */
+   err = -EINVAL;
+   goto out;
+   }
 
branches++;
 
@@ -404,10 +408,9 @@ static int parse_dirs_option(struct super_block *sb, 
struct unionfs_dentry_info
 * branch-overlapping test.
 */
for (i = 0; i  branches; i++) {
+   dent1 = lower_root_info-lower_paths[i].dentry;
for (j = i + 1; j  branches; j++) {
-   dent1 = lower_root_info-lower_paths[i].dentry;
dent2 = lower_root_info-lower_paths[j].dentry;
-
if (is_branch_overlap(dent1, dent2)) {
printk(KERN_WARNING unionfs: branches %d and 
   %d overlap\n, i, j);
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 18/32] Unionfs: unionfs_ioctl bug fixes

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Properly update lower objects, and release lower mnts upon ioctl success or
failure.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/commonfops.c |   25 +++--
 1 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 1050c49..eee68b8 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -684,12 +684,15 @@ static int unionfs_ioctl_queryfile(struct file *file, 
unsigned int cmd,
 {
int err = 0;
fd_set branchlist;
-
int bstart = 0, bend = 0, bindex = 0;
+   int orig_bstart, orig_bend;
struct dentry *dentry, *lower_dentry;
+   struct vfsmount *mnt;
 
-   dentry = file-f_dentry;
+   dentry = file-f_path.dentry;
unionfs_lock_dentry(dentry);
+   orig_bstart = dbstart(dentry);
+   orig_bend = dbend(dentry);
if ((err = unionfs_partial_lookup(dentry)))
goto out;
bstart = dbstart(dentry);
@@ -703,7 +706,25 @@ static int unionfs_ioctl_queryfile(struct file *file, 
unsigned int cmd,
continue;
if (lower_dentry-d_inode)
FD_SET(bindex, branchlist);
+   /* purge any lower objects after partial_lookup */
+   if (bindex  orig_bstart || bindex  orig_bend) {
+   dput(lower_dentry);
+   unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
+   iput(unionfs_lower_inode_idx(dentry-d_inode, bindex));
+   unionfs_set_lower_inode_idx(dentry-d_inode, bindex,
+   NULL);
+   mnt = unionfs_lower_mnt_idx(dentry, bindex);
+   if (!mnt)
+   continue;
+   unionfs_mntput(dentry, bindex);
+   unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
+   }
}
+   /* restore original dentry's offsets */
+   set_dbstart(dentry, orig_bstart);
+   set_dbend(dentry, orig_bend);
+   ibstart(dentry-d_inode) = orig_bstart;
+   ibend(dentry-d_inode) = orig_bend;
 
err = copy_to_user((void __user *)arg, branchlist, sizeof(fd_set));
if (err)
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 15/32] Unionfs: implement f/async

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Unionfs needs its own fsync and fasync instead of calling the generic
file_fsync, because it may have to sync multiple writable lower branches
(not just one).  This also allows Unionfs to compile with CONFIG_BLOCK=n.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/dirfops.c |2 +
 fs/unionfs/file.c|   91 +-
 fs/unionfs/union.h   |3 ++
 3 files changed, 95 insertions(+), 1 deletions(-)

diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
index 8503411..0e93bd7 100644
--- a/fs/unionfs/dirfops.c
+++ b/fs/unionfs/dirfops.c
@@ -273,4 +273,6 @@ struct file_operations unionfs_dir_fops = {
.open   = unionfs_open,
.release= unionfs_file_release,
.flush  = unionfs_flush,
+   .fsync  = unionfs_fsync,
+   .fasync = unionfs_fasync,
 };
diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
index 47b63f3..0555b6c 100644
--- a/fs/unionfs/file.c
+++ b/fs/unionfs/file.c
@@ -135,6 +135,94 @@ out:
return err;
 }
 
+int unionfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+   int bindex, bstart, bend;
+   struct file *lower_file;
+   struct dentry *lower_dentry;
+   struct inode *lower_inode, *inode;
+   int err = -EINVAL;
+
+   unionfs_read_lock(file-f_path.dentry-d_sb);
+   if ((err = unionfs_file_revalidate(file, 1)))
+   goto out;
+
+   bstart = fbstart(file);
+   bend = fbend(file);
+   if (bstart  0 || bend  0)
+   goto out;
+
+   inode = dentry-d_inode;
+   if (!inode) {
+   printk(KERN_ERR
+  unionfs: null lower inode in unionfs_fsync\n);
+   goto out;
+   }
+   for (bindex = bstart; bindex = bend; bindex++) {
+   lower_inode = unionfs_lower_inode_idx(inode, bindex);
+   if (!lower_inode || !lower_inode-i_fop-fsync)
+   continue;
+   lower_file = unionfs_lower_file_idx(file, bindex);
+   lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+   mutex_lock(lower_inode-i_mutex);
+   err = lower_inode-i_fop-fsync(lower_file,
+   lower_dentry,
+   datasync);
+   mutex_unlock(lower_inode-i_mutex);
+   if (err)
+   goto out;
+   }
+
+   unionfs_copy_attr_times(inode);
+
+out:
+   unionfs_read_unlock(file-f_path.dentry-d_sb);
+   return err;
+}
+
+int unionfs_fasync(int fd, struct file *file, int flag)
+{
+   int bindex, bstart, bend;
+   struct file *lower_file;
+   struct dentry *dentry;
+   struct inode *lower_inode, *inode;
+   int err = 0;
+
+   unionfs_read_lock(file-f_path.dentry-d_sb);
+   if ((err = unionfs_file_revalidate(file, 1)))
+   goto out;
+
+   bstart = fbstart(file);
+   bend = fbend(file);
+   if (bstart  0 || bend  0)
+   goto out;
+
+   dentry = file-f_path.dentry;
+   inode = dentry-d_inode;
+   if (!inode) {
+   printk(KERN_ERR
+  unionfs: null lower inode in unionfs_fasync\n);
+   goto out;
+   }
+   for (bindex = bstart; bindex = bend; bindex++) {
+   lower_inode = unionfs_lower_inode_idx(inode, bindex);
+   if (!lower_inode || !lower_inode-i_fop-fasync)
+   continue;
+   lower_file = unionfs_lower_file_idx(file, bindex);
+   mutex_lock(lower_inode-i_mutex);
+   err = lower_inode-i_fop-fasync(fd, lower_file, flag);
+   mutex_unlock(lower_inode-i_mutex);
+   if (err)
+   goto out;
+   }
+
+   unionfs_copy_attr_times(inode);
+
+out:
+   unionfs_read_unlock(file-f_path.dentry-d_sb);
+   return err;
+}
+
 struct file_operations unionfs_main_fops = {
.llseek = generic_file_llseek,
.read   = unionfs_read,
@@ -147,6 +235,7 @@ struct file_operations unionfs_main_fops = {
.open   = unionfs_open,
.flush  = unionfs_flush,
.release= unionfs_file_release,
-   .fsync  = file_fsync,
+   .fsync  = unionfs_fsync,
+   .fasync = unionfs_fasync,
.splice_read= generic_file_splice_read,
 };
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index f8a9cd2..ec33155 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -312,6 +312,9 @@ extern int unionfs_file_release(struct inode *inode, struct 
file *file);
 extern int unionfs_flush(struct file *file, fl_owner_t id);
 extern long unionfs_ioctl(struct file *file, unsigned int cmd,
  unsigned long arg);
+extern int unionfs_fsync(struct

[PATCH 27/32] Unionfs: extended attributes fixes

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/copyup.c |   43 +++
 fs/unionfs/union.h  |6 --
 fs/unionfs/xattr.c  |   16 ++--
 3 files changed, 37 insertions(+), 28 deletions(-)

diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
index 4c45790..36f751e 100644
--- a/fs/unionfs/copyup.c
+++ b/fs/unionfs/copyup.c
@@ -32,27 +32,39 @@ static int copyup_xattrs(struct dentry *old_lower_dentry,
ssize_t list_size = -1;
char *name_list = NULL;
char *attr_value = NULL;
-   char *name_list_orig = NULL;
+   char *name_list_buf = NULL;
 
+   /* query the actual size of the xattr list */
list_size = vfs_listxattr(old_lower_dentry, NULL, 0);
-
if (list_size = 0) {
err = list_size;
goto out;
}
 
+   /* allocate space for the actual list */
name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX);
if (!name_list || IS_ERR(name_list)) {
err = PTR_ERR(name_list);
goto out;
}
+
+   name_list_buf = name_list; /* save for kfree at end */
+
+   /* now get the actual xattr list of the source file */
list_size = vfs_listxattr(old_lower_dentry, name_list, list_size);
+   if (list_size = 0) {
+   err = list_size;
+   goto out;
+   }
+
+   /* allocate space to hold each xattr's value */
attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
if (!attr_value || IS_ERR(attr_value)) {
err = PTR_ERR(name_list);
goto out;
}
-   name_list_orig = name_list;
+
+   /* in a loop, get and set each xattr from src to dst file */
while (*name_list) {
ssize_t size;
 
@@ -65,7 +77,6 @@ static int copyup_xattrs(struct dentry *old_lower_dentry,
err = size;
goto out;
}
-
if (size  XATTR_SIZE_MAX) {
err = -E2BIG;
goto out;
@@ -73,19 +84,27 @@ static int copyup_xattrs(struct dentry *old_lower_dentry,
/* Don't lock here since vfs_setxattr does it for us. */
err = vfs_setxattr(new_lower_dentry, name_list, attr_value,
   size, 0);
-
+   /*
+* Selinux depends on security.* xattrs, so to maintain
+* the security of copied-up files, if Selinux is active,
+* then we must copy these xattrs as well.  So we need to
+* temporarily get FOWNER privileges.
+* XXX: move entire copyup code to SIOQ.
+*/
+   if (err == -EPERM  !capable(CAP_FOWNER)) {
+   cap_raise(current-cap_effective, CAP_FOWNER);
+   err = vfs_setxattr(new_lower_dentry, name_list,
+  attr_value, size, 0);
+   cap_lower(current-cap_effective, CAP_FOWNER);
+   }
if (err  0)
goto out;
name_list += strlen(name_list) + 1;
}
 out:
-   name_list = name_list_orig;
-
-   if (name_list)
-   unionfs_xattr_free(name_list, list_size + 1);
-   if (attr_value)
-   unionfs_xattr_free(attr_value, XATTR_SIZE_MAX);
-   /* It is no big deal if this fails, we just roll with the punches. */
+   unionfs_xattr_kfree(name_list_buf);
+   unionfs_xattr_kfree(attr_value);
+   /* Ignore if xattr isn't supported */
if (err == -ENOTSUPP || err == -EOPNOTSUPP)
err = 0;
return err;
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 26d886e..d1232ac 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -341,8 +341,10 @@ extern struct dentry *unionfs_interpose(struct dentry 
*this_dentry,
 #ifdef CONFIG_UNION_FS_XATTR
 /* Extended attribute functions. */
 extern void *unionfs_xattr_alloc(size_t size, size_t limit);
-extern void unionfs_xattr_free(void *ptr, size_t size);
-
+static inline void unionfs_xattr_kfree(const void *p)
+{
+   kfree(p);
+}
 extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name,
void *value, size_t size);
 extern int unionfs_removexattr(struct dentry *dentry, const char *name);
diff --git a/fs/unionfs/xattr.c b/fs/unionfs/xattr.c
index 46f3d4e..6ab92f3 100644
--- a/fs/unionfs/xattr.c
+++ b/fs/unionfs/xattr.c
@@ -28,25 +28,13 @@ void *unionfs_xattr_alloc(size_t size, size_t limit)
 
if (!size)  /* size request, no buffer is needed */
return NULL;
-   else if (size = PAGE_SIZE)
-   ptr = kmalloc(size, GFP_KERNEL);
-   else
-   ptr = vmalloc(size

[PATCH 05/32] Unionfs: do not use fsstack_copy_attr_all

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Unionfs needs a special fan-out version of fsstack_copy_attr_all, which is
called unionfs_copy_attr_all.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/dentry.c |   12 +---
 fs/unionfs/fanout.h |   50 +-
 fs/unionfs/inode.c  |   13 -
 fs/unionfs/main.c   |2 +-
 fs/unionfs/subr.c   |2 +-
 fs/unionfs/union.h  |5 +++--
 6 files changed, 71 insertions(+), 13 deletions(-)

diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
index f88a285..4a3c479 100644
--- a/fs/unionfs/dentry.c
+++ b/fs/unionfs/dentry.c
@@ -166,9 +166,15 @@ static int __unionfs_d_revalidate_one(struct dentry 
*dentry,
valid = 0;
 
if (valid) {
-   fsstack_copy_attr_all(dentry-d_inode,
- unionfs_lower_inode(dentry-d_inode),
- unionfs_get_nlinks);
+   /*
+* If we get here, and we copy the meta-data from the lower
+* inode to our inode, then it is vital that we have already
+* purged all unionfs-level file data.  We do that in the
+* caller (__unionfs_d_revalidate_chain) by calling
+* purge_inode_data.
+*/
+   unionfs_copy_attr_all(dentry-d_inode,
+ unionfs_lower_inode(dentry-d_inode));
fsstack_copy_inode_size(dentry-d_inode,
unionfs_lower_inode(dentry-d_inode));
}
diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
index 4da34c6..5908bc7 100644
--- a/fs/unionfs/fanout.h
+++ b/fs/unionfs/fanout.h
@@ -305,4 +305,52 @@ static inline void verify_locked(struct dentry *d)
BUG_ON(!mutex_is_locked(UNIONFS_D(d)-lock));
 }
 
-#endif /* _FANOUT_H */
+/* copy a/m/ctime from the lower branch with the newest times */
+static inline void unionfs_copy_attr_times(struct inode *upper)
+{
+   int bindex;
+   struct inode *lower;
+
+   if (!upper)
+   return;
+   for (bindex=ibstart(upper); bindex = ibend(upper); bindex++) {
+   lower = unionfs_lower_inode_idx(upper, bindex);
+   if (!lower)
+   continue; /* not all lower dir objects may exist */
+   if (timespec_compare(upper-i_mtime, lower-i_mtime)  0)
+   upper-i_mtime = lower-i_mtime;
+   if (timespec_compare(upper-i_ctime, lower-i_ctime)  0)
+   upper-i_ctime = lower-i_ctime;
+   if (timespec_compare(upper-i_atime, lower-i_atime)  0)
+   upper-i_atime = lower-i_atime;
+   /* XXX: should we notify_change on our upper inode? */
+   }
+}
+
+/*
+ * A unionfs/fanout version of fsstack_copy_attr_all.  Uses a
+ * unionfs_get_nlinks to properly calcluate the number of links to a file.
+ * Also, copies the max() of all a/m/ctimes for all lower inodes (which is
+ * important if the lower inode is a directory type)
+ */
+static inline void unionfs_copy_attr_all(struct inode *dest,
+const struct inode *src)
+{
+   dest-i_mode = src-i_mode;
+   dest-i_uid = src-i_uid;
+   dest-i_gid = src-i_gid;
+   dest-i_rdev = src-i_rdev;
+
+   unionfs_copy_attr_times(dest);
+
+   dest-i_blkbits = src-i_blkbits;
+   dest-i_flags = src-i_flags;
+
+   /*
+* Update the nlinks AFTER updating the above fields, because the
+* get_links callback may depend on them.
+*/
+   dest-i_nlink = unionfs_get_nlinks(dest);
+}
+
+#endif /* not _FANOUT_H */
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 59bb418..cbbde6f 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -369,12 +369,13 @@ check_link:
/* Its a hard link, so use the same inode */
new_dentry-d_inode = igrab(old_dentry-d_inode);
d_instantiate(new_dentry, new_dentry-d_inode);
-   fsstack_copy_attr_all(dir, lower_new_dentry-d_parent-d_inode,
- unionfs_get_nlinks);
+   unionfs_copy_attr_all(dir, lower_new_dentry-d_parent-d_inode);
fsstack_copy_inode_size(dir, lower_new_dentry-d_parent-d_inode);
 
/* propagate number of hard-links */
old_dentry-d_inode-i_nlink = unionfs_get_nlinks(old_dentry-d_inode);
+   /* new dentry's ctime may have changed due to hard-link counts */
+   unionfs_copy_attr_times(new_dentry-d_inode);
 
 out:
if (!new_dentry-d_inode)
@@ -1084,13 +1085,15 @@ static int unionfs_setattr(struct dentry *dentry, 
struct iattr *ia)
}
 
/* get the size from the first lower inode */
-   lower_inode = unionfs_lower_inode(dentry-d_inode);
-   fsstack_copy_attr_all(inode, lower_inode, unionfs_get_nlinks);
+   lower_inode = unionfs_lower_inode(inode

[PATCH 30/32] Unionfs: update unionfs version number

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Update version number from 2.0 to 2.1 to reflect the amount of work that had
gone in since 2.0 was first released, and also to sync up with Unionfs 2.x
releases for earlier kernels.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 include/linux/union_fs.h |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/include/linux/union_fs.h b/include/linux/union_fs.h
index 9bc4e3b..7f8dcc3 100644
--- a/include/linux/union_fs.h
+++ b/include/linux/union_fs.h
@@ -12,7 +12,8 @@
 #ifndef _LINUX_UNION_FS_H
 #define _LINUX_UNION_FS_H
 
-#define UNIONFS_VERSION  2.0
+#define UNIONFS_VERSION  2.1-mm
+
 /*
  * DEFINITIONS FOR USER AND KERNEL CODE:
  */
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 19/32] Unionfs: partial_lookup update

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Handle new semantics of lookup_backend.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/lookup.c |   22 --
 1 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index e4e8470..d05daa5 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -425,20 +425,30 @@ out:
return ERR_PTR(err);
 }
 
-/* This is a utility function that fills in a unionfs dentry */
+/*
+ * This is a utility function that fills in a unionfs dentry.
+ *
+ * Returns: 0 (ok), or -ERRNO if an error occurred.
+ */
 int unionfs_partial_lookup(struct dentry *dentry)
 {
struct dentry *tmp;
struct nameidata nd = { .flags = 0 };
+   int err = -ENOSYS;
 
tmp = unionfs_lookup_backend(dentry, nd, INTERPOSE_PARTIAL);
-   if (!tmp)
-   return 0;
-   if (IS_ERR(tmp))
-   return PTR_ERR(tmp);
+   if (!tmp) {
+   err = 0;
+   goto out;
+   }
+   if (IS_ERR(tmp)) {
+   err = PTR_ERR(tmp);
+   goto out;
+   }
/* need to change the interface */
BUG_ON(tmp != dentry);
-   return -ENOSYS;
+out:
+   return err;
 }
 
 /* The dentry cache is just so we have properly sized dentries. */
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 10/32] Unionfs: cache-coherency - file flush

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Update our inode's time after flush.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/commonfops.c |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 0dc7492..edb52c0 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -742,6 +742,11 @@ int unionfs_flush(struct file *file, fl_owner_t id)
 
}
 
+   /* on success, update our times */
+   unionfs_copy_attr_times(dentry-d_inode);
+   /* parent time could have changed too (async) */
+   unionfs_copy_attr_times(dentry-d_parent-d_inode);
+
 out_lock:
unionfs_unlock_dentry(dentry);
 out:
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 32/32] Unionfs: unionfs_create rewrite

2007-09-02 Thread Josef 'Jeff' Sipek
The code was hard to follow and violated some invariants (e.g., never modify
a read only branch, and always create on branch 0).

Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/inode.c |  207 +++-
 1 files changed, 58 insertions(+), 149 deletions(-)

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 9adf272..08c1ae0 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -24,9 +24,7 @@ static int unionfs_create(struct inode *parent, struct dentry 
*dentry,
int err = 0;
struct dentry *lower_dentry = NULL;
struct dentry *wh_dentry = NULL;
-   struct dentry *new_lower_dentry;
struct dentry *lower_parent_dentry = NULL;
-   int bindex = 0, bstart;
char *name = NULL;
int valid = 0;
 
@@ -47,177 +45,88 @@ static int unionfs_create(struct inode *parent, struct 
dentry *dentry,
 */
BUG_ON(!valid  dentry-d_inode);
 
-   /* We start out in the leftmost branch. */
-   bstart = dbstart(dentry);
-   lower_dentry = unionfs_lower_dentry(dentry);
-
/*
-* 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 (IS_ERR(name)) {
-   err = PTR_ERR(name);
-   goto out;
-   }
-
-   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;
+   if ((err = is_robranch_super(dentry-d_sb, 0))) {
+   err = -EROFS;
goto out;
}
 
-   if (wh_dentry-d_inode) {
+   /*
+* We _always_ create on branch 0
+*/
+   lower_dentry = unionfs_lower_dentry_idx(dentry, 0);
+   if (lower_dentry) {
/*
-* .wh.foo has been found.
-* First truncate it and then rename it to foo (hence having
-* the same overall effect as a normal create.
+* check if whiteout exists in this branch, i.e. lookup .wh.foo
+* first.
 */
-   struct dentry *lower_dir_dentry;
-   struct iattr newattrs;
-
-   mutex_lock(wh_dentry-d_inode-i_mutex);
-   newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_ATIME
-   | ATTR_MTIME | ATTR_UID | ATTR_GID | ATTR_FORCE
-   | ATTR_KILL_SUID | ATTR_KILL_SGID;
-
-   newattrs.ia_mode = mode  ~current-fs-umask;
-   newattrs.ia_uid = current-fsuid;
-   newattrs.ia_gid = current-fsgid;
-
-   if (wh_dentry-d_inode-i_size != 0) {
-   newattrs.ia_valid |= ATTR_SIZE;
-   newattrs.ia_size = 0;
-   }
-
-   err = notify_change(wh_dentry, newattrs);
-
-   mutex_unlock(wh_dentry-d_inode-i_mutex);
-
-   if (err)
-   printk(KERN_WARNING unionfs: %s:%d: notify_change 
-  failed: %d, ignoring..\n,
-  __FILE__, __LINE__, err);
-
-   new_lower_dentry = unionfs_lower_dentry(dentry);
-   dget(new_lower_dentry);
-
-   lower_dir_dentry = dget_parent(wh_dentry);
-   lock_rename(lower_dir_dentry, lower_dir_dentry);
-
-   if (!(err = is_robranch_super(dentry-d_sb, bstart))) {
-   err = vfs_rename(lower_dir_dentry-d_inode,
-wh_dentry,
-lower_dir_dentry-d_inode,
-new_lower_dentry);
-   }
-   if (!err) {
-   fsstack_copy_attr_times(parent,
-   new_lower_dentry-d_parent-
-   d_inode);
-   fsstack_copy_inode_size(parent,
-   new_lower_dentry-d_parent-
-   d_inode);
-   parent-i_nlink = unionfs_get_nlinks(parent);
+   name = alloc_whname(dentry-d_name.name, dentry-d_name.len);
+   if (IS_ERR(name)) {
+   err = PTR_ERR(name);
+   goto out;
}
 
-   unlock_rename(lower_dir_dentry, lower_dir_dentry);
-   dput(lower_dir_dentry);
-
-   dput(new_lower_dentry);
-
-   if (err) {
-   /* exit if the error returned was NOT -EROFS

[PATCH 03/32] VFS/fsstack: cpp endif comments

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Add comments to #endif's to help clarify code.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 include/linux/fs_stack.h |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
index 6b52faf..28543ad 100644
--- a/include/linux/fs_stack.h
+++ b/include/linux/fs_stack.h
@@ -39,4 +39,4 @@ static inline void fsstack_copy_attr_times(struct inode *dest,
dest-i_ctime = src-i_ctime;
 }
 
-#endif /* _LINUX_FS_STACK_H */
+#endif /* not _LINUX_FS_STACK_H */
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 17/32] Unionfs: interpose updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Update unionfs_interpose to handle spliced dentries, which is important for
NFS exporting.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/inode.c  |   40 +++
 fs/unionfs/lookup.c |   22 +++-
 fs/unionfs/main.c   |  138 +--
 fs/unionfs/union.h  |4 +-
 4 files changed, 141 insertions(+), 63 deletions(-)

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 6cec564..a219a40 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -152,7 +152,12 @@ static int unionfs_create(struct inode *parent, struct 
dentry *dentry,
 wh_dentry);
wh_dentry = NULL;
 
-   err = unionfs_interpose(dentry, parent-i_sb, 0);
+   /*
+* Only INTERPOSE_LOOKUP can return a value other
+* than 0 on err.
+*/
+   err = PTR_ERR(unionfs_interpose(dentry,
+   parent-i_sb, 0));
goto out;
}
}
@@ -194,11 +199,14 @@ static int unionfs_create(struct inode *parent, struct 
dentry *dentry,
if (!IS_COPYUP_ERR(err))
break;
} else {
-   err = unionfs_interpose(dentry, parent-i_sb, 0);
+   /*
+* Only INTERPOSE_LOOKUP can return a value other
+* than 0 on err.
+*/
+   err = PTR_ERR(unionfs_interpose(dentry,
+   parent-i_sb, 0));
if (!err) {
-   fsstack_copy_attr_times(parent,
-   lower_parent_dentry-
-   d_inode);
+   unionfs_copy_attr_times(parent);
fsstack_copy_inode_size(parent,
lower_parent_dentry-
d_inode);
@@ -527,7 +535,12 @@ static int unionfs_symlink(struct inode *dir, struct 
dentry *dentry,
if (!IS_COPYUP_ERR(err))
break;
} else {
-   err = unionfs_interpose(dentry, dir-i_sb, 0);
+   /*
+* Only INTERPOSE_LOOKUP can return a value other
+* than 0 on err.
+*/
+   err = PTR_ERR(unionfs_interpose(dentry,
+   dir-i_sb, 0));
if (!err) {
fsstack_copy_attr_times(dir,
lower_dir_dentry-
@@ -664,10 +677,13 @@ static int unionfs_mkdir(struct inode *parent, struct 
dentry *dentry, int mode)
}
set_dbend(dentry, bindex);
 
-   err = unionfs_interpose(dentry, parent-i_sb, 0);
+   /*
+* Only INTERPOSE_LOOKUP can return a value other than 0 on
+* err.
+*/
+   err = PTR_ERR(unionfs_interpose(dentry, parent-i_sb, 0));
if (!err) {
-   fsstack_copy_attr_times(parent,
-   lower_parent_dentry-d_inode);
+   unionfs_copy_attr_times(parent);
fsstack_copy_inode_size(parent,
lower_parent_dentry-d_inode);
 
@@ -795,7 +811,11 @@ static int unionfs_mknod(struct inode *dir, struct dentry 
*dentry, int mode,
break;
}
 
-   err = unionfs_interpose(dentry, dir-i_sb, 0);
+   /*
+* Only INTERPOSE_LOOKUP can return a value other than 0 on
+* err.
+*/
+   err = PTR_ERR(unionfs_interpose(dentry, dir-i_sb, 0));
if (!err) {
fsstack_copy_attr_times(dir,
lower_parent_dentry-d_inode);
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index 61ee50d..e4e8470 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -72,7 +72,12 @@ out:
return err;
 }
 
-/* main (and complex) driver function for Unionfs's lookup */
+/*
+ * Main (and complex) driver function for Unionfs's lookup
+ *
+ * Returns: NULL (ok), ERR_PTR if an error occurred, or a non-null non-error
+ * PTR if d_splice returned a different dentry.
+ */
 struct dentry *unionfs_lookup_backend(struct dentry *dentry

[PATCH 21/32] Unionfs: mmap fixes

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Most important fixes prevent deadlocks especially under low-memory
conditions, when one is not supposed to cause more memory pressure; also
handle AOP_WRITEPAGE_ACTIVATE from lower file systems.

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/file.c |6 +-
 fs/unionfs/mmap.c |  132 ++---
 2 files changed, 98 insertions(+), 40 deletions(-)

diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
index 0555b6c..b55da4f 100644
--- a/fs/unionfs/file.c
+++ b/fs/unionfs/file.c
@@ -101,9 +101,6 @@ static int unionfs_mmap(struct file *file, struct 
vm_area_struct *vma)
 
unionfs_read_lock(file-f_path.dentry-d_sb);
 
-   if ((err = unionfs_file_revalidate(file, 1)))
-   goto out;
-
/* This might be deferred to mmap's writepage */
willwrite = ((vma-vm_flags | VM_SHARED | VM_WRITE) == vma-vm_flags);
if ((err = unionfs_file_revalidate(file, willwrite)))
@@ -132,6 +129,9 @@ static int unionfs_mmap(struct file *file, struct 
vm_area_struct *vma)
 
 out:
unionfs_read_unlock(file-f_path.dentry-d_sb);
+   if (!err)
+   /* copyup could cause parent dir times to change */
+   unionfs_copy_attr_times(file-f_path.dentry-d_parent-d_inode);
return err;
 }
 
diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c
index 969fd16..d26b572 100644
--- a/fs/unionfs/mmap.c
+++ b/fs/unionfs/mmap.c
@@ -21,7 +21,7 @@
 
 /*
  * Unionfs doesn't implement -writepages, which is OK with the VFS and
- * nkeeps our code simpler and smaller.  Nevertheless, somehow, our own
+ * keeps our code simpler and smaller.  Nevertheless, somehow, our own
  * -writepage must be called so we can sync the upper pages with the lower
  * pages: otherwise data changed at the upper layer won't get written to the
  * lower layer.
@@ -64,10 +64,31 @@ static int unionfs_writepage(struct page *page, struct 
writeback_control *wbc)
inode = page-mapping-host;
lower_inode = unionfs_lower_inode(inode);
 
-   /* find lower page (returns a locked page) */
-   lower_page = grab_cache_page(lower_inode-i_mapping, page-index);
-   if (!lower_page)
+   /*
+* find lower page (returns a locked page)
+*
+* NOTE: we used to call grab_cache_page(), but that was unnecessary
+* as it would have tried to create a new lower page if it didn't
+* exist, leading to deadlocks (esp. under memory-pressure
+* conditions, when it is really a bad idea to *consume* more
+* memory).  Instead, we assume the lower page exists, and if we can
+* find it, then we -writepage on it; if we can't find it, then it
+* couldn't have disappeared unless the kernel already flushed it,
+* in which case we're still OK.  This is especially correct if
+* wbc-sync_mode is WB_SYNC_NONE (as per
+* Documentation/filesystems/vfs.txt).  If we can't flush our page
+* because we can't find a lower page, then at least we re-mark our
+* page as dirty, and return AOP_WRITEPAGE_ACTIVATE as the VFS
+* expects us to.  (Note, if in the future it'd turn out that we
+* have to find a lower page no matter what, then we'd have to
+* resort to RAIF's page pointer flipping trick.)
+*/
+   lower_page = find_lock_page(lower_inode-i_mapping, page-index);
+   if (!lower_page) {
+   err = AOP_WRITEPAGE_ACTIVATE;
+   set_page_dirty(page);
goto out;
+   }
 
/* get page address, and encode it */
kaddr = kmap(page);
@@ -85,24 +106,41 @@ static int unionfs_writepage(struct page *page, struct 
writeback_control *wbc)
wbc-for_writepages = 0;
 
/* call lower writepage (expects locked page) */
+   clear_page_dirty_for_io(lower_page); /* emulate VFS behavior */
err = lower_inode-i_mapping-a_ops-writepage(lower_page, wbc);
wbc-for_writepages = saved_for_writepages; /* restore value */
 
-   /*
-* update mtime and ctime of lower level file system
-* unionfs' mtime and ctime are updated by generic_file_write
-*/
-   lower_inode-i_mtime = lower_inode-i_ctime = CURRENT_TIME;
-
-   page_cache_release(lower_page); /* b/c grab_cache_page increased refcnt 
*/
-
+   /* b/c find_lock_page locked it and -writepage unlocks on success */
if (err)
+   unlock_page(lower_page);
+   /* b/c grab_cache_page increased refcnt */
+   page_cache_release(lower_page);
+
+   if (err  0) {
ClearPageUptodate(page);
-   else
-   SetPageUptodate(page);
+   goto out;
+   }
+   if (err == AOP_WRITEPAGE_ACTIVATE) {
+   /*
+* Lower file systems such as ramfs and tmpfs, may return
+* AOP_WRITEPAGE_ACTIVATE so

[PATCH 29/32] Unionfs: assorted comment and style updates

2007-09-02 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/dirhelper.c |2 --
 fs/unionfs/fanout.h|9 +++--
 fs/unionfs/file.c  |6 --
 fs/unionfs/inode.c |2 +-
 fs/unionfs/lookup.c|2 +-
 fs/unionfs/main.c  |7 +++
 fs/unionfs/rename.c|8 
 fs/unionfs/super.c |7 ++-
 fs/unionfs/union.h |   14 +++---
 fs/unionfs/unlink.c|1 -
 10 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index 24bd327..a72f711 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -31,7 +31,6 @@ int do_delete_whiteouts(struct dentry *dentry, int bindex,
struct dentry *lower_dentry;
char *name = NULL, *p;
struct inode *lower_dir;
-
int i;
struct list_head *pos;
struct filldir_node *cursor;
@@ -95,7 +94,6 @@ int delete_whiteouts(struct dentry *dentry, int bindex,
struct super_block *sb;
struct dentry *lower_dir_dentry;
struct inode *lower_dir;
-
struct sioq_args args;
 
sb = dentry-d_sb;
diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
index 5908bc7..c5bf454 100644
--- a/fs/unionfs/fanout.h
+++ b/fs/unionfs/fanout.h
@@ -65,9 +65,9 @@ static inline void new_branch_id(struct super_block *sb, int 
index)
 }
 
 /*
- * Find new index of matching branch with an existing superblock a a known
+ * Find new index of matching branch with an existing superblock of a known
  * (possibly old) id.  This is needed because branches could have been
- * added/deleted causing the branchs of any open files to shift.
+ * added/deleted causing the branches of any open files to shift.
  *
  * @sb: the new superblock which may have new/different branch IDs
  * @id: the old/existing id we're looking for
@@ -80,10 +80,7 @@ static inline int branch_id_to_idx(struct super_block *sb, 
int id)
if (branch_id(sb, i) == id)
return i;
}
-   /*
-* XXX: maybe we should BUG_ON if not found new branch index?
-* (really that should never happen).
-*/
+   /* in the non-ODF code, this should really never happen */
printk(KERN_WARNING unionfs: cannot find branch with id %d\n, id);
return -1;
 }
diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
index b55da4f..b33f44f 100644
--- a/fs/unionfs/file.c
+++ b/fs/unionfs/file.c
@@ -18,17 +18,12 @@
 
 #include union.h
 
-/***
- * File Operations *
- ***/
-
 static ssize_t unionfs_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
 {
int err;
 
unionfs_read_lock(file-f_path.dentry-d_sb);
-
if ((err = unionfs_file_revalidate(file, 0)))
goto out;
 
@@ -50,7 +45,6 @@ static ssize_t unionfs_aio_read(struct kiocb *iocb, const 
struct iovec *iov,
struct file *file = iocb-ki_filp;
 
unionfs_read_lock(file-f_path.dentry-d_sb);
-
if ((err = unionfs_file_revalidate(file, 0)))
goto out;
 
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 4574fbe..218320e 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -781,7 +781,6 @@ static int unionfs_mknod(struct inode *dir, struct dentry 
*dentry, int mode,
if (err) {
if (!IS_COPYUP_ERR(err))
goto out;
-
bstart--;
} else
whiteout_unlinked = 1;
@@ -882,6 +881,7 @@ static int unionfs_readlink(struct dentry *dentry, char 
__user *buf,
 out:
unionfs_unlock_dentry(dentry);
unionfs_read_unlock(dentry-d_sb);
+
return err;
 }
 
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index 38ee21f..7fa6310 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -197,7 +197,7 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry,
 
/* check if whiteout exists in this branch: lookup .wh.foo */
wh_lower_dentry = lookup_one_len(whname, lower_dir_dentry,
- namelen + UNIONFS_WHLEN);
+namelen + UNIONFS_WHLEN);
if (IS_ERR(wh_lower_dentry)) {
dput(first_lower_dentry);
unionfs_mntput(first_dentry, first_dentry_offset);
diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index ce08d96..4faae44 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -226,6 +226,7 @@ void unionfs_reinterpose(struct dentry *dentry)
  */
 int check_branch(struct nameidata *nd)
 {
+   /* XXX: remove in ODF code -- stacking unions allowed there */
if (!strcmp(nd-dentry-d_sb-s_type-name, unionfs))
return -EINVAL;
if (!nd-dentry-d_inode

[PATCH 5/5] Unionfs: Remove unnecessary BUG_ON in unionfs_follow_link

2007-06-29 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/inode.c |   30 --
 1 files changed, 8 insertions(+), 22 deletions(-)

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index a86da5b..b5f9022 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -832,35 +832,21 @@ out:
 }
 
 /*
- * Check if dentry is valid or not, as per our generation numbers.
- * @dentry: dentry to check.
- * Returns 1 (valid) or 0 (invalid/stale).
+ * unionfs_follow_link takes a dentry, but it is simple.  It only needs to
+ * allocate some memory and then call our ->readlink method.  Our
+ * unionfs_readlink *does* lock our dentry and revalidate the dentry.
+ * Therefore, we do not have to lock our dentry here, to prevent a deadlock;
+ * nor do we need to revalidate it either.  It is safe to not lock our
+ * dentry here, nor revalidate it, because unionfs_follow_link does not do
+ * anything (prior to calling ->readlink) which could become inconsistent
+ * due to branch management.
  */
-static inline int is_valid_dentry(struct dentry *dentry)
-{
-   BUG_ON(!UNIONFS_D(dentry));
-   BUG_ON(!UNIONFS_SB(dentry->d_sb));
-   return (atomic_read(_D(dentry)->generation) ==
-   atomic_read(_SB(dentry->d_sb)->generation));
-}
-
-/* We don't lock the dentry here, because readlink does the heavy lifting. */
 static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
char *buf;
int len = PAGE_SIZE, err;
mm_segment_t old_fs;
 
-   /*
-* FIXME: Really nasty...we can get called from two distinct places:
-* 1) read_link - locks the dentry
-* 2) VFS lookup code - does NOT lock the dentry
-*
-* The proper thing would be to call dentry revalidate. It however
-* expects a locked dentry, and we can't cleanly guarantee that.
-*/
-   BUG_ON(!is_valid_dentry(dentry));
-
unionfs_read_lock(dentry->d_sb);
 
/* This is freed by the put_link method assuming a successful call. */
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/5] Unionfs: Add missing unlock call in unionfs_file_release

2007-06-29 Thread Josef 'Jeff' Sipek
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/commonfops.c |6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 6d87426..8527ac6 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -559,7 +559,7 @@ int unionfs_file_release(struct inode *inode, struct file 
*file)
 * support.
 */
if ((err = unionfs_file_revalidate(file, 1)))
-   return err;
+   goto out;
fileinfo = UNIONFS_F(file);
BUG_ON(file->f_dentry->d_inode != inode);
inodeinfo = UNIONFS_I(inode);
@@ -596,7 +596,9 @@ int unionfs_file_release(struct inode *inode, struct file 
*file)
fileinfo->rdstate = NULL;
}
kfree(fileinfo);
-   return 0;
+out:
+   unionfs_read_unlock(sb);
+   return err;
 }
 
 /* pass the ioctl to the lower fs */
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/5] Unionfs: Use file->f_path instead of file->f_dentry

2007-06-29 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/commonfops.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 8527ac6..28cb4e9 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -708,10 +708,10 @@ int unionfs_flush(struct file *file, fl_owner_t id)
 {
int err = 0;
struct file *lower_file = NULL;
-   struct dentry *dentry = file->f_dentry;
+   struct dentry *dentry = file->f_path.dentry;
int bindex, bstart, bend;
 
-   unionfs_read_lock(file->f_path.dentry->d_sb);
+   unionfs_read_lock(dentry->d_sb);
 
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
@@ -745,6 +745,6 @@ int unionfs_flush(struct file *file, fl_owner_t id)
 out_lock:
unionfs_unlock_dentry(dentry);
 out:
-   unionfs_read_unlock(file->f_path.dentry->d_sb);
+   unionfs_read_unlock(dentry->d_sb);
return err;
 }
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/5] Unionfs: Clarification comment for unionfs_lookup

2007-06-29 Thread Josef 'Jeff' Sipek
From: Erez Zadok <[EMAIL PROTECTED]>

Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>
Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
---
 fs/unionfs/inode.c |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index f946b33..a86da5b 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -217,6 +217,11 @@ out:
return err;
 }
 
+/*
+ * unionfs_lookup is the only special function which takes a dentry, yet we
+ * do NOT want to call __unionfs_d_revalidate_chain because by definition,
+ * we don't have a valid dentry here yet.
+ */
 static struct dentry *unionfs_lookup(struct inode *parent,
 struct dentry *dentry,
 struct nameidata *nd)
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[GIT PULL -mm] Unionfs cleanups and fixes

2007-06-29 Thread Josef 'Jeff' Sipek
The following patches consist of mostly cleanups and bug fixes of the
Unionfs code.

As before, there is a git repo at:

git://git.kernel.org/pub/scm/linux/kernel/git/jsipek/unionfs.git

(master.kernel.org:/pub/scm/linux/kernel/git/jsipek/unionfs.git)

There are 5 new commits:

Erez Zadok (4):
  Unionfs: Convert all instances of "hidden" to "lower"
  Unionfs: Use file->f_path instead of file->f_dentry
  Unionfs: Clarification comment for unionfs_lookup
  Unionfs: Remove unnecessary BUG_ON in unionfs_follow_link

Josef 'Jeff' Sipek (1):
  Unionfs: Add missing unlock call in unionfs_file_release

Thanks,

Josef 'Jeff' Sipek <[EMAIL PROTECTED]>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[GIT PULL -mm] Unionfs cleanups and fixes

2007-06-29 Thread Josef 'Jeff' Sipek
The following patches consist of mostly cleanups and bug fixes of the
Unionfs code.

As before, there is a git repo at:

git://git.kernel.org/pub/scm/linux/kernel/git/jsipek/unionfs.git

(master.kernel.org:/pub/scm/linux/kernel/git/jsipek/unionfs.git)

There are 5 new commits:

Erez Zadok (4):
  Unionfs: Convert all instances of hidden to lower
  Unionfs: Use file-f_path instead of file-f_dentry
  Unionfs: Clarification comment for unionfs_lookup
  Unionfs: Remove unnecessary BUG_ON in unionfs_follow_link

Josef 'Jeff' Sipek (1):
  Unionfs: Add missing unlock call in unionfs_file_release

Thanks,

Josef 'Jeff' Sipek [EMAIL PROTECTED]

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/5] Unionfs: Use file-f_path instead of file-f_dentry

2007-06-29 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/commonfops.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 8527ac6..28cb4e9 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -708,10 +708,10 @@ int unionfs_flush(struct file *file, fl_owner_t id)
 {
int err = 0;
struct file *lower_file = NULL;
-   struct dentry *dentry = file-f_dentry;
+   struct dentry *dentry = file-f_path.dentry;
int bindex, bstart, bend;
 
-   unionfs_read_lock(file-f_path.dentry-d_sb);
+   unionfs_read_lock(dentry-d_sb);
 
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
@@ -745,6 +745,6 @@ int unionfs_flush(struct file *file, fl_owner_t id)
 out_lock:
unionfs_unlock_dentry(dentry);
 out:
-   unionfs_read_unlock(file-f_path.dentry-d_sb);
+   unionfs_read_unlock(dentry-d_sb);
return err;
 }
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/5] Unionfs: Clarification comment for unionfs_lookup

2007-06-29 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/inode.c |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index f946b33..a86da5b 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -217,6 +217,11 @@ out:
return err;
 }
 
+/*
+ * unionfs_lookup is the only special function which takes a dentry, yet we
+ * do NOT want to call __unionfs_d_revalidate_chain because by definition,
+ * we don't have a valid dentry here yet.
+ */
 static struct dentry *unionfs_lookup(struct inode *parent,
 struct dentry *dentry,
 struct nameidata *nd)
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 5/5] Unionfs: Remove unnecessary BUG_ON in unionfs_follow_link

2007-06-29 Thread Josef 'Jeff' Sipek
From: Erez Zadok [EMAIL PROTECTED]

Signed-off-by: Erez Zadok [EMAIL PROTECTED]
Signed-off-by: Josef 'Jeff' Sipek [EMAIL PROTECTED]
---
 fs/unionfs/inode.c |   30 --
 1 files changed, 8 insertions(+), 22 deletions(-)

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index a86da5b..b5f9022 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -832,35 +832,21 @@ out:
 }
 
 /*
- * Check if dentry is valid or not, as per our generation numbers.
- * @dentry: dentry to check.
- * Returns 1 (valid) or 0 (invalid/stale).
+ * unionfs_follow_link takes a dentry, but it is simple.  It only needs to
+ * allocate some memory and then call our -readlink method.  Our
+ * unionfs_readlink *does* lock our dentry and revalidate the dentry.
+ * Therefore, we do not have to lock our dentry here, to prevent a deadlock;
+ * nor do we need to revalidate it either.  It is safe to not lock our
+ * dentry here, nor revalidate it, because unionfs_follow_link does not do
+ * anything (prior to calling -readlink) which could become inconsistent
+ * due to branch management.
  */
-static inline int is_valid_dentry(struct dentry *dentry)
-{
-   BUG_ON(!UNIONFS_D(dentry));
-   BUG_ON(!UNIONFS_SB(dentry-d_sb));
-   return (atomic_read(UNIONFS_D(dentry)-generation) ==
-   atomic_read(UNIONFS_SB(dentry-d_sb)-generation));
-}
-
-/* We don't lock the dentry here, because readlink does the heavy lifting. */
 static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
char *buf;
int len = PAGE_SIZE, err;
mm_segment_t old_fs;
 
-   /*
-* FIXME: Really nasty...we can get called from two distinct places:
-* 1) read_link - locks the dentry
-* 2) VFS lookup code - does NOT lock the dentry
-*
-* The proper thing would be to call dentry revalidate. It however
-* expects a locked dentry, and we can't cleanly guarantee that.
-*/
-   BUG_ON(!is_valid_dentry(dentry));
-
unionfs_read_lock(dentry-d_sb);
 
/* This is freed by the put_link method assuming a successful call. */
-- 
1.5.2.2.238.g7cbf2f2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


  1   2   3   4   5   >