summaryrefslogtreecommitdiffstats
path: root/module/zfs/zpl_xattr.c
diff options
context:
space:
mode:
authorRichard Yao <[email protected]>2013-08-07 08:53:45 -0400
committerBrian Behlendorf <[email protected]>2013-08-15 16:19:07 -0700
commit0f37d0c8bed442dd0d2c1b1dddd68653fa6eec66 (patch)
treebbd56b426b2b72bed0e3f81afaab2ddf5e613e3e /module/zfs/zpl_xattr.c
parent34e143323e359b42bc9d06dd19cc4b1f13091283 (diff)
Linux 3.11 compat: fops->iterate()
Commit torvalds/linux@2233f31aade393641f0eaed43a71110e629bb900 replaced ->readdir() with ->iterate() in struct file_operations. All filesystems must now use the new ->iterate method. To handle this the code was reworked to use the new ->iterate interface. Care was taken to keep the majority of changes confined to the ZPL layer which is already Linux specific. However, minor changes were required to the common zfs_readdir() function. Compatibility with older kernels was accomplished by adding versions of the trivial dir_emit* helper functions. Also the various *_readdir() functions were reworked in to wrappers which create a dir_context structure to pass to the new *_iterate() functions. Unfortunately, the new dir_emit* functions prevent us from passing a private pointer to the filldir function. The xattr directory code leveraged this ability through zfs_readdir() to generate the list of xattr names. Since we can no longer use zfs_readdir() a simplified zpl_xattr_readdir() function was added to perform the same task. Signed-off-by: Richard Yao <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #1653 Issue #1591
Diffstat (limited to 'module/zfs/zpl_xattr.c')
-rw-r--r--module/zfs/zpl_xattr.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/module/zfs/zpl_xattr.c b/module/zfs/zpl_xattr.c
index eb2c00dfb..dca1ad668 100644
--- a/module/zfs/zpl_xattr.c
+++ b/module/zfs/zpl_xattr.c
@@ -80,6 +80,7 @@
#include <sys/zfs_vfsops.h>
#include <sys/zfs_vnops.h>
#include <sys/zfs_znode.h>
+#include <sys/zap.h>
#include <sys/vfs.h>
#include <sys/zpl.h>
@@ -91,11 +92,8 @@ typedef struct xattr_filldir {
} xattr_filldir_t;
static int
-zpl_xattr_filldir(void *arg, const char *name, int name_len,
- loff_t offset, uint64_t objnum, unsigned int d_type)
+zpl_xattr_filldir(xattr_filldir_t *xf, const char *name, int name_len)
{
- xattr_filldir_t *xf = arg;
-
if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
if (!(ITOZSB(xf->inode)->z_flags & ZSB_XATTR))
return (0);
@@ -118,12 +116,46 @@ zpl_xattr_filldir(void *arg, const char *name, int name_len,
return (0);
}
+/*
+ * Read as many directory entry names as will fit in to the provided buffer,
+ * or when no buffer is provided calculate the required buffer size.
+ */
+int
+zpl_xattr_readdir(struct inode *dxip, xattr_filldir_t *xf)
+{
+ zap_cursor_t zc;
+ zap_attribute_t zap;
+ int error;
+
+ zap_cursor_init(&zc, ITOZSB(dxip)->z_os, ITOZ(dxip)->z_id);
+
+ while ((error = -zap_cursor_retrieve(&zc, &zap)) == 0) {
+
+ if (zap.za_integer_length != 8 || zap.za_num_integers != 1) {
+ error = -ENXIO;
+ break;
+ }
+
+ error = zpl_xattr_filldir(xf, zap.za_name, strlen(zap.za_name));
+ if (error)
+ break;
+
+ zap_cursor_advance(&zc);
+ }
+
+ zap_cursor_fini(&zc);
+
+ if (error == -ENOENT)
+ error = 0;
+
+ return (error);
+}
+
static ssize_t
zpl_xattr_list_dir(xattr_filldir_t *xf, cred_t *cr)
{
struct inode *ip = xf->inode;
struct inode *dxip = NULL;
- loff_t pos = 3; /* skip '.', '..', and '.zfs' entries. */
int error;
/* Lookup the xattr directory */
@@ -135,8 +167,7 @@ zpl_xattr_list_dir(xattr_filldir_t *xf, cred_t *cr)
return (error);
}
- /* Fill provided buffer via zpl_zattr_filldir helper */
- error = -zfs_readdir(dxip, (void *)xf, zpl_xattr_filldir, &pos, cr);
+ error = zpl_xattr_readdir(dxip, xf);
iput(dxip);
return (error);
@@ -162,8 +193,8 @@ zpl_xattr_list_sa(xattr_filldir_t *xf)
while ((nvp = nvlist_next_nvpair(zp->z_xattr_cached, nvp)) != NULL) {
ASSERT3U(nvpair_type(nvp), ==, DATA_TYPE_BYTE_ARRAY);
- error = zpl_xattr_filldir((void *)xf, nvpair_name(nvp),
- strlen(nvpair_name(nvp)), 0, 0, 0);
+ error = zpl_xattr_filldir(xf, nvpair_name(nvp),
+ strlen(nvpair_name(nvp)));
if (error)
return (error);
}