kernel: update 3.10 to 3.10.32
[openwrt.git] / target / linux / generic / patches-3.10 / 100-overlayfs.patch
index 32e70eb..02894b3 100644 (file)
          will be called when part or all of the page is to be removed
 --- a/MAINTAINERS
 +++ b/MAINTAINERS
-@@ -5993,6 +5993,13 @@ F:      drivers/scsi/osd/
+@@ -6019,6 +6019,13 @@ F:      drivers/scsi/osd/
  F:    include/scsi/osd_*
  F:    fs/exofs/
  
 +
 +      rc = -EINVAL;
 +      if (s->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
-+              printk(KERN_ERR "eCryptfs: maximum fs stacking depth exceeded\n");
++              pr_err("eCryptfs: maximum fs stacking depth exceeded\n");
 +              goto out_free;
 +      }
  
   * namespace.c
   */
  extern int copy_mount_options(const void __user *, unsigned long *);
+@@ -132,12 +127,6 @@ extern struct dentry *__d_alloc(struct s
+ extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
+ /*
+- * splice.c
+- */
+-extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+-              loff_t *opos, size_t len, unsigned int flags);
+-
+-/*
+  * pipe.c
+  */
+ extern const struct file_operations pipefifo_fops;
 --- a/fs/namei.c
 +++ b/fs/namei.c
 @@ -402,6 +402,7 @@ int __inode_permission(struct inode *ino
  
  /**
   * sb_permission - Check superblock-level permissions
-@@ -2867,9 +2868,12 @@ finish_open_created:
+@@ -2868,9 +2869,12 @@ finish_open_created:
        error = may_open(&nd->path, acc_mode, open_flag);
        if (error)
                goto out;
                goto out;
 --- a/fs/namespace.c
 +++ b/fs/namespace.c
-@@ -1442,6 +1442,24 @@ void drop_collected_mounts(struct vfsmou
+@@ -1442,6 +1442,33 @@ void drop_collected_mounts(struct vfsmou
        namespace_unlock();
  }
  
++/**
++ * clone_private_mount - create a private clone of a path
++ *
++ * This creates a new vfsmount, which will be the clone of @path.  The new will
++ * not be attached anywhere in the namespace and will be private (i.e. changes
++ * to the originating mount won't be propagated into this).
++ *
++ * Release with mntput().
++ */
 +struct vfsmount *clone_private_mount(struct path *path)
 +{
 +      struct mount *old_mnt = real_mount(path->mnt);
 +      down_read(&namespace_sem);
 +      new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
 +      up_read(&namespace_sem);
-+      if (!new_mnt)
-+              return ERR_PTR(-ENOMEM);
++      if (IS_ERR(new_mnt))
++              return ERR_CAST(new_mnt);
 +
 +      return &new_mnt->mnt;
 +}
        int lookup_flags = 0;
 --- /dev/null
 +++ b/fs/overlayfs/Kconfig
-@@ -0,0 +1,4 @@
+@@ -0,0 +1,10 @@
 +config OVERLAYFS_FS
 +      tristate "Overlay filesystem support"
 +      help
-+        Add support for overlay filesystem.
++        An overlay filesystem combines two filesystems - an 'upper' filesystem
++        and a 'lower' filesystem.  When a name exists in both filesystems, the
++        object in the 'upper' filesystem is visible while the object in the
++        'lower' filesystem is either hidden or, in the case of directories,
++        merged with the 'upper' object.
++
++        For more information see Documentation/filesystems/overlayfs.txt
 --- /dev/null
 +++ b/fs/overlayfs/Makefile
 @@ -0,0 +1,7 @@
 +overlayfs-objs := super.o inode.o dir.o readdir.o copy_up.o
 --- /dev/null
 +++ b/fs/overlayfs/copy_up.c
-@@ -0,0 +1,385 @@
+@@ -0,0 +1,387 @@
 +/*
 + *
 + * Copyright (C) 2011 Novell Inc.
 +{
 +      struct file *old_file;
 +      struct file *new_file;
++      loff_t old_pos = 0;
++      loff_t new_pos = 0;
 +      int error = 0;
 +
 +      if (len == 0)
 +
 +      /* FIXME: copy up sparse files efficiently */
 +      while (len) {
-+              loff_t offset = new_file->f_pos;
 +              size_t this_len = OVL_COPY_UP_CHUNK_SIZE;
 +              long bytes;
 +
 +                      break;
 +              }
 +
-+              bytes = do_splice_direct(old_file, &offset, new_file, this_len,
-+                               SPLICE_F_MOVE);
++              bytes = do_splice_direct(old_file, &old_pos,
++                                       new_file, &new_pos,
++                                       this_len, SPLICE_F_MOVE);
 +              if (bytes <= 0) {
 +                      error = bytes;
 +                      break;
 +}
 --- /dev/null
 +++ b/fs/overlayfs/dir.c
-@@ -0,0 +1,604 @@
+@@ -0,0 +1,605 @@
 +/*
 + *
 + * Copyright (C) 2011 Novell Inc.
 +               * There's no way to recover from failure to whiteout.
 +               * What should we do?  Log a big fat error and... ?
 +               */
-+              printk(KERN_ERR "overlayfs: ERROR - failed to whiteout '%s'\n",
++              pr_err("overlayfs: ERROR - failed to whiteout '%s'\n",
 +                     dentry->d_name.name);
 +      }
 +
 +              }
 +              newinode = ovl_new_inode(old->d_sb, newdentry->d_inode->i_mode,
 +                              new->d_fsdata);
-+              if (!newinode)
++              if (!newinode) {
++                      err = -ENOMEM;
 +                      goto link_fail;
++              }
 +              ovl_copyattr(upperdir->d_inode, newinode);
 +
 +              ovl_dentry_version_inc(new->d_parent);
 +      mutex_unlock(&upperdir->d_inode->i_mutex);
 +out:
 +      return err;
-+
 +}
 +
 +static int ovl_rename(struct inode *olddir, struct dentry *old,
 +      loff_t res;
 +      struct ovl_dir_file *od = file->private_data;
 +
-+      mutex_lock(&file->f_dentry->d_inode->i_mutex);
++      mutex_lock(&file_inode(file)->i_mutex);
 +      if (!file->f_pos)
 +              ovl_dir_reset(file);
 +
 +              res = offset;
 +      }
 +out_unlock:
-+      mutex_unlock(&file->f_dentry->d_inode->i_mutex);
++      mutex_unlock(&file_inode(file)->i_mutex);
 +
 +      return res;
 +}
 +
 +              dentry = lookup_one_len(p->name, upperdir, p->len);
 +              if (IS_ERR(dentry)) {
-+                      printk(KERN_WARNING
++                      pr_warn(
 +                          "overlayfs: failed to lookup whiteout %.*s: %li\n",
 +                          p->len, p->name, PTR_ERR(dentry));
 +                      continue;
 +              ret = vfs_unlink(upperdir->d_inode, dentry);
 +              dput(dentry);
 +              if (ret)
-+                      printk(KERN_WARNING
++                      pr_warn(
 +                          "overlayfs: failed to unlink whiteout %.*s: %i\n",
 +                          p->len, p->name, ret);
 +      }
 +
 +struct file *ovl_path_open(struct path *path, int flags)
 +{
-+      path_get(path);
 +      return dentry_open(path, flags, current_cred());
 +}
 +
 +};
 +
 +enum {
-+      Opt_lowerdir,
-+      Opt_upperdir,
-+      Opt_err,
++      OPT_LOWERDIR,
++      OPT_UPPERDIR,
++      OPT_ERR,
 +};
 +
 +static const match_table_t ovl_tokens = {
-+      {Opt_lowerdir,                  "lowerdir=%s"},
-+      {Opt_upperdir,                  "upperdir=%s"},
-+      {Opt_err,                       NULL}
++      {OPT_LOWERDIR,                  "lowerdir=%s"},
++      {OPT_UPPERDIR,                  "upperdir=%s"},
++      {OPT_ERR,                       NULL}
 +};
 +
 +static int ovl_parse_opt(char *opt, struct ovl_config *config)
 +
 +              token = match_token(p, ovl_tokens, args);
 +              switch (token) {
-+              case Opt_upperdir:
++              case OPT_UPPERDIR:
 +                      kfree(config->upperdir);
 +                      config->upperdir = match_strdup(&args[0]);
 +                      if (!config->upperdir)
 +                              return -ENOMEM;
 +                      break;
 +
-+              case Opt_lowerdir:
++              case OPT_LOWERDIR:
 +                      kfree(config->lowerdir);
 +                      config->lowerdir = match_strdup(&args[0]);
 +                      if (!config->lowerdir)
 +
 +      err = -EINVAL;
 +      if (!ufs->config.upperdir || !ufs->config.lowerdir) {
-+              printk(KERN_ERR "overlayfs: missing upperdir or lowerdir\n");
++              pr_err("overlayfs: missing upperdir or lowerdir\n");
 +              goto out_free_config;
 +      }
 +
 +
 +      err = vfs_statfs(&lowerpath, &statfs);
 +      if (err) {
-+              printk(KERN_ERR "overlayfs: statfs failed on lowerpath\n");
++              pr_err("overlayfs: statfs failed on lowerpath\n");
 +              goto out_put_lowerpath;
 +      }
 +      ufs->lower_namelen = statfs.f_namelen;
 +
 +      err = -EINVAL;
 +      if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
-+              printk(KERN_ERR "overlayfs: maximum fs stacking depth exceeded\n");
++              pr_err("overlayfs: maximum fs stacking depth exceeded\n");
 +              goto out_put_lowerpath;
 +      }
 +
 +      ufs->upper_mnt = clone_private_mount(&upperpath);
 +      err = PTR_ERR(ufs->upper_mnt);
 +      if (IS_ERR(ufs->upper_mnt)) {
-+              printk(KERN_ERR "overlayfs: failed to clone upperpath\n");
++              pr_err("overlayfs: failed to clone upperpath\n");
 +              goto out_put_lowerpath;
 +      }
 +
 +      ufs->lower_mnt = clone_private_mount(&lowerpath);
 +      err = PTR_ERR(ufs->lower_mnt);
 +      if (IS_ERR(ufs->lower_mnt)) {
-+              printk(KERN_ERR "overlayfs: failed to clone lowerpath\n");
++              pr_err("overlayfs: failed to clone lowerpath\n");
 +              goto out_put_upper_mnt;
 +      }
 +
 +      .mount          = ovl_mount,
 +      .kill_sb        = kill_anon_super,
 +};
++MODULE_ALIAS_FS("overlayfs");
 +
 +static int __init ovl_init(void)
 +{
 +module_exit(ovl_exit);
 --- a/fs/splice.c
 +++ b/fs/splice.c
-@@ -1311,6 +1311,7 @@ long do_splice_direct(struct file *in, l
+@@ -1331,6 +1331,7 @@ long do_splice_direct(struct file *in, l
  
        return ret;
  }
  extern int generic_permission(struct inode *, int);
  
  static inline bool execute_ok(struct inode *inode)
+@@ -2414,6 +2428,9 @@ extern ssize_t generic_file_splice_write
+               struct file *, loff_t *, size_t, unsigned int);
+ extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
+               struct file *out, loff_t *, size_t len, unsigned int flags);
++extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
++              loff_t *opos, size_t len, unsigned int flags);
++
+ extern void
+ file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
 --- a/include/linux/mount.h
 +++ b/include/linux/mount.h
 @@ -68,6 +68,9 @@ extern void mnt_pin(struct vfsmount *mnt