1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22#include <sys/zfs_context.h>
23#include <sys/zfs_file.h>
24#include <sys/stat.h>
25#include <sys/file.h>
26#include <linux/falloc.h>
27#include <linux/fs.h>
28#include <linux/uaccess.h>
29#ifdef HAVE_FDTABLE_HEADER
30#include <linux/fdtable.h>
31#endif
32
33/*
34 * Open file
35 *
36 * path - fully qualified path to file
37 * flags - file attributes O_READ / O_WRITE / O_EXCL
38 * fpp - pointer to return file pointer
39 *
40 * Returns 0 on success underlying error on failure.
41 */
42int
43zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp)
44{
45	struct file *filp;
46	int saved_umask;
47
48	if (!(flags & O_CREAT) && (flags & O_WRONLY))
49		flags |= O_EXCL;
50
51	if (flags & O_CREAT)
52		saved_umask = xchg(&current->fs->umask, 0);
53
54	filp = filp_open(path, flags, mode);
55
56	if (flags & O_CREAT)
57		(void) xchg(&current->fs->umask, saved_umask);
58
59	if (IS_ERR(filp))
60		return (-PTR_ERR(filp));
61
62	*fpp = filp;
63	return (0);
64}
65
66void
67zfs_file_close(zfs_file_t *fp)
68{
69	filp_close(fp, 0);
70}
71
72static ssize_t
73zfs_file_write_impl(zfs_file_t *fp, const void *buf, size_t count, loff_t *off)
74{
75#if defined(HAVE_KERNEL_WRITE_PPOS)
76	return (kernel_write(fp, buf, count, off));
77#else
78	mm_segment_t saved_fs;
79	ssize_t rc;
80
81	saved_fs = get_fs();
82	set_fs(KERNEL_DS);
83
84	rc = vfs_write(fp, (__force const char __user __user *)buf, count, off);
85
86	set_fs(saved_fs);
87
88	return (rc);
89#endif
90}
91
92/*
93 * Stateful write - use os internal file pointer to determine where to
94 * write and update on successful completion.
95 *
96 * fp -  pointer to file (pipe, socket, etc) to write to
97 * buf - buffer to write
98 * count - # of bytes to write
99 * resid -  pointer to count of unwritten bytes  (if short write)
100 *
101 * Returns 0 on success errno on failure.
102 */
103int
104zfs_file_write(zfs_file_t *fp, const void *buf, size_t count, ssize_t *resid)
105{
106	loff_t off = fp->f_pos;
107	ssize_t rc;
108
109	rc = zfs_file_write_impl(fp, buf, count, &off);
110	if (rc < 0)
111		return (-rc);
112
113	fp->f_pos = off;
114
115	if (resid) {
116		*resid = count - rc;
117	} else if (rc != count) {
118		return (EIO);
119	}
120
121	return (0);
122}
123
124/*
125 * Stateless write - os internal file pointer is not updated.
126 *
127 * fp -  pointer to file (pipe, socket, etc) to write to
128 * buf - buffer to write
129 * count - # of bytes to write
130 * off - file offset to write to (only valid for seekable types)
131 * resid -  pointer to count of unwritten bytes
132 *
133 * Returns 0 on success errno on failure.
134 */
135int
136zfs_file_pwrite(zfs_file_t *fp, const void *buf, size_t count, loff_t off,
137    ssize_t *resid)
138{
139	ssize_t rc;
140
141	rc  = zfs_file_write_impl(fp, buf, count, &off);
142	if (rc < 0)
143		return (-rc);
144
145	if (resid) {
146		*resid = count - rc;
147	} else if (rc != count) {
148		return (EIO);
149	}
150
151	return (0);
152}
153
154static ssize_t
155zfs_file_read_impl(zfs_file_t *fp, void *buf, size_t count, loff_t *off)
156{
157#if defined(HAVE_KERNEL_READ_PPOS)
158	return (kernel_read(fp, buf, count, off));
159#else
160	mm_segment_t saved_fs;
161	ssize_t rc;
162
163	saved_fs = get_fs();
164	set_fs(KERNEL_DS);
165
166	rc = vfs_read(fp, (void __user *)buf, count, off);
167	set_fs(saved_fs);
168
169	return (rc);
170#endif
171}
172
173/*
174 * Stateful read - use os internal file pointer to determine where to
175 * read and update on successful completion.
176 *
177 * fp -  pointer to file (pipe, socket, etc) to read from
178 * buf - buffer to write
179 * count - # of bytes to read
180 * resid -  pointer to count of unread bytes (if short read)
181 *
182 * Returns 0 on success errno on failure.
183 */
184int
185zfs_file_read(zfs_file_t *fp, void *buf, size_t count, ssize_t *resid)
186{
187	loff_t off = fp->f_pos;
188	ssize_t rc;
189
190	rc = zfs_file_read_impl(fp, buf, count, &off);
191	if (rc < 0)
192		return (-rc);
193
194	fp->f_pos = off;
195
196	if (resid) {
197		*resid = count - rc;
198	} else if (rc != count) {
199		return (EIO);
200	}
201
202	return (0);
203}
204
205/*
206 * Stateless read - os internal file pointer is not updated.
207 *
208 * fp -  pointer to file (pipe, socket, etc) to read from
209 * buf - buffer to write
210 * count - # of bytes to write
211 * off - file offset to read from (only valid for seekable types)
212 * resid -  pointer to count of unwritten bytes (if short write)
213 *
214 * Returns 0 on success errno on failure.
215 */
216int
217zfs_file_pread(zfs_file_t *fp, void *buf, size_t count, loff_t off,
218    ssize_t *resid)
219{
220	ssize_t rc;
221
222	rc = zfs_file_read_impl(fp, buf, count, &off);
223	if (rc < 0)
224		return (-rc);
225
226	if (resid) {
227		*resid = count - rc;
228	} else if (rc != count) {
229		return (EIO);
230	}
231
232	return (0);
233}
234
235/*
236 * lseek - set / get file pointer
237 *
238 * fp -  pointer to file (pipe, socket, etc) to read from
239 * offp - value to seek to, returns current value plus passed offset
240 * whence - see man pages for standard lseek whence values
241 *
242 * Returns 0 on success errno on failure (ESPIPE for non seekable types)
243 */
244int
245zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence)
246{
247	loff_t rc;
248
249	if (*offp < 0)
250		return (EINVAL);
251
252	rc = vfs_llseek(fp, *offp, whence);
253	if (rc < 0)
254		return (-rc);
255
256	*offp = rc;
257
258	return (0);
259}
260
261/*
262 * Get file attributes
263 *
264 * filp - file pointer
265 * zfattr - pointer to file attr structure
266 *
267 * Currently only used for fetching size and file mode.
268 *
269 * Returns 0 on success or error code of underlying getattr call on failure.
270 */
271int
272zfs_file_getattr(zfs_file_t *filp, zfs_file_attr_t *zfattr)
273{
274	struct kstat stat;
275	int rc;
276
277#if defined(HAVE_4ARGS_VFS_GETATTR)
278	rc = vfs_getattr(&filp->f_path, &stat, STATX_BASIC_STATS,
279	    AT_STATX_SYNC_AS_STAT);
280#elif defined(HAVE_2ARGS_VFS_GETATTR)
281	rc = vfs_getattr(&filp->f_path, &stat);
282#elif defined(HAVE_3ARGS_VFS_GETATTR)
283	rc = vfs_getattr(filp->f_path.mnt, filp->f_dentry, &stat);
284#else
285#error "No available vfs_getattr()"
286#endif
287	if (rc)
288		return (-rc);
289
290	zfattr->zfa_size = stat.size;
291	zfattr->zfa_mode = stat.mode;
292
293	return (0);
294}
295
296/*
297 * Sync file to disk
298 *
299 * filp - file pointer
300 * flags - O_SYNC and or O_DSYNC
301 *
302 * Returns 0 on success or error code of underlying sync call on failure.
303 */
304int
305zfs_file_fsync(zfs_file_t *filp, int flags)
306{
307	int datasync = 0;
308	int error;
309	int fstrans;
310
311	if (flags & O_DSYNC)
312		datasync = 1;
313
314	/*
315	 * May enter XFS which generates a warning when PF_FSTRANS is set.
316	 * To avoid this the flag is cleared over vfs_sync() and then reset.
317	 */
318	fstrans = __spl_pf_fstrans_check();
319	if (fstrans)
320		current->flags &= ~(__SPL_PF_FSTRANS);
321
322	error = -vfs_fsync(filp, datasync);
323
324	if (fstrans)
325		current->flags |= __SPL_PF_FSTRANS;
326
327	return (error);
328}
329
330/*
331 * fallocate - allocate or free space on disk
332 *
333 * fp - file pointer
334 * mode (non-standard options for hole punching etc)
335 * offset - offset to start allocating or freeing from
336 * len - length to free / allocate
337 *
338 * OPTIONAL
339 */
340int
341zfs_file_fallocate(zfs_file_t *fp, int mode, loff_t offset, loff_t len)
342{
343	/*
344	 * May enter XFS which generates a warning when PF_FSTRANS is set.
345	 * To avoid this the flag is cleared over vfs_sync() and then reset.
346	 */
347	int fstrans = __spl_pf_fstrans_check();
348	if (fstrans)
349		current->flags &= ~(__SPL_PF_FSTRANS);
350
351	/*
352	 * When supported by the underlying file system preferentially
353	 * use the fallocate() callback to preallocate the space.
354	 */
355	int error = EOPNOTSUPP;
356	if (fp->f_op->fallocate)
357		error = fp->f_op->fallocate(fp, mode, offset, len);
358
359	if (fstrans)
360		current->flags |= __SPL_PF_FSTRANS;
361
362	return (error);
363}
364
365/*
366 * Request current file pointer offset
367 *
368 * fp - pointer to file
369 *
370 * Returns current file offset.
371 */
372loff_t
373zfs_file_off(zfs_file_t *fp)
374{
375	return (fp->f_pos);
376}
377
378/*
379 * Request file pointer private data
380 *
381 * fp - pointer to file
382 *
383 * Returns pointer to file private data.
384 */
385void *
386zfs_file_private(zfs_file_t *fp)
387{
388	return (fp->private_data);
389}
390
391/*
392 * unlink file
393 *
394 * path - fully qualified file path
395 *
396 * Returns 0 on success.
397 *
398 * OPTIONAL
399 */
400int
401zfs_file_unlink(const char *path)
402{
403	return (EOPNOTSUPP);
404}
405
406/*
407 * Get reference to file pointer
408 *
409 * fd - input file descriptor
410 *
411 * Returns pointer to file struct or NULL
412 */
413zfs_file_t *
414zfs_file_get(int fd)
415{
416	return (fget(fd));
417}
418
419/*
420 * Drop reference to file pointer
421 *
422 * fp - input file struct pointer
423 */
424void
425zfs_file_put(zfs_file_t *fp)
426{
427	fput(fp);
428}
429