Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 in
file->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.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Al Viro and committed by
Linus Torvalds
233e70f4 3318a386

+13 -109
-5
arch/ia64/kernel/perfmon.c
··· 1995 1995 return -EBADF; 1996 1996 } 1997 1997 1998 - if (filp->f_flags & FASYNC) { 1999 - DPRINT(("cleaning up async_queue=%p\n", ctx->ctx_async_queue)); 2000 - pfm_do_fasync(-1, filp, ctx, 0); 2001 - } 2002 - 2003 1998 PROTECT_CTX(ctx, flags); 2004 1999 2005 2000 state = ctx->ctx_state;
-3
drivers/char/hpet.c
··· 427 427 if (irq) 428 428 free_irq(irq, devp); 429 429 430 - if (file->f_flags & FASYNC) 431 - hpet_fasync(-1, file, 0); 432 - 433 430 file->private_data = NULL; 434 431 return 0; 435 432 }
-2
drivers/char/ipmi/ipmi_devintf.c
··· 162 162 if (rv) 163 163 return rv; 164 164 165 - ipmi_fasync (-1, file, 0); 166 - 167 165 /* FIXME - free the messages in the list. */ 168 166 kfree(priv); 169 167
-1
drivers/char/ipmi/ipmi_watchdog.c
··· 870 870 clear_bit(0, &ipmi_wdog_open); 871 871 } 872 872 873 - ipmi_fasync(-1, filep, 0); 874 873 expect_close = 0; 875 874 876 875 return 0;
-7
drivers/char/random.c
··· 1139 1139 return fasync_helper(fd, filp, on, &fasync); 1140 1140 } 1141 1141 1142 - static int random_release(struct inode *inode, struct file *filp) 1143 - { 1144 - return fasync_helper(-1, filp, 0, &fasync); 1145 - } 1146 - 1147 1142 const struct file_operations random_fops = { 1148 1143 .read = random_read, 1149 1144 .write = random_write, 1150 1145 .poll = random_poll, 1151 1146 .unlocked_ioctl = random_ioctl, 1152 1147 .fasync = random_fasync, 1153 - .release = random_release, 1154 1148 }; 1155 1149 1156 1150 const struct file_operations urandom_fops = { ··· 1152 1158 .write = random_write, 1153 1159 .unlocked_ioctl = random_ioctl, 1154 1160 .fasync = random_fasync, 1155 - .release = random_release, 1156 1161 }; 1157 1162 1158 1163 /***************************************************************
-2
drivers/char/rtc.c
··· 788 788 } 789 789 spin_unlock_irq(&rtc_lock); 790 790 791 - if (file->f_flags & FASYNC) 792 - rtc_fasync(-1, file, 0); 793 791 no_irq: 794 792 #endif 795 793
-1
drivers/char/sonypi.c
··· 898 898 899 899 static int sonypi_misc_release(struct inode *inode, struct file *file) 900 900 { 901 - sonypi_misc_fasync(-1, file, 0); 902 901 mutex_lock(&sonypi_device.lock); 903 902 sonypi_device.open_count--; 904 903 mutex_unlock(&sonypi_device.lock);
-2
drivers/gpu/drm/drm_fops.c
··· 406 406 if (dev->driver->driver_features & DRIVER_GEM) 407 407 drm_gem_release(dev, file_priv); 408 408 409 - drm_fasync(-1, filp, 0); 410 - 411 409 mutex_lock(&dev->ctxlist_mutex); 412 410 if (!list_empty(&dev->ctxlist)) { 413 411 struct drm_ctx_list *pos, *n;
-2
drivers/hid/usbhid/hiddev.c
··· 242 242 struct hiddev_list *list = file->private_data; 243 243 unsigned long flags; 244 244 245 - hiddev_fasync(-1, file, 0); 246 - 247 245 spin_lock_irqsave(&list->hiddev->list_lock, flags); 248 246 list_del(&list->node); 249 247 spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
-3
drivers/ieee1394/dv1394.c
··· 1828 1828 /* OK to free the DMA buffer, no more mappings can exist */ 1829 1829 do_dv1394_shutdown(video, 1); 1830 1830 1831 - /* clean up async I/O users */ 1832 - dv1394_fasync(-1, file, 0); 1833 - 1834 1831 /* give someone else a turn */ 1835 1832 clear_bit(0, &video->open); 1836 1833
-2
drivers/infiniband/core/uverbs_main.c
··· 358 358 } 359 359 spin_unlock_irq(&file->lock); 360 360 361 - ib_uverbs_event_fasync(-1, filp, 0); 362 - 363 361 if (file->is_async) { 364 362 ib_unregister_event_handler(&file->uverbs_file->event_handler); 365 363 kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);
-1
drivers/input/evdev.c
··· 235 235 evdev_ungrab(evdev, client); 236 236 mutex_unlock(&evdev->mutex); 237 237 238 - evdev_fasync(-1, file, 0); 239 238 evdev_detach_client(evdev, client); 240 239 kfree(client); 241 240
-1
drivers/input/joydev.c
··· 244 244 struct joydev_client *client = file->private_data; 245 245 struct joydev *joydev = client->joydev; 246 246 247 - joydev_fasync(-1, file, 0); 248 247 joydev_detach_client(joydev, client); 249 248 kfree(client); 250 249
-13
drivers/input/misc/hp_sdc_rtc.c
··· 71 71 static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait); 72 72 73 73 static int hp_sdc_rtc_open(struct inode *inode, struct file *file); 74 - static int hp_sdc_rtc_release(struct inode *inode, struct file *file); 75 74 static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on); 76 75 77 76 static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off, ··· 413 414 return 0; 414 415 } 415 416 416 - static int hp_sdc_rtc_release(struct inode *inode, struct file *file) 417 - { 418 - /* Turn off interrupts? */ 419 - 420 - if (file->f_flags & FASYNC) { 421 - hp_sdc_rtc_fasync (-1, file, 0); 422 - } 423 - 424 - return 0; 425 - } 426 - 427 417 static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on) 428 418 { 429 419 return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue); ··· 668 680 .poll = hp_sdc_rtc_poll, 669 681 .ioctl = hp_sdc_rtc_ioctl, 670 682 .open = hp_sdc_rtc_open, 671 - .release = hp_sdc_rtc_release, 672 683 .fasync = hp_sdc_rtc_fasync, 673 684 }; 674 685
-1
drivers/input/mousedev.c
··· 519 519 struct mousedev_client *client = file->private_data; 520 520 struct mousedev *mousedev = client->mousedev; 521 521 522 - mousedev_fasync(-1, file, 0); 523 522 mousedev_detach_client(mousedev, client); 524 523 kfree(client); 525 524
-1
drivers/input/serio/serio_raw.c
··· 135 135 136 136 mutex_lock(&serio_raw_mutex); 137 137 138 - serio_raw_fasync(-1, file, 0); 139 138 serio_raw_cleanup(serio_raw); 140 139 141 140 mutex_unlock(&serio_raw_mutex);
-7
drivers/message/fusion/mptctl.c
··· 559 559 return ret; 560 560 } 561 561 562 - static int 563 - mptctl_release(struct inode *inode, struct file *filep) 564 - { 565 - return fasync_helper(-1, filep, 0, &async_queue); 566 - } 567 - 568 562 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 569 563 /* 570 564 * MPT ioctl handler ··· 2700 2706 static const struct file_operations mptctl_fops = { 2701 2707 .owner = THIS_MODULE, 2702 2708 .llseek = no_llseek, 2703 - .release = mptctl_release, 2704 2709 .fasync = mptctl_fasync, 2705 2710 .unlocked_ioctl = mptctl_ioctl, 2706 2711 #ifdef CONFIG_COMPAT
+5 -16
drivers/message/i2o/i2o_config.c
··· 1097 1097 static int cfg_release(struct inode *inode, struct file *file) 1098 1098 { 1099 1099 ulong id = (ulong) file->private_data; 1100 - struct i2o_cfg_info *p1, *p2; 1100 + struct i2o_cfg_info *p, **q; 1101 1101 unsigned long flags; 1102 1102 1103 1103 lock_kernel(); 1104 - p1 = p2 = NULL; 1105 - 1106 1104 spin_lock_irqsave(&i2o_config_lock, flags); 1107 - for (p1 = open_files; p1;) { 1108 - if (p1->q_id == id) { 1109 - 1110 - if (p1->fasync) 1111 - cfg_fasync(-1, file, 0); 1112 - if (p2) 1113 - p2->next = p1->next; 1114 - else 1115 - open_files = p1->next; 1116 - 1117 - kfree(p1); 1105 + for (q = &open_files; (p = *q) != NULL; q = &p->next) { 1106 + if (p->q_id == id) { 1107 + *q = p->next; 1108 + kfree(p); 1118 1109 break; 1119 1110 } 1120 - p2 = p1; 1121 - p1 = p1->next; 1122 1111 } 1123 1112 spin_unlock_irqrestore(&i2o_config_lock, flags); 1124 1113 unlock_kernel();
-1
drivers/misc/sony-laptop.c
··· 1920 1920 1921 1921 static int sonypi_misc_release(struct inode *inode, struct file *file) 1922 1922 { 1923 - sonypi_misc_fasync(-1, file, 0); 1924 1923 atomic_dec(&sonypi_compat.open_count); 1925 1924 return 0; 1926 1925 }
-2
drivers/net/tun.c
··· 1070 1070 1071 1071 DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); 1072 1072 1073 - tun_chr_fasync(-1, file, 0); 1074 - 1075 1073 rtnl_lock(); 1076 1074 1077 1075 /* Detach from net device */
-3
drivers/rtc/rtc-dev.c
··· 446 446 if (rtc->ops->release) 447 447 rtc->ops->release(rtc->dev.parent); 448 448 449 - if (file->f_flags & FASYNC) 450 - rtc_dev_fasync(-1, file, 0); 451 - 452 449 clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); 453 450 return 0; 454 451 }
-12
drivers/scsi/megaraid/megaraid_sas.c
··· 2988 2988 } 2989 2989 2990 2990 /** 2991 - * megasas_mgmt_release - char node "release" entry point 2992 - */ 2993 - static int megasas_mgmt_release(struct inode *inode, struct file *filep) 2994 - { 2995 - filep->private_data = NULL; 2996 - fasync_helper(-1, filep, 0, &megasas_async_queue); 2997 - 2998 - return 0; 2999 - } 3000 - 3001 - /** 3002 2991 * megasas_mgmt_fasync - Async notifier registration from applications 3003 2992 * 3004 2993 * This function adds the calling process to a driver global queue. When an ··· 3334 3345 static const struct file_operations megasas_mgmt_fops = { 3335 3346 .owner = THIS_MODULE, 3336 3347 .open = megasas_mgmt_open, 3337 - .release = megasas_mgmt_release, 3338 3348 .fasync = megasas_mgmt_fasync, 3339 3349 .unlocked_ioctl = megasas_mgmt_ioctl, 3340 3350 #ifdef CONFIG_COMPAT
-1
drivers/scsi/sg.c
··· 327 327 if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) 328 328 return -ENXIO; 329 329 SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name)); 330 - sg_fasync(-1, filp, 0); /* remove filp from async notification list */ 331 330 if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */ 332 331 if (!sdp->detached) { 333 332 scsi_device_put(sdp->device);
-3
drivers/staging/me4000/me4000.c
··· 1633 1633 1634 1634 free_irq(ext_int_context->irq, ext_int_context); 1635 1635 1636 - /* Delete the fasync structure and free memory */ 1637 - me4000_ext_int_fasync(0, file_p, 0); 1638 - 1639 1636 /* Mark as unused */ 1640 1637 ext_int_context->in_use = 0; 1641 1638 } else {
-1
drivers/telephony/ixj.c
··· 2328 2328 j->rec_codec = j->play_codec = 0; 2329 2329 j->rec_frame_size = j->play_frame_size = 0; 2330 2330 j->flags.cidsent = j->flags.cidring = 0; 2331 - ixj_fasync(-1, file_p, 0); /* remove from list of async notification */ 2332 2331 2333 2332 if(j->cardtype == QTI_LINEJACK && !j->readers && !j->writers) { 2334 2333 ixj_set_port(j, PORT_PSTN);
-3
drivers/uio/uio.c
··· 367 367 ret = idev->info->release(idev->info, inode); 368 368 369 369 module_put(idev->owner); 370 - 371 - if (filep->f_flags & FASYNC) 372 - ret = uio_fasync(-1, filep, 0); 373 370 kfree(listener); 374 371 return ret; 375 372 }
-1
drivers/usb/gadget/inode.c
··· 1251 1251 * alternatively, all host requests will time out. 1252 1252 */ 1253 1253 1254 - fasync_helper (-1, fd, 0, &dev->fasync); 1255 1254 kfree (dev->buf); 1256 1255 dev->buf = NULL; 1257 1256 put_dev (dev);
+4
fs/file_table.c
··· 269 269 eventpoll_release(file); 270 270 locks_remove_flock(file); 271 271 272 + if (unlikely(file->f_flags & FASYNC)) { 273 + if (file->f_op && file->f_op->fasync) 274 + file->f_op->fasync(-1, file, 0); 275 + } 272 276 if (file->f_op && file->f_op->release) 273 277 file->f_op->release(inode, file); 274 278 security_file_free(file);
-1
fs/fuse/dev.c
··· 1056 1056 end_requests(fc, &fc->pending); 1057 1057 end_requests(fc, &fc->processing); 1058 1058 spin_unlock(&fc->lock); 1059 - fasync_helper(-1, file, 0, &fc->fasync); 1060 1059 fuse_conn_put(fc); 1061 1060 } 1062 1061
-3
fs/inotify_user.c
··· 537 537 inotify_dev_event_dequeue(dev); 538 538 mutex_unlock(&dev->ev_mutex); 539 539 540 - if (file->f_flags & FASYNC) 541 - inotify_fasync(-1, file, 0); 542 - 543 540 /* free this device: the put matching the get in inotify_init() */ 544 541 put_inotify_dev(dev); 545 542
-3
fs/pipe.c
··· 717 717 static int 718 718 pipe_read_release(struct inode *inode, struct file *filp) 719 719 { 720 - pipe_read_fasync(-1, filp, 0); 721 720 return pipe_release(inode, 1, 0); 722 721 } 723 722 724 723 static int 725 724 pipe_write_release(struct inode *inode, struct file *filp) 726 725 { 727 - pipe_write_fasync(-1, filp, 0); 728 726 return pipe_release(inode, 0, 1); 729 727 } 730 728 ··· 731 733 { 732 734 int decr, decw; 733 735 734 - pipe_rdwr_fasync(-1, filp, 0); 735 736 decr = (filp->f_mode & FMODE_READ) != 0; 736 737 decw = (filp->f_mode & FMODE_WRITE) != 0; 737 738 return pipe_release(inode, decr, decw);
-1
net/socket.c
··· 990 990 printk(KERN_DEBUG "sock_close: NULL inode\n"); 991 991 return 0; 992 992 } 993 - sock_fasync(-1, filp, 0); 994 993 sock_release(SOCKET_I(inode)); 995 994 return 0; 996 995 }
-1
sound/core/control.c
··· 113 113 unsigned int idx; 114 114 115 115 ctl = file->private_data; 116 - fasync_helper(-1, file, 0, &ctl->fasync); 117 116 file->private_data = NULL; 118 117 card = ctl->card; 119 118 write_lock_irqsave(&card->ctl_files_rwlock, flags);
+4 -1
sound/core/init.c
··· 264 264 } 265 265 spin_unlock(&shutdown_lock); 266 266 267 - if (likely(df)) 267 + if (likely(df)) { 268 + if ((file->f_flags & FASYNC) && df->disconnected_f_op->fasync) 269 + df->disconnected_f_op->fasync(-1, file, 0); 268 270 return df->disconnected_f_op->release(inode, file); 271 + } 269 272 270 273 panic("%s(%p, %p) failed!", __func__, inode, file); 271 274 }
-1
sound/core/pcm_native.c
··· 2169 2169 if (snd_BUG_ON(!substream)) 2170 2170 return -ENXIO; 2171 2171 pcm = substream->pcm; 2172 - fasync_helper(-1, file, 0, &substream->runtime->fasync); 2173 2172 mutex_lock(&pcm->open_mutex); 2174 2173 snd_pcm_release_substream(substream); 2175 2174 kfree(pcm_file);
-1
sound/core/timer.c
··· 1263 1263 if (file->private_data) { 1264 1264 tu = file->private_data; 1265 1265 file->private_data = NULL; 1266 - fasync_helper(-1, file, 0, &tu->fasync); 1267 1266 if (tu->timeri) 1268 1267 snd_timer_close(tu->timeri); 1269 1268 kfree(tu->queue);