Lines Matching +full:cache +full:- +full:block +full:- +full:size
1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
18 * block. If all extended attributes of an inode are identical, these
19 * inodes may share the same extended attribute block. Such situations
20 * are automatically detected by keeping a cache of recent attribute block
21 * numbers and hashes over the block's contents in memory.
24 * Extended attribute block layout:
26 * +------------------+
36 * +------------------+
38 * The block header is followed by multiple entry descriptors. These entry
39 * descriptors are variable in size, and aligned to EXT2_XATTR_PAD
43 * Attribute values are aligned to the end of the block, stored in
48 * ----------------
49 * EXT2_I(inode)->i_file_acl is protected by EXT2_I(inode)->xattr_sem.
51 * holding xattr_sem also means that nothing but the EA block's reference
52 * count will change. Multiple writers to an EA block are synchronized
69 #define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
77 inode->i_sb->s_id, inode->i_ino); \
82 printk(KERN_DEBUG "block %pg:%lu: ", \
83 bh->b_bdev, (unsigned long) bh->b_blocknr); \
122 #define EA_BLOCK_CACHE(inode) (EXT2_SB(inode->i_sb)->s_ea_block_cache)
141 if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || in ext2_xattr_header_valid()
142 header->h_blocks != cpu_to_le32(1)) in ext2_xattr_header_valid()
153 size_t size; in ext2_xattr_entry_valid() local
159 if (entry->e_value_block != 0) in ext2_xattr_entry_valid()
162 size = le32_to_cpu(entry->e_value_size); in ext2_xattr_entry_valid()
163 if (size > end_offs || in ext2_xattr_entry_valid()
164 le16_to_cpu(entry->e_value_offs) + size > end_offs) in ext2_xattr_entry_valid()
176 cmp = name_index - entry->e_name_index; in ext2_xattr_cmp_entry()
178 cmp = name_len - entry->e_name_len; in ext2_xattr_cmp_entry()
180 cmp = memcmp(name, entry->e_name, name_len); in ext2_xattr_cmp_entry()
189 * provided, or compute the buffer size required.
190 * Buffer is NULL to compute the size of the buffer required.
201 size_t name_len, size; in ext2_xattr_get() local
210 return -EINVAL; in ext2_xattr_get()
213 return -ERANGE; in ext2_xattr_get()
215 down_read(&EXT2_I(inode)->xattr_sem); in ext2_xattr_get()
216 error = -ENODATA; in ext2_xattr_get()
217 if (!EXT2_I(inode)->i_file_acl) in ext2_xattr_get()
219 ea_idebug(inode, "reading block %d", EXT2_I(inode)->i_file_acl); in ext2_xattr_get()
220 bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl); in ext2_xattr_get()
221 error = -EIO; in ext2_xattr_get()
225 atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); in ext2_xattr_get()
226 end = bh->b_data + bh->b_size; in ext2_xattr_get()
229 ext2_error(inode->i_sb, "ext2_xattr_get", in ext2_xattr_get()
230 "inode %ld: bad block %d", inode->i_ino, in ext2_xattr_get()
231 EXT2_I(inode)->i_file_acl); in ext2_xattr_get()
232 error = -EIO; in ext2_xattr_get()
240 inode->i_sb->s_blocksize)) in ext2_xattr_get()
253 ea_idebug(inode, "cache insert failed"); in ext2_xattr_get()
254 error = -ENODATA; in ext2_xattr_get()
257 size = le32_to_cpu(entry->e_value_size); in ext2_xattr_get()
259 ea_idebug(inode, "cache insert failed"); in ext2_xattr_get()
261 error = -ERANGE; in ext2_xattr_get()
262 if (size > buffer_size) in ext2_xattr_get()
265 memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs), in ext2_xattr_get()
266 size); in ext2_xattr_get()
268 error = size; in ext2_xattr_get()
272 up_read(&EXT2_I(inode)->xattr_sem); in ext2_xattr_get()
281 * provided, or compute the buffer size required.
282 * Buffer is NULL to compute the size of the buffer required.
301 down_read(&EXT2_I(inode)->xattr_sem); in ext2_xattr_list()
303 if (!EXT2_I(inode)->i_file_acl) in ext2_xattr_list()
305 ea_idebug(inode, "reading block %d", EXT2_I(inode)->i_file_acl); in ext2_xattr_list()
306 bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl); in ext2_xattr_list()
307 error = -EIO; in ext2_xattr_list()
311 atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); in ext2_xattr_list()
312 end = bh->b_data + bh->b_size; in ext2_xattr_list()
315 ext2_error(inode->i_sb, "ext2_xattr_list", in ext2_xattr_list()
316 "inode %ld: bad block %d", inode->i_ino, in ext2_xattr_list()
317 EXT2_I(inode)->i_file_acl); in ext2_xattr_list()
318 error = -EIO; in ext2_xattr_list()
322 /* check the on-disk data structure */ in ext2_xattr_list()
326 inode->i_sb->s_blocksize)) in ext2_xattr_list()
331 ea_idebug(inode, "cache insert failed"); in ext2_xattr_list()
338 prefix = ext2_xattr_prefix(entry->e_name_index, dentry); in ext2_xattr_list()
341 size_t size = prefix_len + entry->e_name_len + 1; in ext2_xattr_list() local
344 if (size > rest) { in ext2_xattr_list()
345 error = -ERANGE; in ext2_xattr_list()
350 memcpy(buffer, entry->e_name, entry->e_name_len); in ext2_xattr_list()
351 buffer += entry->e_name_len; in ext2_xattr_list()
354 rest -= size; in ext2_xattr_list()
357 error = buffer_size - rest; /* total size */ in ext2_xattr_list()
361 up_read(&EXT2_I(inode)->xattr_sem); in ext2_xattr_list()
369 * d_inode(dentry)->i_mutex: don't care
372 ext2_listxattr(struct dentry *dentry, char *buffer, size_t size) in ext2_listxattr() argument
374 return ext2_xattr_list(dentry, buffer, size); in ext2_listxattr()
386 spin_lock(&EXT2_SB(sb)->s_lock); in ext2_xattr_update_super_block()
389 spin_unlock(&EXT2_SB(sb)->s_lock); in ext2_xattr_update_super_block()
390 mark_buffer_dirty(EXT2_SB(sb)->s_sbh); in ext2_xattr_update_super_block()
397 * is NULL to remove an existing extended attribute, and non-NULL to
409 struct super_block *sb = inode->i_sb; in ext2_xattr_set()
413 size_t name_len, free, min_offs = sb->s_blocksize; in ext2_xattr_set()
418 * header -- Points either into bh, or to a temporarily in ext2_xattr_set()
420 * here -- The named entry found, or the place for inserting, within in ext2_xattr_set()
421 * the block pointed to by header. in ext2_xattr_set()
422 * last -- Points right after the last named entry within the block in ext2_xattr_set()
424 * min_offs -- The offset of the first value (values are aligned in ext2_xattr_set()
425 * towards the end of the block). in ext2_xattr_set()
426 * end -- Points right after the block pointed to by header. in ext2_xattr_set()
435 return -EINVAL; in ext2_xattr_set()
437 if (name_len > 255 || value_len > sb->s_blocksize) in ext2_xattr_set()
438 return -ERANGE; in ext2_xattr_set()
442 down_write(&EXT2_I(inode)->xattr_sem); in ext2_xattr_set()
443 if (EXT2_I(inode)->i_file_acl) { in ext2_xattr_set()
444 /* The inode already has an extended attribute block. */ in ext2_xattr_set()
445 bh = sb_bread(sb, EXT2_I(inode)->i_file_acl); in ext2_xattr_set()
446 error = -EIO; in ext2_xattr_set()
450 atomic_read(&(bh->b_count)), in ext2_xattr_set()
451 le32_to_cpu(HDR(bh)->h_refcount)); in ext2_xattr_set()
453 end = bh->b_data + bh->b_size; in ext2_xattr_set()
457 "inode %ld: bad block %d", inode->i_ino, in ext2_xattr_set()
458 EXT2_I(inode)->i_file_acl); in ext2_xattr_set()
459 error = -EIO; in ext2_xattr_set()
469 if (!ext2_xattr_entry_valid(last, end, sb->s_blocksize)) in ext2_xattr_set()
471 if (last->e_value_size) { in ext2_xattr_set()
472 size_t offs = le16_to_cpu(last->e_value_offs); in ext2_xattr_set()
489 free = min_offs - ((char*)last - (char*)header) - sizeof(__u32); in ext2_xattr_set()
491 /* We will use a new extended attribute block. */ in ext2_xattr_set()
492 free = sb->s_blocksize - in ext2_xattr_set()
493 sizeof(struct ext2_xattr_header) - sizeof(__u32); in ext2_xattr_set()
498 error = -ENODATA; in ext2_xattr_set()
506 error = -EEXIST; in ext2_xattr_set()
509 free += EXT2_XATTR_SIZE(le32_to_cpu(here->e_value_size)); in ext2_xattr_set()
512 error = -ENOSPC; in ext2_xattr_set()
522 if (header->h_refcount == cpu_to_le32(1)) { in ext2_xattr_set()
523 __u32 hash = le32_to_cpu(header->h_hash); in ext2_xattr_set()
527 hash, bh->b_blocknr); in ext2_xattr_set()
529 ea_bdebug(bh, "modifying in-place"); in ext2_xattr_set()
533 * Someone is trying to reuse the block, leave it alone in ext2_xattr_set()
539 header = kmemdup(HDR(bh), bh->b_size, GFP_KERNEL); in ext2_xattr_set()
540 error = -ENOMEM; in ext2_xattr_set()
543 header->h_refcount = cpu_to_le32(1); in ext2_xattr_set()
545 offset = (char *)here - bh->b_data; in ext2_xattr_set()
547 offset = (char *)last - bh->b_data; in ext2_xattr_set()
550 /* Allocate a buffer where we construct the new block. */ in ext2_xattr_set()
551 header = kzalloc(sb->s_blocksize, GFP_KERNEL); in ext2_xattr_set()
552 error = -ENOMEM; in ext2_xattr_set()
555 header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC); in ext2_xattr_set()
556 header->h_blocks = header->h_refcount = cpu_to_le32(1); in ext2_xattr_set()
561 /* Iff we are modifying the block in-place, bh is locked here. */ in ext2_xattr_set()
565 size_t size = EXT2_XATTR_LEN(name_len); in ext2_xattr_set() local
566 size_t rest = (char *)last - (char *)here; in ext2_xattr_set()
567 memmove((char *)here + size, here, rest); in ext2_xattr_set()
568 memset(here, 0, size); in ext2_xattr_set()
569 here->e_name_index = name_index; in ext2_xattr_set()
570 here->e_name_len = name_len; in ext2_xattr_set()
571 memcpy(here->e_name, name, name_len); in ext2_xattr_set()
573 if (here->e_value_size) { in ext2_xattr_set()
575 size_t offs = le16_to_cpu(here->e_value_offs); in ext2_xattr_set()
577 size_t size = EXT2_XATTR_SIZE( in ext2_xattr_set() local
578 le32_to_cpu(here->e_value_size)); in ext2_xattr_set()
580 if (size == EXT2_XATTR_SIZE(value_len)) { in ext2_xattr_set()
582 size. Just replace. */ in ext2_xattr_set()
583 here->e_value_size = cpu_to_le32(value_len); in ext2_xattr_set()
584 memset(val + size - EXT2_XATTR_PAD, 0, in ext2_xattr_set()
591 memmove(first_val + size, first_val, val - first_val); in ext2_xattr_set()
592 memset(first_val, 0, size); in ext2_xattr_set()
593 min_offs += size; in ext2_xattr_set()
598 size_t o = le16_to_cpu(last->e_value_offs); in ext2_xattr_set()
600 last->e_value_offs = in ext2_xattr_set()
601 cpu_to_le16(o + size); in ext2_xattr_set()
605 here->e_value_offs = 0; in ext2_xattr_set()
609 size_t size = EXT2_XATTR_LEN(name_len); in ext2_xattr_set() local
610 last = ENTRY((char *)last - size); in ext2_xattr_set()
611 memmove(here, (char*)here + size, in ext2_xattr_set()
612 (char*)last - (char*)here); in ext2_xattr_set()
613 memset(last, 0, size); in ext2_xattr_set()
619 here->e_value_size = cpu_to_le32(value_len); in ext2_xattr_set()
621 size_t size = EXT2_XATTR_SIZE(value_len); in ext2_xattr_set() local
622 char *val = (char *)header + min_offs - size; in ext2_xattr_set()
623 here->e_value_offs = in ext2_xattr_set()
624 cpu_to_le16((char *)val - (char *)header); in ext2_xattr_set()
625 memset(val + size - EXT2_XATTR_PAD, 0, in ext2_xattr_set()
633 /* This block is now empty. */ in ext2_xattr_set()
635 unlock_buffer(bh); /* we were modifying in-place. */ in ext2_xattr_set()
640 unlock_buffer(bh); /* we were modifying in-place. */ in ext2_xattr_set()
648 up_write(&EXT2_I(inode)->xattr_sem); in ext2_xattr_set()
660 if (HDR(bh)->h_refcount == cpu_to_le32(1)) { in ext2_xattr_release_block()
661 __u32 hash = le32_to_cpu(HDR(bh)->h_hash); in ext2_xattr_release_block()
666 * serialize with ext2_xattr_set() reusing the block. in ext2_xattr_release_block()
669 bh->b_blocknr); in ext2_xattr_release_block()
672 * Someone is trying to reuse the block. Wait in ext2_xattr_release_block()
681 /* Free the old block. */ in ext2_xattr_release_block()
683 ext2_free_blocks(inode, bh->b_blocknr, 1); in ext2_xattr_release_block()
691 le32_add_cpu(&HDR(bh)->h_refcount, -1); in ext2_xattr_release_block()
696 le32_to_cpu(HDR(bh)->h_refcount)); in ext2_xattr_release_block()
709 struct super_block *sb = inode->i_sb; in ext2_xattr_set2()
717 /* We found an identical block in the cache. */ in ext2_xattr_set2()
719 ea_bdebug(new_bh, "keeping this block"); in ext2_xattr_set2()
721 /* The old block is released after updating in ext2_xattr_set2()
723 ea_bdebug(new_bh, "reusing block"); in ext2_xattr_set2()
730 le32_add_cpu(&HDR(new_bh)->h_refcount, 1); in ext2_xattr_set2()
732 le32_to_cpu(HDR(new_bh)->h_refcount)); in ext2_xattr_set2()
736 /* Keep this block. No need to lock the block as we in ext2_xattr_set2()
742 /* We need to allocate a new block */ in ext2_xattr_set2()
744 EXT2_I(inode)->i_block_group); in ext2_xattr_set2()
746 ext2_fsblk_t block = ext2_new_blocks(inode, goal, in ext2_xattr_set2() local
751 ea_idebug(inode, "creating block %lu", block); in ext2_xattr_set2()
753 new_bh = sb_getblk(sb, block); in ext2_xattr_set2()
755 ext2_free_blocks(inode, block, 1); in ext2_xattr_set2()
757 error = -ENOMEM; in ext2_xattr_set2()
761 memcpy(new_bh->b_data, header, new_bh->b_size); in ext2_xattr_set2()
771 error = -EIO; in ext2_xattr_set2()
778 EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; in ext2_xattr_set2()
784 * as if nothing happened and cleanup the unused block */ in ext2_xattr_set2()
785 if (error && error != -ENOSPC) { in ext2_xattr_set2()
798 * If there was an old block and we are no longer using it, in ext2_xattr_set2()
799 * release the old block. in ext2_xattr_set2()
820 struct ext2_sb_info *sbi = EXT2_SB(inode->i_sb); in ext2_xattr_delete_inode()
826 * here to avoid false-positive warning from lockdep about reclaim in ext2_xattr_delete_inode()
829 if (WARN_ON_ONCE(!down_write_trylock(&EXT2_I(inode)->xattr_sem))) in ext2_xattr_delete_inode()
831 if (!EXT2_I(inode)->i_file_acl) in ext2_xattr_delete_inode()
834 if (!ext2_data_block_valid(sbi, EXT2_I(inode)->i_file_acl, 1)) { in ext2_xattr_delete_inode()
835 ext2_error(inode->i_sb, "ext2_xattr_delete_inode", in ext2_xattr_delete_inode()
836 "inode %ld: xattr block %d is out of data blocks range", in ext2_xattr_delete_inode()
837 inode->i_ino, EXT2_I(inode)->i_file_acl); in ext2_xattr_delete_inode()
841 bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl); in ext2_xattr_delete_inode()
843 ext2_error(inode->i_sb, "ext2_xattr_delete_inode", in ext2_xattr_delete_inode()
844 "inode %ld: block %d read error", inode->i_ino, in ext2_xattr_delete_inode()
845 EXT2_I(inode)->i_file_acl); in ext2_xattr_delete_inode()
848 ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count))); in ext2_xattr_delete_inode()
850 ext2_error(inode->i_sb, "ext2_xattr_delete_inode", in ext2_xattr_delete_inode()
851 "inode %ld: bad block %d", inode->i_ino, in ext2_xattr_delete_inode()
852 EXT2_I(inode)->i_file_acl); in ext2_xattr_delete_inode()
856 EXT2_I(inode)->i_file_acl = 0; in ext2_xattr_delete_inode()
860 up_write(&EXT2_I(inode)->xattr_sem); in ext2_xattr_delete_inode()
866 * Create a new entry in the extended attribute cache, and insert
867 * it unless such an entry is already in the cache.
872 ext2_xattr_cache_insert(struct mb_cache *cache, struct buffer_head *bh) in ext2_xattr_cache_insert() argument
874 __u32 hash = le32_to_cpu(HDR(bh)->h_hash); in ext2_xattr_cache_insert()
877 error = mb_cache_entry_create(cache, GFP_KERNEL, hash, bh->b_blocknr, in ext2_xattr_cache_insert()
880 if (error == -EBUSY) { in ext2_xattr_cache_insert()
881 ea_bdebug(bh, "already in cache"); in ext2_xattr_cache_insert()
908 if (entry1->e_hash != entry2->e_hash || in ext2_xattr_cmp()
909 entry1->e_name_index != entry2->e_name_index || in ext2_xattr_cmp()
910 entry1->e_name_len != entry2->e_name_len || in ext2_xattr_cmp()
911 entry1->e_value_size != entry2->e_value_size || in ext2_xattr_cmp()
912 memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) in ext2_xattr_cmp()
914 if (entry1->e_value_block != 0 || entry2->e_value_block != 0) in ext2_xattr_cmp()
915 return -EIO; in ext2_xattr_cmp()
916 if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), in ext2_xattr_cmp()
917 (char *)header2 + le16_to_cpu(entry2->e_value_offs), in ext2_xattr_cmp()
918 le32_to_cpu(entry1->e_value_size))) in ext2_xattr_cmp()
932 * Find an identical extended attribute block.
934 * Returns a locked buffer head to the block found, or NULL if such
935 * a block was not found or an error occurred.
940 __u32 hash = le32_to_cpu(header->h_hash); in ext2_xattr_cache_find()
944 if (!header->h_hash) in ext2_xattr_cache_find()
952 bh = sb_bread(inode->i_sb, ce->e_value); in ext2_xattr_cache_find()
954 ext2_error(inode->i_sb, "ext2_xattr_cache_find", in ext2_xattr_cache_find()
955 "inode %ld: block %ld read error", in ext2_xattr_cache_find()
956 inode->i_ino, (unsigned long) ce->e_value); in ext2_xattr_cache_find()
959 if (le32_to_cpu(HDR(bh)->h_refcount) > in ext2_xattr_cache_find()
961 ea_idebug(inode, "block %ld refcount %d>%d", in ext2_xattr_cache_find()
962 (unsigned long) ce->e_value, in ext2_xattr_cache_find()
963 le32_to_cpu(HDR(bh)->h_refcount), in ext2_xattr_cache_find()
967 atomic_read(&(bh->b_count))); in ext2_xattr_cache_find()
992 char *name = entry->e_name; in ext2_xattr_hash_entry()
995 for (n=0; n < entry->e_name_len; n++) { in ext2_xattr_hash_entry()
997 (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ in ext2_xattr_hash_entry()
1001 if (entry->e_value_block == 0 && entry->e_value_size != 0) { in ext2_xattr_hash_entry()
1003 le16_to_cpu(entry->e_value_offs)); in ext2_xattr_hash_entry()
1004 for (n = (le32_to_cpu(entry->e_value_size) + in ext2_xattr_hash_entry()
1005 EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) { in ext2_xattr_hash_entry()
1007 (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ in ext2_xattr_hash_entry()
1011 entry->e_hash = cpu_to_le32(hash); in ext2_xattr_hash_entry()
1022 * Re-compute the extended attribute hash value after an entry has changed.
1033 if (!here->e_hash) { in ext2_xattr_rehash()
1034 /* Block is not shared if an entry's hash value == 0 */ in ext2_xattr_rehash()
1039 (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^ in ext2_xattr_rehash()
1040 le32_to_cpu(here->e_hash); in ext2_xattr_rehash()
1043 header->h_hash = cpu_to_le32(hash); in ext2_xattr_rehash()
1055 void ext2_xattr_destroy_cache(struct mb_cache *cache) in ext2_xattr_destroy_cache() argument
1057 if (cache) in ext2_xattr_destroy_cache()
1058 mb_cache_destroy(cache); in ext2_xattr_destroy_cache()