mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	Linux 4.11 compat: iops.getattr and friends
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
This commit is contained in:
		
							parent
							
								
									f974e41426
								
							
						
					
					
						commit
						a3478c0747
					
				
							
								
								
									
										67
									
								
								config/kernel-inode-getattr.m4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								config/kernel-inode-getattr.m4
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | |||||||
|  | dnl # | ||||||
|  | dnl # Linux 4.11 API | ||||||
|  | dnl # See torvalds/linux@a528d35 | ||||||
|  | dnl # | ||||||
|  | AC_DEFUN([ZFS_AC_PATH_KERNEL_IOPS_GETATTR], [ | ||||||
|  | 	AC_MSG_CHECKING([whether iops->getattr() takes a path]) | ||||||
|  | 	ZFS_LINUX_TRY_COMPILE([ | ||||||
|  | 		#include <linux/fs.h> | ||||||
|  | 
 | ||||||
|  | 		int test_getattr( | ||||||
|  | 		    const struct path *p, struct kstat *k, | ||||||
|  | 		    u32 request_mask, unsigned int query_flags) | ||||||
|  | 		    { return 0; } | ||||||
|  | 
 | ||||||
|  | 		static const struct inode_operations | ||||||
|  | 		    iops __attribute__ ((unused)) = { | ||||||
|  | 			.getattr = test_getattr, | ||||||
|  | 		}; | ||||||
|  | 	],[ | ||||||
|  | 	],[ | ||||||
|  | 		AC_MSG_RESULT(yes) | ||||||
|  | 		AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1, | ||||||
|  | 		    [iops->getattr() takes a path]) | ||||||
|  | 	],[ | ||||||
|  | 		AC_MSG_RESULT(no) | ||||||
|  | 	]) | ||||||
|  | ]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | dnl # | ||||||
|  | dnl # Linux 3.9 - 4.10 API | ||||||
|  | dnl # | ||||||
|  | AC_DEFUN([ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR], [ | ||||||
|  | 	AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount]) | ||||||
|  | 	ZFS_LINUX_TRY_COMPILE([ | ||||||
|  | 		#include <linux/fs.h> | ||||||
|  | 
 | ||||||
|  | 		int test_getattr( | ||||||
|  | 		    struct vfsmount *mnt, struct dentry *d, | ||||||
|  | 		    struct kstat *k) | ||||||
|  | 		    { return 0; } | ||||||
|  | 
 | ||||||
|  | 		static const struct inode_operations | ||||||
|  | 		    iops __attribute__ ((unused)) = { | ||||||
|  | 			.getattr = test_getattr, | ||||||
|  | 		}; | ||||||
|  | 	],[ | ||||||
|  | 	],[ | ||||||
|  | 		AC_MSG_RESULT(yes) | ||||||
|  | 		AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1, | ||||||
|  | 		    [iops->getattr() takes a vfsmount]) | ||||||
|  | 	],[ | ||||||
|  | 		AC_MSG_RESULT(no) | ||||||
|  | 	]) | ||||||
|  | ]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | dnl # | ||||||
|  | dnl # The interface of the getattr callback from the inode_operations | ||||||
|  | dnl # structure changed.  Also, the interface of the simple_getattr() | ||||||
|  | dnl # function provided by the kernel changed. | ||||||
|  | dnl # | ||||||
|  | AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GETATTR], [ | ||||||
|  | 	ZFS_AC_PATH_KERNEL_IOPS_GETATTR | ||||||
|  | 	ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR | ||||||
|  | ]) | ||||||
| @ -59,6 +59,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [ | |||||||
| 	ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS | 	ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS | ||||||
| 	ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL | 	ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL | ||||||
| 	ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL | 	ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL | ||||||
|  | 	ZFS_AC_KERNEL_INODE_OPERATIONS_GETATTR | ||||||
| 	ZFS_AC_KERNEL_INODE_SET_FLAGS | 	ZFS_AC_KERNEL_INODE_SET_FLAGS | ||||||
| 	ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE | 	ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE | ||||||
| 	ZFS_AC_KERNEL_SHOW_OPTIONS | 	ZFS_AC_KERNEL_SHOW_OPTIONS | ||||||
|  | |||||||
| @ -454,4 +454,47 @@ setattr_prepare(struct dentry *dentry, struct iattr *ia) | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * 4.11 API change | ||||||
|  |  * These macros are defined by kernel 4.11.  We define them so that the same | ||||||
|  |  * code builds under kernels < 4.11 and >= 4.11.  The macros are set to 0 so | ||||||
|  |  * that it will create obvious failures if they are accidentally used when built | ||||||
|  |  * against a kernel >= 4.11. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef STATX_BASIC_STATS | ||||||
|  | #define	STATX_BASIC_STATS	0 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #ifndef AT_STATX_SYNC_AS_STAT | ||||||
|  | #define	AT_STATX_SYNC_AS_STAT	0 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * 4.11 API change | ||||||
|  |  * 4.11 takes struct path *, < 4.11 takes vfsmount * | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifdef HAVE_VFSMOUNT_IOPS_GETATTR | ||||||
|  | #define	ZPL_GETATTR_WRAPPER(func)					\ | ||||||
|  | static int								\ | ||||||
|  | func(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)	\ | ||||||
|  | {									\ | ||||||
|  | 	struct path path = { .mnt = mnt, .dentry = dentry };		\ | ||||||
|  | 	return func##_impl(&path, stat, STATX_BASIC_STATS,		\ | ||||||
|  | 	    AT_STATX_SYNC_AS_STAT);					\ | ||||||
|  | } | ||||||
|  | #elif defined(HAVE_PATH_IOPS_GETATTR) | ||||||
|  | #define	ZPL_GETATTR_WRAPPER(func)					\ | ||||||
|  | static int								\ | ||||||
|  | func(const 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 */ | #endif /* _ZFS_VFS_H */ | ||||||
|  | |||||||
| @ -100,16 +100,15 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||||||
|  */ |  */ | ||||||
| /* ARGSUSED */ | /* ARGSUSED */ | ||||||
| static int | static int | ||||||
| zpl_root_getattr(struct vfsmount *mnt, struct dentry *dentry, | zpl_root_getattr_impl(const struct path *path, struct kstat *stat, | ||||||
|     struct kstat *stat) |     u32 request_mask, unsigned int query_flags) | ||||||
| { | { | ||||||
| 	int error; | 	generic_fillattr(path->dentry->d_inode, stat); | ||||||
| 
 |  | ||||||
| 	error = simple_getattr(mnt, dentry, stat); |  | ||||||
| 	stat->atime = CURRENT_TIME; | 	stat->atime = CURRENT_TIME; | ||||||
| 
 | 
 | ||||||
| 	return (error); | 	return (0); | ||||||
| } | } | ||||||
|  | ZPL_GETATTR_WRAPPER(zpl_root_getattr); | ||||||
| 
 | 
 | ||||||
| static struct dentry * | static struct dentry * | ||||||
| #ifdef HAVE_LOOKUP_NAMEIDATA | #ifdef HAVE_LOOKUP_NAMEIDATA | ||||||
| @ -375,21 +374,22 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, zpl_umode_t mode) | |||||||
|  */ |  */ | ||||||
| /* ARGSUSED */ | /* ARGSUSED */ | ||||||
| static int | static int | ||||||
| zpl_snapdir_getattr(struct vfsmount *mnt, struct dentry *dentry, | zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat, | ||||||
|     struct kstat *stat) |     u32 request_mask, unsigned int query_flags) | ||||||
| { | { | ||||||
| 	zfsvfs_t *zfsvfs = ITOZSB(dentry->d_inode); | 	zfsvfs_t *zfsvfs = ITOZSB(path->dentry->d_inode); | ||||||
| 	int error; |  | ||||||
| 
 | 
 | ||||||
| 	ZFS_ENTER(zfsvfs); | 	ZFS_ENTER(zfsvfs); | ||||||
| 	error = simple_getattr(mnt, dentry, stat); | 	generic_fillattr(path->dentry->d_inode, stat); | ||||||
|  | 
 | ||||||
| 	stat->nlink = stat->size = 2; | 	stat->nlink = stat->size = 2; | ||||||
| 	stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zfsvfs->z_os); | 	stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zfsvfs->z_os); | ||||||
| 	stat->atime = CURRENT_TIME; | 	stat->atime = CURRENT_TIME; | ||||||
| 	ZFS_EXIT(zfsvfs); | 	ZFS_EXIT(zfsvfs); | ||||||
| 
 | 
 | ||||||
| 	return (error); | 	return (0); | ||||||
| } | } | ||||||
|  | ZPL_GETATTR_WRAPPER(zpl_snapdir_getattr); | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * The '.zfs/snapshot' directory file operations.  These mainly control |  * The '.zfs/snapshot' directory file operations.  These mainly control | ||||||
| @ -509,10 +509,10 @@ zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||||||
| 
 | 
 | ||||||
| /* ARGSUSED */ | /* ARGSUSED */ | ||||||
| static int | static int | ||||||
| zpl_shares_getattr(struct vfsmount *mnt, struct dentry *dentry, | zpl_shares_getattr_impl(const struct path *path, struct kstat *stat, | ||||||
|     struct kstat *stat) |     u32 request_mask, unsigned int query_flags) | ||||||
| { | { | ||||||
| 	struct inode *ip = dentry->d_inode; | 	struct inode *ip = path->dentry->d_inode; | ||||||
| 	zfsvfs_t *zfsvfs = ITOZSB(ip); | 	zfsvfs_t *zfsvfs = ITOZSB(ip); | ||||||
| 	znode_t *dzp; | 	znode_t *dzp; | ||||||
| 	int error; | 	int error; | ||||||
| @ -520,11 +520,11 @@ zpl_shares_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||||||
| 	ZFS_ENTER(zfsvfs); | 	ZFS_ENTER(zfsvfs); | ||||||
| 
 | 
 | ||||||
| 	if (zfsvfs->z_shares_dir == 0) { | 	if (zfsvfs->z_shares_dir == 0) { | ||||||
| 		error = simple_getattr(mnt, dentry, stat); | 		generic_fillattr(path->dentry->d_inode, stat); | ||||||
| 		stat->nlink = stat->size = 2; | 		stat->nlink = stat->size = 2; | ||||||
| 		stat->atime = CURRENT_TIME; | 		stat->atime = CURRENT_TIME; | ||||||
| 		ZFS_EXIT(zfsvfs); | 		ZFS_EXIT(zfsvfs); | ||||||
| 		return (error); | 		return (0); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp); | 	error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp); | ||||||
| @ -538,6 +538,7 @@ zpl_shares_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||||||
| 
 | 
 | ||||||
| 	return (error); | 	return (error); | ||||||
| } | } | ||||||
|  | ZPL_GETATTR_WRAPPER(zpl_shares_getattr); | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * The '.zfs/shares' directory file operations. |  * The '.zfs/shares' directory file operations. | ||||||
|  | |||||||
| @ -340,18 +340,25 @@ zpl_rmdir(struct inode *dir, struct dentry *dentry) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, | ||||||
|  |     unsigned int query_flags) | ||||||
| { | { | ||||||
| 	int error; | 	int error; | ||||||
| 	fstrans_cookie_t cookie; | 	fstrans_cookie_t cookie; | ||||||
| 
 | 
 | ||||||
| 	cookie = spl_fstrans_mark(); | 	cookie = spl_fstrans_mark(); | ||||||
| 	error = -zfs_getattr_fast(dentry->d_inode, stat); | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * XXX request_mask and query_flags currently ignored. | ||||||
|  | 	 */ | ||||||
|  | 
 | ||||||
|  | 	error = -zfs_getattr_fast(path->dentry->d_inode, stat); | ||||||
| 	spl_fstrans_unmark(cookie); | 	spl_fstrans_unmark(cookie); | ||||||
| 	ASSERT3S(error, <=, 0); | 	ASSERT3S(error, <=, 0); | ||||||
| 
 | 
 | ||||||
| 	return (error); | 	return (error); | ||||||
| } | } | ||||||
|  | ZPL_GETATTR_WRAPPER(zpl_getattr); | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| zpl_setattr(struct dentry *dentry, struct iattr *ia) | zpl_setattr(struct dentry *dentry, struct iattr *ia) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Olaf Faaland
						Olaf Faaland