Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux 4.11 compat getattr/struct kstat changes #5875

Merged
merged 1 commit into from
Mar 21, 2017

Conversation

ofaaland
Copy link
Contributor

@ofaaland ofaaland commented Mar 7, 2017

Description

Accomodate changes to struct kstat and getattr-related interfaces. See also the related SPL changes.
Requires-spl: refs/pull/608/head

Motivation and Context

Linux 4.11 struct kstat and getattr-related interface changes breaks build.

How Has This Been Tested?

Built and tested with ztest on x86_64 RHEL7 VM. Depending on builbot for more complete testing.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the ZFS on Linux code style requirements.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • Change has been approved by a ZFS on Linux member.

@mention-bot
Copy link

@ofaaland, thanks for your PR! By analyzing the history of the files in this pull request, we identified @gmelikov, @dajhorn and @behlendorf to be potential reviewers.

@ofaaland ofaaland added Type: Building Indicates an issue related to building binaries Status: Work in Progress Not yet ready for general review labels Mar 7, 2017
@ofaaland ofaaland force-pushed the b_vfs_getattr branch 2 times, most recently from c77fc03 to d29eda8 Compare March 8, 2017 00:45
@tuxoko
Copy link
Contributor

tuxoko commented Mar 8, 2017

@ofaaland
iops->getattr and related stuffs are also changed

@ofaaland
Copy link
Contributor Author

ofaaland commented Mar 8, 2017

Yep.

@ofaaland
Copy link
Contributor Author

ofaaland commented Mar 9, 2017

This first crack at handling the iops->getattr and simple_getattr() changes is mostly just to get it to build and ensure the configure checks are working.

@ofaaland ofaaland force-pushed the b_vfs_getattr branch 4 times, most recently from d8ef1d3 to bec4989 Compare March 9, 2017 01:41
tuxoko
tuxoko previously requested changes Mar 9, 2017
#include <linux/fs.h>

int test_getattr(
const struct path *p, struct dentry *d, struct kstat *k,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no dentry in the new form.

u32 request_mask,
unsigned int query_flags
#endif /* defined(HAVE_PATH_SIMPLE_GETATTR) */
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use new form for this function, and make a wrapper function with old form inside ifdef

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tuxoko,
Thanks for the feedback and pointing out the dentry error.

I'm not certain I understand what you mean. Using this function as an example, it must provide the same interface as simple_getattr() and also calls simple_getattr() within its body, so it seems to me that one either has conditional blocks like this, or separate implementations so that the arguments received can be passed on to the simple_getattr() call.

That said, I agree this is not easy to read and likely not the best way. Brian pointed out that in some cases I could move the common logic into an _impl function and then have one version with the old interface and one with the new, wrapped in the appropriate ifdefs, that both call the same common function after making the simple_getattr() call appropriately.

I just pushed an update that fixes the mistakes that earlier were preventing it from building. I'll work on it more tomorrow.

@tuxoko
Copy link
Contributor

tuxoko commented Mar 10, 2017

diff --git a/include/linux/vfs_compat.h b/include/linux/vfs_compat.h
index baa2980..e093e46 100644
--- a/include/linux/vfs_compat.h
+++ b/include/linux/vfs_compat.h
@@ -454,4 +454,26 @@ setattr_prepare(struct dentry *dentry, struct iattr *ia)
 }
 #endif
 
+#ifdef HAVE_3ARGS_IOPS_GETATTR
+#define	GETATTR_WRAPPER(func)						\
+static int								\
+func(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)	\
+{									\
+	struct path = { .mnt = mnt, .dentry = dentry };			\
+	return func##_impl(&path, stat, STATX_BASIC_STATS,		\
+	    AT_STATX_SYNC_AS_STAT);					\
+}
+#elif defined(HAVE_4ARGS_IOPS_GETATTR)
+#define	GETATTR_WRAPPER(func)						\
+static int								\
+func(struct path *path, struct kstat *stat, u32 request_mask,		\
+    unsigned int query_flags)						\
+{									\
+	return func##_impl(path, stat, request_mask, query_flags);	\
+}
+#else
+#error
+#endif
+
+
 #endif /* _ZFS_VFS_H */
diff --git a/module/zfs/zpl_ctldir.c b/module/zfs/zpl_ctldir.c
index cdd6668..18ca1d4 100644
--- a/module/zfs/zpl_ctldir.c
+++ b/module/zfs/zpl_ctldir.c
@@ -100,16 +100,21 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
  */
 /* ARGSUSED */
 static int
-zpl_root_getattr(struct vfsmount *mnt, struct dentry *dentry,
-    struct kstat *stat)
+zpl_root_getattr_impl(struct path *path, struct kstat *stat, u32 request_mask,
+    unsigned int query_flags)
 {
 	int error;
 
-	error = simple_getattr(mnt, dentry, stat);
+#ifdef HAVE_3ARGS_IOPS_GETATTR
+	error = simple_getattr(path->mnt, path->dentry, stat);
+#else
+	error = simple_getattr(path, stat, request_mask, query_flags);
+#endif
 	stat->atime = CURRENT_TIME;
 
 	return (error);
 }
+GETATTR_WRAPPER(zpl_root_getattr);
 
 static struct dentry *
 #ifdef HAVE_LOOKUP_NAMEIDATA
@@ -375,14 +380,18 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, zpl_umode_t mode)
  */
 /* ARGSUSED */
 static int
-zpl_snapdir_getattr(struct vfsmount *mnt, struct dentry *dentry,
-    struct kstat *stat)
+zpl_snapdir_getattr_impl(struct path *path, struct kstat *stat, u32 request_mask,
+    unsigned int query_flags)
 {
 	zfs_sb_t *zsb = ITOZSB(dentry->d_inode);
 	int error;
 
 	ZFS_ENTER(zsb);
-	error = simple_getattr(mnt, dentry, stat);
+#ifdef HAVE_3ARGS_IOPS_GETATTR
+	error = simple_getattr(path->mnt, path->dentry, stat);
+#else
+	error = simple_getattr(path, stat, request_mask, query_flags);
+#endif
 	stat->nlink = stat->size = 2;
 	stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zsb->z_os);
 	stat->atime = CURRENT_TIME;
@@ -390,6 +399,7 @@ zpl_snapdir_getattr(struct vfsmount *mnt, struct dentry *dentry,
 
 	return (error);
 }
+GETATTR_WRAPPER(zpl_root_getattr);
 
 /*
  * The '.zfs/snapshot' directory file operations.  These mainly control
diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c
index b39a8bb..dc6af11 100644
--- a/module/zfs/zpl_inode.c
+++ b/module/zfs/zpl_inode.c
@@ -340,18 +340,20 @@ zpl_rmdir(struct inode *dir, struct dentry *dentry)
 }
 
 static int
-zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+zpl_getattr_impl(struct path *path, struct kstat *stat, u32 request_mask,
+    unsigned int query_flags)
 {
 	int error;
 	fstrans_cookie_t cookie;
 
 	cookie = spl_fstrans_mark();
-	error = -zfs_getattr_fast(dentry->d_inode, stat);
+	error = -zfs_getattr_fast(path->dentry->d_inode, stat);
 	spl_fstrans_unmark(cookie);
 	ASSERT3S(error, <=, 0);
 
 	return (error);
 }
+GETATTR_WRAPPER(zpl_getattr);
 
 static int
 zpl_setattr(struct dentry *dentry, struct iattr *ia)

@ofaaland
Can you try something like this.

@ofaaland
Copy link
Contributor Author

@tuxoko, I see. I got sidetracked but will come back to this. I personally dislike using token pasting with function names because I depend a lot on tagging around. But it does clean up some of the mess and make the new interface stand out a lot better. I'll play with it more tomorrow.

@behlendorf
Copy link
Contributor

We do something similar to this already in zpl_xattr.c. I think this could be OK if we also provided a wrapper for simple_getattr(). Also if we do go this route lets call the wrapper macro ZPL_GETATTR_WRAPPER which is consistent with the xattr version.

@ofaaland ofaaland force-pushed the b_vfs_getattr branch 5 times, most recently from 8f86252 to 73e8c64 Compare March 16, 2017 02:06
@ofaaland ofaaland dismissed tuxoko’s stale review March 16, 2017 17:28

Made the suggested change

* Used by zpl*getattr* functions below.
*/
static int
zpl_simple_getattr(const struct path *path, struct kstat *stat,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should get rid of this function and just call generic_fillattr. That'll make things much easier.
The only difference is simple_getattr stat->blocks = inode->i_mapping->nrpages << (PAGE_SHIFT - 9); which we don't really use since the caller are all directories.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea.

tuxoko
tuxoko previously requested changes Mar 16, 2017
/* Must be set before the call to generic_fillattr() */
stat->result_mask = STATX_BASIC_STATS;
#endif /* defined(HAVE_STAT_RESULT_MASK) */

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this chunk, this is already done in vfs layer.
http://elixir.free-electrons.com/source/fs/stat.c?v=4.11-rc2#L67

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done by vfs_getattr(), but not by simple_getattr() or generic_fillattr().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, and this function and simple_getattr are both hooks for iop->getattr(), so we don't need to do it if simple_getattr() don't do it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

@ofaaland ofaaland dismissed tuxoko’s stale review March 16, 2017 19:59

Made the requested changes.

@ofaaland ofaaland removed the Status: Work in Progress Not yet ready for general review label Mar 16, 2017
@ofaaland ofaaland changed the title [WIP] SPL PR #608 for Linux 4.11 compat vfs_getattr() change SPL PR #608 for Linux 4.11 compat vfs_getattr() change Mar 16, 2017
@ofaaland ofaaland changed the title SPL PR #608 for Linux 4.11 compat vfs_getattr() change SPL PR #608 for Linux 4.11 compat getattr/struct kstat changes Mar 16, 2017
@ofaaland ofaaland changed the title SPL PR #608 for Linux 4.11 compat getattr/struct kstat changes Linux 4.11 compat getattr/struct kstat changes Mar 16, 2017
int error;

error = simple_getattr(mnt, dentry, stat);
generic_fillattr(path->dentry->d_inode, stat);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching to generic_fillattr() means we're dropping the blocks update. However, that shouldn't be an issue since these are all virtual directories anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generic_fillattr does set blocks from i_blocks. simple_getattr set blocks according to mmapped pages which only makes sense for tmpfs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point

],[
AC_MSG_RESULT(no)
])
])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is entirely unused. Did you intend to use it in the actual patch?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was used for code that got removed. I'll remove it and push again.

@behlendorf
Copy link
Contributor

Almost there, one remaining fix.

configure:19136: error: possibly undefined macro: ZFS_AC_KERNEL_STAT_RESULT_MASK

In torvalds/linux@a528d35, there are changes to the getattr family of functions,
struct kstat, and the interface of inode_operations .getattr.

The inode_operations .getattr and simple_getattr() interface changed to:

int (*getattr) (const struct path *, struct dentry *, struct kstat *,
    u32 request_mask, unsigned int query_flags)

The request_mask argument indicates which field(s) the caller intends to use.
Fields the caller has not specified via request_mask may be set in the returned
struct anyway, but their values may be approximate.

The query_flags argument indicates whether the filesystem must update
the attributes from the backing store.

Currently both fields are ignored.  It is possible that getattr-related
functions within zfs could be optimized based on the request_mask.

struct kstat includes new fields:
u32               result_mask;  /* What fields the user got */
u64               attributes;   /* See STATX_ATTR_* flags */
struct timespec   btime;        /* File creation time */

Fields attribute and btime are cleared; the result_mask reflects this.  These
appear to be optional based on simple_getattr() and vfs_getattr() within the
kernel, which take the same approach.

Requires-spl: refs/pull/608/head

Signed-off-by: Olaf Faaland <faaland1@llnl.gov>
@behlendorf behlendorf merged commit a3478c0 into openzfs:master Mar 21, 2017
@behlendorf
Copy link
Contributor

@ofaaland @tuxoko thanks! It's great to have this fixed!

@ofaaland ofaaland deleted the b_vfs_getattr branch April 13, 2017 00:34
l1k pushed a commit to l1k/zfs that referenced this pull request Apr 17, 2017
In torvalds/linux@a528d35, there are changes to the getattr family of functions,
struct kstat, and the interface of inode_operations .getattr.

The inode_operations .getattr and simple_getattr() interface changed to:

int (*getattr) (const struct path *, struct dentry *, struct kstat *,
    u32 request_mask, unsigned int query_flags)

The request_mask argument indicates which field(s) the caller intends to use.
Fields the caller has not specified via request_mask may be set in the returned
struct anyway, but their values may be approximate.

The query_flags argument indicates whether the filesystem must update
the attributes from the backing store.

Currently both fields are ignored.  It is possible that getattr-related
functions within zfs could be optimized based on the request_mask.

struct kstat includes new fields:
u32               result_mask;  /* What fields the user got */
u64               attributes;   /* See STATX_ATTR_* flags */
struct timespec   btime;        /* File creation time */

Fields attribute and btime are cleared; the result_mask reflects this.  These
appear to be optional based on simple_getattr() and vfs_getattr() within the
kernel, which take the same approach.

Reviewed-by: Chunwei Chen <david.chen@osnexus.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Olaf Faaland <faaland1@llnl.gov>
Closes openzfs#5875
tonyhutter pushed a commit to tonyhutter/zfs that referenced this pull request May 18, 2017
In torvalds/linux@a528d35, there are changes to the getattr family of functions,
struct kstat, and the interface of inode_operations .getattr.

The inode_operations .getattr and simple_getattr() interface changed to:

int (*getattr) (const struct path *, struct dentry *, struct kstat *,
    u32 request_mask, unsigned int query_flags)

The request_mask argument indicates which field(s) the caller intends to use.
Fields the caller has not specified via request_mask may be set in the returned
struct anyway, but their values may be approximate.

The query_flags argument indicates whether the filesystem must update
the attributes from the backing store.

Currently both fields are ignored.  It is possible that getattr-related
functions within zfs could be optimized based on the request_mask.

struct kstat includes new fields:
u32               result_mask;  /* What fields the user got */
u64               attributes;   /* See STATX_ATTR_* flags */
struct timespec   btime;        /* File creation time */

Fields attribute and btime are cleared; the result_mask reflects this.  These
appear to be optional based on simple_getattr() and vfs_getattr() within the
kernel, which take the same approach.

Reviewed-by: Chunwei Chen <david.chen@osnexus.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Olaf Faaland <faaland1@llnl.gov>
Closes openzfs#5875
@jgottula
Copy link
Contributor

I'm reasonably certain that this 4.11 compat patch (a3478c0) is responsible for a new(ish) bug related to automounting in .zfs/snapshot: #6154

@svde
Copy link

svde commented Jun 2, 2017

Fedora 25 was updated to 4.11.3-200.fc25. This bug is preventing the dkms module from building.

tonyhutter pushed a commit that referenced this pull request Jun 9, 2017
In torvalds/linux@a528d35, there are changes to the getattr family of functions,
struct kstat, and the interface of inode_operations .getattr.

The inode_operations .getattr and simple_getattr() interface changed to:

int (*getattr) (const struct path *, struct dentry *, struct kstat *,
    u32 request_mask, unsigned int query_flags)

The request_mask argument indicates which field(s) the caller intends to use.
Fields the caller has not specified via request_mask may be set in the returned
struct anyway, but their values may be approximate.

The query_flags argument indicates whether the filesystem must update
the attributes from the backing store.

Currently both fields are ignored.  It is possible that getattr-related
functions within zfs could be optimized based on the request_mask.

struct kstat includes new fields:
u32               result_mask;  /* What fields the user got */
u64               attributes;   /* See STATX_ATTR_* flags */
struct timespec   btime;        /* File creation time */

Fields attribute and btime are cleared; the result_mask reflects this.  These
appear to be optional based on simple_getattr() and vfs_getattr() within the
kernel, which take the same approach.

Reviewed-by: Chunwei Chen <david.chen@osnexus.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Olaf Faaland <faaland1@llnl.gov>
Closes #5875
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Building Indicates an issue related to building binaries
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants