Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * This file contians vfs file ops for 9P2000.
0004  *
0005  *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
0006  *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
0007  */
0008 
0009 #include <linux/module.h>
0010 #include <linux/errno.h>
0011 #include <linux/fs.h>
0012 #include <linux/sched.h>
0013 #include <linux/file.h>
0014 #include <linux/stat.h>
0015 #include <linux/string.h>
0016 #include <linux/inet.h>
0017 #include <linux/list.h>
0018 #include <linux/pagemap.h>
0019 #include <linux/utsname.h>
0020 #include <linux/uaccess.h>
0021 #include <linux/idr.h>
0022 #include <linux/uio.h>
0023 #include <linux/slab.h>
0024 #include <net/9p/9p.h>
0025 #include <net/9p/client.h>
0026 
0027 #include "v9fs.h"
0028 #include "v9fs_vfs.h"
0029 #include "fid.h"
0030 #include "cache.h"
0031 
0032 static const struct vm_operations_struct v9fs_file_vm_ops;
0033 static const struct vm_operations_struct v9fs_mmap_file_vm_ops;
0034 
0035 /**
0036  * v9fs_file_open - open a file (or directory)
0037  * @inode: inode to be opened
0038  * @file: file being opened
0039  *
0040  */
0041 
0042 int v9fs_file_open(struct inode *inode, struct file *file)
0043 {
0044     int err;
0045     struct v9fs_inode *v9inode;
0046     struct v9fs_session_info *v9ses;
0047     struct p9_fid *fid, *writeback_fid;
0048     int omode;
0049 
0050     p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file);
0051     v9inode = V9FS_I(inode);
0052     v9ses = v9fs_inode2v9ses(inode);
0053     if (v9fs_proto_dotl(v9ses))
0054         omode = v9fs_open_to_dotl_flags(file->f_flags);
0055     else
0056         omode = v9fs_uflags2omode(file->f_flags,
0057                     v9fs_proto_dotu(v9ses));
0058     fid = file->private_data;
0059     if (!fid) {
0060         fid = v9fs_fid_clone(file_dentry(file));
0061         if (IS_ERR(fid))
0062             return PTR_ERR(fid);
0063 
0064         err = p9_client_open(fid, omode);
0065         if (err < 0) {
0066             p9_fid_put(fid);
0067             return err;
0068         }
0069         if ((file->f_flags & O_APPEND) &&
0070             (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)))
0071             generic_file_llseek(file, 0, SEEK_END);
0072 
0073         file->private_data = fid;
0074     }
0075 
0076     mutex_lock(&v9inode->v_mutex);
0077     if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) &&
0078         !v9inode->writeback_fid &&
0079         ((file->f_flags & O_ACCMODE) != O_RDONLY)) {
0080         /*
0081          * clone a fid and add it to writeback_fid
0082          * we do it during open time instead of
0083          * page dirty time via write_begin/page_mkwrite
0084          * because we want write after unlink usecase
0085          * to work.
0086          */
0087         writeback_fid = v9fs_writeback_fid(file_dentry(file));
0088         if (IS_ERR(writeback_fid)) {
0089             err = PTR_ERR(writeback_fid);
0090             mutex_unlock(&v9inode->v_mutex);
0091             goto out_error;
0092         }
0093         v9inode->writeback_fid = (void *) writeback_fid;
0094     }
0095     mutex_unlock(&v9inode->v_mutex);
0096     if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
0097         fscache_use_cookie(v9fs_inode_cookie(v9inode),
0098                    file->f_mode & FMODE_WRITE);
0099     v9fs_open_fid_add(inode, &fid);
0100     return 0;
0101 out_error:
0102     p9_fid_put(file->private_data);
0103     file->private_data = NULL;
0104     return err;
0105 }
0106 
0107 /**
0108  * v9fs_file_lock - lock a file (or directory)
0109  * @filp: file to be locked
0110  * @cmd: lock command
0111  * @fl: file lock structure
0112  *
0113  * Bugs: this looks like a local only lock, we should extend into 9P
0114  *       by using open exclusive
0115  */
0116 
0117 static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
0118 {
0119     struct inode *inode = file_inode(filp);
0120 
0121     p9_debug(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
0122 
0123     if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
0124         filemap_write_and_wait(inode->i_mapping);
0125         invalidate_mapping_pages(&inode->i_data, 0, -1);
0126     }
0127 
0128     return 0;
0129 }
0130 
0131 static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
0132 {
0133     struct p9_flock flock;
0134     struct p9_fid *fid;
0135     uint8_t status = P9_LOCK_ERROR;
0136     int res = 0;
0137     unsigned char fl_type;
0138     struct v9fs_session_info *v9ses;
0139 
0140     fid = filp->private_data;
0141     BUG_ON(fid == NULL);
0142 
0143     BUG_ON((fl->fl_flags & FL_POSIX) != FL_POSIX);
0144 
0145     res = locks_lock_file_wait(filp, fl);
0146     if (res < 0)
0147         goto out;
0148 
0149     /* convert posix lock to p9 tlock args */
0150     memset(&flock, 0, sizeof(flock));
0151     /* map the lock type */
0152     switch (fl->fl_type) {
0153     case F_RDLCK:
0154         flock.type = P9_LOCK_TYPE_RDLCK;
0155         break;
0156     case F_WRLCK:
0157         flock.type = P9_LOCK_TYPE_WRLCK;
0158         break;
0159     case F_UNLCK:
0160         flock.type = P9_LOCK_TYPE_UNLCK;
0161         break;
0162     }
0163     flock.start = fl->fl_start;
0164     if (fl->fl_end == OFFSET_MAX)
0165         flock.length = 0;
0166     else
0167         flock.length = fl->fl_end - fl->fl_start + 1;
0168     flock.proc_id = fl->fl_pid;
0169     flock.client_id = fid->clnt->name;
0170     if (IS_SETLKW(cmd))
0171         flock.flags = P9_LOCK_FLAGS_BLOCK;
0172 
0173     v9ses = v9fs_inode2v9ses(file_inode(filp));
0174 
0175     /*
0176      * if its a blocked request and we get P9_LOCK_BLOCKED as the status
0177      * for lock request, keep on trying
0178      */
0179     for (;;) {
0180         res = p9_client_lock_dotl(fid, &flock, &status);
0181         if (res < 0)
0182             goto out_unlock;
0183 
0184         if (status != P9_LOCK_BLOCKED)
0185             break;
0186         if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd))
0187             break;
0188         if (schedule_timeout_interruptible(v9ses->session_lock_timeout)
0189                 != 0)
0190             break;
0191         /*
0192          * p9_client_lock_dotl overwrites flock.client_id with the
0193          * server message, free and reuse the client name
0194          */
0195         if (flock.client_id != fid->clnt->name) {
0196             kfree(flock.client_id);
0197             flock.client_id = fid->clnt->name;
0198         }
0199     }
0200 
0201     /* map 9p status to VFS status */
0202     switch (status) {
0203     case P9_LOCK_SUCCESS:
0204         res = 0;
0205         break;
0206     case P9_LOCK_BLOCKED:
0207         res = -EAGAIN;
0208         break;
0209     default:
0210         WARN_ONCE(1, "unknown lock status code: %d\n", status);
0211         fallthrough;
0212     case P9_LOCK_ERROR:
0213     case P9_LOCK_GRACE:
0214         res = -ENOLCK;
0215         break;
0216     }
0217 
0218 out_unlock:
0219     /*
0220      * incase server returned error for lock request, revert
0221      * it locally
0222      */
0223     if (res < 0 && fl->fl_type != F_UNLCK) {
0224         fl_type = fl->fl_type;
0225         fl->fl_type = F_UNLCK;
0226         /* Even if this fails we want to return the remote error */
0227         locks_lock_file_wait(filp, fl);
0228         fl->fl_type = fl_type;
0229     }
0230     if (flock.client_id != fid->clnt->name)
0231         kfree(flock.client_id);
0232 out:
0233     return res;
0234 }
0235 
0236 static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)
0237 {
0238     struct p9_getlock glock;
0239     struct p9_fid *fid;
0240     int res = 0;
0241 
0242     fid = filp->private_data;
0243     BUG_ON(fid == NULL);
0244 
0245     posix_test_lock(filp, fl);
0246     /*
0247      * if we have a conflicting lock locally, no need to validate
0248      * with server
0249      */
0250     if (fl->fl_type != F_UNLCK)
0251         return res;
0252 
0253     /* convert posix lock to p9 tgetlock args */
0254     memset(&glock, 0, sizeof(glock));
0255     glock.type  = P9_LOCK_TYPE_UNLCK;
0256     glock.start = fl->fl_start;
0257     if (fl->fl_end == OFFSET_MAX)
0258         glock.length = 0;
0259     else
0260         glock.length = fl->fl_end - fl->fl_start + 1;
0261     glock.proc_id = fl->fl_pid;
0262     glock.client_id = fid->clnt->name;
0263 
0264     res = p9_client_getlock_dotl(fid, &glock);
0265     if (res < 0)
0266         goto out;
0267     /* map 9p lock type to os lock type */
0268     switch (glock.type) {
0269     case P9_LOCK_TYPE_RDLCK:
0270         fl->fl_type = F_RDLCK;
0271         break;
0272     case P9_LOCK_TYPE_WRLCK:
0273         fl->fl_type = F_WRLCK;
0274         break;
0275     case P9_LOCK_TYPE_UNLCK:
0276         fl->fl_type = F_UNLCK;
0277         break;
0278     }
0279     if (glock.type != P9_LOCK_TYPE_UNLCK) {
0280         fl->fl_start = glock.start;
0281         if (glock.length == 0)
0282             fl->fl_end = OFFSET_MAX;
0283         else
0284             fl->fl_end = glock.start + glock.length - 1;
0285         fl->fl_pid = -glock.proc_id;
0286     }
0287 out:
0288     if (glock.client_id != fid->clnt->name)
0289         kfree(glock.client_id);
0290     return res;
0291 }
0292 
0293 /**
0294  * v9fs_file_lock_dotl - lock a file (or directory)
0295  * @filp: file to be locked
0296  * @cmd: lock command
0297  * @fl: file lock structure
0298  *
0299  */
0300 
0301 static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl)
0302 {
0303     struct inode *inode = file_inode(filp);
0304     int ret = -ENOLCK;
0305 
0306     p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %pD\n",
0307          filp, cmd, fl, filp);
0308 
0309     if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
0310         filemap_write_and_wait(inode->i_mapping);
0311         invalidate_mapping_pages(&inode->i_data, 0, -1);
0312     }
0313 
0314     if (IS_SETLK(cmd) || IS_SETLKW(cmd))
0315         ret = v9fs_file_do_lock(filp, cmd, fl);
0316     else if (IS_GETLK(cmd))
0317         ret = v9fs_file_getlock(filp, fl);
0318     else
0319         ret = -EINVAL;
0320     return ret;
0321 }
0322 
0323 /**
0324  * v9fs_file_flock_dotl - lock a file
0325  * @filp: file to be locked
0326  * @cmd: lock command
0327  * @fl: file lock structure
0328  *
0329  */
0330 
0331 static int v9fs_file_flock_dotl(struct file *filp, int cmd,
0332     struct file_lock *fl)
0333 {
0334     struct inode *inode = file_inode(filp);
0335     int ret = -ENOLCK;
0336 
0337     p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %pD\n",
0338          filp, cmd, fl, filp);
0339 
0340     if (!(fl->fl_flags & FL_FLOCK))
0341         goto out_err;
0342 
0343     if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
0344         filemap_write_and_wait(inode->i_mapping);
0345         invalidate_mapping_pages(&inode->i_data, 0, -1);
0346     }
0347     /* Convert flock to posix lock */
0348     fl->fl_flags |= FL_POSIX;
0349     fl->fl_flags ^= FL_FLOCK;
0350 
0351     if (IS_SETLK(cmd) | IS_SETLKW(cmd))
0352         ret = v9fs_file_do_lock(filp, cmd, fl);
0353     else
0354         ret = -EINVAL;
0355 out_err:
0356     return ret;
0357 }
0358 
0359 /**
0360  * v9fs_file_read_iter - read from a file
0361  * @iocb: The operation parameters
0362  * @to: The buffer to read into
0363  *
0364  */
0365 static ssize_t
0366 v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
0367 {
0368     struct p9_fid *fid = iocb->ki_filp->private_data;
0369     int ret, err = 0;
0370 
0371     p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n",
0372          iov_iter_count(to), iocb->ki_pos);
0373 
0374     if (iocb->ki_filp->f_flags & O_NONBLOCK)
0375         ret = p9_client_read_once(fid, iocb->ki_pos, to, &err);
0376     else
0377         ret = p9_client_read(fid, iocb->ki_pos, to, &err);
0378     if (!ret)
0379         return err;
0380 
0381     iocb->ki_pos += ret;
0382     return ret;
0383 }
0384 
0385 /**
0386  * v9fs_file_write_iter - write to a file
0387  * @iocb: The operation parameters
0388  * @from: The data to write
0389  *
0390  */
0391 static ssize_t
0392 v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
0393 {
0394     struct file *file = iocb->ki_filp;
0395     ssize_t retval;
0396     loff_t origin;
0397     int err = 0;
0398 
0399     retval = generic_write_checks(iocb, from);
0400     if (retval <= 0)
0401         return retval;
0402 
0403     origin = iocb->ki_pos;
0404     retval = p9_client_write(file->private_data, iocb->ki_pos, from, &err);
0405     if (retval > 0) {
0406         struct inode *inode = file_inode(file);
0407         loff_t i_size;
0408         unsigned long pg_start, pg_end;
0409 
0410         pg_start = origin >> PAGE_SHIFT;
0411         pg_end = (origin + retval - 1) >> PAGE_SHIFT;
0412         if (inode->i_mapping && inode->i_mapping->nrpages)
0413             invalidate_inode_pages2_range(inode->i_mapping,
0414                               pg_start, pg_end);
0415         iocb->ki_pos += retval;
0416         i_size = i_size_read(inode);
0417         if (iocb->ki_pos > i_size) {
0418             inode_add_bytes(inode, iocb->ki_pos - i_size);
0419             /*
0420              * Need to serialize against i_size_write() in
0421              * v9fs_stat2inode()
0422              */
0423             v9fs_i_size_write(inode, iocb->ki_pos);
0424         }
0425         return retval;
0426     }
0427     return err;
0428 }
0429 
0430 static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end,
0431                int datasync)
0432 {
0433     struct p9_fid *fid;
0434     struct inode *inode = filp->f_mapping->host;
0435     struct p9_wstat wstat;
0436     int retval;
0437 
0438     retval = file_write_and_wait_range(filp, start, end);
0439     if (retval)
0440         return retval;
0441 
0442     inode_lock(inode);
0443     p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync);
0444 
0445     fid = filp->private_data;
0446     v9fs_blank_wstat(&wstat);
0447 
0448     retval = p9_client_wstat(fid, &wstat);
0449     inode_unlock(inode);
0450 
0451     return retval;
0452 }
0453 
0454 int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
0455              int datasync)
0456 {
0457     struct p9_fid *fid;
0458     struct inode *inode = filp->f_mapping->host;
0459     int retval;
0460 
0461     retval = file_write_and_wait_range(filp, start, end);
0462     if (retval)
0463         return retval;
0464 
0465     inode_lock(inode);
0466     p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync);
0467 
0468     fid = filp->private_data;
0469 
0470     retval = p9_client_fsync(fid, datasync);
0471     inode_unlock(inode);
0472 
0473     return retval;
0474 }
0475 
0476 static int
0477 v9fs_file_mmap(struct file *filp, struct vm_area_struct *vma)
0478 {
0479     int retval;
0480 
0481 
0482     retval = generic_file_mmap(filp, vma);
0483     if (!retval)
0484         vma->vm_ops = &v9fs_file_vm_ops;
0485 
0486     return retval;
0487 }
0488 
0489 static int
0490 v9fs_mmap_file_mmap(struct file *filp, struct vm_area_struct *vma)
0491 {
0492     int retval;
0493     struct inode *inode;
0494     struct v9fs_inode *v9inode;
0495     struct p9_fid *fid;
0496 
0497     inode = file_inode(filp);
0498     v9inode = V9FS_I(inode);
0499     mutex_lock(&v9inode->v_mutex);
0500     if (!v9inode->writeback_fid &&
0501         (vma->vm_flags & VM_SHARED) &&
0502         (vma->vm_flags & VM_WRITE)) {
0503         /*
0504          * clone a fid and add it to writeback_fid
0505          * we do it during mmap instead of
0506          * page dirty time via write_begin/page_mkwrite
0507          * because we want write after unlink usecase
0508          * to work.
0509          */
0510         fid = v9fs_writeback_fid(file_dentry(filp));
0511         if (IS_ERR(fid)) {
0512             retval = PTR_ERR(fid);
0513             mutex_unlock(&v9inode->v_mutex);
0514             return retval;
0515         }
0516         v9inode->writeback_fid = (void *) fid;
0517     }
0518     mutex_unlock(&v9inode->v_mutex);
0519 
0520     retval = generic_file_mmap(filp, vma);
0521     if (!retval)
0522         vma->vm_ops = &v9fs_mmap_file_vm_ops;
0523 
0524     return retval;
0525 }
0526 
0527 static vm_fault_t
0528 v9fs_vm_page_mkwrite(struct vm_fault *vmf)
0529 {
0530     struct v9fs_inode *v9inode;
0531     struct folio *folio = page_folio(vmf->page);
0532     struct file *filp = vmf->vma->vm_file;
0533     struct inode *inode = file_inode(filp);
0534 
0535 
0536     p9_debug(P9_DEBUG_VFS, "folio %p fid %lx\n",
0537          folio, (unsigned long)filp->private_data);
0538 
0539     v9inode = V9FS_I(inode);
0540 
0541     /* Wait for the page to be written to the cache before we allow it to
0542      * be modified.  We then assume the entire page will need writing back.
0543      */
0544 #ifdef CONFIG_9P_FSCACHE
0545     if (folio_test_fscache(folio) &&
0546         folio_wait_fscache_killable(folio) < 0)
0547         return VM_FAULT_NOPAGE;
0548 #endif
0549 
0550     /* Update file times before taking page lock */
0551     file_update_time(filp);
0552 
0553     BUG_ON(!v9inode->writeback_fid);
0554     if (folio_lock_killable(folio) < 0)
0555         return VM_FAULT_RETRY;
0556     if (folio_mapping(folio) != inode->i_mapping)
0557         goto out_unlock;
0558     folio_wait_stable(folio);
0559 
0560     return VM_FAULT_LOCKED;
0561 out_unlock:
0562     folio_unlock(folio);
0563     return VM_FAULT_NOPAGE;
0564 }
0565 
0566 /**
0567  * v9fs_mmap_file_read_iter - read from a file
0568  * @iocb: The operation parameters
0569  * @to: The buffer to read into
0570  *
0571  */
0572 static ssize_t
0573 v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
0574 {
0575     /* TODO: Check if there are dirty pages */
0576     return v9fs_file_read_iter(iocb, to);
0577 }
0578 
0579 /**
0580  * v9fs_mmap_file_write_iter - write to a file
0581  * @iocb: The operation parameters
0582  * @from: The data to write
0583  *
0584  */
0585 static ssize_t
0586 v9fs_mmap_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
0587 {
0588     /*
0589      * TODO: invalidate mmaps on filp's inode between
0590      * offset and offset+count
0591      */
0592     return v9fs_file_write_iter(iocb, from);
0593 }
0594 
0595 static void v9fs_mmap_vm_close(struct vm_area_struct *vma)
0596 {
0597     struct inode *inode;
0598 
0599     struct writeback_control wbc = {
0600         .nr_to_write = LONG_MAX,
0601         .sync_mode = WB_SYNC_ALL,
0602         .range_start = (loff_t)vma->vm_pgoff * PAGE_SIZE,
0603          /* absolute end, byte at end included */
0604         .range_end = (loff_t)vma->vm_pgoff * PAGE_SIZE +
0605             (vma->vm_end - vma->vm_start - 1),
0606     };
0607 
0608     if (!(vma->vm_flags & VM_SHARED))
0609         return;
0610 
0611     p9_debug(P9_DEBUG_VFS, "9p VMA close, %p, flushing", vma);
0612 
0613     inode = file_inode(vma->vm_file);
0614     filemap_fdatawrite_wbc(inode->i_mapping, &wbc);
0615 }
0616 
0617 
0618 static const struct vm_operations_struct v9fs_file_vm_ops = {
0619     .fault = filemap_fault,
0620     .map_pages = filemap_map_pages,
0621     .page_mkwrite = v9fs_vm_page_mkwrite,
0622 };
0623 
0624 static const struct vm_operations_struct v9fs_mmap_file_vm_ops = {
0625     .close = v9fs_mmap_vm_close,
0626     .fault = filemap_fault,
0627     .map_pages = filemap_map_pages,
0628     .page_mkwrite = v9fs_vm_page_mkwrite,
0629 };
0630 
0631 
0632 const struct file_operations v9fs_cached_file_operations = {
0633     .llseek = generic_file_llseek,
0634     .read_iter = generic_file_read_iter,
0635     .write_iter = generic_file_write_iter,
0636     .open = v9fs_file_open,
0637     .release = v9fs_dir_release,
0638     .lock = v9fs_file_lock,
0639     .mmap = v9fs_file_mmap,
0640     .splice_read = generic_file_splice_read,
0641     .splice_write = iter_file_splice_write,
0642     .fsync = v9fs_file_fsync,
0643 };
0644 
0645 const struct file_operations v9fs_cached_file_operations_dotl = {
0646     .llseek = generic_file_llseek,
0647     .read_iter = generic_file_read_iter,
0648     .write_iter = generic_file_write_iter,
0649     .open = v9fs_file_open,
0650     .release = v9fs_dir_release,
0651     .lock = v9fs_file_lock_dotl,
0652     .flock = v9fs_file_flock_dotl,
0653     .mmap = v9fs_file_mmap,
0654     .splice_read = generic_file_splice_read,
0655     .splice_write = iter_file_splice_write,
0656     .fsync = v9fs_file_fsync_dotl,
0657 };
0658 
0659 const struct file_operations v9fs_file_operations = {
0660     .llseek = generic_file_llseek,
0661     .read_iter = v9fs_file_read_iter,
0662     .write_iter = v9fs_file_write_iter,
0663     .open = v9fs_file_open,
0664     .release = v9fs_dir_release,
0665     .lock = v9fs_file_lock,
0666     .mmap = generic_file_readonly_mmap,
0667     .splice_read = generic_file_splice_read,
0668     .splice_write = iter_file_splice_write,
0669     .fsync = v9fs_file_fsync,
0670 };
0671 
0672 const struct file_operations v9fs_file_operations_dotl = {
0673     .llseek = generic_file_llseek,
0674     .read_iter = v9fs_file_read_iter,
0675     .write_iter = v9fs_file_write_iter,
0676     .open = v9fs_file_open,
0677     .release = v9fs_dir_release,
0678     .lock = v9fs_file_lock_dotl,
0679     .flock = v9fs_file_flock_dotl,
0680     .mmap = generic_file_readonly_mmap,
0681     .splice_read = generic_file_splice_read,
0682     .splice_write = iter_file_splice_write,
0683     .fsync = v9fs_file_fsync_dotl,
0684 };
0685 
0686 const struct file_operations v9fs_mmap_file_operations = {
0687     .llseek = generic_file_llseek,
0688     .read_iter = v9fs_mmap_file_read_iter,
0689     .write_iter = v9fs_mmap_file_write_iter,
0690     .open = v9fs_file_open,
0691     .release = v9fs_dir_release,
0692     .lock = v9fs_file_lock,
0693     .mmap = v9fs_mmap_file_mmap,
0694     .splice_read = generic_file_splice_read,
0695     .splice_write = iter_file_splice_write,
0696     .fsync = v9fs_file_fsync,
0697 };
0698 
0699 const struct file_operations v9fs_mmap_file_operations_dotl = {
0700     .llseek = generic_file_llseek,
0701     .read_iter = v9fs_mmap_file_read_iter,
0702     .write_iter = v9fs_mmap_file_write_iter,
0703     .open = v9fs_file_open,
0704     .release = v9fs_dir_release,
0705     .lock = v9fs_file_lock_dotl,
0706     .flock = v9fs_file_flock_dotl,
0707     .mmap = v9fs_mmap_file_mmap,
0708     .splice_read = generic_file_splice_read,
0709     .splice_write = iter_file_splice_write,
0710     .fsync = v9fs_file_fsync_dotl,
0711 };