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