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