]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 23 Feb 2015 01:42:14 +0000 (17:42 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 23 Feb 2015 01:42:14 +0000 (17:42 -0800)
Pull more vfs updates from Al Viro:
 "Assorted stuff from this cycle.  The big ones here are multilayer
  overlayfs from Miklos and beginning of sorting ->d_inode accesses out
  from David"

* 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (51 commits)
  autofs4 copy_dev_ioctl(): keep the value of ->size we'd used for allocation
  procfs: fix race between symlink removals and traversals
  debugfs: leave freeing a symlink body until inode eviction
  Documentation/filesystems/Locking: ->get_sb() is long gone
  trylock_super(): replacement for grab_super_passive()
  fanotify: Fix up scripted S_ISDIR/S_ISREG/S_ISLNK conversions
  Cachefiles: Fix up scripted S_ISDIR/S_ISREG/S_ISLNK conversions
  VFS: (Scripted) Convert S_ISLNK/DIR/REG(dentry->d_inode) to d_is_*(dentry)
  SELinux: Use d_is_positive() rather than testing dentry->d_inode
  Smack: Use d_is_positive() rather than testing dentry->d_inode
  TOMOYO: Use d_is_dir() rather than d_inode and S_ISDIR()
  Apparmor: Use d_is_positive/negative() rather than testing dentry->d_inode
  Apparmor: mediated_filesystem() should use dentry->d_sb not inode->i_sb
  VFS: Split DCACHE_FILE_TYPE into regular and special types
  VFS: Add a fallthrough flag for marking virtual dentries
  VFS: Add a whiteout dentry type
  VFS: Introduce inode-getting helpers for layered/unioned fs environments
  Infiniband: Fix potential NULL d_inode dereference
  posix_acl: fix reference leaks in posix_acl_create
  autofs4: Wrong format for printing dentry
  ...

1  2 
drivers/infiniband/hw/qib/qib_fs.c
fs/ceph/dir.c
fs/ceph/file.c
fs/xfs/xfs_ioctl.c

index 55f240a363fe04801bc39b38e41670f0db19b86e,d2427640d7e99a7cdab8329dd0f8f94b3a10bad0..650897a8591e872f338d03994da3ed18e5a51bf7
@@@ -106,7 -106,7 +106,7 @@@ static ssize_t driver_stats_read(struc
  {
        qib_stats.sps_ints = qib_sps_ints();
        return simple_read_from_buffer(buf, count, ppos, &qib_stats,
 -                                     sizeof qib_stats);
 +                                     sizeof(qib_stats));
  }
  
  /*
@@@ -133,7 -133,7 +133,7 @@@ static ssize_t driver_names_read(struc
                                 size_t count, loff_t *ppos)
  {
        return simple_read_from_buffer(buf, count, ppos, qib_statnames,
 -              sizeof qib_statnames - 1); /* no null */
 +              sizeof(qib_statnames) - 1); /* no null */
  }
  
  static const struct file_operations driver_ops[] = {
@@@ -379,7 -379,7 +379,7 @@@ static int add_cntr_files(struct super_
        int ret, i;
  
        /* create the per-unit directory */
 -      snprintf(unit, sizeof unit, "%u", dd->unit);
 +      snprintf(unit, sizeof(unit), "%u", dd->unit);
        ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir,
                          &simple_dir_operations, dd);
        if (ret) {
@@@ -455,7 -455,7 +455,7 @@@ static int remove_file(struct dentry *p
        }
  
        spin_lock(&tmp->d_lock);
-       if (!(d_unhashed(tmp) && tmp->d_inode)) {
+       if (!d_unhashed(tmp) && tmp->d_inode) {
                __d_drop(tmp);
                spin_unlock(&tmp->d_lock);
                simple_unlink(parent->d_inode, tmp);
@@@ -482,7 -482,7 +482,7 @@@ static int remove_device_files(struct s
  
        root = dget(sb->s_root);
        mutex_lock(&root->d_inode->i_mutex);
 -      snprintf(unit, sizeof unit, "%u", dd->unit);
 +      snprintf(unit, sizeof(unit), "%u", dd->unit);
        dir = lookup_one_len(unit, root, strlen(unit));
  
        if (IS_ERR(dir)) {
@@@ -560,7 -560,6 +560,7 @@@ static struct dentry *qibfs_mount(struc
                        const char *dev_name, void *data)
  {
        struct dentry *ret;
 +
        ret = mount_single(fs_type, flags, data, qibfs_fill_super);
        if (!IS_ERR(ret))
                qib_super = ret->d_sb;
diff --combined fs/ceph/dir.c
index 0411dbb15815fd7036dc7f88b5926a4f30190c35,f099aefb0d1913e9de25c0f4aaae6c8b7ba40392..83e9976f718983ccfb5d95c56893e81c7d01caa9
@@@ -26,6 -26,8 +26,6 @@@
   * point by name.
   */
  
 -const struct inode_operations ceph_dir_iops;
 -const struct file_operations ceph_dir_fops;
  const struct dentry_operations ceph_dentry_ops;
  
  /*
@@@ -670,17 -672,13 +670,17 @@@ int ceph_handle_notrace_create(struct i
                /*
                 * We created the item, then did a lookup, and found
                 * it was already linked to another inode we already
 -               * had in our cache (and thus got spliced).  Link our
 -               * dentry to that inode, but don't hash it, just in
 -               * case the VFS wants to dereference it.
 +               * had in our cache (and thus got spliced). To not
 +               * confuse VFS (especially when inode is a directory),
 +               * we don't link our dentry to that inode, return an
 +               * error instead.
 +               *
 +               * This event should be rare and it happens only when
 +               * we talk to old MDS. Recent MDS does not send traceless
 +               * reply for request that creates new inode.
                 */
 -              BUG_ON(!result->d_inode);
 -              d_instantiate(dentry, result->d_inode);
 -              return 0;
 +              d_drop(result);
 +              return -ESTALE;
        }
        return PTR_ERR(result);
  }
@@@ -904,7 -902,7 +904,7 @@@ static int ceph_unlink(struct inode *di
        } else if (ceph_snap(dir) == CEPH_NOSNAP) {
                dout("unlink/rmdir dir %p dn %p inode %p\n",
                     dir, dentry, inode);
-               op = S_ISDIR(dentry->d_inode->i_mode) ?
+               op = d_is_dir(dentry) ?
                        CEPH_MDS_OP_RMDIR : CEPH_MDS_OP_UNLINK;
        } else
                goto out;
@@@ -1337,13 -1335,6 +1337,13 @@@ const struct file_operations ceph_dir_f
        .fsync = ceph_dir_fsync,
  };
  
 +const struct file_operations ceph_snapdir_fops = {
 +      .iterate = ceph_readdir,
 +      .llseek = ceph_dir_llseek,
 +      .open = ceph_open,
 +      .release = ceph_release,
 +};
 +
  const struct inode_operations ceph_dir_iops = {
        .lookup = ceph_lookup,
        .permission = ceph_permission,
        .atomic_open = ceph_atomic_open,
  };
  
 +const struct inode_operations ceph_snapdir_iops = {
 +      .lookup = ceph_lookup,
 +      .permission = ceph_permission,
 +      .getattr = ceph_getattr,
 +      .mkdir = ceph_mkdir,
 +      .rmdir = ceph_unlink,
 +};
 +
  const struct dentry_operations ceph_dentry_ops = {
        .d_revalidate = ceph_d_revalidate,
        .d_release = ceph_d_release,
diff --combined fs/ceph/file.c
index a3d774b351494b64b2f03c6db2d9270017defc76,851939c666f8d0e90104b75e361ee05c42a22fd5..d533075a823d5eb92e709547b8fe790c59cba981
@@@ -275,10 -275,10 +275,10 @@@ int ceph_atomic_open(struct inode *dir
        err = ceph_mdsc_do_request(mdsc,
                                   (flags & (O_CREAT|O_TRUNC)) ? dir : NULL,
                                   req);
 +      err = ceph_handle_snapdir(req, dentry, err);
        if (err)
                goto out_req;
  
 -      err = ceph_handle_snapdir(req, dentry, err);
        if (err == 0 && (flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
                err = ceph_handle_notrace_create(dir, dentry);
  
        }
        if (err)
                goto out_req;
-       if (dn || dentry->d_inode == NULL || S_ISLNK(dentry->d_inode->i_mode)) {
+       if (dn || dentry->d_inode == NULL || d_is_symlink(dentry)) {
                /* make vfs retry on splice, ENOENT, or symlink */
                dout("atomic_open finish_no_open on dn %p\n", dn);
                err = finish_no_open(file, dn);
@@@ -392,14 -392,13 +392,14 @@@ more
        if (ret >= 0) {
                int didpages;
                if (was_short && (pos + ret < inode->i_size)) {
 -                      u64 tmp = min(this_len - ret,
 -                                      inode->i_size - pos - ret);
 +                      int zlen = min(this_len - ret,
 +                                     inode->i_size - pos - ret);
 +                      int zoff = (o_direct ? buf_align : io_align) +
 +                                  read + ret;
                        dout(" zero gap %llu to %llu\n",
 -                              pos + ret, pos + ret + tmp);
 -                      ceph_zero_page_vector_range(page_align + read + ret,
 -                                                      tmp, pages);
 -                      ret += tmp;
 +                              pos + ret, pos + ret + zlen);
 +                      ceph_zero_page_vector_range(zoff, zlen, pages);
 +                      ret += zlen;
                }
  
                didpages = (page_align + ret) >> PAGE_CACHE_SHIFT;
@@@ -879,34 -878,28 +879,34 @@@ again
  
                i_size = i_size_read(inode);
                if (retry_op == READ_INLINE) {
 -                      /* does not support inline data > PAGE_SIZE */
 -                      if (i_size > PAGE_CACHE_SIZE) {
 -                              ret = -EIO;
 -                      } else if (iocb->ki_pos < i_size) {
 +                      BUG_ON(ret > 0 || read > 0);
 +                      if (iocb->ki_pos < i_size &&
 +                          iocb->ki_pos < PAGE_CACHE_SIZE) {
                                loff_t end = min_t(loff_t, i_size,
                                                   iocb->ki_pos + len);
 +                              end = min_t(loff_t, end, PAGE_CACHE_SIZE);
                                if (statret < end)
                                        zero_user_segment(page, statret, end);
                                ret = copy_page_to_iter(page,
                                                iocb->ki_pos & ~PAGE_MASK,
                                                end - iocb->ki_pos, to);
                                iocb->ki_pos += ret;
 -                      } else {
 -                              ret = 0;
 +                              read += ret;
 +                      }
 +                      if (iocb->ki_pos < i_size && read < len) {
 +                              size_t zlen = min_t(size_t, len - read,
 +                                                  i_size - iocb->ki_pos);
 +                              ret = iov_iter_zero(zlen, to);
 +                              iocb->ki_pos += ret;
 +                              read += ret;
                        }
                        __free_pages(page, 0);
 -                      return ret;
 +                      return read;
                }
  
                /* hit EOF or hole? */
                if (retry_op == CHECK_EOF && iocb->ki_pos < i_size &&
 -                      ret < len) {
 +                  ret < len) {
                        dout("sync_read hit hole, ppos %lld < size %lld"
                             ", reading more\n", iocb->ki_pos,
                             inode->i_size);
diff --combined fs/xfs/xfs_ioctl.c
index bf70a2affb05b0b736d27ca1ceebac68015e5f7c,fe3c0fe71e64f8b3702cbaa27666b71d480b1200..ac4feae45eb308c39629f177c0b6620fae77fb69
@@@ -39,7 -39,6 +39,7 @@@
  #include "xfs_icache.h"
  #include "xfs_symlink.h"
  #include "xfs_trans.h"
 +#include "xfs_pnfs.h"
  
  #include <linux/capability.h>
  #include <linux/dcache.h>
@@@ -287,7 -286,7 +287,7 @@@ xfs_readlink_by_handle
                return PTR_ERR(dentry);
  
        /* Restrict this handle operation to symlinks only. */
-       if (!S_ISLNK(dentry->d_inode->i_mode)) {
+       if (!d_is_symlink(dentry)) {
                error = -EINVAL;
                goto out_dput;
        }
@@@ -609,7 -608,6 +609,7 @@@ xfs_ioc_space
  {
        struct iattr            iattr;
        enum xfs_prealloc_flags flags = 0;
 +      uint                    iolock = XFS_IOLOCK_EXCL;
        int                     error;
  
        /*
        if (error)
                return error;
  
 -      xfs_ilock(ip, XFS_IOLOCK_EXCL);
 +      xfs_ilock(ip, iolock);
 +      error = xfs_break_layouts(inode, &iolock);
 +      if (error)
 +              goto out_unlock;
  
        switch (bf->l_whence) {
        case 0: /*SEEK_SET*/
        error = xfs_update_prealloc_flags(ip, flags);
  
  out_unlock:
 -      xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 +      xfs_iunlock(ip, iolock);
        mnt_drop_write_file(filp);
        return error;
  }