diff options
Diffstat (limited to 'fs/ext4/xattr.c')
-rw-r--r-- | fs/ext4/xattr.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index dc969c357aa..e832e96095b 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -475,8 +475,14 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, struct buffer_head *bh) { struct mb_cache_entry *ce = NULL; + int error = 0; ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr); + error = ext4_journal_get_write_access(handle, bh); + if (error) + goto out; + + lock_buffer(bh); if (BHDR(bh)->h_refcount == cpu_to_le32(1)) { ea_bdebug(bh, "refcount now=0; freeing"); if (ce) @@ -485,21 +491,21 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, get_bh(bh); ext4_forget(handle, 1, inode, bh, bh->b_blocknr); } else { - if (ext4_journal_get_write_access(handle, bh) == 0) { - lock_buffer(bh); - BHDR(bh)->h_refcount = cpu_to_le32( + BHDR(bh)->h_refcount = cpu_to_le32( le32_to_cpu(BHDR(bh)->h_refcount) - 1); - ext4_journal_dirty_metadata(handle, bh); - if (IS_SYNC(inode)) - handle->h_sync = 1; - DQUOT_FREE_BLOCK(inode, 1); - unlock_buffer(bh); - ea_bdebug(bh, "refcount now=%d; releasing", - le32_to_cpu(BHDR(bh)->h_refcount)); - } + error = ext4_journal_dirty_metadata(handle, bh); + if (IS_SYNC(inode)) + handle->h_sync = 1; + DQUOT_FREE_BLOCK(inode, 1); + ea_bdebug(bh, "refcount now=%d; releasing", + le32_to_cpu(BHDR(bh)->h_refcount)); if (ce) mb_cache_entry_release(ce); } + unlock_buffer(bh); +out: + ext4_std_error(inode->i_sb, error); + return; } struct ext4_xattr_info { @@ -675,7 +681,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, struct buffer_head *new_bh = NULL; struct ext4_xattr_search *s = &bs->s; struct mb_cache_entry *ce = NULL; - int error; + int error = 0; #define header(x) ((struct ext4_xattr_header *)(x)) @@ -684,16 +690,17 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, if (s->base) { ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev, bs->bh->b_blocknr); + error = ext4_journal_get_write_access(handle, bs->bh); + if (error) + goto cleanup; + lock_buffer(bs->bh); + if (header(s->base)->h_refcount == cpu_to_le32(1)) { if (ce) { mb_cache_entry_free(ce); ce = NULL; } ea_bdebug(bs->bh, "modifying in-place"); - error = ext4_journal_get_write_access(handle, bs->bh); - if (error) - goto cleanup; - lock_buffer(bs->bh); error = ext4_xattr_set_entry(i, s); if (!error) { if (!IS_LAST_ENTRY(s->first)) @@ -713,6 +720,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, } else { int offset = (char *)s->here - bs->bh->b_data; + unlock_buffer(bs->bh); + jbd2_journal_release_buffer(handle, bs->bh); if (ce) { mb_cache_entry_release(ce); ce = NULL; |