Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
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(&current->sighand->siglock);
		ctx->sigmask = sigmask;
		spin_unlock_irq(&current->sighand->siglock);

		wake_up(&current->sighand->signalfd_wqh);
		fput(file);
	}

	return ufd;
}
Ejemplo n.º 7
0
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(&current->sighand->siglock);
		ctx->sigmask = sigmask;
		spin_unlock_irq(&current->sighand->siglock);

		wake_up(&current->sighand->signalfd_wqh);
		fput(file);
	}

	return ufd;

err_fdalloc:
	kfree(ctx);
	return error;
}
Ejemplo n.º 8
0
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(&current->sighand->siglock);
        ctx->sigmask = sigmask;
        spin_unlock_irq(&current->sighand->siglock);

        wake_up(&current->sighand->signalfd_wqh);
        fput(file);
    }

    return ufd;
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
0
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(&current->sighand->siglock);
		ctx->sigmask = *sigmask;
		spin_unlock_irq(&current->sighand->siglock);

		wake_up(&current->sighand->signalfd_wqh);
		fput(file);
	}

	return ufd;
}
Ejemplo n.º 15
0
_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;
	}
}
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
0
/* 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;
}