A large number of ext4 bug fixes and cleanups for v4.13
-----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEK2m5VNv+CHkogTfJ8vlZVpUNgaMFAlmHbBAACgkQ8vlZVpUN gaMu3gf+LpI5bI1XA3R8KbXB2snnz6wM7OzArfqvreX+m+xP1CK6nVpAIgpkZqfw QkQ1xPJk7Q25vex/pPcsgLO0Vxf0i4vpydK+fYnf30S4WvGQVq6OHZWFFv2zM2YB 7TWxjG+KryM7j6JSXdUiSTKP3nX84TW/IMIWuZMR1nuOa8N5M4yD3uc+3EBTjSbq P/dxfmkp2hQKnlZVBWqCjJDhtxwUYTF4iZ/pbSVeGbgHCh1674ml+airb4K9ltNU 0vR0JChD12YJaafjaAyIrqqKwDGvnN+H5wyhCodEV9w8jthbcU04Jfmi1auB9UxT y7/sgbV64W2o5hBwxY3RXjZkVLpDsw== =Mtr7 -----END PGP SIGNATURE----- Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4 Pull ext4 fixes from Ted Ts'o: "A large number of ext4 bug fixes and cleanups for v4.13" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: fix copy paste error in ext4_swap_extents() ext4: fix overflow caused by missing cast in ext4_resize_fs() ext4, project: expand inode extra size if possible ext4: cleanup ext4_expand_extra_isize_ea() ext4: restructure ext4_expand_extra_isize ext4: fix forgetten xattr lock protection in ext4_expand_extra_isize ext4: make xattr inode reads faster ext4: inplace xattr block update fails to deduplicate blocks ext4: remove unused mode parameter ext4: fix warning about stack corruption ext4: fix dir_nlink behaviour ext4: silence array overflow warning ext4: fix SEEK_HOLE/SEEK_DATA for blocksize < pagesize ext4: release discard bio after sending discard commands ext4: convert swap_inode_data() over to use swap() on most of the fields ext4: error should be cleared if ea_inode isn't added to the cache ext4: Don't clear SGID when inheriting ACLs ext4: preserve i_mode if __ext4_set_acl() fails ext4: remove unused metadata accounting variables ext4: correct comment references to ext4_ext_direct_IO()
This commit is contained in:
Коммит
ed66da1104
|
@ -193,13 +193,6 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type,
|
|||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
|
||||
if (acl) {
|
||||
error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
|
||||
if (error)
|
||||
return error;
|
||||
inode->i_ctime = current_time(inode);
|
||||
ext4_mark_inode_dirty(handle, inode);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACL_TYPE_DEFAULT:
|
||||
|
@ -221,8 +214,9 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type,
|
|||
value, size, xattr_flags);
|
||||
|
||||
kfree(value);
|
||||
if (!error)
|
||||
if (!error) {
|
||||
set_cached_acl(inode, type, acl);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -233,6 +227,8 @@ ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type)
|
|||
handle_t *handle;
|
||||
int error, credits, retries = 0;
|
||||
size_t acl_size = acl ? ext4_acl_size(acl->a_count) : 0;
|
||||
umode_t mode = inode->i_mode;
|
||||
int update_mode = 0;
|
||||
|
||||
error = dquot_initialize(inode);
|
||||
if (error)
|
||||
|
@ -247,7 +243,20 @@ retry:
|
|||
if (IS_ERR(handle))
|
||||
return PTR_ERR(handle);
|
||||
|
||||
if ((type == ACL_TYPE_ACCESS) && acl) {
|
||||
error = posix_acl_update_mode(inode, &mode, &acl);
|
||||
if (error)
|
||||
goto out_stop;
|
||||
update_mode = 1;
|
||||
}
|
||||
|
||||
error = __ext4_set_acl(handle, inode, type, acl, 0 /* xattr_flags */);
|
||||
if (!error && update_mode) {
|
||||
inode->i_mode = mode;
|
||||
inode->i_ctime = current_time(inode);
|
||||
ext4_mark_inode_dirty(handle, inode);
|
||||
}
|
||||
out_stop:
|
||||
ext4_journal_stop(handle);
|
||||
if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
|
||||
goto retry;
|
||||
|
|
|
@ -961,7 +961,7 @@ struct ext4_inode_info {
|
|||
/*
|
||||
* i_block_group is the number of the block group which contains
|
||||
* this file's inode. Constant across the lifetime of the inode,
|
||||
* it is ued for making block allocation decisions - we try to
|
||||
* it is used for making block allocation decisions - we try to
|
||||
* place a file's data blocks near its inode block, and new inodes
|
||||
* near to their parent directory's inode.
|
||||
*/
|
||||
|
@ -1049,10 +1049,8 @@ struct ext4_inode_info {
|
|||
ext4_group_t i_last_alloc_group;
|
||||
|
||||
/* allocation reservation info for delalloc */
|
||||
/* In case of bigalloc, these refer to clusters rather than blocks */
|
||||
/* In case of bigalloc, this refer to clusters rather than blocks */
|
||||
unsigned int i_reserved_data_blocks;
|
||||
unsigned int i_reserved_meta_blocks;
|
||||
unsigned int i_allocated_meta_blocks;
|
||||
ext4_lblk_t i_da_metadata_calc_last_lblock;
|
||||
int i_da_metadata_calc_len;
|
||||
|
||||
|
@ -2022,7 +2020,8 @@ static inline __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize)
|
|||
|
||||
#define is_dx(dir) (ext4_has_feature_dir_index((dir)->i_sb) && \
|
||||
ext4_test_inode_flag((dir), EXT4_INODE_INDEX))
|
||||
#define EXT4_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT4_LINK_MAX)
|
||||
#define EXT4_DIR_LINK_MAX(dir) unlikely((dir)->i_nlink >= EXT4_LINK_MAX && \
|
||||
!(ext4_has_feature_dir_nlink((dir)->i_sb) && is_dx(dir)))
|
||||
#define EXT4_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
|
||||
|
||||
/* Legal values for the dx_root hash_version field: */
|
||||
|
@ -2462,6 +2461,8 @@ extern void ext4_process_freed_data(struct super_block *sb, tid_t commit_tid);
|
|||
int ext4_inode_is_fast_symlink(struct inode *inode);
|
||||
struct buffer_head *ext4_getblk(handle_t *, struct inode *, ext4_lblk_t, int);
|
||||
struct buffer_head *ext4_bread(handle_t *, struct inode *, ext4_lblk_t, int);
|
||||
int ext4_bread_batch(struct inode *inode, ext4_lblk_t block, int bh_count,
|
||||
bool wait, struct buffer_head **bhs);
|
||||
int ext4_get_block_unwritten(struct inode *inode, sector_t iblock,
|
||||
struct buffer_head *bh_result, int create);
|
||||
int ext4_get_block(struct inode *inode, sector_t iblock,
|
||||
|
@ -3074,7 +3075,7 @@ extern int ext4_handle_dirty_dirent_node(handle_t *handle,
|
|||
struct inode *inode,
|
||||
struct buffer_head *bh);
|
||||
#define S_SHIFT 12
|
||||
static const unsigned char ext4_type_by_mode[S_IFMT >> S_SHIFT] = {
|
||||
static const unsigned char ext4_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
|
||||
[S_IFREG >> S_SHIFT] = EXT4_FT_REG_FILE,
|
||||
[S_IFDIR >> S_SHIFT] = EXT4_FT_DIR,
|
||||
[S_IFCHR >> S_SHIFT] = EXT4_FT_CHRDEV,
|
||||
|
|
|
@ -227,6 +227,9 @@ int ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
|
|||
|
||||
int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode);
|
||||
|
||||
int ext4_expand_extra_isize(struct inode *inode,
|
||||
unsigned int new_extra_isize,
|
||||
struct ext4_iloc *iloc);
|
||||
/*
|
||||
* Wrapper functions with which ext4 calls into JBD.
|
||||
*/
|
||||
|
|
|
@ -4652,7 +4652,7 @@ retry:
|
|||
|
||||
static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
|
||||
ext4_lblk_t len, loff_t new_size,
|
||||
int flags, int mode)
|
||||
int flags)
|
||||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
handle_t *handle;
|
||||
|
@ -4815,7 +4815,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
|
|||
round_down(offset, 1 << blkbits) >> blkbits,
|
||||
(round_up((offset + len), 1 << blkbits) -
|
||||
round_down(offset, 1 << blkbits)) >> blkbits,
|
||||
new_size, flags, mode);
|
||||
new_size, flags);
|
||||
if (ret)
|
||||
goto out_dio;
|
||||
|
||||
|
@ -4841,7 +4841,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
|
|||
inode->i_mtime = inode->i_ctime = current_time(inode);
|
||||
|
||||
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
|
||||
flags, mode);
|
||||
flags);
|
||||
up_write(&EXT4_I(inode)->i_mmap_sem);
|
||||
if (ret)
|
||||
goto out_dio;
|
||||
|
@ -4976,8 +4976,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
|
|||
ext4_inode_block_unlocked_dio(inode);
|
||||
inode_dio_wait(inode);
|
||||
|
||||
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
|
||||
flags, mode);
|
||||
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, flags);
|
||||
ext4_inode_resume_unlocked_dio(inode);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
@ -5837,7 +5836,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
|
|||
if (e1_blk > lblk1)
|
||||
next1 = e1_blk;
|
||||
if (e2_blk > lblk2)
|
||||
next2 = e1_blk;
|
||||
next2 = e2_blk;
|
||||
/* Do we have something to swap */
|
||||
if (next1 == EXT_MAX_BLOCKS || next2 == EXT_MAX_BLOCKS)
|
||||
goto finish;
|
||||
|
|
|
@ -537,6 +537,8 @@ static int ext4_find_unwritten_pgoff(struct inode *inode,
|
|||
lastoff = page_offset(page);
|
||||
bh = head = page_buffers(page);
|
||||
do {
|
||||
if (lastoff + bh->b_size <= startoff)
|
||||
goto next;
|
||||
if (buffer_uptodate(bh) ||
|
||||
buffer_unwritten(bh)) {
|
||||
if (whence == SEEK_DATA)
|
||||
|
@ -551,6 +553,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode,
|
|||
unlock_page(page);
|
||||
goto out;
|
||||
}
|
||||
next:
|
||||
lastoff += bh->b_size;
|
||||
bh = bh->b_this_page;
|
||||
} while (bh != head);
|
||||
|
|
198
fs/ext4/inode.c
198
fs/ext4/inode.c
|
@ -892,7 +892,7 @@ static int ext4_dio_get_block_unwritten_async(struct inode *inode,
|
|||
/*
|
||||
* Get block function for non-AIO DIO writes when we create unwritten extent if
|
||||
* blocks are not allocated yet. The extent will be converted to written
|
||||
* after IO is complete from ext4_ext_direct_IO() function.
|
||||
* after IO is complete by ext4_direct_IO_write().
|
||||
*/
|
||||
static int ext4_dio_get_block_unwritten_sync(struct inode *inode,
|
||||
sector_t iblock, struct buffer_head *bh_result, int create)
|
||||
|
@ -907,7 +907,7 @@ static int ext4_dio_get_block_unwritten_sync(struct inode *inode,
|
|||
|
||||
/*
|
||||
* Mark inode as having pending DIO writes to unwritten extents.
|
||||
* ext4_ext_direct_IO() checks this flag and converts extents to
|
||||
* ext4_direct_IO_write() checks this flag and converts extents to
|
||||
* written.
|
||||
*/
|
||||
if (!ret && buffer_unwritten(bh_result))
|
||||
|
@ -1015,6 +1015,50 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
|
|||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
/* Read a contiguous batch of blocks. */
|
||||
int ext4_bread_batch(struct inode *inode, ext4_lblk_t block, int bh_count,
|
||||
bool wait, struct buffer_head **bhs)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < bh_count; i++) {
|
||||
bhs[i] = ext4_getblk(NULL, inode, block + i, 0 /* map_flags */);
|
||||
if (IS_ERR(bhs[i])) {
|
||||
err = PTR_ERR(bhs[i]);
|
||||
bh_count = i;
|
||||
goto out_brelse;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < bh_count; i++)
|
||||
/* Note that NULL bhs[i] is valid because of holes. */
|
||||
if (bhs[i] && !buffer_uptodate(bhs[i]))
|
||||
ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1,
|
||||
&bhs[i]);
|
||||
|
||||
if (!wait)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < bh_count; i++)
|
||||
if (bhs[i])
|
||||
wait_on_buffer(bhs[i]);
|
||||
|
||||
for (i = 0; i < bh_count; i++) {
|
||||
if (bhs[i] && !buffer_uptodate(bhs[i])) {
|
||||
err = -EIO;
|
||||
goto out_brelse;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
out_brelse:
|
||||
for (i = 0; i < bh_count; i++) {
|
||||
brelse(bhs[i]);
|
||||
bhs[i] = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int ext4_walk_page_buffers(handle_t *handle,
|
||||
struct buffer_head *head,
|
||||
unsigned from,
|
||||
|
@ -5658,22 +5702,16 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
|
|||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand an inode by new_extra_isize bytes.
|
||||
* Returns 0 on success or negative error number on failure.
|
||||
*/
|
||||
static int ext4_expand_extra_isize(struct inode *inode,
|
||||
unsigned int new_extra_isize,
|
||||
struct ext4_iloc iloc,
|
||||
handle_t *handle)
|
||||
static int __ext4_expand_extra_isize(struct inode *inode,
|
||||
unsigned int new_extra_isize,
|
||||
struct ext4_iloc *iloc,
|
||||
handle_t *handle, int *no_expand)
|
||||
{
|
||||
struct ext4_inode *raw_inode;
|
||||
struct ext4_xattr_ibody_header *header;
|
||||
int error;
|
||||
|
||||
if (EXT4_I(inode)->i_extra_isize >= new_extra_isize)
|
||||
return 0;
|
||||
|
||||
raw_inode = ext4_raw_inode(&iloc);
|
||||
raw_inode = ext4_raw_inode(iloc);
|
||||
|
||||
header = IHDR(inode, raw_inode);
|
||||
|
||||
|
@ -5688,8 +5726,98 @@ static int ext4_expand_extra_isize(struct inode *inode,
|
|||
}
|
||||
|
||||
/* try to expand with EAs present */
|
||||
return ext4_expand_extra_isize_ea(inode, new_extra_isize,
|
||||
raw_inode, handle);
|
||||
error = ext4_expand_extra_isize_ea(inode, new_extra_isize,
|
||||
raw_inode, handle);
|
||||
if (error) {
|
||||
/*
|
||||
* Inode size expansion failed; don't try again
|
||||
*/
|
||||
*no_expand = 1;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand an inode by new_extra_isize bytes.
|
||||
* Returns 0 on success or negative error number on failure.
|
||||
*/
|
||||
static int ext4_try_to_expand_extra_isize(struct inode *inode,
|
||||
unsigned int new_extra_isize,
|
||||
struct ext4_iloc iloc,
|
||||
handle_t *handle)
|
||||
{
|
||||
int no_expand;
|
||||
int error;
|
||||
|
||||
if (ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND))
|
||||
return -EOVERFLOW;
|
||||
|
||||
/*
|
||||
* In nojournal mode, we can immediately attempt to expand
|
||||
* the inode. When journaled, we first need to obtain extra
|
||||
* buffer credits since we may write into the EA block
|
||||
* with this same handle. If journal_extend fails, then it will
|
||||
* only result in a minor loss of functionality for that inode.
|
||||
* If this is felt to be critical, then e2fsck should be run to
|
||||
* force a large enough s_min_extra_isize.
|
||||
*/
|
||||
if (ext4_handle_valid(handle) &&
|
||||
jbd2_journal_extend(handle,
|
||||
EXT4_DATA_TRANS_BLOCKS(inode->i_sb)) != 0)
|
||||
return -ENOSPC;
|
||||
|
||||
if (ext4_write_trylock_xattr(inode, &no_expand) == 0)
|
||||
return -EBUSY;
|
||||
|
||||
error = __ext4_expand_extra_isize(inode, new_extra_isize, &iloc,
|
||||
handle, &no_expand);
|
||||
ext4_write_unlock_xattr(inode, &no_expand);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ext4_expand_extra_isize(struct inode *inode,
|
||||
unsigned int new_extra_isize,
|
||||
struct ext4_iloc *iloc)
|
||||
{
|
||||
handle_t *handle;
|
||||
int no_expand;
|
||||
int error, rc;
|
||||
|
||||
if (ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND)) {
|
||||
brelse(iloc->bh);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
handle = ext4_journal_start(inode, EXT4_HT_INODE,
|
||||
EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
|
||||
if (IS_ERR(handle)) {
|
||||
error = PTR_ERR(handle);
|
||||
brelse(iloc->bh);
|
||||
return error;
|
||||
}
|
||||
|
||||
ext4_write_lock_xattr(inode, &no_expand);
|
||||
|
||||
BUFFER_TRACE(iloc.bh, "get_write_access");
|
||||
error = ext4_journal_get_write_access(handle, iloc->bh);
|
||||
if (error) {
|
||||
brelse(iloc->bh);
|
||||
goto out_stop;
|
||||
}
|
||||
|
||||
error = __ext4_expand_extra_isize(inode, new_extra_isize, iloc,
|
||||
handle, &no_expand);
|
||||
|
||||
rc = ext4_mark_iloc_dirty(handle, inode, iloc);
|
||||
if (!error)
|
||||
error = rc;
|
||||
|
||||
ext4_write_unlock_xattr(inode, &no_expand);
|
||||
out_stop:
|
||||
ext4_journal_stop(handle);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5709,44 +5837,18 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
|
|||
{
|
||||
struct ext4_iloc iloc;
|
||||
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
||||
static unsigned int mnt_count;
|
||||
int err, ret;
|
||||
int err;
|
||||
|
||||
might_sleep();
|
||||
trace_ext4_mark_inode_dirty(inode, _RET_IP_);
|
||||
err = ext4_reserve_inode_write(handle, inode, &iloc);
|
||||
if (err)
|
||||
return err;
|
||||
if (EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize &&
|
||||
!ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND)) {
|
||||
/*
|
||||
* In nojournal mode, we can immediately attempt to expand
|
||||
* the inode. When journaled, we first need to obtain extra
|
||||
* buffer credits since we may write into the EA block
|
||||
* with this same handle. If journal_extend fails, then it will
|
||||
* only result in a minor loss of functionality for that inode.
|
||||
* If this is felt to be critical, then e2fsck should be run to
|
||||
* force a large enough s_min_extra_isize.
|
||||
*/
|
||||
if (!ext4_handle_valid(handle) ||
|
||||
jbd2_journal_extend(handle,
|
||||
EXT4_DATA_TRANS_BLOCKS(inode->i_sb)) == 0) {
|
||||
ret = ext4_expand_extra_isize(inode,
|
||||
sbi->s_want_extra_isize,
|
||||
iloc, handle);
|
||||
if (ret) {
|
||||
if (mnt_count !=
|
||||
le16_to_cpu(sbi->s_es->s_mnt_count)) {
|
||||
ext4_warning(inode->i_sb,
|
||||
"Unable to expand inode %lu. Delete"
|
||||
" some EAs or run e2fsck.",
|
||||
inode->i_ino);
|
||||
mnt_count =
|
||||
le16_to_cpu(sbi->s_es->s_mnt_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize)
|
||||
ext4_try_to_expand_extra_isize(inode, sbi->s_want_extra_isize,
|
||||
iloc, handle);
|
||||
|
||||
return ext4_mark_iloc_dirty(handle, inode, &iloc);
|
||||
}
|
||||
|
||||
|
|
|
@ -64,18 +64,16 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2)
|
|||
ei1 = EXT4_I(inode1);
|
||||
ei2 = EXT4_I(inode2);
|
||||
|
||||
memswap(&inode1->i_flags, &inode2->i_flags, sizeof(inode1->i_flags));
|
||||
memswap(&inode1->i_version, &inode2->i_version,
|
||||
sizeof(inode1->i_version));
|
||||
memswap(&inode1->i_blocks, &inode2->i_blocks,
|
||||
sizeof(inode1->i_blocks));
|
||||
memswap(&inode1->i_bytes, &inode2->i_bytes, sizeof(inode1->i_bytes));
|
||||
memswap(&inode1->i_atime, &inode2->i_atime, sizeof(inode1->i_atime));
|
||||
memswap(&inode1->i_mtime, &inode2->i_mtime, sizeof(inode1->i_mtime));
|
||||
swap(inode1->i_flags, inode2->i_flags);
|
||||
swap(inode1->i_version, inode2->i_version);
|
||||
swap(inode1->i_blocks, inode2->i_blocks);
|
||||
swap(inode1->i_bytes, inode2->i_bytes);
|
||||
swap(inode1->i_atime, inode2->i_atime);
|
||||
swap(inode1->i_mtime, inode2->i_mtime);
|
||||
|
||||
memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data));
|
||||
memswap(&ei1->i_flags, &ei2->i_flags, sizeof(ei1->i_flags));
|
||||
memswap(&ei1->i_disksize, &ei2->i_disksize, sizeof(ei1->i_disksize));
|
||||
swap(ei1->i_flags, ei2->i_flags);
|
||||
swap(ei1->i_disksize, ei2->i_disksize);
|
||||
ext4_es_remove_extent(inode1, 0, EXT_MAX_BLOCKS);
|
||||
ext4_es_remove_extent(inode2, 0, EXT_MAX_BLOCKS);
|
||||
|
||||
|
@ -351,11 +349,14 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
|
|||
|
||||
raw_inode = ext4_raw_inode(&iloc);
|
||||
if (!EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) {
|
||||
err = -EOVERFLOW;
|
||||
err = ext4_expand_extra_isize(inode,
|
||||
EXT4_SB(sb)->s_want_extra_isize,
|
||||
&iloc);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
} else {
|
||||
brelse(iloc.bh);
|
||||
goto out_unlock;
|
||||
}
|
||||
brelse(iloc.bh);
|
||||
|
||||
dquot_initialize(inode);
|
||||
|
||||
|
|
|
@ -2295,9 +2295,12 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
|
|||
int err, buddy_loaded = 0;
|
||||
struct ext4_buddy e4b;
|
||||
struct ext4_group_info *grinfo;
|
||||
unsigned char blocksize_bits = min_t(unsigned char,
|
||||
sb->s_blocksize_bits,
|
||||
EXT4_MAX_BLOCK_LOG_SIZE);
|
||||
struct sg {
|
||||
struct ext4_group_info info;
|
||||
ext4_grpblk_t counters[EXT4_MAX_BLOCK_LOG_SIZE + 2];
|
||||
ext4_grpblk_t counters[blocksize_bits + 2];
|
||||
} sg;
|
||||
|
||||
group--;
|
||||
|
@ -2306,8 +2309,6 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
|
|||
" 2^0 2^1 2^2 2^3 2^4 2^5 2^6 "
|
||||
" 2^7 2^8 2^9 2^10 2^11 2^12 2^13 ]\n");
|
||||
|
||||
i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
|
||||
sizeof(struct ext4_group_info);
|
||||
grinfo = ext4_get_group_info(sb, group);
|
||||
/* Load the group info in memory only if not already loaded. */
|
||||
if (unlikely(EXT4_MB_GRP_NEED_INIT(grinfo))) {
|
||||
|
@ -2319,7 +2320,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
|
|||
buddy_loaded = 1;
|
||||
}
|
||||
|
||||
memcpy(&sg, ext4_get_group_info(sb, group), i);
|
||||
memcpy(&sg, ext4_get_group_info(sb, group), sizeof(sg));
|
||||
|
||||
if (buddy_loaded)
|
||||
ext4_mb_unload_buddy(&e4b);
|
||||
|
@ -2327,7 +2328,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
|
|||
seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg.info.bb_free,
|
||||
sg.info.bb_fragments, sg.info.bb_first_free);
|
||||
for (i = 0; i <= 13; i++)
|
||||
seq_printf(seq, " %-5u", i <= sb->s_blocksize_bits + 1 ?
|
||||
seq_printf(seq, " %-5u", i <= blocksize_bits + 1 ?
|
||||
sg.info.bb_counters[i] : 0);
|
||||
seq_printf(seq, " ]\n");
|
||||
|
||||
|
@ -2892,8 +2893,10 @@ void ext4_process_freed_data(struct super_block *sb, tid_t commit_tid)
|
|||
break;
|
||||
}
|
||||
|
||||
if (discard_bio)
|
||||
if (discard_bio) {
|
||||
submit_bio_wait(discard_bio);
|
||||
bio_put(discard_bio);
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(entry, tmp, &freed_data_list, efd_list)
|
||||
|
|
|
@ -1342,13 +1342,12 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
|
|||
struct super_block *sb;
|
||||
struct buffer_head *bh_use[NAMEI_RA_SIZE];
|
||||
struct buffer_head *bh, *ret = NULL;
|
||||
ext4_lblk_t start, block, b;
|
||||
ext4_lblk_t start, block;
|
||||
const u8 *name = d_name->name;
|
||||
int ra_max = 0; /* Number of bh's in the readahead
|
||||
size_t ra_max = 0; /* Number of bh's in the readahead
|
||||
buffer, bh_use[] */
|
||||
int ra_ptr = 0; /* Current index into readahead
|
||||
size_t ra_ptr = 0; /* Current index into readahead
|
||||
buffer */
|
||||
int num = 0;
|
||||
ext4_lblk_t nblocks;
|
||||
int i, namelen, retval;
|
||||
struct ext4_filename fname;
|
||||
|
@ -1411,31 +1410,17 @@ restart:
|
|||
if (ra_ptr >= ra_max) {
|
||||
/* Refill the readahead buffer */
|
||||
ra_ptr = 0;
|
||||
b = block;
|
||||
for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
|
||||
/*
|
||||
* Terminate if we reach the end of the
|
||||
* directory and must wrap, or if our
|
||||
* search has finished at this block.
|
||||
*/
|
||||
if (b >= nblocks || (num && block == start)) {
|
||||
bh_use[ra_max] = NULL;
|
||||
break;
|
||||
}
|
||||
num++;
|
||||
bh = ext4_getblk(NULL, dir, b++, 0);
|
||||
if (IS_ERR(bh)) {
|
||||
if (ra_max == 0) {
|
||||
ret = bh;
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
break;
|
||||
}
|
||||
bh_use[ra_max] = bh;
|
||||
if (bh)
|
||||
ll_rw_block(REQ_OP_READ,
|
||||
REQ_META | REQ_PRIO,
|
||||
1, &bh);
|
||||
if (block < start)
|
||||
ra_max = start - block;
|
||||
else
|
||||
ra_max = nblocks - block;
|
||||
ra_max = min(ra_max, ARRAY_SIZE(bh_use));
|
||||
retval = ext4_bread_batch(dir, block, ra_max,
|
||||
false /* wait */, bh_use);
|
||||
if (retval) {
|
||||
ret = ERR_PTR(retval);
|
||||
ra_max = 0;
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
}
|
||||
if ((bh = bh_use[ra_ptr++]) == NULL)
|
||||
|
@ -2395,19 +2380,22 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* DIR_NLINK feature is set if 1) nlinks > EXT4_LINK_MAX or 2) nlinks == 2,
|
||||
* since this indicates that nlinks count was previously 1.
|
||||
* Set directory link count to 1 if nlinks > EXT4_LINK_MAX, or if nlinks == 2
|
||||
* since this indicates that nlinks count was previously 1 to avoid overflowing
|
||||
* the 16-bit i_links_count field on disk. Directories with i_nlink == 1 mean
|
||||
* that subdirectory link counts are not being maintained accurately.
|
||||
*
|
||||
* The caller has already checked for i_nlink overflow in case the DIR_LINK
|
||||
* feature is not enabled and returned -EMLINK. The is_dx() check is a proxy
|
||||
* for checking S_ISDIR(inode) (since the INODE_INDEX feature will not be set
|
||||
* on regular files) and to avoid creating huge/slow non-HTREE directories.
|
||||
*/
|
||||
static void ext4_inc_count(handle_t *handle, struct inode *inode)
|
||||
{
|
||||
inc_nlink(inode);
|
||||
if (is_dx(inode) && inode->i_nlink > 1) {
|
||||
/* limit is 16-bit i_links_count */
|
||||
if (inode->i_nlink >= EXT4_LINK_MAX || inode->i_nlink == 2) {
|
||||
set_nlink(inode, 1);
|
||||
ext4_set_feature_dir_nlink(inode->i_sb);
|
||||
}
|
||||
}
|
||||
if (is_dx(inode) &&
|
||||
(inode->i_nlink > EXT4_LINK_MAX || inode->i_nlink == 2))
|
||||
set_nlink(inode, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1927,7 +1927,8 @@ retry:
|
|||
n_desc_blocks = o_desc_blocks +
|
||||
le16_to_cpu(es->s_reserved_gdt_blocks);
|
||||
n_group = n_desc_blocks * EXT4_DESC_PER_BLOCK(sb);
|
||||
n_blocks_count = n_group * EXT4_BLOCKS_PER_GROUP(sb);
|
||||
n_blocks_count = (ext4_fsblk_t)n_group *
|
||||
EXT4_BLOCKS_PER_GROUP(sb);
|
||||
n_group--; /* set to last group number */
|
||||
}
|
||||
|
||||
|
|
|
@ -978,8 +978,6 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
|
|||
ei->i_es_shk_nr = 0;
|
||||
ei->i_es_shrink_lblk = 0;
|
||||
ei->i_reserved_data_blocks = 0;
|
||||
ei->i_reserved_meta_blocks = 0;
|
||||
ei->i_allocated_meta_blocks = 0;
|
||||
ei->i_da_metadata_calc_len = 0;
|
||||
ei->i_da_metadata_calc_last_lblock = 0;
|
||||
spin_lock_init(&(ei->i_block_reservation_lock));
|
||||
|
|
|
@ -317,28 +317,41 @@ static void ext4_xattr_inode_set_hash(struct inode *ea_inode, u32 hash)
|
|||
*/
|
||||
static int ext4_xattr_inode_read(struct inode *ea_inode, void *buf, size_t size)
|
||||
{
|
||||
unsigned long block = 0;
|
||||
struct buffer_head *bh;
|
||||
int blocksize = ea_inode->i_sb->s_blocksize;
|
||||
size_t csize, copied = 0;
|
||||
void *copy_pos = buf;
|
||||
int blocksize = 1 << ea_inode->i_blkbits;
|
||||
int bh_count = (size + blocksize - 1) >> ea_inode->i_blkbits;
|
||||
int tail_size = (size % blocksize) ?: blocksize;
|
||||
struct buffer_head *bhs_inline[8];
|
||||
struct buffer_head **bhs = bhs_inline;
|
||||
int i, ret;
|
||||
|
||||
while (copied < size) {
|
||||
csize = (size - copied) > blocksize ? blocksize : size - copied;
|
||||
bh = ext4_bread(NULL, ea_inode, block, 0);
|
||||
if (IS_ERR(bh))
|
||||
return PTR_ERR(bh);
|
||||
if (!bh)
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
memcpy(copy_pos, bh->b_data, csize);
|
||||
brelse(bh);
|
||||
|
||||
copy_pos += csize;
|
||||
block += 1;
|
||||
copied += csize;
|
||||
if (bh_count > ARRAY_SIZE(bhs_inline)) {
|
||||
bhs = kmalloc_array(bh_count, sizeof(*bhs), GFP_NOFS);
|
||||
if (!bhs)
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
|
||||
ret = ext4_bread_batch(ea_inode, 0 /* block */, bh_count,
|
||||
true /* wait */, bhs);
|
||||
if (ret)
|
||||
goto free_bhs;
|
||||
|
||||
for (i = 0; i < bh_count; i++) {
|
||||
/* There shouldn't be any holes in ea_inode. */
|
||||
if (!bhs[i]) {
|
||||
ret = -EFSCORRUPTED;
|
||||
goto put_bhs;
|
||||
}
|
||||
memcpy((char *)buf + blocksize * i, bhs[i]->b_data,
|
||||
i < bh_count - 1 ? blocksize : tail_size);
|
||||
}
|
||||
ret = 0;
|
||||
put_bhs:
|
||||
for (i = 0; i < bh_count; i++)
|
||||
brelse(bhs[i]);
|
||||
free_bhs:
|
||||
if (bhs != bhs_inline)
|
||||
kfree(bhs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
|
||||
|
@ -451,6 +464,7 @@ ext4_xattr_inode_get(struct inode *inode, struct ext4_xattr_entry *entry,
|
|||
}
|
||||
/* Do not add ea_inode to the cache. */
|
||||
ea_inode_cache = NULL;
|
||||
err = 0;
|
||||
} else if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -1815,9 +1829,6 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
|
|||
ea_bdebug(bs->bh, "modifying in-place");
|
||||
error = ext4_xattr_set_entry(i, s, handle, inode,
|
||||
true /* is_block */);
|
||||
if (!error)
|
||||
ext4_xattr_block_cache_insert(ea_block_cache,
|
||||
bs->bh);
|
||||
ext4_xattr_block_csum_set(inode, bs->bh);
|
||||
unlock_buffer(bs->bh);
|
||||
if (error == -EFSCORRUPTED)
|
||||
|
@ -1973,6 +1984,7 @@ inserted:
|
|||
} else if (bs->bh && s->base == bs->bh->b_data) {
|
||||
/* We were modifying this block in-place. */
|
||||
ea_bdebug(bs->bh, "keeping this block");
|
||||
ext4_xattr_block_cache_insert(ea_block_cache, bs->bh);
|
||||
new_bh = bs->bh;
|
||||
get_bh(new_bh);
|
||||
} else {
|
||||
|
@ -2625,23 +2637,21 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
|
|||
struct ext4_inode *raw_inode, handle_t *handle)
|
||||
{
|
||||
struct ext4_xattr_ibody_header *header;
|
||||
struct buffer_head *bh = NULL;
|
||||
struct buffer_head *bh;
|
||||
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
||||
static unsigned int mnt_count;
|
||||
size_t min_offs;
|
||||
size_t ifree, bfree;
|
||||
int total_ino;
|
||||
void *base, *end;
|
||||
int error = 0, tried_min_extra_isize = 0;
|
||||
int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize);
|
||||
int s_min_extra_isize = le16_to_cpu(sbi->s_es->s_min_extra_isize);
|
||||
int isize_diff; /* How much do we need to grow i_extra_isize */
|
||||
int no_expand;
|
||||
|
||||
if (ext4_write_trylock_xattr(inode, &no_expand) == 0)
|
||||
return 0;
|
||||
|
||||
retry:
|
||||
isize_diff = new_extra_isize - EXT4_I(inode)->i_extra_isize;
|
||||
if (EXT4_I(inode)->i_extra_isize >= new_extra_isize)
|
||||
goto out;
|
||||
return 0;
|
||||
|
||||
header = IHDR(inode, raw_inode);
|
||||
|
||||
|
@ -2676,6 +2686,7 @@ retry:
|
|||
EXT4_ERROR_INODE(inode, "bad block %llu",
|
||||
EXT4_I(inode)->i_file_acl);
|
||||
error = -EFSCORRUPTED;
|
||||
brelse(bh);
|
||||
goto cleanup;
|
||||
}
|
||||
base = BHDR(bh);
|
||||
|
@ -2683,11 +2694,11 @@ retry:
|
|||
min_offs = end - base;
|
||||
bfree = ext4_xattr_free_space(BFIRST(bh), &min_offs, base,
|
||||
NULL);
|
||||
brelse(bh);
|
||||
if (bfree + ifree < isize_diff) {
|
||||
if (!tried_min_extra_isize && s_min_extra_isize) {
|
||||
tried_min_extra_isize++;
|
||||
new_extra_isize = s_min_extra_isize;
|
||||
brelse(bh);
|
||||
goto retry;
|
||||
}
|
||||
error = -ENOSPC;
|
||||
|
@ -2705,7 +2716,6 @@ retry:
|
|||
s_min_extra_isize) {
|
||||
tried_min_extra_isize++;
|
||||
new_extra_isize = s_min_extra_isize;
|
||||
brelse(bh);
|
||||
goto retry;
|
||||
}
|
||||
goto cleanup;
|
||||
|
@ -2717,18 +2727,13 @@ shift:
|
|||
EXT4_GOOD_OLD_INODE_SIZE + new_extra_isize,
|
||||
(void *)header, total_ino);
|
||||
EXT4_I(inode)->i_extra_isize = new_extra_isize;
|
||||
brelse(bh);
|
||||
out:
|
||||
ext4_write_unlock_xattr(inode, &no_expand);
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
brelse(bh);
|
||||
/*
|
||||
* Inode size expansion failed; don't try again
|
||||
*/
|
||||
no_expand = 1;
|
||||
ext4_write_unlock_xattr(inode, &no_expand);
|
||||
if (error && (mnt_count != le16_to_cpu(sbi->s_es->s_mnt_count))) {
|
||||
ext4_warning(inode->i_sb, "Unable to expand inode %lu. Delete some EAs or run e2fsck.",
|
||||
inode->i_ino);
|
||||
mnt_count = le16_to_cpu(sbi->s_es->s_mnt_count);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -937,21 +937,19 @@ TRACE_EVENT(ext4_alloc_da_blocks,
|
|||
TP_STRUCT__entry(
|
||||
__field( dev_t, dev )
|
||||
__field( ino_t, ino )
|
||||
__field( unsigned int, data_blocks )
|
||||
__field( unsigned int, meta_blocks )
|
||||
__field( unsigned int, data_blocks )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->dev = inode->i_sb->s_dev;
|
||||
__entry->ino = inode->i_ino;
|
||||
__entry->data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
|
||||
__entry->meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
|
||||
),
|
||||
|
||||
TP_printk("dev %d,%d ino %lu data_blocks %u meta_blocks %u",
|
||||
TP_printk("dev %d,%d ino %lu reserved_data_blocks %u",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
(unsigned long) __entry->ino,
|
||||
__entry->data_blocks, __entry->meta_blocks)
|
||||
__entry->data_blocks)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ext4_mballoc_alloc,
|
||||
|
@ -1153,8 +1151,6 @@ TRACE_EVENT(ext4_da_update_reserve_space,
|
|||
__field( __u64, i_blocks )
|
||||
__field( int, used_blocks )
|
||||
__field( int, reserved_data_blocks )
|
||||
__field( int, reserved_meta_blocks )
|
||||
__field( int, allocated_meta_blocks )
|
||||
__field( int, quota_claim )
|
||||
__field( __u16, mode )
|
||||
),
|
||||
|
@ -1166,22 +1162,16 @@ TRACE_EVENT(ext4_da_update_reserve_space,
|
|||
__entry->used_blocks = used_blocks;
|
||||
__entry->reserved_data_blocks =
|
||||
EXT4_I(inode)->i_reserved_data_blocks;
|
||||
__entry->reserved_meta_blocks =
|
||||
EXT4_I(inode)->i_reserved_meta_blocks;
|
||||
__entry->allocated_meta_blocks =
|
||||
EXT4_I(inode)->i_allocated_meta_blocks;
|
||||
__entry->quota_claim = quota_claim;
|
||||
__entry->mode = inode->i_mode;
|
||||
),
|
||||
|
||||
TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu used_blocks %d "
|
||||
"reserved_data_blocks %d reserved_meta_blocks %d "
|
||||
"allocated_meta_blocks %d quota_claim %d",
|
||||
"reserved_data_blocks %d quota_claim %d",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
(unsigned long) __entry->ino,
|
||||
__entry->mode, __entry->i_blocks,
|
||||
__entry->used_blocks, __entry->reserved_data_blocks,
|
||||
__entry->reserved_meta_blocks, __entry->allocated_meta_blocks,
|
||||
__entry->quota_claim)
|
||||
);
|
||||
|
||||
|
@ -1195,7 +1185,6 @@ TRACE_EVENT(ext4_da_reserve_space,
|
|||
__field( ino_t, ino )
|
||||
__field( __u64, i_blocks )
|
||||
__field( int, reserved_data_blocks )
|
||||
__field( int, reserved_meta_blocks )
|
||||
__field( __u16, mode )
|
||||
),
|
||||
|
||||
|
@ -1204,17 +1193,15 @@ TRACE_EVENT(ext4_da_reserve_space,
|
|||
__entry->ino = inode->i_ino;
|
||||
__entry->i_blocks = inode->i_blocks;
|
||||
__entry->reserved_data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
|
||||
__entry->reserved_meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
|
||||
__entry->mode = inode->i_mode;
|
||||
),
|
||||
|
||||
TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu "
|
||||
"reserved_data_blocks %d reserved_meta_blocks %d",
|
||||
"reserved_data_blocks %d",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
(unsigned long) __entry->ino,
|
||||
__entry->mode, __entry->i_blocks,
|
||||
__entry->reserved_data_blocks,
|
||||
__entry->reserved_meta_blocks)
|
||||
__entry->reserved_data_blocks)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ext4_da_release_space,
|
||||
|
@ -1228,8 +1215,6 @@ TRACE_EVENT(ext4_da_release_space,
|
|||
__field( __u64, i_blocks )
|
||||
__field( int, freed_blocks )
|
||||
__field( int, reserved_data_blocks )
|
||||
__field( int, reserved_meta_blocks )
|
||||
__field( int, allocated_meta_blocks )
|
||||
__field( __u16, mode )
|
||||
),
|
||||
|
||||
|
@ -1239,19 +1224,15 @@ TRACE_EVENT(ext4_da_release_space,
|
|||
__entry->i_blocks = inode->i_blocks;
|
||||
__entry->freed_blocks = freed_blocks;
|
||||
__entry->reserved_data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
|
||||
__entry->reserved_meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
|
||||
__entry->allocated_meta_blocks = EXT4_I(inode)->i_allocated_meta_blocks;
|
||||
__entry->mode = inode->i_mode;
|
||||
),
|
||||
|
||||
TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu freed_blocks %d "
|
||||
"reserved_data_blocks %d reserved_meta_blocks %d "
|
||||
"allocated_meta_blocks %d",
|
||||
"reserved_data_blocks %d",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
(unsigned long) __entry->ino,
|
||||
__entry->mode, __entry->i_blocks,
|
||||
__entry->freed_blocks, __entry->reserved_data_blocks,
|
||||
__entry->reserved_meta_blocks, __entry->allocated_meta_blocks)
|
||||
__entry->freed_blocks, __entry->reserved_data_blocks)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(ext4__bitmap_load,
|
||||
|
|
Загрузка…
Ссылка в новой задаче