1/*-
2 * Copyright (c) 2010 Isilon Systems, Inc.
3 * Copyright (c) 2010 iX Systems, Inc.
4 * Copyright (c) 2010 Panasas, Inc.
5 * Copyright (c) 2013-2018 Mellanox Technologies, Ltd.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice unmodified, this list of conditions, and the following
13 *    disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $FreeBSD: stable/11/sys/compat/linuxkpi/common/include/linux/fs.h 341850 2018-12-12 10:09:23Z hselasky $
30 */
31#ifndef	_LINUX_FS_H_
32#define	_LINUX_FS_H_
33
34#include <sys/cdefs.h>
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/conf.h>
38#include <sys/vnode.h>
39#include <sys/file.h>
40#include <sys/filedesc.h>
41#include <linux/types.h>
42#include <linux/wait.h>
43#include <linux/semaphore.h>
44#include <linux/spinlock.h>
45#include <linux/dcache.h>
46
47struct module;
48struct kiocb;
49struct iovec;
50struct dentry;
51struct page;
52struct file_lock;
53struct pipe_inode_info;
54struct vm_area_struct;
55struct poll_table_struct;
56struct files_struct;
57struct pfs_node;
58struct linux_cdev;
59
60#define	inode	vnode
61#define	i_cdev	v_rdev
62#define	i_private v_data
63
64#define	S_IRUGO	(S_IRUSR | S_IRGRP | S_IROTH)
65#define	S_IWUGO	(S_IWUSR | S_IWGRP | S_IWOTH)
66
67
68typedef struct files_struct *fl_owner_t;
69
70struct file_operations;
71
72struct linux_file_wait_queue {
73	struct wait_queue wq;
74	struct wait_queue_head *wqh;
75	atomic_t state;
76#define	LINUX_FWQ_STATE_INIT 0
77#define	LINUX_FWQ_STATE_NOT_READY 1
78#define	LINUX_FWQ_STATE_QUEUED 2
79#define	LINUX_FWQ_STATE_READY 3
80#define	LINUX_FWQ_STATE_MAX 4
81};
82
83struct linux_file {
84	struct file	*_file;
85	const struct file_operations	*f_op;
86	void		*private_data;
87	int		f_flags;
88	int		f_mode;	/* Just starting mode. */
89	struct dentry	*f_dentry;
90	struct dentry	f_dentry_store;
91	struct selinfo	f_selinfo;
92	struct sigio	*f_sigio;
93	struct vnode	*f_vnode;
94#define	f_inode	f_vnode
95	volatile u_int	f_count;
96
97	/* anonymous shmem object */
98	vm_object_t	f_shmem;
99
100	/* kqfilter support */
101	int		f_kqflags;
102#define	LINUX_KQ_FLAG_HAS_READ (1 << 0)
103#define	LINUX_KQ_FLAG_HAS_WRITE (1 << 1)
104#define	LINUX_KQ_FLAG_NEED_READ (1 << 2)
105#define	LINUX_KQ_FLAG_NEED_WRITE (1 << 3)
106	/* protects f_selinfo.si_note */
107	spinlock_t	f_kqlock;
108	struct linux_file_wait_queue f_wait_queue;
109
110	/* pointer to associated character device, if any */
111	struct linux_cdev *f_cdev;
112};
113
114#define	file		linux_file
115#define	fasync_struct	sigio *
116
117#define	fasync_helper(fd, filp, on, queue)				\
118({									\
119	if ((on))							\
120		*(queue) = &(filp)->f_sigio;				\
121	else								\
122		*(queue) = NULL;					\
123	0;								\
124})
125
126#define	kill_fasync(queue, sig, pollstat)				\
127do {									\
128	if (*(queue) != NULL)						\
129		pgsigio(*(queue), (sig), 0);				\
130} while (0)
131
132typedef int (*filldir_t)(void *, const char *, int, loff_t, u64, unsigned);
133
134struct file_operations {
135	struct module *owner;
136	ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
137	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
138	unsigned int (*poll) (struct file *, struct poll_table_struct *);
139	long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
140	long (*compat_ioctl)(struct file *, unsigned int, unsigned long);
141	int (*mmap)(struct file *, struct vm_area_struct *);
142	int (*open)(struct inode *, struct file *);
143	int (*release)(struct inode *, struct file *);
144	int (*fasync)(int, struct file *, int);
145
146/* Although not supported in FreeBSD, to align with Linux code
147 * we are adding llseek() only when it is mapped to no_llseek which returns
148 * an illegal seek error
149 */
150	loff_t (*llseek)(struct file *, loff_t, int);
151#if 0
152	/* We do not support these methods.  Don't permit them to compile. */
153	loff_t (*llseek)(struct file *, loff_t, int);
154	ssize_t (*aio_read)(struct kiocb *, const struct iovec *,
155	    unsigned long, loff_t);
156	ssize_t (*aio_write)(struct kiocb *, const struct iovec *,
157	    unsigned long, loff_t);
158	int (*readdir)(struct file *, void *, filldir_t);
159	int (*ioctl)(struct inode *, struct file *, unsigned int,
160	    unsigned long);
161	int (*flush)(struct file *, fl_owner_t id);
162	int (*fsync)(struct file *, struct dentry *, int datasync);
163	int (*aio_fsync)(struct kiocb *, int datasync);
164	int (*lock)(struct file *, int, struct file_lock *);
165	ssize_t (*sendpage)(struct file *, struct page *, int, size_t,
166	    loff_t *, int);
167	unsigned long (*get_unmapped_area)(struct file *, unsigned long,
168	    unsigned long, unsigned long, unsigned long);
169	int (*check_flags)(int);
170	int (*flock)(struct file *, int, struct file_lock *);
171	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
172	    loff_t *, size_t, unsigned int);
173	ssize_t (*splice_read)(struct file *, loff_t *,
174	    struct pipe_inode_info *, size_t, unsigned int);
175	int (*setlease)(struct file *, long, struct file_lock **);
176#endif
177};
178#define	fops_get(fops)		(fops)
179#define	replace_fops(f, fops)	((f)->f_op = (fops))
180
181#define	FMODE_READ	FREAD
182#define	FMODE_WRITE	FWRITE
183#define	FMODE_EXEC	FEXEC
184
185int __register_chrdev(unsigned int major, unsigned int baseminor,
186    unsigned int count, const char *name,
187    const struct file_operations *fops);
188int __register_chrdev_p(unsigned int major, unsigned int baseminor,
189    unsigned int count, const char *name,
190    const struct file_operations *fops, uid_t uid,
191    gid_t gid, int mode);
192void __unregister_chrdev(unsigned int major, unsigned int baseminor,
193    unsigned int count, const char *name);
194
195static inline void
196unregister_chrdev(unsigned int major, const char *name)
197{
198
199	__unregister_chrdev(major, 0, 256, name);
200}
201
202static inline int
203register_chrdev(unsigned int major, const char *name,
204    const struct file_operations *fops)
205{
206
207	return (__register_chrdev(major, 0, 256, name, fops));
208}
209
210static inline int
211register_chrdev_p(unsigned int major, const char *name,
212    const struct file_operations *fops, uid_t uid, gid_t gid, int mode)
213{
214
215	return (__register_chrdev_p(major, 0, 256, name, fops, uid, gid, mode));
216}
217
218static inline int
219register_chrdev_region(dev_t dev, unsigned range, const char *name)
220{
221
222	return 0;
223}
224
225static inline void
226unregister_chrdev_region(dev_t dev, unsigned range)
227{
228
229	return;
230}
231
232static inline int
233alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
234			const char *name)
235{
236
237	return 0;
238}
239
240/* No current support for seek op in FreeBSD */
241static inline int
242nonseekable_open(struct inode *inode, struct file *filp)
243{
244	return 0;
245}
246
247extern unsigned int linux_iminor(struct inode *);
248#define	iminor(...) linux_iminor(__VA_ARGS__)
249
250static inline struct linux_file *
251get_file(struct linux_file *f)
252{
253
254	refcount_acquire(f->_file == NULL ? &f->f_count : &f->_file->f_count);
255	return (f);
256}
257
258static inline struct inode *
259igrab(struct inode *inode)
260{
261	int error;
262
263	error = vget(inode, 0, curthread);
264	if (error)
265		return (NULL);
266
267	return (inode);
268}
269
270static inline void
271iput(struct inode *inode)
272{
273
274	vrele(inode);
275}
276
277static inline loff_t
278no_llseek(struct file *file, loff_t offset, int whence)
279{
280
281	return (-ESPIPE);
282}
283
284static inline loff_t
285noop_llseek(struct linux_file *file, loff_t offset, int whence)
286{
287
288	return (file->_file->f_offset);
289}
290
291static inline struct vnode *
292file_inode(const struct linux_file *file)
293{
294
295	return (file->f_vnode);
296}
297
298static inline int
299call_mmap(struct linux_file *file, struct vm_area_struct *vma)
300{
301
302	return (file->f_op->mmap(file, vma));
303}
304
305/* Shared memory support */
306unsigned long linux_invalidate_mapping_pages(vm_object_t, pgoff_t, pgoff_t);
307struct page *linux_shmem_read_mapping_page_gfp(vm_object_t, int, gfp_t);
308struct linux_file *linux_shmem_file_setup(const char *, loff_t, unsigned long);
309void linux_shmem_truncate_range(vm_object_t, loff_t, loff_t);
310
311#define	invalidate_mapping_pages(...) \
312  linux_invalidate_mapping_pages(__VA_ARGS__)
313
314#define	shmem_read_mapping_page(...) \
315  linux_shmem_read_mapping_page_gfp(__VA_ARGS__, 0)
316
317#define	shmem_read_mapping_page_gfp(...) \
318  linux_shmem_read_mapping_page_gfp(__VA_ARGS__)
319
320#define	shmem_file_setup(...) \
321  linux_shmem_file_setup(__VA_ARGS__)
322
323#define	shmem_truncate_range(...) \
324  linux_shmem_truncate_range(__VA_ARGS__)
325
326#endif /* _LINUX_FS_H_ */
327