Skip to content

Commit

Permalink
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/tytso/ext4

Pull ext4 updates from Ted Ts'o:
 "The first major feature for ext4 this merge window is the largedir
  feature, which allows ext4 directories to support over 2 billion
  directory entries (assuming ~64 byte file names; in practice, users
  will run into practical performance limits first.) This feature was
  originally written by the Lustre team, and credit goes to Artem
  Blagodarenko from Seagate for getting this feature upstream.

  The second major major feature allows ext4 to support extended
  attribute values up to 64k. This feature was also originally from
  Lustre, and has been enhanced by Tahsin Erdogan from Google with a
  deduplication feature so that if multiple files have the same xattr
  value (for example, Windows ACL's stored by Samba), only one copy will
  be stored on disk for encoding and caching efficiency.

  We also have the usual set of bug fixes, cleanups, and optimizations"

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (47 commits)
  ext4: fix spelling mistake: "prellocated" -> "preallocated"
  ext4: fix __ext4_new_inode() journal credits calculation
  ext4: skip ext4_init_security() and encryption on ea_inodes
  fs: generic_block_bmap(): initialize all of the fields in the temp bh
  ext4: change fast symlink test to not rely on i_blocks
  ext4: require key for truncate(2) of encrypted file
  ext4: don't bother checking for encryption key in ->mmap()
  ext4: check return value of kstrtoull correctly in reserved_clusters_store
  ext4: fix off-by-one fsmap error on 1k block filesystems
  ext4: return EFSBADCRC if a bad checksum error is found in ext4_find_entry()
  ext4: return EIO on read error in ext4_find_entry
  ext4: forbid encrypting root directory
  ext4: send parallel discards on commit completions
  ext4: avoid unnecessary stalls in ext4_evict_inode()
  ext4: add nombcache mount option
  ext4: strong binding of xattr inode references
  ext4: eliminate xattr entry e_hash recalculation for removes
  ext4: reserve space for xattr entries/names
  quota: add get_inode_usage callback to transfer multi-inode charges
  ext4: xattr inode deduplication
  ...
  • Loading branch information
torvalds committed Jul 9, 2017
2 parents 58f587c + ff95015 commit bc2c642
Show file tree
Hide file tree
Showing 30 changed files with 2,117 additions and 549 deletions.
8 changes: 4 additions & 4 deletions fs/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -3031,11 +3031,11 @@ EXPORT_SYMBOL(block_write_full_page);
sector_t generic_block_bmap(struct address_space *mapping, sector_t block,
get_block_t *get_block)
{
struct buffer_head tmp;
struct inode *inode = mapping->host;
tmp.b_state = 0;
tmp.b_blocknr = 0;
tmp.b_size = i_blocksize(inode);
struct buffer_head tmp = {
.b_size = i_blocksize(inode),
};

get_block(inode, block, &tmp, 0);
return tmp.b_blocknr;
}
Expand Down
1 change: 1 addition & 0 deletions fs/crypto/policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child,
memcpy(ctx.master_key_descriptor, ci->ci_master_key,
FS_KEY_DESCRIPTOR_SIZE);
get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE);
BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE);
res = parent->i_sb->s_cop->set_context(child, &ctx,
sizeof(ctx), fs_data);
if (res)
Expand Down
2 changes: 1 addition & 1 deletion fs/ext2/ext2.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ struct ext2_sb_info {
* of the mount options.
*/
spinlock_t s_lock;
struct mb_cache *s_mb_cache;
struct mb_cache *s_ea_block_cache;
};

static inline spinlock_t *
Expand Down
16 changes: 8 additions & 8 deletions fs/ext2/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ static void ext2_put_super (struct super_block * sb)

ext2_quota_off_umount(sb);

if (sbi->s_mb_cache) {
ext2_xattr_destroy_cache(sbi->s_mb_cache);
sbi->s_mb_cache = NULL;
if (sbi->s_ea_block_cache) {
ext2_xattr_destroy_cache(sbi->s_ea_block_cache);
sbi->s_ea_block_cache = NULL;
}
if (!(sb->s_flags & MS_RDONLY)) {
struct ext2_super_block *es = sbi->s_es;
Expand Down Expand Up @@ -1131,9 +1131,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
}

#ifdef CONFIG_EXT2_FS_XATTR
sbi->s_mb_cache = ext2_xattr_create_cache();
if (!sbi->s_mb_cache) {
ext2_msg(sb, KERN_ERR, "Failed to create an mb_cache");
sbi->s_ea_block_cache = ext2_xattr_create_cache();
if (!sbi->s_ea_block_cache) {
ext2_msg(sb, KERN_ERR, "Failed to create ea_block_cache");
goto failed_mount3;
}
#endif
Expand Down Expand Up @@ -1182,8 +1182,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
sb->s_id);
goto failed_mount;
failed_mount3:
if (sbi->s_mb_cache)
ext2_xattr_destroy_cache(sbi->s_mb_cache);
if (sbi->s_ea_block_cache)
ext2_xattr_destroy_cache(sbi->s_ea_block_cache);
percpu_counter_destroy(&sbi->s_freeblocks_counter);
percpu_counter_destroy(&sbi->s_freeinodes_counter);
percpu_counter_destroy(&sbi->s_dirs_counter);
Expand Down
48 changes: 25 additions & 23 deletions fs/ext2/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ const struct xattr_handler *ext2_xattr_handlers[] = {
NULL
};

#define EA_BLOCK_CACHE(inode) (EXT2_SB(inode->i_sb)->s_ea_block_cache)

static inline const struct xattr_handler *
ext2_xattr_handler(int name_index)
{
Expand Down Expand Up @@ -150,7 +152,7 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
size_t name_len, size;
char *end;
int error;
struct mb_cache *ext2_mb_cache = EXT2_SB(inode->i_sb)->s_mb_cache;
struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);

ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
name_index, name, buffer, (long)buffer_size);
Expand Down Expand Up @@ -195,7 +197,7 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
goto found;
entry = next;
}
if (ext2_xattr_cache_insert(ext2_mb_cache, bh))
if (ext2_xattr_cache_insert(ea_block_cache, bh))
ea_idebug(inode, "cache insert failed");
error = -ENODATA;
goto cleanup;
Expand All @@ -208,7 +210,7 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
goto bad_block;

if (ext2_xattr_cache_insert(ext2_mb_cache, bh))
if (ext2_xattr_cache_insert(ea_block_cache, bh))
ea_idebug(inode, "cache insert failed");
if (buffer) {
error = -ERANGE;
Expand Down Expand Up @@ -246,7 +248,7 @@ ext2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
char *end;
size_t rest = buffer_size;
int error;
struct mb_cache *ext2_mb_cache = EXT2_SB(inode->i_sb)->s_mb_cache;
struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);

ea_idebug(inode, "buffer=%p, buffer_size=%ld",
buffer, (long)buffer_size);
Expand Down Expand Up @@ -281,7 +283,7 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
goto bad_block;
entry = next;
}
if (ext2_xattr_cache_insert(ext2_mb_cache, bh))
if (ext2_xattr_cache_insert(ea_block_cache, bh))
ea_idebug(inode, "cache insert failed");

/* list the attribute names */
Expand Down Expand Up @@ -493,8 +495,8 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
* This must happen under buffer lock for
* ext2_xattr_set2() to reliably detect modified block
*/
mb_cache_entry_delete_block(EXT2_SB(sb)->s_mb_cache,
hash, bh->b_blocknr);
mb_cache_entry_delete(EA_BLOCK_CACHE(inode), hash,
bh->b_blocknr);

/* keep the buffer locked while modifying it. */
} else {
Expand Down Expand Up @@ -627,7 +629,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
struct super_block *sb = inode->i_sb;
struct buffer_head *new_bh = NULL;
int error;
struct mb_cache *ext2_mb_cache = EXT2_SB(sb)->s_mb_cache;
struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);

if (header) {
new_bh = ext2_xattr_cache_find(inode, header);
Expand Down Expand Up @@ -655,7 +657,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
don't need to change the reference count. */
new_bh = old_bh;
get_bh(new_bh);
ext2_xattr_cache_insert(ext2_mb_cache, new_bh);
ext2_xattr_cache_insert(ea_block_cache, new_bh);
} else {
/* We need to allocate a new block */
ext2_fsblk_t goal = ext2_group_first_block_no(sb,
Expand All @@ -676,7 +678,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
memcpy(new_bh->b_data, header, new_bh->b_size);
set_buffer_uptodate(new_bh);
unlock_buffer(new_bh);
ext2_xattr_cache_insert(ext2_mb_cache, new_bh);
ext2_xattr_cache_insert(ea_block_cache, new_bh);

ext2_xattr_update_super_block(sb);
}
Expand Down Expand Up @@ -721,8 +723,8 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
* This must happen under buffer lock for
* ext2_xattr_set2() to reliably detect freed block
*/
mb_cache_entry_delete_block(ext2_mb_cache,
hash, old_bh->b_blocknr);
mb_cache_entry_delete(ea_block_cache, hash,
old_bh->b_blocknr);
/* Free the old block. */
ea_bdebug(old_bh, "freeing");
ext2_free_blocks(inode, old_bh->b_blocknr, 1);
Expand Down Expand Up @@ -795,8 +797,8 @@ ext2_xattr_delete_inode(struct inode *inode)
* This must happen under buffer lock for ext2_xattr_set2() to
* reliably detect freed block
*/
mb_cache_entry_delete_block(EXT2_SB(inode->i_sb)->s_mb_cache,
hash, bh->b_blocknr);
mb_cache_entry_delete(EA_BLOCK_CACHE(inode), hash,
bh->b_blocknr);
ext2_free_blocks(inode, EXT2_I(inode)->i_file_acl, 1);
get_bh(bh);
bforget(bh);
Expand Down Expand Up @@ -897,21 +899,21 @@ ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
{
__u32 hash = le32_to_cpu(header->h_hash);
struct mb_cache_entry *ce;
struct mb_cache *ext2_mb_cache = EXT2_SB(inode->i_sb)->s_mb_cache;
struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);

if (!header->h_hash)
return NULL; /* never share */
ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
again:
ce = mb_cache_entry_find_first(ext2_mb_cache, hash);
ce = mb_cache_entry_find_first(ea_block_cache, hash);
while (ce) {
struct buffer_head *bh;

bh = sb_bread(inode->i_sb, ce->e_block);
bh = sb_bread(inode->i_sb, ce->e_value);
if (!bh) {
ext2_error(inode->i_sb, "ext2_xattr_cache_find",
"inode %ld: block %ld read error",
inode->i_ino, (unsigned long) ce->e_block);
inode->i_ino, (unsigned long) ce->e_value);
} else {
lock_buffer(bh);
/*
Expand All @@ -924,27 +926,27 @@ ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
* entry is still hashed is reliable.
*/
if (hlist_bl_unhashed(&ce->e_hash_list)) {
mb_cache_entry_put(ext2_mb_cache, ce);
mb_cache_entry_put(ea_block_cache, ce);
unlock_buffer(bh);
brelse(bh);
goto again;
} else if (le32_to_cpu(HDR(bh)->h_refcount) >
EXT2_XATTR_REFCOUNT_MAX) {
ea_idebug(inode, "block %ld refcount %d>%d",
(unsigned long) ce->e_block,
(unsigned long) ce->e_value,
le32_to_cpu(HDR(bh)->h_refcount),
EXT2_XATTR_REFCOUNT_MAX);
} else if (!ext2_xattr_cmp(header, HDR(bh))) {
ea_bdebug(bh, "b_count=%d",
atomic_read(&(bh->b_count)));
mb_cache_entry_touch(ext2_mb_cache, ce);
mb_cache_entry_put(ext2_mb_cache, ce);
mb_cache_entry_touch(ea_block_cache, ce);
mb_cache_entry_put(ea_block_cache, ce);
return bh;
}
unlock_buffer(bh);
brelse(bh);
}
ce = mb_cache_entry_find_next(ext2_mb_cache, ce);
ce = mb_cache_entry_find_next(ea_block_cache, ce);
}
return NULL;
}
Expand Down
21 changes: 13 additions & 8 deletions fs/ext4/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ ext4_get_acl(struct inode *inode, int type)
*/
static int
__ext4_set_acl(handle_t *handle, struct inode *inode, int type,
struct posix_acl *acl)
struct posix_acl *acl, int xattr_flags)
{
int name_index;
void *value = NULL;
Expand Down Expand Up @@ -218,7 +218,7 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type,
}

error = ext4_xattr_set_handle(handle, inode, name_index, "",
value, size, 0);
value, size, xattr_flags);

kfree(value);
if (!error)
Expand All @@ -231,18 +231,23 @@ int
ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
handle_t *handle;
int error, retries = 0;
int error, credits, retries = 0;
size_t acl_size = acl ? ext4_acl_size(acl->a_count) : 0;

error = dquot_initialize(inode);
if (error)
return error;
retry:
handle = ext4_journal_start(inode, EXT4_HT_XATTR,
ext4_jbd2_credits_xattr(inode));
error = ext4_xattr_set_credits(inode, acl_size, false /* is_create */,
&credits);
if (error)
return error;

handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits);
if (IS_ERR(handle))
return PTR_ERR(handle);

error = __ext4_set_acl(handle, inode, type, acl);
error = __ext4_set_acl(handle, inode, type, acl, 0 /* xattr_flags */);
ext4_journal_stop(handle);
if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
goto retry;
Expand All @@ -267,13 +272,13 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)

if (default_acl) {
error = __ext4_set_acl(handle, inode, ACL_TYPE_DEFAULT,
default_acl);
default_acl, XATTR_CREATE);
posix_acl_release(default_acl);
}
if (acl) {
if (!error)
error = __ext4_set_acl(handle, inode, ACL_TYPE_ACCESS,
acl);
acl, XATTR_CREATE);
posix_acl_release(acl);
}
return error;
Expand Down
Loading

0 comments on commit bc2c642

Please sign in to comment.