diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-04-28 00:36:39 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-04-28 00:36:39 -0400 |
commit | d35cc56ddfc948d8df1aa6d41ac345fcec01854d (patch) | |
tree | 7e23a0e3dde639236e019aa88309d919941958e5 /fs/ext4/xattr.c | |
parent | 86d56134f1b67d0c18025ba5cade95c048ed528d (diff) | |
parent | d1db0eea852497762cab43b905b879dfcd3b8987 (diff) |
Merge 3.15-rc3 into staging-next
Diffstat (limited to 'fs/ext4/xattr.c')
-rw-r--r-- | fs/ext4/xattr.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 1f5cf5880718..4eec399ec807 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -520,8 +520,8 @@ static void ext4_xattr_update_super_block(handle_t *handle, | |||
520 | } | 520 | } |
521 | 521 | ||
522 | /* | 522 | /* |
523 | * Release the xattr block BH: If the reference count is > 1, decrement | 523 | * Release the xattr block BH: If the reference count is > 1, decrement it; |
524 | * it; otherwise free the block. | 524 | * otherwise free the block. |
525 | */ | 525 | */ |
526 | static void | 526 | static void |
527 | ext4_xattr_release_block(handle_t *handle, struct inode *inode, | 527 | ext4_xattr_release_block(handle_t *handle, struct inode *inode, |
@@ -542,16 +542,31 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, | |||
542 | if (ce) | 542 | if (ce) |
543 | mb_cache_entry_free(ce); | 543 | mb_cache_entry_free(ce); |
544 | get_bh(bh); | 544 | get_bh(bh); |
545 | unlock_buffer(bh); | ||
545 | ext4_free_blocks(handle, inode, bh, 0, 1, | 546 | ext4_free_blocks(handle, inode, bh, 0, 1, |
546 | EXT4_FREE_BLOCKS_METADATA | | 547 | EXT4_FREE_BLOCKS_METADATA | |
547 | EXT4_FREE_BLOCKS_FORGET); | 548 | EXT4_FREE_BLOCKS_FORGET); |
548 | unlock_buffer(bh); | ||
549 | } else { | 549 | } else { |
550 | le32_add_cpu(&BHDR(bh)->h_refcount, -1); | 550 | le32_add_cpu(&BHDR(bh)->h_refcount, -1); |
551 | if (ce) | 551 | if (ce) |
552 | mb_cache_entry_release(ce); | 552 | mb_cache_entry_release(ce); |
553 | /* | ||
554 | * Beware of this ugliness: Releasing of xattr block references | ||
555 | * from different inodes can race and so we have to protect | ||
556 | * from a race where someone else frees the block (and releases | ||
557 | * its journal_head) before we are done dirtying the buffer. In | ||
558 | * nojournal mode this race is harmless and we actually cannot | ||
559 | * call ext4_handle_dirty_xattr_block() with locked buffer as | ||
560 | * that function can call sync_dirty_buffer() so for that case | ||
561 | * we handle the dirtying after unlocking the buffer. | ||
562 | */ | ||
563 | if (ext4_handle_valid(handle)) | ||
564 | error = ext4_handle_dirty_xattr_block(handle, inode, | ||
565 | bh); | ||
553 | unlock_buffer(bh); | 566 | unlock_buffer(bh); |
554 | error = ext4_handle_dirty_xattr_block(handle, inode, bh); | 567 | if (!ext4_handle_valid(handle)) |
568 | error = ext4_handle_dirty_xattr_block(handle, inode, | ||
569 | bh); | ||
555 | if (IS_SYNC(inode)) | 570 | if (IS_SYNC(inode)) |
556 | ext4_handle_sync(handle); | 571 | ext4_handle_sync(handle); |
557 | dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1)); | 572 | dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1)); |