linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ben Hutchings <ben@decadent.org.uk>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: akpm@linux-foundation.org, Denis Kirjanov <kda@linux-powerpc.org>,
	"Linus Torvalds" <torvalds@linux-foundation.org>,
	"Kirill Smelkov" <kirr@nexedi.com>,
	"Christoph Hellwig" <hch@lst.de>,
	"Jonathan Corbet" <corbet@lwn.net>,
	"Juergen Gross" <jgross@suse.com>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Han-Wen Nienhuys" <hanwen@google.com>,
	"Julia Lawall" <Julia.Lawall@lip6.fr>,
	"Yongzhi Pan" <panyongzhi@gmail.com>,
	"David Vrabel" <david.vrabel@citrix.com>,
	"Nikolaus Rath" <Nikolaus@rath.org>,
	"Kirill Tkhai" <ktkhai@virtuozzo.com>,
	"Arnd Bergmann" <arnd@arndb.de>,
	"Miklos Szeredi" <miklos@szeredi.hu>,
	"Michael Kerrisk" <mtk.manpages@gmail.com>,
	"Tejun Heo" <tj@kernel.org>
Subject: [PATCH 3.16 122/129] fs: stream_open - opener for stream-like files so  that read and write can run simultaneously without deadlock
Date: Sun, 07 Jul 2019 17:54:17 +0100	[thread overview]
Message-ID: <lsq.1562518457.714019616@decadent.org.uk> (raw)
In-Reply-To: <lsq.1562518456.876074874@decadent.org.uk>

3.16.70-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Kirill Smelkov <kirr@nexedi.com>

commit 10dce8af34226d90fa56746a934f8da5dcdba3df upstream.

[ while porting to 3.16 xenbus conflict was trivially resolved in a way
  that actually fixes /proc/xen/xenbus deadlock introduced in 3.14,
  because original upstream commit 581d21a2d02a to fix xenbus deadlock
  was not included into 3.16 . ]

Commit 9c225f2655e3 ("vfs: atomic f_pos accesses as per POSIX") added
locking for file.f_pos access and in particular made concurrent read and
write not possible - now both those functions take f_pos lock for the
whole run, and so if e.g. a read is blocked waiting for data, write will
deadlock waiting for that read to complete.

This caused regression for stream-like files where previously read and
write could run simultaneously, but after that patch could not do so
anymore. See e.g. commit 581d21a2d02a ("xenbus: fix deadlock on writes
to /proc/xen/xenbus") which fixes such regression for particular case of
/proc/xen/xenbus.

The patch that added f_pos lock in 2014 did so to guarantee POSIX thread
safety for read/write/lseek and added the locking to file descriptors of
all regular files. In 2014 that thread-safety problem was not new as it
was already discussed earlier in 2006.

However even though 2006'th version of Linus's patch was adding f_pos
locking "only for files that are marked seekable with FMODE_LSEEK (thus
avoiding the stream-like objects like pipes and sockets)", the 2014
version - the one that actually made it into the tree as 9c225f2655e3 -
is doing so irregardless of whether a file is seekable or not.

See

    https://lore.kernel.org/lkml/53022DB1.4070805@gmail.com/
    https://lwn.net/Articles/180387
    https://lwn.net/Articles/180396

for historic context.

The reason that it did so is, probably, that there are many files that
are marked non-seekable, but e.g. their read implementation actually
depends on knowing current position to correctly handle the read. Some
examples:

	kernel/power/user.c		snapshot_read
	fs/debugfs/file.c		u32_array_read
	fs/fuse/control.c		fuse_conn_waiting_read + ...
	drivers/hwmon/asus_atk0110.c	atk_debugfs_ggrp_read
	arch/s390/hypfs/inode.c		hypfs_read_iter
	...

Despite that, many nonseekable_open users implement read and write with
pure stream semantics - they don't depend on passed ppos at all. And for
those cases where read could wait for something inside, it creates a
situation similar to xenbus - the write could be never made to go until
read is done, and read is waiting for some, potentially external, event,
for potentially unbounded time -> deadlock.

Besides xenbus, there are 14 such places in the kernel that I've found
with semantic patch (see below):

	drivers/xen/evtchn.c:667:8-24: ERROR: evtchn_fops: .read() can deadlock .write()
	drivers/isdn/capi/capi.c:963:8-24: ERROR: capi_fops: .read() can deadlock .write()
	drivers/input/evdev.c:527:1-17: ERROR: evdev_fops: .read() can deadlock .write()
	drivers/char/pcmcia/cm4000_cs.c:1685:7-23: ERROR: cm4000_fops: .read() can deadlock .write()
	net/rfkill/core.c:1146:8-24: ERROR: rfkill_fops: .read() can deadlock .write()
	drivers/s390/char/fs3270.c:488:1-17: ERROR: fs3270_fops: .read() can deadlock .write()
	drivers/usb/misc/ldusb.c:310:1-17: ERROR: ld_usb_fops: .read() can deadlock .write()
	drivers/hid/uhid.c:635:1-17: ERROR: uhid_fops: .read() can deadlock .write()
	net/batman-adv/icmp_socket.c:80:1-17: ERROR: batadv_fops: .read() can deadlock .write()
	drivers/media/rc/lirc_dev.c:198:1-17: ERROR: lirc_fops: .read() can deadlock .write()
	drivers/leds/uleds.c:77:1-17: ERROR: uleds_fops: .read() can deadlock .write()
	drivers/input/misc/uinput.c:400:1-17: ERROR: uinput_fops: .read() can deadlock .write()
	drivers/infiniband/core/user_mad.c:985:7-23: ERROR: umad_fops: .read() can deadlock .write()
	drivers/gnss/core.c:45:1-17: ERROR: gnss_fops: .read() can deadlock .write()

In addition to the cases above another regression caused by f_pos
locking is that now FUSE filesystems that implement open with
FOPEN_NONSEEKABLE flag, can no longer implement bidirectional
stream-like files - for the same reason as above e.g. read can deadlock
write locking on file.f_pos in the kernel.

FUSE's FOPEN_NONSEEKABLE was added in 2008 in a7c1b990f715 ("fuse:
implement nonseekable open") to support OSSPD. OSSPD implements /dev/dsp
in userspace with FOPEN_NONSEEKABLE flag, with corresponding read and
write routines not depending on current position at all, and with both
read and write being potentially blocking operations:

See

    https://github.com/libfuse/osspd
    https://lwn.net/Articles/308445

    https://github.com/libfuse/osspd/blob/14a9cff0/osspd.c#L1406
    https://github.com/libfuse/osspd/blob/14a9cff0/osspd.c#L1438-L1477
    https://github.com/libfuse/osspd/blob/14a9cff0/osspd.c#L1479-L1510

Corresponding libfuse example/test also describes FOPEN_NONSEEKABLE as
"somewhat pipe-like files ..." with read handler not using offset.
However that test implements only read without write and cannot exercise
the deadlock scenario:

    https://github.com/libfuse/libfuse/blob/fuse-3.4.2-3-ga1bff7d/example/poll.c#L124-L131
    https://github.com/libfuse/libfuse/blob/fuse-3.4.2-3-ga1bff7d/example/poll.c#L146-L163
    https://github.com/libfuse/libfuse/blob/fuse-3.4.2-3-ga1bff7d/example/poll.c#L209-L216

I've actually hit the read vs write deadlock for real while implementing
my FUSE filesystem where there is /head/watch file, for which open
creates separate bidirectional socket-like stream in between filesystem
and its user with both read and write being later performed
simultaneously. And there it is semantically not easy to split the
stream into two separate read-only and write-only channels:

    https://lab.nexedi.com/kirr/wendelin.core/blob/f13aa600/wcfs/wcfs.go#L88-169

Let's fix this regression. The plan is:

1. We can't change nonseekable_open to include &~FMODE_ATOMIC_POS -
   doing so would break many in-kernel nonseekable_open users which
   actually use ppos in read/write handlers.

2. Add stream_open() to kernel to open stream-like non-seekable file
   descriptors. Read and write on such file descriptors would never use
   nor change ppos. And with that property on stream-like files read and
   write will be running without taking f_pos lock - i.e. read and write
   could be running simultaneously.

3. With semantic patch search and convert to stream_open all in-kernel
   nonseekable_open users for which read and write actually do not
   depend on ppos and where there is no other methods in file_operations
   which assume @offset access.

4. Add FOPEN_STREAM to fs/fuse/ and open in-kernel file-descriptors via
   steam_open if that bit is present in filesystem open reply.

   It was tempting to change fs/fuse/ open handler to use stream_open
   instead of nonseekable_open on just FOPEN_NONSEEKABLE flags, but
   grepping through Debian codesearch shows users of FOPEN_NONSEEKABLE,
   and in particular GVFS which actually uses offset in its read and
   write handlers

	https://codesearch.debian.net/search?q=-%3Enonseekable+%3D
	https://gitlab.gnome.org/GNOME/gvfs/blob/1.40.0-6-gcbc54396/client/gvfsfusedaemon.c#L1080
	https://gitlab.gnome.org/GNOME/gvfs/blob/1.40.0-6-gcbc54396/client/gvfsfusedaemon.c#L1247-1346
	https://gitlab.gnome.org/GNOME/gvfs/blob/1.40.0-6-gcbc54396/client/gvfsfusedaemon.c#L1399-1481

   so if we would do such a change it will break a real user.

5. Add stream_open and FOPEN_STREAM handling to stable kernels starting
   from v3.14+ (the kernel where 9c225f2655 first appeared).

   This will allow to patch OSSPD and other FUSE filesystems that
   provide stream-like files to return FOPEN_STREAM | FOPEN_NONSEEKABLE
   in their open handler and this way avoid the deadlock on all kernel
   versions. This should work because fs/fuse/ ignores unknown open
   flags returned from a filesystem and so passing FOPEN_STREAM to a
   kernel that is not aware of this flag cannot hurt. In turn the kernel
   that is not aware of FOPEN_STREAM will be < v3.14 where just
   FOPEN_NONSEEKABLE is sufficient to implement streams without read vs
   write deadlock.

This patch adds stream_open, converts /proc/xen/xenbus to it and adds
semantic patch to automatically locate in-kernel places that are either
required to be converted due to read vs write deadlock, or that are just
safe to be converted because read and write do not use ppos and there
are no other funky methods in file_operations.

Regarding semantic patch I've verified each generated change manually -
that it is correct to convert - and each other nonseekable_open instance
left - that it is either not correct to convert there, or that it is not
converted due to current stream_open.cocci limitations.

The script also does not convert files that should be valid to convert,
but that currently have .llseek = noop_llseek or generic_file_llseek for
unknown reason despite file being opened with nonseekable_open (e.g.
drivers/input/mousedev.c)

Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Yongzhi Pan <panyongzhi@gmail.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: David Vrabel <david.vrabel@citrix.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Tejun Heo <tj@kernel.org>
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Julia Lawall <Julia.Lawall@lip6.fr>
Cc: Nikolaus Rath <Nikolaus@rath.org>
Cc: Han-Wen Nienhuys <hanwen@google.com>
Signed-off-by: Kirill Smelkov <kirr@nexedi.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[ backport to 3.16: actually fixed deadlock on /proc/xen/xenbus as 581d21a2d02a was not backported to 3.16 ]
Signed-off-by: Kirill Smelkov <kirr@nexedi.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/xen/xenbus/xenbus_dev_frontend.c |   2 +-
 fs/open.c                                |  18 ++
 fs/read_write.c                          |   5 +-
 include/linux/fs.h                       |   4 +
 scripts/coccinelle/api/stream_open.cocci | 363 +++++++++++++++++++++++
 5 files changed, 389 insertions(+), 3 deletions(-)
 create mode 100644 scripts/coccinelle/api/stream_open.cocci

diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c
index 6bd06f9d737d..3126bcafb555 100644
--- a/drivers/xen/xenbus/xenbus_dev_frontend.c
+++ b/drivers/xen/xenbus/xenbus_dev_frontend.c
@@ -533,7 +533,7 @@ static int xenbus_file_open(struct inode *inode, struct file *filp)
 	if (xen_store_evtchn == 0)
 		return -ENOENT;
 
-	nonseekable_open(inode, filp);
+	stream_open(inode, filp);
 
 	u = kzalloc(sizeof(*u), GFP_KERNEL);
 	if (u == NULL)
diff --git a/fs/open.c b/fs/open.c
index fc44237e4a2e..c4949a39726a 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1104,3 +1104,21 @@ int nonseekable_open(struct inode *inode, struct file *filp)
 }
 
 EXPORT_SYMBOL(nonseekable_open);
+
+/*
+ * stream_open is used by subsystems that want stream-like file descriptors.
+ * Such file descriptors are not seekable and don't have notion of position
+ * (file.f_pos is always 0). Contrary to file descriptors of other regular
+ * files, .read() and .write() can run simultaneously.
+ *
+ * stream_open never fails and is marked to return int so that it could be
+ * directly used as file_operations.open .
+ */
+int stream_open(struct inode *inode, struct file *filp)
+{
+	filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE | FMODE_ATOMIC_POS);
+	filp->f_mode |= FMODE_STREAM;
+	return 0;
+}
+
+EXPORT_SYMBOL(stream_open);
diff --git a/fs/read_write.c b/fs/read_write.c
index 07053752c148..c3b99ff5da0d 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -549,12 +549,13 @@ EXPORT_SYMBOL(vfs_write);
 
 static inline loff_t file_pos_read(struct file *file)
 {
-	return file->f_pos;
+	return file->f_mode & FMODE_STREAM ? 0 : file->f_pos;
 }
 
 static inline void file_pos_write(struct file *file, loff_t pos)
 {
-	file->f_pos = pos;
+	if ((file->f_mode & FMODE_STREAM) == 0)
+		file->f_pos = pos;
 }
 
 SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 461e82373ebd..49ca7649e5b5 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -133,6 +133,9 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 /* Has write method(s) */
 #define FMODE_CAN_WRITE         ((__force fmode_t)0x40000)
 
+/* File is stream-like */
+#define FMODE_STREAM		((__force fmode_t)0x200000)
+
 /* File was opened by fanotify and shouldn't generate fanotify events */
 #define FMODE_NONOTIFY		((__force fmode_t)0x1000000)
 
@@ -2472,6 +2475,7 @@ extern loff_t fixed_size_llseek(struct file *file, loff_t offset,
 		int whence, loff_t size);
 extern int generic_file_open(struct inode * inode, struct file * filp);
 extern int nonseekable_open(struct inode * inode, struct file * filp);
+extern int stream_open(struct inode * inode, struct file * filp);
 
 #ifdef CONFIG_FS_XIP
 extern ssize_t xip_file_read(struct file *filp, char __user *buf, size_t len,
diff --git a/scripts/coccinelle/api/stream_open.cocci b/scripts/coccinelle/api/stream_open.cocci
new file mode 100644
index 000000000000..350145da7669
--- /dev/null
+++ b/scripts/coccinelle/api/stream_open.cocci
@@ -0,0 +1,363 @@
+// SPDX-License-Identifier: GPL-2.0
+// Author: Kirill Smelkov (kirr@nexedi.com)
+//
+// Search for stream-like files that are using nonseekable_open and convert
+// them to stream_open. A stream-like file is a file that does not use ppos in
+// its read and write. Rationale for the conversion is to avoid deadlock in
+// between read and write.
+
+virtual report
+virtual patch
+virtual explain  // explain decisions in the patch (SPFLAGS="-D explain")
+
+// stream-like reader & writer - ones that do not depend on f_pos.
+@ stream_reader @
+identifier readstream, ppos;
+identifier f, buf, len;
+type loff_t;
+@@
+  ssize_t readstream(struct file *f, char *buf, size_t len, loff_t *ppos)
+  {
+    ... when != ppos
+  }
+
+@ stream_writer @
+identifier writestream, ppos;
+identifier f, buf, len;
+type loff_t;
+@@
+  ssize_t writestream(struct file *f, const char *buf, size_t len, loff_t *ppos)
+  {
+    ... when != ppos
+  }
+
+
+// a function that blocks
+@ blocks @
+identifier block_f;
+identifier wait_event =~ "^wait_event_.*";
+@@
+  block_f(...) {
+    ... when exists
+    wait_event(...)
+    ... when exists
+  }
+
+// stream_reader that can block inside.
+//
+// XXX wait_* can be called not directly from current function (e.g. func -> f -> g -> wait())
+// XXX currently reader_blocks supports only direct and 1-level indirect cases.
+@ reader_blocks_direct @
+identifier stream_reader.readstream;
+identifier wait_event =~ "^wait_event_.*";
+@@
+  readstream(...)
+  {
+    ... when exists
+    wait_event(...)
+    ... when exists
+  }
+
+@ reader_blocks_1 @
+identifier stream_reader.readstream;
+identifier blocks.block_f;
+@@
+  readstream(...)
+  {
+    ... when exists
+    block_f(...)
+    ... when exists
+  }
+
+@ reader_blocks depends on reader_blocks_direct || reader_blocks_1 @
+identifier stream_reader.readstream;
+@@
+  readstream(...) {
+    ...
+  }
+
+
+// file_operations + whether they have _any_ .read, .write, .llseek ... at all.
+//
+// XXX add support for file_operations xxx[N] = ...	(sound/core/pcm_native.c)
+@ fops0 @
+identifier fops;
+@@
+  struct file_operations fops = {
+    ...
+  };
+
+@ has_read @
+identifier fops0.fops;
+identifier read_f;
+@@
+  struct file_operations fops = {
+    .read = read_f,
+  };
+
+@ has_read_iter @
+identifier fops0.fops;
+identifier read_iter_f;
+@@
+  struct file_operations fops = {
+    .read_iter = read_iter_f,
+  };
+
+@ has_write @
+identifier fops0.fops;
+identifier write_f;
+@@
+  struct file_operations fops = {
+    .write = write_f,
+  };
+
+@ has_write_iter @
+identifier fops0.fops;
+identifier write_iter_f;
+@@
+  struct file_operations fops = {
+    .write_iter = write_iter_f,
+  };
+
+@ has_llseek @
+identifier fops0.fops;
+identifier llseek_f;
+@@
+  struct file_operations fops = {
+    .llseek = llseek_f,
+  };
+
+@ has_no_llseek @
+identifier fops0.fops;
+@@
+  struct file_operations fops = {
+    .llseek = no_llseek,
+  };
+
+@ has_mmap @
+identifier fops0.fops;
+identifier mmap_f;
+@@
+  struct file_operations fops = {
+    .mmap = mmap_f,
+  };
+
+@ has_copy_file_range @
+identifier fops0.fops;
+identifier copy_file_range_f;
+@@
+  struct file_operations fops = {
+    .copy_file_range = copy_file_range_f,
+  };
+
+@ has_remap_file_range @
+identifier fops0.fops;
+identifier remap_file_range_f;
+@@
+  struct file_operations fops = {
+    .remap_file_range = remap_file_range_f,
+  };
+
+@ has_splice_read @
+identifier fops0.fops;
+identifier splice_read_f;
+@@
+  struct file_operations fops = {
+    .splice_read = splice_read_f,
+  };
+
+@ has_splice_write @
+identifier fops0.fops;
+identifier splice_write_f;
+@@
+  struct file_operations fops = {
+    .splice_write = splice_write_f,
+  };
+
+
+// file_operations that is candidate for stream_open conversion - it does not
+// use mmap and other methods that assume @offset access to file.
+//
+// XXX for simplicity require no .{read/write}_iter and no .splice_{read/write} for now.
+// XXX maybe_steam.fops cannot be used in other rules - it gives "bad rule maybe_stream or bad variable fops".
+@ maybe_stream depends on (!has_llseek || has_no_llseek) && !has_mmap && !has_copy_file_range && !has_remap_file_range && !has_read_iter && !has_write_iter && !has_splice_read && !has_splice_write @
+identifier fops0.fops;
+@@
+  struct file_operations fops = {
+  };
+
+
+// ---- conversions ----
+
+// XXX .open = nonseekable_open -> .open = stream_open
+// XXX .open = func -> openfunc -> nonseekable_open
+
+// read & write
+//
+// if both are used in the same file_operations together with an opener -
+// under that conditions we can use stream_open instead of nonseekable_open.
+@ fops_rw depends on maybe_stream @
+identifier fops0.fops, openfunc;
+identifier stream_reader.readstream;
+identifier stream_writer.writestream;
+@@
+  struct file_operations fops = {
+      .open  = openfunc,
+      .read  = readstream,
+      .write = writestream,
+  };
+
+@ report_rw depends on report @
+identifier fops_rw.openfunc;
+position p1;
+@@
+  openfunc(...) {
+    <...
+     nonseekable_open@p1
+    ...>
+  }
+
+@ script:python depends on report && reader_blocks @
+fops << fops0.fops;
+p << report_rw.p1;
+@@
+coccilib.report.print_report(p[0],
+  "ERROR: %s: .read() can deadlock .write(); change nonseekable_open -> stream_open to fix." % (fops,))
+
+@ script:python depends on report && !reader_blocks @
+fops << fops0.fops;
+p << report_rw.p1;
+@@
+coccilib.report.print_report(p[0],
+  "WARNING: %s: .read() and .write() have stream semantic; safe to change nonseekable_open -> stream_open." % (fops,))
+
+
+@ explain_rw_deadlocked depends on explain && reader_blocks @
+identifier fops_rw.openfunc;
+@@
+  openfunc(...) {
+    <...
+-    nonseekable_open
++    nonseekable_open /* read & write (was deadlock) */
+    ...>
+  }
+
+
+@ explain_rw_nodeadlock depends on explain && !reader_blocks @
+identifier fops_rw.openfunc;
+@@
+  openfunc(...) {
+    <...
+-    nonseekable_open
++    nonseekable_open /* read & write (no direct deadlock) */
+    ...>
+  }
+
+@ patch_rw depends on patch @
+identifier fops_rw.openfunc;
+@@
+  openfunc(...) {
+    <...
+-   nonseekable_open
++   stream_open
+    ...>
+  }
+
+
+// read, but not write
+@ fops_r depends on maybe_stream && !has_write @
+identifier fops0.fops, openfunc;
+identifier stream_reader.readstream;
+@@
+  struct file_operations fops = {
+      .open  = openfunc,
+      .read  = readstream,
+  };
+
+@ report_r depends on report @
+identifier fops_r.openfunc;
+position p1;
+@@
+  openfunc(...) {
+    <...
+    nonseekable_open@p1
+    ...>
+  }
+
+@ script:python depends on report @
+fops << fops0.fops;
+p << report_r.p1;
+@@
+coccilib.report.print_report(p[0],
+  "WARNING: %s: .read() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,))
+
+@ explain_r depends on explain @
+identifier fops_r.openfunc;
+@@
+  openfunc(...) {
+    <...
+-   nonseekable_open
++   nonseekable_open /* read only */
+    ...>
+  }
+
+@ patch_r depends on patch @
+identifier fops_r.openfunc;
+@@
+  openfunc(...) {
+    <...
+-   nonseekable_open
++   stream_open
+    ...>
+  }
+
+
+// write, but not read
+@ fops_w depends on maybe_stream && !has_read @
+identifier fops0.fops, openfunc;
+identifier stream_writer.writestream;
+@@
+  struct file_operations fops = {
+      .open  = openfunc,
+      .write = writestream,
+  };
+
+@ report_w depends on report @
+identifier fops_w.openfunc;
+position p1;
+@@
+  openfunc(...) {
+    <...
+    nonseekable_open@p1
+    ...>
+  }
+
+@ script:python depends on report @
+fops << fops0.fops;
+p << report_w.p1;
+@@
+coccilib.report.print_report(p[0],
+  "WARNING: %s: .write() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,))
+
+@ explain_w depends on explain @
+identifier fops_w.openfunc;
+@@
+  openfunc(...) {
+    <...
+-   nonseekable_open
++   nonseekable_open /* write only */
+    ...>
+  }
+
+@ patch_w depends on patch @
+identifier fops_w.openfunc;
+@@
+  openfunc(...) {
+    <...
+-   nonseekable_open
++   stream_open
+    ...>
+  }
+
+
+// no read, no write - don't change anything


  parent reply	other threads:[~2019-07-07 19:39 UTC|newest]

Thread overview: 138+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-07 16:54 [PATCH 3.16 000/129] 3.16.70-rc1 review Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 009/129] clk: vf610: fix refcount leak in vf610_clocks_init() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 091/129] Btrfs: fix corruption reading shared and compressed extents after hole punching Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 008/129] clk: imx6sx: fix refcount leak in imx6sx_clocks_init() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 033/129] pinctrl: sh-pfc: r8a7778: Fix HSPI pin numbers and names Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 114/129] It's wrong to add len to sector_nr in raid10 reshape twice Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 110/129] route: set the deleted fnhe fnhe_daddr to 0 in ip_del_fnhe to fix a race Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 037/129] mtd: docg3: Don't leak docg3->bbt in error path Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 048/129] USB: serial: cp210x: add ID for Ingenico 3070 Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 074/129] perf header: Fix wrong node write in NUMA_TOPOLOGY feature Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 061/129] pinctrl: sh-pfc: r8a7791: Fix scifb2_data_c pin group Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 077/129] KVM: x86/mmu: Do not cache MMIO accesses while memslots are in flux Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 040/129] tty: ipwireless: Fix potential NULL pointer dereference Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 080/129] powerpc/83xx: Also save/restore SPRG4-7 during suspend Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 095/129] powerpc/32: Clear on-stack exception marker upon exception return Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 128/129] mwifiex: Fix heap overflow in mwifiex_uap_parse_tail_ies() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 106/129] net/hsr: fix possible crash in add_timer() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 035/129] applicom: Fix potential Spectre v1 vulnerabilities Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 081/129] powerpc/wii: properly disable use of BATs when requested Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 026/129] media: s5p-jpeg: Check for fmt_ver_flag when doing fmt enumeration Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 119/129] l2tp: fix infoleak in l2tp_ip6_recvmsg() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 093/129] NFSv4.1: Reinitialise sequence results before retransmitting a request Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 065/129] tpm/tpm_i2c_atmel: Return -E2BIG when the transfer is incomplete Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 105/129] scsi: virtio_scsi: don't send sc payload with tmfs Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 075/129] drm/radeon/evergreen_cs: fix missing break in switch statement Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 005/129] clk: socfpga: fix refcount leak Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 078/129] fs/nfs: Fix nfs_parse_devname to not modify it's argument Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 079/129] irqchip/brcmstb-l2: Use _irqsave locking variants in non-interrupt code Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 113/129] kernel/sysctl.c: add missing range check in do_proc_dointvec_minmax_conv Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 003/129] staging: iio: adt7316: allow adt751x to use internal vref for all dacs Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 052/129] rtc: 88pm80x: fix unintended sign extension Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 010/129] clk: armada-370: fix refcount leak in a370_clk_init() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 071/129] ASoC: fsl_esai: fix register setting issue in RIGHT_J mode Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 117/129] net/mlx4_core: Fix locking in SRIOV mode when switching between events and polling Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 017/129] staging: iio: adt7316: fix the dac write calculation Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 094/129] 9p: use inode->i_lock to protect i_size_write() under 32-bit Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 013/129] clk: dove: fix refcount leak in dove_clk_init() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 045/129] splice: don't merge into linked buffers Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 023/129] selinux: avoid silent denials in permissive mode under RCU walk Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 086/129] ALSA: bebob: use more identical mod_alias for Saffire Pro 10 I/O against Liquid Saffire 56 Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 064/129] iscsi_ibft: Fix missing break in switch statement Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 098/129] CIFS: Do not reset lease state to NONE on lease break Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 047/129] rtc: ds1672: fix unintended sign extension Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 076/129] ASoC: fsl: Fix of-node refcount unbalance in fsl_ssi_probe_from_dt() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 025/129] powerpc/irq: drop arch_early_irq_init() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 089/129] regulator: wm831x-dcdc: Fix list of wm831x_dcdc_ilim from mA to uA Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 100/129] CIFS: Fix read after write for files with read caching Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 019/129] ARM: s3c24xx: Fix boolean expressions in osiris_dvs_notify Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 116/129] net: sh_eth: fix a missing check of of_get_phy_mode Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 024/129] crypto: pcbc - remove bogus memcpy()s with src == dest Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 088/129] serial: 8250_of: assume reg-shift of 2 for mrvl,mmp-uart Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 030/129] crypto: tgr192 - fix unaligned memory access Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 004/129] clk: highbank: fix refcount leak in hb_clk_init() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 092/129] tools lib traceevent: Fix buffer overflow in arg_eval Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 027/129] media: s5p-jpeg: Correct step and max values for V4L2_CID_JPEG_RESTART_INTERVAL Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 058/129] ext4: update quota information while swapping boot loader inode Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 044/129] crypto: arm64/aes-ccm - fix logical bug in AAD MAC handling Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 111/129] vxlan: test dev->flags & IFF_UP before calling gro_cells_receive() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 101/129] mm/vmalloc: fix size check for remap_vmalloc_range_partial() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 001/129] staging: iio: adt7316: fix register and bit definitions Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 068/129] serial: 8250_pci: Have ACCES cards that use the four port Pericom PI7C9X7954 chip use the pci_pericom_setup() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 115/129] md: Fix failed allocation of md_register_thread Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 011/129] clk: kirkwood: fix refcount leak in kirkwood_clk_init() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 029/129] crypto: hash - set CRYPTO_TFM_NEED_KEY if ->setkey() fails Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 007/129] clk: imx6q: fix refcount leak in imx6q_clocks_init() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 108/129] lib/div64.c: off by one in shift Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 018/129] drm: Fix error handling in drm_legacy_addctx Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 112/129] gro_cells: make sure device is up in gro_cells_receive() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 002/129] staging: iio: adt7316: invert the logic of the check for an ldac pin Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 038/129] mtd: docg3: Fix kasprintf() usage Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 042/129] devres: always use dev_name() in devm_ioremap_resource() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 039/129] mtd: docg3: Fix passing zero to 'PTR_ERR' warning in doc_probe_device Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 049/129] media: uvcvideo: Avoid NULL pointer dereference at the end of streaming Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 072/129] cdc-wdm: pass return value of recover_from_urb_loss Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 118/129] net/mlx4_core: Fix qp mtt size calculation Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 070/129] USB: serial: ftdi_sio: add ID for Hjelmslund Electronics USB485 Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 129/129] netns: provide pure entropy for net_hash_mix() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 099/129] nfsd: fix memory corruption caused by readdir Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 096/129] net-sysfs: Fix mem leak in netdev_register_kobject Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 082/129] clocksource/drivers/exynos_mct: Fix error path in timer resources initialization Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 103/129] mm, swap: bounds check swap_info array accesses to avoid NULL derefs Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 087/129] staging: android: ashmem: Avoid range_alloc() allocation with ashmem_mutex held Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 066/129] tpm: Fix off-by-one when reading binary_bios_measurements Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 021/129] RDMA/ocrdma: Fix out of bounds index check in query pkey Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 016/129] staging: iio: adt7316: fix the dac read calculation Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 053/129] rtc: pm8xxx: fix unintended sign extension Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 034/129] hpet: Fix missing '=' character in the __setup() code of hpet_mmap_enable Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 104/129] s390/virtio: handle find on invalid queue gracefully Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 107/129] cpufreq: pxa2xx: remove incorrect __init annotation Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 028/129] media: v4l2: i2c: ov7670: Fix PLL bypass register values Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 083/129] mmc: omap: fix the maximum timeout setting Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 043/129] crypto: testmgr - skip crc32c context test for ahash algorithms Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 056/129] jbd2: clear dirty flag when revoking a buffer from an older transaction Ben Hutchings
2019-07-07 16:54 ` Ben Hutchings [this message]
2019-07-07 16:54 ` [PATCH 3.16 015/129] staging: iio: adt7316: fix handling of dac high resolution option Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 123/129] fuse: Add FOPEN_STREAM to use stream_open() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 127/129] mwifiex: Abort at too short BSS descriptor element Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 062/129] pinctrl: sh-pfc: sh73a0: Fix fsic_spdif pin groups Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 090/129] powerpc/powernv: Make opal log only readable by root Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 051/129] rtc: 88pm860x: fix unintended sign extension Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 060/129] parport_pc: fix find_superio io compare code, should use equal test Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 063/129] ext4: fix crash during online resizing Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 055/129] bcache: treat stale && dirty keys as bad keys Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 109/129] xen, cpu_hotplug: Prevent an out of bounds access Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 073/129] libertas_tf: don't set URB_ZERO_PACKET on IN USB transfer Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 036/129] rcu: Do RCU GP kthread self-wakeup from softirq and interrupt Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 050/129] crypto: ahash - fix another early termination in hash walk Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 125/129] media: uvcvideo: Fix 'type' check leading to overflow Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 126/129] mwifiex: Fix possible buffer overflows at parsing bss descriptor Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 012/129] clk: armada-xp: fix refcount leak in axp_clk_init() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 014/129] staging: iio: adt7316: fix dac_bits assignment Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 057/129] ext4: fix check of inode in swap_inode_boot_loader Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 069/129] leds: lp55xx: fix null deref on firmware load failure Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 102/129] mm: fix potential data race in SyS_swapon Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 124/129] binder: Replace "%p" with "%pK" for stable Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 121/129] tcp: refine memory limit test in tcp_fragment() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 022/129] security/selinux: pass 'flags' arg to avc_audit() and avc_has_perm_flags() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 120/129] pptp: dst_release sk_dst_cache in pptp_sock_destruct Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 084/129] btrfs: init csum_list before possible free Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 046/129] scsi: target/iscsi: Avoid iscsit_release_commands_from_conn() deadlock Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 085/129] powerpc/mm/hash: Handle mmap_min_addr correctly in get_unmapped_area topdown search Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 020/129] IB/usnic: Fix out of bounds index check in query pkey Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 059/129] ext4: add mask of ext4 flags to swap Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 032/129] m68k: Add -ffreestanding to CFLAGS Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 054/129] bcache: never writeback a discard operation Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 097/129] ip6mr: Do not call __IP6_INC_STATS() from preemptible context Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 067/129] serial: 8250_pci: Fix number of ports for ACCES serial cards Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 031/129] ASoC: imx-sgtl5000: put of nodes if finding codec fails Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 006/129] clk: samsung: exynos4: fix refcount leak in exynos4_get_xom() Ben Hutchings
2019-07-07 16:54 ` [PATCH 3.16 041/129] ext2: Fix underflow in ext2_max_size() Ben Hutchings
2019-07-08 11:05 ` [PATCH 3.16 000/129] 3.16.70-rc1 review Guenter Roeck
2019-07-08 15:21   ` Ben Hutchings
2019-07-08 13:05 ` Luke Nowakowski-Krijger
2019-07-08 15:29   ` Ben Hutchings
2019-07-08 20:21     ` Luke Nowakowski-Krijger
2019-07-08 13:43 ` Amol Surati
2019-07-09 18:07 ` Guenter Roeck
2019-07-09 18:09   ` Ben Hutchings

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=lsq.1562518457.714019616@decadent.org.uk \
    --to=ben@decadent.org.uk \
    --cc=Julia.Lawall@lip6.fr \
    --cc=Nikolaus@rath.org \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=corbet@lwn.net \
    --cc=david.vrabel@citrix.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=hanwen@google.com \
    --cc=hch@lst.de \
    --cc=jgross@suse.com \
    --cc=kda@linux-powerpc.org \
    --cc=kirr@nexedi.com \
    --cc=ktkhai@virtuozzo.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=mtk.manpages@gmail.com \
    --cc=panyongzhi@gmail.com \
    --cc=stable@vger.kernel.org \
    --cc=tj@kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).