Skip to content

Commit

Permalink
Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/tytso/ext4

Pull ext4 bugfixes from Ted Ts'o:
 "These changes contains a fix for overlayfs interacting with some
  (badly behaved) dentry code in various file systems.  These have been
  reviewed by Al and the respective file system mtinainers and are going
  through the ext4 tree for convenience.

  This also has a few ext4 encryption bug fixes that were discovered in
  Android testing (yes, we will need to get these sync'ed up with the
  fs/crypto code; I'll take care of that).  It also has some bug fixes
  and a change to ignore the legacy quota options to allow for xfstests
  regression testing of ext4's internal quota feature and to be more
  consistent with how xfs handles this case"

* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: ignore quota mount options if the quota feature is enabled
  ext4 crypto: fix some error handling
  ext4: avoid calling dquot_get_next_id() if quota is not enabled
  ext4: retry block allocation for failed DIO and DAX writes
  ext4: add lockdep annotations for i_data_sem
  ext4: allow readdir()'s of large empty directories to be interrupted
  btrfs: fix crash/invalid memory access on fsync when using overlayfs
  ext4 crypto: use dget_parent() in ext4_d_revalidate()
  ext4: use file_dentry()
  ext4: use dget_parent() in ext4_file_open()
  nfs: use file_dentry()
  fs: add file_dentry()
  ext4 crypto: don't let data integrity writebacks fail with ENOMEM
  ext4: check if in-inode xattr is corrupted in ext4_expand_extra_isize_ea()
  • Loading branch information
torvalds committed Apr 8, 2016
2 parents 1c915b3 + c325a67 commit 93061f3
Show file tree
Hide file tree
Showing 19 changed files with 264 additions and 86 deletions.
2 changes: 1 addition & 1 deletion fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1905,7 +1905,7 @@ static int start_ordered_ops(struct inode *inode, loff_t start, loff_t end)
*/
int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
{
struct dentry *dentry = file->f_path.dentry;
struct dentry *dentry = file_dentry(file);
struct inode *inode = d_inode(dentry);
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_trans_handle *trans;
Expand Down
5 changes: 4 additions & 1 deletion fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1667,7 +1667,8 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
DCACHE_OP_REVALIDATE |
DCACHE_OP_WEAK_REVALIDATE |
DCACHE_OP_DELETE |
DCACHE_OP_SELECT_INODE));
DCACHE_OP_SELECT_INODE |
DCACHE_OP_REAL));
dentry->d_op = op;
if (!op)
return;
Expand All @@ -1685,6 +1686,8 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
dentry->d_flags |= DCACHE_OP_PRUNE;
if (op->d_select_inode)
dentry->d_flags |= DCACHE_OP_SELECT_INODE;
if (op->d_real)
dentry->d_flags |= DCACHE_OP_REAL;

}
EXPORT_SYMBOL(d_set_d_op);
Expand Down
49 changes: 29 additions & 20 deletions fs/ext4/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx)
* Return: An allocated and initialized encryption context on success; error
* value or NULL otherwise.
*/
struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode,
gfp_t gfp_flags)
{
struct ext4_crypto_ctx *ctx = NULL;
int res = 0;
Expand All @@ -118,7 +119,7 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
list_del(&ctx->free_list);
spin_unlock_irqrestore(&ext4_crypto_ctx_lock, flags);
if (!ctx) {
ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, GFP_NOFS);
ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, gfp_flags);
if (!ctx) {
res = -ENOMEM;
goto out;
Expand Down Expand Up @@ -255,7 +256,8 @@ static int ext4_page_crypto(struct inode *inode,
ext4_direction_t rw,
pgoff_t index,
struct page *src_page,
struct page *dest_page)
struct page *dest_page,
gfp_t gfp_flags)

{
u8 xts_tweak[EXT4_XTS_TWEAK_SIZE];
Expand All @@ -266,7 +268,7 @@ static int ext4_page_crypto(struct inode *inode,
struct crypto_skcipher *tfm = ci->ci_ctfm;
int res = 0;

req = skcipher_request_alloc(tfm, GFP_NOFS);
req = skcipher_request_alloc(tfm, gfp_flags);
if (!req) {
printk_ratelimited(KERN_ERR
"%s: crypto_request_alloc() failed\n",
Expand Down Expand Up @@ -307,9 +309,10 @@ static int ext4_page_crypto(struct inode *inode,
return 0;
}

static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx)
static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx,
gfp_t gfp_flags)
{
ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, GFP_NOWAIT);
ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, gfp_flags);
if (ctx->w.bounce_page == NULL)
return ERR_PTR(-ENOMEM);
ctx->flags |= EXT4_WRITE_PATH_FL;
Expand All @@ -332,25 +335,26 @@ static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx)
* error value or NULL.
*/
struct page *ext4_encrypt(struct inode *inode,
struct page *plaintext_page)
struct page *plaintext_page,
gfp_t gfp_flags)
{
struct ext4_crypto_ctx *ctx;
struct page *ciphertext_page = NULL;
int err;

BUG_ON(!PageLocked(plaintext_page));

ctx = ext4_get_crypto_ctx(inode);
ctx = ext4_get_crypto_ctx(inode, gfp_flags);
if (IS_ERR(ctx))
return (struct page *) ctx;

/* The encryption operation will require a bounce page. */
ciphertext_page = alloc_bounce_page(ctx);
ciphertext_page = alloc_bounce_page(ctx, gfp_flags);
if (IS_ERR(ciphertext_page))
goto errout;
ctx->w.control_page = plaintext_page;
err = ext4_page_crypto(inode, EXT4_ENCRYPT, plaintext_page->index,
plaintext_page, ciphertext_page);
plaintext_page, ciphertext_page, gfp_flags);
if (err) {
ciphertext_page = ERR_PTR(err);
errout:
Expand Down Expand Up @@ -378,8 +382,8 @@ int ext4_decrypt(struct page *page)
{
BUG_ON(!PageLocked(page));

return ext4_page_crypto(page->mapping->host,
EXT4_DECRYPT, page->index, page, page);
return ext4_page_crypto(page->mapping->host, EXT4_DECRYPT,
page->index, page, page, GFP_NOFS);
}

int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk,
Expand All @@ -398,23 +402,24 @@ int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk,

BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE);

ctx = ext4_get_crypto_ctx(inode);
ctx = ext4_get_crypto_ctx(inode, GFP_NOFS);
if (IS_ERR(ctx))
return PTR_ERR(ctx);

ciphertext_page = alloc_bounce_page(ctx);
ciphertext_page = alloc_bounce_page(ctx, GFP_NOWAIT);
if (IS_ERR(ciphertext_page)) {
err = PTR_ERR(ciphertext_page);
goto errout;
}

while (len--) {
err = ext4_page_crypto(inode, EXT4_ENCRYPT, lblk,
ZERO_PAGE(0), ciphertext_page);
ZERO_PAGE(0), ciphertext_page,
GFP_NOFS);
if (err)
goto errout;

bio = bio_alloc(GFP_KERNEL, 1);
bio = bio_alloc(GFP_NOWAIT, 1);
if (!bio) {
err = -ENOMEM;
goto errout;
Expand Down Expand Up @@ -473,13 +478,16 @@ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size)
*/
static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags)
{
struct inode *dir = d_inode(dentry->d_parent);
struct ext4_crypt_info *ci = EXT4_I(dir)->i_crypt_info;
struct dentry *dir;
struct ext4_crypt_info *ci;
int dir_has_key, cached_with_key;

if (!ext4_encrypted_inode(dir))
dir = dget_parent(dentry);
if (!ext4_encrypted_inode(d_inode(dir))) {
dput(dir);
return 0;

}
ci = EXT4_I(d_inode(dir))->i_crypt_info;
if (ci && ci->ci_keyring_key &&
(ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
(1 << KEY_FLAG_REVOKED) |
Expand All @@ -489,6 +497,7 @@ static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags)
/* this should eventually be an flag in d_flags */
cached_with_key = dentry->d_fsdata != NULL;
dir_has_key = (ci != NULL);
dput(dir);

/*
* If the dentry was cached without the key, and it is a
Expand Down
5 changes: 5 additions & 0 deletions fs/ext4/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
while (ctx->pos < inode->i_size) {
struct ext4_map_blocks map;

if (fatal_signal_pending(current)) {
err = -ERESTARTSYS;
goto errout;
}
cond_resched();
map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb);
map.m_len = 1;
err = ext4_map_blocks(NULL, inode, &map, 0);
Expand Down
29 changes: 27 additions & 2 deletions fs/ext4/ext4.h
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,29 @@ do { \

#include "extents_status.h"

/*
* Lock subclasses for i_data_sem in the ext4_inode_info structure.
*
* These are needed to avoid lockdep false positives when we need to
* allocate blocks to the quota inode during ext4_map_blocks(), while
* holding i_data_sem for a normal (non-quota) inode. Since we don't
* do quota tracking for the quota inode, this avoids deadlock (as
* well as infinite recursion, since it isn't turtles all the way
* down...)
*
* I_DATA_SEM_NORMAL - Used for most inodes
* I_DATA_SEM_OTHER - Used by move_inode.c for the second normal inode
* where the second inode has larger inode number
* than the first
* I_DATA_SEM_QUOTA - Used for quota inodes only
*/
enum {
I_DATA_SEM_NORMAL = 0,
I_DATA_SEM_OTHER,
I_DATA_SEM_QUOTA,
};


/*
* fourth extended file system inode data in memory
*/
Expand Down Expand Up @@ -2282,11 +2305,13 @@ extern struct kmem_cache *ext4_crypt_info_cachep;
bool ext4_valid_contents_enc_mode(uint32_t mode);
uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size);
extern struct workqueue_struct *ext4_read_workqueue;
struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode);
struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode,
gfp_t gfp_flags);
void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx);
void ext4_restore_control_page(struct page *data_page);
struct page *ext4_encrypt(struct inode *inode,
struct page *plaintext_page);
struct page *plaintext_page,
gfp_t gfp_flags);
int ext4_decrypt(struct page *page);
int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk,
ext4_fsblk_t pblk, ext4_lblk_t len);
Expand Down
12 changes: 8 additions & 4 deletions fs/ext4/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
struct super_block *sb = inode->i_sb;
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
struct vfsmount *mnt = filp->f_path.mnt;
struct inode *dir = filp->f_path.dentry->d_parent->d_inode;
struct dentry *dir;
struct path path;
char buf[64], *cp;
int ret;
Expand Down Expand Up @@ -373,14 +373,18 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
if (ext4_encryption_info(inode) == NULL)
return -ENOKEY;
}
if (ext4_encrypted_inode(dir) &&
!ext4_is_child_context_consistent_with_parent(dir, inode)) {

dir = dget_parent(file_dentry(filp));
if (ext4_encrypted_inode(d_inode(dir)) &&
!ext4_is_child_context_consistent_with_parent(d_inode(dir), inode)) {
ext4_warning(inode->i_sb,
"Inconsistent encryption contexts: %lu/%lu\n",
(unsigned long) dir->i_ino,
(unsigned long) d_inode(dir)->i_ino,
(unsigned long) inode->i_ino);
dput(dir);
return -EPERM;
}
dput(dir);
/*
* Set up the jbd2_inode if we are opening the inode for
* writing and the journal is present
Expand Down
58 changes: 28 additions & 30 deletions fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -763,39 +763,47 @@ int ext4_get_block_unwritten(struct inode *inode, sector_t iblock,
/* Maximum number of blocks we map for direct IO at once. */
#define DIO_MAX_BLOCKS 4096

static handle_t *start_dio_trans(struct inode *inode,
struct buffer_head *bh_result)
/*
* Get blocks function for the cases that need to start a transaction -
* generally difference cases of direct IO and DAX IO. It also handles retries
* in case of ENOSPC.
*/
static int ext4_get_block_trans(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int flags)
{
int dio_credits;
handle_t *handle;
int retries = 0;
int ret;

/* Trim mapping request to maximum we can map at once for DIO */
if (bh_result->b_size >> inode->i_blkbits > DIO_MAX_BLOCKS)
bh_result->b_size = DIO_MAX_BLOCKS << inode->i_blkbits;
dio_credits = ext4_chunk_trans_blocks(inode,
bh_result->b_size >> inode->i_blkbits);
return ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, dio_credits);
retry:
handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, dio_credits);
if (IS_ERR(handle))
return PTR_ERR(handle);

ret = _ext4_get_block(inode, iblock, bh_result, flags);
ext4_journal_stop(handle);

if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
goto retry;
return ret;
}

/* Get block function for DIO reads and writes to inodes without extents */
int ext4_dio_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh, int create)
{
handle_t *handle;
int ret;

/* We don't expect handle for direct IO */
WARN_ON_ONCE(ext4_journal_current_handle());

if (create) {
handle = start_dio_trans(inode, bh);
if (IS_ERR(handle))
return PTR_ERR(handle);
}
ret = _ext4_get_block(inode, iblock, bh,
create ? EXT4_GET_BLOCKS_CREATE : 0);
if (create)
ext4_journal_stop(handle);
return ret;
if (!create)
return _ext4_get_block(inode, iblock, bh, 0);
return ext4_get_block_trans(inode, iblock, bh, EXT4_GET_BLOCKS_CREATE);
}

/*
Expand All @@ -806,18 +814,13 @@ int ext4_dio_get_block(struct inode *inode, sector_t iblock,
static int ext4_dio_get_block_unwritten_async(struct inode *inode,
sector_t iblock, struct buffer_head *bh_result, int create)
{
handle_t *handle;
int ret;

/* We don't expect handle for direct IO */
WARN_ON_ONCE(ext4_journal_current_handle());

handle = start_dio_trans(inode, bh_result);
if (IS_ERR(handle))
return PTR_ERR(handle);
ret = _ext4_get_block(inode, iblock, bh_result,
EXT4_GET_BLOCKS_IO_CREATE_EXT);
ext4_journal_stop(handle);
ret = ext4_get_block_trans(inode, iblock, bh_result,
EXT4_GET_BLOCKS_IO_CREATE_EXT);

/*
* When doing DIO using unwritten extents, we need io_end to convert
Expand Down Expand Up @@ -850,18 +853,13 @@ static int ext4_dio_get_block_unwritten_async(struct inode *inode,
static int ext4_dio_get_block_unwritten_sync(struct inode *inode,
sector_t iblock, struct buffer_head *bh_result, int create)
{
handle_t *handle;
int ret;

/* We don't expect handle for direct IO */
WARN_ON_ONCE(ext4_journal_current_handle());

handle = start_dio_trans(inode, bh_result);
if (IS_ERR(handle))
return PTR_ERR(handle);
ret = _ext4_get_block(inode, iblock, bh_result,
EXT4_GET_BLOCKS_IO_CREATE_EXT);
ext4_journal_stop(handle);
ret = ext4_get_block_trans(inode, iblock, bh_result,
EXT4_GET_BLOCKS_IO_CREATE_EXT);

/*
* Mark inode as having pending DIO writes to unwritten extents.
Expand Down
Loading

0 comments on commit 93061f3

Please sign in to comment.