From 027daf239150eb3be383620c34a6ba62aae5b5ef Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 13 Apr 2016 19:14:26 -0400 Subject: [PATCH] Rebase to v4.6-rc3 --- add-lockdep-annotations-for-i_data_sem | 146 -------------- ...hed-and-interruption-of-large-empty-directories | 48 ----- avoid-calling-get_next_id-if-quota-not-enabled | 50 ----- ...lid-memory-access-on-fsync-when-using-overlayfs | 87 --------- ...attr-is-corrupted-in-ext4_expand_extra_isize_ea | 84 -------- ...-let-data-integrity-writebacks-fail-with-ENOMEM | 215 --------------------- crypto-fix-some-error-handling | 24 --- ...a-mount-options-if-the-quota-feature-is-enabled | 69 ------- nfs-use-file-dentry | 94 --------- ...-block-allocation-for-failed-DIO-and-DAX-writes | 130 ------------- series | 18 +- timestamps | 19 +- use-dget_parent-in-ext4_d_revalidate | 48 ----- use-dget_parent-in-ext4_file_open | 57 ------ use-file_dentry | 39 ---- vfs-add-file-dentry | 181 ----------------- 16 files changed, 3 insertions(+), 1306 deletions(-) delete mode 100644 add-lockdep-annotations-for-i_data_sem delete mode 100644 allow-resched-and-interruption-of-large-empty-directories delete mode 100644 avoid-calling-get_next_id-if-quota-not-enabled delete mode 100644 btrfs-fix-crash-invalid-memory-access-on-fsync-when-using-overlayfs delete mode 100644 check-if-in-inode-xattr-is-corrupted-in-ext4_expand_extra_isize_ea delete mode 100644 crypto-dont-let-data-integrity-writebacks-fail-with-ENOMEM delete mode 100644 crypto-fix-some-error-handling delete mode 100644 ignore-quota-mount-options-if-the-quota-feature-is-enabled delete mode 100644 nfs-use-file-dentry delete mode 100644 retry-block-allocation-for-failed-DIO-and-DAX-writes delete mode 100644 use-dget_parent-in-ext4_d_revalidate delete mode 100644 use-dget_parent-in-ext4_file_open delete mode 100644 use-file_dentry delete mode 100644 vfs-add-file-dentry diff --git a/add-lockdep-annotations-for-i_data_sem b/add-lockdep-annotations-for-i_data_sem deleted file mode 100644 index effab20b..00000000 --- a/add-lockdep-annotations-for-i_data_sem +++ /dev/null @@ -1,146 +0,0 @@ -ext4: add lockdep annotations for i_data_sem - -With the internal Quota feature, mke2fs creates empty quota inodes and -quota usage tracking is enabled as soon as the file system is mounted. -Since quotacheck is no longer preallocating all of the blocks in the -quota inode that are likely needed to be written to, we are now seeing -a lockdep false positive caused by needing to allocate a quota block -from inside ext4_map_blocks(), while holding i_data_sem for a data -inode. This results in this complaint: - - Possible unsafe locking scenario: - - CPU0 CPU1 - ---- ---- - lock(&ei->i_data_sem); - lock(&s->s_dquot.dqio_mutex); - lock(&ei->i_data_sem); - lock(&s->s_dquot.dqio_mutex); - -Google-Bug-Id: 27907753 - -Signed-off-by: Theodore Ts'o -Cc: stable@vger.kernel.org ---- - fs/ext4/ext4.h | 23 +++++++++++++++++++++++ - fs/ext4/move_extent.c | 11 +++++++++-- - fs/ext4/super.c | 25 +++++++++++++++++++++++-- - 3 files changed, 55 insertions(+), 4 deletions(-) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index 7e4e3e9..6a857af 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -912,6 +912,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 - */ - struct ext4_inode_info { -diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c -index 4098acc..796ff0e 100644 ---- a/fs/ext4/move_extent.c -+++ b/fs/ext4/move_extent.c -@@ -60,10 +60,10 @@ ext4_double_down_write_data_sem(struct inode *first, struct inode *second) - { - if (first < second) { - down_write(&EXT4_I(first)->i_data_sem); -- down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); -+ down_write_nested(&EXT4_I(second)->i_data_sem, I_DATA_SEM_OTHER); - } else { - down_write(&EXT4_I(second)->i_data_sem); -- down_write_nested(&EXT4_I(first)->i_data_sem, SINGLE_DEPTH_NESTING); -+ down_write_nested(&EXT4_I(first)->i_data_sem, I_DATA_SEM_OTHER); - - } - } -@@ -484,6 +484,13 @@ mext_check_arguments(struct inode *orig_inode, - return -EBUSY; - } - -+ if (IS_NOQUOTA(orig_inode) || IS_NOQUOTA(donor_inode)) { -+ ext4_debug("ext4 move extent: The argument files should " -+ "not be quota files [ino:orig %lu, donor %lu]\n", -+ orig_inode->i_ino, donor_inode->i_ino); -+ return -EBUSY; -+ } -+ - /* Ext4 move extent supports only extent based file */ - if (!(ext4_test_inode_flag(orig_inode, EXT4_INODE_EXTENTS))) { - ext4_debug("ext4 move extent: orig file is not extents " -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 5392975..7ebd9f0 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -5028,6 +5028,20 @@ static int ext4_quota_on_mount(struct super_block *sb, int type) - EXT4_SB(sb)->s_jquota_fmt, type); - } - -+static void lockdep_set_quota_inode(struct inode *inode, int subclass) -+{ -+ struct ext4_inode_info *ei = EXT4_I(inode); -+ -+ /* The first argument of lockdep_set_subclass has to be -+ * *exactly* the same as the argument to init_rwsem() --- in -+ * this case, in init_once() --- or lockdep gets unhappy -+ * because the name of the lock is set using the -+ * stringification of the argument to init_rwsem(). -+ */ -+ (void) ei; /* shut up clang warning if !CONFIG_LOCKDEP */ -+ lockdep_set_subclass(&ei->i_data_sem, subclass); -+} -+ - /* - * Standard function to be called on quota_on - */ -@@ -5067,8 +5081,12 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, - if (err) - return err; - } -- -- return dquot_quota_on(sb, type, format_id, path); -+ lockdep_set_quota_inode(path->dentry->d_inode, I_DATA_SEM_QUOTA); -+ err = dquot_quota_on(sb, type, format_id, path); -+ if (err) -+ lockdep_set_quota_inode(path->dentry->d_inode, -+ I_DATA_SEM_NORMAL); -+ return err; - } - - static int ext4_quota_enable(struct super_block *sb, int type, int format_id, -@@ -5095,8 +5113,11 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id, - - /* Don't account quota for quota files to avoid recursion */ - qf_inode->i_flags |= S_NOQUOTA; -+ lockdep_set_quota_inode(qf_inode, I_DATA_SEM_QUOTA); - err = dquot_enable(qf_inode, type, format_id, flags); - iput(qf_inode); -+ if (err) -+ lockdep_set_quota_inode(qf_inode, I_DATA_SEM_NORMAL); - - return err; - } diff --git a/allow-resched-and-interruption-of-large-empty-directories b/allow-resched-and-interruption-of-large-empty-directories deleted file mode 100644 index 2565916b..00000000 --- a/allow-resched-and-interruption-of-large-empty-directories +++ /dev/null @@ -1,48 +0,0 @@ -ext4: allow readdir()'s of large empty directories to be interrupted - -If a directory has a large number of empty blocks, iterating over all -of them can take a long time, leading to scheduler warnings and users -getting irritated when they can't kill a process in the middle of one -of these long-running readdir operations. Fix this by adding checks to -ext4_readdir() and ext4_htree_fill_tree(). - -Reported-by: Benjamin LaHaise -Google-Bug-Id: 27880676 -Signed-off-by: Theodore Ts'o ---- - fs/ext4/dir.c | 5 +++++ - fs/ext4/namei.c | 5 +++++ - 2 files changed, 10 insertions(+) - -diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c -index 33f5e2a..ebfcb89 100644 ---- a/fs/ext4/dir.c -+++ b/fs/ext4/dir.c -@@ -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); -diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c -index 48e4b89..db98f89f 100644 ---- a/fs/ext4/namei.c -+++ b/fs/ext4/namei.c -@@ -1107,6 +1107,11 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, - } - - while (1) { -+ if (signal_pending(current)) { -+ err = -ERESTARTSYS; -+ goto errout; -+ } -+ cond_resched(); - block = dx_get_block(frame->at); - ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo, - start_hash, start_minor_hash); diff --git a/avoid-calling-get_next_id-if-quota-not-enabled b/avoid-calling-get_next_id-if-quota-not-enabled deleted file mode 100644 index cd10fd20..00000000 --- a/avoid-calling-get_next_id-if-quota-not-enabled +++ /dev/null @@ -1,50 +0,0 @@ -ext4: avoid calling dquot_get_next_id() if quota is not enabled - -This should be fixed in the quota layer so we can test with the quota -mutex held, but for now, we need this to avoid tests from crashing the -kernel aborting the regression test suite. - -Signed-off-by: Theodore Ts'o ---- - fs/ext4/super.c | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 63fe83d..0e6231b 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -1113,6 +1113,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type, - static int ext4_quota_enable(struct super_block *sb, int type, int format_id, - unsigned int flags); - static int ext4_enable_quotas(struct super_block *sb); -+static int ext4_get_next_id(struct super_block *sb, struct kqid *qid); - - static struct dquot **ext4_get_dquots(struct inode *inode) - { -@@ -1129,7 +1130,7 @@ static const struct dquot_operations ext4_quota_operations = { - .alloc_dquot = dquot_alloc, - .destroy_dquot = dquot_destroy, - .get_projid = ext4_get_projid, -- .get_next_id = dquot_get_next_id, -+ .get_next_id = ext4_get_next_id, - }; - - static const struct quotactl_ops ext4_qctl_operations = { -@@ -5255,6 +5256,17 @@ out: - return len; - } - -+static int ext4_get_next_id(struct super_block *sb, struct kqid *qid) -+{ -+ const struct quota_format_ops *ops; -+ -+ if (!sb_has_quota_loaded(sb, qid->type)) -+ return -ESRCH; -+ ops = sb_dqopt(sb)->ops[qid->type]; -+ if (!ops || !ops->get_next_id) -+ return -ENOSYS; -+ return dquot_get_next_id(sb, qid); -+} - #endif - - static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, diff --git a/btrfs-fix-crash-invalid-memory-access-on-fsync-when-using-overlayfs b/btrfs-fix-crash-invalid-memory-access-on-fsync-when-using-overlayfs deleted file mode 100644 index f56e7c76..00000000 --- a/btrfs-fix-crash-invalid-memory-access-on-fsync-when-using-overlayfs +++ /dev/null @@ -1,87 +0,0 @@ -btrfs: fix crash/invalid memory access on fsync when using overlayfs - -From: Filipe Manana - -If the lower or upper directory of an overlayfs mount belong to a btrfs -file system and we fsync the file through the overlayfs' merged directory -we ended up accessing an inode that didn't belong to btrfs as if it were -a btrfs inode at btrfs_sync_file() resulting in a crash like the following: - -[ 7782.588845] BUG: unable to handle kernel NULL pointer dereference at 0000000000000544 -[ 7782.590624] IP: [] btrfs_sync_file+0x11b/0x3e9 [btrfs] -[ 7782.591931] PGD 4d954067 PUD 1e878067 PMD 0 -[ 7782.592016] Oops: 0002 [#6] PREEMPT SMP DEBUG_PAGEALLOC -[ 7782.592016] Modules linked in: btrfs overlay ppdev crc32c_generic evdev xor raid6_pq psmouse pcspkr sg serio_raw acpi_cpufreq parport_pc parport tpm_tis i2c_piix4 tpm i2c_core processor button loop autofs4 ext4 crc16 mbcache jbd2 sr_mod cdrom sd_mod ata_generic virtio_scsi ata_piix virtio_pci libata virtio_ring virtio scsi_mod e1000 floppy [last unloaded: btrfs] -[ 7782.592016] CPU: 10 PID: 16437 Comm: xfs_io Tainted: G D 4.5.0-rc6-btrfs-next-26+ #1 -[ 7782.592016] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS by qemu-project.org 04/01/2014 -[ 7782.592016] task: ffff88001b8d40c0 ti: ffff880137488000 task.ti: ffff880137488000 -[ 7782.592016] RIP: 0010:[] [] btrfs_sync_file+0x11b/0x3e9 [btrfs] -[ 7782.592016] RSP: 0018:ffff88013748be40 EFLAGS: 00010286 -[ 7782.592016] RAX: 0000000080000000 RBX: ffff880133b30c88 RCX: 0000000000000001 -[ 7782.592016] RDX: 0000000000000001 RSI: ffffffff8148fec0 RDI: 00000000ffffffff -[ 7782.592016] RBP: ffff88013748bec0 R08: 0000000000000001 R09: 0000000000000000 -[ 7782.624248] R10: ffff88013748be40 R11: 0000000000000246 R12: 0000000000000000 -[ 7782.624248] R13: 0000000000000000 R14: 00000000009305a0 R15: ffff880015e3be40 -[ 7782.624248] FS: 00007fa83b9cb700(0000) GS:ffff88023ed40000(0000) knlGS:0000000000000000 -[ 7782.624248] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 -[ 7782.624248] CR2: 0000000000000544 CR3: 00000001fa652000 CR4: 00000000000006e0 -[ 7782.624248] Stack: -[ 7782.624248] ffffffff8108b5cc ffff88013748bec0 0000000000000246 ffff8800b005ded0 -[ 7782.624248] ffff880133b30d60 8000000000000000 7fffffffffffffff 0000000000000246 -[ 7782.624248] 0000000000000246 ffffffff81074f9b ffffffff8104357c ffff880015e3be40 -[ 7782.624248] Call Trace: -[ 7782.624248] [] ? arch_local_irq_save+0x9/0xc -[ 7782.624248] [] ? ___might_sleep+0xce/0x217 -[ 7782.624248] [] ? __do_page_fault+0x3c0/0x43a -[ 7782.624248] [] vfs_fsync_range+0x8c/0x9e -[ 7782.624248] [] vfs_fsync+0x1c/0x1e -[ 7782.624248] [] do_fsync+0x31/0x4a -[ 7782.624248] [] SyS_fsync+0x10/0x14 -[ 7782.624248] [] entry_SYSCALL_64_fastpath+0x12/0x6b -[ 7782.624248] Code: 85 c0 0f 85 e2 02 00 00 48 8b 45 b0 31 f6 4c 29 e8 48 ff c0 48 89 45 a8 48 8d 83 d8 00 00 00 48 89 c7 48 89 45 a0 e8 fc 43 18 e1 41 ff 84 24 44 05 00 00 48 8b 83 58 ff ff ff 48 c1 e8 07 83 -[ 7782.624248] RIP [] btrfs_sync_file+0x11b/0x3e9 [btrfs] -[ 7782.624248] RSP -[ 7782.624248] CR2: 0000000000000544 -[ 7782.661994] ---[ end trace 721e14960eb939bc ]--- - -This started happening since commit 4bacc9c9234 (overlayfs: Make f_path -always point to the overlay and f_inode to the underlay) and even though -after this change we could still access the btrfs inode through -struct file->f_mapping->host or struct file->f_inode, we would end up -resulting in more similar issues later on at check_parent_dirs_for_sync() -because the dentry we got (from struct file->f_path.dentry) was from -overlayfs and not from btrfs, that is, we had no way of getting the dentry -that belonged to btrfs (we always got the dentry that belonged to -overlayfs). - -The new patch from Miklos Szeredi, titled "vfs: add file_dentry()" and -recently submitted to linux-fsdevel, adds a file_dentry() API that allows -us to get the btrfs dentry from the input file and therefore being able -to fsync when the upper and lower directories belong to btrfs filesystems. - -This issue has been reported several times by users in the mailing list -and bugzilla. A test case for xfstests is being submitted as well. - -Fixes: 4bacc9c9234c ("overlayfs: Make f_path always point to the overlay and f_inode to the underlay") -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=101951 -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=109791 -Signed-off-by: Filipe Manana -Signed-off-by: Chris Mason -Cc: stable@vger.kernel.org ---- - fs/btrfs/file.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c -index 15a09cb..2f40482 100644 ---- a/fs/btrfs/file.c -+++ b/fs/btrfs/file.c -@@ -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; diff --git a/check-if-in-inode-xattr-is-corrupted-in-ext4_expand_extra_isize_ea b/check-if-in-inode-xattr-is-corrupted-in-ext4_expand_extra_isize_ea deleted file mode 100644 index f6cffba1..00000000 --- a/check-if-in-inode-xattr-is-corrupted-in-ext4_expand_extra_isize_ea +++ /dev/null @@ -1,84 +0,0 @@ -ext4: check if in-inode xattr is corrupted in ext4_expand_extra_isize_ea() - -We aren't checking to see if the in-inode extended attribute is -corrupted before we try to expand the inode's extra isize fields. - -This can lead to potential crashes caused by the BUG_ON() check in -ext4_xattr_shift_entries(). - -Signed-off-by: Theodore Ts'o ---- - fs/ext4/xattr.c | 32 ++++++++++++++++++++++++++++---- - 1 file changed, 28 insertions(+), 4 deletions(-) - -diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c -index 0441e05..e79bd32 100644 ---- a/fs/ext4/xattr.c -+++ b/fs/ext4/xattr.c -@@ -230,6 +230,27 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) - return error; - } - -+static int -+__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header, -+ void *end, const char *function, unsigned int line) -+{ -+ struct ext4_xattr_entry *entry = IFIRST(header); -+ int error = -EFSCORRUPTED; -+ -+ if (((void *) header >= end) || -+ (header->h_magic != le32_to_cpu(EXT4_XATTR_MAGIC))) -+ goto errout; -+ error = ext4_xattr_check_names(entry, end, entry); -+errout: -+ if (error) -+ __ext4_error_inode(inode, function, line, 0, -+ "corrupted in-inode xattr"); -+ return error; -+} -+ -+#define xattr_check_inode(inode, header, end) \ -+ __xattr_check_inode((inode), (header), (end), __func__, __LINE__) -+ - static inline int - ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size) - { -@@ -341,7 +362,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name, - header = IHDR(inode, raw_inode); - entry = IFIRST(header); - end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; -- error = ext4_xattr_check_names(entry, end, entry); -+ error = xattr_check_inode(inode, header, end); - if (error) - goto cleanup; - error = ext4_xattr_find_entry(&entry, name_index, name, -@@ -477,7 +498,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size) - raw_inode = ext4_raw_inode(&iloc); - header = IHDR(inode, raw_inode); - end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; -- error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header)); -+ error = xattr_check_inode(inode, header, end); - if (error) - goto cleanup; - error = ext4_xattr_list_entries(dentry, IFIRST(header), -@@ -1040,8 +1061,7 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, - is->s.here = is->s.first; - is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; - if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { -- error = ext4_xattr_check_names(IFIRST(header), is->s.end, -- IFIRST(header)); -+ error = xattr_check_inode(inode, header, is->s.end); - if (error) - return error; - /* Find the named attribute. */ -@@ -1356,6 +1376,10 @@ retry: - last = entry; - total_ino = sizeof(struct ext4_xattr_ibody_header); - -+ error = xattr_check_inode(inode, header, end); -+ if (error) -+ goto cleanup; -+ - free = ext4_xattr_free_space(last, &min_offs, base, &total_ino); - if (free >= new_extra_isize) { - entry = IFIRST(header); diff --git a/crypto-dont-let-data-integrity-writebacks-fail-with-ENOMEM b/crypto-dont-let-data-integrity-writebacks-fail-with-ENOMEM deleted file mode 100644 index 31bab67d..00000000 --- a/crypto-dont-let-data-integrity-writebacks-fail-with-ENOMEM +++ /dev/null @@ -1,215 +0,0 @@ -ext4 crypto: don't let data integrity writebacks fail with ENOMEM - -We don't want the writeback triggered from the journal commit (in -data=writeback mode) to cause the journal to abort due to -generic_writepages() returning an ENOMEM error. In addition, if -fsync() fails with ENOMEM, most applications will probably not do the -right thing. - -So if we are doing a data integrity sync, and ext4_encrypt() returns -ENOMEM, we will submit any queued I/O to date, and then retry the -allocation using GFP_NOFAIL. - -Google-Bug-Id: 27641567 - -Signed-off-by: Theodore Ts'o ---- - fs/ext4/crypto.c | 37 +++++++++++++++++++++---------------- - fs/ext4/ext4.h | 6 ++++-- - fs/ext4/page-io.c | 14 +++++++++++++- - fs/ext4/readpage.c | 2 +- - 4 files changed, 39 insertions(+), 20 deletions(-) - -diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c -index f7284ff..ea69ce4 100644 ---- a/fs/ext4/crypto.c -+++ b/fs/ext4/crypto.c -@@ -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; -@@ -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; -@@ -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]; -@@ -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", -@@ -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; -@@ -332,7 +335,8 @@ 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; -@@ -340,17 +344,17 @@ struct page *ext4_encrypt(struct inode *inode, - - 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: -@@ -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, -@@ -398,11 +402,11 @@ int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk, - - BUG_ON(inode->i_sb->s_blocksize != PAGE_CACHE_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; -@@ -410,11 +414,12 @@ int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk, - - 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; -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index c047435..7e4e3e9 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -2282,11 +2282,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); -diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c -index d77d15f..51b3492 100644 ---- a/fs/ext4/page-io.c -+++ b/fs/ext4/page-io.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - #include "ext4_jbd2.h" - #include "xattr.h" -@@ -470,9 +471,20 @@ int ext4_bio_write_page(struct ext4_io_submit *io, - - if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode) && - nr_to_submit) { -- data_page = ext4_encrypt(inode, page); -+ gfp_t gfp_flags = GFP_NOFS; -+ -+ retry_encrypt: -+ data_page = ext4_encrypt(inode, page, gfp_flags); - if (IS_ERR(data_page)) { - ret = PTR_ERR(data_page); -+ if (ret == ENOMEM && wbc->sync_mode == WB_SYNC_ALL) { -+ if (io->io_bio) { -+ ext4_io_submit(io); -+ congestion_wait(BLK_RW_ASYNC, HZ/50); -+ } -+ gfp_flags |= __GFP_NOFAIL; -+ goto retry_encrypt; -+ } - data_page = NULL; - goto out; - } -diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c -index 5dc5e95..bc7642f 100644 ---- a/fs/ext4/readpage.c -+++ b/fs/ext4/readpage.c -@@ -279,7 +279,7 @@ int ext4_mpage_readpages(struct address_space *mapping, - - if (ext4_encrypted_inode(inode) && - S_ISREG(inode->i_mode)) { -- ctx = ext4_get_crypto_ctx(inode); -+ ctx = ext4_get_crypto_ctx(inode, GFP_NOFS); - if (IS_ERR(ctx)) - goto set_error_page; - } diff --git a/crypto-fix-some-error-handling b/crypto-fix-some-error-handling deleted file mode 100644 index 9e01423e..00000000 --- a/crypto-fix-some-error-handling +++ /dev/null @@ -1,24 +0,0 @@ -ext4 crypto: fix some error handling - -From: Dan Carpenter - -We should be testing for -ENOMEM but the minus sign is missing. - -Fixes: c9af28fdd449 ('ext4 crypto: don't let data integrity writebacks fail with ENOMEM') -Signed-off-by: Dan Carpenter -Signed-off-by: Theodore Ts'o - -diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c -index 51b3492..b39d9c7 100644 ---- a/fs/ext4/page-io.c -+++ b/fs/ext4/page-io.c -@@ -477,7 +477,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, - data_page = ext4_encrypt(inode, page, gfp_flags); - if (IS_ERR(data_page)) { - ret = PTR_ERR(data_page); -- if (ret == ENOMEM && wbc->sync_mode == WB_SYNC_ALL) { -+ if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) { - if (io->io_bio) { - ext4_io_submit(io); - congestion_wait(BLK_RW_ASYNC, HZ/50); - diff --git a/ignore-quota-mount-options-if-the-quota-feature-is-enabled b/ignore-quota-mount-options-if-the-quota-feature-is-enabled deleted file mode 100644 index 3f83a348..00000000 --- a/ignore-quota-mount-options-if-the-quota-feature-is-enabled +++ /dev/null @@ -1,69 +0,0 @@ -ext4: ignore quota mount options if the quota feature is enabled - -From: Theodore Ts'o - -Previously, ext4 would fail the mount if the file system had the quota -feature enabled and quota mount options (used for the older quota -setups) were present. This broke xfstests, since xfs silently ignores -the usrquote and grpquota mount options if they are specified. This -commit changes things so that we are consistent with xfs; having the -mount options specified is harmless, so no sense break users by -forbidding them. - -Cc: stable@vger.kernel.org -Signed-off-by: Theodore Ts'o ---- - fs/ext4/super.c | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 5392975..94adae4 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -1323,9 +1323,9 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args) - return -1; - } - if (ext4_has_feature_quota(sb)) { -- ext4_msg(sb, KERN_ERR, "Cannot set journaled quota options " -- "when QUOTA feature is enabled"); -- return -1; -+ ext4_msg(sb, KERN_INFO, "Journaled quota options " -+ "ignored when QUOTA feature is enabled"); -+ return 1; - } - qname = match_strdup(args); - if (!qname) { -@@ -1688,10 +1688,10 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, - return -1; - } - if (ext4_has_feature_quota(sb)) { -- ext4_msg(sb, KERN_ERR, -- "Cannot set journaled quota options " -+ ext4_msg(sb, KERN_INFO, -+ "Quota format mount options ignored " - "when QUOTA feature is enabled"); -- return -1; -+ return 1; - } - sbi->s_jquota_fmt = m->mount_opt; - #endif -@@ -1756,11 +1756,11 @@ static int parse_options(char *options, struct super_block *sb, - #ifdef CONFIG_QUOTA - if (ext4_has_feature_quota(sb) && - (test_opt(sb, USRQUOTA) || test_opt(sb, GRPQUOTA))) { -- ext4_msg(sb, KERN_ERR, "Cannot set quota options when QUOTA " -- "feature is enabled"); -- return 0; -- } -- if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) { -+ ext4_msg(sb, KERN_INFO, "Quota feature enabled, usrquota and grpquota " -+ "mount options ignored."); -+ clear_opt(sb, USRQUOTA); -+ clear_opt(sb, GRPQUOTA); -+ } else if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) { - if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA]) - clear_opt(sb, USRQUOTA); - --- -2.5.0 - diff --git a/nfs-use-file-dentry b/nfs-use-file-dentry deleted file mode 100644 index fe83870e..00000000 --- a/nfs-use-file-dentry +++ /dev/null @@ -1,94 +0,0 @@ -nfs: use file_dentry() - -From: Miklos Szeredi - -NFS may be used as lower layer of overlayfs and accessing f_path.dentry can -lead to a crash. - -Fix by replacing direct access of file->f_path.dentry with the -file_dentry() accessor, which will always return a native object. - -Fixes: 4bacc9c9234c ("overlayfs: Make f_path always point to the overlay and f_inode to the underlay") -Signed-off-by: Miklos Szeredi -Tested-by: Goldwyn Rodrigues -Acked-by: Trond Myklebust -Signed-off-by: Theodore Ts'o -Cc: # v4.2 -Cc: David Howells -Cc: Al Viro ---- - fs/nfs/dir.c | 6 +++--- - fs/nfs/inode.c | 2 +- - fs/nfs/nfs4file.c | 4 ++-- - 3 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c -index 9cce67043f92..7ded17764754 100644 ---- a/fs/nfs/dir.c -+++ b/fs/nfs/dir.c -@@ -377,7 +377,7 @@ int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc, - again: - timestamp = jiffies; - gencount = nfs_inc_attr_generation_counter(); -- error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, entry->cookie, pages, -+ error = NFS_PROTO(inode)->readdir(file_dentry(file), cred, entry->cookie, pages, - NFS_SERVER(inode)->dtsize, desc->plus); - if (error < 0) { - /* We requested READDIRPLUS, but the server doesn't grok it */ -@@ -560,7 +560,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en - count++; - - if (desc->plus != 0) -- nfs_prime_dcache(desc->file->f_path.dentry, entry); -+ nfs_prime_dcache(file_dentry(desc->file), entry); - - status = nfs_readdir_add_to_array(entry, page); - if (status != 0) -@@ -864,7 +864,7 @@ static bool nfs_dir_mapping_need_revalidate(struct inode *dir) - */ - static int nfs_readdir(struct file *file, struct dir_context *ctx) - { -- struct dentry *dentry = file->f_path.dentry; -+ struct dentry *dentry = file_dentry(file); - struct inode *inode = d_inode(dentry); - nfs_readdir_descriptor_t my_desc, - *desc = &my_desc; -diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c -index 86faecf8f328..847b678af4f0 100644 ---- a/fs/nfs/inode.c -+++ b/fs/nfs/inode.c -@@ -940,7 +940,7 @@ int nfs_open(struct inode *inode, struct file *filp) - { - struct nfs_open_context *ctx; - -- ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode); -+ ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - nfs_file_set_open_context(filp, ctx); -diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c -index 57ca1c8039c1..2a9ff14cfb3b 100644 ---- a/fs/nfs/nfs4file.c -+++ b/fs/nfs/nfs4file.c -@@ -26,7 +26,7 @@ static int - nfs4_file_open(struct inode *inode, struct file *filp) - { - struct nfs_open_context *ctx; -- struct dentry *dentry = filp->f_path.dentry; -+ struct dentry *dentry = file_dentry(filp); - struct dentry *parent = NULL; - struct inode *dir; - unsigned openflags = filp->f_flags; -@@ -57,7 +57,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) - parent = dget_parent(dentry); - dir = d_inode(parent); - -- ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode); -+ ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode); - err = PTR_ERR(ctx); - if (IS_ERR(ctx)) - goto out; --- -2.1.4 - - diff --git a/retry-block-allocation-for-failed-DIO-and-DAX-writes b/retry-block-allocation-for-failed-DIO-and-DAX-writes deleted file mode 100644 index 91a3083b..00000000 --- a/retry-block-allocation-for-failed-DIO-and-DAX-writes +++ /dev/null @@ -1,130 +0,0 @@ -ext4: retry block allocation for failed DIO and DAX writes - -From: Jan Kara - -Currently if block allocation for DIO or DAX write fails due to ENOSPC, -we just returned it to userspace. However these ENOSPC errors can be -transient because the transaction freeing blocks has not yet committed. -This demonstrates as failures of generic/102 test when the filesystem is -mounted with 'dax' mount option. - -Fix the problem by properly retrying the allocation in case of ENOSPC -error in get blocks functions used for direct IO. - -Signed-off-by: Jan Kara -Signed-off-by: Theodore Ts'o -Tested-by: Ross Zwisler ---- - fs/ext4/inode.c | 58 ++++++++++++++++++++++++++++------------------------------ - 1 file changed, 28 insertions(+), 30 deletions(-) - -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index dab84a2..8710174 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -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); - } - - /* -@@ -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 -@@ -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. diff --git a/series b/series index c6e3f029..8779f90a 100644 --- a/series +++ b/series @@ -1,20 +1,4 @@ -# 0304688676bdf - -check-if-in-inode-xattr-is-corrupted-in-ext4_expand_extra_isize_ea -crypto-dont-let-data-integrity-writebacks-fail-with-ENOMEM - -vfs-add-file-dentry -nfs-use-file-dentry -use-dget_parent-in-ext4_file_open -use-file_dentry -use-dget_parent-in-ext4_d_revalidate -btrfs-fix-crash-invalid-memory-access-on-fsync-when-using-overlayfs -allow-resched-and-interruption-of-large-empty-directories -add-lockdep-annotations-for-i_data_sem -retry-block-allocation-for-failed-DIO-and-DAX-writes -avoid-calling-get_next_id-if-quota-not-enabled -crypto-fix-some-error-handling -ignore-quota-mount-options-if-the-quota-feature-is-enabled +# v4.6-rc3 ########################################## # unstable patches diff --git a/timestamps b/timestamps index 1be697e9..e4d78233 100755 --- a/timestamps +++ b/timestamps @@ -28,22 +28,7 @@ touch -d @1453078165 crypto-add-ioctls-to-backup-crypto-metadata touch -d @1453097831 crypto-rename-ext4_get_encryption_info touch -d @1453098259 crypto-add-ciphertext_access-mount-option touch -d @1456200258 optimize-group-search-for-inode-allocation -touch -d @1458677595 check-if-in-inode-xattr-is-corrupted-in-ext4_expand_extra_isize_ea -touch -d @1459023274 crypto-dont-let-data-integrity-writebacks-fail-with-ENOMEM -touch -d @1459023277 vfs-add-file-dentry -touch -d @1459023279 nfs-use-file-dentry -touch -d @1459023281 use-dget_parent-in-ext4_file_open -touch -d @1459023282 use-file_dentry -touch -d @1459023342 use-dget_parent-in-ext4_d_revalidate -touch -d @1459378993 btrfs-fix-crash-invalid-memory-access-on-fsync-when-using-overlayfs -touch -d @1459391784 allow-resched-and-interruption-of-large-empty-directories -touch -d @1459488688 add-lockdep-annotations-for-i_data_sem -touch -d @1459490842 retry-block-allocation-for-failed-DIO-and-DAX-writes -touch -d @1459526403 avoid-calling-get_next_id-if-quota-not-enabled -touch -d @1459635218 crypto-fix-some-error-handling -touch -d @1459717417 ignore-quota-mount-options-if-the-quota-feature-is-enabled -touch -d @1459717437 series touch -d @1459717477 stable-boundary touch -d @1460424255 status -touch -d @1460578176 #series# -touch -d @1460589204 timestamps +touch -d @1460589235 series +touch -d @1460589252 timestamps diff --git a/use-dget_parent-in-ext4_d_revalidate b/use-dget_parent-in-ext4_d_revalidate deleted file mode 100644 index bda56d2a..00000000 --- a/use-dget_parent-in-ext4_d_revalidate +++ /dev/null @@ -1,48 +0,0 @@ -ext4 crypto: use dget_parent() in ext4_d_revalidate() - -This avoids potential problems caused by a race where the inode gets -renamed out from its parent directory and the parent directory is -deleted while ext4_d_revalidate() is running. - -Fixes: 28b4c263961c -Reported-by: Al Viro -Signed-off-by: Theodore Ts'o -Cc: stable@vger.kernel.org - ---- - fs/ext4/crypto.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c -index 38f7562..ecb5439 100644 ---- a/fs/ext4/crypto.c -+++ b/fs/ext4/crypto.c -@@ -475,13 +475,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) | -@@ -491,6 +494,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 diff --git a/use-dget_parent-in-ext4_file_open b/use-dget_parent-in-ext4_file_open deleted file mode 100644 index 8163032d..00000000 --- a/use-dget_parent-in-ext4_file_open +++ /dev/null @@ -1,57 +0,0 @@ -ext4: use dget_parent() in ext4_file_open() - -From: Miklos Szeredi - -In f_op->open() lock on parent is not held, so there's no guarantee that -parent dentry won't go away at any time. - -Even after this patch there's no guarantee that 'dir' will stay the parent -of 'inode', but at least it won't be freed while being used. - -Fixes: ff978b09f973 ("ext4 crypto: move context consistency check to ext4_file_open()") -Signed-off-by: Miklos Szeredi -Signed-off-by: Theodore Ts'o -Cc: # v4.5 ---- - fs/ext4/file.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index 4cd318f31cbe..feb9ffc6f20d 100644 ---- a/fs/ext4/file.c -+++ b/fs/ext4/file.c -@@ -335,7 +335,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; -@@ -379,14 +379,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(filp->f_path.dentry); -+ 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 --- -2.1.4 - - diff --git a/use-file_dentry b/use-file_dentry deleted file mode 100644 index 0c900f40..00000000 --- a/use-file_dentry +++ /dev/null @@ -1,39 +0,0 @@ -ext4: use file_dentry() - -From: Miklos Szeredi - -EXT4 may be used as lower layer of overlayfs and accessing f_path.dentry -can lead to a crash. - -Fix by replacing direct access of file->f_path.dentry with the -file_dentry() accessor, which will always return a native object. - -Reported-by: Daniel Axtens -Fixes: 4bacc9c9234c ("overlayfs: Make f_path always point to the overlay and f_inode to the underlay") -Fixes: ff978b09f973 ("ext4 crypto: move context consistency check to ext4_file_open()") -Signed-off-by: Miklos Szeredi -Signed-off-by: Theodore Ts'o -Cc: David Howells -Cc: Al Viro -Cc: # v4.5 ---- - fs/ext4/file.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index feb9ffc6f20d..38847f38b34a 100644 ---- a/fs/ext4/file.c -+++ b/fs/ext4/file.c -@@ -380,7 +380,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) - return -ENOKEY; - } - -- dir = dget_parent(filp->f_path.dentry); -+ 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, --- -2.1.4 - - diff --git a/vfs-add-file-dentry b/vfs-add-file-dentry deleted file mode 100644 index bb60a476..00000000 --- a/vfs-add-file-dentry +++ /dev/null @@ -1,181 +0,0 @@ -fs: add file_dentry() - -From: Miklos Szeredi - -This series fixes bugs in nfs and ext4 due to 4bacc9c9234c ("overlayfs: -Make f_path always point to the overlay and f_inode to the underlay"). - -Regular files opened on overlayfs will result in the file being opened on -the underlying filesystem, while f_path points to the overlayfs -mount/dentry. - -This confuses filesystems which get the dentry from struct file and assume -it's theirs. - -Add a new helper, file_dentry() [*], to get the filesystem's own dentry -from the file. This checks file->f_path.dentry->d_flags against -DCACHE_OP_REAL, and returns file->f_path.dentry if DCACHE_OP_REAL is not -set (this is the common, non-overlayfs case). - -In the uncommon case it will call into overlayfs's ->d_real() to get the -underlying dentry, matching file_inode(file). - -The reason we need to check against the inode is that if the file is copied -up while being open, d_real() would return the upper dentry, while the open -file comes from the lower dentry. - -[*] If possible, it's better simply to use file_inode() instead. - -Signed-off-by: Miklos Szeredi -Signed-off-by: Theodore Ts'o -Tested-by: Goldwyn Rodrigues -Reviewed-by: Trond Myklebust -Cc: # v4.2 -Cc: David Howells -Cc: Al Viro -Cc: Daniel Axtens ---- -changes in v2: - - - rename method to d_op->d_real() - - check d_flag instead of comparing inode for base dentry - - ovl_d_real() now handles recursion - - WARN instead of BUG and be more verbose - - add d_real() helper too - - fs/dcache.c | 5 ++++- - fs/overlayfs/super.c | 33 +++++++++++++++++++++++++++++++++ - include/linux/dcache.h | 10 ++++++++++ - include/linux/fs.h | 10 ++++++++++ - 4 files changed, 57 insertions(+), 1 deletion(-) - ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -1667,7 +1667,8 @@ void d_set_d_op(struct dentry *dentry, c - 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; -@@ -1685,6 +1686,8 @@ void d_set_d_op(struct dentry *dentry, c - 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); ---- a/include/linux/dcache.h -+++ b/include/linux/dcache.h -@@ -161,6 +161,7 @@ struct dentry_operations { - struct vfsmount *(*d_automount)(struct path *); - int (*d_manage)(struct dentry *, bool); - struct inode *(*d_select_inode)(struct dentry *, unsigned); -+ struct dentry *(*d_real)(struct dentry *, struct inode *); - } ____cacheline_aligned; - - /* -@@ -229,6 +230,7 @@ struct dentry_operations { - #define DCACHE_OP_SELECT_INODE 0x02000000 /* Unioned entry: dcache op selects inode */ - - #define DCACHE_ENCRYPTED_WITH_KEY 0x04000000 /* dir is encrypted with a valid key */ -+#define DCACHE_OP_REAL 0x08000000 - - extern seqlock_t rename_lock; - -@@ -555,4 +557,12 @@ static inline struct dentry *d_backing_d - return upper; - } - -+static inline struct dentry *d_real(struct dentry *dentry) -+{ -+ if (unlikely(dentry->d_flags & DCACHE_OP_REAL)) -+ return dentry->d_op->d_real(dentry, NULL); -+ else -+ return dentry; -+} -+ - #endif /* __LINUX_DCACHE_H */ ---- a/fs/overlayfs/super.c -+++ b/fs/overlayfs/super.c -@@ -295,6 +295,37 @@ static void ovl_dentry_release(struct de - } - } - -+static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode) -+{ -+ struct dentry *real; -+ -+ if (d_is_dir(dentry)) { -+ if (!inode || inode == d_inode(dentry)) -+ return dentry; -+ goto bug; -+ } -+ -+ real = ovl_dentry_upper(dentry); -+ if (real && (!inode || inode == d_inode(real))) -+ return real; -+ -+ real = ovl_dentry_lower(dentry); -+ if (!real) -+ goto bug; -+ -+ if (!inode || inode == d_inode(real)) -+ return real; -+ -+ /* Handle recursion */ -+ if (real->d_flags & DCACHE_OP_REAL) -+ return real->d_op->d_real(real, inode); -+ -+bug: -+ WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry, -+ inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0); -+ return dentry; -+} -+ - static int ovl_dentry_revalidate(struct dentry *dentry, unsigned int flags) - { - struct ovl_entry *oe = dentry->d_fsdata; -@@ -339,11 +370,13 @@ static int ovl_dentry_weak_revalidate(st - static const struct dentry_operations ovl_dentry_operations = { - .d_release = ovl_dentry_release, - .d_select_inode = ovl_d_select_inode, -+ .d_real = ovl_d_real, - }; - - static const struct dentry_operations ovl_reval_dentry_operations = { - .d_release = ovl_dentry_release, - .d_select_inode = ovl_d_select_inode, -+ .d_real = ovl_d_real, - .d_revalidate = ovl_dentry_revalidate, - .d_weak_revalidate = ovl_dentry_weak_revalidate, - }; ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1241,6 +1241,16 @@ static inline struct inode *file_inode(c - return f->f_inode; - } - -+static inline struct dentry *file_dentry(const struct file *file) -+{ -+ struct dentry *dentry = file->f_path.dentry; -+ -+ if (unlikely(dentry->d_flags & DCACHE_OP_REAL)) -+ return dentry->d_op->d_real(dentry, file_inode(file)); -+ else -+ return dentry; -+} -+ - static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl) - { - return locks_lock_inode_wait(file_inode(filp), fl); --- -To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - -- 2.11.4.GIT