linux/fs/9p/vfs_file.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  linux/fs/9p/vfs_file.c
   4 *
   5 * This file contians vfs file ops for 9P2000.
   6 *
   7 *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
   8 *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/errno.h>
  13#include <linux/fs.h>
  14#include <linux/sched.h>
  15#include <linux/file.h>
  16#include <linux/stat.h>
  17#include <linux/string.h>
  18#include <linux/inet.h>
  19#include <linux/list.h>
  20#include <linux/pagemap.h>
  21#include <linux/utsname.h>
  22#include <linux/uaccess.h>
  23#include <linux/idr.h>
  24#include <linux/uio.h>
  25#include <linux/slab.h>
  26#include <net/9p/9p.h>
  27#include <net/9p/client.h>
  28
  29#include "v9fs.h"
  30#include "v9fs_vfs.h"
  31#include "fid.h"
  32#include "cache.h"
  33
  34static const struct vm_operations_struct v9fs_file_vm_ops;
  35static const struct vm_operations_struct v9fs_mmap_file_vm_ops;
  36
  37/**
  38 * v9fs_file_open - open a file (or directory)
  39 * @inode: inode to be opened
  40 * @file: file being opened
  41 *
  42 */
  43
  44int v9fs_file_open(struct inode *inode, struct file *file)
  45{
  46        int err;
  47        struct v9fs_inode *v9inode;
  48        struct v9fs_session_info *v9ses;
  49        struct p9_fid *fid;
  50        int omode;
  51
  52        p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file);
  53        v9inode = V9FS_I(inode);
  54        v9ses = v9fs_inode2v9ses(inode);
  55        if (v9fs_proto_dotl(v9ses))
  56                omode = v9fs_open_to_dotl_flags(file->f_flags);
  57        else
  58                omode = v9fs_uflags2omode(file->f_flags,
  59                                        v9fs_proto_dotu(v9ses));
  60        fid = file->private_data;
  61        if (!fid) {
  62                fid = v9fs_fid_clone(file_dentry(file));
  63                if (IS_ERR(fid))
  64                        return PTR_ERR(fid);
  65
  66                err = p9_client_open(fid, omode);
  67                if (err < 0) {
  68                        p9_client_clunk(fid);
  69                        return err;
  70                }
  71                if ((file->f_flags & O_APPEND) &&
  72                        (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)))
  73                        generic_file_llseek(file, 0, SEEK_END);
  74        }
  75
  76        file->private_data = fid;
  77        mutex_lock(&v9inode->v_mutex);
  78        if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) &&
  79            !v9inode->writeback_fid &&
  80            ((file->f_flags & O_ACCMODE) != O_RDONLY)) {
  81                /*
  82                 * clone a fid and add it to writeback_fid
  83                 * we do it during open time instead of
  84                 * page dirty time via write_begin/page_mkwrite
  85                 * because we want write after unlink usecase
  86                 * to work.
  87                 */
  88                fid = v9fs_writeback_fid(file_dentry(file));
  89                if (IS_ERR(fid)) {
  90                        err = PTR_ERR(fid);
  91                        mutex_unlock(&v9inode->v_mutex);
  92                        goto out_error;
  93                }
  94                v9inode->writeback_fid = (void *) fid;
  95        }
  96        mutex_unlock(&v9inode->v_mutex);
  97        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
  98                v9fs_cache_inode_set_cookie(inode, file);
  99        return 0;
 100out_error:
 101        p9_client_clunk(file->private_data);
 102        file->private_data = NULL;
 103        return err;
 104}
 105
 106/**
 107 * v9fs_file_lock - lock a file (or directory)
 108 * @filp: file to be locked
 109 * @cmd: lock command
 110 * @fl: file lock structure
 111 *
 112 * Bugs: this looks like a local only lock, we should extend into 9P
 113 *       by using open exclusive
 114 */
 115
 116static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
 117{
 118        int res = 0;
 119        struct inode *inode = file_inode(filp);
 120
 121        p9_debug(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
 122
 123        /* No mandatory locks */
 124        if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
 125                return -ENOLCK;
 126
 127        if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
 128                filemap_write_and_wait(inode->i_mapping);
 129                invalidate_mapping_pages(&inode->i_data, 0, -1);
 130        }
 131
 132        return res;
 133}
 134
 135static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
 136{
 137        struct p9_flock flock;
 138        struct p9_fid *fid;
 139        uint8_t status = P9_LOCK_ERROR;
 140        int res = 0;
 141        unsigned char fl_type;
 142        struct v9fs_session_info *v9ses;
 143
 144        fid = filp->private_data;
 145        BUG_ON(fid == NULL);
 146
 147        if ((fl->fl_flags & FL_POSIX) != FL_POSIX)
 148                BUG();
 149
 150        res = locks_lock_file_wait(filp, fl);
 151        if (res < 0)
 152                goto out;
 153
 154        /* convert posix lock to p9 tlock args */
 155        memset(&flock, 0, sizeof(flock));
 156        /* map the lock type */
 157        switch (fl->fl_type) {
 158        case F_RDLCK:
 159                flock.type = P9_LOCK_TYPE_RDLCK;
 160                break;
 161        case F_WRLCK:
 162                flock.type = P9_LOCK_TYPE_WRLCK;
 163                break;
 164        case F_UNLCK:
 165                flock.type = P9_LOCK_TYPE_UNLCK;
 166                break;
 167        }
 168        flock.start = fl->fl_start;
 169        if (fl->fl_end == OFFSET_MAX)
 170                flock.length = 0;
 171        else
 172                flock.length = fl->fl_end - fl->fl_start + 1;
 173        flock.proc_id = fl->fl_pid;
 174        flock.client_id = fid->clnt->name;
 175        if (IS_SETLKW(cmd))
 176                flock.flags = P9_LOCK_FLAGS_BLOCK;
 177
 178        v9ses = v9fs_inode2v9ses(file_inode(filp));
 179
 180        /*
 181         * if its a blocked request and we get P9_LOCK_BLOCKED as the status
 182         * for lock request, keep on trying
 183         */
 184        for (;;) {
 185                res = p9_client_lock_dotl(fid, &flock, &status);
 186                if (res < 0)
 187                        goto out_unlock;
 188
 189                if (status != P9_LOCK_BLOCKED)
 190                        break;
 191                if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd))
 192                        break;
 193                if (schedule_timeout_interruptible(v9ses->session_lock_timeout)
 194                                != 0)
 195                        break;
 196                /*
 197                 * p9_client_lock_dotl overwrites flock.client_id with the
 198                 * server message, free and reuse the client name
 199                 */
 200                if (flock.client_id != fid->clnt->name) {
 201                        kfree(flock.client_id);
 202                        flock.client_id = fid->clnt->name;
 203                }
 204        }
 205
 206        /* map 9p status to VFS status */
 207        switch (status) {
 208        case P9_LOCK_SUCCESS:
 209                res = 0;
 210                break;
 211        case P9_LOCK_BLOCKED:
 212                res = -EAGAIN;
 213                break;
 214        default:
 215                WARN_ONCE(1, "unknown lock status code: %d\n", status);
 216                /* fall through */
 217        case P9_LOCK_ERROR:
 218        case P9_LOCK_GRACE:
 219                res = -ENOLCK;
 220                break;
 221        }
 222
 223out_unlock:
 224        /*
 225         * incase server returned error for lock request, revert
 226         * it locally
 227         */
 228        if (res < 0 && fl->fl_type != F_UNLCK) {
 229                fl_type = fl->fl_type;
 230                fl->fl_type = F_UNLCK;
 231                /* Even if this fails we want to return the remote error */
 232                locks_lock_file_wait(filp, fl);
 233                fl->fl_type = fl_type;
 234        }
 235        if (flock.client_id != fid->clnt->name)
 236                kfree(flock.client_id);
 237out:
 238        return res;
 239}
 240
 241static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)
 242{
 243        struct p9_getlock glock;
 244        struct p9_fid *fid;
 245        int res = 0;
 246
 247        fid = filp->private_data;
 248        BUG_ON(fid == NULL);
 249
 250        posix_test_lock(filp, fl);
 251        /*
 252         * if we have a conflicting lock locally, no need to validate
 253         * with server
 254         */
 255        if (fl->fl_type != F_UNLCK)
 256                return res;
 257
 258        /* convert posix lock to p9 tgetlock args */
 259        memset(&glock, 0, sizeof(glock));
 260        glock.type  = P9_LOCK_TYPE_UNLCK;
 261        glock.start = fl->fl_start;
 262        if (fl->fl_end == OFFSET_MAX)
 263                glock.length = 0;
 264        else
 265                glock.length = fl->fl_end - fl->fl_start + 1;
 266        glock.proc_id = fl->fl_pid;
 267        glock.client_id = fid->clnt->name;
 268
 269        res = p9_client_getlock_dotl(fid, &glock);
 270        if (res < 0)
 271                goto out;
 272        /* map 9p lock type to os lock type */
 273        switch (glock.type) {
 274        case P9_LOCK_TYPE_RDLCK:
 275                fl->fl_type = F_RDLCK;
 276                break;
 277        case P9_LOCK_TYPE_WRLCK:
 278                fl->fl_type = F_WRLCK;
 279                break;
 280        case P9_LOCK_TYPE_UNLCK:
 281                fl->fl_type = F_UNLCK;
 282                break;
 283        }
 284        if (glock.type != P9_LOCK_TYPE_UNLCK) {
 285                fl->fl_start = glock.start;
 286                if (glock.length == 0)
 287                        fl->fl_end = OFFSET_MAX;
 288                else
 289                        fl->fl_end = glock.start + glock.length - 1;
 290                fl->fl_pid = -glock.proc_id;
 291        }
 292out:
 293        if (glock.client_id != fid->clnt->name)
 294                kfree(glock.client_id);
 295        return res;
 296}
 297
 298/**
 299 * v9fs_file_lock_dotl - lock a file (or directory)
 300 * @filp: file to be locked
 301 * @cmd: lock command
 302 * @fl: file lock structure
 303 *
 304 */
 305
 306static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl)
 307{
 308        struct inode *inode = file_inode(filp);
 309        int ret = -ENOLCK;
 310
 311        p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %pD\n",
 312                 filp, cmd, fl, filp);
 313
 314        /* No mandatory locks */
 315        if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
 316                goto out_err;
 317
 318        if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
 319                filemap_write_and_wait(inode->i_mapping);
 320                invalidate_mapping_pages(&inode->i_data, 0, -1);
 321        }
 322
 323        if (IS_SETLK(cmd) || IS_SETLKW(cmd))
 324                ret = v9fs_file_do_lock(filp, cmd, fl);
 325        else if (IS_GETLK(cmd))
 326                ret = v9fs_file_getlock(filp, fl);
 327        else
 328                ret = -EINVAL;
 329out_err:
 330        return ret;
 331}
 332
 333/**
 334 * v9fs_file_flock_dotl - lock a file
 335 * @filp: file to be locked
 336 * @cmd: lock command
 337 * @fl: file lock structure
 338 *
 339 */
 340
 341static int v9fs_file_flock_dotl(struct file *filp, int cmd,
 342        struct file_lock *fl)
 343{
 344        struct inode *inode = file_inode(filp);
 345        int ret = -ENOLCK;
 346
 347        p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %pD\n",
 348                 filp, cmd, fl, filp);
 349
 350        /* No mandatory locks */
 351        if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
 352                goto out_err;
 353
 354        if (!(fl->fl_flags & FL_FLOCK))
 355                goto out_err;
 356
 357        if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
 358                filemap_write_and_wait(inode->i_mapping);
 359                invalidate_mapping_pages(&inode->i_data, 0, -1);
 360        }
 361        /* Convert flock to posix lock */
 362        fl->fl_flags |= FL_POSIX;
 363        fl->fl_flags ^= FL_FLOCK;
 364
 365        if (IS_SETLK(cmd) | IS_SETLKW(cmd))
 366                ret = v9fs_file_do_lock(filp, cmd, fl);
 367        else
 368                ret = -EINVAL;
 369out_err:
 370        return ret;
 371}
 372
 373/**
 374 * v9fs_file_read - read from a file
 375 * @filp: file pointer to read
 376 * @udata: user data buffer to read data into
 377 * @count: size of buffer
 378 * @offset: offset at which to read data
 379 *
 380 */
 381
 382static ssize_t
 383v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
 384{
 385        struct p9_fid *fid = iocb->ki_filp->private_data;
 386        int ret, err = 0;
 387
 388        p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n",
 389                 iov_iter_count(to), iocb->ki_pos);
 390
 391        ret = p9_client_read(fid, iocb->ki_pos, to, &err);
 392        if (!ret)
 393                return err;
 394
 395        iocb->ki_pos += ret;
 396        return ret;
 397}
 398
 399/**
 400 * v9fs_file_write - write to a file
 401 * @filp: file pointer to write
 402 * @data: data buffer to write data from
 403 * @count: size of buffer
 404 * @offset: offset at which to write data
 405 *
 406 */
 407static ssize_t
 408v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 409{
 410        struct file *file = iocb->ki_filp;
 411        ssize_t retval;
 412        loff_t origin;
 413        int err = 0;
 414
 415        retval = generic_write_checks(iocb, from);
 416        if (retval <= 0)
 417                return retval;
 418
 419        origin = iocb->ki_pos;
 420        retval = p9_client_write(file->private_data, iocb->ki_pos, from, &err);
 421        if (retval > 0) {
 422                struct inode *inode = file_inode(file);
 423                loff_t i_size;
 424                unsigned long pg_start, pg_end;
 425                pg_start = origin >> PAGE_SHIFT;
 426                pg_end = (origin + retval - 1) >> PAGE_SHIFT;
 427                if (inode->i_mapping && inode->i_mapping->nrpages)
 428                        invalidate_inode_pages2_range(inode->i_mapping,
 429                                                      pg_start, pg_end);
 430                iocb->ki_pos += retval;
 431                i_size = i_size_read(inode);
 432                if (iocb->ki_pos > i_size) {
 433                        inode_add_bytes(inode, iocb->ki_pos - i_size);
 434                        /*
 435                         * Need to serialize against i_size_write() in
 436                         * v9fs_stat2inode()
 437                         */
 438                        v9fs_i_size_write(inode, iocb->ki_pos);
 439                }
 440                return retval;
 441        }
 442        return err;
 443}
 444
 445static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end,
 446                           int datasync)
 447{
 448        struct p9_fid *fid;
 449        struct inode *inode = filp->f_mapping->host;
 450        struct p9_wstat wstat;
 451        int retval;
 452
 453        retval = file_write_and_wait_range(filp, start, end);
 454        if (retval)
 455                return retval;
 456
 457        inode_lock(inode);
 458        p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync);
 459
 460        fid = filp->private_data;
 461        v9fs_blank_wstat(&wstat);
 462
 463        retval = p9_client_wstat(fid, &wstat);
 464        inode_unlock(inode);
 465
 466        return retval;
 467}
 468
 469int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
 470                         int datasync)
 471{
 472        struct p9_fid *fid;
 473        struct inode *inode = filp->f_mapping->host;
 474        int retval;
 475
 476        retval = file_write_and_wait_range(filp, start, end);
 477        if (retval)
 478                return retval;
 479
 480        inode_lock(inode);
 481        p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync);
 482
 483        fid = filp->private_data;
 484
 485        retval = p9_client_fsync(fid, datasync);
 486        inode_unlock(inode);
 487
 488        return retval;
 489}
 490
 491static int
 492v9fs_file_mmap(struct file *filp, struct vm_area_struct *vma)
 493{
 494        int retval;
 495
 496
 497        retval = generic_file_mmap(filp, vma);
 498        if (!retval)
 499                vma->vm_ops = &v9fs_file_vm_ops;
 500
 501        return retval;
 502}
 503
 504static int
 505v9fs_mmap_file_mmap(struct file *filp, struct vm_area_struct *vma)
 506{
 507        int retval;
 508        struct inode *inode;
 509        struct v9fs_inode *v9inode;
 510        struct p9_fid *fid;
 511
 512        inode = file_inode(filp);
 513        v9inode = V9FS_I(inode);
 514        mutex_lock(&v9inode->v_mutex);
 515        if (!v9inode->writeback_fid &&
 516            (vma->vm_flags & VM_WRITE)) {
 517                /*
 518                 * clone a fid and add it to writeback_fid
 519                 * we do it during mmap instead of
 520                 * page dirty time via write_begin/page_mkwrite
 521                 * because we want write after unlink usecase
 522                 * to work.
 523                 */
 524                fid = v9fs_writeback_fid(file_dentry(filp));
 525                if (IS_ERR(fid)) {
 526                        retval = PTR_ERR(fid);
 527                        mutex_unlock(&v9inode->v_mutex);
 528                        return retval;
 529                }
 530                v9inode->writeback_fid = (void *) fid;
 531        }
 532        mutex_unlock(&v9inode->v_mutex);
 533
 534        retval = generic_file_mmap(filp, vma);
 535        if (!retval)
 536                vma->vm_ops = &v9fs_mmap_file_vm_ops;
 537
 538        return retval;
 539}
 540
 541static vm_fault_t
 542v9fs_vm_page_mkwrite(struct vm_fault *vmf)
 543{
 544        struct v9fs_inode *v9inode;
 545        struct page *page = vmf->page;
 546        struct file *filp = vmf->vma->vm_file;
 547        struct inode *inode = file_inode(filp);
 548
 549
 550        p9_debug(P9_DEBUG_VFS, "page %p fid %lx\n",
 551                 page, (unsigned long)filp->private_data);
 552
 553        /* Update file times before taking page lock */
 554        file_update_time(filp);
 555
 556        v9inode = V9FS_I(inode);
 557        /* make sure the cache has finished storing the page */
 558        v9fs_fscache_wait_on_page_write(inode, page);
 559        BUG_ON(!v9inode->writeback_fid);
 560        lock_page(page);
 561        if (page->mapping != inode->i_mapping)
 562                goto out_unlock;
 563        wait_for_stable_page(page);
 564
 565        return VM_FAULT_LOCKED;
 566out_unlock:
 567        unlock_page(page);
 568        return VM_FAULT_NOPAGE;
 569}
 570
 571/**
 572 * v9fs_mmap_file_read - read from a file
 573 * @filp: file pointer to read
 574 * @data: user data buffer to read data into
 575 * @count: size of buffer
 576 * @offset: offset at which to read data
 577 *
 578 */
 579static ssize_t
 580v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
 581{
 582        /* TODO: Check if there are dirty pages */
 583        return v9fs_file_read_iter(iocb, to);
 584}
 585
 586/**
 587 * v9fs_mmap_file_write - write to a file
 588 * @filp: file pointer to write
 589 * @data: data buffer to write data from
 590 * @count: size of buffer
 591 * @offset: offset at which to write data
 592 *
 593 */
 594static ssize_t
 595v9fs_mmap_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 596{
 597        /*
 598         * TODO: invalidate mmaps on filp's inode between
 599         * offset and offset+count
 600         */
 601        return v9fs_file_write_iter(iocb, from);
 602}
 603
 604static void v9fs_mmap_vm_close(struct vm_area_struct *vma)
 605{
 606        struct inode *inode;
 607
 608        struct writeback_control wbc = {
 609                .nr_to_write = LONG_MAX,
 610                .sync_mode = WB_SYNC_ALL,
 611                .range_start = vma->vm_pgoff * PAGE_SIZE,
 612                 /* absolute end, byte at end included */
 613                .range_end = vma->vm_pgoff * PAGE_SIZE +
 614                        (vma->vm_end - vma->vm_start - 1),
 615        };
 616
 617
 618        p9_debug(P9_DEBUG_VFS, "9p VMA close, %p, flushing", vma);
 619
 620        inode = file_inode(vma->vm_file);
 621
 622        if (!mapping_cap_writeback_dirty(inode->i_mapping))
 623                wbc.nr_to_write = 0;
 624
 625        might_sleep();
 626        sync_inode(inode, &wbc);
 627}
 628
 629
 630static const struct vm_operations_struct v9fs_file_vm_ops = {
 631        .fault = filemap_fault,
 632        .map_pages = filemap_map_pages,
 633        .page_mkwrite = v9fs_vm_page_mkwrite,
 634};
 635
 636static const struct vm_operations_struct v9fs_mmap_file_vm_ops = {
 637        .close = v9fs_mmap_vm_close,
 638        .fault = filemap_fault,
 639        .map_pages = filemap_map_pages,
 640        .page_mkwrite = v9fs_vm_page_mkwrite,
 641};
 642
 643
 644const struct file_operations v9fs_cached_file_operations = {
 645        .llseek = generic_file_llseek,
 646        .read_iter = generic_file_read_iter,
 647        .write_iter = generic_file_write_iter,
 648        .open = v9fs_file_open,
 649        .release = v9fs_dir_release,
 650        .lock = v9fs_file_lock,
 651        .mmap = v9fs_file_mmap,
 652        .fsync = v9fs_file_fsync,
 653};
 654
 655const struct file_operations v9fs_cached_file_operations_dotl = {
 656        .llseek = generic_file_llseek,
 657        .read_iter = generic_file_read_iter,
 658        .write_iter = generic_file_write_iter,
 659        .open = v9fs_file_open,
 660        .release = v9fs_dir_release,
 661        .lock = v9fs_file_lock_dotl,
 662        .flock = v9fs_file_flock_dotl,
 663        .mmap = v9fs_file_mmap,
 664        .fsync = v9fs_file_fsync_dotl,
 665};
 666
 667const struct file_operations v9fs_file_operations = {
 668        .llseek = generic_file_llseek,
 669        .read_iter = v9fs_file_read_iter,
 670        .write_iter = v9fs_file_write_iter,
 671        .open = v9fs_file_open,
 672        .release = v9fs_dir_release,
 673        .lock = v9fs_file_lock,
 674        .mmap = generic_file_readonly_mmap,
 675        .fsync = v9fs_file_fsync,
 676};
 677
 678const struct file_operations v9fs_file_operations_dotl = {
 679        .llseek = generic_file_llseek,
 680        .read_iter = v9fs_file_read_iter,
 681        .write_iter = v9fs_file_write_iter,
 682        .open = v9fs_file_open,
 683        .release = v9fs_dir_release,
 684        .lock = v9fs_file_lock_dotl,
 685        .flock = v9fs_file_flock_dotl,
 686        .mmap = generic_file_readonly_mmap,
 687        .fsync = v9fs_file_fsync_dotl,
 688};
 689
 690const struct file_operations v9fs_mmap_file_operations = {
 691        .llseek = generic_file_llseek,
 692        .read_iter = v9fs_mmap_file_read_iter,
 693        .write_iter = v9fs_mmap_file_write_iter,
 694        .open = v9fs_file_open,
 695        .release = v9fs_dir_release,
 696        .lock = v9fs_file_lock,
 697        .mmap = v9fs_mmap_file_mmap,
 698        .fsync = v9fs_file_fsync,
 699};
 700
 701const struct file_operations v9fs_mmap_file_operations_dotl = {
 702        .llseek = generic_file_llseek,
 703        .read_iter = v9fs_mmap_file_read_iter,
 704        .write_iter = v9fs_mmap_file_write_iter,
 705        .open = v9fs_file_open,
 706        .release = v9fs_dir_release,
 707        .lock = v9fs_file_lock_dotl,
 708        .flock = v9fs_file_flock_dotl,
 709        .mmap = v9fs_mmap_file_mmap,
 710        .fsync = v9fs_file_fsync_dotl,
 711};
 712