diff options
author | Davide Italiano <dccitaliano@gmail.com> | 2015-09-16 17:36:23 +0300 |
---|---|---|
committer | Jiri Slaby <jslaby@suse.cz> | 2015-09-18 09:26:31 +0200 |
commit | 7e7ec82ecd66ed0cfd77346d8cb4676e06b881ec (patch) | |
tree | 079b1098fa07160962b820d9fdc0edcb36e51c86 | |
parent | bf9adcbe5206ddd199d7447f1d79729a7980dbdd (diff) | |
download | lwn-7e7ec82ecd66ed0cfd77346d8cb4676e06b881ec.tar.gz lwn-7e7ec82ecd66ed0cfd77346d8cb4676e06b881ec.zip |
ext4: move check under lock scope to close a race.
commit 280227a75b56ab5d35854f3a77ef74a7ad56a203 upstream
fallocate() checks that the file is extent-based and returns
EOPNOTSUPP in case is not. Other tasks can convert from and to
indirect and extent so it's safe to check only after grabbing
the inode mutex.
[Nikolay Borisov: Bakported to 3.12.47
- Adjusted context
- Add the 'out' label]
Signed-off-by: Davide Italiano <dccitaliano@gmail.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Nikolay Borisov <kernel@kyup.com>
Cc: Jan Kara <jack@suse.cz>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
-rw-r--r-- | fs/ext4/extents.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index c9830686cbd5..a9d23daa0d6f 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -4634,12 +4634,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (ret) return ret; - /* - * currently supporting (pre)allocate mode for extent-based - * files _only_ - */ - if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) - return -EOPNOTSUPP; trace_ext4_fallocate_enter(inode, offset, len, mode); map.m_lblk = offset >> blkbits; @@ -4654,6 +4648,16 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) */ credits = ext4_chunk_trans_blocks(inode, max_blocks); mutex_lock(&inode->i_mutex); + + /* + * currently supporting (pre)allocate mode for extent-based + * files _only_ + */ + if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { + ret = -EOPNOTSUPP; + goto out; + } + ret = inode_newsize_ok(inode, (len + offset)); if (ret) { mutex_unlock(&inode->i_mutex); @@ -4714,6 +4718,7 @@ retry: ret = 0; goto retry; } +out: mutex_unlock(&inode->i_mutex); trace_ext4_fallocate_exit(inode, offset, max_blocks, ret > 0 ? ret2 : ret); |