* [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter
@ 2015-04-04 19:13 Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 01/16] fs: save file->f_flags to kiocb->ki_flags Dmitry Monakhov
` (15 more replies)
0 siblings, 16 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov
There are many places inside vfs/fs where code flow depends on file->f_flags,
but this check is racy because one can change it via fcntl(,F_SETFL,)
For example O_DIRECT usually flag checked twice:
xxx_file_write_iter -> check O_DIRECT, and perform some optimizations
->__generic_file_write_iter -> check O_DIRECT,
which may break things: for example http://www.spinics.net/lists/linux-ext4/msg45683.html
For that reason some filesystems simply do not use __generic_file_write_iter()
wihch result in code duplication. Right way to fix this is to save volatile flags
inside kiocb->ki_flags similar to ->ki_pos
Other private discussion: message-id:20141218105101.GD13705@quack.suse.cz
TOC:
##First two patches introduce helpers and update generic code
kiocb_flags-v1/0001-fs-save-file-f_flags-to-kiocb-ki_flags.patch
kiocb_flags-v1/0002-vfs-check-kiocb-ki_flags-instead-filp-fl_flags.patch
## Switch filesystems to kiocb->ki_flags
kiocb_flags-v1/0003-ext4-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0004-9p-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0005-btrfs-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0006-ceph-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0007-cifs-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0008-gfs2-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0009-nfs-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0010-ntfs-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0011-ocfs2-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0012-udf-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0013-xfs-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0014-fuse-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
## Fix pipe and splice issues caused by race with fcntl(,F_SETFL,)
kiocb_flags-v1/0015-pipe-use-is_xxx_kiocb-instead-of-filp-fl_flags.patch
kiocb_flags-v1/0016-splice-fix-race-beween-splice_write-vs-fcntl-F_SETFL.patch
Patch set survived basic run of xfstests
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 01/16] fs: save file->f_flags to kiocb->ki_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 02/16] vfs: check kiocb->ki_flags instead filp->fl_flags Dmitry Monakhov
` (14 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov
There are many places inside vfs/fs where code flow depends on file->f_flags,
but this check is racy because one can change it via fcntl(,F_SETFL,)
For example O_DIRECT usually flag checked twice:
xxx_file_write_iter -> check O_DIRECT, and perform some optimization
->__generic_file_write_iter -> check O_DIRECT,
which may break things: for example http://www.spinics.net/lists/linux-ext4/msg45683.html
For that reason some filesystems simply do not use __generic_file_write_iter()
which result in code duplication. Right way to fix this is to save volatile flags
inside kiocb->ki_flags similar to ->ki_pos
Other private discussion: message-id:20141218105101.GD13705@quack.suse.cz
This patch store O_DIRECT|O_APPEND|O_NONBLOCK|O_NDELAY
to kiocb->ki_flags on kiocb initialization.
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/aio.c | 7 ++++---
fs/read_write.c | 20 ++++++++++++++++++++
include/linux/fs.h | 30 +++++++++++++++++++++++++++---
3 files changed, 51 insertions(+), 6 deletions(-)
diff --git a/fs/aio.c b/fs/aio.c
index 3b8467a..f58c4d6 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1482,6 +1482,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
struct iocb *iocb, bool compat)
{
struct aio_kiocb *req;
+ struct file* filp;
ssize_t ret;
/* enforce forwards compatibility on users */
@@ -1504,14 +1505,14 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
if (unlikely(!req))
return -EAGAIN;
- req->common.ki_filp = fget(iocb->aio_fildes);
- if (unlikely(!req->common.ki_filp)) {
+ filp = fget(iocb->aio_fildes);
+ if (unlikely(!filp)) {
ret = -EBADF;
goto out_put_req;
}
+ kiocb_init_file(&req->common, filp);
req->common.ki_pos = iocb->aio_offset;
req->common.ki_complete = aio_complete;
- req->common.ki_flags = 0;
if (iocb->aio_flags & IOCB_FLAG_RESFD) {
/*
diff --git a/fs/read_write.c b/fs/read_write.c
index 69128b3..00e1ca4 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -41,6 +41,26 @@ static inline int unsigned_offsets(struct file *file)
return file->f_mode & FMODE_UNSIGNED_OFFSET;
}
+void kiocb_init_file(struct kiocb *kiocb, struct file *filp)
+{
+ kiocb->ki_flags = 0;
+ kiocb->ki_filp = filp;
+
+ /* Socket aio */
+ if (kiocb->ki_filp == NULL)
+ return;
+
+ if (filp->f_flags & O_APPEND)
+ kiocb->ki_flags |= IOCB_APPEND;
+ if (filp->f_flags & O_NONBLOCK)
+ kiocb->ki_flags |= IOCB_NONBLOCK;
+ if (filp->f_flags & O_NDELAY)
+ kiocb->ki_flags |= IOCB_NDELAY;
+ if (filp->f_flags & O_DIRECT)
+ kiocb->ki_flags |= IOCB_DIRECT;
+}
+EXPORT_SYMBOL(kiocb_init_file);
+
/**
* vfs_setpos - update the file offset for lseek
* @file: file structure in question
diff --git a/include/linux/fs.h b/include/linux/fs.h
index dfbd88a..4c20030 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -315,6 +315,10 @@ struct address_space;
struct writeback_control;
#define IOCB_EVENTFD (1 << 0)
+#define IOCB_APPEND (1 << 1)
+#define IOCB_NONBLOCK (1 << 2)
+#define IOCB_NDELAY (1 << 3)
+#define IOCB_DIRECT (1 << 4)
struct kiocb {
struct file *ki_filp;
@@ -329,11 +333,11 @@ static inline bool is_sync_kiocb(struct kiocb *kiocb)
return kiocb->ki_complete == NULL;
}
+extern void kiocb_init_file(struct kiocb *kiocb, struct file *filp);
static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
{
- *kiocb = (struct kiocb) {
- .ki_filp = filp,
- };
+ memset(kiocb, 0 , sizeof(*kiocb));
+ kiocb_init_file(kiocb, filp);
}
/*
@@ -2776,6 +2780,26 @@ extern int generic_show_options(struct seq_file *m, struct dentry *root);
extern void save_mount_options(struct super_block *sb, char *options);
extern void replace_mount_options(struct super_block *sb, char *options);
+static inline bool is_append_kiocb(struct kiocb *kiocb)
+{
+ return kiocb->ki_flags & IOCB_APPEND;
+}
+
+static inline bool is_direct_kiocb(struct kiocb *kiocb)
+{
+ return (kiocb->ki_flags & IOCB_DIRECT) |
+ IS_DAX(file_inode(kiocb->ki_filp));
+
+}
+
+
+static inline bool is_nonblock_kiocb(struct kiocb *kiocb)
+{
+ return kiocb->ki_flags & IOCB_NONBLOCK;
+}
+
+/* XXX: this is obsolete helper, and will be removed soon.
+ * One should use io_direct_kiocb() instead */
static inline bool io_is_direct(struct file *filp)
{
return (filp->f_flags & O_DIRECT) || IS_DAX(file_inode(filp));
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 02/16] vfs: check kiocb->ki_flags instead filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 01/16] fs: save file->f_flags to kiocb->ki_flags Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 21:36 ` Al Viro
2015-04-04 19:13 ` [PATCH 03/16] ext4: use is_xxx_kiocb instead of filp->fl_flags Dmitry Monakhov
` (13 subsequent siblings)
15 siblings, 1 reply; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov
generic_write_checks now accept kiocb as an argument
Unfortunetly it is impossible to get rid of old interface because some crappy
do not support write_iter interface so leave __generic_write_checks as backward
compatibility helper.
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
include/linux/fs.h | 8 +++++++-
mm/filemap.c | 13 +++++++------
2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4c20030..992685e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2570,7 +2570,7 @@ extern int sb_min_blocksize(struct super_block *, int);
extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
-int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk);
+int __generic_write_checks(struct file * file, loff_t *pos, size_t *count, int isblk, int append);
extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *);
extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *);
extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *);
@@ -2798,6 +2798,12 @@ static inline bool is_nonblock_kiocb(struct kiocb *kiocb)
return kiocb->ki_flags & IOCB_NONBLOCK;
}
+static inline int generic_write_checks(struct kiocb *iocb, loff_t *pos, size_t *count, int isblk)
+{
+ return __generic_write_checks(iocb->ki_filp, pos, count, isblk,
+ is_append_kiocb(iocb));
+}
+
/* XXX: this is obsolete helper, and will be removed soon.
* One should use io_direct_kiocb() instead */
static inline bool io_is_direct(struct file *filp)
diff --git a/mm/filemap.c b/mm/filemap.c
index 876f4e6..b519824 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1694,7 +1694,7 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
loff_t *ppos = &iocb->ki_pos;
loff_t pos = *ppos;
- if (io_is_direct(file)) {
+ if (is_direct_kiocb(iocb)) {
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
size_t count = iov_iter_count(iter);
@@ -2260,7 +2260,8 @@ EXPORT_SYMBOL(read_cache_page_gfp);
* Returns appropriate error code that caller should return or
* zero in case that write should be allowed.
*/
-inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk)
+inline int __generic_write_checks(struct file *file, loff_t *pos, size_t *count,
+ int isblk, int is_append)
{
struct inode *inode = file->f_mapping->host;
unsigned long limit = rlimit(RLIMIT_FSIZE);
@@ -2270,7 +2271,7 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
if (!isblk) {
/* FIXME: this is for backwards compatibility with 2.4 */
- if (file->f_flags & O_APPEND)
+ if (is_append)
*pos = i_size_read(inode);
if (limit != RLIM_INFINITY) {
@@ -2333,7 +2334,7 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
}
return 0;
}
-EXPORT_SYMBOL(generic_write_checks);
+EXPORT_SYMBOL(__generic_write_checks);
int pagecache_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
@@ -2565,7 +2566,7 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
/* We can write back this queue in page reclaim */
current->backing_dev_info = inode_to_bdi(inode);
- err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
+ err = generic_write_checks(iocb, &pos, &count, S_ISBLK(inode->i_mode));
if (err)
goto out;
@@ -2582,7 +2583,7 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (err)
goto out;
- if (io_is_direct(file)) {
+ if (is_direct_kiocb(iocb)) {
loff_t endbyte;
written = generic_file_direct_write(iocb, from, pos);
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 03/16] ext4: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 01/16] fs: save file->f_flags to kiocb->ki_flags Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 02/16] vfs: check kiocb->ki_flags instead filp->fl_flags Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 04/16] 9p: " Dmitry Monakhov
` (12 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, linux-ext4
Cc: linux-ext4@vger.kernel.org
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/ext4/file.c | 12 +++++-------
1 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 598abbb..27cf1cc 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -95,7 +95,6 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct inode *inode = file_inode(iocb->ki_filp);
struct mutex *aio_mutex = NULL;
struct blk_plug plug;
- int o_direct = io_is_direct(file);
int overwrite = 0;
size_t length = iov_iter_count(from);
ssize_t ret;
@@ -105,18 +104,17 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
* Unaligned direct AIO must be serialized; see comment above
* In the case of O_APPEND, assume that we must always serialize
*/
- if (o_direct &&
+ if (is_direct_kiocb(iocb) &&
ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
!is_sync_kiocb(iocb) &&
- (file->f_flags & O_APPEND ||
- ext4_unaligned_aio(inode, from, pos))) {
+ (is_append_kiocb(iocb) || ext4_unaligned_aio(inode, from, pos))) {
aio_mutex = ext4_aio_mutex(inode);
mutex_lock(aio_mutex);
ext4_unwritten_wait(inode);
}
mutex_lock(&inode->i_mutex);
- if (file->f_flags & O_APPEND)
+ if (is_append_kiocb(iocb))
iocb->ki_pos = pos = i_size_read(inode);
/*
@@ -138,7 +136,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
}
iocb->private = &overwrite;
- if (o_direct) {
+ if (is_direct_kiocb(iocb)) {
blk_start_plug(&plug);
@@ -182,7 +180,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (err < 0)
ret = err;
}
- if (o_direct)
+ if (is_direct_kiocb(iocb))
blk_finish_plug(&plug);
errout:
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 04/16] 9p: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (2 preceding siblings ...)
2015-04-04 19:13 ` [PATCH 03/16] ext4: use is_xxx_kiocb instead of filp->fl_flags Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 05/16] btrfs: " Dmitry Monakhov
` (11 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, v9fs-developer
Cc: v9fs-developer@lists.sourceforge.net
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/9p/vfs_file.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index b401337..c2a120a 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -509,7 +509,8 @@ v9fs_file_write(struct file *filp, const char __user * data,
loff_t origin = *offset;
- retval = generic_write_checks(filp, &origin, &count, 0);
+ retval = __generic_write_checks(filp, &origin, &count, 0,
+ filp->f_flags & O_APPEND);
if (retval)
goto out;
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 05/16] btrfs: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (3 preceding siblings ...)
2015-04-04 19:13 ` [PATCH 04/16] 9p: " Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 06/16] ceph: " Dmitry Monakhov
` (10 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, linux-btrfs
Cc: linux-btrfs@vger.kernel.org
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/btrfs/file.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index aee18f8..4dc3856 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1747,7 +1747,7 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
mutex_lock(&inode->i_mutex);
current->backing_dev_info = inode_to_bdi(inode);
- err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
+ err = generic_write_checks(iocb, &pos, &count, S_ISBLK(inode->i_mode));
if (err) {
mutex_unlock(&inode->i_mutex);
goto out;
@@ -1800,7 +1800,7 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
if (sync)
atomic_inc(&BTRFS_I(inode)->sync_writers);
- if (file->f_flags & O_DIRECT) {
+ if (is_direct_kiocb(iocb)) {
num_written = __btrfs_direct_write(iocb, from, pos);
} else {
num_written = __btrfs_buffered_write(file, from, pos);
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 06/16] ceph: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (4 preceding siblings ...)
2015-04-04 19:13 ` [PATCH 05/16] btrfs: " Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 07/16] cifs: " Dmitry Monakhov
` (9 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, ceph-devel
Cc: ceph-devel@vger.kernel.org
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/ceph/file.c | 13 ++++++-------
1 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 139f2fe..3ac67bf 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -442,7 +442,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
dout("sync_read on file %p %llu~%u %s\n", file, off,
(unsigned)len,
- (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
+ (is_direct_kiocb(iocb)) ? "O_DIRECT" : "");
if (!len)
return 0;
@@ -457,7 +457,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
if (ret < 0)
return ret;
- if (file->f_flags & O_DIRECT) {
+ if (is_direct_kiocb(iocb)) {
while (iov_iter_count(i)) {
size_t start;
ssize_t n;
@@ -828,8 +828,7 @@ again:
return ret;
if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 ||
- (iocb->ki_filp->f_flags & O_DIRECT) ||
- (fi->flags & CEPH_F_SYNC)) {
+ is_direct_kiocb(iocb) || (fi->flags & CEPH_F_SYNC)) {
dout("aio_sync_read %p %llx.%llx %llu~%u got cap refs on %s\n",
inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
@@ -953,7 +952,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
/* We can write back this queue in page reclaim */
current->backing_dev_info = inode_to_bdi(inode);
- err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
+ err = generic_write_checks(iocb, &pos, &count, S_ISBLK(inode->i_mode));
if (err)
goto out;
@@ -997,12 +996,12 @@ retry_snap:
inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
- (file->f_flags & O_DIRECT) || (fi->flags & CEPH_F_SYNC)) {
+ is_direct_kiocb(iocb) || (fi->flags & CEPH_F_SYNC)) {
struct iov_iter data;
mutex_unlock(&inode->i_mutex);
/* we might need to revert back to that point */
data = *from;
- if (file->f_flags & O_DIRECT)
+ if (is_direct_kiocb(iocb))
written = ceph_sync_direct_write(iocb, &data, pos);
else
written = ceph_sync_write(iocb, &data, pos);
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 07/16] cifs: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (5 preceding siblings ...)
2015-04-04 19:13 ` [PATCH 06/16] ceph: " Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [Cluster-devel] " Dmitry Monakhov
` (8 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, linux-cifs
Cc: linux-cifs@vger.kernel.org
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/cifs/file.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index a94b3e6..25527e9 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2560,7 +2560,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
}
static ssize_t
-cifs_iovec_write(struct file *file, struct iov_iter *from, loff_t *poffset)
+cifs_iovec_write(struct kiocb *iocb, struct iov_iter *from, loff_t *poffset)
{
size_t len;
ssize_t total_written = 0;
@@ -2573,7 +2573,7 @@ cifs_iovec_write(struct file *file, struct iov_iter *from, loff_t *poffset)
int rc;
len = iov_iter_count(from);
- rc = generic_write_checks(file, poffset, &len, 0);
+ rc = generic_write_checks(iocb, poffset, &len, 0);
if (rc)
return rc;
@@ -2583,8 +2583,8 @@ cifs_iovec_write(struct file *file, struct iov_iter *from, loff_t *poffset)
iov_iter_truncate(from, len);
INIT_LIST_HEAD(&wdata_list);
- cifs_sb = CIFS_FILE_SB(file);
- open_file = file->private_data;
+ cifs_sb = CIFS_FILE_SB(iocb->ki_filp);
+ open_file = iocb->ki_filp->private_data;
tcon = tlink_tcon(open_file->tlink);
if (!tcon->ses->server->ops->async_writev)
@@ -2670,7 +2670,7 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
* write request.
*/
- written = cifs_iovec_write(iocb->ki_filp, from, &pos);
+ written = cifs_iovec_write(iocb, from, &pos);
if (written > 0) {
set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
iocb->ki_pos = pos;
@@ -2696,7 +2696,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
*/
down_read(&cinode->lock_sem);
mutex_lock(&inode->i_mutex);
- if (file->f_flags & O_APPEND)
+ if (is_append_kiocb(iocb))
lock_pos = i_size_read(inode);
if (!cifs_find_lock_conflict(cfile, lock_pos, iov_iter_count(from),
server->vals->exclusive_lock_type, NULL,
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 08/16] gfs2: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 02/16] vfs: check kiocb->ki_flags instead filp->fl_flags Dmitry Monakhov
` (14 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, cluster-devel
Cc: cluster-devel@redhat.com
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/gfs2/file.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index f6fc412..25da110 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -709,7 +709,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from));
- if (file->f_flags & O_APPEND) {
+ if (is_append_kiocb(iocb)) {
struct gfs2_holder gh;
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Cluster-devel] [PATCH 08/16] gfs2: use is_xxx_kiocb instead of filp->fl_flags
@ 2015-04-04 19:13 ` Dmitry Monakhov
0 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: cluster-devel.redhat.com
Cc: cluster-devel at redhat.com
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/gfs2/file.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index f6fc412..25da110 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -709,7 +709,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from));
- if (file->f_flags & O_APPEND) {
+ if (is_append_kiocb(iocb)) {
struct gfs2_holder gh;
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 09/16] nfs: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (7 preceding siblings ...)
2015-04-04 19:13 ` [Cluster-devel] " Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 10/16] ntfs: " Dmitry Monakhov
` (6 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, linux-nfs
Cc: linux-nfs@vger.kernel.org
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/nfs/direct.c | 7 +++----
fs/nfs/file.c | 6 +++---
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index c3929fb..76950c6 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -964,8 +964,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
loff_t pos)
{
ssize_t result = -EINVAL;
- struct file *file = iocb->ki_filp;
- struct address_space *mapping = file->f_mapping;
+ struct address_space *mapping = iocb->ki_filp->f_mapping;
struct inode *inode = mapping->host;
struct nfs_direct_req *dreq;
struct nfs_lock_context *l_ctx;
@@ -976,9 +975,9 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count);
dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n",
- file, count, (long long) pos);
+ iocb->ki_filp, count, (long long) pos);
- result = generic_write_checks(file, &pos, &count, 0);
+ result = generic_write_checks(iocb, &pos, &count, 0);
if (result)
goto out;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 37b1558..709cb7f 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -170,7 +170,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
struct inode *inode = file_inode(iocb->ki_filp);
ssize_t result;
- if (iocb->ki_filp->f_flags & O_DIRECT)
+ if (is_direct_kiocb(iocb))
return nfs_file_direct_read(iocb, to, iocb->ki_pos);
dprintk("NFS: read(%pD2, %zu@%lu)\n",
@@ -680,7 +680,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
if (result)
return result;
- if (file->f_flags & O_DIRECT)
+ if (is_direct_kiocb(iocb))
return nfs_file_direct_write(iocb, from, pos);
dprintk("NFS: write(%pD2, %zu@%Ld)\n",
@@ -692,7 +692,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
/*
* O_APPEND implies that we must revalidate the file length.
*/
- if (file->f_flags & O_APPEND) {
+ if (is_append_kiocb(iocb)) {
result = nfs_revalidate_file_size(inode, file);
if (result)
goto out;
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 10/16] ntfs: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (8 preceding siblings ...)
2015-04-04 19:13 ` [PATCH 09/16] nfs: " Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 11/16] ocfs2: " Dmitry Monakhov
` (5 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, linux-ntfs-dev
Cc: linux-ntfs-dev@lists.sourceforge.net
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/ntfs/file.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index c1da78d..648b3a4 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -345,7 +345,8 @@ static ssize_t ntfs_prepare_file_for_write(struct file *file, loff_t *ppos,
(unsigned long long)*ppos, (unsigned long)*count);
/* We can write back this queue in page reclaim. */
current->backing_dev_info = inode_to_bdi(vi);
- err = generic_write_checks(file, ppos, count, S_ISBLK(vi->i_mode));
+ err = __generic_write_checks(file, ppos, count, S_ISBLK(vi->i_mode),
+ file->f_flags & O_APPEND);
if (unlikely(err))
goto out;
/*
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 11/16] ocfs2: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (9 preceding siblings ...)
2015-04-04 19:13 ` [PATCH 10/16] ntfs: " Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 12/16] udf: " Dmitry Monakhov
` (4 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, ocfs2-devel
Cc: ocfs2-devel@oss.oracle.com
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/ocfs2/file.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 266845d..c22b240 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2283,8 +2283,8 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
if (count == 0)
return 0;
- appending = file->f_flags & O_APPEND ? 1 : 0;
- direct_io = file->f_flags & O_DIRECT ? 1 : 0;
+ appending = is_append_kiocb(iocb);
+ direct_io = is_direct_kiocb(iocb);
mutex_lock(&inode->i_mutex);
@@ -2374,7 +2374,7 @@ relock:
/* communicate with ocfs2_dio_end_io */
ocfs2_iocb_set_rw_locked(iocb, rw_level);
- ret = generic_write_checks(file, ppos, &count,
+ ret = generic_write_checks(iocb, ppos, &count,
S_ISBLK(inode->i_mode));
if (ret)
goto out_dio;
@@ -2436,7 +2436,7 @@ relock:
out_dio:
/* buffered aio wouldn't have proper lock coverage today */
- BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
+ BUG_ON(ret == -EIOCBQUEUED && !is_direct_kiocb(iocb));
if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) ||
((file->f_flags & O_DIRECT) && !direct_io)) {
@@ -2547,7 +2547,7 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
* buffered reads protect themselves in ->readpage(). O_DIRECT reads
* need locks to protect pending reads from racing with truncate.
*/
- if (filp->f_flags & O_DIRECT) {
+ if (is_direct_kiocb(iocb)) {
have_alloc_sem = 1;
ocfs2_iocb_set_sem_locked(iocb);
@@ -2581,7 +2581,7 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
trace_generic_file_aio_read_ret(ret);
/* buffered aio wouldn't have proper lock coverage today */
- BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT));
+ BUG_ON(ret == -EIOCBQUEUED && !is_direct_kiocb(iocb));
/* see ocfs2_file_write_iter */
if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) {
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 12/16] udf: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (10 preceding siblings ...)
2015-04-04 19:13 ` [PATCH 11/16] ocfs2: " Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 13/16] xfs: " Dmitry Monakhov
` (3 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, jack
Cc: jack@suse.cz
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/udf/file.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 7f885cc..78ccc0f 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -128,7 +128,7 @@ static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
mutex_lock(&inode->i_mutex);
down_write(&iinfo->i_data_sem);
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
- if (file->f_flags & O_APPEND)
+ if (is_append_kiocb(iocb))
pos = inode->i_size;
else
pos = iocb->ki_pos;
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 13/16] xfs: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (11 preceding siblings ...)
2015-04-04 19:13 ` [PATCH 12/16] udf: " Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 14/16] fuse: " Dmitry Monakhov
` (2 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, xfs
Also function interface cleanup in order to vfs:write_iter interface agreeament
Cc: xfs@oss.sgi.com
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/xfs/xfs_file.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index f44212f..148039b 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -279,7 +279,7 @@ xfs_file_read_iter(
XFS_STATS_INC(xs_read_calls);
- if (unlikely(file->f_flags & O_DIRECT))
+ if (unlikely(is_direct_kiocb(iocb)))
ioflags |= XFS_IO_ISDIRECT;
if (file->f_mode & FMODE_NOCMTIME)
ioflags |= XFS_IO_INVIS;
@@ -544,17 +544,18 @@ xfs_zero_eof(
*/
STATIC ssize_t
xfs_file_aio_write_checks(
- struct file *file,
+ struct kiocb *iocb,
loff_t *pos,
size_t *count,
int *iolock)
{
+ struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
struct xfs_inode *ip = XFS_I(inode);
int error = 0;
restart:
- error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode));
+ error = generic_write_checks(iocb, pos, count, S_ISBLK(inode->i_mode));
if (error)
return error;
@@ -678,7 +679,7 @@ xfs_file_dio_aio_write(
xfs_rw_ilock(ip, iolock);
}
- ret = xfs_file_aio_write_checks(file, &pos, &count, &iolock);
+ ret = xfs_file_aio_write_checks(iocb, &pos, &count, &iolock);
if (ret)
goto out;
iov_iter_truncate(from, count);
@@ -739,7 +740,7 @@ xfs_file_buffered_aio_write(
xfs_rw_ilock(ip, iolock);
- ret = xfs_file_aio_write_checks(file, &pos, &count, &iolock);
+ ret = xfs_file_aio_write_checks(iocb, &pos, &count, &iolock);
if (ret)
goto out;
@@ -803,7 +804,7 @@ xfs_file_write_iter(
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
return -EIO;
- if (unlikely(file->f_flags & O_DIRECT))
+ if (unlikely(is_direct_kiocb(iocb)))
ret = xfs_file_dio_aio_write(iocb, from);
else
ret = xfs_file_buffered_aio_write(iocb, from);
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 14/16] fuse: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (12 preceding siblings ...)
2015-04-04 19:13 ` [PATCH 13/16] xfs: " Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 15/16] pipe: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 16/16] splice: fix race beween splice_write vs fcntl(,F_SETFL,) Dmitry Monakhov
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov, fuse-devel
Cc: fuse-devel@lists.sourceforge.net
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/fuse/file.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index ff102cb..ba8ad87 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1167,7 +1167,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
/* We can write back this queue in page reclaim */
current->backing_dev_info = inode_to_bdi(inode);
- err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
+ err = generic_write_checks(iocb, &pos, &count, S_ISBLK(inode->i_mode));
if (err)
goto out;
@@ -1183,7 +1183,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (err)
goto out;
- if (file->f_flags & O_DIRECT) {
+ if (is_direct_kiocb(iocb)) {
written = generic_file_direct_write(iocb, from, pos);
if (written < 0 || !iov_iter_count(from))
goto out;
@@ -1421,7 +1421,8 @@ static ssize_t __fuse_direct_write(struct fuse_io_priv *io,
ssize_t res;
- res = generic_write_checks(file, ppos, &count, 0);
+ res = __generic_write_checks(file, ppos, &count, 0,
+ file->f_flags & O_APPEND);
if (!res) {
iov_iter_truncate(iter, count);
res = fuse_direct_io(io, iter, ppos, FUSE_DIO_WRITE);
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 15/16] pipe: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (13 preceding siblings ...)
2015-04-04 19:13 ` [PATCH 14/16] fuse: " Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 16/16] splice: fix race beween splice_write vs fcntl(,F_SETFL,) Dmitry Monakhov
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov
Also fix other long standing issues caused by fcntl(,F_SETFL,):
- One can disable O_DIRECT for pipe[1] (paketized IO), but can not enable it again.
- Currently we do not set O_APPEND on pipe[1] (IMHO it is wrong, but let it be)
so it is reasonable to completely prohibit change O_APPEND flag on both
end's of pipe. Add ->check_flags method in order to diallow O_APPEND toggling.
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/fcntl.c | 6 ++++--
fs/pipe.c | 20 +++++++++++++++-----
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/fs/fcntl.c b/fs/fcntl.c
index ee85cd4..0bdc9c7 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -51,9 +51,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
if (arg & O_NDELAY)
arg |= O_NONBLOCK;
+ /* allowed only for inodes with ->direct_io method or write pipe */
if (arg & O_DIRECT) {
- if (!filp->f_mapping || !filp->f_mapping->a_ops ||
- !filp->f_mapping->a_ops->direct_IO)
+ if ((!filp->f_mapping || !filp->f_mapping->a_ops ||
+ !filp->f_mapping->a_ops->direct_IO) &&
+ !(get_pipe_info(filp) && (filp->f_flags | O_WRONLY)))
return -EINVAL;
}
diff --git a/fs/pipe.c b/fs/pipe.c
index 2d084f2..95b5fe4 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -301,7 +301,7 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
*/
if (ret)
break;
- if (filp->f_flags & O_NONBLOCK) {
+ if (is_nonblock_kiocb(iocb)) {
ret = -EAGAIN;
break;
}
@@ -329,9 +329,9 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
return ret;
}
-static inline int is_packetized(struct file *file)
+static inline int is_packetized(struct kiocb *kiocb)
{
- return (file->f_flags & O_DIRECT) != 0;
+ return is_direct_kiocb(kiocb);
}
static ssize_t
@@ -427,7 +427,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
buf->offset = 0;
buf->len = copied;
buf->flags = 0;
- if (is_packetized(filp)) {
+ if (is_packetized(iocb)) {
buf->ops = &packet_pipe_buf_ops;
buf->flags = PIPE_BUF_FLAG_PACKET;
}
@@ -439,7 +439,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
}
if (bufs < pipe->buffers)
continue;
- if (filp->f_flags & O_NONBLOCK) {
+ if (is_nonblock_kiocb(iocb)) {
if (!ret)
ret = -EAGAIN;
break;
@@ -943,6 +943,15 @@ err:
return ret;
}
+/* XXX: Currently it is not possible distinguish read side from write one */
+static int pipe_check_flags(int flags)
+{
+ if (flags & O_APPEND)
+ return -EINVAL;
+
+ return 0;
+}
+
const struct file_operations pipefifo_fops = {
.open = fifo_open,
.llseek = no_llseek,
@@ -954,6 +963,7 @@ const struct file_operations pipefifo_fops = {
.unlocked_ioctl = pipe_ioctl,
.release = pipe_release,
.fasync = pipe_fasync,
+ .check_flags = pipe_check_flags,
};
/*
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 16/16] splice: fix race beween splice_write vs fcntl(,F_SETFL,)
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
` (14 preceding siblings ...)
2015-04-04 19:13 ` [PATCH 15/16] pipe: " Dmitry Monakhov
@ 2015-04-04 19:13 ` Dmitry Monakhov
15 siblings, 0 replies; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-04 19:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, viro, Dmitry Monakhov
file->f_flags & O_APPEND is checked twice
-> do_splice_direct or do_splice: return EINVAL if O_APPEND enabled
-> generic_write_checks: seek to end in case of O_APPEND
This is obviously whong and result in unpredictable behaviour if raced with
fcntl. It is reasonable to recheck append flag after kiocb was constructed (
f_flags becomes stable), for that reason we should use special analog of
vfs_write_iter()
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/splice.c | 23 ++++++++++++++++++++++-
1 files changed, 22 insertions(+), 1 deletions(-)
diff --git a/fs/splice.c b/fs/splice.c
index 41cbb16..7ac43db 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -922,6 +922,27 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
return ret;
}
+ssize_t splice_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos)
+{
+ struct kiocb kiocb;
+ ssize_t ret;
+
+ if (!file->f_op->write_iter)
+ return -EINVAL;
+
+ init_sync_kiocb(&kiocb, file);
+ if (is_append_kiocb(&kiocb))
+ return -EINVAL;
+
+ kiocb.ki_pos = *ppos;
+ iter->type |= WRITE;
+ ret = file->f_op->write_iter(&kiocb, iter);
+ BUG_ON(ret == -EIOCBQUEUED);
+ if (ret > 0)
+ *ppos = kiocb.ki_pos;
+ return ret;
+}
+
/**
* iter_file_splice_write - splice data from a pipe to a file
@@ -1005,7 +1026,7 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
iov_iter_bvec(&from, ITER_BVEC | WRITE, array, n,
sd.total_len - left);
- ret = vfs_iter_write(out, &from, &sd.pos);
+ ret = splice_iter_write(out, &from, &sd.pos);
if (ret <= 0)
break;
--
1.7.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 02/16] vfs: check kiocb->ki_flags instead filp->fl_flags
2015-04-04 19:13 ` [PATCH 02/16] vfs: check kiocb->ki_flags instead filp->fl_flags Dmitry Monakhov
@ 2015-04-04 21:36 ` Al Viro
2015-04-05 11:03 ` Dmitry Monakhov
0 siblings, 1 reply; 24+ messages in thread
From: Al Viro @ 2015-04-04 21:36 UTC (permalink / raw)
To: Dmitry Monakhov; +Cc: linux-kernel, linux-fsdevel
On Sat, Apr 04, 2015 at 11:13:11PM +0400, Dmitry Monakhov wrote:
> generic_write_checks now accept kiocb as an argument
> Unfortunetly it is impossible to get rid of old interface because some crappy
> do not support write_iter interface so leave __generic_write_checks as backward
> compatibility helper.
Check the current vfs.git#for-next (there's even some generic_write_checks()
work in it). The same goes for the rest of the series. Please, rebase it.
What's more, generic_write_checks() should take iov_iter *, not the address
of something its ->count had been copied into. Note that all callers of that
thing end up doing iov_iter_truncate() pretty soon afterwards. I hadn't
pushed that one out yet (there is some weirdness in ocfs2 which might be
a bug; I want to sort that out first), but that's where it's going.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 02/16] vfs: check kiocb->ki_flags instead filp->fl_flags
2015-04-04 21:36 ` Al Viro
@ 2015-04-05 11:03 ` Dmitry Monakhov
2015-04-05 18:11 ` Al Viro
0 siblings, 1 reply; 24+ messages in thread
From: Dmitry Monakhov @ 2015-04-05 11:03 UTC (permalink / raw)
To: Al Viro; +Cc: linux-kernel, linux-fsdevel
[-- Attachment #1: Type: text/plain, Size: 1811 bytes --]
Al Viro <viro@ZenIV.linux.org.uk> writes:
> On Sat, Apr 04, 2015 at 11:13:11PM +0400, Dmitry Monakhov wrote:
>> generic_write_checks now accept kiocb as an argument
>> Unfortunetly it is impossible to get rid of old interface because some crappy
>> do not support write_iter interface so leave __generic_write_checks as backward
>> compatibility helper.
>
> Check the current vfs.git#for-next (there's even some generic_write_checks()
> work in it). The same goes for the rest of the series. Please, rebase it.
Ok. Yes you right. I've prepared patches against vfs.git#for-next(48a0c62) but
it is too old. Will rebase. Also it is reasonable to fold my fs-xxx
conversion to one combo patch similar to (d04cfe7840)
>
> What's more, generic_write_checks() should take iov_iter *, not the address
> of something its ->count had been copied into. Note that all callers of that
> thing end up doing iov_iter_truncate() pretty soon afterwards. I hadn't
> pushed that one out yet (there is some weirdness in ocfs2 which might be
> a bug; I want to sort that out first), but that's where it's going.
I'm not sure I have get your point about ocfs2 because it does
iov_iter_truncate() right after generic_write_checks()
But nfs definitely has a bug because iter was not truncated after generic_write_checks
->nfs_file_direct_write
->generic_write_checks(file, &pos, &count);
dreq->bytes_left = count;
task_io_account_write(count);
->nfs_direct_write_schedule_iovec(dreq, iter, pos);
###Ignore dreq->bytes_left(ala count) and submit non truncated iter
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 472 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 02/16] vfs: check kiocb->ki_flags instead filp->fl_flags
2015-04-05 11:03 ` Dmitry Monakhov
@ 2015-04-05 18:11 ` Al Viro
2015-04-05 21:54 ` Al Viro
0 siblings, 1 reply; 24+ messages in thread
From: Al Viro @ 2015-04-05 18:11 UTC (permalink / raw)
To: Dmitry Monakhov; +Cc: linux-kernel, linux-fsdevel
On Sun, Apr 05, 2015 at 02:03:22PM +0300, Dmitry Monakhov wrote:
> I'm not sure I have get your point about ocfs2 because it does
> iov_iter_truncate() right after generic_write_checks()
This
ret = ocfs2_prepare_inode_for_write(file, ppos, count, appending,
&can_do_direct, &has_refcount);
being done before generic_write_checks(). It actually duplicates some
parts of generic_write_checks() inside (O_APPEND-related, and AFAICS
they _are_ triggered twice that way).
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 02/16] vfs: check kiocb->ki_flags instead filp->fl_flags
2015-04-05 18:11 ` Al Viro
@ 2015-04-05 21:54 ` Al Viro
0 siblings, 0 replies; 24+ messages in thread
From: Al Viro @ 2015-04-05 21:54 UTC (permalink / raw)
To: Dmitry Monakhov; +Cc: linux-kernel, linux-fsdevel
On Sun, Apr 05, 2015 at 07:11:45PM +0100, Al Viro wrote:
> On Sun, Apr 05, 2015 at 02:03:22PM +0300, Dmitry Monakhov wrote:
>
> > I'm not sure I have get your point about ocfs2 because it does
> > iov_iter_truncate() right after generic_write_checks()
>
> This
> ret = ocfs2_prepare_inode_for_write(file, ppos, count, appending,
> &can_do_direct, &has_refcount);
> being done before generic_write_checks(). It actually duplicates some
> parts of generic_write_checks() inside (O_APPEND-related, and AFAICS
> they _are_ triggered twice that way).
XFS seems to be buggered as well:
/* DIO must be aligned to device logical sector size */
if ((pos | count) & target->bt_logical_sectormask)
return -EINVAL;
/* "unaligned" here means not aligned to a filesystem block */
if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask))
unaligned_io = 1;
...
ret = xfs_file_aio_write_checks(file, &pos, &count, &iolock);
now, play with rlimit() and suddenly the alignment checks above have nothing
to do with what'll actually happen after that sucker - it's calling
generic_write_checks(), so...
Incidentally, we want the result of alignment check to decide how to take
the lock that protects the file size, so simply lifting O_APPEND treatment
above those won't do. I suspect that in case of lock taken shared we
need to redo alignment checks and treat "it became unaligned" as "unlock
and redo it with lock taken exclusive".
BTW, xfs_break_layouts() having dropped and regained lock would invalidate
the O_APPEND treatment in generic_write_checks() just prior (both in
xfs_file_aio_write_checks())...
Al "really not fond of xfs_rw_ilock()" Viro...
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Cluster-devel] [PATCH 08/16] gfs2: use is_xxx_kiocb instead of filp->fl_flags
2015-04-04 19:13 ` [Cluster-devel] " Dmitry Monakhov
@ 2015-04-07 13:11 ` Steven Whitehouse
-1 siblings, 0 replies; 24+ messages in thread
From: Steven Whitehouse @ 2015-04-07 13:11 UTC (permalink / raw)
To: Dmitry Monakhov, linux-kernel; +Cc: linux-fsdevel, cluster-devel, viro
Hi,
On 04/04/15 20:13, Dmitry Monakhov wrote:
> Cc: cluster-devel@redhat.com
> Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Acked-by: Steven Whitehouse <swhiteho@redhat.com>
Steve.
> ---
> fs/gfs2/file.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index f6fc412..25da110 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -709,7 +709,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
>
> gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from));
>
> - if (file->f_flags & O_APPEND) {
> + if (is_append_kiocb(iocb)) {
> struct gfs2_holder gh;
>
> ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
^ permalink raw reply [flat|nested] 24+ messages in thread
* [Cluster-devel] [PATCH 08/16] gfs2: use is_xxx_kiocb instead of filp->fl_flags
@ 2015-04-07 13:11 ` Steven Whitehouse
0 siblings, 0 replies; 24+ messages in thread
From: Steven Whitehouse @ 2015-04-07 13:11 UTC (permalink / raw)
To: cluster-devel.redhat.com
Hi,
On 04/04/15 20:13, Dmitry Monakhov wrote:
> Cc: cluster-devel at redhat.com
> Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Acked-by: Steven Whitehouse <swhiteho@redhat.com>
Steve.
> ---
> fs/gfs2/file.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index f6fc412..25da110 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -709,7 +709,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
>
> gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from));
>
> - if (file->f_flags & O_APPEND) {
> + if (is_append_kiocb(iocb)) {
> struct gfs2_holder gh;
>
> ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2015-04-07 13:12 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-04 19:13 [PATCH 00/16] fs: fixup racy check file->f_flags for xxx_write_iter Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 01/16] fs: save file->f_flags to kiocb->ki_flags Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 02/16] vfs: check kiocb->ki_flags instead filp->fl_flags Dmitry Monakhov
2015-04-04 21:36 ` Al Viro
2015-04-05 11:03 ` Dmitry Monakhov
2015-04-05 18:11 ` Al Viro
2015-04-05 21:54 ` Al Viro
2015-04-04 19:13 ` [PATCH 03/16] ext4: use is_xxx_kiocb instead of filp->fl_flags Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 04/16] 9p: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 05/16] btrfs: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 06/16] ceph: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 07/16] cifs: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 08/16] gfs2: " Dmitry Monakhov
2015-04-04 19:13 ` [Cluster-devel] " Dmitry Monakhov
2015-04-07 13:11 ` Steven Whitehouse
2015-04-07 13:11 ` Steven Whitehouse
2015-04-04 19:13 ` [PATCH 09/16] nfs: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 10/16] ntfs: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 11/16] ocfs2: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 12/16] udf: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 13/16] xfs: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 14/16] fuse: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 15/16] pipe: " Dmitry Monakhov
2015-04-04 19:13 ` [PATCH 16/16] splice: fix race beween splice_write vs fcntl(,F_SETFL,) Dmitry Monakhov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.