X-Git-Url: http://git.samba.org/samba.git/?p=sfrench%2Fcifs-2.6.git;a=blobdiff_plain;f=fs%2Fext3%2Fxattr.c;h=a6ea4d6a8bb2f61a9fee389c6b6f519ff68251a5;hp=99857a400f4be217dcf92e5f16ac6c62783b62e2;hb=c587f0c0a69227587baaa12e75815b6644457c0a;hpb=c4366889dda8110247be59ca41fddb82951a8c26 diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 99857a400f4b..a6ea4d6a8bb2 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -475,8 +475,15 @@ ext3_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(ext3_xattr_cache, bh->b_bdev, bh->b_blocknr); + error = ext3_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 +492,20 @@ ext3_xattr_release_block(handle_t *handle, struct inode *inode, get_bh(bh); ext3_forget(handle, 1, inode, bh, bh->b_blocknr); } else { - if (ext3_journal_get_write_access(handle, bh) == 0) { - lock_buffer(bh); - BHDR(bh)->h_refcount = cpu_to_le32( - le32_to_cpu(BHDR(bh)->h_refcount) - 1); - ext3_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)); - } + le32_add_cpu(&BHDR(bh)->h_refcount, -1); + error = ext3_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: + ext3_std_error(inode->i_sb, error); + return; } struct ext3_xattr_info { @@ -675,7 +681,7 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode, struct buffer_head *new_bh = NULL; struct ext3_xattr_search *s = &bs->s; struct mb_cache_entry *ce = NULL; - int error; + int error = 0; #define header(x) ((struct ext3_xattr_header *)(x)) @@ -684,16 +690,17 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode, if (s->base) { ce = mb_cache_entry_get(ext3_xattr_cache, bs->bh->b_bdev, bs->bh->b_blocknr); + error = ext3_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 = ext3_journal_get_write_access(handle, bs->bh); - if (error) - goto cleanup; - lock_buffer(bs->bh); error = ext3_xattr_set_entry(i, s); if (!error) { if (!IS_LAST_ENTRY(s->first)) @@ -713,12 +720,15 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode, } else { int offset = (char *)s->here - bs->bh->b_data; + unlock_buffer(bs->bh); + journal_release_buffer(handle, bs->bh); + if (ce) { mb_cache_entry_release(ce); ce = NULL; } ea_bdebug(bs->bh, "cloning"); - s->base = kmalloc(bs->bh->b_size, GFP_KERNEL); + s->base = kmalloc(bs->bh->b_size, GFP_NOFS); error = -ENOMEM; if (s->base == NULL) goto cleanup; @@ -730,12 +740,11 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode, } } else { /* Allocate a buffer where we construct the new block. */ - s->base = kmalloc(sb->s_blocksize, GFP_KERNEL); + s->base = kzalloc(sb->s_blocksize, GFP_NOFS); /* assert(header == s->base) */ error = -ENOMEM; if (s->base == NULL) goto cleanup; - memset(s->base, 0, sb->s_blocksize); header(s->base)->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC); header(s->base)->h_blocks = cpu_to_le32(1); header(s->base)->h_refcount = cpu_to_le32(1); @@ -770,8 +779,7 @@ inserted: if (error) goto cleanup_dquot; lock_buffer(new_bh); - BHDR(new_bh)->h_refcount = cpu_to_le32(1 + - le32_to_cpu(BHDR(new_bh)->h_refcount)); + le32_add_cpu(&BHDR(new_bh)->h_refcount, 1); ea_bdebug(new_bh, "reusing; refcount now=%d", le32_to_cpu(BHDR(new_bh)->h_refcount)); unlock_buffer(new_bh);