Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 138860
b: refs/heads/master
c: 0ab2621
h: refs/heads/master
v: v3
  • Loading branch information
Jeff Mahoney authored and Linus Torvalds committed Mar 30, 2009
1 parent b1db877 commit 047dc58
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 50 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 48b32a3553a54740d236b79a90f20147a25875e3
refs/heads/master: 0ab2621ebd9a28bf7a524ecd50d492a10579dfcc
3 changes: 1 addition & 2 deletions trunk/fs/reiserfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1914,9 +1914,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
goto out_inserted_sd;
}

/* XXX CHECK THIS */
if (reiserfs_posixacl(inode->i_sb)) {
retval = reiserfs_inherit_default_acl(dir, dentry, inode);
retval = reiserfs_inherit_default_acl(th, dir, dentry, inode);
if (retval) {
err = retval;
reiserfs_check_path(&path_to_key);
Expand Down
14 changes: 3 additions & 11 deletions trunk/fs/reiserfs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,15 +598,13 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode,
2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
struct reiserfs_transaction_handle th;
int locked;

if (!(inode = new_inode(dir->i_sb))) {
return -ENOMEM;
}
new_inode_init(inode, dir, mode);

locked = reiserfs_cache_default_acl(dir);

jbegin_count += reiserfs_cache_default_acl(dir);
reiserfs_write_lock(dir->i_sb);

retval = journal_begin(&th, dir->i_sb, jbegin_count);
Expand Down Expand Up @@ -662,7 +660,6 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
JOURNAL_PER_BALANCE_CNT * 3 +
2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
int locked;

if (!new_valid_dev(rdev))
return -EINVAL;
Expand All @@ -672,8 +669,7 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
}
new_inode_init(inode, dir, mode);

locked = reiserfs_cache_default_acl(dir);

jbegin_count += reiserfs_cache_default_acl(dir);
reiserfs_write_lock(dir->i_sb);

retval = journal_begin(&th, dir->i_sb, jbegin_count);
Expand Down Expand Up @@ -732,7 +728,6 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
JOURNAL_PER_BALANCE_CNT * 3 +
2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
int locked;

#ifdef DISPLACE_NEW_PACKING_LOCALITIES
/* set flag that new packing locality created and new blocks for the content * of that directory are not displaced yet */
Expand All @@ -744,8 +739,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
}
new_inode_init(inode, dir, mode);

locked = reiserfs_cache_default_acl(dir);

jbegin_count += reiserfs_cache_default_acl(dir);
reiserfs_write_lock(dir->i_sb);

retval = journal_begin(&th, dir->i_sb, jbegin_count);
Expand Down Expand Up @@ -1034,8 +1028,6 @@ static int reiserfs_symlink(struct inode *parent_dir,
memcpy(name, symname, strlen(symname));
padd_item(name, item_len, strlen(symname));

/* We would inherit the default ACL here, but symlinks don't get ACLs */

retval = journal_begin(&th, parent_dir->i_sb, jbegin_count);
if (retval) {
drop_new_inode(inode);
Expand Down
39 changes: 30 additions & 9 deletions trunk/fs/reiserfs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,8 +632,9 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name)
* 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_handle(struct reiserfs_transaction_handle *th,
struct inode *inode, const char *name,
const void *buffer, size_t buffer_size, int flags)
{
int err = 0;
struct dentry *dentry;
Expand Down Expand Up @@ -723,14 +724,34 @@ __reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
return err;
}

int
reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
size_t buffer_size, int flags)
/* We need to start a transaction to maintain lock ordering */
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;

struct reiserfs_transaction_handle th;
int error, error2;
size_t jbegin_count = reiserfs_xattr_nblocks(inode, buffer_size);

if (!(flags & XATTR_REPLACE))
jbegin_count += reiserfs_xattr_jcreate_nblocks(inode);

reiserfs_write_lock(inode->i_sb);
error = journal_begin(&th, inode->i_sb, jbegin_count);
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);
if (error == 0)
error = error2;
reiserfs_write_unlock(inode->i_sb);

return error;
}

/*
Expand Down
105 changes: 81 additions & 24 deletions trunk/fs/reiserfs/xattr_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@
#include <linux/reiserfs_acl.h>
#include <asm/uaccess.h>

static int reiserfs_set_acl(struct inode *inode, int type,
static int reiserfs_set_acl(struct reiserfs_transaction_handle *th,
struct inode *inode, int type,
struct posix_acl *acl);

static int
xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
{
struct posix_acl *acl;
int error;

int error, error2;
struct reiserfs_transaction_handle th;
size_t jcreate_blocks;
if (!reiserfs_posixacl(inode->i_sb))
return -EOPNOTSUPP;
if (!is_owner_or_cap(inode))
Expand All @@ -36,7 +38,21 @@ xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
} else
acl = NULL;

error = reiserfs_set_acl(inode, type, acl);
/* Pessimism: We can't assume that anything from the xattr root up
* has been created. */

jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
reiserfs_xattr_nblocks(inode, size) * 2;

reiserfs_write_lock(inode->i_sb);
error = journal_begin(&th, inode->i_sb, jcreate_blocks);
if (error == 0) {
error = reiserfs_set_acl(&th, inode, type, acl);
error2 = journal_end(&th, inode->i_sb, jcreate_blocks);
if (error2)
error = error2;
}
reiserfs_write_unlock(inode->i_sb);

release_and_out:
posix_acl_release(acl);
Expand Down Expand Up @@ -266,7 +282,8 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
* BKL held [before 2.5.x]
*/
static int
reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
int type, struct posix_acl *acl)
{
char *name;
void *value = NULL;
Expand Down Expand Up @@ -310,7 +327,7 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
return (int)PTR_ERR(value);
}

error = __reiserfs_xattr_set(inode, name, value, size, 0);
error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0);

/*
* Ensure that the inode gets dirtied if we're only using
Expand All @@ -337,7 +354,8 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
/* dir->i_mutex: locked,
* inode is new and not released into the wild yet */
int
reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
struct inode *dir, struct dentry *dentry,
struct inode *inode)
{
struct posix_acl *acl;
Expand Down Expand Up @@ -374,7 +392,8 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,

/* Copy the default ACL to the default ACL of a new directory */
if (S_ISDIR(inode->i_mode)) {
err = reiserfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
acl);
if (err)
goto cleanup;
}
Expand All @@ -395,9 +414,9 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,

/* If we need an ACL.. */
if (need_acl > 0) {
err =
reiserfs_set_acl(inode, ACL_TYPE_ACCESS,
acl_copy);
err = reiserfs_set_acl(th, inode,
ACL_TYPE_ACCESS,
acl_copy);
if (err)
goto cleanup_copy;
}
Expand All @@ -415,21 +434,45 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
return err;
}

/* Looks up and caches the result of the default ACL.
* We do this so that we don't need to carry the xattr_sem into
* reiserfs_new_inode if we don't need to */
/* This is used to cache the default acl before a new object is created.
* The biggest reason for this is to get an idea of how many blocks will
* actually be required for the create operation if we must inherit an ACL.
* An ACL write can add up to 3 object creations and an additional file write
* so we'd prefer not to reserve that many blocks in the journal if we can.
* It also has the advantage of not loading the ACL with a transaction open,
* this may seem silly, but if the owner of the directory is doing the
* creation, the ACL may not be loaded since the permissions wouldn't require
* it.
* We return the number of blocks required for the transaction.
*/
int reiserfs_cache_default_acl(struct inode *inode)
{
int ret = 0;
if (reiserfs_posixacl(inode->i_sb) && !IS_PRIVATE(inode)) {
struct posix_acl *acl;
acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
ret = (acl && !IS_ERR(acl));
if (ret)
posix_acl_release(acl);
struct posix_acl *acl;
int nblocks = 0;

if (IS_PRIVATE(inode))
return 0;

acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);

if (acl && !IS_ERR(acl)) {
int size = reiserfs_acl_size(acl->a_count);

/* Other xattrs can be created during inode creation. We don't
* want to claim too many blocks, so we check to see if we
* we need to create the tree to the xattrs, and then we
* just want two files. */
nblocks = reiserfs_xattr_jcreate_nblocks(inode);
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);

REISERFS_I(inode)->i_flags |= i_has_xattr_dir;

/* We need to account for writes + bitmaps for two files */
nblocks += reiserfs_xattr_nblocks(inode, size) * 4;
posix_acl_release(acl);
}

return ret;
return nblocks;
}

int reiserfs_acl_chmod(struct inode *inode)
Expand All @@ -455,8 +498,22 @@ int reiserfs_acl_chmod(struct inode *inode)
if (!clone)
return -ENOMEM;
error = posix_acl_chmod_masq(clone, inode->i_mode);
if (!error)
error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
if (!error) {
struct reiserfs_transaction_handle th;
size_t size = reiserfs_xattr_nblocks(inode,
reiserfs_acl_size(clone->a_count));
reiserfs_write_lock(inode->i_sb);
error = journal_begin(&th, inode->i_sb, size * 2);
if (!error) {
int error2;
error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS,
clone);
error2 = journal_end(&th, inode->i_sb, size * 2);
if (error2)
error = error2;
}
reiserfs_write_unlock(inode->i_sb);
}
posix_acl_release(clone);
return error;
}
Expand Down
3 changes: 2 additions & 1 deletion trunk/include/linux/reiserfs_acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ static inline int reiserfs_acl_count(size_t size)
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
struct posix_acl *reiserfs_get_acl(struct inode *inode, int type);
int reiserfs_acl_chmod(struct inode *inode);
int reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
int reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
struct inode *dir, struct dentry *dentry,
struct inode *inode);
int reiserfs_cache_default_acl(struct inode *dir);
extern struct xattr_handler reiserfs_posix_acl_default_handler;
Expand Down
4 changes: 4 additions & 0 deletions trunk/include/linux/reiserfs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,10 @@ struct reiserfs_journal_header {
#define JOURNAL_MAX_COMMIT_AGE 30
#define JOURNAL_MAX_TRANS_AGE 30
#define JOURNAL_PER_BALANCE_CNT (3 * (MAX_HEIGHT-2) + 9)
#define JOURNAL_BLOCKS_PER_OBJECT(sb) (JOURNAL_PER_BALANCE_CNT * 3 + \
2 * (REISERFS_QUOTA_INIT_BLOCKS(sb) + \
REISERFS_QUOTA_TRANS_BLOCKS(sb)))

#ifdef CONFIG_QUOTA
/* We need to update data and inode (atime) */
#define REISERFS_QUOTA_TRANS_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? 2 : 0)
Expand Down
40 changes: 38 additions & 2 deletions trunk/include/linux/reiserfs_xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,50 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name);
int reiserfs_permission(struct inode *inode, int mask);

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);
int reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *,
struct inode *, const char *, const void *,
size_t, int);

extern struct xattr_handler reiserfs_xattr_user_handler;
extern struct xattr_handler reiserfs_xattr_trusted_handler;
extern struct xattr_handler reiserfs_xattr_security_handler;

#define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header))
static inline loff_t reiserfs_xattr_nblocks(struct inode *inode, loff_t size)
{
loff_t ret = 0;
if (reiserfs_file_data_log(inode)) {
ret = _ROUND_UP(xattr_size(size), inode->i_sb->s_blocksize);
ret >>= inode->i_sb->s_blocksize_bits;
}
return ret;
}

/* We may have to create up to 3 objects: xattr root, xattr dir, xattr file.
* Let's try to be smart about it.
* xattr root: We cache it. If it's not cached, we may need to create it.
* xattr dir: If anything has been loaded for this inode, we can set a flag
* saying so.
* xattr file: Since we don't cache xattrs, we can't tell. We always include
* blocks for it.
*
* However, since root and dir can be created between calls - YOU MUST SAVE
* THIS VALUE.
*/
static inline size_t reiserfs_xattr_jcreate_nblocks(struct inode *inode)
{
size_t nblocks = JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);

if ((REISERFS_I(inode)->i_flags & i_has_xattr_dir) == 0) {
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
if (REISERFS_SB(inode->i_sb)->xattr_root == NULL)
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
}

return nblocks;
}

static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
{
init_rwsem(&REISERFS_I(inode)->i_xattr_sem);
Expand Down

0 comments on commit 047dc58

Please sign in to comment.