summaryrefslogtreecommitdiff
path: root/fs/reiserfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/reiserfs')
-rw-r--r--fs/reiserfs/file.c7
-rw-r--r--fs/reiserfs/inode.c6
-rw-r--r--fs/reiserfs/namei.c50
-rw-r--r--fs/reiserfs/reiserfs.h2
-rw-r--r--fs/reiserfs/xattr.c55
-rw-r--r--fs/reiserfs/xattr_security.c31
6 files changed, 108 insertions, 43 deletions
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 467d13da198f..b54cc7048f02 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -261,3 +261,10 @@ const struct inode_operations reiserfs_file_inode_operations = {
.fileattr_get = reiserfs_fileattr_get,
.fileattr_set = reiserfs_fileattr_set,
};
+
+const struct inode_operations reiserfs_priv_file_inode_operations = {
+ .setattr = reiserfs_setattr,
+ .permission = reiserfs_permission,
+ .fileattr_get = reiserfs_fileattr_get,
+ .fileattr_set = reiserfs_fileattr_set,
+};
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index d54cab854f60..d8debbb6105f 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2087,10 +2087,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
* Mark it private if we're creating the privroot
* or something under it.
*/
- if (IS_PRIVATE(dir) || dentry == REISERFS_SB(sb)->priv_root) {
- inode->i_flags |= S_PRIVATE;
- inode->i_opflags &= ~IOP_XATTR;
- }
+ if (IS_PRIVATE(dir) || dentry == REISERFS_SB(sb)->priv_root)
+ reiserfs_init_priv_inode(inode);
if (reiserfs_posixacl(inode->i_sb)) {
reiserfs_write_unlock(inode->i_sb);
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 42d2c20e1345..52240cc891cf 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -378,13 +378,11 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
/*
* Propagate the private flag so we know we're
- * in the priv tree. Also clear IOP_XATTR
+ * in the priv tree. Also clear xattr support
* since we don't have xattrs on xattr files.
*/
- if (IS_PRIVATE(dir)) {
- inode->i_flags |= S_PRIVATE;
- inode->i_opflags &= ~IOP_XATTR;
- }
+ if (IS_PRIVATE(dir))
+ reiserfs_init_priv_inode(inode);
}
reiserfs_write_unlock(dir->i_sb);
if (retval == IO_ERROR) {
@@ -1649,6 +1647,48 @@ static int reiserfs_rename(struct mnt_idmap *idmap,
return retval;
}
+static const struct inode_operations reiserfs_priv_dir_inode_operations = {
+ .create = reiserfs_create,
+ .lookup = reiserfs_lookup,
+ .link = reiserfs_link,
+ .unlink = reiserfs_unlink,
+ .symlink = reiserfs_symlink,
+ .mkdir = reiserfs_mkdir,
+ .rmdir = reiserfs_rmdir,
+ .mknod = reiserfs_mknod,
+ .rename = reiserfs_rename,
+ .setattr = reiserfs_setattr,
+ .permission = reiserfs_permission,
+ .fileattr_get = reiserfs_fileattr_get,
+ .fileattr_set = reiserfs_fileattr_set,
+};
+
+static const struct inode_operations reiserfs_priv_symlink_inode_operations = {
+ .get_link = page_get_link,
+ .setattr = reiserfs_setattr,
+ .permission = reiserfs_permission,
+};
+
+static const struct inode_operations reiserfs_priv_special_inode_operations = {
+ .setattr = reiserfs_setattr,
+ .permission = reiserfs_permission,
+};
+
+void reiserfs_init_priv_inode(struct inode *inode)
+{
+ inode->i_flags |= S_PRIVATE;
+ inode->i_opflags &= ~IOP_XATTR;
+
+ if (S_ISREG(inode->i_mode))
+ inode->i_op = &reiserfs_priv_file_inode_operations;
+ else if (S_ISDIR(inode->i_mode))
+ inode->i_op = &reiserfs_priv_dir_inode_operations;
+ else if (S_ISLNK(inode->i_mode))
+ inode->i_op = &reiserfs_priv_symlink_inode_operations;
+ else
+ inode->i_op = &reiserfs_priv_special_inode_operations;
+}
+
/* directories can handle most operations... */
const struct inode_operations reiserfs_dir_inode_operations = {
.create = reiserfs_create,
diff --git a/fs/reiserfs/reiserfs.h b/fs/reiserfs/reiserfs.h
index 98e6f53c2fe0..1bccf6a2e908 100644
--- a/fs/reiserfs/reiserfs.h
+++ b/fs/reiserfs/reiserfs.h
@@ -3106,6 +3106,7 @@ int reiserfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
int __reiserfs_write_begin(struct page *page, unsigned from, unsigned len);
/* namei.c */
+void reiserfs_init_priv_inode(struct inode *inode);
void set_de_name_and_namelen(struct reiserfs_dir_entry *de);
int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
struct treepath *path, struct reiserfs_dir_entry *de);
@@ -3175,6 +3176,7 @@ void reiserfs_unmap_buffer(struct buffer_head *);
/* file.c */
extern const struct inode_operations reiserfs_file_inode_operations;
+extern const struct inode_operations reiserfs_priv_file_inode_operations;
extern const struct file_operations reiserfs_file_operations;
extern const struct address_space_operations reiserfs_address_space_operations;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 06d810c72c52..651027967159 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -52,6 +52,7 @@
#include <linux/quotaops.h>
#include <linux/security.h>
#include <linux/posix_acl_xattr.h>
+#include <linux/xattr.h>
#define PRIVROOT_NAME ".reiserfs_priv"
#define XAROOT_NAME "xattrs"
@@ -770,23 +771,34 @@ out:
(handler) != NULL; \
(handler) = *(handlers)++)
+static inline bool reiserfs_posix_acl_list(const char *name,
+ struct dentry *dentry)
+{
+ return (posix_acl_type(name) >= 0) &&
+ IS_POSIXACL(d_backing_inode(dentry));
+}
+
/* This is the implementation for the xattr plugin infrastructure */
-static inline const struct xattr_handler *
-find_xattr_handler_prefix(const struct xattr_handler **handlers,
- const char *name)
+static inline bool reiserfs_xattr_list(const struct xattr_handler **handlers,
+ const char *name, struct dentry *dentry)
{
- const struct xattr_handler *xah;
+ if (handlers) {
+ const struct xattr_handler *xah = NULL;
- if (!handlers)
- return NULL;
+ for_each_xattr_handler(handlers, xah) {
+ const char *prefix = xattr_prefix(xah);
- for_each_xattr_handler(handlers, xah) {
- const char *prefix = xattr_prefix(xah);
- if (strncmp(prefix, name, strlen(prefix)) == 0)
- break;
+ if (strncmp(prefix, name, strlen(prefix)))
+ continue;
+
+ if (!xattr_handler_can_list(xah, dentry))
+ return false;
+
+ return true;
+ }
}
- return xah;
+ return reiserfs_posix_acl_list(name, dentry);
}
struct listxattr_buf {
@@ -807,12 +819,8 @@ static bool listxattr_filler(struct dir_context *ctx, const char *name,
if (name[0] != '.' ||
(namelen != 1 && (name[1] != '.' || namelen != 2))) {
- const struct xattr_handler *handler;
-
- handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr,
- name);
- if (!handler /* Unsupported xattr name */ ||
- (handler->list && !handler->list(b->dentry)))
+ if (!reiserfs_xattr_list(b->dentry->d_sb->s_xattr, name,
+ b->dentry))
return true;
size = namelen + 1;
if (b->buf) {
@@ -888,8 +896,7 @@ static int create_privroot(struct dentry *dentry)
return -EOPNOTSUPP;
}
- d_inode(dentry)->i_flags |= S_PRIVATE;
- d_inode(dentry)->i_opflags &= ~IOP_XATTR;
+ reiserfs_init_priv_inode(d_inode(dentry));
reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
"storage.\n", PRIVROOT_NAME);
@@ -911,10 +918,6 @@ const struct xattr_handler *reiserfs_xattr_handlers[] = {
#ifdef CONFIG_REISERFS_FS_SECURITY
&reiserfs_xattr_security_handler,
#endif
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
- &posix_acl_access_xattr_handler,
- &posix_acl_default_xattr_handler,
-#endif
NULL
};
@@ -975,10 +978,8 @@ int reiserfs_lookup_privroot(struct super_block *s)
if (!IS_ERR(dentry)) {
REISERFS_SB(s)->priv_root = dentry;
d_set_d_op(dentry, &xattr_lookup_poison_ops);
- if (d_really_is_positive(dentry)) {
- d_inode(dentry)->i_flags |= S_PRIVATE;
- d_inode(dentry)->i_opflags &= ~IOP_XATTR;
- }
+ if (d_really_is_positive(dentry))
+ reiserfs_init_priv_inode(d_inode(dentry));
} else
err = PTR_ERR(dentry);
inode_unlock(d_inode(s->s_root));
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 41c0ea84fbff..6e0a099dd788 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -39,6 +39,22 @@ static bool security_list(struct dentry *dentry)
return !IS_PRIVATE(d_inode(dentry));
}
+static int
+reiserfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+ void *fs_info)
+{
+ struct reiserfs_security_handle *sec = fs_info;
+
+ sec->value = kmemdup(xattr_array->value, xattr_array->value_len,
+ GFP_KERNEL);
+ if (!sec->value)
+ return -ENOMEM;
+
+ sec->name = xattr_array->name;
+ sec->length = xattr_array->value_len;
+ return 0;
+}
+
/* Initializes the security context for a new inode and returns the number
* of blocks needed for the transaction. If successful, reiserfs_security
* must be released using reiserfs_security_free when the caller is done. */
@@ -56,12 +72,9 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,
if (IS_PRIVATE(dir))
return 0;
- error = security_old_inode_init_security(inode, dir, qstr, &sec->name,
- &sec->value, &sec->length);
+ error = security_inode_init_security(inode, dir, qstr,
+ &reiserfs_initxattrs, sec);
if (error) {
- if (error == -EOPNOTSUPP)
- error = 0;
-
sec->name = NULL;
sec->value = NULL;
sec->length = 0;
@@ -82,11 +95,15 @@ int reiserfs_security_write(struct reiserfs_transaction_handle *th,
struct inode *inode,
struct reiserfs_security_handle *sec)
{
+ char xattr_name[XATTR_NAME_MAX + 1] = XATTR_SECURITY_PREFIX;
int error;
- if (strlen(sec->name) < sizeof(XATTR_SECURITY_PREFIX))
+
+ if (XATTR_SECURITY_PREFIX_LEN + strlen(sec->name) > XATTR_NAME_MAX)
return -EINVAL;
- error = reiserfs_xattr_set_handle(th, inode, sec->name, sec->value,
+ strlcat(xattr_name, sec->name, sizeof(xattr_name));
+
+ error = reiserfs_xattr_set_handle(th, inode, xattr_name, sec->value,
sec->length, XATTR_CREATE);
if (error == -ENODATA || error == -EOPNOTSUPP)
error = 0;