asmlinkage long sys_eventfd2(unsigned int count, int flags) { int fd; struct eventfd_ctx *ctx; /* Check the EFD_* constants for consistency. */ BUILD_BUG_ON(EFD_CLOEXEC != O_CLOEXEC); BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK); if (flags & ~(EFD_CLOEXEC | EFD_NONBLOCK)) return -EINVAL; ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; init_waitqueue_head(&ctx->wqh); ctx->count = count; /* * When we call this, the initialization must be complete, since * anon_inode_getfd() will install the fd. */ fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx, flags & (O_CLOEXEC | O_NONBLOCK)); if (fd < 0) kfree(ctx); return fd; }
asmlinkage long sys_eventfd(unsigned int count) { int error, fd; struct eventfd_ctx *ctx; struct file *file; struct inode *inode; ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; init_waitqueue_head(&ctx->wqh); ctx->count = count; /* * When we call this, the initialization must be complete, since * anon_inode_getfd() will install the fd. */ error = anon_inode_getfd(&fd, &inode, &file, "[eventfd]", &eventfd_fops, ctx); if (!error) return fd; kfree(ctx); return error; }
static int do_eventfd(unsigned int count, int flags) { struct eventfd_ctx *ctx; int fd; /* Check the EFD_* constants for consistency. */ BUILD_BUG_ON(EFD_CLOEXEC != O_CLOEXEC); BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK); if (flags & ~EFD_FLAGS_SET) return -EINVAL; ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; kref_init(&ctx->kref); init_waitqueue_head(&ctx->wqh); ctx->count = count; ctx->flags = flags; ctx->id = ida_simple_get(&eventfd_ida, 0, 0, GFP_KERNEL); fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx, O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS)); if (fd < 0) eventfd_free_ctx(ctx); return fd; }
SYSCALL_DEFINE4(waitfd, int, which, pid_t, upid, int, options, int, flags) { int ufd; struct waitfd_ctx *ctx; /* * Options validation from do_waitid() */ if (options & ~(WNOHANG|WNOWAIT|WEXITED|WSTOPPED|WCONTINUED)) return -EINVAL; if (!(options & (WEXITED|WSTOPPED|WCONTINUED))) return -EINVAL; ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; ctx->options = options; ctx->upid = upid; ctx->which = which; ufd = anon_inode_getfd("[waitfd]", &waitfd_fops, ctx, O_RDWR | flags | ((options & WNOHANG) ? O_NONBLOCK | 0 : 0)); /* * Use the fd's nonblocking state from now on, since that can change. */ ctx->options &= ~WNOHANG; if (ufd < 0) kfree(ctx); return ufd; }
static int sync_setup(const char *name, const struct file_operations *fops, struct dsscomp_sync_obj *sync, int flags) { if (!sync) return -ENOMEM; sync->refs.counter = 1; sync->fd = anon_inode_getfd(name, fops, sync, flags); return sync->fd < 0 ? sync->fd : 0; }
SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask, size_t, sizemask, int, flags) { sigset_t sigmask; struct signalfd_ctx *ctx; /* Check the SFD_* constants for consistency. */ BUILD_BUG_ON(SFD_CLOEXEC != O_CLOEXEC); BUILD_BUG_ON(SFD_NONBLOCK != O_NONBLOCK); if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK)) return -EINVAL; if (sizemask != sizeof(sigset_t) || copy_from_user(&sigmask, user_mask, sizeof(sigmask))) return -EINVAL; sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); signotset(&sigmask); if (ufd == -1) { ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; ctx->sigmask = sigmask; /* * When we call this, the initialization must be complete, since * anon_inode_getfd() will install the fd. */ ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx, flags & (O_CLOEXEC | O_NONBLOCK)); if (ufd < 0) kfree(ctx); } else { struct file *file = fget(ufd); if (!file) return -EBADF; ctx = file->private_data; if (file->f_op != &signalfd_fops) { fput(file); return -EINVAL; } spin_lock_irq(¤t->sighand->siglock); ctx->sigmask = sigmask; spin_unlock_irq(¤t->sighand->siglock); wake_up(¤t->sighand->signalfd_wqh); fput(file); } return ufd; }
asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask) { int error; sigset_t sigmask; struct signalfd_ctx *ctx; struct file *file; struct inode *inode; if (sizemask != sizeof(sigset_t) || copy_from_user(&sigmask, user_mask, sizeof(sigmask))) return -EINVAL; sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); signotset(&sigmask); if (ufd == -1) { ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; ctx->sigmask = sigmask; /* * When we call this, the initialization must be complete, since * anon_inode_getfd() will install the fd. */ error = anon_inode_getfd(&ufd, &inode, &file, "[signalfd]", &signalfd_fops, ctx); if (error) goto err_fdalloc; } else { file = fget(ufd); if (!file) return -EBADF; ctx = file->private_data; if (file->f_op != &signalfd_fops) { fput(file); return -EINVAL; } spin_lock_irq(¤t->sighand->siglock); ctx->sigmask = sigmask; spin_unlock_irq(¤t->sighand->siglock); wake_up(¤t->sighand->signalfd_wqh); fput(file); } return ufd; err_fdalloc: kfree(ctx); return error; }
SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask, size_t, sizemask, int, flags) { sigset_t sigmask; struct signalfd_ctx *ctx; BUILD_BUG_ON(SFD_CLOEXEC != O_CLOEXEC); BUILD_BUG_ON(SFD_NONBLOCK != O_NONBLOCK); if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK)) return -EINVAL; if (sizemask != sizeof(sigset_t) || copy_from_user(&sigmask, user_mask, sizeof(sigmask))) return -EINVAL; sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); signotset(&sigmask); if (ufd == -1) { ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; ctx->sigmask = sigmask; ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx, O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK))); if (ufd < 0) kfree(ctx); } else { struct file *file = fget(ufd); if (!file) return -EBADF; ctx = file->private_data; if (file->f_op != &signalfd_fops) { fput(file); return -EINVAL; } spin_lock_irq(¤t->sighand->siglock); ctx->sigmask = sigmask; spin_unlock_irq(¤t->sighand->siglock); wake_up(¤t->sighand->signalfd_wqh); fput(file); } return ufd; }
int au_fhsm_fd(struct super_block *sb, int oflags) { int err, fd; struct au_sbinfo *sbinfo; struct au_fhsm *fhsm; err = -EPERM; if (unlikely(!capable(CAP_SYS_ADMIN))) goto out; err = -EINVAL; if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK))) goto out; err = 0; sbinfo = au_sbi(sb); fhsm = &sbinfo->si_fhsm; spin_lock(&fhsm->fhsm_spin); if (!fhsm->fhsm_pid) fhsm->fhsm_pid = current->pid; else err = -EBUSY; spin_unlock(&fhsm->fhsm_spin); if (unlikely(err)) goto out; oflags |= O_RDONLY; /* oflags |= FMODE_NONOTIFY; */ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags); err = fd; if (unlikely(fd < 0)) goto out_pid; /* succeed reglardless 'fhsm' status */ kobject_get(&sbinfo->si_kobj); si_noflush_read_lock(sb); if (au_ftest_si(sbinfo, FHSM)) au_fhsm_wrote_all(sb, /*force*/0); si_read_unlock(sb); goto out; /* success */ out_pid: spin_lock(&fhsm->fhsm_spin); fhsm->fhsm_pid = 0; spin_unlock(&fhsm->fhsm_spin); out: AuTraceErr(err); return err; }
static long hiboma_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { long r = -EINVAL; switch(ioctl) { case HIBOMA_GET_VERSION: r = HIBOMA_VERSION; break; case HIBOMA_OPEN_FD: r = anon_inode_getfd("hiboma-anon", &hiboma_anon_fops, NULL, O_RDWR | O_CLOEXEC); } return r; }
mali_error kbase_stream_create(const char *name, int *const out_fd) { struct sync_timeline *tl; BUG_ON(!out_fd); tl = kbase_sync_timeline_alloc(name); if (!tl) return MALI_ERROR_FUNCTION_FAILED; *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY | O_CLOEXEC); if (*out_fd < 0) { sync_timeline_destroy(tl); return MALI_ERROR_FUNCTION_FAILED; } else { return MALI_ERROR_NONE; } }
int kbase_stream_create(const char *name, int *const out_fd) { struct sync_timeline *tl; BUG_ON(!out_fd); tl = kbase_sync_timeline_alloc(name); if (!tl) return -EINVAL; *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY | O_CLOEXEC); if (*out_fd < 0) { sync_timeline_destroy(tl); return -EINVAL; } return 0; }
/* 这才是真正的epoll_create啊~~ */ SYSCALL_DEFINE1(epoll_create1, int, flags) { int error; struct eventpoll *ep = NULL; /* Check the EPOLL_* constant for consistency. */ /* 这句没啥用处... */ BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC); /* 对于epoll来讲, 目前唯一有效的FLAG就是CLOEXEC */ if (flags & ~EPOLL_CLOEXEC) return -EINVAL; /* * Create the internal data structure ("struct eventpoll"). */ /* 分配一个struct eventpoll, 分配和初始化细节我们随后深聊~ */ error = ep_alloc(&ep); if (error < 0) return error; /* * Creates all the items needed to setup an eventpoll file. That is, * a file structure and a free file descriptor. */ /* 这里是创建一个匿名fd, 说起来就话长了...长话短说: * epollfd本身并不存在一个真正的文件与之对应, 所以内核需要创建一个 * "虚拟"的文件, 并为之分配真正的struct file结构, 而且有真正的fd. * 这里2个参数比较关键: * eventpoll_fops, fops就是file operations, 就是当你对这个文件(这里是虚拟的)进行操作(比如读)时, * fops里面的函数指针指向真正的操作实现, 类似C++里面虚函数和子类的概念. * epoll只实现了poll和release(就是close)操作, 其它文件系统操作都有VFS全权处理了. * ep, ep就是struct epollevent, 它会作为一个私有数据保存在struct file的private指针里面. * 其实说白了, 就是为了能通过fd找到struct file, 通过struct file能找到eventpoll结构. * 如果懂一点Linux下字符设备驱动开发, 这里应该是很好理解的, * 推荐阅读 <Linux device driver 3rd> */ error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep, O_RDWR | (flags & O_CLOEXEC)); if (error < 0) ep_free(ep); return error; }
long do_signalfd(int ufd, sigset_t *sigmask, int flags) { struct signalfd_ctx *ctx; if (ufd == -1) { ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; ctx->sigmask = *sigmask; /* * When we call this, the initialization must be complete, since * anon_inode_getfd() will install the fd. */ ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx, flags & (O_CLOEXEC | O_NONBLOCK)); if (ufd < 0) kfree(ctx); } else { struct file *file = fget(ufd); if (!file) return -EBADF; ctx = file->private_data; if (file->f_op != &signalfd_fops) { fput(file); return -EINVAL; } spin_lock_irq(¤t->sighand->siglock); ctx->sigmask = *sigmask; spin_unlock_irq(¤t->sighand->siglock); wake_up(¤t->sighand->signalfd_wqh); fput(file); } return ufd; }
_mali_osk_errcode_t mali_stream_create(const char * name, int *out_fd) { struct sync_timeline * tl; BUG_ON(!out_fd); tl = mali_sync_timeline_alloc(name); if (!tl) { return _MALI_OSK_ERR_FAULT; } *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY | O_CLOEXEC); if (*out_fd < 0) { sync_timeline_destroy(tl); return _MALI_OSK_ERR_FAULT; } else { return _MALI_OSK_ERR_OK; } }
int tee_session_create_fd(struct tee_context *ctx, struct tee_cmd_io *cmd_io) { int ret; struct tee_session *sess; struct tee *tee = ctx->tee; BUG_ON(cmd_io->fd_sess > 0); dev_dbg(_DEV(tee), "%s: >\n", __func__); sess = tee_session_create_and_open(ctx, cmd_io); if (IS_ERR_OR_NULL(sess)) { ret = PTR_ERR(sess); dev_dbg(_DEV(tee), "%s: ERROR can't create the session (ret=%d, err=0x%08x, org=%d)\n", __func__, ret, cmd_io->err, cmd_io->origin); cmd_io->fd_sess = -1; goto out; } /* Retrieve a fd */ cmd_io->fd_sess = -1; ret = anon_inode_getfd("tee_session", &tee_session_fops, sess, O_CLOEXEC); if (ret < 0) { dev_err(_DEV(tee), "%s: ERROR can't get a fd (ret=%d)\n", __func__, ret); tee_session_close_and_destroy(sess); goto out; } cmd_io->fd_sess = ret; ret = 0; out: dev_dbg(_DEV(tee), "%s: < ret=%d, sess=%p, fd=%d\n", __func__, ret, sess, cmd_io->fd_sess); return ret; }
/* get a file descriptor corresponding to the channel */ int vbus_chnx_get_fd(unsigned char chnr, unsigned char prio, int oflag) { /* supress compiler waring: cast to pointer from integer of different * size */ unsigned long lchnr = chnr; int fd = anon_inode_getfd("[vbus_chnx]", &vbus_chnx_fops, (void*)lchnr, oflag); if (fd > 0) { if (prio == 0) prio = 1; else if (prio > 255) prio = 255; _ctxs[chnr].prio = prio; _ctxs[chnr].datap = NULL; _ctxs[chnr].pos = 0; } _ctxs[chnr].fd = fd; pr_info("get fd: %d, prio: %d\n", fd, prio); return fd; }
/* * Start requested lock. * * Allocates required memory, copies dma_buf_fd list from userspace, * acquires related KDS resources, and starts the lock. */ static int dma_buf_lock_dolock(dma_buf_lock_k_request *request) { dma_buf_lock_resource *resource; int size; int fd; int i; int ret; if (NULL == request->list_of_dma_buf_fds) { return -EINVAL; } if (request->count <= 0) { return -EINVAL; } if (request->count > DMA_BUF_LOCK_BUF_MAX) { return -EINVAL; } if (request->exclusive != DMA_BUF_LOCK_NONEXCLUSIVE && request->exclusive != DMA_BUF_LOCK_EXCLUSIVE) { return -EINVAL; } resource = kzalloc(sizeof(dma_buf_lock_resource), GFP_KERNEL); if (NULL == resource) { return -ENOMEM; } atomic_set(&resource->locked, 0); kref_init(&resource->refcount); INIT_LIST_HEAD(&resource->link); resource->count = request->count; /* Allocate space to store dma_buf_fds received from user space */ size = request->count * sizeof(int); resource->list_of_dma_buf_fds = kmalloc(size, GFP_KERNEL); if (NULL == resource->list_of_dma_buf_fds) { kfree(resource); return -ENOMEM; } /* Allocate space to store dma_buf pointers associated with dma_buf_fds */ size = sizeof(struct dma_buf *) * request->count; resource->dma_bufs = kmalloc(size, GFP_KERNEL); if (NULL == resource->dma_bufs) { kfree(resource->list_of_dma_buf_fds); kfree(resource); return -ENOMEM; } /* Allocate space to store kds_resources associated with dma_buf_fds */ size = sizeof(struct kds_resource *) * request->count; resource->kds_resources = kmalloc(size, GFP_KERNEL); if (NULL == resource->kds_resources) { kfree(resource->dma_bufs); kfree(resource->list_of_dma_buf_fds); kfree(resource); return -ENOMEM; } /* Copy requested list of dma_buf_fds from user space */ size = request->count * sizeof(int); if (0 != copy_from_user(resource->list_of_dma_buf_fds, (void __user *)request->list_of_dma_buf_fds, size)) { kfree(resource->list_of_dma_buf_fds); kfree(resource->dma_bufs); kfree(resource->kds_resources); kfree(resource); return -ENOMEM; } #if DMA_BUF_LOCK_DEBUG for (i = 0; i < request->count; i++) { printk("dma_buf %i = %X\n", i, resource->list_of_dma_buf_fds[i]); } #endif /* Add resource to global list */ mutex_lock(&dma_buf_lock_mutex); list_add(&resource->link, &dma_buf_lock_resource_list); mutex_unlock(&dma_buf_lock_mutex); for (i = 0; i < request->count; i++) { /* Convert fd into dma_buf structure */ resource->dma_bufs[i] = dma_buf_get(resource->list_of_dma_buf_fds[i]); if (IS_ERR_VALUE(PTR_ERR(resource->dma_bufs[i]))) { mutex_lock(&dma_buf_lock_mutex); kref_put(&resource->refcount, dma_buf_lock_dounlock); mutex_unlock(&dma_buf_lock_mutex); return -EINVAL; } /*Get kds_resource associated with dma_buf */ resource->kds_resources[i] = get_dma_buf_kds_resource(resource->dma_bufs[i]); if (NULL == resource->kds_resources[i]) { mutex_lock(&dma_buf_lock_mutex); kref_put(&resource->refcount, dma_buf_lock_dounlock); mutex_unlock(&dma_buf_lock_mutex); return -EINVAL; } #if DMA_BUF_LOCK_DEBUG printk("dma_buf_lock_dolock : dma_buf_fd %i dma_buf %X kds_resource %X\n", resource->list_of_dma_buf_fds[i], (unsigned int)resource->dma_bufs[i], (unsigned int)resource->kds_resources[i]); #endif } kds_callback_init(&resource->cb, 1, dma_buf_lock_kds_callback); init_waitqueue_head(&resource->wait); kref_get(&resource->refcount); /* Create file descriptor associated with lock request */ fd = anon_inode_getfd("dma_buf_lock", &dma_buf_lock_handle_fops, (void *)resource, 0); if (fd < 0) { mutex_lock(&dma_buf_lock_mutex); kref_put(&resource->refcount, dma_buf_lock_dounlock); kref_put(&resource->refcount, dma_buf_lock_dounlock); mutex_unlock(&dma_buf_lock_mutex); return fd; } resource->exclusive = request->exclusive; /* Start locking process */ ret = kds_async_waitall(&resource->resource_set,KDS_FLAG_LOCKED_ACTION, &resource->cb, resource, NULL, request->count, &resource->exclusive, resource->kds_resources); if (IS_ERR_VALUE(ret)) { put_unused_fd(fd); mutex_lock(&dma_buf_lock_mutex); kref_put(&resource->refcount, dma_buf_lock_dounlock); mutex_unlock(&dma_buf_lock_mutex); return ret; } #if DMA_BUF_LOCK_DEBUG printk("dma_buf_lock_dolock : complete\n"); #endif mutex_lock(&dma_buf_lock_mutex); kref_put(&resource->refcount, dma_buf_lock_dounlock); mutex_unlock(&dma_buf_lock_mutex); return fd; }