diff options
Diffstat (limited to 'fs/ext4/xattr.c')
-rw-r--r-- | fs/ext4/xattr.c | 59 |
1 files changed, 32 insertions, 27 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index e175e94116ac..1f5cf5880718 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -81,7 +81,7 @@ | |||
81 | # define ea_bdebug(bh, fmt, ...) no_printk(fmt, ##__VA_ARGS__) | 81 | # define ea_bdebug(bh, fmt, ...) no_printk(fmt, ##__VA_ARGS__) |
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | static void ext4_xattr_cache_insert(struct buffer_head *); | 84 | static void ext4_xattr_cache_insert(struct mb_cache *, struct buffer_head *); |
85 | static struct buffer_head *ext4_xattr_cache_find(struct inode *, | 85 | static struct buffer_head *ext4_xattr_cache_find(struct inode *, |
86 | struct ext4_xattr_header *, | 86 | struct ext4_xattr_header *, |
87 | struct mb_cache_entry **); | 87 | struct mb_cache_entry **); |
@@ -90,8 +90,6 @@ static void ext4_xattr_rehash(struct ext4_xattr_header *, | |||
90 | static int ext4_xattr_list(struct dentry *dentry, char *buffer, | 90 | static int ext4_xattr_list(struct dentry *dentry, char *buffer, |
91 | size_t buffer_size); | 91 | size_t buffer_size); |
92 | 92 | ||
93 | static struct mb_cache *ext4_xattr_cache; | ||
94 | |||
95 | static const struct xattr_handler *ext4_xattr_handler_map[] = { | 93 | static const struct xattr_handler *ext4_xattr_handler_map[] = { |
96 | [EXT4_XATTR_INDEX_USER] = &ext4_xattr_user_handler, | 94 | [EXT4_XATTR_INDEX_USER] = &ext4_xattr_user_handler, |
97 | #ifdef CONFIG_EXT4_FS_POSIX_ACL | 95 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
@@ -117,6 +115,9 @@ const struct xattr_handler *ext4_xattr_handlers[] = { | |||
117 | NULL | 115 | NULL |
118 | }; | 116 | }; |
119 | 117 | ||
118 | #define EXT4_GET_MB_CACHE(inode) (((struct ext4_sb_info *) \ | ||
119 | inode->i_sb->s_fs_info)->s_mb_cache) | ||
120 | |||
120 | static __le32 ext4_xattr_block_csum(struct inode *inode, | 121 | static __le32 ext4_xattr_block_csum(struct inode *inode, |
121 | sector_t block_nr, | 122 | sector_t block_nr, |
122 | struct ext4_xattr_header *hdr) | 123 | struct ext4_xattr_header *hdr) |
@@ -265,6 +266,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name, | |||
265 | struct ext4_xattr_entry *entry; | 266 | struct ext4_xattr_entry *entry; |
266 | size_t size; | 267 | size_t size; |
267 | int error; | 268 | int error; |
269 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
268 | 270 | ||
269 | ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", | 271 | ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", |
270 | name_index, name, buffer, (long)buffer_size); | 272 | name_index, name, buffer, (long)buffer_size); |
@@ -286,7 +288,7 @@ bad_block: | |||
286 | error = -EIO; | 288 | error = -EIO; |
287 | goto cleanup; | 289 | goto cleanup; |
288 | } | 290 | } |
289 | ext4_xattr_cache_insert(bh); | 291 | ext4_xattr_cache_insert(ext4_mb_cache, bh); |
290 | entry = BFIRST(bh); | 292 | entry = BFIRST(bh); |
291 | error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1); | 293 | error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1); |
292 | if (error == -EIO) | 294 | if (error == -EIO) |
@@ -409,6 +411,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
409 | struct inode *inode = dentry->d_inode; | 411 | struct inode *inode = dentry->d_inode; |
410 | struct buffer_head *bh = NULL; | 412 | struct buffer_head *bh = NULL; |
411 | int error; | 413 | int error; |
414 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
412 | 415 | ||
413 | ea_idebug(inode, "buffer=%p, buffer_size=%ld", | 416 | ea_idebug(inode, "buffer=%p, buffer_size=%ld", |
414 | buffer, (long)buffer_size); | 417 | buffer, (long)buffer_size); |
@@ -430,7 +433,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
430 | error = -EIO; | 433 | error = -EIO; |
431 | goto cleanup; | 434 | goto cleanup; |
432 | } | 435 | } |
433 | ext4_xattr_cache_insert(bh); | 436 | ext4_xattr_cache_insert(ext4_mb_cache, bh); |
434 | error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size); | 437 | error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size); |
435 | 438 | ||
436 | cleanup: | 439 | cleanup: |
@@ -526,8 +529,9 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, | |||
526 | { | 529 | { |
527 | struct mb_cache_entry *ce = NULL; | 530 | struct mb_cache_entry *ce = NULL; |
528 | int error = 0; | 531 | int error = 0; |
532 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
529 | 533 | ||
530 | ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr); | 534 | ce = mb_cache_entry_get(ext4_mb_cache, bh->b_bdev, bh->b_blocknr); |
531 | error = ext4_journal_get_write_access(handle, bh); | 535 | error = ext4_journal_get_write_access(handle, bh); |
532 | if (error) | 536 | if (error) |
533 | goto out; | 537 | goto out; |
@@ -567,12 +571,13 @@ static size_t ext4_xattr_free_space(struct ext4_xattr_entry *last, | |||
567 | size_t *min_offs, void *base, int *total) | 571 | size_t *min_offs, void *base, int *total) |
568 | { | 572 | { |
569 | for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { | 573 | for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { |
570 | *total += EXT4_XATTR_LEN(last->e_name_len); | ||
571 | if (!last->e_value_block && last->e_value_size) { | 574 | if (!last->e_value_block && last->e_value_size) { |
572 | size_t offs = le16_to_cpu(last->e_value_offs); | 575 | size_t offs = le16_to_cpu(last->e_value_offs); |
573 | if (offs < *min_offs) | 576 | if (offs < *min_offs) |
574 | *min_offs = offs; | 577 | *min_offs = offs; |
575 | } | 578 | } |
579 | if (total) | ||
580 | *total += EXT4_XATTR_LEN(last->e_name_len); | ||
576 | } | 581 | } |
577 | return (*min_offs - ((void *)last - base) - sizeof(__u32)); | 582 | return (*min_offs - ((void *)last - base) - sizeof(__u32)); |
578 | } | 583 | } |
@@ -745,13 +750,14 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, | |||
745 | struct ext4_xattr_search *s = &bs->s; | 750 | struct ext4_xattr_search *s = &bs->s; |
746 | struct mb_cache_entry *ce = NULL; | 751 | struct mb_cache_entry *ce = NULL; |
747 | int error = 0; | 752 | int error = 0; |
753 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
748 | 754 | ||
749 | #define header(x) ((struct ext4_xattr_header *)(x)) | 755 | #define header(x) ((struct ext4_xattr_header *)(x)) |
750 | 756 | ||
751 | if (i->value && i->value_len > sb->s_blocksize) | 757 | if (i->value && i->value_len > sb->s_blocksize) |
752 | return -ENOSPC; | 758 | return -ENOSPC; |
753 | if (s->base) { | 759 | if (s->base) { |
754 | ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev, | 760 | ce = mb_cache_entry_get(ext4_mb_cache, bs->bh->b_bdev, |
755 | bs->bh->b_blocknr); | 761 | bs->bh->b_blocknr); |
756 | error = ext4_journal_get_write_access(handle, bs->bh); | 762 | error = ext4_journal_get_write_access(handle, bs->bh); |
757 | if (error) | 763 | if (error) |
@@ -769,7 +775,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, | |||
769 | if (!IS_LAST_ENTRY(s->first)) | 775 | if (!IS_LAST_ENTRY(s->first)) |
770 | ext4_xattr_rehash(header(s->base), | 776 | ext4_xattr_rehash(header(s->base), |
771 | s->here); | 777 | s->here); |
772 | ext4_xattr_cache_insert(bs->bh); | 778 | ext4_xattr_cache_insert(ext4_mb_cache, |
779 | bs->bh); | ||
773 | } | 780 | } |
774 | unlock_buffer(bs->bh); | 781 | unlock_buffer(bs->bh); |
775 | if (error == -EIO) | 782 | if (error == -EIO) |
@@ -905,7 +912,7 @@ getblk_failed: | |||
905 | memcpy(new_bh->b_data, s->base, new_bh->b_size); | 912 | memcpy(new_bh->b_data, s->base, new_bh->b_size); |
906 | set_buffer_uptodate(new_bh); | 913 | set_buffer_uptodate(new_bh); |
907 | unlock_buffer(new_bh); | 914 | unlock_buffer(new_bh); |
908 | ext4_xattr_cache_insert(new_bh); | 915 | ext4_xattr_cache_insert(ext4_mb_cache, new_bh); |
909 | error = ext4_handle_dirty_xattr_block(handle, | 916 | error = ext4_handle_dirty_xattr_block(handle, |
910 | inode, new_bh); | 917 | inode, new_bh); |
911 | if (error) | 918 | if (error) |
@@ -1228,7 +1235,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, | |||
1228 | struct ext4_xattr_block_find *bs = NULL; | 1235 | struct ext4_xattr_block_find *bs = NULL; |
1229 | char *buffer = NULL, *b_entry_name = NULL; | 1236 | char *buffer = NULL, *b_entry_name = NULL; |
1230 | size_t min_offs, free; | 1237 | size_t min_offs, free; |
1231 | int total_ino, total_blk; | 1238 | int total_ino; |
1232 | void *base, *start, *end; | 1239 | void *base, *start, *end; |
1233 | int extra_isize = 0, error = 0, tried_min_extra_isize = 0; | 1240 | int extra_isize = 0, error = 0, tried_min_extra_isize = 0; |
1234 | int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize); | 1241 | int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize); |
@@ -1286,8 +1293,7 @@ retry: | |||
1286 | first = BFIRST(bh); | 1293 | first = BFIRST(bh); |
1287 | end = bh->b_data + bh->b_size; | 1294 | end = bh->b_data + bh->b_size; |
1288 | min_offs = end - base; | 1295 | min_offs = end - base; |
1289 | free = ext4_xattr_free_space(first, &min_offs, base, | 1296 | free = ext4_xattr_free_space(first, &min_offs, base, NULL); |
1290 | &total_blk); | ||
1291 | if (free < new_extra_isize) { | 1297 | if (free < new_extra_isize) { |
1292 | if (!tried_min_extra_isize && s_min_extra_isize) { | 1298 | if (!tried_min_extra_isize && s_min_extra_isize) { |
1293 | tried_min_extra_isize++; | 1299 | tried_min_extra_isize++; |
@@ -1495,13 +1501,13 @@ ext4_xattr_put_super(struct super_block *sb) | |||
1495 | * Returns 0, or a negative error number on failure. | 1501 | * Returns 0, or a negative error number on failure. |
1496 | */ | 1502 | */ |
1497 | static void | 1503 | static void |
1498 | ext4_xattr_cache_insert(struct buffer_head *bh) | 1504 | ext4_xattr_cache_insert(struct mb_cache *ext4_mb_cache, struct buffer_head *bh) |
1499 | { | 1505 | { |
1500 | __u32 hash = le32_to_cpu(BHDR(bh)->h_hash); | 1506 | __u32 hash = le32_to_cpu(BHDR(bh)->h_hash); |
1501 | struct mb_cache_entry *ce; | 1507 | struct mb_cache_entry *ce; |
1502 | int error; | 1508 | int error; |
1503 | 1509 | ||
1504 | ce = mb_cache_entry_alloc(ext4_xattr_cache, GFP_NOFS); | 1510 | ce = mb_cache_entry_alloc(ext4_mb_cache, GFP_NOFS); |
1505 | if (!ce) { | 1511 | if (!ce) { |
1506 | ea_bdebug(bh, "out of memory"); | 1512 | ea_bdebug(bh, "out of memory"); |
1507 | return; | 1513 | return; |
@@ -1573,12 +1579,13 @@ ext4_xattr_cache_find(struct inode *inode, struct ext4_xattr_header *header, | |||
1573 | { | 1579 | { |
1574 | __u32 hash = le32_to_cpu(header->h_hash); | 1580 | __u32 hash = le32_to_cpu(header->h_hash); |
1575 | struct mb_cache_entry *ce; | 1581 | struct mb_cache_entry *ce; |
1582 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
1576 | 1583 | ||
1577 | if (!header->h_hash) | 1584 | if (!header->h_hash) |
1578 | return NULL; /* never share */ | 1585 | return NULL; /* never share */ |
1579 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); | 1586 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); |
1580 | again: | 1587 | again: |
1581 | ce = mb_cache_entry_find_first(ext4_xattr_cache, inode->i_sb->s_bdev, | 1588 | ce = mb_cache_entry_find_first(ext4_mb_cache, inode->i_sb->s_bdev, |
1582 | hash); | 1589 | hash); |
1583 | while (ce) { | 1590 | while (ce) { |
1584 | struct buffer_head *bh; | 1591 | struct buffer_head *bh; |
@@ -1676,19 +1683,17 @@ static void ext4_xattr_rehash(struct ext4_xattr_header *header, | |||
1676 | 1683 | ||
1677 | #undef BLOCK_HASH_SHIFT | 1684 | #undef BLOCK_HASH_SHIFT |
1678 | 1685 | ||
1679 | int __init | 1686 | #define HASH_BUCKET_BITS 10 |
1680 | ext4_init_xattr(void) | 1687 | |
1688 | struct mb_cache * | ||
1689 | ext4_xattr_create_cache(char *name) | ||
1681 | { | 1690 | { |
1682 | ext4_xattr_cache = mb_cache_create("ext4_xattr", 6); | 1691 | return mb_cache_create(name, HASH_BUCKET_BITS); |
1683 | if (!ext4_xattr_cache) | ||
1684 | return -ENOMEM; | ||
1685 | return 0; | ||
1686 | } | 1692 | } |
1687 | 1693 | ||
1688 | void | 1694 | void ext4_xattr_destroy_cache(struct mb_cache *cache) |
1689 | ext4_exit_xattr(void) | ||
1690 | { | 1695 | { |
1691 | if (ext4_xattr_cache) | 1696 | if (cache) |
1692 | mb_cache_destroy(ext4_xattr_cache); | 1697 | mb_cache_destroy(cache); |
1693 | ext4_xattr_cache = NULL; | ||
1694 | } | 1698 | } |
1699 | |||