saner FASYNC handling on file close
Subsystems (27)
Al Viro
maintainerRFC PATCH 1/1 saner FASYNC handling on file close
As it is, all instances of ->release() for files that have
->fasync() need to remember to evict file from fasync lists; forgetting that creates a hole and we actually have a bunch that *does* forget.
So let's keep our lives simple - let __fput() check FASYNC infile->f_flags and call ->fasync() there if it's been set. And lose that crap in ->release() instances - leaving it there is still valid, but we don't have to bother anymore.
Comments?
---
arch/ia64/kernel/perfmon.c +0 -5
@@ -1995,11 +1995,6 @@ pfm_close(struct inode *inode, struct file *filp)return -EBADF ; } -if (filp->f_flags &FASYNC ) { -DPRINT (("cleaning up async_queue=%p\n" , ctx->ctx_async_queue)); -pfm_do_fasync (-1 , filp, ctx,0 ); - } -PROTECT_CTX (ctx, flags); state = ctx->ctx_state;
drivers/char/hpet.c +0 -3
@@ -427,9 +427,6 @@ static int hpet_release(struct inode *inode, struct file *file)if (irq)free_irq (irq, devp); -if (file->f_flags &FASYNC ) -hpet_fasync (-1 , file,0 ); - file->private_data =NULL ;return 0 ; }
drivers/char/ipmi/ipmi_devintf.c +0 -2
@@ -162,8 +162,6 @@ static int ipmi_release(struct inode *inode, struct file *file)if (rv)return rv; -ipmi_fasync (-1 , file,0 ); -/* FIXME - free the messages in the list. */ kfree (priv);
drivers/char/ipmi/ipmi_watchdog.c +0 -1
@@ -870,7 +870,6 @@ static int ipmi_close(struct inode *ino, struct file *filep)clear_bit (0 , &ipmi_wdog_open); } -ipmi_fasync (-1 , filep,0 ); expect_close =0 ;return 0 ;
drivers/char/random.c +0 -7
@@ -1139,18 +1139,12 @@ static int random_fasync(int fd, struct file *filp, int on)return fasync_helper (fd, filp, on, &fasync); } -static int random_release (struct inode *inode,struct file *filp) -{ -return fasync_helper (-1 , filp,0 , &fasync); -} -const struct file_operations random_fops = { .read = random_read, .write = random_write, .poll = random_poll, .unlocked_ioctl = random_ioctl, .fasync = random_fasync, - .release = random_release, };const struct file_operations urandom_fops = {
@@ -1158,7 +1152,6 @@ const struct file_operations urandom_fops = { .write = random_write, .unlocked_ioctl = random_ioctl, .fasync = random_fasync, - .release = random_release, };/***************************************************************
drivers/char/rtc.c +0 -2
@@ -788,8 +788,6 @@ static int rtc_release(struct inode *inode, struct file *file) } spin_unlock_irq(&rtc_lock); -if (file->f_flags &FASYNC ) -rtc_fasync (-1 , file,0 ); no_irq:#endif
drivers/char/sonypi.c +0 -1
@@ -898,7 +898,6 @@ static int sonypi_misc_fasync(int fd, struct file *filp, int on)static int sonypi_misc_release (struct inode *inode,struct file *file) { -sonypi_misc_fasync (-1 , file,0 );mutex_lock (&sonypi_device.lock); sonypi_device.open_count--;mutex_unlock (&sonypi_device.lock);
drivers/gpu/drm/drm_fops.c +0 -2
@@ -406,8 +406,6 @@ int drm_release(struct inode *inode, struct file *filp)if (dev->driver->driver_features &DRIVER_GEM )drm_gem_release (dev, file_priv); -drm_fasync (-1 , filp,0 ); -mutex_lock (&dev->ctxlist_mutex);if (!list_empty (&dev->ctxlist)) {struct drm_ctx_list *pos, *n;
drivers/hid/usbhid/hiddev.c +0 -2
@@ -242,8 +242,6 @@ static int hiddev_release(struct inode * inode, struct file * file)struct hiddev_list *list = file->private_data;unsigned long flags; -hiddev_fasync (-1 , file,0 ); -spin_lock_irqsave (&list->hiddev->list_lock, flags);list_del (&list->node);spin_unlock_irqrestore (&list->hiddev->list_lock, flags);
drivers/ieee1394/dv1394.c +0 -3
@@ -1828,9 +1828,6 @@ static int dv1394_release(struct inode *inode, struct file *file)/* OK to free the DMA buffer, no more mappings can exist */ do_dv1394_shutdown (video,1 ); -/* clean up async I/O users */ -dv1394_fasync (-1 , file,0 ); -/* give someone else a turn */ clear_bit (0 , &video->open);
drivers/infiniband/core/uverbs_main.c +0 -2
@@ -358,8 +358,6 @@ static int ib_uverbs_event_close(struct inode *inode, struct file *filp) }spin_unlock_irq (&file->lock); -ib_uverbs_event_fasync (-1 , filp,0 ); -if (file->is_async) {ib_unregister_event_handler (&file->uverbs_file->event_handler);kref_put (&file->uverbs_file->ref, ib_uverbs_release_file);
drivers/input/evdev.c +0 -1
@@ -235,7 +235,6 @@ static int evdev_release(struct inode *inode, struct file *file)evdev_ungrab (evdev, client);mutex_unlock (&evdev->mutex); -evdev_fasync (-1 , file,0 );evdev_detach_client (evdev, client);kfree (client);
drivers/input/joydev.c +0 -1
@@ -244,7 +244,6 @@ static int joydev_release(struct inode *inode, struct file *file)struct joydev_client *client = file->private_data;struct joydev *joydev = client->joydev; -joydev_fasync (-1 , file,0 );joydev_detach_client (joydev, client);kfree (client);
drivers/input/misc/hp_sdc_rtc.c +0 -13
@@ -71,7 +71,6 @@ static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,static unsigned int hp_sdc_rtc_poll (struct file *file,poll_table *wait);static int hp_sdc_rtc_open (struct inode *inode,struct file *file); -static int hp_sdc_rtc_release (struct inode *inode,struct file *file);static int hp_sdc_rtc_fasync (int fd,struct file *filp,int on); static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
@@ -414,17 +413,6 @@ static int hp_sdc_rtc_open(struct inode *inode, struct file *file)return 0 ; } -static int hp_sdc_rtc_release (struct inode *inode,struct file *file) -{ -/* Turn off interrupts? */ - -if (file->f_flags &FASYNC ) { -hp_sdc_rtc_fasync (-1 , file,0 ); - } - -return 0 ; -} -static int hp_sdc_rtc_fasync (int fd,struct file *filp,int on) {return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue);
@@ -680,7 +668,6 @@ static const struct file_operations hp_sdc_rtc_fops = { .poll = hp_sdc_rtc_poll, .ioctl = hp_sdc_rtc_ioctl, .open = hp_sdc_rtc_open, - .release = hp_sdc_rtc_release, .fasync = hp_sdc_rtc_fasync, };
drivers/input/mousedev.c +0 -1
@@ -519,7 +519,6 @@ static int mousedev_release(struct inode *inode, struct file *file)struct mousedev_client *client = file->private_data;struct mousedev *mousedev = client->mousedev; -mousedev_fasync (-1 , file,0 );mousedev_detach_client (mousedev, client);kfree (client);
drivers/input/serio/serio_raw.c +0 -1
@@ -135,7 +135,6 @@ static int serio_raw_release(struct inode *inode, struct file *file)mutex_lock (&serio_raw_mutex); -serio_raw_fasync (-1 , file,0 );serio_raw_cleanup (serio_raw);mutex_unlock (&serio_raw_mutex);
drivers/message/fusion/mptctl.c +0 -7
@@ -559,12 +559,6 @@ mptctl_fasync(int fd, struct file *filep, int mode)return ret; } -static int -mptctl_release (struct inode *inode,struct file *filep) -{ -return fasync_helper (-1 , filep,0 , &async_queue); -} -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * MPT ioctl handler
@@ -2706,7 +2700,6 @@ mptctl_hp_targetinfo(unsigned long arg)static const struct file_operations mptctl_fops = { .owner =THIS_MODULE , .llseek = no_llseek, - .release = mptctl_release, .fasync = mptctl_fasync, .unlocked_ioctl = mptctl_ioctl, #ifdef CONFIG_COMPAT
drivers/message/i2o/i2o_config.c +5 -16
@@ -1097,28 +1097,17 @@ static int cfg_fasync(int fd, struct file *fp, int on)static int cfg_release (struct inode *inode,struct file *file) {ulong id = (ulong ) file->private_data; -struct i2o_cfg_info *p1, *p2; +struct i2o_cfg_info *p, **q;unsigned long flags;lock_kernel (); - p1 = p2 =NULL ; -spin_lock_irqsave (&i2o_config_lock, flags); -for (p1 = open_files; p1;) { -if (p1->q_id == id) { - -if (p1->fasync) -cfg_fasync (-1 , file,0 ); -if (p2) - p2->next = p1->next; -else - open_files = p1->next; - -kfree (p1); +for (q = &open_files; (p = *q) !=NULL ; q = &p->next) { +if (p->q_id == id) { + *q = p->next; +kfree (p);break ; } - p2 = p1; - p1 = p1->next; }spin_unlock_irqrestore (&i2o_config_lock, flags);unlock_kernel ();
drivers/misc/sony-laptop.c +0 -1
@@ -1920,7 +1920,6 @@ static int sonypi_misc_fasync(int fd, struct file *filp, int on)static int sonypi_misc_release (struct inode *inode,struct file *file) { -sonypi_misc_fasync (-1 , file,0 );atomic_dec (&sonypi_compat.open_count);return 0 ; }
drivers/net/tun.c +0 -2
@@ -1070,8 +1070,6 @@ static int tun_chr_close(struct inode *inode, struct file *file)DBG (KERN_INFO "%s: tun_chr_close\n" , tun->dev->name); -tun_chr_fasync (-1 , file,0 ); -rtnl_lock ();/* Detach from net device */
drivers/rtc/rtc-dev.c +0 -3
@@ -446,9 +446,6 @@ static int rtc_dev_release(struct inode *inode, struct file *file)if (rtc->ops->release) rtc->ops->release (rtc->dev.parent); -if (file->f_flags &FASYNC ) -rtc_dev_fasync (-1 , file,0 ); -clear_bit_unlock (RTC_DEV_BUSY , &rtc->flags);return 0 ; }
drivers/scsi/megaraid/megaraid_sas.c +0 -12
@@ -2988,17 +2988,6 @@ static int megasas_mgmt_open(struct inode *inode, struct file *filep) }/** -* megasas_mgmt_release - char node "release" entry point -*/ -static int megasas_mgmt_release (struct inode *inode,struct file *filep) -{ - filep->private_data =NULL ; -fasync_helper (-1 , filep,0 , &megasas_async_queue); - -return 0 ; -} - -/** * megasas_mgmt_fasync - Async notifier registration from applications * * This function adds the calling process to a driver global queue. When an
@@ -3345,7 +3334,6 @@ megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd,static const struct file_operations megasas_mgmt_fops = { .owner =THIS_MODULE , .open = megasas_mgmt_open, - .release = megasas_mgmt_release, .fasync = megasas_mgmt_fasync, .unlocked_ioctl = megasas_mgmt_ioctl, #ifdef CONFIG_COMPAT
drivers/scsi/sg.c +0 -1
@@ -327,7 +327,6 @@ sg_release(struct inode *inode, struct file *filp)if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))return -ENXIO ;SCSI_LOG_TIMEOUT (3 ,printk ("sg_release: %s\n" , sdp->disk->disk_name)); -sg_fasync (-1 , filp,0 );/* remove filp from async notification list */ if (0 ==sg_remove_sfp (sdp, sfp)) {/* Returns 1 when sdp gone */ if (!sdp->detached) {scsi_device_put (sdp->device);
drivers/staging/me4000/me4000.c +0 -3
@@ -1633,9 +1633,6 @@ static int me4000_release(struct inode *inode_p, struct file *file_p)free_irq (ext_int_context->irq, ext_int_context); -/* Delete the fasync structure and free memory */ -me4000_ext_int_fasync (0 , file_p,0 ); -/* Mark as unused */ ext_int_context->in_use =0 ; }else {
drivers/telephony/ixj.c +0 -1
@@ -2328,7 +2328,6 @@ static int ixj_release(struct inode *inode, struct file *file_p) j->rec_codec = j->play_codec =0 ; j->rec_frame_size = j->play_frame_size =0 ; j->flags.cidsent = j->flags.cidring =0 ; -ixj_fasync (-1 , file_p,0 );/* remove from list of async notification */ if (j->cardtype ==QTI_LINEJACK && !j->readers && !j->writers) {ixj_set_port (j,PORT_PSTN );
drivers/uio/uio.c +0 -3
@@ -367,9 +367,6 @@ static int uio_release(struct inode *inode, struct file *filep) ret = idev->info->release (idev->info, inode);module_put (idev->owner); - -if (filep->f_flags &FASYNC ) - ret =uio_fasync (-1 , filep,0 );kfree (listener);return ret; }
drivers/usb/gadget/inode.c +0 -1
@@ -1251,7 +1251,6 @@ dev_release (struct inode *inode, struct file *fd)* alternatively, all host requests will time out. */ -fasync_helper (-1 , fd,0 , &dev->fasync);kfree (dev->buf); dev->buf =NULL ;put_dev (dev);
fs/file_table.c +4 -0
@@ -269,6 +269,10 @@ void __fput(struct file *file)eventpoll_release (file);locks_remove_flock (file); +if (unlikely (file->f_flags &FASYNC )) { +if (file->f_op && file->f_op->fasync) + file->f_op->fasync (-1 , file,0 ); + }if (file->f_op && file->f_op->release) file->f_op->release (inode, file);security_file_free (file);
fs/fuse/dev.c +0 -1
@@ -1056,7 +1056,6 @@ static int fuse_dev_release(struct inode *inode, struct file *file)end_requests (fc, &fc->pending);end_requests (fc, &fc->processing);spin_unlock (&fc->lock); -fasync_helper (-1 , file,0 , &fc->fasync);fuse_conn_put (fc); }
fs/inotify_user.c +0 -3
@@ -537,9 +537,6 @@ static int inotify_release(struct inode *ignored, struct file *file)inotify_dev_event_dequeue (dev);mutex_unlock (&dev->ev_mutex); -if (file->f_flags &FASYNC ) -inotify_fasync (-1 , file,0 ); -/* free this device: the put matching the get in inotify_init() */ put_inotify_dev (dev);
fs/pipe.c +0 -3
@@ -717,14 +717,12 @@ pipe_rdwr_fasync(int fd, struct file *filp, int on)static int pipe_read_release (struct inode *inode,struct file *filp) { -pipe_read_fasync (-1 , filp,0 );return pipe_release (inode,1 ,0 ); }static int pipe_write_release (struct inode *inode,struct file *filp) { -pipe_write_fasync (-1 , filp,0 );return pipe_release (inode,0 ,1 ); }
@@ -733,7 +731,6 @@ pipe_rdwr_release(struct inode *inode, struct file *filp) {int decr, decw; -pipe_rdwr_fasync (-1 , filp,0 ); decr = (filp->f_mode &FMODE_READ ) !=0 ; decw = (filp->f_mode &FMODE_WRITE ) !=0 ;return pipe_release (inode, decr, decw);
net/socket.c +0 -1
@@ -990,7 +990,6 @@ static int sock_close(struct inode *inode, struct file *filp)printk (KERN_DEBUG "sock_close: NULL inode\n" );return 0 ; } -sock_fasync (-1 , filp,0 );sock_release (SOCKET_I (inode));return 0 ; }
sound/core/control.c +0 -1
@@ -113,7 +113,6 @@ static int snd_ctl_release(struct inode *inode, struct file *file)unsigned int idx; ctl = file->private_data; -fasync_helper (-1 , file,0 , &ctl->fasync); file->private_data =NULL ; card = ctl->card;write_lock_irqsave (&card->ctl_files_rwlock, flags);
sound/core/init.c +4 -1
@@ -264,8 +264,11 @@ static int snd_disconnect_release(struct inode *inode, struct file *file) }spin_unlock (&shutdown_lock); -if (likely (df)) +if (likely (df)) { +if ((file->f_flags &FASYNC ) && df->disconnected_f_op->fasync) + df->disconnected_f_op->fasync (-1 , file,0 );return df->disconnected_f_op->release (inode, file); + }panic ("%s(%p, %p) failed!" , __func__, inode, file); }
sound/core/pcm_native.c +0 -1
@@ -2169,7 +2169,6 @@ static int snd_pcm_release(struct inode *inode, struct file *file)if (snd_BUG_ON (!substream))return -ENXIO ; pcm = substream->pcm; -fasync_helper (-1 , file,0 , &substream->runtime->fasync);mutex_lock (&pcm->open_mutex);snd_pcm_release_substream (substream);kfree (pcm_file);
sound/core/timer.c +0 -1
@@ -1263,7 +1263,6 @@ static int snd_timer_user_release(struct inode *inode, struct file *file)if (file->private_data) { tu = file->private_data; file->private_data =NULL ; -fasync_helper (-1 , file,0 , &tu->fasync);if (tu->timeri)snd_timer_close (tu->timeri);kfree (tu->queue);
Quoted 11 lines · Al Viro
As it is, all instances of ->release() for files that have->fasync() need to remember to evict file from fasync lists; forgetting that creates a hole and we actually have a bunch that *does* forget.
So let's keep our lives simple - let
__fput()check FASYNC infile->f_flagsand call ->fasync() there if it's been set. And lose that crap in ->release() instances - leaving it there is still valid, but we don't have to bother anymore.Comments?
This looks like "obviously the right thing". Done.
Linus