diff options
Diffstat (limited to 'fs/reiserfs/xattr.c')
| -rw-r--r-- | fs/reiserfs/xattr.c | 220 | 
1 files changed, 106 insertions, 114 deletions
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 5d04a7828e7..ca416d099e7 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -33,7 +33,7 @@   * The xattrs themselves are protected by the xattr_sem.   */ -#include <linux/reiserfs_fs.h> +#include "reiserfs.h"  #include <linux/capability.h>  #include <linux/dcache.h>  #include <linux/namei.h> @@ -43,46 +43,50 @@  #include <linux/file.h>  #include <linux/pagemap.h>  #include <linux/xattr.h> -#include <linux/reiserfs_xattr.h> -#include <linux/reiserfs_acl.h> +#include "xattr.h" +#include "acl.h"  #include <asm/uaccess.h>  #include <net/checksum.h>  #include <linux/stat.h>  #include <linux/quotaops.h>  #include <linux/security.h> +#include <linux/posix_acl_xattr.h>  #define PRIVROOT_NAME ".reiserfs_priv"  #define XAROOT_NAME   "xattrs" -/* Helpers for inode ops. We do this so that we don't have all the VFS +/* + * Helpers for inode ops. We do this so that we don't have all the VFS   * overhead and also for proper i_mutex annotation. - * dir->i_mutex must be held for all of them. */ + * dir->i_mutex must be held for all of them. + */  #ifdef CONFIG_REISERFS_FS_XATTR  static int xattr_create(struct inode *dir, struct dentry *dentry, int mode)  {  	BUG_ON(!mutex_is_locked(&dir->i_mutex)); -	return dir->i_op->create(dir, dentry, mode, NULL); +	return dir->i_op->create(dir, dentry, mode, true);  }  #endif -static int xattr_mkdir(struct inode *dir, struct dentry *dentry, int mode) +static int xattr_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)  {  	BUG_ON(!mutex_is_locked(&dir->i_mutex));  	return dir->i_op->mkdir(dir, dentry, mode);  } -/* We use I_MUTEX_CHILD here to silence lockdep. It's safe because xattr +/* + * We use I_MUTEX_CHILD here to silence lockdep. It's safe because xattr   * mutation ops aren't called during rename or splace, which are the   * only other users of I_MUTEX_CHILD. It violates the ordering, but that's - * better than allocating another subclass just for this code. */ + * better than allocating another subclass just for this code. + */  static int xattr_unlink(struct inode *dir, struct dentry *dentry)  {  	int error;  	BUG_ON(!mutex_is_locked(&dir->i_mutex)); -	reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex, -					I_MUTEX_CHILD, dir->i_sb); +	mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);  	error = dir->i_op->unlink(dir, dentry);  	mutex_unlock(&dentry->d_inode->i_mutex); @@ -96,16 +100,13 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry)  	int error;  	BUG_ON(!mutex_is_locked(&dir->i_mutex)); -	reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex, -					I_MUTEX_CHILD, dir->i_sb); -	dentry_unhash(dentry); +	mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);  	error = dir->i_op->rmdir(dir, dentry);  	if (!error)  		dentry->d_inode->i_flags |= S_DEAD;  	mutex_unlock(&dentry->d_inode->i_mutex);  	if (!error)  		d_delete(dentry); -	dput(dentry);  	return error;  } @@ -169,10 +170,13 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags)  	return xadir;  } -/* The following are side effects of other operations that aren't explicitly +/* + * 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. */ + * or ownership changes, object deletions, etc. + */  struct reiserfs_dentry_buf { +	struct dir_context ctx;  	struct dentry *xadir;  	int count;  	struct dentry *dentries[8]; @@ -189,8 +193,8 @@ fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset,  	if (dbuf->count == ARRAY_SIZE(dbuf->dentries))  		return -ENOSPC; -	if (name[0] == '.' && (name[1] == '\0' || -			       (name[1] == '.' && name[2] == '\0'))) +	if (name[0] == '.' && (namelen < 2 || +			       (namelen == 2 && name[1] == '.')))  		return 0;  	dentry = lookup_one_len(name, dbuf->xadir, namelen); @@ -225,74 +229,71 @@ static int reiserfs_for_each_xattr(struct inode *inode,  {  	struct dentry *dir;  	int i, err = 0; -	loff_t pos = 0;  	struct reiserfs_dentry_buf buf = { -		.count = 0, +		.ctx.actor = fill_with_dentries,  	};  	/* Skip out, an xattr has no xattrs associated with it */  	if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1)  		return 0; -	reiserfs_write_unlock(inode->i_sb);  	dir = open_xa_dir(inode, XATTR_REPLACE);  	if (IS_ERR(dir)) {  		err = PTR_ERR(dir); -		reiserfs_write_lock(inode->i_sb);  		goto out;  	} else if (!dir->d_inode) {  		err = 0; -		reiserfs_write_lock(inode->i_sb);  		goto out_dir;  	}  	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); -	reiserfs_write_lock(inode->i_sb); -  	buf.xadir = dir; -	err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos); -	while ((err == 0 || err == -ENOSPC) && buf.count) { -		err = 0; - -		for (i = 0; i < buf.count && buf.dentries[i]; i++) { -			int lerr = 0; +	while (1) { +		err = reiserfs_readdir_inode(dir->d_inode, &buf.ctx); +		if (err) +			break; +		if (!buf.count) +			break; +		for (i = 0; !err && i < buf.count && buf.dentries[i]; i++) {  			struct dentry *dentry = buf.dentries[i]; -			if (err == 0 && !S_ISDIR(dentry->d_inode->i_mode)) -				lerr = action(dentry, data); +			if (!S_ISDIR(dentry->d_inode->i_mode)) +				err = action(dentry, data);  			dput(dentry);  			buf.dentries[i] = NULL; -			err = lerr ?: err;  		} +		if (err) +			break;  		buf.count = 0; -		if (!err) -			err = reiserfs_readdir_dentry(dir, &buf, -						      fill_with_dentries, &pos);  	}  	mutex_unlock(&dir->d_inode->i_mutex); -	/* Clean up after a failed readdir */  	cleanup_dentry_buf(&buf);  	if (!err) { -		/* We start a transaction here to avoid a ABBA situation +		/* +		 * We start a transaction here to avoid a ABBA situation  		 * between the xattr root's i_mutex and the journal lock.  		 * This doesn't incur much additional overhead since the  		 * new transaction will just nest inside the -		 * outer transaction. */ +		 * outer transaction. +		 */  		int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 +  			     4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb);  		struct reiserfs_transaction_handle th; +		reiserfs_write_lock(inode->i_sb);  		err = journal_begin(&th, inode->i_sb, blocks); +		reiserfs_write_unlock(inode->i_sb);  		if (!err) {  			int jerror; -			reiserfs_mutex_lock_nested_safe( -					  &dir->d_parent->d_inode->i_mutex, -					  I_MUTEX_XATTR, inode->i_sb); +			mutex_lock_nested(&dir->d_parent->d_inode->i_mutex, +					  I_MUTEX_XATTR);  			err = action(dir, data); -			jerror = journal_end(&th, inode->i_sb, blocks); +			reiserfs_write_lock(inode->i_sb); +			jerror = journal_end(&th); +			reiserfs_write_unlock(inode->i_sb);  			mutex_unlock(&dir->d_parent->d_inode->i_mutex);  			err = jerror ?: err;  		} @@ -320,7 +321,19 @@ static int delete_one_xattr(struct dentry *dentry, void *data)  static int chown_one_xattr(struct dentry *dentry, void *data)  {  	struct iattr *attrs = data; -	return reiserfs_setattr(dentry, attrs); +	int ia_valid = attrs->ia_valid; +	int err; + +	/* +	 * We only want the ownership bits. Otherwise, we'll do +	 * things like change a directory to a regular file if +	 * ATTR_MODE is set. +	 */ +	attrs->ia_valid &= (ATTR_UID|ATTR_GID); +	err = reiserfs_setattr(dentry, attrs); +	attrs->ia_valid = ia_valid; + +	return err;  }  /* No i_mutex, but the inode is unconnected. */ @@ -344,9 +357,11 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs)  }  #ifdef CONFIG_REISERFS_FS_XATTR -/* Returns a dentry corresponding to a specific extended attribute file +/* + * 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. */ + * valid or negative dentry, or an error is returned. + */  static struct dentry *xattr_lookup(struct inode *inode, const char *name,  				    int flags)  { @@ -395,8 +410,10 @@ static struct page *reiserfs_get_page(struct inode *dir, size_t n)  {  	struct address_space *mapping = dir->i_mapping;  	struct page *page; -	/* We can deadlock if we try to free dentries, -	   and an unlink/rmdir has just occured - GFP_NOFS avoids this */ +	/* +	 * We can deadlock if we try to free dentries, +	 * and an unlink/rmdir has just occurred - GFP_NOFS avoids this +	 */  	mapping_set_gfp_mask(mapping, GFP_NOFS);  	page = read_mapping_page(mapping, n >> PAGE_CACHE_SHIFT, NULL);  	if (!IS_ERR(page)) { @@ -406,7 +423,7 @@ static struct page *reiserfs_get_page(struct inode *dir, size_t n)  	}  	return page; -      fail: +fail:  	reiserfs_put_page(page);  	return ERR_PTR(-EIO);  } @@ -447,9 +464,7 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name)  	}  	if (dentry->d_inode) { -		reiserfs_write_lock(inode->i_sb);  		err = xattr_unlink(xadir->d_inode, dentry); -		reiserfs_write_unlock(inode->i_sb);  		update_ctime(inode);  	} @@ -483,24 +498,17 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,  	if (get_inode_sd_version(inode) == STAT_DATA_V1)  		return -EOPNOTSUPP; -	reiserfs_write_unlock(inode->i_sb); -  	if (!buffer) {  		err = lookup_and_delete_xattr(inode, name); -		reiserfs_write_lock(inode->i_sb);  		return err;  	}  	dentry = xattr_lookup(inode, name, flags); -	if (IS_ERR(dentry)) { -		reiserfs_write_lock(inode->i_sb); +	if (IS_ERR(dentry))  		return PTR_ERR(dentry); -	}  	down_write(&REISERFS_I(inode)->i_xattr_sem); -	reiserfs_write_lock(inode->i_sb); -  	xahash = xattr_hash(buffer, buffer_size);  	while (buffer_pos < buffer_size || buffer_pos == 0) {  		size_t chunk; @@ -530,6 +538,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,  			rxh->h_hash = cpu_to_le32(xahash);  		} +		reiserfs_write_lock(inode->i_sb);  		err = __reiserfs_write_begin(page, page_offset, chunk + skip);  		if (!err) {  			if (buffer) @@ -538,6 +547,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,  						    page_offset + chunk +  						    skip);  		} +		reiserfs_write_unlock(inode->i_sb);  		unlock_page(page);  		reiserfs_put_page(page);  		buffer_pos += chunk; @@ -555,13 +565,10 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,  			.ia_valid = ATTR_SIZE | ATTR_CTIME,  		}; -		reiserfs_write_unlock(inode->i_sb);  		mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); -		down_write(&dentry->d_inode->i_alloc_sem); -		reiserfs_write_lock(inode->i_sb); +		inode_dio_wait(dentry->d_inode);  		err = reiserfs_setattr(dentry, &newattrs); -		up_write(&dentry->d_inode->i_alloc_sem);  		mutex_unlock(&dentry->d_inode->i_mutex);  	} else  		update_ctime(inode); @@ -585,18 +592,19 @@ int reiserfs_xattr_set(struct inode *inode, const char *name,  	reiserfs_write_lock(inode->i_sb);  	error = journal_begin(&th, inode->i_sb, jbegin_count); +	reiserfs_write_unlock(inode->i_sb);  	if (error) { -		reiserfs_write_unlock(inode->i_sb);  		return error;  	}  	error = reiserfs_xattr_set_handle(&th, inode, name,  					  buffer, buffer_size, flags); -	error2 = journal_end(&th, inode->i_sb, jbegin_count); +	reiserfs_write_lock(inode->i_sb); +	error2 = journal_end(&th); +	reiserfs_write_unlock(inode->i_sb);  	if (error == 0)  		error = error2; -	reiserfs_write_unlock(inode->i_sb);  	return error;  } @@ -619,8 +627,10 @@ reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer,  	if (name == NULL)  		return -EINVAL; -	/* We can't have xattrs attached to v1 items since they don't have -	 * generation numbers */ +	/* +	 * We can't have xattrs attached to v1 items since they don't have +	 * generation numbers +	 */  	if (get_inode_sd_version(inode) == STAT_DATA_V1)  		return -EOPNOTSUPP; @@ -791,6 +801,7 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name)  }  struct listxattr_buf { +	struct dir_context ctx;  	size_t size;  	size_t pos;  	char *buf; @@ -836,8 +847,8 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)  {  	struct dentry *dir;  	int err = 0; -	loff_t pos = 0;  	struct listxattr_buf buf = { +		.ctx.actor = listxattr_filler,  		.dentry = dentry,  		.buf = buffer,  		.size = buffer ? size : 0, @@ -859,7 +870,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)  	}  	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); -	err = reiserfs_readdir_dentry(dir, &buf, listxattr_filler, &pos); +	err = reiserfs_readdir_inode(dir->d_inode, &buf.ctx);  	mutex_unlock(&dir->d_inode->i_mutex);  	if (!err) @@ -870,24 +881,6 @@ out:  	return err;  } -static int reiserfs_check_acl(struct inode *inode, int mask) -{ -	struct posix_acl *acl; -	int error = -EAGAIN; /* do regular unix permission checks by default */ - -	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); - -	if (acl) { -		if (!IS_ERR(acl)) { -			error = posix_acl_permission(inode, acl, mask); -			posix_acl_release(acl); -		} else if (PTR_ERR(acl) != -ENODATA) -			error = PTR_ERR(acl); -	} - -	return error; -} -  static int create_privroot(struct dentry *dentry)  {  	int err; @@ -917,7 +910,7 @@ static int create_privroot(struct dentry *dentry) { return 0; }  #endif  /* Actual operations that are exported to VFS-land */ -const struct xattr_handler *reiserfs_xattr_handlers[] = { +static const struct xattr_handler *reiserfs_xattr_handlers[] = {  #ifdef CONFIG_REISERFS_FS_XATTR  	&reiserfs_xattr_user_handler,  	&reiserfs_xattr_trusted_handler, @@ -926,20 +919,24 @@ const struct xattr_handler *reiserfs_xattr_handlers[] = {  	&reiserfs_xattr_security_handler,  #endif  #ifdef CONFIG_REISERFS_FS_POSIX_ACL -	&reiserfs_posix_acl_access_handler, -	&reiserfs_posix_acl_default_handler, +	&posix_acl_access_xattr_handler, +	&posix_acl_default_xattr_handler,  #endif  	NULL  };  static int xattr_mount_check(struct super_block *s)  { -	/* We need generation numbers to ensure that the oid mapping is correct -	 * v3.5 filesystems don't have them. */ +	/* +	 * We need generation numbers to ensure that the oid mapping is correct +	 * v3.5 filesystems don't have them. +	 */  	if (old_format_only(s)) {  		if (reiserfs_xattrs_optional(s)) { -			/* Old format filesystem, but optional xattrs have -			 * been enabled. Error out. */ +			/* +			 * 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. " @@ -960,17 +957,10 @@ int reiserfs_permission(struct inode *inode, int mask)  	if (IS_PRIVATE(inode))  		return 0; -#ifdef CONFIG_REISERFS_FS_XATTR -	/* -	 * Stat data v1 doesn't support ACLs. -	 */ -	if (get_inode_sd_version(inode) != STAT_DATA_V1) -		return generic_permission(inode, mask, reiserfs_check_acl); -#endif -	return generic_permission(inode, mask, NULL); +	return generic_permission(inode, mask);  } -static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd) +static int xattr_hide_revalidate(struct dentry *dentry, unsigned int flags)  {  	return -EPERM;  } @@ -985,12 +975,12 @@ int reiserfs_lookup_privroot(struct super_block *s)  	int err = 0;  	/* If we don't have the privroot located yet - go find it */ -	reiserfs_mutex_lock_safe(&s->s_root->d_inode->i_mutex, s); +	mutex_lock(&s->s_root->d_inode->i_mutex);  	dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,  				strlen(PRIVROOT_NAME));  	if (!IS_ERR(dentry)) {  		REISERFS_SB(s)->priv_root = dentry; -		dentry->d_op = &xattr_lookup_poison_ops; +		d_set_d_op(dentry, &xattr_lookup_poison_ops);  		if (dentry->d_inode)  			dentry->d_inode->i_flags |= S_PRIVATE;  	} else @@ -1000,9 +990,11 @@ int reiserfs_lookup_privroot(struct super_block *s)  	return err;  } -/* We need to take a copy of the mount flags since things like +/* + * We need to take a copy of the mount flags since things like   * MS_RDONLY don't get set until *after* we're called. - * mount_flags != mount_options */ + * mount_flags != mount_options + */  int reiserfs_xattr_init(struct super_block *s, int mount_flags)  {  	int err = 0; @@ -1013,14 +1005,14 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)  		goto error;  	if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) { -		reiserfs_mutex_lock_safe(&s->s_root->d_inode->i_mutex, s); +		mutex_lock(&s->s_root->d_inode->i_mutex);  		err = create_privroot(REISERFS_SB(s)->priv_root);  		mutex_unlock(&s->s_root->d_inode->i_mutex);  	}  	if (privroot->d_inode) {  		s->s_xattr = reiserfs_xattr_handlers; -		reiserfs_mutex_lock_safe(&privroot->d_inode->i_mutex, s); +		mutex_lock(&privroot->d_inode->i_mutex);  		if (!REISERFS_SB(s)->xattr_root) {  			struct dentry *dentry;  			dentry = lookup_one_len(XAROOT_NAME, privroot, @@ -1035,8 +1027,8 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)  error:  	if (err) { -		clear_bit(REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt)); -		clear_bit(REISERFS_POSIXACL, &(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);  	}  	/* The super_block MS_POSIXACL must mirror the (no)acl mount option. */  | 
