file.h revision 284443
1193240Ssam/*-
2193240Ssam * Copyright (c) 2010 Isilon Systems, Inc.
3193240Ssam * Copyright (c) 2010 iX Systems, Inc.
4193240Ssam * Copyright (c) 2010 Panasas, Inc.
5193240Ssam * Copyright (c) 2013 Mellanox Technologies, Ltd.
6193240Ssam * All rights reserved.
7193240Ssam *
8193240Ssam * Redistribution and use in source and binary forms, with or without
9193240Ssam * modification, are permitted provided that the following conditions
10193240Ssam * are met:
11193240Ssam * 1. Redistributions of source code must retain the above copyright
12193240Ssam *    notice unmodified, this list of conditions, and the following
13193240Ssam *    disclaimer.
14193240Ssam * 2. Redistributions in binary form must reproduce the above copyright
15193240Ssam *    notice, this list of conditions and the following disclaimer in the
16193240Ssam *    documentation and/or other materials provided with the distribution.
17193240Ssam *
18193240Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19193240Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20193240Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21193240Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22193240Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23193240Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24193240Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25193240Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26193240Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27193240Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28193240Ssam */
29193240Ssam#ifndef	_LINUX_FILE_H_
30193240Ssam#define	_LINUX_FILE_H_
31193240Ssam
32193240Ssam#include <sys/param.h>
33193240Ssam#include <sys/file.h>
34193240Ssam#include <sys/filedesc.h>
35193240Ssam#include <sys/refcount.h>
36234866Suqs#include <sys/capsicum.h>
37193240Ssam#include <sys/proc.h>
38193240Ssam
39193240Ssam#include <linux/fs.h>
40193240Ssam
41193240Ssamstruct linux_file;
42
43#undef file
44
45extern struct fileops linuxfileops;
46
47static inline struct linux_file *
48linux_fget(unsigned int fd)
49{
50	cap_rights_t rights;
51	struct file *file;
52
53	if (fget_unlocked(curthread->td_proc->p_fd, fd,
54	    cap_rights_init(&rights), &file, NULL) != 0) {
55		return (NULL);
56	}
57	return (struct linux_file *)file->f_data;
58}
59
60static inline void
61fput(struct linux_file *filp)
62{
63	if (filp->_file == NULL) {
64		kfree(filp);
65		return;
66	}
67	if (refcount_release(&filp->_file->f_count)) {
68		_fdrop(filp->_file, curthread);
69		kfree(filp);
70	}
71}
72
73static inline void
74put_unused_fd(unsigned int fd)
75{
76	cap_rights_t rights;
77	struct file *file;
78
79	if (fget_unlocked(curthread->td_proc->p_fd, fd,
80	    cap_rights_init(&rights), &file, NULL) != 0) {
81		return;
82	}
83	/*
84	 * NOTE: We should only get here when the "fd" has not been
85	 * installed, so no need to free the associated Linux file
86	 * structure.
87	 */
88	fdclose(curthread, file, fd);
89
90	/* drop extra reference */
91	fdrop(file, curthread);
92}
93
94static inline void
95fd_install(unsigned int fd, struct linux_file *filp)
96{
97	cap_rights_t rights;
98	struct file *file;
99
100	if (fget_unlocked(curthread->td_proc->p_fd, fd,
101	    cap_rights_init(&rights), &file, NULL) != 0) {
102		file = NULL;
103	}
104	filp->_file = file;
105	finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops);
106
107	/* drop the extra reference */
108	fput(filp);
109}
110
111static inline int
112get_unused_fd(void)
113{
114	struct file *file;
115	int error;
116	int fd;
117
118	error = falloc(curthread, &file, &fd, 0);
119	if (error)
120		return -error;
121	/* drop the extra reference */
122	fdrop(file, curthread);
123	return fd;
124}
125
126static inline struct linux_file *
127alloc_file(int mode, const struct file_operations *fops)
128{
129	struct linux_file *filp;
130
131	filp = kzalloc(sizeof(*filp), GFP_KERNEL);
132	if (filp == NULL)
133		return (NULL);
134	filp->f_op = fops;
135	filp->f_mode = mode;
136
137	return filp;
138}
139
140struct fd {
141	struct linux_file *linux_file;
142};
143
144static inline void fdput(struct fd fd)
145{
146	fput(fd.linux_file);
147}
148
149static inline struct fd fdget(unsigned int fd)
150{
151	struct linux_file *f = linux_fget(fd);
152	return (struct fd){f};
153}
154
155#define	file	linux_file
156#define	fget	linux_fget
157
158#endif	/* _LINUX_FILE_H_ */
159