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