blob: ab5e92897270ae7ef4e9f3dd228769ef897eef7c [file] [log] [blame]
David Brazdil0f672f62019-12-10 10:32:29 +00001// SPDX-License-Identifier: GPL-2.0-only
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002/*
3 * Copyright (C) 2017 Red Hat, Inc.
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004 */
5
6#include <linux/cred.h>
7#include <linux/file.h>
8#include <linux/mount.h>
9#include <linux/xattr.h>
10#include <linux/uio.h>
David Brazdil0f672f62019-12-10 10:32:29 +000011#include <linux/uaccess.h>
Olivier Deprez0e641232021-09-23 10:07:05 +020012#include <linux/splice.h>
13#include <linux/mm.h>
14#include <linux/fs.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000015#include "overlayfs.h"
16
17static char ovl_whatisit(struct inode *inode, struct inode *realinode)
18{
19 if (realinode != ovl_inode_upper(inode))
20 return 'l';
21 if (ovl_has_upperdata(inode))
22 return 'u';
23 else
24 return 'm';
25}
26
Olivier Deprez0e641232021-09-23 10:07:05 +020027/* No atime modificaton nor notify on underlying */
28#define OVL_OPEN_FLAGS (O_NOATIME | FMODE_NONOTIFY)
29
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000030static struct file *ovl_open_realfile(const struct file *file,
31 struct inode *realinode)
32{
33 struct inode *inode = file_inode(file);
34 struct file *realfile;
35 const struct cred *old_cred;
Olivier Deprez0e641232021-09-23 10:07:05 +020036 int flags = file->f_flags | OVL_OPEN_FLAGS;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000037
38 old_cred = ovl_override_creds(inode->i_sb);
David Brazdil0f672f62019-12-10 10:32:29 +000039 realfile = open_with_fake_path(&file->f_path, flags, realinode,
40 current_cred());
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000041 revert_creds(old_cred);
42
43 pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",
44 file, file, ovl_whatisit(inode, realinode), file->f_flags,
45 realfile, IS_ERR(realfile) ? 0 : realfile->f_flags);
46
47 return realfile;
48}
49
50#define OVL_SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT)
51
52static int ovl_change_flags(struct file *file, unsigned int flags)
53{
54 struct inode *inode = file_inode(file);
55 int err;
56
Olivier Deprez0e641232021-09-23 10:07:05 +020057 flags |= OVL_OPEN_FLAGS;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000058
59 /* If some flag changed that cannot be changed then something's amiss */
60 if (WARN_ON((file->f_flags ^ flags) & ~OVL_SETFL_MASK))
61 return -EIO;
62
63 flags &= OVL_SETFL_MASK;
64
65 if (((flags ^ file->f_flags) & O_APPEND) && IS_APPEND(inode))
66 return -EPERM;
67
68 if (flags & O_DIRECT) {
69 if (!file->f_mapping->a_ops ||
70 !file->f_mapping->a_ops->direct_IO)
71 return -EINVAL;
72 }
73
74 if (file->f_op->check_flags) {
75 err = file->f_op->check_flags(flags);
76 if (err)
77 return err;
78 }
79
80 spin_lock(&file->f_lock);
81 file->f_flags = (file->f_flags & ~OVL_SETFL_MASK) | flags;
82 spin_unlock(&file->f_lock);
83
84 return 0;
85}
86
87static int ovl_real_fdget_meta(const struct file *file, struct fd *real,
88 bool allow_meta)
89{
90 struct inode *inode = file_inode(file);
91 struct inode *realinode;
92
93 real->flags = 0;
94 real->file = file->private_data;
95
96 if (allow_meta)
97 realinode = ovl_inode_real(inode);
98 else
99 realinode = ovl_inode_realdata(inode);
100
101 /* Has it been copied up since we'd opened it? */
102 if (unlikely(file_inode(real->file) != realinode)) {
103 real->flags = FDPUT_FPUT;
104 real->file = ovl_open_realfile(file, realinode);
105
106 return PTR_ERR_OR_ZERO(real->file);
107 }
108
109 /* Did the flags change since open? */
Olivier Deprez0e641232021-09-23 10:07:05 +0200110 if (unlikely((file->f_flags ^ real->file->f_flags) & ~OVL_OPEN_FLAGS))
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000111 return ovl_change_flags(real->file, file->f_flags);
112
113 return 0;
114}
115
116static int ovl_real_fdget(const struct file *file, struct fd *real)
117{
118 return ovl_real_fdget_meta(file, real, false);
119}
120
121static int ovl_open(struct inode *inode, struct file *file)
122{
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000123 struct file *realfile;
124 int err;
125
David Brazdil0f672f62019-12-10 10:32:29 +0000126 err = ovl_maybe_copy_up(file_dentry(file), file->f_flags);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000127 if (err)
128 return err;
129
130 /* No longer need these flags, so don't pass them on to underlying fs */
131 file->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
132
133 realfile = ovl_open_realfile(file, ovl_inode_realdata(inode));
134 if (IS_ERR(realfile))
135 return PTR_ERR(realfile);
136
137 file->private_data = realfile;
138
139 return 0;
140}
141
142static int ovl_release(struct inode *inode, struct file *file)
143{
144 fput(file->private_data);
145
146 return 0;
147}
148
149static loff_t ovl_llseek(struct file *file, loff_t offset, int whence)
150{
David Brazdil0f672f62019-12-10 10:32:29 +0000151 struct inode *inode = file_inode(file);
152 struct fd real;
153 const struct cred *old_cred;
Olivier Deprez0e641232021-09-23 10:07:05 +0200154 loff_t ret;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000155
David Brazdil0f672f62019-12-10 10:32:29 +0000156 /*
157 * The two special cases below do not need to involve real fs,
158 * so we can optimizing concurrent callers.
159 */
160 if (offset == 0) {
161 if (whence == SEEK_CUR)
162 return file->f_pos;
163
164 if (whence == SEEK_SET)
165 return vfs_setpos(file, 0, 0);
166 }
167
168 ret = ovl_real_fdget(file, &real);
169 if (ret)
170 return ret;
171
172 /*
173 * Overlay file f_pos is the master copy that is preserved
174 * through copy up and modified on read/write, but only real
175 * fs knows how to SEEK_HOLE/SEEK_DATA and real fs may impose
176 * limitations that are more strict than ->s_maxbytes for specific
177 * files, so we use the real file to perform seeks.
178 */
179 inode_lock(inode);
180 real.file->f_pos = file->f_pos;
181
182 old_cred = ovl_override_creds(inode->i_sb);
183 ret = vfs_llseek(real.file, offset, whence);
184 revert_creds(old_cred);
185
186 file->f_pos = real.file->f_pos;
187 inode_unlock(inode);
188
189 fdput(real);
190
191 return ret;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000192}
193
194static void ovl_file_accessed(struct file *file)
195{
196 struct inode *inode, *upperinode;
197
198 if (file->f_flags & O_NOATIME)
199 return;
200
201 inode = file_inode(file);
202 upperinode = ovl_inode_upper(inode);
203
204 if (!upperinode)
205 return;
206
207 if ((!timespec64_equal(&inode->i_mtime, &upperinode->i_mtime) ||
208 !timespec64_equal(&inode->i_ctime, &upperinode->i_ctime))) {
209 inode->i_mtime = upperinode->i_mtime;
210 inode->i_ctime = upperinode->i_ctime;
211 }
212
213 touch_atime(&file->f_path);
214}
215
216static rwf_t ovl_iocb_to_rwf(struct kiocb *iocb)
217{
218 int ifl = iocb->ki_flags;
219 rwf_t flags = 0;
220
221 if (ifl & IOCB_NOWAIT)
222 flags |= RWF_NOWAIT;
223 if (ifl & IOCB_HIPRI)
224 flags |= RWF_HIPRI;
225 if (ifl & IOCB_DSYNC)
226 flags |= RWF_DSYNC;
227 if (ifl & IOCB_SYNC)
228 flags |= RWF_SYNC;
229
230 return flags;
231}
232
233static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter)
234{
235 struct file *file = iocb->ki_filp;
236 struct fd real;
237 const struct cred *old_cred;
238 ssize_t ret;
239
240 if (!iov_iter_count(iter))
241 return 0;
242
243 ret = ovl_real_fdget(file, &real);
244 if (ret)
245 return ret;
246
247 old_cred = ovl_override_creds(file_inode(file)->i_sb);
248 ret = vfs_iter_read(real.file, iter, &iocb->ki_pos,
249 ovl_iocb_to_rwf(iocb));
250 revert_creds(old_cred);
251
252 ovl_file_accessed(file);
253
254 fdput(real);
255
256 return ret;
257}
258
259static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
260{
261 struct file *file = iocb->ki_filp;
262 struct inode *inode = file_inode(file);
263 struct fd real;
264 const struct cred *old_cred;
265 ssize_t ret;
266
267 if (!iov_iter_count(iter))
268 return 0;
269
270 inode_lock(inode);
271 /* Update mode */
272 ovl_copyattr(ovl_inode_real(inode), inode);
273 ret = file_remove_privs(file);
274 if (ret)
275 goto out_unlock;
276
277 ret = ovl_real_fdget(file, &real);
278 if (ret)
279 goto out_unlock;
280
281 old_cred = ovl_override_creds(file_inode(file)->i_sb);
282 file_start_write(real.file);
283 ret = vfs_iter_write(real.file, iter, &iocb->ki_pos,
284 ovl_iocb_to_rwf(iocb));
285 file_end_write(real.file);
286 revert_creds(old_cred);
287
288 /* Update size */
289 ovl_copyattr(ovl_inode_real(inode), inode);
290
291 fdput(real);
292
293out_unlock:
294 inode_unlock(inode);
295
296 return ret;
297}
298
Olivier Deprez0e641232021-09-23 10:07:05 +0200299static ssize_t ovl_splice_read(struct file *in, loff_t *ppos,
300 struct pipe_inode_info *pipe, size_t len,
301 unsigned int flags)
302{
303 ssize_t ret;
304 struct fd real;
305 const struct cred *old_cred;
306
307 ret = ovl_real_fdget(in, &real);
308 if (ret)
309 return ret;
310
311 old_cred = ovl_override_creds(file_inode(in)->i_sb);
312 ret = generic_file_splice_read(real.file, ppos, pipe, len, flags);
313 revert_creds(old_cred);
314
315 ovl_file_accessed(in);
316 fdput(real);
317 return ret;
318}
319
320static ssize_t
321ovl_splice_write(struct pipe_inode_info *pipe, struct file *out,
322 loff_t *ppos, size_t len, unsigned int flags)
323{
324 struct fd real;
325 const struct cred *old_cred;
326 ssize_t ret;
327
328 ret = ovl_real_fdget(out, &real);
329 if (ret)
330 return ret;
331
332 old_cred = ovl_override_creds(file_inode(out)->i_sb);
333 ret = iter_file_splice_write(pipe, real.file, ppos, len, flags);
334 revert_creds(old_cred);
335
336 ovl_file_accessed(out);
337 fdput(real);
338 return ret;
339}
340
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000341static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
342{
343 struct fd real;
344 const struct cred *old_cred;
345 int ret;
346
347 ret = ovl_real_fdget_meta(file, &real, !datasync);
348 if (ret)
349 return ret;
350
351 /* Don't sync lower file for fear of receiving EROFS error */
352 if (file_inode(real.file) == ovl_inode_upper(file_inode(file))) {
353 old_cred = ovl_override_creds(file_inode(file)->i_sb);
354 ret = vfs_fsync_range(real.file, start, end, datasync);
355 revert_creds(old_cred);
356 }
357
358 fdput(real);
359
360 return ret;
361}
362
363static int ovl_mmap(struct file *file, struct vm_area_struct *vma)
364{
365 struct file *realfile = file->private_data;
366 const struct cred *old_cred;
367 int ret;
368
369 if (!realfile->f_op->mmap)
370 return -ENODEV;
371
372 if (WARN_ON(file != vma->vm_file))
373 return -EIO;
374
375 vma->vm_file = get_file(realfile);
376
377 old_cred = ovl_override_creds(file_inode(file)->i_sb);
378 ret = call_mmap(vma->vm_file, vma);
379 revert_creds(old_cred);
380
381 if (ret) {
382 /* Drop reference count from new vm_file value */
383 fput(realfile);
384 } else {
385 /* Drop reference count from previous vm_file value */
386 fput(file);
387 }
388
389 ovl_file_accessed(file);
390
391 return ret;
392}
393
394static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
395{
396 struct inode *inode = file_inode(file);
397 struct fd real;
398 const struct cred *old_cred;
399 int ret;
400
401 ret = ovl_real_fdget(file, &real);
402 if (ret)
403 return ret;
404
405 old_cred = ovl_override_creds(file_inode(file)->i_sb);
406 ret = vfs_fallocate(real.file, mode, offset, len);
407 revert_creds(old_cred);
408
409 /* Update size */
410 ovl_copyattr(ovl_inode_real(inode), inode);
411
412 fdput(real);
413
414 return ret;
415}
416
417static int ovl_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
418{
419 struct fd real;
420 const struct cred *old_cred;
421 int ret;
422
423 ret = ovl_real_fdget(file, &real);
424 if (ret)
425 return ret;
426
427 old_cred = ovl_override_creds(file_inode(file)->i_sb);
428 ret = vfs_fadvise(real.file, offset, len, advice);
429 revert_creds(old_cred);
430
431 fdput(real);
432
433 return ret;
434}
435
436static long ovl_real_ioctl(struct file *file, unsigned int cmd,
437 unsigned long arg)
438{
439 struct fd real;
440 const struct cred *old_cred;
441 long ret;
442
443 ret = ovl_real_fdget(file, &real);
444 if (ret)
445 return ret;
446
447 old_cred = ovl_override_creds(file_inode(file)->i_sb);
448 ret = vfs_ioctl(real.file, cmd, arg);
449 revert_creds(old_cred);
450
451 fdput(real);
452
453 return ret;
454}
455
David Brazdil0f672f62019-12-10 10:32:29 +0000456static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd,
457 unsigned long arg, unsigned int iflags)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000458{
459 long ret;
460 struct inode *inode = file_inode(file);
David Brazdil0f672f62019-12-10 10:32:29 +0000461 unsigned int old_iflags;
462
463 if (!inode_owner_or_capable(inode))
464 return -EACCES;
465
466 ret = mnt_want_write_file(file);
467 if (ret)
468 return ret;
469
470 inode_lock(inode);
471
472 /* Check the capability before cred override */
473 ret = -EPERM;
474 old_iflags = READ_ONCE(inode->i_flags);
475 if (((iflags ^ old_iflags) & (S_APPEND | S_IMMUTABLE)) &&
476 !capable(CAP_LINUX_IMMUTABLE))
477 goto unlock;
478
479 ret = ovl_maybe_copy_up(file_dentry(file), O_WRONLY);
480 if (ret)
481 goto unlock;
482
483 ret = ovl_real_ioctl(file, cmd, arg);
484
485 ovl_copyflags(ovl_inode_real(inode), inode);
486unlock:
487 inode_unlock(inode);
488
489 mnt_drop_write_file(file);
490
491 return ret;
492
493}
494
495static unsigned int ovl_fsflags_to_iflags(unsigned int flags)
496{
497 unsigned int iflags = 0;
498
499 if (flags & FS_SYNC_FL)
500 iflags |= S_SYNC;
501 if (flags & FS_APPEND_FL)
502 iflags |= S_APPEND;
503 if (flags & FS_IMMUTABLE_FL)
504 iflags |= S_IMMUTABLE;
505 if (flags & FS_NOATIME_FL)
506 iflags |= S_NOATIME;
507
508 return iflags;
509}
510
511static long ovl_ioctl_set_fsflags(struct file *file, unsigned int cmd,
512 unsigned long arg)
513{
514 unsigned int flags;
515
516 if (get_user(flags, (int __user *) arg))
517 return -EFAULT;
518
519 return ovl_ioctl_set_flags(file, cmd, arg,
520 ovl_fsflags_to_iflags(flags));
521}
522
523static unsigned int ovl_fsxflags_to_iflags(unsigned int xflags)
524{
525 unsigned int iflags = 0;
526
527 if (xflags & FS_XFLAG_SYNC)
528 iflags |= S_SYNC;
529 if (xflags & FS_XFLAG_APPEND)
530 iflags |= S_APPEND;
531 if (xflags & FS_XFLAG_IMMUTABLE)
532 iflags |= S_IMMUTABLE;
533 if (xflags & FS_XFLAG_NOATIME)
534 iflags |= S_NOATIME;
535
536 return iflags;
537}
538
539static long ovl_ioctl_set_fsxflags(struct file *file, unsigned int cmd,
540 unsigned long arg)
541{
542 struct fsxattr fa;
543
544 memset(&fa, 0, sizeof(fa));
545 if (copy_from_user(&fa, (void __user *) arg, sizeof(fa)))
546 return -EFAULT;
547
548 return ovl_ioctl_set_flags(file, cmd, arg,
549 ovl_fsxflags_to_iflags(fa.fsx_xflags));
550}
551
552static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
553{
554 long ret;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000555
556 switch (cmd) {
557 case FS_IOC_GETFLAGS:
David Brazdil0f672f62019-12-10 10:32:29 +0000558 case FS_IOC_FSGETXATTR:
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000559 ret = ovl_real_ioctl(file, cmd, arg);
560 break;
561
562 case FS_IOC_SETFLAGS:
David Brazdil0f672f62019-12-10 10:32:29 +0000563 ret = ovl_ioctl_set_fsflags(file, cmd, arg);
564 break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000565
David Brazdil0f672f62019-12-10 10:32:29 +0000566 case FS_IOC_FSSETXATTR:
567 ret = ovl_ioctl_set_fsxflags(file, cmd, arg);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000568 break;
569
570 default:
571 ret = -ENOTTY;
572 }
573
574 return ret;
575}
576
577static long ovl_compat_ioctl(struct file *file, unsigned int cmd,
578 unsigned long arg)
579{
580 switch (cmd) {
581 case FS_IOC32_GETFLAGS:
582 cmd = FS_IOC_GETFLAGS;
583 break;
584
585 case FS_IOC32_SETFLAGS:
586 cmd = FS_IOC_SETFLAGS;
587 break;
588
589 default:
590 return -ENOIOCTLCMD;
591 }
592
593 return ovl_ioctl(file, cmd, arg);
594}
595
596enum ovl_copyop {
597 OVL_COPY,
598 OVL_CLONE,
599 OVL_DEDUPE,
600};
601
David Brazdil0f672f62019-12-10 10:32:29 +0000602static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000603 struct file *file_out, loff_t pos_out,
David Brazdil0f672f62019-12-10 10:32:29 +0000604 loff_t len, unsigned int flags, enum ovl_copyop op)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000605{
606 struct inode *inode_out = file_inode(file_out);
607 struct fd real_in, real_out;
608 const struct cred *old_cred;
David Brazdil0f672f62019-12-10 10:32:29 +0000609 loff_t ret;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000610
611 ret = ovl_real_fdget(file_out, &real_out);
612 if (ret)
613 return ret;
614
615 ret = ovl_real_fdget(file_in, &real_in);
616 if (ret) {
617 fdput(real_out);
618 return ret;
619 }
620
621 old_cred = ovl_override_creds(file_inode(file_out)->i_sb);
622 switch (op) {
623 case OVL_COPY:
624 ret = vfs_copy_file_range(real_in.file, pos_in,
625 real_out.file, pos_out, len, flags);
626 break;
627
628 case OVL_CLONE:
629 ret = vfs_clone_file_range(real_in.file, pos_in,
David Brazdil0f672f62019-12-10 10:32:29 +0000630 real_out.file, pos_out, len, flags);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000631 break;
632
633 case OVL_DEDUPE:
634 ret = vfs_dedupe_file_range_one(real_in.file, pos_in,
David Brazdil0f672f62019-12-10 10:32:29 +0000635 real_out.file, pos_out, len,
636 flags);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000637 break;
638 }
639 revert_creds(old_cred);
640
641 /* Update size */
642 ovl_copyattr(ovl_inode_real(inode_out), inode_out);
643
644 fdput(real_in);
645 fdput(real_out);
646
647 return ret;
648}
649
650static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in,
651 struct file *file_out, loff_t pos_out,
652 size_t len, unsigned int flags)
653{
654 return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, flags,
655 OVL_COPY);
656}
657
David Brazdil0f672f62019-12-10 10:32:29 +0000658static loff_t ovl_remap_file_range(struct file *file_in, loff_t pos_in,
659 struct file *file_out, loff_t pos_out,
660 loff_t len, unsigned int remap_flags)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000661{
David Brazdil0f672f62019-12-10 10:32:29 +0000662 enum ovl_copyop op;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000663
David Brazdil0f672f62019-12-10 10:32:29 +0000664 if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
665 return -EINVAL;
666
667 if (remap_flags & REMAP_FILE_DEDUP)
668 op = OVL_DEDUPE;
669 else
670 op = OVL_CLONE;
671
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000672 /*
673 * Don't copy up because of a dedupe request, this wouldn't make sense
674 * most of the time (data would be duplicated instead of deduplicated).
675 */
David Brazdil0f672f62019-12-10 10:32:29 +0000676 if (op == OVL_DEDUPE &&
677 (!ovl_inode_upper(file_inode(file_in)) ||
678 !ovl_inode_upper(file_inode(file_out))))
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000679 return -EPERM;
680
David Brazdil0f672f62019-12-10 10:32:29 +0000681 return ovl_copyfile(file_in, pos_in, file_out, pos_out, len,
682 remap_flags, op);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000683}
684
685const struct file_operations ovl_file_operations = {
686 .open = ovl_open,
687 .release = ovl_release,
688 .llseek = ovl_llseek,
689 .read_iter = ovl_read_iter,
690 .write_iter = ovl_write_iter,
691 .fsync = ovl_fsync,
692 .mmap = ovl_mmap,
693 .fallocate = ovl_fallocate,
694 .fadvise = ovl_fadvise,
695 .unlocked_ioctl = ovl_ioctl,
696 .compat_ioctl = ovl_compat_ioctl,
Olivier Deprez0e641232021-09-23 10:07:05 +0200697 .splice_read = ovl_splice_read,
698 .splice_write = ovl_splice_write,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000699
700 .copy_file_range = ovl_copy_file_range,
David Brazdil0f672f62019-12-10 10:32:29 +0000701 .remap_file_range = ovl_remap_file_range,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000702};