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); \
126 #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()
337 ext2_xattr_handler(entry->e_name_index); in ext2_xattr_list()
339 if (handler && (!handler->list || handler->list(dentry))) { in ext2_xattr_list()
340 const char *prefix = handler->prefix ?: handler->name; in ext2_xattr_list()
342 size_t size = prefix_len + entry->e_name_len + 1; in ext2_xattr_list() local
345 if (size > rest) { in ext2_xattr_list()
346 error = -ERANGE; in ext2_xattr_list()
351 memcpy(buffer, entry->e_name, entry->e_name_len); in ext2_xattr_list()
352 buffer += entry->e_name_len; in ext2_xattr_list()
355 rest -= size; in ext2_xattr_list()
358 error = buffer_size - rest; /* total size */ in ext2_xattr_list()
362 up_read(&EXT2_I(inode)->xattr_sem); in ext2_xattr_list()
370 * d_inode(dentry)->i_mutex: don't care
373 ext2_listxattr(struct dentry *dentry, char *buffer, size_t size) in ext2_listxattr() argument
375 return ext2_xattr_list(dentry, buffer, size); in ext2_listxattr()
387 spin_lock(&EXT2_SB(sb)->s_lock); in ext2_xattr_update_super_block()
390 spin_unlock(&EXT2_SB(sb)->s_lock); in ext2_xattr_update_super_block()
391 mark_buffer_dirty(EXT2_SB(sb)->s_sbh); in ext2_xattr_update_super_block()
398 * is NULL to remove an existing extended attribute, and non-NULL to
410 struct super_block *sb = inode->i_sb; in ext2_xattr_set()
414 size_t name_len, free, min_offs = sb->s_blocksize; in ext2_xattr_set()
419 * header -- Points either into bh, or to a temporarily in ext2_xattr_set()
421 * here -- The named entry found, or the place for inserting, within in ext2_xattr_set()
422 * the block pointed to by header. in ext2_xattr_set()
423 * last -- Points right after the last named entry within the block in ext2_xattr_set()
425 * min_offs -- The offset of the first value (values are aligned in ext2_xattr_set()
426 * towards the end of the block). in ext2_xattr_set()
427 * end -- Points right after the block pointed to by header. in ext2_xattr_set()
436 return -EINVAL; in ext2_xattr_set()
438 if (name_len > 255 || value_len > sb->s_blocksize) in ext2_xattr_set()
439 return -ERANGE; in ext2_xattr_set()
443 down_write(&EXT2_I(inode)->xattr_sem); in ext2_xattr_set()
444 if (EXT2_I(inode)->i_file_acl) { in ext2_xattr_set()
445 /* The inode already has an extended attribute block. */ in ext2_xattr_set()
446 bh = sb_bread(sb, EXT2_I(inode)->i_file_acl); in ext2_xattr_set()
447 error = -EIO; in ext2_xattr_set()
451 atomic_read(&(bh->b_count)), in ext2_xattr_set()
452 le32_to_cpu(HDR(bh)->h_refcount)); in ext2_xattr_set()
454 end = bh->b_data + bh->b_size; in ext2_xattr_set()
458 "inode %ld: bad block %d", inode->i_ino, in ext2_xattr_set()
459 EXT2_I(inode)->i_file_acl); in ext2_xattr_set()
460 error = -EIO; in ext2_xattr_set()
470 if (!ext2_xattr_entry_valid(last, end, sb->s_blocksize)) in ext2_xattr_set()
472 if (last->e_value_size) { in ext2_xattr_set()
473 size_t offs = le16_to_cpu(last->e_value_offs); in ext2_xattr_set()
490 free = min_offs - ((char*)last - (char*)header) - sizeof(__u32); in ext2_xattr_set()
492 /* We will use a new extended attribute block. */ in ext2_xattr_set()
493 free = sb->s_blocksize - in ext2_xattr_set()
494 sizeof(struct ext2_xattr_header) - sizeof(__u32); in ext2_xattr_set()
499 error = -ENODATA; in ext2_xattr_set()
507 error = -EEXIST; in ext2_xattr_set()
510 free += EXT2_XATTR_SIZE(le32_to_cpu(here->e_value_size)); in ext2_xattr_set()
513 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()
525 ea_bdebug(bh, "modifying in-place"); in ext2_xattr_set()
528 * ext2_xattr_set2() to reliably detect modified block in ext2_xattr_set()
531 bh->b_blocknr); 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()
551 /* Allocate a buffer where we construct the new block. */ in ext2_xattr_set()
552 header = kzalloc(sb->s_blocksize, GFP_KERNEL); in ext2_xattr_set()
553 error = -ENOMEM; in ext2_xattr_set()
556 end = (char *)header + sb->s_blocksize; in ext2_xattr_set()
557 header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC); in ext2_xattr_set()
558 header->h_blocks = header->h_refcount = cpu_to_le32(1); in ext2_xattr_set()
562 /* Iff we are modifying the block in-place, bh is locked here. */ in ext2_xattr_set()
566 size_t size = EXT2_XATTR_LEN(name_len); in ext2_xattr_set() local
567 size_t rest = (char *)last - (char *)here; in ext2_xattr_set()
568 memmove((char *)here + size, here, rest); in ext2_xattr_set()
569 memset(here, 0, size); in ext2_xattr_set()
570 here->e_name_index = name_index; in ext2_xattr_set()
571 here->e_name_len = name_len; in ext2_xattr_set()
572 memcpy(here->e_name, name, name_len); in ext2_xattr_set()
574 if (here->e_value_size) { in ext2_xattr_set()
576 size_t offs = le16_to_cpu(here->e_value_offs); in ext2_xattr_set()
578 size_t size = EXT2_XATTR_SIZE( in ext2_xattr_set() local
579 le32_to_cpu(here->e_value_size)); in ext2_xattr_set()
581 if (size == EXT2_XATTR_SIZE(value_len)) { in ext2_xattr_set()
583 size. Just replace. */ in ext2_xattr_set()
584 here->e_value_size = cpu_to_le32(value_len); in ext2_xattr_set()
585 memset(val + size - EXT2_XATTR_PAD, 0, in ext2_xattr_set()
592 memmove(first_val + size, first_val, val - first_val); in ext2_xattr_set()
593 memset(first_val, 0, size); in ext2_xattr_set()
594 min_offs += size; in ext2_xattr_set()
599 size_t o = le16_to_cpu(last->e_value_offs); in ext2_xattr_set()
601 last->e_value_offs = in ext2_xattr_set()
602 cpu_to_le16(o + size); in ext2_xattr_set()
606 here->e_value_offs = 0; in ext2_xattr_set()
610 size_t size = EXT2_XATTR_LEN(name_len); in ext2_xattr_set() local
611 last = ENTRY((char *)last - size); in ext2_xattr_set()
612 memmove(here, (char*)here + size, in ext2_xattr_set()
613 (char*)last - (char*)here); in ext2_xattr_set()
614 memset(last, 0, size); in ext2_xattr_set()
620 here->e_value_size = cpu_to_le32(value_len); in ext2_xattr_set()
622 size_t size = EXT2_XATTR_SIZE(value_len); in ext2_xattr_set() local
623 char *val = (char *)header + min_offs - size; in ext2_xattr_set()
624 here->e_value_offs = in ext2_xattr_set()
625 cpu_to_le16((char *)val - (char *)header); in ext2_xattr_set()
626 memset(val + size - EXT2_XATTR_PAD, 0, in ext2_xattr_set()
634 /* This block is now empty. */ in ext2_xattr_set()
636 unlock_buffer(bh); /* we were modifying in-place. */ in ext2_xattr_set()
641 unlock_buffer(bh); /* we were modifying in-place. */ in ext2_xattr_set()
649 up_write(&EXT2_I(inode)->xattr_sem); in ext2_xattr_set()
661 struct super_block *sb = inode->i_sb; in ext2_xattr_set2()
669 /* We found an identical block in the cache. */ in ext2_xattr_set2()
671 ea_bdebug(new_bh, "keeping this block"); in ext2_xattr_set2()
673 /* The old block is released after updating in ext2_xattr_set2()
675 ea_bdebug(new_bh, "reusing block"); in ext2_xattr_set2()
682 le32_add_cpu(&HDR(new_bh)->h_refcount, 1); in ext2_xattr_set2()
684 le32_to_cpu(HDR(new_bh)->h_refcount)); in ext2_xattr_set2()
688 /* Keep this block. No need to lock the block as we in ext2_xattr_set2()
694 /* We need to allocate a new block */ in ext2_xattr_set2()
696 EXT2_I(inode)->i_block_group); in ext2_xattr_set2()
697 int block = ext2_new_block(inode, goal, &error); in ext2_xattr_set2() local
700 ea_idebug(inode, "creating block %d", block); in ext2_xattr_set2()
702 new_bh = sb_getblk(sb, block); in ext2_xattr_set2()
704 ext2_free_blocks(inode, block, 1); in ext2_xattr_set2()
706 error = -ENOMEM; in ext2_xattr_set2()
710 memcpy(new_bh->b_data, header, new_bh->b_size); in ext2_xattr_set2()
720 error = -EIO; in ext2_xattr_set2()
727 EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; in ext2_xattr_set2()
728 inode->i_ctime = current_time(inode); in ext2_xattr_set2()
733 * as if nothing happened and cleanup the unused block */ in ext2_xattr_set2()
734 if (error && error != -ENOSPC) { in ext2_xattr_set2()
747 * If there was an old block and we are no longer using it, in ext2_xattr_set2()
748 * release the old block. in ext2_xattr_set2()
751 if (HDR(old_bh)->h_refcount == cpu_to_le32(1)) { in ext2_xattr_set2()
752 __u32 hash = le32_to_cpu(HDR(old_bh)->h_hash); in ext2_xattr_set2()
756 * ext2_xattr_set2() to reliably detect freed block in ext2_xattr_set2()
759 old_bh->b_blocknr); in ext2_xattr_set2()
760 /* Free the old block. */ in ext2_xattr_set2()
762 ext2_free_blocks(inode, old_bh->b_blocknr, 1); in ext2_xattr_set2()
770 le32_add_cpu(&HDR(old_bh)->h_refcount, -1); in ext2_xattr_set2()
775 le32_to_cpu(HDR(old_bh)->h_refcount)); in ext2_xattr_set2()
796 struct ext2_sb_info *sbi = EXT2_SB(inode->i_sb); in ext2_xattr_delete_inode()
802 * here to avoid false-positive warning from lockdep about reclaim in ext2_xattr_delete_inode()
805 if (WARN_ON_ONCE(!down_write_trylock(&EXT2_I(inode)->xattr_sem))) in ext2_xattr_delete_inode()
807 if (!EXT2_I(inode)->i_file_acl) in ext2_xattr_delete_inode()
810 if (!ext2_data_block_valid(sbi, EXT2_I(inode)->i_file_acl, 1)) { in ext2_xattr_delete_inode()
811 ext2_error(inode->i_sb, "ext2_xattr_delete_inode", in ext2_xattr_delete_inode()
812 "inode %ld: xattr block %d is out of data blocks range", in ext2_xattr_delete_inode()
813 inode->i_ino, EXT2_I(inode)->i_file_acl); in ext2_xattr_delete_inode()
817 bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl); in ext2_xattr_delete_inode()
819 ext2_error(inode->i_sb, "ext2_xattr_delete_inode", in ext2_xattr_delete_inode()
820 "inode %ld: block %d read error", inode->i_ino, in ext2_xattr_delete_inode()
821 EXT2_I(inode)->i_file_acl); in ext2_xattr_delete_inode()
824 ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count))); in ext2_xattr_delete_inode()
826 ext2_error(inode->i_sb, "ext2_xattr_delete_inode", in ext2_xattr_delete_inode()
827 "inode %ld: bad block %d", inode->i_ino, in ext2_xattr_delete_inode()
828 EXT2_I(inode)->i_file_acl); in ext2_xattr_delete_inode()
832 if (HDR(bh)->h_refcount == cpu_to_le32(1)) { in ext2_xattr_delete_inode()
833 __u32 hash = le32_to_cpu(HDR(bh)->h_hash); in ext2_xattr_delete_inode()
837 * reliably detect freed block in ext2_xattr_delete_inode()
840 bh->b_blocknr); in ext2_xattr_delete_inode()
841 ext2_free_blocks(inode, EXT2_I(inode)->i_file_acl, 1); in ext2_xattr_delete_inode()
846 le32_add_cpu(&HDR(bh)->h_refcount, -1); in ext2_xattr_delete_inode()
848 le32_to_cpu(HDR(bh)->h_refcount)); in ext2_xattr_delete_inode()
855 EXT2_I(inode)->i_file_acl = 0; in ext2_xattr_delete_inode()
859 up_write(&EXT2_I(inode)->xattr_sem); in ext2_xattr_delete_inode()
865 * Create a new entry in the extended attribute cache, and insert
866 * it unless such an entry is already in the cache.
871 ext2_xattr_cache_insert(struct mb_cache *cache, struct buffer_head *bh) in ext2_xattr_cache_insert() argument
873 __u32 hash = le32_to_cpu(HDR(bh)->h_hash); in ext2_xattr_cache_insert()
876 error = mb_cache_entry_create(cache, GFP_NOFS, hash, bh->b_blocknr, in ext2_xattr_cache_insert()
879 if (error == -EBUSY) { in ext2_xattr_cache_insert()
880 ea_bdebug(bh, "already in cache"); in ext2_xattr_cache_insert()
907 if (entry1->e_hash != entry2->e_hash || in ext2_xattr_cmp()
908 entry1->e_name_index != entry2->e_name_index || in ext2_xattr_cmp()
909 entry1->e_name_len != entry2->e_name_len || in ext2_xattr_cmp()
910 entry1->e_value_size != entry2->e_value_size || in ext2_xattr_cmp()
911 memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) in ext2_xattr_cmp()
913 if (entry1->e_value_block != 0 || entry2->e_value_block != 0) in ext2_xattr_cmp()
914 return -EIO; in ext2_xattr_cmp()
915 if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), in ext2_xattr_cmp()
916 (char *)header2 + le16_to_cpu(entry2->e_value_offs), in ext2_xattr_cmp()
917 le32_to_cpu(entry1->e_value_size))) in ext2_xattr_cmp()
931 * Find an identical extended attribute block.
933 * Returns a locked buffer head to the block found, or NULL if such
934 * a block was not found or an error occurred.
939 __u32 hash = le32_to_cpu(header->h_hash); in ext2_xattr_cache_find()
943 if (!header->h_hash) in ext2_xattr_cache_find()
951 bh = sb_bread(inode->i_sb, ce->e_value); in ext2_xattr_cache_find()
953 ext2_error(inode->i_sb, "ext2_xattr_cache_find", in ext2_xattr_cache_find()
954 "inode %ld: block %ld read error", in ext2_xattr_cache_find()
955 inode->i_ino, (unsigned long) ce->e_value); in ext2_xattr_cache_find()
960 * rehashing of xattr block. Once we hold buffer lock in ext2_xattr_cache_find()
961 * xattr block's state is stable so we can check in ext2_xattr_cache_find()
962 * whether the block got freed / rehashed or not. in ext2_xattr_cache_find()
964 * freeing / rehashing xattr block, checking whether in ext2_xattr_cache_find()
967 if (hlist_bl_unhashed(&ce->e_hash_list)) { in ext2_xattr_cache_find()
972 } else if (le32_to_cpu(HDR(bh)->h_refcount) > in ext2_xattr_cache_find()
974 ea_idebug(inode, "block %ld refcount %d>%d", in ext2_xattr_cache_find()
975 (unsigned long) ce->e_value, in ext2_xattr_cache_find()
976 le32_to_cpu(HDR(bh)->h_refcount), in ext2_xattr_cache_find()
980 atomic_read(&(bh->b_count))); in ext2_xattr_cache_find()
1005 char *name = entry->e_name; in ext2_xattr_hash_entry()
1008 for (n=0; n < entry->e_name_len; n++) { in ext2_xattr_hash_entry()
1010 (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ in ext2_xattr_hash_entry()
1014 if (entry->e_value_block == 0 && entry->e_value_size != 0) { in ext2_xattr_hash_entry()
1016 le16_to_cpu(entry->e_value_offs)); in ext2_xattr_hash_entry()
1017 for (n = (le32_to_cpu(entry->e_value_size) + in ext2_xattr_hash_entry()
1018 EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) { in ext2_xattr_hash_entry()
1020 (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ in ext2_xattr_hash_entry()
1024 entry->e_hash = cpu_to_le32(hash); in ext2_xattr_hash_entry()
1035 * Re-compute the extended attribute hash value after an entry has changed.
1046 if (!here->e_hash) { in ext2_xattr_rehash()
1047 /* Block is not shared if an entry's hash value == 0 */ in ext2_xattr_rehash()
1052 (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^ in ext2_xattr_rehash()
1053 le32_to_cpu(here->e_hash); in ext2_xattr_rehash()
1056 header->h_hash = cpu_to_le32(hash); in ext2_xattr_rehash()
1068 void ext2_xattr_destroy_cache(struct mb_cache *cache) in ext2_xattr_destroy_cache() argument
1070 if (cache) in ext2_xattr_destroy_cache()
1071 mb_cache_destroy(cache); in ext2_xattr_destroy_cache()