1*b8b072cbSMiklos Szeredi // SPDX-License-Identifier: GPL-2.0-only 2*b8b072cbSMiklos Szeredi 3*b8b072cbSMiklos Szeredi #include "dev.h" 4*b8b072cbSMiklos Szeredi #include "fuse_i.h" 5*b8b072cbSMiklos Szeredi 6*b8b072cbSMiklos Szeredi void fuse_end_polls(struct fuse_conn *fc) 7*b8b072cbSMiklos Szeredi { 8*b8b072cbSMiklos Szeredi struct rb_node *p; 9*b8b072cbSMiklos Szeredi 10*b8b072cbSMiklos Szeredi spin_lock(&fc->lock); 11*b8b072cbSMiklos Szeredi p = rb_first(&fc->polled_files); 12*b8b072cbSMiklos Szeredi 13*b8b072cbSMiklos Szeredi while (p) { 14*b8b072cbSMiklos Szeredi struct fuse_file *ff; 15*b8b072cbSMiklos Szeredi ff = rb_entry(p, struct fuse_file, polled_node); 16*b8b072cbSMiklos Szeredi wake_up_interruptible_all(&ff->poll_wait); 17*b8b072cbSMiklos Szeredi 18*b8b072cbSMiklos Szeredi p = rb_next(p); 19*b8b072cbSMiklos Szeredi } 20*b8b072cbSMiklos Szeredi spin_unlock(&fc->lock); 21*b8b072cbSMiklos Szeredi } 22*b8b072cbSMiklos Szeredi 23*b8b072cbSMiklos Szeredi /* 24*b8b072cbSMiklos Szeredi * All files which have been polled are linked to RB tree 25*b8b072cbSMiklos Szeredi * fuse_conn->polled_files which is indexed by kh. Walk the tree and 26*b8b072cbSMiklos Szeredi * find the matching one. 27*b8b072cbSMiklos Szeredi */ 28*b8b072cbSMiklos Szeredi static struct rb_node **fuse_find_polled_node(struct fuse_conn *fc, u64 kh, 29*b8b072cbSMiklos Szeredi struct rb_node **parent_out) 30*b8b072cbSMiklos Szeredi { 31*b8b072cbSMiklos Szeredi struct rb_node **link = &fc->polled_files.rb_node; 32*b8b072cbSMiklos Szeredi struct rb_node *last = NULL; 33*b8b072cbSMiklos Szeredi 34*b8b072cbSMiklos Szeredi while (*link) { 35*b8b072cbSMiklos Szeredi struct fuse_file *ff; 36*b8b072cbSMiklos Szeredi 37*b8b072cbSMiklos Szeredi last = *link; 38*b8b072cbSMiklos Szeredi ff = rb_entry(last, struct fuse_file, polled_node); 39*b8b072cbSMiklos Szeredi 40*b8b072cbSMiklos Szeredi if (kh < ff->kh) 41*b8b072cbSMiklos Szeredi link = &last->rb_left; 42*b8b072cbSMiklos Szeredi else if (kh > ff->kh) 43*b8b072cbSMiklos Szeredi link = &last->rb_right; 44*b8b072cbSMiklos Szeredi else 45*b8b072cbSMiklos Szeredi return link; 46*b8b072cbSMiklos Szeredi } 47*b8b072cbSMiklos Szeredi 48*b8b072cbSMiklos Szeredi if (parent_out) 49*b8b072cbSMiklos Szeredi *parent_out = last; 50*b8b072cbSMiklos Szeredi return link; 51*b8b072cbSMiklos Szeredi } 52*b8b072cbSMiklos Szeredi 53*b8b072cbSMiklos Szeredi /* 54*b8b072cbSMiklos Szeredi * The file is about to be polled. Make sure it's on the polled_files 55*b8b072cbSMiklos Szeredi * RB tree. Note that files once added to the polled_files tree are 56*b8b072cbSMiklos Szeredi * not removed before the file is released. This is because a file 57*b8b072cbSMiklos Szeredi * polled once is likely to be polled again. 58*b8b072cbSMiklos Szeredi */ 59*b8b072cbSMiklos Szeredi static void fuse_register_polled_file(struct fuse_conn *fc, 60*b8b072cbSMiklos Szeredi struct fuse_file *ff) 61*b8b072cbSMiklos Szeredi { 62*b8b072cbSMiklos Szeredi spin_lock(&fc->lock); 63*b8b072cbSMiklos Szeredi if (RB_EMPTY_NODE(&ff->polled_node)) { 64*b8b072cbSMiklos Szeredi struct rb_node **link, *parent; 65*b8b072cbSMiklos Szeredi 66*b8b072cbSMiklos Szeredi link = fuse_find_polled_node(fc, ff->kh, &parent); 67*b8b072cbSMiklos Szeredi BUG_ON(*link); 68*b8b072cbSMiklos Szeredi rb_link_node(&ff->polled_node, parent, link); 69*b8b072cbSMiklos Szeredi rb_insert_color(&ff->polled_node, &fc->polled_files); 70*b8b072cbSMiklos Szeredi } 71*b8b072cbSMiklos Szeredi spin_unlock(&fc->lock); 72*b8b072cbSMiklos Szeredi } 73*b8b072cbSMiklos Szeredi 74*b8b072cbSMiklos Szeredi __poll_t fuse_file_poll(struct file *file, poll_table *wait) 75*b8b072cbSMiklos Szeredi { 76*b8b072cbSMiklos Szeredi struct fuse_file *ff = file->private_data; 77*b8b072cbSMiklos Szeredi struct fuse_mount *fm = ff->fm; 78*b8b072cbSMiklos Szeredi struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh }; 79*b8b072cbSMiklos Szeredi struct fuse_poll_out outarg; 80*b8b072cbSMiklos Szeredi FUSE_ARGS(args); 81*b8b072cbSMiklos Szeredi int err; 82*b8b072cbSMiklos Szeredi 83*b8b072cbSMiklos Szeredi if (fm->fc->no_poll) 84*b8b072cbSMiklos Szeredi return DEFAULT_POLLMASK; 85*b8b072cbSMiklos Szeredi 86*b8b072cbSMiklos Szeredi poll_wait(file, &ff->poll_wait, wait); 87*b8b072cbSMiklos Szeredi inarg.events = mangle_poll(poll_requested_events(wait)); 88*b8b072cbSMiklos Szeredi 89*b8b072cbSMiklos Szeredi /* 90*b8b072cbSMiklos Szeredi * Ask for notification iff there's someone waiting for it. 91*b8b072cbSMiklos Szeredi * The client may ignore the flag and always notify. 92*b8b072cbSMiklos Szeredi */ 93*b8b072cbSMiklos Szeredi if (waitqueue_active(&ff->poll_wait)) { 94*b8b072cbSMiklos Szeredi inarg.flags |= FUSE_POLL_SCHEDULE_NOTIFY; 95*b8b072cbSMiklos Szeredi fuse_register_polled_file(fm->fc, ff); 96*b8b072cbSMiklos Szeredi } 97*b8b072cbSMiklos Szeredi 98*b8b072cbSMiklos Szeredi args.opcode = FUSE_POLL; 99*b8b072cbSMiklos Szeredi args.nodeid = ff->nodeid; 100*b8b072cbSMiklos Szeredi args.in_numargs = 1; 101*b8b072cbSMiklos Szeredi args.in_args[0].size = sizeof(inarg); 102*b8b072cbSMiklos Szeredi args.in_args[0].value = &inarg; 103*b8b072cbSMiklos Szeredi args.out_numargs = 1; 104*b8b072cbSMiklos Szeredi args.out_args[0].size = sizeof(outarg); 105*b8b072cbSMiklos Szeredi args.out_args[0].value = &outarg; 106*b8b072cbSMiklos Szeredi err = fuse_simple_request(fm, &args); 107*b8b072cbSMiklos Szeredi 108*b8b072cbSMiklos Szeredi if (!err) 109*b8b072cbSMiklos Szeredi return demangle_poll(outarg.revents); 110*b8b072cbSMiklos Szeredi if (err == -ENOSYS) { 111*b8b072cbSMiklos Szeredi fm->fc->no_poll = 1; 112*b8b072cbSMiklos Szeredi return DEFAULT_POLLMASK; 113*b8b072cbSMiklos Szeredi } 114*b8b072cbSMiklos Szeredi return EPOLLERR; 115*b8b072cbSMiklos Szeredi } 116*b8b072cbSMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_file_poll); 117*b8b072cbSMiklos Szeredi 118*b8b072cbSMiklos Szeredi /* 119*b8b072cbSMiklos Szeredi * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and 120*b8b072cbSMiklos Szeredi * wakes up the poll waiters. 121*b8b072cbSMiklos Szeredi */ 122*b8b072cbSMiklos Szeredi int fuse_notify_poll_wakeup(struct fuse_conn *fc, 123*b8b072cbSMiklos Szeredi struct fuse_notify_poll_wakeup_out *outarg) 124*b8b072cbSMiklos Szeredi { 125*b8b072cbSMiklos Szeredi u64 kh = outarg->kh; 126*b8b072cbSMiklos Szeredi struct rb_node **link; 127*b8b072cbSMiklos Szeredi 128*b8b072cbSMiklos Szeredi spin_lock(&fc->lock); 129*b8b072cbSMiklos Szeredi 130*b8b072cbSMiklos Szeredi link = fuse_find_polled_node(fc, kh, NULL); 131*b8b072cbSMiklos Szeredi if (*link) { 132*b8b072cbSMiklos Szeredi struct fuse_file *ff; 133*b8b072cbSMiklos Szeredi 134*b8b072cbSMiklos Szeredi ff = rb_entry(*link, struct fuse_file, polled_node); 135*b8b072cbSMiklos Szeredi wake_up_interruptible_sync(&ff->poll_wait); 136*b8b072cbSMiklos Szeredi } 137*b8b072cbSMiklos Szeredi 138*b8b072cbSMiklos Szeredi spin_unlock(&fc->lock); 139*b8b072cbSMiklos Szeredi return 0; 140*b8b072cbSMiklos Szeredi } 141*b8b072cbSMiklos Szeredi 142