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_debug(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 = v9fs_open_to_dotl_flags(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_debug(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        /* map the lock type */
 173        switch (fl->fl_type) {
 174        case F_RDLCK:
 175                flock.type = P9_LOCK_TYPE_RDLCK;
 176                break;
 177        case F_WRLCK:
 178                flock.type = P9_LOCK_TYPE_WRLCK;
 179                break;
 180        case F_UNLCK:
 181                flock.type = P9_LOCK_TYPE_UNLCK;
 182                break;
 183        }
 184        flock.start = fl->fl_start;
 185        if (fl->fl_end == OFFSET_MAX)
 186                flock.length = 0;
 187        else
 188                flock.length = fl->fl_end - fl->fl_start + 1;
 189        flock.proc_id = fl->fl_pid;
 190        flock.client_id = utsname()->nodename;
 191        if (IS_SETLKW(cmd))
 192                flock.flags = P9_LOCK_FLAGS_BLOCK;
 193
 194        /*
 195         * if its a blocked request and we get P9_LOCK_BLOCKED as the status
 196         * for lock request, keep on trying
 197         */
 198        for (;;) {
 199                res = p9_client_lock_dotl(fid, &flock, &status);
 200                if (res < 0)
 201                        break;
 202
 203                if (status != P9_LOCK_BLOCKED)
 204                        break;
 205                if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd))
 206                        break;
 207                if (schedule_timeout_interruptible(P9_LOCK_TIMEOUT) != 0)
 208                        break;
 209        }
 210
 211        /* map 9p status to VFS status */
 212        switch (status) {
 213        case P9_LOCK_SUCCESS:
 214                res = 0;
 215                break;
 216        case P9_LOCK_BLOCKED:
 217                res = -EAGAIN;
 218                break;
 219        case P9_LOCK_ERROR:
 220        case P9_LOCK_GRACE:
 221                res = -ENOLCK;
 222                break;
 223        default:
 224                BUG();
 225        }
 226
 227        /*
 228         * incase server returned error for lock request, revert
 229         * it locally
 230         */
 231        if (res < 0 && fl->fl_type != F_UNLCK) {
 232                fl_type = fl->fl_type;
 233                fl->fl_type = F_UNLCK;
 234                res = posix_lock_file_wait(filp, fl);
 235                fl->fl_type = fl_type;
 236        }
 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 = utsname()->nodename;
 268
 269        res = p9_client_getlock_dotl(fid, &glock);
 270        if (res < 0)
 271                return res;
 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        }
 292        return res;
 293}
 294
 295/**
 296 * v9fs_file_lock_dotl - lock a file (or directory)
 297 * @filp: file to be locked
 298 * @cmd: lock command
 299 * @fl: file lock structure
 300 *
 301 */
 302
 303static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl)
 304{
 305        struct inode *inode = filp->f_path.dentry->d_inode;
 306        int ret = -ENOLCK;
 307
 308        p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n",
 309                 filp, cmd, fl, filp->f_path.dentry->d_name.name);
 310
 311        /* No mandatory locks */
 312        if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
 313                goto out_err;
 314
 315        if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
 316                filemap_write_and_wait(inode->i_mapping);
 317                invalidate_mapping_pages(&inode->i_data, 0, -1);
 318        }
 319
 320        if (IS_SETLK(cmd) || IS_SETLKW(cmd))
 321                ret = v9fs_file_do_lock(filp, cmd, fl);
 322        else if (IS_GETLK(cmd))
 323                ret = v9fs_file_getlock(filp, fl);
 324        else
 325                ret = -EINVAL;
 326out_err:
 327        return ret;
 328}
 329
 330/**
 331 * v9fs_file_flock_dotl - lock a file
 332 * @filp: file to be locked
 333 * @cmd: lock command
 334 * @fl: file lock structure
 335 *
 336 */
 337
 338static int v9fs_file_flock_dotl(struct file *filp, int cmd,
 339        struct file_lock *fl)
 340{
 341        struct inode *inode = filp->f_path.dentry->d_inode;
 342        int ret = -ENOLCK;
 343
 344        p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n",
 345                 filp, cmd, fl, filp->f_path.dentry->d_name.name);
 346
 347        /* No mandatory locks */
 348        if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
 349                goto out_err;
 350
 351        if (!(fl->fl_flags & FL_FLOCK))
 352                goto out_err;
 353
 354        if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
 355                filemap_write_and_wait(inode->i_mapping);
 356                invalidate_mapping_pages(&inode->i_data, 0, -1);
 357        }
 358        /* Convert flock to posix lock */
 359        fl->fl_owner = (fl_owner_t)filp;
 360        fl->fl_start = 0;
 361        fl->fl_end = OFFSET_MAX;
 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_fid_readn - read from a fid
 375 * @fid: fid to read
 376 * @data: data buffer to read data into
 377 * @udata: user data buffer to read data into
 378 * @count: size of buffer
 379 * @offset: offset at which to read data
 380 *
 381 */
 382ssize_t
 383v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count,
 384               u64 offset)
 385{
 386        int n, total, size;
 387
 388        p9_debug(P9_DEBUG_VFS, "fid %d offset %llu count %d\n",
 389                 fid->fid, (long long unsigned)offset, count);
 390        n = 0;
 391        total = 0;
 392        size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ;
 393        do {
 394                n = p9_client_read(fid, data, udata, offset, count);
 395                if (n <= 0)
 396                        break;
 397
 398                if (data)
 399                        data += n;
 400                if (udata)
 401                        udata += n;
 402
 403                offset += n;
 404                count -= n;
 405                total += n;
 406        } while (count > 0 && n == size);
 407
 408        if (n < 0)
 409                total = n;
 410
 411        return total;
 412}
 413
 414/**
 415 * v9fs_file_readn - read from a file
 416 * @filp: file pointer to read
 417 * @data: data buffer to read data into
 418 * @udata: user data buffer to read data into
 419 * @count: size of buffer
 420 * @offset: offset at which to read data
 421 *
 422 */
 423ssize_t
 424v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
 425               u64 offset)
 426{
 427        return v9fs_fid_readn(filp->private_data, data, udata, count, offset);
 428}
 429
 430/**
 431 * v9fs_file_read - read from a file
 432 * @filp: file pointer to read
 433 * @udata: user data buffer to read data into
 434 * @count: size of buffer
 435 * @offset: offset at which to read data
 436 *
 437 */
 438
 439static ssize_t
 440v9fs_file_read(struct file *filp, char __user *udata, size_t count,
 441               loff_t * offset)
 442{
 443        int ret;
 444        struct p9_fid *fid;
 445        size_t size;
 446
 447        p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset);
 448        fid = filp->private_data;
 449
 450        size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ;
 451        if (count > size)
 452                ret = v9fs_file_readn(filp, NULL, udata, count, *offset);
 453        else
 454                ret = p9_client_read(fid, NULL, udata, *offset, count);
 455
 456        if (ret > 0)
 457                *offset += ret;
 458
 459        return ret;
 460}
 461
 462ssize_t
 463v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid,
 464                         const char __user *data, size_t count,
 465                         loff_t *offset, int invalidate)
 466{
 467        int n;
 468        loff_t i_size;
 469        size_t total = 0;
 470        struct p9_client *clnt;
 471        loff_t origin = *offset;
 472        unsigned long pg_start, pg_end;
 473
 474        p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n",
 475                 data, (int)count, (int)*offset);
 476
 477        clnt = fid->clnt;
 478        do {
 479                n = p9_client_write(fid, NULL, data+total, origin+total, count);
 480                if (n <= 0)
 481                        break;
 482                count -= n;
 483                total += n;
 484        } while (count > 0);
 485
 486        if (invalidate && (total > 0)) {
 487                pg_start = origin >> PAGE_CACHE_SHIFT;
 488                pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT;
 489                if (inode->i_mapping && inode->i_mapping->nrpages)
 490                        invalidate_inode_pages2_range(inode->i_mapping,
 491                                                      pg_start, pg_end);
 492                *offset += total;
 493                i_size = i_size_read(inode);
 494                if (*offset > i_size) {
 495                        inode_add_bytes(inode, *offset - i_size);
 496                        i_size_write(inode, *offset);
 497                }
 498        }
 499        if (n < 0)
 500                return n;
 501
 502        return total;
 503}
 504
 505/**
 506 * v9fs_file_write - write to a file
 507 * @filp: file pointer to write
 508 * @data: data buffer to write data from
 509 * @count: size of buffer
 510 * @offset: offset at which to write data
 511 *
 512 */
 513static ssize_t
 514v9fs_file_write(struct file *filp, const char __user * data,
 515                size_t count, loff_t *offset)
 516{
 517        ssize_t retval = 0;
 518        loff_t origin = *offset;
 519
 520
 521        retval = generic_write_checks(filp, &origin, &count, 0);
 522        if (retval)
 523                goto out;
 524
 525        retval = -EINVAL;
 526        if ((ssize_t) count < 0)
 527                goto out;
 528        retval = 0;
 529        if (!count)
 530                goto out;
 531
 532        retval = v9fs_file_write_internal(filp->f_path.dentry->d_inode,
 533                                        filp->private_data,
 534                                        data, count, &origin, 1);
 535        /* update offset on successful write */
 536        if (retval > 0)
 537                *offset = origin;
 538out:
 539        return retval;
 540}
 541
 542
 543static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end,
 544                           int datasync)
 545{
 546        struct p9_fid *fid;
 547        struct inode *inode = filp->f_mapping->host;
 548        struct p9_wstat wstat;
 549        int retval;
 550
 551        retval = filemap_write_and_wait_range(inode->i_mapping, start, end);
 552        if (retval)
 553                return retval;
 554
 555        mutex_lock(&inode->i_mutex);
 556        p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync);
 557
 558        fid = filp->private_data;
 559        v9fs_blank_wstat(&wstat);
 560
 561        retval = p9_client_wstat(fid, &wstat);
 562        mutex_unlock(&inode->i_mutex);
 563
 564        return retval;
 565}
 566
 567int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
 568                         int datasync)
 569{
 570        struct p9_fid *fid;
 571        struct inode *inode = filp->f_mapping->host;
 572        int retval;
 573
 574        retval = filemap_write_and_wait_range(inode->i_mapping, start, end);
 575        if (retval)
 576                return retval;
 577
 578        mutex_lock(&inode->i_mutex);
 579        p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync);
 580
 581        fid = filp->private_data;
 582
 583        retval = p9_client_fsync(fid, datasync);
 584        mutex_unlock(&inode->i_mutex);
 585
 586        return retval;
 587}
 588
 589static int
 590v9fs_file_mmap(struct file *file, struct vm_area_struct *vma)
 591{
 592        int retval;
 593
 594        retval = generic_file_mmap(file, vma);
 595        if (!retval)
 596                vma->vm_ops = &v9fs_file_vm_ops;
 597
 598        return retval;
 599}
 600
 601static int
 602v9fs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 603{
 604        struct v9fs_inode *v9inode;
 605        struct page *page = vmf->page;
 606        struct file *filp = vma->vm_file;
 607        struct inode *inode = filp->f_path.dentry->d_inode;
 608
 609
 610        p9_debug(P9_DEBUG_VFS, "page %p fid %lx\n",
 611                 page, (unsigned long)filp->private_data);
 612
 613        /* Update file times before taking page lock */
 614        file_update_time(filp);
 615
 616        v9inode = V9FS_I(inode);
 617        /* make sure the cache has finished storing the page */
 618        v9fs_fscache_wait_on_page_write(inode, page);
 619        BUG_ON(!v9inode->writeback_fid);
 620        lock_page(page);
 621        if (page->mapping != inode->i_mapping)
 622                goto out_unlock;
 623
 624        return VM_FAULT_LOCKED;
 625out_unlock:
 626        unlock_page(page);
 627        return VM_FAULT_NOPAGE;
 628}
 629
 630static ssize_t
 631v9fs_direct_read(struct file *filp, char __user *udata, size_t count,
 632                 loff_t *offsetp)
 633{
 634        loff_t size, offset;
 635        struct inode *inode;
 636        struct address_space *mapping;
 637
 638        offset = *offsetp;
 639        mapping = filp->f_mapping;
 640        inode = mapping->host;
 641        if (!count)
 642                return 0;
 643        size = i_size_read(inode);
 644        if (offset < size)
 645                filemap_write_and_wait_range(mapping, offset,
 646                                             offset + count - 1);
 647
 648        return v9fs_file_read(filp, udata, count, offsetp);
 649}
 650
 651/**
 652 * v9fs_cached_file_read - read from a file
 653 * @filp: file pointer to read
 654 * @udata: user data buffer to read data into
 655 * @count: size of buffer
 656 * @offset: offset at which to read data
 657 *
 658 */
 659static ssize_t
 660v9fs_cached_file_read(struct file *filp, char __user *data, size_t count,
 661                      loff_t *offset)
 662{
 663        if (filp->f_flags & O_DIRECT)
 664                return v9fs_direct_read(filp, data, count, offset);
 665        return do_sync_read(filp, data, count, offset);
 666}
 667
 668static ssize_t
 669v9fs_direct_write(struct file *filp, const char __user * data,
 670                  size_t count, loff_t *offsetp)
 671{
 672        loff_t offset;
 673        ssize_t retval;
 674        struct inode *inode;
 675        struct address_space *mapping;
 676
 677        offset = *offsetp;
 678        mapping = filp->f_mapping;
 679        inode = mapping->host;
 680        if (!count)
 681                return 0;
 682
 683        mutex_lock(&inode->i_mutex);
 684        retval = filemap_write_and_wait_range(mapping, offset,
 685                                              offset + count - 1);
 686        if (retval)
 687                goto err_out;
 688        /*
 689         * After a write we want buffered reads to be sure to go to disk to get
 690         * the new data.  We invalidate clean cached page from the region we're
 691         * about to write.  We do this *before* the write so that if we fail
 692         * here we fall back to buffered write
 693         */
 694        if (mapping->nrpages) {
 695                pgoff_t pg_start = offset >> PAGE_CACHE_SHIFT;
 696                pgoff_t pg_end   = (offset + count - 1) >> PAGE_CACHE_SHIFT;
 697
 698                retval = invalidate_inode_pages2_range(mapping,
 699                                                        pg_start, pg_end);
 700                /*
 701                 * If a page can not be invalidated, fall back
 702                 * to buffered write.
 703                 */
 704                if (retval) {
 705                        if (retval == -EBUSY)
 706                                goto buff_write;
 707                        goto err_out;
 708                }
 709        }
 710        retval = v9fs_file_write(filp, data, count, offsetp);
 711err_out:
 712        mutex_unlock(&inode->i_mutex);
 713        return retval;
 714
 715buff_write:
 716        mutex_unlock(&inode->i_mutex);
 717        return do_sync_write(filp, data, count, offsetp);
 718}
 719
 720/**
 721 * v9fs_cached_file_write - write to a file
 722 * @filp: file pointer to write
 723 * @data: data buffer to write data from
 724 * @count: size of buffer
 725 * @offset: offset at which to write data
 726 *
 727 */
 728static ssize_t
 729v9fs_cached_file_write(struct file *filp, const char __user * data,
 730                       size_t count, loff_t *offset)
 731{
 732
 733        if (filp->f_flags & O_DIRECT)
 734                return v9fs_direct_write(filp, data, count, offset);
 735        return do_sync_write(filp, data, count, offset);
 736}
 737
 738static const struct vm_operations_struct v9fs_file_vm_ops = {
 739        .fault = filemap_fault,
 740        .page_mkwrite = v9fs_vm_page_mkwrite,
 741};
 742
 743
 744const struct file_operations v9fs_cached_file_operations = {
 745        .llseek = generic_file_llseek,
 746        .read = v9fs_cached_file_read,
 747        .write = v9fs_cached_file_write,
 748        .aio_read = generic_file_aio_read,
 749        .aio_write = generic_file_aio_write,
 750        .open = v9fs_file_open,
 751        .release = v9fs_dir_release,
 752        .lock = v9fs_file_lock,
 753        .mmap = v9fs_file_mmap,
 754        .fsync = v9fs_file_fsync,
 755};
 756
 757const struct file_operations v9fs_cached_file_operations_dotl = {
 758        .llseek = generic_file_llseek,
 759        .read = v9fs_cached_file_read,
 760        .write = v9fs_cached_file_write,
 761        .aio_read = generic_file_aio_read,
 762        .aio_write = generic_file_aio_write,
 763        .open = v9fs_file_open,
 764        .release = v9fs_dir_release,
 765        .lock = v9fs_file_lock_dotl,
 766        .flock = v9fs_file_flock_dotl,
 767        .mmap = v9fs_file_mmap,
 768        .fsync = v9fs_file_fsync_dotl,
 769};
 770
 771const struct file_operations v9fs_file_operations = {
 772        .llseek = generic_file_llseek,
 773        .read = v9fs_file_read,
 774        .write = v9fs_file_write,
 775        .open = v9fs_file_open,
 776        .release = v9fs_dir_release,
 777        .lock = v9fs_file_lock,
 778        .mmap = generic_file_readonly_mmap,
 779        .fsync = v9fs_file_fsync,
 780};
 781
 782const struct file_operations v9fs_file_operations_dotl = {
 783        .llseek = generic_file_llseek,
 784        .read = v9fs_file_read,
 785        .write = v9fs_file_write,
 786        .open = v9fs_file_open,
 787        .release = v9fs_dir_release,
 788        .lock = v9fs_file_lock_dotl,
 789        .flock = v9fs_file_flock_dotl,
 790        .mmap = generic_file_readonly_mmap,
 791        .fsync = v9fs_file_fsync_dotl,
 792};
 793
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.