Author: pluto                        Date: Thu Sep 11 21:08:00 2008 GMT
Module: SOURCES                       Tag: LINUX_2_6
---- Log message:
- updated.

---- Files affected:
SOURCES:
   kernel-unionfs.patch (1.1.2.1 -> 1.1.2.2) 

---- Diffs:

================================================================
Index: SOURCES/kernel-unionfs.patch
diff -u SOURCES/kernel-unionfs.patch:1.1.2.1 
SOURCES/kernel-unionfs.patch:1.1.2.2
--- SOURCES/kernel-unionfs.patch:1.1.2.1        Thu May  8 01:36:52 2008
+++ SOURCES/kernel-unionfs.patch        Thu Sep 11 23:07:55 2008
@@ -1,8 +1,8 @@
 diff --git a/Documentation/filesystems/00-INDEX 
b/Documentation/filesystems/00-INDEX
-index e68021c..9dcbd6d 100644
+index 52cd611..bc6b437 100644
 --- a/Documentation/filesystems/00-INDEX
 +++ b/Documentation/filesystems/00-INDEX
-@@ -100,6 +100,8 @@ udf.txt
+@@ -106,6 +106,8 @@ udf.txt
        - info and mount options for the UDF filesystem.
  ufs.txt
        - info on the ufs filesystem.
@@ -29,10 +29,10 @@
 +      - Usage information and examples.
 diff --git a/Documentation/filesystems/unionfs/concepts.txt 
b/Documentation/filesystems/unionfs/concepts.txt
 new file mode 100644
-index 0000000..8d9a1c5
+index 0000000..b853788
 --- /dev/null
 +++ b/Documentation/filesystems/unionfs/concepts.txt
-@@ -0,0 +1,226 @@
+@@ -0,0 +1,287 @@
 +Unionfs 2.x CONCEPTS:
 +=====================
 +
@@ -87,6 +87,42 @@
 +eliminate 'foo' from the namespace (as well as the whiteout itself.)
 +
 +
++Opaque Directories:
++===================
++
++Assume we have a unionfs mount comprising of two branches.  Branch 0 is
++empty; branch 1 has the directory /a and file /a/f.  Let's say we mount a
++union of branch 0 as read-write and branch 1 as read-only.  Now, let's say
++we try to perform the following operation in the union:
++
++      rm -fr a
++
++Because branch 1 is not writable, we cannot physically remove the file /a/f
++or the directory /a.  So instead, we will create a whiteout in branch 0
++named /.wh.a, masking out the name "a" from branch 1.  Next, let's say we
++try to create a directory named "a" as follows:
++
++      mkdir a
++
++Because we have a whiteout for "a" already, Unionfs behaves as if "a"
++doesn't exist, and thus will delete the whiteout and replace it with an
++actual directory named "a".
++
++The problem now is that if you try to "ls" in the union, Unionfs will
++perform is normal directory name unification, for *all* directories named
++"a" in all branches.  This will cause the file /a/f from branch 1 to
++re-appear in the union's namespace, which violates Unix semantics.
++
++To avoid this problem, we have a different form of whiteouts for
++directories, called "opaque directories" (same as BSD Union Mount does).
++Whenever we replace a whiteout with a directory, that directory is marked as
++opaque.  In Unionfs 2.x, it means that we create a file named
++/a/.wh.__dir_opaque in branch 0, after having created directory /a there.
++When unionfs notices that a directory is opaque, it stops all namespace
++operations (including merging readdir contents) at that opaque directory.
++This prevents re-exposing names from masked out directories.
++
++
 +Duplicate Elimination:
 +======================
 +
@@ -97,6 +133,31 @@
 +(numerically lowest value) and "hide" the others.
 +
 +
++Unlinking:
++=========
++
++Unlink operation on non-directory instances is optimized to remove the
++maximum possible objects in case multiple underlying branches have the same
++file name.  The unlink operation will first try to delete file instances
++from highest priority branch and then move further to delete from remaining
++branches in order of their decreasing priority.  Consider a case (F..D..F),
++where F is a file and D is a directory of the same name; here, some
++intermediate branch could have an empty directory instance with the same
++name, so this operation also tries to delete this directory instance and
++proceed further to delete from next possible lower priority branch.  The
++unionfs unlink operation will smoothly delete the files with same name from
++all possible underlying branches.  In case if some error occurs, it creates
++whiteout in highest priority branch that will hide file instance in rest of
++the branches.  An error could occur either if an unlink operations in any of
++the underlying branch failed or if a branch has no write permission.
++
++This unlinking policy is known as "delete all" and it has the benefit of
++overall reducing the number of inodes used by duplicate files, and further
++reducing the total number of inodes consumed by whiteouts.  The cost is of
++extra processing, but testing shows this extra processing is well worth the
++savings.
++
++
 +Copyup:
 +=======
 +
@@ -471,30 +532,29 @@
 +
 +For more information, see <http://unionfs.filesystems.org/>.
 diff --git a/MAINTAINERS b/MAINTAINERS
-index 1d2edb4..e58f41f 100644
+index 56a2f67..26a2176 100644
 --- a/MAINTAINERS
 +++ b/MAINTAINERS
-@@ -3923,6 +3923,15 @@ L:      [EMAIL PROTECTED]
+@@ -4093,6 +4093,14 @@ L:      [EMAIL PROTECTED]
  W:    http://www.kernel.dk
  S:    Maintained
  
 +UNIONFS
 +P:    Erez Zadok
 +M:    [EMAIL PROTECTED]
-+P:    Josef "Jeff" Sipek
-+M:    [EMAIL PROTECTED]
 +L:    [EMAIL PROTECTED]
 +W:    http://unionfs.filesystems.org
++T:    git git.kernel.org/pub/scm/linux/kernel/git/ezk/unionfs.git
 +S:    Maintained
 +
  USB ACM DRIVER
  P:    Oliver Neukum
  M:    [EMAIL PROTECTED]
 diff --git a/fs/Kconfig b/fs/Kconfig
-index d731282..9adebb3 100644
+index 2694648..ee32927 100644
 --- a/fs/Kconfig
 +++ b/fs/Kconfig
-@@ -1003,6 +1003,47 @@ config CONFIGFS_FS
+@@ -1031,6 +1031,47 @@ config CONFIGFS_FS
  
  endmenu
  
@@ -542,7 +602,7 @@
  menu "Miscellaneous filesystems"
  
  config ADFS_FS
-@@ -1055,18 +1096,6 @@ config AFFS_FS
+@@ -1083,18 +1124,6 @@ config AFFS_FS
          To compile this file system support as a module, choose M here: the
          module will be called affs.  If unsure, say N.
  
@@ -562,16 +622,19 @@
        tristate "Apple Macintosh file system support (EXPERIMENTAL)"
        depends on BLOCK && EXPERIMENTAL
 diff --git a/fs/Makefile b/fs/Makefile
-index 1e7a11b..22ebb61 100644
+index 1e7a11b..dadf53b 100644
 --- a/fs/Makefile
 +++ b/fs/Makefile
-@@ -119,3 +119,4 @@ obj-$(CONFIG_HPPFS)                += hppfs/
- obj-$(CONFIG_DEBUG_FS)                += debugfs/
- obj-$(CONFIG_OCFS2_FS)                += ocfs2/
- obj-$(CONFIG_GFS2_FS)           += gfs2/
+@@ -85,6 +85,7 @@ obj-$(CONFIG_ISO9660_FS)     += isofs/
+ obj-$(CONFIG_HFSPLUS_FS)      += hfsplus/ # Before hfs to find wrapped HFS+
+ obj-$(CONFIG_HFS_FS)          += hfs/
+ obj-$(CONFIG_ECRYPT_FS)               += ecryptfs/
 +obj-$(CONFIG_UNION_FS)                += unionfs/
+ obj-$(CONFIG_VXFS_FS)         += freevxfs/
+ obj-$(CONFIG_NFS_FS)          += nfs/
+ obj-$(CONFIG_EXPORTFS)                += exportfs/
 diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
-index 841a032..e5c4343 100644
+index 5e59658..4621f89 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)
@@ -584,10 +647,10 @@
  out:
        return rc;
 diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
-index e238611..687819d 100644
+index c92cc1c..71fcaea 100644
 --- a/fs/ecryptfs/inode.c
 +++ b/fs/ecryptfs/inode.c
-@@ -575,9 +575,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry 
*old_dentry,
+@@ -570,9 +570,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;
@@ -599,9 +662,9 @@
  out_lock:
        unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
        dput(lower_new_dentry->d_parent);
-@@ -910,7 +910,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct 
iattr *ia)
- 
+@@ -907,7 +907,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct 
iattr *ia)
        rc = notify_change(lower_dentry, ia);
+       mutex_unlock(&lower_dentry->d_inode->i_mutex);
  out:
 -      fsstack_copy_attr_all(inode, lower_inode, NULL);
 +      fsstack_copy_attr_all(inode, lower_inode);
@@ -609,7 +672,7 @@
  }
  
 diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
-index d25ac95..7eac062 100644
+index d603631..59daba3 100644
 --- a/fs/ecryptfs/main.c
 +++ b/fs/ecryptfs/main.c
 @@ -211,7 +211,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct 
dentry *dentry,
@@ -622,22 +685,99 @@
         * other metadata */
        fsstack_copy_inode_size(inode, lower_inode);
 diff --git a/fs/namei.c b/fs/namei.c
-index 941c8e8..60762d8 100644
+index 01e67dd..b51fde0 100644
 --- a/fs/namei.c
 +++ b/fs/namei.c
-@@ -399,6 +399,7 @@ void release_open_intent(struct nameidata *nd)
+@@ -404,6 +404,7 @@ void release_open_intent(struct nameidata *nd)
        else
                fput(nd->intent.open.file);
  }
-+EXPORT_SYMBOL(release_open_intent);
++EXPORT_SYMBOL_GPL(release_open_intent);
  
  static inline struct dentry *
  do_revalidate(struct dentry *dentry, struct nameidata *nd)
+diff --git a/fs/splice.c b/fs/splice.c
+index aa5f6f6..4282fdf 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -878,8 +878,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
+ /*
+  * Attempt to initiate a splice from pipe to file.
+  */
+-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+-                         loff_t *ppos, size_t len, unsigned int flags)
++long vfs_splice_from(struct pipe_inode_info *pipe, struct file *out,
++                   loff_t *ppos, size_t len, unsigned int flags)
+ {
+       int ret;
+ 
+@@ -895,13 +895,14 @@ static long do_splice_from(struct pipe_inode_info *pipe, 
struct file *out,
+ 
+       return out->f_op->splice_write(pipe, out, ppos, len, flags);
+ }
++EXPORT_SYMBOL_GPL(vfs_splice_from);
+ 
+ /*
+  * Attempt to initiate a splice from a file to a pipe.
+  */
+-static long do_splice_to(struct file *in, loff_t *ppos,
+-                       struct pipe_inode_info *pipe, size_t len,
+-                       unsigned int flags)
++long vfs_splice_to(struct file *in, loff_t *ppos,
++                 struct pipe_inode_info *pipe, size_t len,
++                 unsigned int flags)
+ {
+       int ret;
+ 
+@@ -917,6 +918,7 @@ static long do_splice_to(struct file *in, loff_t *ppos,
+ 
+       return in->f_op->splice_read(in, ppos, pipe, len, flags);
+ }
++EXPORT_SYMBOL_GPL(vfs_splice_to);
+ 
+ /**
+  * splice_direct_to_actor - splices data directly between two non-pipes
+@@ -986,7 +988,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct 
splice_desc *sd,
+               size_t read_len;
+               loff_t pos = sd->pos, prev_pos = pos;
+ 
+-              ret = do_splice_to(in, &pos, pipe, len, flags);
++              ret = vfs_splice_to(in, &pos, pipe, len, flags);
+               if (unlikely(ret <= 0))
+                       goto out_release;
+ 
+@@ -1045,7 +1047,7 @@ static int direct_splice_actor(struct pipe_inode_info 
*pipe,
+ {
+       struct file *file = sd->u.file;
+ 
+-      return do_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags);
++      return vfs_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags);
+ }
+ 
+ /**
+@@ -1119,7 +1121,7 @@ static long do_splice(struct file *in, loff_t __user 
*off_in,
+               } else
+                       off = &out->f_pos;
+ 
+-              ret = do_splice_from(pipe, out, off, len, flags);
++              ret = vfs_splice_from(pipe, out, off, len, flags);
+ 
+               if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
+                       ret = -EFAULT;
+@@ -1140,7 +1142,7 @@ static long do_splice(struct file *in, loff_t __user 
*off_in,
+               } else
+                       off = &in->f_pos;
+ 
+-              ret = do_splice_to(in, off, pipe, len, flags);
++              ret = vfs_splice_to(in, off, pipe, len, flags);
+ 
+               if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
+                       ret = -EFAULT;
 diff --git a/fs/stack.c b/fs/stack.c
-index 67716f6..4336f2b 100644
+index 67716f6..a66ff6c 100644
 --- a/fs/stack.c
 +++ b/fs/stack.c
-@@ -1,24 +1,42 @@
+@@ -1,24 +1,82 @@
 +/*
 + * Copyright (c) 2006-2007 Erez Zadok
 + * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
@@ -660,17 +800,59 @@
   * This function cannot be inlined since i_size_{read,write} is rather
   * heavy-weight on 32-bit systems
   */
- void fsstack_copy_inode_size(struct inode *dst, const struct inode *src)
+-void fsstack_copy_inode_size(struct inode *dst, const struct inode *src)
++void fsstack_copy_inode_size(struct inode *dst, struct inode *src)
  {
 -      i_size_write(dst, i_size_read((struct inode *)src));
-+#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
-+      spin_lock(&dst->i_lock);
-+#endif
-+      i_size_write(dst, i_size_read(src));
-       dst->i_blocks = src->i_blocks;
-+#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
-+      spin_unlock(&dst->i_lock);
-+#endif
+-      dst->i_blocks = src->i_blocks;
++      loff_t i_size;
++      blkcnt_t i_blocks;
++
++      /*
++       * i_size_read() includes its own seqlocking and protection from
++       * preemption (see include/linux/fs.h): we need nothing extra for
++       * that here, and prefer to avoid nesting locks than attempt to
++       * keep i_size and i_blocks in synch together.
++       */
++      i_size = i_size_read(src);
++
++      /*
++       * But if CONFIG_LSF (on 32-bit), we ought to make an effort to keep
++       * the two halves of i_blocks in synch despite SMP or PREEMPT - though
++       * stat's generic_fillattr() doesn't bother, and we won't be applying
++       * quotas (where i_blocks does become important) at the upper level.
++       *
++       * We don't actually know what locking is used at the lower level; but
++       * if it's a filesystem that supports quotas, it will be using i_lock
++       * as in inode_add_bytes().  tmpfs uses other locking, and its 32-bit
++       * is (just) able to exceed 2TB i_size with the aid of holes; but its
++       * i_blocks cannot carry into the upper long without almost 2TB swap -
++       * let's ignore that case.
++       */
++      if (sizeof(i_blocks) > sizeof(long))
++              spin_lock(&src->i_lock);
++      i_blocks = src->i_blocks;
++      if (sizeof(i_blocks) > sizeof(long))
++              spin_unlock(&src->i_lock);
++
++      /*
++       * If CONFIG_SMP on 32-bit, it's vital for fsstack_copy_inode_size()
++       * to hold some lock around i_size_write(), otherwise i_size_read()
++       * may spin forever (see include/linux/fs.h).  We don't necessarily
++       * hold i_mutex when this is called, so take i_lock for that case.
++       *
++       * And if CONFIG_LSF (on 32-bit), continue our effort to keep the
++       * two halves of i_blocks in synch despite SMP or PREEMPT: use i_lock
++       * for that case too, and do both at once by combining the tests.
++       *
++       * There is none of this locking overhead in the 64-bit case.
++       */
++      if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long))
++              spin_lock(&dst->i_lock);
++      i_size_write(dst, i_size);
++      dst->i_blocks = i_blocks;
++      if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long))
++              spin_unlock(&dst->i_lock);
  }
  EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
  
@@ -685,7 +867,7 @@
  {
        dest->i_mode = src->i_mode;
        dest->i_uid = src->i_uid;
-@@ -29,14 +47,6 @@ void fsstack_copy_attr_all(struct inode *dest, const struct 
inode *src,
+@@ -29,14 +87,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;
@@ -703,11 +885,11 @@
  EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
 diff --git a/fs/unionfs/Makefile b/fs/unionfs/Makefile
 new file mode 100644
-index 0000000..917bc7f
+index 0000000..6614204
 --- /dev/null
 +++ b/fs/unionfs/Makefile
 @@ -0,0 +1,17 @@
-+UNIONFS_VERSION="2.2.4 (for 2.6.25-rc2)"
++UNIONFS_VERSION="2.4 (for 2.6.26)"
 +
 +EXTRA_CFLAGS += -DUNIONFS_VERSION=\"$(UNIONFS_VERSION)\"
 +
@@ -715,7 +897,7 @@
 +
 +unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \
 +      rdstate.o copyup.o dirhelper.o rename.o unlink.o \
-+      lookup.o commonfops.o dirfops.o sioq.o mmap.o
++      lookup.o commonfops.o dirfops.o sioq.o mmap.o whiteout.o
 +
 +unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o
 +
@@ -726,12 +908,12 @@
 +endif
 diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
 new file mode 100644
-index 0000000..2add167
+index 0000000..5861970
 --- /dev/null
 +++ b/fs/unionfs/commonfops.c
-@@ -0,0 +1,849 @@
+@@ -0,0 +1,905 @@
 +/*
-+ * Copyright (c) 2003-2007 Erez Zadok
++ * Copyright (c) 2003-2008 Erez Zadok
 + * Copyright (c) 2003-2006 Charles P. Wright
 + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
 + * Copyright (c) 2005-2006 Junjiro Okajima
@@ -740,8 +922,8 @@
 + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
 + * 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 SUNY
++ * Copyright (c) 2003-2008 Stony Brook University
++ * Copyright (c) 2003-2008 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
@@ -982,7 +1164,6 @@
 +      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,
@@ -991,9 +1172,13 @@
 +              else
 +                      err = copyup_deleted_file(file, dentry, bstart,
 +                                                bindex);
-+
-+              if (!err)
++              /* if succeeded, set lower open-file flags and break */
++              if (!err) {
++                      struct file *lower_file;
++                      lower_file = unionfs_lower_file_idx(file, bindex);
++                      lower_file->f_flags = file->f_flags;
 +                      break;
++              }
 +      }
 +      if (err || (bstart <= fbstart(file)))
 +              goto out;
@@ -1004,133 +1189,99 @@
 +                      fput(unionfs_lower_file_idx(file, bindex));
 +                      unionfs_set_lower_file_idx(file, bindex, NULL);
 +              }
-+              if (unionfs_lower_mnt_idx(dentry, bindex)) {
-+                      unionfs_mntput(dentry, bindex);
-+                      unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
-+              }
-+              if (unionfs_lower_dentry_idx(dentry, bindex)) {
-+                      BUG_ON(!dentry->d_inode);
-+                      iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
-+                      unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
-+                                                  NULL);
-+                      dput(unionfs_lower_dentry_idx(dentry, bindex));
-+                      unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
-+              }
 +      }
++      path_put_lowers(dentry, bstart, bend, false);
++      iput_lowers(dentry->d_inode, bstart, bend, false);
 +      /* for reg file, we only open it "once" */
 +      fbend(file) = fbstart(file);
-+      set_dbend(dentry, dbstart(dentry));
++      dbend(dentry) = dbstart(dentry);
 +      ibend(dentry->d_inode) = ibstart(dentry->d_inode);
 +
 +out:
 +      unionfs_check_file(file);
-+      unionfs_check_dentry(dentry);
 +      return err;
 +}
 +
 +/*
-+ * Revalidate the struct file
-+ * @file: file to revalidate
-+ * @willwrite: true if caller may cause changes to the file; false otherwise.
-+ * Caller must lock/unlock dentry's branch configuration.
++ * Helper function for unionfs_file_revalidate/locked.
++ * Expects dentry/parent to be locked already, and revalidated.
 + */
-+int unionfs_file_revalidate_locked(struct file *file, bool willwrite)
++static int __unionfs_file_revalidate(struct file *file, struct dentry *dentry,
++                                   struct super_block *sb, int sbgen,
++                                   int dgen, bool willwrite)
 +{
-+      struct super_block *sb;
-+      struct dentry *dentry;
-+      int sbgen, fgen, dgen;
-+      int bstart, bend;
++      int fgen;
++      int bstart, bend, orig_brid;
 +      int size;
 +      int err = 0;
 +
-+      dentry = file->f_path.dentry;
-+      sb = dentry->d_sb;
-+
-+      /*
-+       * First revalidate the dentry inside struct file,
-+       * but not unhashed dentries.
-+       */
-+reval_dentry:
-+      if (unlikely(!d_deleted(dentry) &&
-+                   !__unionfs_d_revalidate_chain(dentry, NULL, willwrite))) {
-+              err = -ESTALE;
-+              goto out_nofree;
-+      }
-+
-+      sbgen = atomic_read(&UNIONFS_SB(sb)->generation);
-+      dgen = atomic_read(&UNIONFS_D(dentry)->generation);
 +      fgen = atomic_read(&UNIONFS_F(file)->generation);
 +
-+      if (unlikely(sbgen > dgen)) {
-+              pr_debug("unionfs: retry dentry revalidation\n");
-+              schedule();
-+              goto reval_dentry;
-+      }
-+      BUG_ON(sbgen > dgen);
-+
 +      /*
 +       * There are two cases we are interested in.  The first is if the
 +       * generation is lower than the super-block.  The second is if
 +       * someone has copied up this file from underneath us, we also need
 +       * to refresh things.
 +       */
-+      if (unlikely(!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);
-+
-+              /* Now we reopen the file(s) as in unionfs_open. */
-+              bstart = fbstart(file) = dbstart(dentry);
-+              bend = fbend(file) = dbend(dentry);
-+
-+              size = sizeof(struct file *) * sbmax(sb);
-+              UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
-+              if (unlikely(!UNIONFS_F(file)->lower_files)) {
-+                      err = -ENOMEM;
++      if (d_deleted(dentry) ||
++          (sbgen <= fgen &&
++           dbstart(dentry) == fbstart(file) &&
++           unionfs_lower_file(file)))
++              goto out_may_copyup;
++
++      /* save orig branch ID */
++      orig_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)];
++
++      /* First we throw out the existing files. */
++      cleanup_file(file);
++
++      /* Now we reopen the file(s) as in unionfs_open. */
++      bstart = fbstart(file) = dbstart(dentry);
++      bend = fbend(file) = dbend(dentry);
++
++      size = sizeof(struct file *) * sbmax(sb);
++      UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
++      if (unlikely(!UNIONFS_F(file)->lower_files)) {
++              err = -ENOMEM;
++              goto out;
++      }
++      size = sizeof(int) * sbmax(sb);
++      UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
++      if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) {
++              err = -ENOMEM;
++              goto out;
++      }
++
++      if (S_ISDIR(dentry->d_inode->i_mode)) {
<<Diff was trimmed, longer than 597 lines>>

---- CVS-web:
    
http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/SOURCES/kernel-unionfs.patch?r1=1.1.2.1&r2=1.1.2.2&f=u

_______________________________________________
pld-cvs-commit mailing list
[email protected]
http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit

Reply via email to