mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Linux 4.5 compat: xattr list handler
The registered xattr .list handler was simplified in the 4.5 kernel
to only perform a permission check. Given a dentry for the file it
must return a boolean indicating if the name is visible. This
differs slightly from the previous APIs which also required the
function to copy the name in to the provided list and return its
size. That is now all the responsibility of the caller.
This should be straight forward change to make to ZoL since we've
always required the caller to make the copy. However, this was
slightly complicated by the need to support 3 older APIs. Yes,
between 2.6.32 and 4.5 there are 4 versions of this interface!
Therefore, while the functional change in this patch is small it
includes significant cleanup to make the code understandable and
maintainable. These changes include:
- Improved configure checks for .list, .get, and .set interfaces.
- Interfaces checked from newest to oldest.
- Strict checking for each possible known interface.
- Configure fails when no known interface is available.
- HAVE_*_XATTR_LIST renamed HAVE_XATTR_LIST_* for consistency
with similar iops and fops configure checks.
- POSIX_ACL_XATTR_{DEFAULT|ACCESS} were removed forcing callers to
move to their replacements, XATTR_NAME_POSIX_ACL_{DEFAULT|ACCESS}.
Compatibility wrapper were added for old kernels.
- ZPL_XATTR_LIST_WRAPPER added which behaves the same as the existing
ZPL_XATTR_{GET|SET} WRAPPERs. Only the inode is guaranteed to be
a valid pointer, passing NULL for the 'list' and 'name' variables
is allowed and must be checked for. All .list functions were
updated to use the wrapper to aid readability.
- zpl_xattr_filldir() updated to use the .list function for its
permission check which is consistent with the updated Linux 4.5
interface. If a .list function is registered it should return 0
to indicate a name should be skipped, if there is no registered
function the name will be added.
- Additional documentation from xattr(7) describing the correct
behavior for each namespace was added before the relevant handlers.
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tim Chase <tim@chase2k.com>
Signed-off-by: Chunwei Chen <tuxoko@gmail.com>
Issue #4228
This commit is contained in:
@@ -41,12 +41,86 @@ typedef const struct xattr_handler xattr_handler_t;
|
||||
typedef struct xattr_handler xattr_handler_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 3.7 API change,
|
||||
* Preferred XATTR_NAME_* definitions introduced, these are mapped to
|
||||
* the previous definitions for older kernels.
|
||||
*/
|
||||
#ifndef XATTR_NAME_POSIX_ACL_DEFAULT
|
||||
#define XATTR_NAME_POSIX_ACL_DEFAULT POSIX_ACL_XATTR_DEFAULT
|
||||
#endif
|
||||
|
||||
#ifndef XATTR_NAME_POSIX_ACL_ACCESS
|
||||
#define XATTR_NAME_POSIX_ACL_ACCESS POSIX_ACL_XATTR_ACCESS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 4.5 API change,
|
||||
*/
|
||||
#if defined(HAVE_XATTR_LIST_SIMPLE)
|
||||
#define ZPL_XATTR_LIST_WRAPPER(fn) \
|
||||
static bool \
|
||||
fn(struct dentry *dentry) \
|
||||
{ \
|
||||
return (!!__ ## fn(dentry->d_inode, NULL, 0, NULL, 0)); \
|
||||
}
|
||||
/*
|
||||
* 4.4 API change,
|
||||
*/
|
||||
#elif defined(HAVE_XATTR_LIST_DENTRY)
|
||||
#define ZPL_XATTR_LIST_WRAPPER(fn) \
|
||||
static size_t \
|
||||
fn(struct dentry *dentry, char *list, size_t list_size, \
|
||||
const char *name, size_t name_len, int type) \
|
||||
{ \
|
||||
return (__ ## fn(dentry->d_inode, \
|
||||
list, list_size, name, name_len)); \
|
||||
}
|
||||
/*
|
||||
* 2.6.33 API change,
|
||||
* The xattr_hander->get() callback was changed to take a dentry
|
||||
*/
|
||||
#elif defined(HAVE_XATTR_LIST_HANDLER)
|
||||
#define ZPL_XATTR_LIST_WRAPPER(fn) \
|
||||
static size_t \
|
||||
fn(const struct xattr_handler *handler, struct dentry *dentry, \
|
||||
char *list, size_t list_size, const char *name, size_t name_len) \
|
||||
{ \
|
||||
return (__ ## fn(dentry->d_inode, \
|
||||
list, list_size, name, name_len)); \
|
||||
}
|
||||
/*
|
||||
* 2.6.32 API
|
||||
*/
|
||||
#elif defined(HAVE_XATTR_LIST_INODE)
|
||||
#define ZPL_XATTR_LIST_WRAPPER(fn) \
|
||||
static size_t \
|
||||
fn(struct inode *ip, char *list, size_t list_size, \
|
||||
const char *name, size_t name_len) \
|
||||
{ \
|
||||
return (__ ## fn(ip, list, list_size, name, name_len)); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 4.4 API change,
|
||||
* The xattr_handler->get() callback was changed to take a xattr_handler,
|
||||
* and handler_flags argument was removed and should be accessed by
|
||||
* handler->flags.
|
||||
*/
|
||||
#if defined(HAVE_XATTR_GET_HANDLER)
|
||||
#define ZPL_XATTR_GET_WRAPPER(fn) \
|
||||
static int \
|
||||
fn(const struct xattr_handler *handler, struct dentry *dentry, \
|
||||
const char *name, void *buffer, size_t size) \
|
||||
{ \
|
||||
return (__ ## fn(dentry->d_inode, name, buffer, size)); \
|
||||
}
|
||||
/*
|
||||
* 2.6.33 API change,
|
||||
* The xattr_handler->get() callback was changed to take a dentry
|
||||
* instead of an inode, and a handler_flags argument was added.
|
||||
*/
|
||||
#ifdef HAVE_DENTRY_XATTR_GET
|
||||
#elif defined(HAVE_XATTR_GET_DENTRY)
|
||||
#define ZPL_XATTR_GET_WRAPPER(fn) \
|
||||
static int \
|
||||
fn(struct dentry *dentry, const char *name, void *buffer, size_t size, \
|
||||
@@ -55,34 +129,37 @@ fn(struct dentry *dentry, const char *name, void *buffer, size_t size, \
|
||||
return (__ ## fn(dentry->d_inode, name, buffer, size)); \
|
||||
}
|
||||
/*
|
||||
* 4.4 API change,
|
||||
* The xattr_hander->get() callback was changed to take a xattr_handler,
|
||||
* and handler_flags argument was removed and should be accessed by
|
||||
* handler->flags.
|
||||
* 2.6.32 API
|
||||
*/
|
||||
#elif defined(HAVE_HANDLER_XATTR_GET)
|
||||
#define ZPL_XATTR_GET_WRAPPER(fn) \
|
||||
static int \
|
||||
fn(const struct xattr_handler *handler, struct dentry *dentry, \
|
||||
const char *name, void *buffer, size_t size) \
|
||||
{ \
|
||||
return (__ ## fn(dentry->d_inode, name, buffer, size)); \
|
||||
}
|
||||
#else
|
||||
#elif defined(HAVE_XATTR_GET_INODE)
|
||||
#define ZPL_XATTR_GET_WRAPPER(fn) \
|
||||
static int \
|
||||
fn(struct inode *ip, const char *name, void *buffer, size_t size) \
|
||||
{ \
|
||||
return (__ ## fn(ip, name, buffer, size)); \
|
||||
}
|
||||
#endif /* HAVE_DENTRY_XATTR_GET */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 4.4 API change,
|
||||
* The xattr_handler->set() callback was changed to take a xattr_handler,
|
||||
* and handler_flags argument was removed and should be accessed by
|
||||
* handler->flags.
|
||||
*/
|
||||
#if defined(HAVE_XATTR_SET_HANDLER)
|
||||
#define ZPL_XATTR_SET_WRAPPER(fn) \
|
||||
static int \
|
||||
fn(const struct xattr_handler *handler, struct dentry *dentry, \
|
||||
const char *name, const void *buffer, size_t size, int flags) \
|
||||
{ \
|
||||
return (__ ## fn(dentry->d_inode, name, buffer, size, flags)); \
|
||||
}
|
||||
/*
|
||||
* 2.6.33 API change,
|
||||
* The xattr_hander->set() callback was changed to take a dentry
|
||||
* The xattr_handler->set() callback was changed to take a dentry
|
||||
* instead of an inode, and a handler_flags argument was added.
|
||||
*/
|
||||
#ifdef HAVE_DENTRY_XATTR_SET
|
||||
#elif defined(HAVE_XATTR_SET_DENTRY)
|
||||
#define ZPL_XATTR_SET_WRAPPER(fn) \
|
||||
static int \
|
||||
fn(struct dentry *dentry, const char *name, const void *buffer, \
|
||||
@@ -91,20 +168,9 @@ fn(struct dentry *dentry, const char *name, const void *buffer, \
|
||||
return (__ ## fn(dentry->d_inode, name, buffer, size, flags)); \
|
||||
}
|
||||
/*
|
||||
* 4.4 API change,
|
||||
* The xattr_hander->set() callback was changed to take a xattr_handler,
|
||||
* and handler_flags argument was removed and should be accessed by
|
||||
* handler->flags.
|
||||
* 2.6.32 API
|
||||
*/
|
||||
#elif defined(HAVE_HANDLER_XATTR_SET)
|
||||
#define ZPL_XATTR_SET_WRAPPER(fn) \
|
||||
static int \
|
||||
fn(const struct xattr_handler *handler, struct dentry *dentry, \
|
||||
const char *name, const void *buffer, size_t size, int flags) \
|
||||
{ \
|
||||
return (__ ## fn(dentry->d_inode, name, buffer, size, flags)); \
|
||||
}
|
||||
#else
|
||||
#elif defined(HAVE_XATTR_SET_INODE)
|
||||
#define ZPL_XATTR_SET_WRAPPER(fn) \
|
||||
static int \
|
||||
fn(struct inode *ip, const char *name, const void *buffer, \
|
||||
@@ -112,7 +178,7 @@ fn(struct inode *ip, const char *name, const void *buffer, \
|
||||
{ \
|
||||
return (__ ## fn(ip, name, buffer, size, flags)); \
|
||||
}
|
||||
#endif /* HAVE_DENTRY_XATTR_SET */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_6ARGS_SECURITY_INODE_INIT_SECURITY
|
||||
#define zpl_security_inode_init_security(ip, dip, qstr, nm, val, len) \
|
||||
|
||||
Reference in New Issue
Block a user