static int faf_polled_fd_add(kerrighed_node_t client, int server_fd, unsigned long dvfs_id) { struct faf_polled_fd *polled_fd; struct faf_polled_fd_node *polled_fd_node; struct epoll_event event; int err; mutex_lock(&faf_polled_fd_mutex); err = -ENOMEM; polled_fd = faf_polled_fd_find(dvfs_id); if (IS_ERR(polled_fd)) { err = PTR_ERR(polled_fd); goto err_polled_fd; } polled_fd_node = faf_polled_fd_find_node(polled_fd, client); if (!polled_fd_node) goto err_polled_fd_node; err = 0; polled_fd_node->count++; if (polled_fd_node->count > 1) /* Already polled by this node */ goto out_unlock_polled_fd; if (polled_fd->count > 1) /* Already polled by another node */ goto out_unlock_polled_fd; err = faf_poll_init_epfd(); if (err) goto err_epoll_ctl; event.events = FAF_POLL_EVENTS; event.data = dvfs_id; err = sys_epoll_ctl(faf_poll_epfd, EPOLL_CTL_ADD, server_fd, &event); if (err) goto err_epoll_ctl; out_unlock_polled_fd: mutex_unlock(&faf_polled_fd_mutex); return err; err_epoll_ctl: polled_fd_node->count--; faf_polled_fd_node_free(polled_fd, polled_fd_node); err_polled_fd_node: if (!polled_fd->count) faf_polled_fd_free(polled_fd); err_polled_fd: printk(KERN_WARNING "faf_polled_fd_add: failed to forward polling of %lu\n", dvfs_id); goto out_unlock_polled_fd; }
asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd, struct oabi_epoll_event __user *event) { struct oabi_epoll_event user; struct epoll_event kernel; mm_segment_t fs; long ret; if (op == EPOLL_CTL_DEL) return sys_epoll_ctl(epfd, op, fd, NULL); if (copy_from_user(&user, event, sizeof(user))) return -EFAULT; kernel.events = user.events; kernel.data = user.data; fs = get_fs(); set_fs(KERNEL_DS); ret = sys_epoll_ctl(epfd, op, fd, &kernel); set_fs(fs); return ret; }
static int faf_polled_fd_remove(kerrighed_node_t client, int server_fd, unsigned long dvfs_id) { struct dvfs_file_struct *dvfs_file; struct faf_polled_fd *polled_fd; struct faf_polled_fd_node *polled_fd_node; int err; dvfs_file = _kddm_get_object_no_ft(dvfs_file_struct_ctnr, dvfs_id); if (dvfs_file && dvfs_file->file) { /* TODO: still required? */ if (atomic_read (&dvfs_file->file->f_count) == 0) dvfs_file->file = NULL; } mutex_lock(&faf_polled_fd_mutex); polled_fd = __faf_polled_fd_find(dvfs_id); BUG_ON(!polled_fd); BUG_ON(!polled_fd->count); polled_fd_node = __faf_polled_fd_find_node(polled_fd, client); BUG_ON(!polled_fd_node); BUG_ON(!polled_fd_node->count); polled_fd_node->count--; if (!polled_fd_node->count) faf_polled_fd_node_free(polled_fd, polled_fd_node); if (polled_fd->count) goto out_unlock; if (!dvfs_file || !dvfs_file->file) /* * The file is already closed or about to be closed. The last * __fput() automatically removes it from the interest set of * faf_poll_epfd. */ goto free_polled_fd; BUG_ON(faf_poll_epfd < 0); err = sys_epoll_ctl(faf_poll_epfd, EPOLL_CTL_DEL, server_fd, NULL); BUG_ON(err); free_polled_fd: faf_polled_fd_free(polled_fd); out_unlock: mutex_unlock(&faf_polled_fd_mutex); _kddm_put_object(dvfs_file_struct_ctnr, dvfs_id); return 0; }
static int os_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) { long rc; mm_segment_t oldfs = get_fs(); set_fs(KERNEL_DS); rc = sys_epoll_ctl(epfd, op, fd, event); set_fs(oldfs); if (rc) { errno = -rc; return -1; } else { return 0; } }