aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/seq
Commit message (Collapse)AuthorAge
* ALSA: seq: fill client ID in return value of pool operationTakashi Sakamoto2015-04-11
| | | | | | | | | | | The returned value of 'get/seq client pool' operation has zeroed value for its client ID, against requested client ID. This commit fix the bug by filling it with index value of referred client object. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Fix init order of snd_seq_device stuffTakashi Iwai2015-03-11
| | | | | | | | | | | When the sequencer driver is built in kernel, it may panic at boot because of the uninitialized snd_seq_bus_type. Initialize it properly via subsys_initcall() instead of module_init() to assure that the bus is registered beforehand. Reported-by: Fengguang Wu <fengguang.wu@intel.com> Fixes: 7c37ae5c625a ('ALSA: seq: Rewrite sequencer device binding with standard bus') Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Drop superfluous error/debug messages after malloc failuresTakashi Iwai2015-03-10
| | | | | | | | The kernel memory allocators already report the errors when the requested allocation fails, thus we don't need to warn it again in each caller side. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq_oss: Drop superfluous error/debug messages after malloc failuresTakashi Iwai2015-03-10
| | | | | | | | The kernel memory allocators already report the errors when the requested allocation fails, thus we don't need to warn it again in each caller side. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Drop snd_seq_autoload_lock() and _unlock()Takashi Iwai2015-02-12
| | | | | | | | The autoload lock became already superfluous due to the recent rework of autoload code. Let's drop them now. This allows us to simplify a few codes nicely. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Define driver object in each driverTakashi Iwai2015-02-12
| | | | | | | | | | | | | This patch moves the driver object initialization and allocation to each driver's module init/exit code like other normal drivers. The snd_seq_driver struct is now published in seq_device.h, and each driver is responsible to define it with proper driver attributes (name, probe and remove) with snd_seq_driver specific attributes as id and argsize fields. The helper functions snd_seq_driver_register(), snd_seq_driver_unregister() and module_snd_seq_driver() are used for simplifying codes. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Clean up device and driver structsTakashi Iwai2015-02-12
| | | | | | | | Use const string pointer instead of copying the id string to each object. Also drop the status and list fields of snd_seq_device struct that are no longer used. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Rewrite sequencer device binding with standard busTakashi Iwai2015-02-12
| | | | | | | | | | | | | | | | | | | We've used the old house-made code for binding the sequencer device and driver. This can be far better implemented with the standard bus nowadays. This patch refactors the whole sequencer binding code with the bus /sys/bus/snd_seq. The devices appear as id-card-device on this bus and are bound with the drivers corresponding to the given id like the former implementation. The module autoload is also kept like before. There is no change in API functions by this patch, and almost all transitions are kept inside seq_device.c. The proc file output will change slightly but kept compatible as much as possible. Further integration works will follow in later patches. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Don't compile snd_seq_device_load_drivers() for built-inTakashi Iwai2015-02-12
| | | | Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Move EXPORT_SYMBOL() after each functionTakashi Iwai2015-02-12
| | | | | | ... to follow the standard coding style. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: potential out of bounds in do_control()Dan Carpenter2015-02-12
| | | | | | | | | | | | | | | | | Smatch complains that "control" is user specifigy and needs to be capped. The call tree to understand this warning is quite long. snd_seq_write() <-- get the event from the user snd_seq_client_enqueue_event() snd_seq_deliver_event() deliver_to_subscribers() snd_seq_deliver_single_event() snd_opl3_oss_event_input() snd_midi_process_event() do_control() Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* Merge branch 'topic/snd-device' into for-nextTakashi Iwai2015-02-03
|\
| * ALSA: Simplify snd_device_register() variantsTakashi Iwai2015-02-02
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Now that all callers have been replaced with snd_device_register_for_dev(), let's drop the obsolete device registration code and concentrate only on the code handling struct device directly. That said, - remove the old snd_device_register(), - rename snd_device_register_for_dev() with snd_device_register(), - drop superfluous arguments from snd_device_register(), - change snd_unregister_device() to pass the device pointer directly Reviewed-by: Jaroslav Kysela <perex@perex.cz> Signed-off-by: Takashi Iwai <tiwai@suse.de>
| * ALSA: seq: Handle the device directlyTakashi Iwai2015-02-02
| | | | | | | | | | | | | | | | | | Like the previous change for the timer device, this patch changes the device management for the ALSA sequencer device using the struct device directly. Reviewed-by: Jaroslav Kysela <perex@perex.cz> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* | ALSA: seq: remove unused callback_all fieldClemens Ladisch2015-01-26
| | | | | | | | | | Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* | ALSA: seq: fix off-by-one error in port limit checkClemens Ladisch2015-01-26
| | | | | | | | | | Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* | ALSA: seq: correctly report maximum number of portsClemens Ladisch2015-01-26
| | | | | | | | | | | | | | | | Due to SNDRV_SEQ_ADDRESS_BROADCAST, not all 256 port number values can be used. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* | Merge branch 'for-linus' into for-nextTakashi Iwai2015-01-26
|\| | | | | | | | | Sync with the latest 3.19-rc state for applying other ALSA sequencer core fixes.
| * ALSA: seq-dummy: remove deadlock-causing events on closeClemens Ladisch2015-01-26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When the last subscriber to a "Through" port has been removed, the subscribed destination ports might still be active, so it would be wrong to send "all sounds off" and "reset controller" events to them. The proper place for such a shutdown would be the closing of the actual MIDI port (and close_substream() in rawmidi.c already can do this). This also fixes a deadlock when dummy_unuse() tries to send events to its own port that is already locked because it is being freed. Reported-by: Peter Billam <peter@www.pjb.com.au> Cc: <stable@vger.kernel.org> Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* | ALSA: seq: Deletion of unnecessary checks before the function call ↵Markus Elfring2015-01-04
|/ | | | | | | | | | | | "snd_midi_event_free" The snd_midi_event_free() function tests whether its argument is NULL and then returns immediately. Thus the test around the call is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring <elfring@users.sourceforge.net> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: core: Deletion of unnecessary checks before two function callsMarkus Elfring2014-11-21
| | | | | | | | | | The functions snd_seq_oss_timer_delete() and vunmap() perform also input parameter validation. Thus the test around the call is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring <elfring@users.sourceforge.net> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* Subject: ALSA: seq: Remove autoload locks in driver registrationTakashi Iwai2014-10-18
| | | | | | | | | | Since we're calling request_module() asynchronously now, we can get rid of the autoload lock in snd_seq_device_register_driver(), as well as in the snd-seq driver registration itself. This enables the automatic loading of dependent sequencer modules, such as snd-seq-virmidi from snd-emu10k1-synth. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: bind seq driver automaticallyTakashi Iwai2014-10-18
| | | | | | | | | | | | | | | | | | | | | | | | Currently the sequencer module binding is performed independently from the card module itself. The reason behind it is to keep the sequencer stuff optional and allow the system running without it (e.g. for using PCM or rawmidi only). This works in most cases, but a remaining problem is that the binding isn't done automatically when a new driver module is probed. Typically this becomes visible when a hotplug driver like usb audio is used. This patch tries to address this and other potential issues. First, the seq-binder (seq_device.c) tries to load a missing driver module at creating a new device object. This is done asynchronously in a workq for avoiding the deadlock (modprobe call in module init path). This action, however, should be enabled only when the sequencer stuff was already initialized, i.e. snd-seq module was already loaded. For that, a new function, snd_seq_autoload_init() is introduced here; this clears the blocking of autoloading, and also tries to load all pending driver modules. Reported-by: Adam Goode <agoode@chromium.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Use atomic ops for autoload refcountTakashi Iwai2014-10-15
| | | | | | ... just to robustify for races. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: seq_memory.c: Fix closing brace followed by ifRasmus Villemoes2014-06-23
| | | | | | | Add a newline and, while at it, remove a space and redundant braces. Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Continue broadcasting events to ports if one of them failsAdam Goode2014-06-04
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Sometimes PORT_EXIT messages are lost when a process is exiting. This happens if you subscribe to the announce port with client A, then subscribe to the announce port with client B, then kill client A. Client B will not see the PORT_EXIT message because client A's port is closing and is earlier in the announce port subscription list. The for each loop will try to send the announcement to client A and fail, then will stop trying to broadcast to other ports. Killing B works fine since the announcement will already have gone to A. The CLIENT_EXIT message does not get lost. How to reproduce problem: *** termA $ aseqdump -p 0:1 0:1 Port subscribed 0:1 -> 128:0 *** termB $ aseqdump -p 0:1 *** termA 0:1 Client start client 129 0:1 Port start 129:0 0:1 Port subscribed 0:1 -> 129:0 *** termB 0:1 Port subscribed 0:1 -> 129:0 *** termA ^C *** termB 0:1 Client exit client 128 <--- expected Port exit as well (before client exit) Signed-off-by: Adam Goode <agoode@google.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: correctly detect input buffer overflowAdam Goode2014-06-04
| | | | | | | | | | snd_seq_event_dup returns -ENOMEM in some buffer-full conditions, but usually returns -EAGAIN. Make -EAGAIN trigger the overflow condition in snd_seq_fifo_event_in so that the fifo is cleared and -ENOSPC is returned to userspace as stated in the alsa-lib docs. Signed-off-by: Adam Goode <agoode@google.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: core: Fix format string mismatch in seq_midi.cMasanari Iida2014-04-28
| | | | | | | | Fix format string mismatch in snd_seq_midisynth_register_port(). Argument type of p is unsigned int. Signed-off-by: Masanari Iida <standby24x7@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq_oss: Use standard printk helpersTakashi Iwai2014-02-14
| | | | | | Use the standard pr_xxx() helpers instead of home-baked snd_print*(). Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Use standard printk helpersTakashi Iwai2014-02-14
| | | | | | Use the standard pr_xxx() helpers instead of home-baked snd_print*(). Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: core: Use standard printk helpersTakashi Iwai2014-02-14
| | | | | | | Use dev_err() & co as much as possible. If not available (no device assigned at the calling point), use pr_xxx() helpers instead. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq_oss: Drop debug printsTakashi Iwai2014-02-14
| | | | | | | The debug prints in snd-seq-oss module are rather useless. Let's clean up before further modifications. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: Drop unused name argument in snd_register_oss_device()Takashi Iwai2014-02-12
| | | | | | | The last argument, name, of snd_oss_register_device() is nowhere referred in the function in the current code. Let's drop it. Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq-oss: Initialize MIDI clients asynchronouslyTakashi Iwai2013-07-17
| | | | | | | | | | | | | | | | We've got bug reports that the module loading stuck on Debian system with 3.10 kernel. The debugging session revealed that the initial registration of OSS sequencer clients stuck at module loading time, which involves again with request_module() at the init phase. This is triggered only by special --install stuff Debian is using, but it's still not good to have such loops. As a workaround, call the registration part asynchronously. This is a better approach irrespective of the hang fix, in anyway. Reported-and-tested-by: Philipp Matthias Hahn <pmhahn@pmhahn.de> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: Fix missing error handling in snd_seq_timer_open()Takashi Iwai2013-03-11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | snd_seq_timer_open() didn't catch the whole error path but let through if the timer id is a slave. This may lead to Oops by accessing the uninitialized pointer. BUG: unable to handle kernel NULL pointer dereference at 00000000000002ae IP: [<ffffffff819b3477>] snd_seq_timer_open+0xe7/0x130 PGD 785cd067 PUD 76964067 PMD 0 Oops: 0002 [#4] SMP CPU 0 Pid: 4288, comm: trinity-child7 Tainted: G D W 3.9.0-rc1+ #100 Bochs Bochs RIP: 0010:[<ffffffff819b3477>] [<ffffffff819b3477>] snd_seq_timer_open+0xe7/0x130 RSP: 0018:ffff88006ece7d38 EFLAGS: 00010246 RAX: 0000000000000286 RBX: ffff88007851b400 RCX: 0000000000000000 RDX: 000000000000ffff RSI: ffff88006ece7d58 RDI: ffff88006ece7d38 RBP: ffff88006ece7d98 R08: 000000000000000a R09: 000000000000fffe R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 R13: ffff8800792c5400 R14: 0000000000e8f000 R15: 0000000000000007 FS: 00007f7aaa650700(0000) GS:ffff88007f800000(0000) GS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000002ae CR3: 000000006efec000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process trinity-child7 (pid: 4288, threadinfo ffff88006ece6000, task ffff880076a8a290) Stack: 0000000000000286 ffffffff828f2be0 ffff88006ece7d58 ffffffff810f354d 65636e6575716573 2065756575712072 ffff8800792c0030 0000000000000000 ffff88006ece7d98 ffff8800792c5400 ffff88007851b400 ffff8800792c5520 Call Trace: [<ffffffff810f354d>] ? trace_hardirqs_on+0xd/0x10 [<ffffffff819b17e9>] snd_seq_queue_timer_open+0x29/0x70 [<ffffffff819ae01a>] snd_seq_ioctl_set_queue_timer+0xda/0x120 [<ffffffff819acb9b>] snd_seq_do_ioctl+0x9b/0xd0 [<ffffffff819acbe0>] snd_seq_ioctl+0x10/0x20 [<ffffffff811b9542>] do_vfs_ioctl+0x522/0x570 [<ffffffff8130a4b3>] ? file_has_perm+0x83/0xa0 [<ffffffff810f354d>] ? trace_hardirqs_on+0xd/0x10 [<ffffffff811b95ed>] sys_ioctl+0x5d/0xa0 [<ffffffff813663fe>] ? trace_hardirqs_on_thunk+0x3a/0x3f [<ffffffff81faed69>] system_call_fastpath+0x16/0x1b Reported-and-tested-by: Tommi Rantala <tt.rantala@gmail.com> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: seq: seq_oss_event: missing range checksDan Carpenter2013-03-04
| | | | | | | | | | | | | | | | | | The "dev" variable could be out of bounds. Calling snd_seq_oss_synth_is_valid() checks that it is is a valid device which has been opened. We check this inside set_note_event() so this function can't succeed without a valid "dev". But we need to do the check earlier to prevent invalid dereferences and memory corruption. One call tree where "dev" could be out of bounds is: -> snd_seq_oss_oob_user() -> snd_seq_oss_process_event() -> extended_event() -> note_on_event() Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* various: Fix spelling of "registered" in comments.Adam Buchbinder2012-11-19
| | | | | | | Some comments misspell "registered"; this fixes them. No code changes. Signed-off-by: Adam Buchbinder <adam.buchbinder@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
* ALSA: lto, sound: Fix export symbols for !CONFIG_MODULESAndi Kleen2012-08-20
| | | | | | | | | The new LTO EXPORT_SYMBOL references symbols even without CONFIG_MODULES. Since these functions are macros in this case this doesn't work. Add a ifdef to fix the build. Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* Documentation: remove references to /etc/modprobe.confLucas De Marchi2012-03-30
| | | | | | | | | | | | | | | | Usage of /etc/modprobe.conf file was deprecated by module-init-tools and is no longer parsed by new kmod tool. References to this file are replaced in Documentation, comments and Kconfig according to the context. There are also some references to the old /etc/modules.conf from 2.4 kernels that are being removed. Signed-off-by: Lucas De Marchi <lucas.demarchi@profusion.mobi> Acked-by: Takashi Iwai <tiwai@suse.de> Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Randy Dunlap <rdunlap@xenotime.net> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
* device.h: cleanup users outside of linux/include (C files)Paul Gortmaker2012-03-11
| | | | | | | | | | | | | | For files that are actively using linux/device.h, make sure that they call it out. This will allow us to clean up some of the implicit uses of linux/device.h within include/* without introducing build regressions. Yes, this was created by "cheating" -- i.e. the headers were cleaned up, and then the fallout was found and fixed, and then the two commits were reordered. This ensures we don't introduce build regressions into the git history. Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
* ALSA: module_param: make bool parameters really boolRusty Russell2011-12-19
| | | | | | | | | | | | module_param(bool) used to counter-intuitively take an int. In fddd5201 (mid-2009) we allowed bool or int/unsigned int using a messy trick. It's time to remove the int/unsigned int option. For this version it'll simply give a warning, but it'll break next kernel version. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* sound: Add export.h for THIS_MODULE/EXPORT_SYMBOL where neededPaul Gortmaker2011-10-31
| | | | | | | | These aren't modules, but they do make use of these macros, so they will need export.h to get that definition. Previously, they got it via the implicit module.h inclusion. Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
* sound: Add module.h to the previously silent sound usersPaul Gortmaker2011-10-31
| | | | | | | | Lots of sound drivers were getting module.h via the implicit presence of it in <linux/device.h> but we are going to clean that up. So fix up those users now. Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
* sound: fix drivers needing module.h not moduleparam.hPaul Gortmaker2011-10-31
| | | | | | | | | The implicit presence of module.h lured several users into incorrectly thinking that they only needed/used modparam.h but once we clean up the module.h presence, these will show up as build failures, so fix 'em now. Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
* ALSA: core: remove unused variables.Luca Tettamanti2011-05-26
| | | | | | | Drop a few variables that are never read. Signed-off-by: Luca Tettamanti <kronos.it@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* Fix common misspellingsLucas De Marchi2011-03-31
| | | | | | Fixes generated by 'codespell' and manually reviewed. Signed-off-by: Lucas De Marchi <lucas.demarchi@profusion.mobi>
* sound:core:seq:seq_ports.c Remove one to many n's in a word.Justin P. Mattock2011-02-27
| | | | | | | The Patch below removes one to many "n's" in a word.. Signed-off-by: Justin P. Mattock <justinmattock@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: core: sparse cleanupsClemens Ladisch2011-02-14
| | | | | | | | | Change the core code where sparse complains. In most cases, this means just adding annotations to confirm that we indeed want to do the dirty things we're doing. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* ALSA: support module on-demand loading for seq and timerKay Sievers2010-11-23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If CONFIG_SND_DYNAMIC_MINORS is used, assign /dev/snd/seq and /dev/snd/timer the usual static minors, and export specific module aliases to generate udev module on-demand loading instructions: $ cat /lib/modules/2.6.33.4-smp/modules.devname # Device nodes to trigger on-demand module loading. microcode cpu/microcode c10:184 fuse fuse c10:229 ppp_generic ppp c108:0 tun net/tun c10:200 uinput uinput c10:223 dm_mod mapper/control c10:236 snd_timer snd/timer c116:33 snd_seq snd/seq c116:1 The last two lines instruct udev to create device nodes, even when the modules are not loaded at that time. As soon as userspace accesses any of these nodes, the in-kernel module-loader will load the module, and the device can be used. The header file minor calculation needed to be simplified to make __stringify() (supports only two indirections) in the MODULE_ALIAS macro work. This is part of systemd's effort to get rid of unconditional module load instructions and needless init scripts. Cc: Lennart Poettering <lennart@poettering.net> Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
* llseek: automatically add .llseek fopArnd Bergmann2010-10-15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | All file_operations should get a .llseek operation so we can make nonseekable_open the default for future file operations without a .llseek pointer. The three cases that we can automatically detect are no_llseek, seq_lseek and default_llseek. For cases where we can we can automatically prove that the file offset is always ignored, we use noop_llseek, which maintains the current behavior of not returning an error from a seek. New drivers should normally not use noop_llseek but instead use no_llseek and call nonseekable_open at open time. Existing drivers can be converted to do the same when the maintainer knows for certain that no user code relies on calling seek on the device file. The generated code is often incorrectly indented and right now contains comments that clarify for each added line why a specific variant was chosen. In the version that gets submitted upstream, the comments will be gone and I will manually fix the indentation, because there does not seem to be a way to do that using coccinelle. Some amount of new code is currently sitting in linux-next that should get the same modifications, which I will do at the end of the merge window. Many thanks to Julia Lawall for helping me learn to write a semantic patch that does all this. ===== begin semantic patch ===== // This adds an llseek= method to all file operations, // as a preparation for making no_llseek the default. // // The rules are // - use no_llseek explicitly if we do nonseekable_open // - use seq_lseek for sequential files // - use default_llseek if we know we access f_pos // - use noop_llseek if we know we don't access f_pos, // but we still want to allow users to call lseek // @ open1 exists @ identifier nested_open; @@ nested_open(...) { <+... nonseekable_open(...) ...+> } @ open exists@ identifier open_f; identifier i, f; identifier open1.nested_open; @@ int open_f(struct inode *i, struct file *f) { <+... ( nonseekable_open(...) | nested_open(...) ) ...+> } @ read disable optional_qualifier exists @ identifier read_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; expression E; identifier func; @@ ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off) { <+... ( *off = E | *off += E | func(..., off, ...) | E = *off ) ...+> } @ read_no_fpos disable optional_qualifier exists @ identifier read_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; @@ ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off) { ... when != off } @ write @ identifier write_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; expression E; identifier func; @@ ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off) { <+... ( *off = E | *off += E | func(..., off, ...) | E = *off ) ...+> } @ write_no_fpos @ identifier write_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; @@ ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off) { ... when != off } @ fops0 @ identifier fops; @@ struct file_operations fops = { ... }; @ has_llseek depends on fops0 @ identifier fops0.fops; identifier llseek_f; @@ struct file_operations fops = { ... .llseek = llseek_f, ... }; @ has_read depends on fops0 @ identifier fops0.fops; identifier read_f; @@ struct file_operations fops = { ... .read = read_f, ... }; @ has_write depends on fops0 @ identifier fops0.fops; identifier write_f; @@ struct file_operations fops = { ... .write = write_f, ... }; @ has_open depends on fops0 @ identifier fops0.fops; identifier open_f; @@ struct file_operations fops = { ... .open = open_f, ... }; // use no_llseek if we call nonseekable_open //////////////////////////////////////////// @ nonseekable1 depends on !has_llseek && has_open @ identifier fops0.fops; identifier nso ~= "nonseekable_open"; @@ struct file_operations fops = { ... .open = nso, ... +.llseek = no_llseek, /* nonseekable */ }; @ nonseekable2 depends on !has_llseek @ identifier fops0.fops; identifier open.open_f; @@ struct file_operations fops = { ... .open = open_f, ... +.llseek = no_llseek, /* open uses nonseekable */ }; // use seq_lseek for sequential files ///////////////////////////////////// @ seq depends on !has_llseek @ identifier fops0.fops; identifier sr ~= "seq_read"; @@ struct file_operations fops = { ... .read = sr, ... +.llseek = seq_lseek, /* we have seq_read */ }; // use default_llseek if there is a readdir /////////////////////////////////////////// @ fops1 depends on !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier readdir_e; @@ // any other fop is used that changes pos struct file_operations fops = { ... .readdir = readdir_e, ... +.llseek = default_llseek, /* readdir is present */ }; // use default_llseek if at least one of read/write touches f_pos ///////////////////////////////////////////////////////////////// @ fops2 depends on !fops1 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read.read_f; @@ // read fops use offset struct file_operations fops = { ... .read = read_f, ... +.llseek = default_llseek, /* read accesses f_pos */ }; @ fops3 depends on !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier write.write_f; @@ // write fops use offset struct file_operations fops = { ... .write = write_f, ... + .llseek = default_llseek, /* write accesses f_pos */ }; // Use noop_llseek if neither read nor write accesses f_pos /////////////////////////////////////////////////////////// @ fops4 depends on !fops1 && !fops2 && !fops3 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read_no_fpos.read_f; identifier write_no_fpos.write_f; @@ // write fops use offset struct file_operations fops = { ... .write = write_f, .read = read_f, ... +.llseek = noop_llseek, /* read and write both use no f_pos */ }; @ depends on has_write && !has_read && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier write_no_fpos.write_f; @@ struct file_operations fops = { ... .write = write_f, ... +.llseek = noop_llseek, /* write uses no f_pos */ }; @ depends on has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read_no_fpos.read_f; @@ struct file_operations fops = { ... .read = read_f, ... +.llseek = noop_llseek, /* read uses no f_pos */ }; @ depends on !has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; @@ struct file_operations fops = { ... +.llseek = noop_llseek, /* no read or write fn */ }; ===== End semantic patch ===== Signed-off-by: Arnd Bergmann <arnd@arndb.de> Cc: Julia Lawall <julia@diku.dk> Cc: Christoph Hellwig <hch@infradead.org>