Commit 4c05141d authored by Jeff Mahoney's avatar Jeff Mahoney Committed by Jeff Mahoney

reiserfs: locking, push write lock out of xattr code

The reiserfs xattr code doesn't need the write lock and sleeps all over
the place. We can simplify the locking by releasing it and reacquiring
after the xattr call.
Signed-off-by: default avatarJeff Mahoney <jeffm@suse.com>
parent c095ba72
...@@ -30,7 +30,6 @@ void reiserfs_evict_inode(struct inode *inode) ...@@ -30,7 +30,6 @@ void reiserfs_evict_inode(struct inode *inode)
JOURNAL_PER_BALANCE_CNT * 2 + JOURNAL_PER_BALANCE_CNT * 2 +
2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb); 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
int depth;
int err; int err;
if (!inode->i_nlink && !is_bad_inode(inode)) if (!inode->i_nlink && !is_bad_inode(inode))
...@@ -40,12 +39,14 @@ void reiserfs_evict_inode(struct inode *inode) ...@@ -40,12 +39,14 @@ void reiserfs_evict_inode(struct inode *inode)
if (inode->i_nlink) if (inode->i_nlink)
goto no_delete; goto no_delete;
depth = reiserfs_write_lock_once(inode->i_sb);
/* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */ /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */ if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
int depth;
reiserfs_delete_xattrs(inode); reiserfs_delete_xattrs(inode);
depth = reiserfs_write_lock_once(inode->i_sb);
if (journal_begin(&th, inode->i_sb, jbegin_count)) if (journal_begin(&th, inode->i_sb, jbegin_count))
goto out; goto out;
reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(inode);
...@@ -72,12 +73,12 @@ void reiserfs_evict_inode(struct inode *inode) ...@@ -72,12 +73,12 @@ void reiserfs_evict_inode(struct inode *inode)
/* all items of file are deleted, so we can remove "save" link */ /* all items of file are deleted, so we can remove "save" link */
remove_save_link(inode, 0 /* not truncate */ ); /* we can't do anything remove_save_link(inode, 0 /* not truncate */ ); /* we can't do anything
* about an error here */ * about an error here */
out:
reiserfs_write_unlock_once(inode->i_sb, depth);
} else { } else {
/* no object items are in the tree */ /* no object items are in the tree */
; ;
} }
out:
reiserfs_write_unlock_once(inode->i_sb, depth);
clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */ clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */
dquot_drop(inode); dquot_drop(inode);
inode->i_blocks = 0; inode->i_blocks = 0;
...@@ -1941,7 +1942,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, ...@@ -1941,7 +1942,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
} }
if (reiserfs_posixacl(inode->i_sb)) { if (reiserfs_posixacl(inode->i_sb)) {
reiserfs_write_unlock(inode->i_sb);
retval = reiserfs_inherit_default_acl(th, dir, dentry, inode); retval = reiserfs_inherit_default_acl(th, dir, dentry, inode);
reiserfs_write_lock(inode->i_sb);
if (retval) { if (retval) {
err = retval; err = retval;
reiserfs_check_path(&path_to_key); reiserfs_check_path(&path_to_key);
...@@ -1956,7 +1959,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, ...@@ -1956,7 +1959,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
inode->i_flags |= S_PRIVATE; inode->i_flags |= S_PRIVATE;
if (security->name) { if (security->name) {
reiserfs_write_unlock(inode->i_sb);
retval = reiserfs_security_write(th, inode, security); retval = reiserfs_security_write(th, inode, security);
reiserfs_write_lock(inode->i_sb);
if (retval) { if (retval) {
err = retval; err = retval;
reiserfs_check_path(&path_to_key); reiserfs_check_path(&path_to_key);
...@@ -3129,6 +3134,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3129,6 +3134,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
*/ */
if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 && if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 &&
attr->ia_size > MAX_NON_LFS) { attr->ia_size > MAX_NON_LFS) {
reiserfs_write_unlock_once(inode->i_sb, depth);
error = -EFBIG; error = -EFBIG;
goto out; goto out;
} }
...@@ -3150,8 +3156,10 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3150,8 +3156,10 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
if (err) if (err)
error = err; error = err;
} }
if (error) if (error) {
reiserfs_write_unlock_once(inode->i_sb, depth);
goto out; goto out;
}
/* /*
* file size is changed, ctime and mtime are * file size is changed, ctime and mtime are
* to be updated * to be updated
...@@ -3159,6 +3167,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3159,6 +3167,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
attr->ia_valid |= (ATTR_MTIME | ATTR_CTIME); attr->ia_valid |= (ATTR_MTIME | ATTR_CTIME);
} }
} }
reiserfs_write_unlock_once(inode->i_sb, depth);
if ((((attr->ia_valid & ATTR_UID) && (from_kuid(&init_user_ns, attr->ia_uid) & ~0xffff)) || if ((((attr->ia_valid & ATTR_UID) && (from_kuid(&init_user_ns, attr->ia_uid) & ~0xffff)) ||
((attr->ia_valid & ATTR_GID) && (from_kgid(&init_user_ns, attr->ia_gid) & ~0xffff))) && ((attr->ia_valid & ATTR_GID) && (from_kgid(&init_user_ns, attr->ia_gid) & ~0xffff))) &&
...@@ -3183,14 +3192,16 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3183,14 +3192,16 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
return error; return error;
/* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */ /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
depth = reiserfs_write_lock_once(inode->i_sb);
error = journal_begin(&th, inode->i_sb, jbegin_count); error = journal_begin(&th, inode->i_sb, jbegin_count);
reiserfs_write_unlock_once(inode->i_sb, depth);
if (error) if (error)
goto out; goto out;
reiserfs_write_unlock_once(inode->i_sb, depth);
error = dquot_transfer(inode, attr); error = dquot_transfer(inode, attr);
depth = reiserfs_write_lock_once(inode->i_sb); depth = reiserfs_write_lock_once(inode->i_sb);
if (error) { if (error) {
journal_end(&th, inode->i_sb, jbegin_count); journal_end(&th, inode->i_sb, jbegin_count);
reiserfs_write_unlock_once(inode->i_sb, depth);
goto out; goto out;
} }
...@@ -3202,17 +3213,11 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3202,17 +3213,11 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
inode->i_gid = attr->ia_gid; inode->i_gid = attr->ia_gid;
mark_inode_dirty(inode); mark_inode_dirty(inode);
error = journal_end(&th, inode->i_sb, jbegin_count); error = journal_end(&th, inode->i_sb, jbegin_count);
reiserfs_write_unlock_once(inode->i_sb, depth);
if (error) if (error)
goto out; goto out;
} }
/*
* Relax the lock here, as it might truncate the
* inode pages and wait for inode pages locks.
* To release such page lock, the owner needs the
* reiserfs lock
*/
reiserfs_write_unlock_once(inode->i_sb, depth);
if ((attr->ia_valid & ATTR_SIZE) && if ((attr->ia_valid & ATTR_SIZE) &&
attr->ia_size != i_size_read(inode)) { attr->ia_size != i_size_read(inode)) {
error = inode_newsize_ok(inode, attr->ia_size); error = inode_newsize_ok(inode, attr->ia_size);
...@@ -3226,16 +3231,13 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3226,16 +3231,13 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
setattr_copy(inode, attr); setattr_copy(inode, attr);
mark_inode_dirty(inode); mark_inode_dirty(inode);
} }
depth = reiserfs_write_lock_once(inode->i_sb);
if (!error && reiserfs_posixacl(inode->i_sb)) { if (!error && reiserfs_posixacl(inode->i_sb)) {
if (attr->ia_valid & ATTR_MODE) if (attr->ia_valid & ATTR_MODE)
error = reiserfs_acl_chmod(inode); error = reiserfs_acl_chmod(inode);
} }
out: out:
reiserfs_write_unlock_once(inode->i_sb, depth);
return error; return error;
} }
......
...@@ -1335,7 +1335,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1335,7 +1335,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
kfree(qf_names[i]); kfree(qf_names[i]);
#endif #endif
err = -EINVAL; err = -EINVAL;
goto out_unlock; goto out_err_unlock;
} }
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
handle_quota_files(s, qf_names, &qfmt); handle_quota_files(s, qf_names, &qfmt);
...@@ -1379,35 +1379,32 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1379,35 +1379,32 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
if (blocks) { if (blocks) {
err = reiserfs_resize(s, blocks); err = reiserfs_resize(s, blocks);
if (err != 0) if (err != 0)
goto out_unlock; goto out_err_unlock;
} }
if (*mount_flags & MS_RDONLY) { if (*mount_flags & MS_RDONLY) {
reiserfs_write_unlock(s);
reiserfs_xattr_init(s, *mount_flags); reiserfs_xattr_init(s, *mount_flags);
/* remount read-only */ /* remount read-only */
if (s->s_flags & MS_RDONLY) if (s->s_flags & MS_RDONLY)
/* it is read-only already */ /* it is read-only already */
goto out_ok; goto out_ok_unlocked;
/*
* Drop write lock. Quota will retake it when needed and lock
* ordering requires calling dquot_suspend() without it.
*/
reiserfs_write_unlock(s);
err = dquot_suspend(s, -1); err = dquot_suspend(s, -1);
if (err < 0) if (err < 0)
goto out_err; goto out_err;
reiserfs_write_lock(s);
/* try to remount file system with read-only permissions */ /* try to remount file system with read-only permissions */
if (sb_umount_state(rs) == REISERFS_VALID_FS if (sb_umount_state(rs) == REISERFS_VALID_FS
|| REISERFS_SB(s)->s_mount_state != REISERFS_VALID_FS) { || REISERFS_SB(s)->s_mount_state != REISERFS_VALID_FS) {
goto out_ok; goto out_ok_unlocked;
} }
reiserfs_write_lock(s);
err = journal_begin(&th, s, 10); err = journal_begin(&th, s, 10);
if (err) if (err)
goto out_unlock; goto out_err_unlock;
/* Mounting a rw partition read-only. */ /* Mounting a rw partition read-only. */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
...@@ -1416,13 +1413,14 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1416,13 +1413,14 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
} else { } else {
/* remount read-write */ /* remount read-write */
if (!(s->s_flags & MS_RDONLY)) { if (!(s->s_flags & MS_RDONLY)) {
reiserfs_write_unlock(s);
reiserfs_xattr_init(s, *mount_flags); reiserfs_xattr_init(s, *mount_flags);
goto out_ok; /* We are read-write already */ goto out_ok_unlocked; /* We are read-write already */
} }
if (reiserfs_is_journal_aborted(journal)) { if (reiserfs_is_journal_aborted(journal)) {
err = journal->j_errno; err = journal->j_errno;
goto out_unlock; goto out_err_unlock;
} }
handle_data_mode(s, mount_options); handle_data_mode(s, mount_options);
...@@ -1431,7 +1429,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1431,7 +1429,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */
err = journal_begin(&th, s, 10); err = journal_begin(&th, s, 10);
if (err) if (err)
goto out_unlock; goto out_err_unlock;
/* Mount a partition which is read-only, read-write */ /* Mount a partition which is read-only, read-write */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
...@@ -1448,26 +1446,22 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1448,26 +1446,22 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
SB_JOURNAL(s)->j_must_wait = 1; SB_JOURNAL(s)->j_must_wait = 1;
err = journal_end(&th, s, 10); err = journal_end(&th, s, 10);
if (err) if (err)
goto out_unlock; goto out_err_unlock;
reiserfs_write_unlock(s);
if (!(*mount_flags & MS_RDONLY)) { if (!(*mount_flags & MS_RDONLY)) {
/*
* Drop write lock. Quota will retake it when needed and lock
* ordering requires calling dquot_resume() without it.
*/
reiserfs_write_unlock(s);
dquot_resume(s, -1); dquot_resume(s, -1);
reiserfs_write_lock(s); reiserfs_write_lock(s);
finish_unfinished(s); finish_unfinished(s);
reiserfs_write_unlock(s);
reiserfs_xattr_init(s, *mount_flags); reiserfs_xattr_init(s, *mount_flags);
} }
out_ok: out_ok_unlocked:
replace_mount_options(s, new_opts); replace_mount_options(s, new_opts);
reiserfs_write_unlock(s);
return 0; return 0;
out_unlock: out_err_unlock:
reiserfs_write_unlock(s); reiserfs_write_unlock(s);
out_err: out_err:
kfree(new_opts); kfree(new_opts);
...@@ -2014,12 +2008,14 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) ...@@ -2014,12 +2008,14 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
goto error; goto error;
} }
reiserfs_write_unlock(s);
if ((errval = reiserfs_lookup_privroot(s)) || if ((errval = reiserfs_lookup_privroot(s)) ||
(errval = reiserfs_xattr_init(s, s->s_flags))) { (errval = reiserfs_xattr_init(s, s->s_flags))) {
dput(s->s_root); dput(s->s_root);
s->s_root = NULL; s->s_root = NULL;
goto error; goto error_unlocked;
} }
reiserfs_write_lock(s);
/* look for files which were to be removed in previous session */ /* look for files which were to be removed in previous session */
finish_unfinished(s); finish_unfinished(s);
...@@ -2028,12 +2024,14 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) ...@@ -2028,12 +2024,14 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
reiserfs_info(s, "using 3.5.x disk format\n"); reiserfs_info(s, "using 3.5.x disk format\n");
} }
reiserfs_write_unlock(s);
if ((errval = reiserfs_lookup_privroot(s)) || if ((errval = reiserfs_lookup_privroot(s)) ||
(errval = reiserfs_xattr_init(s, s->s_flags))) { (errval = reiserfs_xattr_init(s, s->s_flags))) {
dput(s->s_root); dput(s->s_root);
s->s_root = NULL; s->s_root = NULL;
goto error; goto error_unlocked;
} }
reiserfs_write_lock(s);
} }
// mark hash in super block: it could be unset. overwrite should be ok // mark hash in super block: it could be unset. overwrite should be ok
set_sb_hash_function_code(rs, function2code(sbi->s_hash_function)); set_sb_hash_function_code(rs, function2code(sbi->s_hash_function));
......
...@@ -81,8 +81,7 @@ static int xattr_unlink(struct inode *dir, struct dentry *dentry) ...@@ -81,8 +81,7 @@ static int xattr_unlink(struct inode *dir, struct dentry *dentry)
int error; int error;
BUG_ON(!mutex_is_locked(&dir->i_mutex)); BUG_ON(!mutex_is_locked(&dir->i_mutex));
reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex, mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
I_MUTEX_CHILD, dir->i_sb);
error = dir->i_op->unlink(dir, dentry); error = dir->i_op->unlink(dir, dentry);
mutex_unlock(&dentry->d_inode->i_mutex); mutex_unlock(&dentry->d_inode->i_mutex);
...@@ -96,8 +95,7 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -96,8 +95,7 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
int error; int error;
BUG_ON(!mutex_is_locked(&dir->i_mutex)); BUG_ON(!mutex_is_locked(&dir->i_mutex));
reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex, mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
I_MUTEX_CHILD, dir->i_sb);
error = dir->i_op->rmdir(dir, dentry); error = dir->i_op->rmdir(dir, dentry);
if (!error) if (!error)
dentry->d_inode->i_flags |= S_DEAD; dentry->d_inode->i_flags |= S_DEAD;
...@@ -232,22 +230,17 @@ static int reiserfs_for_each_xattr(struct inode *inode, ...@@ -232,22 +230,17 @@ static int reiserfs_for_each_xattr(struct inode *inode,
if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1)
return 0; return 0;
reiserfs_write_unlock(inode->i_sb);
dir = open_xa_dir(inode, XATTR_REPLACE); dir = open_xa_dir(inode, XATTR_REPLACE);
if (IS_ERR(dir)) { if (IS_ERR(dir)) {
err = PTR_ERR(dir); err = PTR_ERR(dir);
reiserfs_write_lock(inode->i_sb);
goto out; goto out;
} else if (!dir->d_inode) { } else if (!dir->d_inode) {
err = 0; err = 0;
reiserfs_write_lock(inode->i_sb);
goto out_dir; goto out_dir;
} }
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
reiserfs_write_lock(inode->i_sb);
buf.xadir = dir; buf.xadir = dir;
while (1) { while (1) {
err = reiserfs_readdir_inode(dir->d_inode, &buf.ctx); err = reiserfs_readdir_inode(dir->d_inode, &buf.ctx);
...@@ -281,14 +274,17 @@ static int reiserfs_for_each_xattr(struct inode *inode, ...@@ -281,14 +274,17 @@ static int reiserfs_for_each_xattr(struct inode *inode,
int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 + int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 +
4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb); 4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb);
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
reiserfs_write_lock(inode->i_sb);
err = journal_begin(&th, inode->i_sb, blocks); err = journal_begin(&th, inode->i_sb, blocks);
reiserfs_write_unlock(inode->i_sb);
if (!err) { if (!err) {
int jerror; int jerror;
reiserfs_mutex_lock_nested_safe( mutex_lock_nested(&dir->d_parent->d_inode->i_mutex,
&dir->d_parent->d_inode->i_mutex, I_MUTEX_XATTR);
I_MUTEX_XATTR, inode->i_sb);
err = action(dir, data); err = action(dir, data);
reiserfs_write_lock(inode->i_sb);
jerror = journal_end(&th, inode->i_sb, blocks); jerror = journal_end(&th, inode->i_sb, blocks);
reiserfs_write_unlock(inode->i_sb);
mutex_unlock(&dir->d_parent->d_inode->i_mutex); mutex_unlock(&dir->d_parent->d_inode->i_mutex);
err = jerror ?: err; err = jerror ?: err;
} }
...@@ -455,9 +451,7 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name) ...@@ -455,9 +451,7 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name)
} }
if (dentry->d_inode) { if (dentry->d_inode) {
reiserfs_write_lock(inode->i_sb);
err = xattr_unlink(xadir->d_inode, dentry); err = xattr_unlink(xadir->d_inode, dentry);
reiserfs_write_unlock(inode->i_sb);
update_ctime(inode); update_ctime(inode);
} }
...@@ -491,24 +485,17 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, ...@@ -491,24 +485,17 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
if (get_inode_sd_version(inode) == STAT_DATA_V1) if (get_inode_sd_version(inode) == STAT_DATA_V1)
return -EOPNOTSUPP; return -EOPNOTSUPP;
reiserfs_write_unlock(inode->i_sb);
if (!buffer) { if (!buffer) {
err = lookup_and_delete_xattr(inode, name); err = lookup_and_delete_xattr(inode, name);
reiserfs_write_lock(inode->i_sb);
return err; return err;
} }
dentry = xattr_lookup(inode, name, flags); dentry = xattr_lookup(inode, name, flags);
if (IS_ERR(dentry)) { if (IS_ERR(dentry))
reiserfs_write_lock(inode->i_sb);
return PTR_ERR(dentry); return PTR_ERR(dentry);
}
down_write(&REISERFS_I(inode)->i_xattr_sem); down_write(&REISERFS_I(inode)->i_xattr_sem);
reiserfs_write_lock(inode->i_sb);
xahash = xattr_hash(buffer, buffer_size); xahash = xattr_hash(buffer, buffer_size);
while (buffer_pos < buffer_size || buffer_pos == 0) { while (buffer_pos < buffer_size || buffer_pos == 0) {
size_t chunk; size_t chunk;
...@@ -538,6 +525,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, ...@@ -538,6 +525,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
rxh->h_hash = cpu_to_le32(xahash); rxh->h_hash = cpu_to_le32(xahash);
} }
reiserfs_write_lock(inode->i_sb);
err = __reiserfs_write_begin(page, page_offset, chunk + skip); err = __reiserfs_write_begin(page, page_offset, chunk + skip);
if (!err) { if (!err) {
if (buffer) if (buffer)
...@@ -546,6 +534,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, ...@@ -546,6 +534,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
page_offset + chunk + page_offset + chunk +
skip); skip);
} }
reiserfs_write_unlock(inode->i_sb);
unlock_page(page); unlock_page(page);
reiserfs_put_page(page); reiserfs_put_page(page);
buffer_pos += chunk; buffer_pos += chunk;
...@@ -563,10 +552,8 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, ...@@ -563,10 +552,8 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
.ia_valid = ATTR_SIZE | ATTR_CTIME, .ia_valid = ATTR_SIZE | ATTR_CTIME,
}; };
reiserfs_write_unlock(inode->i_sb);
mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
inode_dio_wait(dentry->d_inode); inode_dio_wait(dentry->d_inode);
reiserfs_write_lock(inode->i_sb);
err = reiserfs_setattr(dentry, &newattrs); err = reiserfs_setattr(dentry, &newattrs);
mutex_unlock(&dentry->d_inode->i_mutex); mutex_unlock(&dentry->d_inode->i_mutex);
...@@ -592,18 +579,19 @@ int reiserfs_xattr_set(struct inode *inode, const char *name, ...@@ -592,18 +579,19 @@ int reiserfs_xattr_set(struct inode *inode, const char *name,
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock(inode->i_sb);
error = journal_begin(&th, inode->i_sb, jbegin_count); error = journal_begin(&th, inode->i_sb, jbegin_count);
reiserfs_write_unlock(inode->i_sb);
if (error) { if (error) {
reiserfs_write_unlock(inode->i_sb);
return error; return error;
} }
error = reiserfs_xattr_set_handle(&th, inode, name, error = reiserfs_xattr_set_handle(&th, inode, name,
buffer, buffer_size, flags); buffer, buffer_size, flags);
reiserfs_write_lock(inode->i_sb);
error2 = journal_end(&th, inode->i_sb, jbegin_count); error2 = journal_end(&th, inode->i_sb, jbegin_count);
reiserfs_write_unlock(inode->i_sb);
if (error == 0) if (error == 0)
error = error2; error = error2;
reiserfs_write_unlock(inode->i_sb);
return error; return error;
} }
...@@ -968,7 +956,7 @@ int reiserfs_lookup_privroot(struct super_block *s) ...@@ -968,7 +956,7 @@ int reiserfs_lookup_privroot(struct super_block *s)
int err = 0; int err = 0;
/* If we don't have the privroot located yet - go find it */ /* 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, dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
strlen(PRIVROOT_NAME)); strlen(PRIVROOT_NAME));
if (!IS_ERR(dentry)) { if (!IS_ERR(dentry)) {
...@@ -996,14 +984,14 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) ...@@ -996,14 +984,14 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
goto error; goto error;
if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) { 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); err = create_privroot(REISERFS_SB(s)->priv_root);
mutex_unlock(&s->s_root->d_inode->i_mutex); mutex_unlock(&s->s_root->d_inode->i_mutex);
} }
if (privroot->d_inode) { if (privroot->d_inode) {
s->s_xattr = reiserfs_xattr_handlers; 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) { if (!REISERFS_SB(s)->xattr_root) {
struct dentry *dentry; struct dentry *dentry;
dentry = lookup_one_len(XAROOT_NAME, privroot, dentry = lookup_one_len(XAROOT_NAME, privroot,
......
...@@ -49,13 +49,15 @@ posix_acl_set(struct dentry *dentry, const char *name, const void *value, ...@@ -49,13 +49,15 @@ posix_acl_set(struct dentry *dentry, const char *name, const void *value,
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock(inode->i_sb);
error = journal_begin(&th, inode->i_sb, jcreate_blocks); error = journal_begin(&th, inode->i_sb, jcreate_blocks);
reiserfs_write_unlock(inode->i_sb);
if (error == 0) { if (error == 0) {
error = reiserfs_set_acl(&th, inode, type, acl); error = reiserfs_set_acl(&th, inode, type, acl);
reiserfs_write_lock(inode->i_sb);
error2 = journal_end(&th, inode->i_sb, jcreate_blocks); error2 = journal_end(&th, inode->i_sb, jcreate_blocks);
reiserfs_write_unlock(inode->i_sb);
if (error2) if (error2)
error = error2; error = error2;
} }
reiserfs_write_unlock(inode->i_sb);
release_and_out: release_and_out:
posix_acl_release(acl); posix_acl_release(acl);
...@@ -435,12 +437,14 @@ int reiserfs_cache_default_acl(struct inode *inode) ...@@ -435,12 +437,14 @@ int reiserfs_cache_default_acl(struct inode *inode)
return nblocks; return nblocks;
} }
/*
* Called under i_mutex
*/
int reiserfs_acl_chmod(struct inode *inode) int reiserfs_acl_chmod(struct inode *inode)
{ {
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
struct posix_acl *acl; struct posix_acl *acl;
size_t size; size_t size;
int depth;
int error; int error;
if (IS_PRIVATE(inode)) if (IS_PRIVATE(inode))
...@@ -454,9 +458,7 @@ int reiserfs_acl_chmod(struct inode *inode) ...@@ -454,9 +458,7 @@ int reiserfs_acl_chmod(struct inode *inode)
return 0; return 0;
} }
reiserfs_write_unlock(inode->i_sb);
acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
reiserfs_write_lock(inode->i_sb);
if (!acl) if (!acl)
return 0; return 0;
if (IS_ERR(acl)) if (IS_ERR(acl))
...@@ -466,16 +468,18 @@ int reiserfs_acl_chmod(struct inode *inode) ...@@ -466,16 +468,18 @@ int reiserfs_acl_chmod(struct inode *inode)
return error; return error;
size = reiserfs_xattr_nblocks(inode, reiserfs_acl_size(acl->a_count)); size = reiserfs_xattr_nblocks(inode, reiserfs_acl_size(acl->a_count));
depth = reiserfs_write_lock_once(inode->i_sb); reiserfs_write_lock(inode->i_sb);
error = journal_begin(&th, inode->i_sb, size * 2); error = journal_begin(&th, inode->i_sb, size * 2);
reiserfs_write_unlock(inode->i_sb);
if (!error) { if (!error) {
int error2; int error2;
error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, acl); error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, acl);
reiserfs_write_lock(inode->i_sb);
error2 = journal_end(&th, inode->i_sb, size * 2); error2 = journal_end(&th, inode->i_sb, size * 2);
reiserfs_write_unlock(inode->i_sb);
if (error2) if (error2)
error = error2; error = error2;
} }
reiserfs_write_unlock_once(inode->i_sb, depth);
posix_acl_release(acl); posix_acl_release(acl);
return error; return error;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment