Re: [PATCH 3/3] nfs: Store and use inode in nfs_open_context

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 03/04/2016 07:41 AM, Trond Myklebust wrote:
On Fri, Mar 4, 2016 at 5:17 AM, Miklos Szeredi <miklos@xxxxxxxxxx> wrote:
On Thu, Mar 03, 2016 at 09:16:33AM +0100, Miklos Szeredi wrote:
My plan was to introduce a file_dentry() helper that MUST be used by
filesystems to get the dentry from the file and that makes sure it's
the right one (check against file_inode()).   If not, then we could
call into overlayfs to return the right one, similar to
->d_select_inode(), except we want to have a dentry and we want to
have *a particular dentry* matching file_inode() (the file could have
been copied up in the mean time).

Something like the following (untested, against overlayfs-next.git)

Thanks,
Miklos

---
  fs/nfs/dir.c           |    6 +++---
  fs/nfs/inode.c         |    2 +-
  fs/nfs/nfs4file.c      |    4 ++--
  fs/open.c              |   11 +++++++++++
  fs/overlayfs/super.c   |   16 ++++++++++++++++
  include/linux/dcache.h |    1 +
  include/linux/fs.h     |    2 ++
  7 files changed, 36 insertions(+), 6 deletions(-)

--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -377,7 +377,7 @@ int nfs_readdir_xdr_filler(struct page *
   again:
         timestamp = jiffies;
         gencount = nfs_inc_attr_generation_counter();
-       error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, entry->cookie, pages,
+       error = NFS_PROTO(inode)->readdir(file_dentry(file), cred, entry->cookie, pages,
                                           NFS_SERVER(inode)->dtsize, desc->plus);
         if (error < 0) {
                 /* We requested READDIRPLUS, but the server doesn't grok it */
@@ -560,7 +560,7 @@ int nfs_readdir_page_filler(nfs_readdir_
                 count++;

                 if (desc->plus != 0)
-                       nfs_prime_dcache(desc->file->f_path.dentry, entry);
+                       nfs_prime_dcache(file_dentry(desc->file), entry);

                 status = nfs_readdir_add_to_array(entry, page);
                 if (status != 0)
@@ -864,7 +864,7 @@ static bool nfs_dir_mapping_need_revalid
   */
  static int nfs_readdir(struct file *file, struct dir_context *ctx)
  {
-       struct dentry   *dentry = file->f_path.dentry;
+       struct dentry   *dentry = file_dentry(file);
         struct inode    *inode = d_inode(dentry);
         nfs_readdir_descriptor_t my_desc,
                         *desc = &my_desc;
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -940,7 +940,7 @@ int nfs_open(struct inode *inode, struct
  {
         struct nfs_open_context *ctx;

-       ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
+       ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode);
         if (IS_ERR(ctx))
                 return PTR_ERR(ctx);
         nfs_file_set_open_context(filp, ctx);
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -26,7 +26,7 @@ static int
  nfs4_file_open(struct inode *inode, struct file *filp)
  {
         struct nfs_open_context *ctx;
-       struct dentry *dentry = filp->f_path.dentry;
+       struct dentry *dentry = file_dentry(filp);
         struct dentry *parent = NULL;
         struct inode *dir;
         unsigned openflags = filp->f_flags;
@@ -57,7 +57,7 @@ nfs4_file_open(struct inode *inode, stru
         parent = dget_parent(dentry);
         dir = d_inode(parent);

-       ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
+       ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode);
         err = PTR_ERR(ctx);
         if (IS_ERR(ctx))
                 goto out;
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1234,6 +1234,8 @@ static inline struct inode *file_inode(c
         return f->f_inode;
  }

+extern struct dentry *file_dentry(const struct file *file);
+
  static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl)
  {
         return locks_lock_inode_wait(file_inode(filp), fl);
--- a/fs/open.c
+++ b/fs/open.c
@@ -831,6 +831,17 @@ char *file_path(struct file *filp, char
  }
  EXPORT_SYMBOL(file_path);

+struct dentry *file_dentry(const struct file *file)
+{
+       struct dentry *dentry = file->f_path.dentry;
+
+       if (d_inode(dentry) == file_inode(file))
+               return dentry;
+       else
+               return dentry->d_op->d_select_dentry(dentry, file_inode(file));
+}
+EXPORT_SYMBOL(file_dentry);
+
  /**
   * vfs_open - open the file at the given path
   * @path: path to open
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -336,14 +336,30 @@ static int ovl_dentry_weak_revalidate(st
         return ret;
  }

+static struct dentry *ovl_d_select_dentry(struct dentry *dentry,
+                                        struct inode *inode)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+       struct dentry *realentry = ovl_upperdentry_dereference(oe);
+
+       if (realentry && inode == d_inode(realentry))
+               return realentry;
+       realentry = __ovl_dentry_lower(oe);
+       if (realentry && inode == d_inode(realentry))
+               return realentry;
+       BUG();
+}
+
  static const struct dentry_operations ovl_dentry_operations = {
         .d_release = ovl_dentry_release,
         .d_select_inode = ovl_d_select_inode,
+       .d_select_dentry = ovl_d_select_dentry,
  };

  static const struct dentry_operations ovl_reval_dentry_operations = {
         .d_release = ovl_dentry_release,
         .d_select_inode = ovl_d_select_inode,
+       .d_select_dentry = ovl_d_select_dentry,
         .d_revalidate = ovl_dentry_revalidate,
         .d_weak_revalidate = ovl_dentry_weak_revalidate,
  };
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -161,6 +161,7 @@ struct dentry_operations {
         struct vfsmount *(*d_automount)(struct path *);
         int (*d_manage)(struct dentry *, bool);
         struct inode *(*d_select_inode)(struct dentry *, unsigned);
+       struct dentry *(*d_select_dentry)(struct dentry *, struct inode *);
  } ____cacheline_aligned;

  /*

Thanks Miklos! That looks reasonable, assuming it tests out correctly.


Tested and it looks good. Thanks Miklos.

Tested-by: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx>


--
Goldwyn
--
To unsubscribe from this list: send the line "unsubscribe linux-unionfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux