From: Jeff Mahoney <jeffm@suse.com>
To: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
ReiserFS Development List <reiserfs-devel@vger.kernel.org>
Subject: [patch 23/35 xattr-rework] reiserfs: use generic xattr handlers
Date: Mon, 30 Mar 2009 14:02:38 -0400 [thread overview]
Message-ID: <20090330181012.245860652@suse.com> (raw)
In-Reply-To: 20090330180215.951354436@suse.com
[-- Attachment #1: patches.suse/reiserfs-use-generic-xattr-handlers.diff --]
[-- Type: text/plain, Size: 34003 bytes --]
Christoph Hellwig had asked me quite some time ago to port the reiserfs
xattrs to the generic xattr interface.
This patch replaces the reiserfs-specific xattr handling code with the
generic struct xattr_handler.
However, since reiserfs doesn't split the prefix and name when accessing
xattrs, it can't leverage generic_{set,get,list,remove}xattr without
needlessly reconstructing the name on the back end.
Update 7/26/07: Added missing dput() to deletion path.
Update 8/30/07: Added missing mark_inode_dirty when i_mode is used to
represent an ACL and no previous ACL existed.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
fs/reiserfs/super.c | 7
fs/reiserfs/xattr.c | 467 ++++++++++++++++-------------------------
fs/reiserfs/xattr_acl.c | 79 ++----
fs/reiserfs/xattr_security.c | 26 --
fs/reiserfs/xattr_trusted.c | 45 ---
fs/reiserfs/xattr_user.c | 31 --
include/linux/reiserfs_acl.h | 16 -
include/linux/reiserfs_fs_sb.h | 3
include/linux/reiserfs_xattr.h | 25 --
9 files changed, 258 insertions(+), 441 deletions(-)
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -2261,9 +2261,6 @@ static int __init init_reiserfs_fs(void)
return ret;
}
- if ((ret = reiserfs_xattr_register_handlers()))
- goto failed_reiserfs_xattr_register_handlers;
-
reiserfs_proc_info_global_init();
reiserfs_proc_register_global("version",
reiserfs_global_version_in_proc);
@@ -2274,9 +2271,6 @@ static int __init init_reiserfs_fs(void)
return 0;
}
- reiserfs_xattr_unregister_handlers();
-
- failed_reiserfs_xattr_register_handlers:
reiserfs_proc_unregister_global("version");
reiserfs_proc_info_global_done();
destroy_inodecache();
@@ -2286,7 +2280,6 @@ static int __init init_reiserfs_fs(void)
static void __exit exit_reiserfs_fs(void)
{
- reiserfs_xattr_unregister_handlers();
reiserfs_proc_unregister_global("version");
reiserfs_proc_info_global_done();
unregister_filesystem(&reiserfs_fs_type);
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -271,7 +271,7 @@ reiserfs_set_acl(struct inode *inode, in
char *name;
void *value = NULL;
struct posix_acl **p_acl;
- size_t size;
+ size_t size = 0;
int error;
struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
@@ -308,16 +308,21 @@ reiserfs_set_acl(struct inode *inode, in
value = posix_acl_to_disk(acl, &size);
if (IS_ERR(value))
return (int)PTR_ERR(value);
- error = reiserfs_xattr_set(inode, name, value, size, 0);
- } else {
- error = reiserfs_xattr_del(inode, name);
- if (error == -ENODATA) {
- /* This may seem odd here, but it means that the ACL was set
- * with a value representable with mode bits. If there was
- * an ACL before, reiserfs_xattr_del already dirtied the inode.
- */
+ }
+
+ error = __reiserfs_xattr_set(inode, name, value, size, 0);
+
+ /*
+ * Ensure that the inode gets dirtied if we're only using
+ * the mode bits and an old ACL didn't exist. We don't need
+ * to check if the inode is hashed here since we won't get
+ * called by reiserfs_inherit_default_acl().
+ */
+ if (error == -ENODATA) {
+ error = 0;
+ if (type == ACL_TYPE_ACCESS) {
+ inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
- error = 0;
}
}
@@ -474,33 +479,22 @@ posix_acl_access_set(struct inode *inode
return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
}
-static int posix_acl_access_del(struct inode *inode, const char *name)
-{
- struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
- if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1)
- return -EINVAL;
- iset_acl(inode, &reiserfs_i->i_acl_access, ERR_PTR(-ENODATA));
- return 0;
-}
-
-static int
-posix_acl_access_list(struct inode *inode, const char *name, int namelen,
- char *out)
+static size_t posix_acl_access_list(struct inode *inode, char *list,
+ size_t list_size, const char *name,
+ size_t name_len)
{
- int len = namelen;
+ const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
if (!reiserfs_posixacl(inode->i_sb))
return 0;
- if (out)
- memcpy(out, name, len);
-
- return len;
+ if (list && size <= list_size)
+ memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
+ return size;
}
-struct reiserfs_xattr_handler posix_acl_access_handler = {
+struct xattr_handler reiserfs_posix_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.get = posix_acl_access_get,
.set = posix_acl_access_set,
- .del = posix_acl_access_del,
.list = posix_acl_access_list,
};
@@ -522,32 +516,21 @@ posix_acl_default_set(struct inode *inod
return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
}
-static int posix_acl_default_del(struct inode *inode, const char *name)
-{
- struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
- if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1)
- return -EINVAL;
- iset_acl(inode, &reiserfs_i->i_acl_default, ERR_PTR(-ENODATA));
- return 0;
-}
-
-static int
-posix_acl_default_list(struct inode *inode, const char *name, int namelen,
- char *out)
+static size_t posix_acl_default_list(struct inode *inode, char *list,
+ size_t list_size, const char *name,
+ size_t name_len)
{
- int len = namelen;
+ const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
if (!reiserfs_posixacl(inode->i_sb))
return 0;
- if (out)
- memcpy(out, name, len);
-
- return len;
+ if (list && size <= list_size)
+ memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
+ return size;
}
-struct reiserfs_xattr_handler posix_acl_default_handler = {
+struct xattr_handler reiserfs_posix_acl_default_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
.get = posix_acl_default_get,
.set = posix_acl_default_set,
- .del = posix_acl_default_del,
.list = posix_acl_default_list,
};
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -53,7 +53,6 @@
#define PRIVROOT_NAME ".reiserfs_priv"
#define XAROOT_NAME "xattrs"
-static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char *);
/* Helpers for inode ops. We do this so that we don't have all the VFS
* overhead and also for proper i_mutex annotation.
@@ -110,7 +109,6 @@ static int xattr_rmdir(struct inode *dir
return error;
}
-
#define xattr_may_create(flags) (!flags || flags & XATTR_CREATE)
/* Returns and possibly creates the xattr dir. */
@@ -339,14 +337,17 @@ int xattr_readdir(struct inode *inode, f
return res;
}
-/* expects xadir->d_inode->i_mutex to be locked */
+/* The following are side effects of other operations that aren't explicitly
+ * modifying extended attributes. This includes operations such as permissions
+ * or ownership changes, object deletions, etc. */
+
static int
-__reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen)
+reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen,
+ loff_t offset, u64 ino, unsigned int d_type)
{
+ struct dentry *xadir = (struct dentry *)buf;
struct dentry *dentry;
- struct inode *dir = xadir->d_inode;
int err = 0;
- struct reiserfs_xattr_handler *xah;
dentry = lookup_one_len(name, xadir, namelen);
if (IS_ERR(dentry)) {
@@ -361,28 +362,7 @@ __reiserfs_xattr_del(struct dentry *xadi
if (S_ISDIR(dentry->d_inode->i_mode))
goto out_file;
- if (!IS_PRIVATE(dentry->d_inode)) {
- reiserfs_error(dir->i_sb, "jdm-20003",
- "OID %08x [%.*s/%.*s] doesn't have "
- "priv flag set [parent is %sset].",
- le32_to_cpu(INODE_PKEY(dentry->d_inode)->
- k_objectid), xadir->d_name.len,
- xadir->d_name.name, namelen, name,
- IS_PRIVATE(xadir->d_inode) ? "" :
- "not ");
- dput(dentry);
- return -EIO;
- }
-
- /* Deletion pre-operation */
- xah = find_xattr_handler_prefix(name);
- if (xah && xah->del) {
- err = xah->del(dentry->d_inode, name);
- if (err)
- goto out;
- }
-
- err = xattr_unlink(dir, dentry);
+ err = xattr_unlink(xadir->d_inode, dentry);
out_file:
dput(dentry);
@@ -391,20 +371,6 @@ out:
return err;
}
-/* The following are side effects of other operations that aren't explicitly
- * modifying extended attributes. This includes operations such as permissions
- * or ownership changes, object deletions, etc. */
-
-static int
-reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen,
- loff_t offset, u64 ino, unsigned int d_type)
-{
- struct dentry *xadir = (struct dentry *)buf;
-
- return __reiserfs_xattr_del(xadir, name, namelen);
-
-}
-
/* This is called w/ inode->i_mutex downed */
int reiserfs_delete_xattrs(struct inode *inode)
{
@@ -541,14 +507,11 @@ out:
}
#ifdef CONFIG_REISERFS_FS_XATTR
-static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char
- *prefix);
-
/* Returns a dentry corresponding to a specific extended attribute file
* for the inode. If flags allow, the file is created. Otherwise, a
* valid or negative dentry, or an error is returned. */
-static struct dentry *get_xa_file_dentry(const struct inode *inode,
- const char *name, int flags)
+static struct dentry *xattr_lookup(struct inode *inode, const char *name,
+ int flags)
{
struct dentry *xadir, *xafile;
int err = 0;
@@ -623,6 +586,45 @@ int reiserfs_commit_write(struct file *f
int reiserfs_prepare_write(struct file *f, struct page *page,
unsigned from, unsigned to);
+static void update_ctime(struct inode *inode)
+{
+ struct timespec now = current_fs_time(inode->i_sb);
+ if (hlist_unhashed(&inode->i_hash) || !inode->i_nlink ||
+ timespec_equal(&inode->i_ctime, &now))
+ return;
+
+ inode->i_ctime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);
+}
+
+static int lookup_and_delete_xattr(struct inode *inode, const char *name)
+{
+ int err = 0;
+ struct dentry *dentry, *xadir;
+
+ xadir = open_xa_dir(inode, XATTR_REPLACE);
+ if (IS_ERR(xadir))
+ return PTR_ERR(xadir);
+
+ dentry = lookup_one_len(name, xadir, strlen(name));
+ if (IS_ERR(dentry)) {
+ err = PTR_ERR(dentry);
+ goto out_dput;
+ }
+
+ if (dentry->d_inode) {
+ mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR);
+ err = xattr_unlink(xadir->d_inode, dentry);
+ mutex_unlock(&xadir->d_inode->i_mutex);
+ update_ctime(inode);
+ }
+
+ dput(dentry);
+out_dput:
+ dput(xadir);
+ return err;
+}
+
/* Generic extended attribute operations that can be used by xa plugins */
@@ -630,8 +632,8 @@ int reiserfs_prepare_write(struct file *
* inode->i_mutex: down
*/
int
-reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
- size_t buffer_size, int flags)
+__reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
+ size_t buffer_size, int flags)
{
int err = 0;
struct dentry *dentry;
@@ -639,37 +641,22 @@ reiserfs_xattr_set(struct inode *inode,
char *data;
size_t file_pos = 0;
size_t buffer_pos = 0;
- struct iattr newattrs;
+ size_t new_size;
__u32 xahash = 0;
if (get_inode_sd_version(inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
if (!buffer)
- return reiserfs_xattr_del(inode, name);
+ return lookup_and_delete_xattr(inode, name);
- dentry = get_xa_file_dentry(inode, name, flags);
- if (IS_ERR(dentry)) {
- err = PTR_ERR(dentry);
- goto out;
- }
+ dentry = xattr_lookup(inode, name, flags);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
down_write(&REISERFS_I(inode)->i_xattr_sem);
xahash = xattr_hash(buffer, buffer_size);
-
- /* Resize it so we're ok to write there */
- newattrs.ia_size = buffer_size;
- newattrs.ia_ctime = current_fs_time(inode->i_sb);
- newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
- mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
- down_write(&dentry->d_inode->i_alloc_sem);
- err = reiserfs_setattr(dentry, &newattrs);
- up_write(&dentry->d_inode->i_alloc_sem);
- mutex_unlock(&dentry->d_inode->i_mutex);
- if (err)
- goto out_filp;
-
while (buffer_pos < buffer_size || buffer_pos == 0) {
size_t chunk;
size_t skip = 0;
@@ -682,7 +669,7 @@ reiserfs_xattr_set(struct inode *inode,
page = reiserfs_get_page(dentry->d_inode, file_pos);
if (IS_ERR(page)) {
err = PTR_ERR(page);
- goto out_filp;
+ goto out_unlock;
}
lock_page(page);
@@ -716,20 +703,33 @@ reiserfs_xattr_set(struct inode *inode,
break;
}
- /* We can't mark the inode dirty if it's not hashed. This is the case
- * when we're inheriting the default ACL. If we dirty it, the inode
- * gets marked dirty, but won't (ever) make it onto the dirty list until
- * it's synced explicitly to clear I_DIRTY. This is bad. */
- if (!hlist_unhashed(&inode->i_hash)) {
- inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
- }
-
- out_filp:
+ new_size = buffer_size + sizeof(struct reiserfs_xattr_header);
+ if (!err && new_size < i_size_read(dentry->d_inode)) {
+ struct iattr newattrs = {
+ .ia_ctime = current_fs_time(inode->i_sb),
+ .ia_size = buffer_size,
+ .ia_valid = ATTR_SIZE | ATTR_CTIME,
+ };
+ mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
+ down_write(&dentry->d_inode->i_alloc_sem);
+ err = reiserfs_setattr(dentry, &newattrs);
+ up_write(&dentry->d_inode->i_alloc_sem);
+ mutex_unlock(&dentry->d_inode->i_mutex);
+ } else
+ update_ctime(inode);
+out_unlock:
up_write(&REISERFS_I(inode)->i_xattr_sem);
dput(dentry);
+ return err;
+}
- out:
+int
+reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
+ size_t buffer_size, int flags)
+{
+ int err = __reiserfs_xattr_set(inode, name, buffer, buffer_size, flags);
+ if (err == -ENODATA)
+ err = 0;
return err;
}
@@ -737,7 +737,7 @@ reiserfs_xattr_set(struct inode *inode,
* inode->i_mutex: down
*/
int
-reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
+reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer,
size_t buffer_size)
{
ssize_t err = 0;
@@ -756,7 +756,7 @@ reiserfs_xattr_get(const struct inode *i
if (get_inode_sd_version(inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
- dentry = get_xa_file_dentry(inode, name, XATTR_REPLACE);
+ dentry = xattr_lookup(inode, name, XATTR_REPLACE);
if (IS_ERR(dentry)) {
err = PTR_ERR(dentry);
goto out;
@@ -837,32 +837,53 @@ out:
return err;
}
-int reiserfs_xattr_del(struct inode *inode, const char *name)
-{
- struct dentry *dir;
- int err;
+/* Actual operations that are exported to VFS-land */
+struct xattr_handler *reiserfs_xattr_handlers[] = {
+ &reiserfs_xattr_user_handler,
+ &reiserfs_xattr_trusted_handler,
+#ifdef CONFIG_REISERFS_FS_SECURITY
+ &reiserfs_xattr_security_handler,
+#endif
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
+ &reiserfs_posix_acl_access_handler,
+ &reiserfs_posix_acl_default_handler,
+#endif
+ NULL
+};
- dir = open_xa_dir(inode, XATTR_REPLACE);
- if (IS_ERR(dir)) {
- err = PTR_ERR(dir);
- goto out;
- }
+/*
+ * In order to implement different sets of xattr operations for each xattr
+ * prefix with the generic xattr API, a filesystem should create a
+ * null-terminated array of struct xattr_handler (one for each prefix) and
+ * hang a pointer to it off of the s_xattr field of the superblock.
+ *
+ * The generic_fooxattr() functions will use this list to dispatch xattr
+ * operations to the correct xattr_handler.
+ */
+#define for_each_xattr_handler(handlers, handler) \
+ for ((handler) = *(handlers)++; \
+ (handler) != NULL; \
+ (handler) = *(handlers)++)
- mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
- err = __reiserfs_xattr_del(dir, name, strlen(name));
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(dir);
+/* This is the implementation for the xattr plugin infrastructure */
+static inline struct xattr_handler *
+find_xattr_handler_prefix(struct xattr_handler **handlers,
+ const char *name)
+{
+ struct xattr_handler *xah;
- if (!err) {
- inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
+ if (!handlers)
+ return NULL;
+
+ for_each_xattr_handler(handlers, xah) {
+ if (strncmp(xah->prefix, name, strlen(xah->prefix)) == 0)
+ break;
}
- out:
- return err;
+ return xah;
}
-/* Actual operations that are exported to VFS-land */
+
/*
* Inode operation getxattr()
*/
@@ -870,15 +891,15 @@ ssize_t
reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
size_t size)
{
- struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);
- int err;
+ struct inode *inode = dentry->d_inode;
+ struct xattr_handler *handler;
- if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
- get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
+ handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
+
+ if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
- err = xah->get(dentry->d_inode, name, buffer, size);
- return err;
+ return handler->get(inode, name, buffer, size);
}
/*
@@ -890,15 +911,15 @@ int
reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags)
{
- struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);
- int err;
+ struct inode *inode = dentry->d_inode;
+ struct xattr_handler *handler;
- if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
- get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
+ handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
+
+ if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
- err = xah->set(dentry->d_inode, name, value, size, flags);
- return err;
+ return handler->set(inode, name, value, size, flags);
}
/*
@@ -908,71 +929,65 @@ reiserfs_setxattr(struct dentry *dentry,
*/
int reiserfs_removexattr(struct dentry *dentry, const char *name)
{
- int err;
- struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);
+ struct inode *inode = dentry->d_inode;
+ struct xattr_handler *handler;
+ handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
- if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
- get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
+ if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
- err = reiserfs_xattr_del(dentry->d_inode, name);
-
- dentry->d_inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(dentry->d_inode);
-
- return err;
+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
}
-/* This is what filldir will use:
- * r_pos will always contain the amount of space required for the entire
- * list. If r_pos becomes larger than r_size, we need more space and we
- * return an error indicating this. If r_pos is less than r_size, then we've
- * filled the buffer successfully and we return success */
-struct reiserfs_listxattr_buf {
- int r_pos;
- int r_size;
- char *r_buf;
- struct inode *r_inode;
+struct listxattr_buf {
+ size_t size;
+ size_t pos;
+ char *buf;
+ struct inode *inode;
};
-static int
-reiserfs_listxattr_filler(void *buf, const char *name, int namelen,
- loff_t offset, u64 ino, unsigned int d_type)
+static int listxattr_filler(void *buf, const char *name, int namelen,
+ loff_t offset, u64 ino, unsigned int d_type)
{
- struct reiserfs_listxattr_buf *b = (struct reiserfs_listxattr_buf *)buf;
- int len = 0;
- if (name[0] != '.'
- || (namelen != 1 && (name[1] != '.' || namelen != 2))) {
- struct reiserfs_xattr_handler *xah =
- find_xattr_handler_prefix(name);
- if (!xah)
- return 0; /* Unsupported xattr name, skip it */
-
- /* We call ->list() twice because the operation isn't required to just
- * return the name back - we want to make sure we have enough space */
- len += xah->list(b->r_inode, name, namelen, NULL);
-
- if (len) {
- if (b->r_pos + len + 1 <= b->r_size) {
- char *p = b->r_buf + b->r_pos;
- p += xah->list(b->r_inode, name, namelen, p);
- *p++ = '\0';
- }
- b->r_pos += len + 1;
+ struct listxattr_buf *b = (struct listxattr_buf *)buf;
+ size_t size;
+ if (name[0] != '.' ||
+ (namelen != 1 && (name[1] != '.' || namelen != 2))) {
+ struct xattr_handler *handler;
+ handler = find_xattr_handler_prefix(b->inode->i_sb->s_xattr,
+ name);
+ if (!handler) /* Unsupported xattr name */
+ return 0;
+ if (b->buf) {
+ size = handler->list(b->inode, b->buf + b->pos,
+ b->size, name, namelen);
+ if (size > b->size)
+ return -ERANGE;
+ } else {
+ size = handler->list(b->inode, NULL, 0, name, namelen);
}
- }
+ b->pos += size;
+ }
return 0;
}
/*
* Inode operation listxattr()
+ *
+ * We totally ignore the generic listxattr here because it would be stupid
+ * not to. Since the xattrs are organized in a directory, we can just
+ * readdir to find them.
*/
ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
{
struct dentry *dir;
int err = 0;
- struct reiserfs_listxattr_buf buf;
+ struct listxattr_buf buf = {
+ .inode = dentry->d_inode,
+ .buf = buffer,
+ .size = buffer ? size : 0,
+ };
if (!dentry->d_inode)
return -EINVAL;
@@ -985,120 +1000,22 @@ ssize_t reiserfs_listxattr(struct dentry
if (IS_ERR(dir)) {
err = PTR_ERR(dir);
if (err == -ENODATA)
- err = 0; /* Not an error if there aren't any xattrs */
+ err = 0; /* Not an error if there aren't any xattrs */
goto out;
}
- buf.r_buf = buffer;
- buf.r_size = buffer ? size : 0;
- buf.r_pos = 0;
- buf.r_inode = dentry->d_inode;
-
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
- err = xattr_readdir(dir->d_inode, reiserfs_listxattr_filler, &buf);
+ err = xattr_readdir(dir->d_inode, listxattr_filler, &buf);
mutex_unlock(&dir->d_inode->i_mutex);
- if (!err) {
- if (buf.r_pos > buf.r_size && buffer != NULL)
- err = -ERANGE;
- else
- err = buf.r_pos;
- }
+ if (!err)
+ err = buf.pos;
dput(dir);
out:
return err;
}
-/* This is the implementation for the xattr plugin infrastructure */
-static LIST_HEAD(xattr_handlers);
-static DEFINE_RWLOCK(handler_lock);
-
-static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char
- *prefix)
-{
- struct reiserfs_xattr_handler *xah = NULL;
- struct list_head *p;
-
- read_lock(&handler_lock);
- list_for_each(p, &xattr_handlers) {
- xah = list_entry(p, struct reiserfs_xattr_handler, handlers);
- if (strncmp(xah->prefix, prefix, strlen(xah->prefix)) == 0)
- break;
- xah = NULL;
- }
-
- read_unlock(&handler_lock);
- return xah;
-}
-
-static void __unregister_handlers(void)
-{
- struct reiserfs_xattr_handler *xah;
- struct list_head *p, *tmp;
-
- list_for_each_safe(p, tmp, &xattr_handlers) {
- xah = list_entry(p, struct reiserfs_xattr_handler, handlers);
- if (xah->exit)
- xah->exit();
-
- list_del_init(p);
- }
- INIT_LIST_HEAD(&xattr_handlers);
-}
-
-int __init reiserfs_xattr_register_handlers(void)
-{
- int err = 0;
- struct reiserfs_xattr_handler *xah;
- struct list_head *p;
-
- write_lock(&handler_lock);
-
- /* If we're already initialized, nothing to do */
- if (!list_empty(&xattr_handlers)) {
- write_unlock(&handler_lock);
- return 0;
- }
-
- /* Add the handlers */
- list_add_tail(&user_handler.handlers, &xattr_handlers);
- list_add_tail(&trusted_handler.handlers, &xattr_handlers);
-#ifdef CONFIG_REISERFS_FS_SECURITY
- list_add_tail(&security_handler.handlers, &xattr_handlers);
-#endif
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
- list_add_tail(&posix_acl_access_handler.handlers, &xattr_handlers);
- list_add_tail(&posix_acl_default_handler.handlers, &xattr_handlers);
-#endif
-
- /* Run initializers, if available */
- list_for_each(p, &xattr_handlers) {
- xah = list_entry(p, struct reiserfs_xattr_handler, handlers);
- if (xah->init) {
- err = xah->init();
- if (err) {
- list_del_init(p);
- break;
- }
- }
- }
-
- /* Clean up other handlers, if any failed */
- if (err)
- __unregister_handlers();
-
- write_unlock(&handler_lock);
- return err;
-}
-
-void reiserfs_xattr_unregister_handlers(void)
-{
- write_lock(&handler_lock);
- __unregister_handlers();
- write_unlock(&handler_lock);
-}
-
static int reiserfs_check_acl(struct inode *inode, int mask)
{
struct posix_acl *acl;
@@ -1157,20 +1074,16 @@ static int xattr_mount_check(struct supe
{
/* We need generation numbers to ensure that the oid mapping is correct
* v3.5 filesystems don't have them. */
- if (!old_format_only(s)) {
- set_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
- } else if (reiserfs_xattrs_optional(s)) {
- /* Old format filesystem, but optional xattrs have been enabled
- * at mount time. Error out. */
- reiserfs_warning(s, "jdm-20005",
- "xattrs/ACLs not supported on pre v3.6 "
- "format filesystem. Failing mount.");
- return -EOPNOTSUPP;
- } else {
- /* Old format filesystem, but no optional xattrs have
- * been enabled. This means we silently disable xattrs
- * on the filesystem. */
- clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
+ if (old_format_only(s)) {
+ if (reiserfs_xattrs_optional(s)) {
+ /* Old format filesystem, but optional xattrs have
+ * been enabled. Error out. */
+ reiserfs_warning(s, "jdm-2005",
+ "xattrs/ACLs not supported "
+ "on pre-v3.6 format filesystems. "
+ "Failing mount.");
+ return -EOPNOTSUPP;
+ }
}
return 0;
@@ -1251,9 +1164,11 @@ int reiserfs_xattr_init(struct super_blo
}
#ifdef CONFIG_REISERFS_FS_XATTR
+ if (!err)
+ s->s_xattr = reiserfs_xattr_handlers;
+
error:
if (err) {
- clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
clear_bit(REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt));
clear_bit(REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt));
}
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -31,35 +31,25 @@ security_set(struct inode *inode, const
return reiserfs_xattr_set(inode, name, buffer, size, flags);
}
-static int security_del(struct inode *inode, const char *name)
+static size_t security_list(struct inode *inode, char *list, size_t list_len,
+ const char *name, size_t namelen)
{
- if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
- return -EINVAL;
-
- if (IS_PRIVATE(inode))
- return -EPERM;
-
- return 0;
-}
-
-static int
-security_list(struct inode *inode, const char *name, int namelen, char *out)
-{
- int len = namelen;
+ const size_t len = namelen + 1;
if (IS_PRIVATE(inode))
return 0;
- if (out)
- memcpy(out, name, len);
+ if (list && len <= list_len) {
+ memcpy(list, name, namelen);
+ list[namelen] = '\0';
+ }
return len;
}
-struct reiserfs_xattr_handler security_handler = {
+struct xattr_handler reiserfs_xattr_security_handler = {
.prefix = XATTR_SECURITY_PREFIX,
.get = security_get,
.set = security_set,
- .del = security_del,
.list = security_list,
};
--- a/fs/reiserfs/xattr_trusted.c
+++ b/fs/reiserfs/xattr_trusted.c
@@ -13,10 +13,7 @@ trusted_get(struct inode *inode, const c
if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
return -EINVAL;
- if (!reiserfs_xattrs(inode->i_sb))
- return -EOPNOTSUPP;
-
- if (!(capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode)))
+ if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
return -EPERM;
return reiserfs_xattr_get(inode, name, buffer, size);
@@ -29,50 +26,30 @@ trusted_set(struct inode *inode, const c
if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
return -EINVAL;
- if (!reiserfs_xattrs(inode->i_sb))
- return -EOPNOTSUPP;
-
- if (!(capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode)))
+ if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
return -EPERM;
return reiserfs_xattr_set(inode, name, buffer, size, flags);
}
-static int trusted_del(struct inode *inode, const char *name)
+static size_t trusted_list(struct inode *inode, char *list, size_t list_size,
+ const char *name, size_t name_len)
{
- if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
- return -EINVAL;
+ const size_t len = name_len + 1;
- if (!reiserfs_xattrs(inode->i_sb))
- return -EOPNOTSUPP;
-
- if (!(capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode)))
- return -EPERM;
-
- return 0;
-}
-
-static int
-trusted_list(struct inode *inode, const char *name, int namelen, char *out)
-{
- int len = namelen;
-
- if (!reiserfs_xattrs(inode->i_sb))
+ if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
return 0;
- if (!(capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode)))
- return 0;
-
- if (out)
- memcpy(out, name, len);
-
+ if (list && len <= list_size) {
+ memcpy(list, name, name_len);
+ list[name_len] = '\0';
+ }
return len;
}
-struct reiserfs_xattr_handler trusted_handler = {
+struct xattr_handler reiserfs_xattr_trusted_handler = {
.prefix = XATTR_TRUSTED_PREFIX,
.get = trusted_get,
.set = trusted_set,
- .del = trusted_del,
.list = trusted_list,
};
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -6,10 +6,6 @@
#include <linux/reiserfs_xattr.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
-# include <linux/reiserfs_acl.h>
-#endif
-
static int
user_get(struct inode *inode, const char *name, void *buffer, size_t size)
{
@@ -25,7 +21,6 @@ static int
user_set(struct inode *inode, const char *name, const void *buffer,
size_t size, int flags)
{
-
if (strlen(name) < sizeof(XATTR_USER_PREFIX))
return -EINVAL;
@@ -34,33 +29,23 @@ user_set(struct inode *inode, const char
return reiserfs_xattr_set(inode, name, buffer, size, flags);
}
-static int user_del(struct inode *inode, const char *name)
+static size_t user_list(struct inode *inode, char *list, size_t list_size,
+ const char *name, size_t name_len)
{
- if (strlen(name) < sizeof(XATTR_USER_PREFIX))
- return -EINVAL;
-
- if (!reiserfs_xattrs_user(inode->i_sb))
- return -EOPNOTSUPP;
- return 0;
-}
+ const size_t len = name_len + 1;
-static int
-user_list(struct inode *inode, const char *name, int namelen, char *out)
-{
- int len = namelen;
if (!reiserfs_xattrs_user(inode->i_sb))
return 0;
-
- if (out)
- memcpy(out, name, len);
-
+ if (list && len <= list_size) {
+ memcpy(list, name, name_len);
+ list[name_len] = '\0';
+ }
return len;
}
-struct reiserfs_xattr_handler user_handler = {
+struct xattr_handler reiserfs_xattr_user_handler = {
.prefix = XATTR_USER_PREFIX,
.get = user_get,
.set = user_set,
- .del = user_del,
.list = user_list,
};
--- a/include/linux/reiserfs_acl.h
+++ b/include/linux/reiserfs_acl.h
@@ -52,10 +52,8 @@ int reiserfs_acl_chmod(struct inode *ino
int reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
struct inode *inode);
int reiserfs_cache_default_acl(struct inode *dir);
-extern int reiserfs_xattr_posix_acl_init(void) __init;
-extern int reiserfs_xattr_posix_acl_exit(void);
-extern struct reiserfs_xattr_handler posix_acl_default_handler;
-extern struct reiserfs_xattr_handler posix_acl_access_handler;
+extern struct xattr_handler reiserfs_posix_acl_default_handler;
+extern struct xattr_handler reiserfs_posix_acl_access_handler;
static inline void reiserfs_init_acl_access(struct inode *inode)
{
@@ -75,16 +73,6 @@ static inline struct posix_acl *reiserfs
return NULL;
}
-static inline int reiserfs_xattr_posix_acl_init(void)
-{
- return 0;
-}
-
-static inline int reiserfs_xattr_posix_acl_exit(void)
-{
- return 0;
-}
-
static inline int reiserfs_acl_chmod(struct inode *inode)
{
return 0;
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -450,7 +450,6 @@ enum reiserfs_mount_options {
REISERFS_NO_UNHASHED_RELOCATION,
REISERFS_HASHED_RELOCATION,
REISERFS_ATTRS,
- REISERFS_XATTRS,
REISERFS_XATTRS_USER,
REISERFS_POSIXACL,
REISERFS_BARRIER_NONE,
@@ -488,7 +487,7 @@ enum reiserfs_mount_options {
#define reiserfs_data_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_LOG))
#define reiserfs_data_ordered(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_ORDERED))
#define reiserfs_data_writeback(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_WRITEBACK))
-#define reiserfs_xattrs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS))
+#define reiserfs_xattrs(s) ((s)->s_xattr != NULL)
#define reiserfs_xattrs_user(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS_USER))
#define reiserfs_posixacl(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_POSIXACL))
#define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s))
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -29,20 +29,6 @@ struct iattr;
struct super_block;
struct nameidata;
-struct reiserfs_xattr_handler {
- char *prefix;
- int (*init) (void);
- void (*exit) (void);
- int (*get) (struct inode * inode, const char *name, void *buffer,
- size_t size);
- int (*set) (struct inode * inode, const char *name, const void *buffer,
- size_t size, int flags);
- int (*del) (struct inode * inode, const char *name);
- int (*list) (struct inode * inode, const char *name, int namelen,
- char *out);
- struct list_head handlers;
-};
-
int reiserfs_xattr_register_handlers(void) __init;
void reiserfs_xattr_unregister_handlers(void);
int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
@@ -59,13 +45,14 @@ ssize_t reiserfs_listxattr(struct dentry
int reiserfs_removexattr(struct dentry *dentry, const char *name);
int reiserfs_permission(struct inode *inode, int mask);
-int reiserfs_xattr_del(struct inode *, const char *);
-int reiserfs_xattr_get(const struct inode *, const char *, void *, size_t);
+int reiserfs_xattr_get(struct inode *, const char *, void *, size_t);
+int __reiserfs_xattr_set(struct inode *, const char *, const void *,
+ size_t, int);
int reiserfs_xattr_set(struct inode *, const char *, const void *, size_t, int);
-extern struct reiserfs_xattr_handler user_handler;
-extern struct reiserfs_xattr_handler trusted_handler;
-extern struct reiserfs_xattr_handler security_handler;
+extern struct xattr_handler reiserfs_xattr_user_handler;
+extern struct xattr_handler reiserfs_xattr_trusted_handler;
+extern struct xattr_handler reiserfs_xattr_security_handler;
static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
{
next prev parent reply other threads:[~2009-03-30 18:02 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-03-30 18:02 [patch 00/35] Jeff's ReiserFS Patch Queue Jeff Mahoney
2009-03-30 18:02 ` [patch 01/35 quick-fixes] reiserfs: add support for mount count incrementing Jeff Mahoney
2009-03-30 18:02 ` [patch 02/35 quick-fixes] reiserfs: audit transaction ids to always be unsigned ints Jeff Mahoney
2009-03-30 18:02 ` [patch 03/35 error-handling] reiserfs: use buffer_info for leaf_paste_entries Jeff Mahoney
2009-03-30 18:02 ` [patch 04/35 error-handling] reiserfs: use more consistent printk formatting Jeff Mahoney
2009-03-30 18:02 ` [patch 05/35 error-handling] reiserfs: make some warnings informational Jeff Mahoney
2009-03-30 18:02 ` [patch 06/35 error-handling] reiserfs: rework reiserfs_warning Jeff Mahoney
2009-03-30 18:02 ` [patch 07/35 error-handling] reiserfs: prepare_error_buf wrongly consumes va_arg Jeff Mahoney
2009-03-30 18:02 ` [patch 08/35 error-handling] reiserfs: eliminate reiserfs_warning from uniqueness functions Jeff Mahoney
2009-03-30 18:02 ` [patch 09/35 error-handling] reiserfs: add locking around error buffer Jeff Mahoney
2009-03-30 18:48 ` Andi Kleen
2009-03-30 19:32 ` Jeff Mahoney
2009-03-30 18:02 ` [patch 10/35 error-handling] reiserfs: rework reiserfs_panic Jeff Mahoney
2009-03-30 18:02 ` [patch 11/35 error-handling] reiserfs: rearrange journal abort Jeff Mahoney
2009-03-30 18:02 ` [patch 12/35 error-handling] reiserfs: introduce reiserfs_error() Jeff Mahoney
2009-03-30 18:02 ` [patch 13/35 error-handling] reiserfs: use reiserfs_error() Jeff Mahoney
2009-03-30 18:02 ` [patch 14/35 xattr-rework] reiserfs: small variable cleanup Jeff Mahoney
2009-03-30 18:02 ` [patch 15/35 xattr-rework] reiserfs: xattr reiserfs_get_page takes offset instead of index Jeff Mahoney
2009-03-30 18:02 ` [patch 16/35 xattr-rework] reiserfs: remove link detection code Jeff Mahoney
2009-03-30 18:02 ` [patch 17/35 xattr-rework] reiserfs: remove IS_PRIVATE helpers Jeff Mahoney
2009-03-30 18:02 ` [patch 18/35 xattr-rework] reiserfs: Clean up xattrs when REISERFS_FS_XATTR is unset Jeff Mahoney
2009-03-31 18:44 ` Christoph Hellwig
2009-03-30 18:02 ` [patch 19/35 xattr-rework] reiserfs: simplify xattr internal file lookups/opens Jeff Mahoney
2009-03-30 18:02 ` [patch 20/35 xattr-rework] reiserfs: eliminate per-super xattr lock Jeff Mahoney
2009-03-30 18:02 ` [patch 21/35 xattr-rework] reiserfs: make per-inode xattr locking more fine grained Jeff Mahoney
2009-03-30 18:02 ` [patch 22/35 xattr-rework] reiserfs: remove i_has_xattr_dir Jeff Mahoney
2009-03-30 18:02 ` Jeff Mahoney [this message]
2009-03-30 18:02 ` [patch 24/35 xattr-rework] reiserfs: journaled xattrs Jeff Mahoney
2009-03-30 18:02 ` [patch 25/35 xattr-rework] reiserfs: use generic readdir for operations across all xattrs Jeff Mahoney
2009-03-30 18:02 ` [patch 26/35 xattr-rework] reiserfs: add atomic addition of selinux attributes during inode creation Jeff Mahoney
2009-03-30 18:02 ` [patch 27/35 code-cleanup] reiserfs: factor out buffer_info initialization Jeff Mahoney
2009-03-30 18:02 ` [patch 28/35 code-cleanup] reiserfs: cleanup path functions Jeff Mahoney
2009-03-30 18:02 ` [patch 29/35 code-cleanup] reiserfs: strip trailing whitespace Jeff Mahoney
2009-03-30 18:02 ` [patch 30/35 code-cleanup] reiserfs: rename p_s_sb to sb Jeff Mahoney
2009-03-30 18:02 ` [patch 31/35 code-cleanup] reiserfs: rename p_s_bh to bh Jeff Mahoney
2009-03-30 18:02 ` [patch 32/35 code-cleanup] reiserfs: rename p_s_inode to inode Jeff Mahoney
2009-03-30 18:50 ` Andi Kleen
2009-03-30 19:18 ` Jeff Mahoney
2009-03-30 18:02 ` [patch 33/35 code-cleanup] reiserfs: rename p_s_tb to tb Jeff Mahoney
2009-03-30 18:02 ` [patch 34/35 code-cleanup] reiserfs: rename p_._ variables Jeff Mahoney
2009-03-30 18:02 ` [patch 35/35 code-cleanup] reiserfs: rename [cn]_* variables Jeff Mahoney
2009-03-30 19:38 ` [patch 00/35] Jeff's ReiserFS Patch Queue Linus Torvalds
2009-03-30 19:59 ` Jeff Mahoney
2009-04-01 16:16 ` Ingo Molnar
2009-04-01 16:16 ` Ingo Molnar
2009-04-01 16:28 ` Jeff Mahoney
2009-04-01 16:28 ` Jeff Mahoney
2009-04-01 16:34 ` Ingo Molnar
2009-04-01 16:34 ` Ingo Molnar
2009-04-01 16:51 ` Frederic Weisbecker
2009-04-01 16:51 ` Frederic Weisbecker
2009-04-01 22:18 ` Bron Gondwana
2009-04-01 23:59 ` Frederic Weisbecker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090330181012.245860652@suse.com \
--to=jeffm@suse.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=reiserfs-devel@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.