linux/fs/nfs/nfs4file.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/nfs/file.c
   3 *
   4 *  Copyright (C) 1992  Rick Sladkey
   5 */
   6#include <linux/nfs_fs.h>
   7#include "internal.h"
   8#include "fscache.h"
   9#include "pnfs.h"
  10
  11#define NFSDBG_FACILITY         NFSDBG_FILE
  12
  13static int
  14nfs4_file_open(struct inode *inode, struct file *filp)
  15{
  16        struct nfs_open_context *ctx;
  17        struct dentry *dentry = filp->f_path.dentry;
  18        struct dentry *parent = NULL;
  19        struct inode *dir;
  20        unsigned openflags = filp->f_flags;
  21        struct iattr attr;
  22        int opened = 0;
  23        int err;
  24
  25        /*
  26         * If no cached dentry exists or if it's negative, NFSv4 handled the
  27         * opens in ->lookup() or ->create().
  28         *
  29         * We only get this far for a cached positive dentry.  We skipped
  30         * revalidation, so handle it here by dropping the dentry and returning
  31         * -EOPENSTALE.  The VFS will retry the lookup/create/open.
  32         */
  33
  34        dprintk("NFS: open file(%pd2)\n", dentry);
  35
  36        if ((openflags & O_ACCMODE) == 3)
  37                openflags--;
  38
  39        /* We can't create new files here */
  40        openflags &= ~(O_CREAT|O_EXCL);
  41
  42        parent = dget_parent(dentry);
  43        dir = parent->d_inode;
  44
  45        ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
  46        err = PTR_ERR(ctx);
  47        if (IS_ERR(ctx))
  48                goto out;
  49
  50        attr.ia_valid = ATTR_OPEN;
  51        if (openflags & O_TRUNC) {
  52                attr.ia_valid |= ATTR_SIZE;
  53                attr.ia_size = 0;
  54                nfs_wb_all(inode);
  55        }
  56
  57        inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, &opened);
  58        if (IS_ERR(inode)) {
  59                err = PTR_ERR(inode);
  60                switch (err) {
  61                case -EPERM:
  62                case -EACCES:
  63                case -EDQUOT:
  64                case -ENOSPC:
  65                case -EROFS:
  66                        goto out_put_ctx;
  67                default:
  68                        goto out_drop;
  69                }
  70        }
  71        if (inode != dentry->d_inode)
  72                goto out_drop;
  73
  74        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
  75        nfs_file_set_open_context(filp, ctx);
  76        nfs_fscache_open_file(inode, filp);
  77        err = 0;
  78
  79out_put_ctx:
  80        put_nfs_open_context(ctx);
  81out:
  82        dput(parent);
  83        return err;
  84
  85out_drop:
  86        d_drop(dentry);
  87        err = -EOPENSTALE;
  88        goto out_put_ctx;
  89}
  90
  91static int
  92nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
  93{
  94        int ret;
  95        struct inode *inode = file_inode(file);
  96
  97        do {
  98                ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
  99                if (ret != 0)
 100                        break;
 101                mutex_lock(&inode->i_mutex);
 102                ret = nfs_file_fsync_commit(file, start, end, datasync);
 103                if (!ret && !datasync)
 104                        /* application has asked for meta-data sync */
 105                        ret = pnfs_layoutcommit_inode(inode, true);
 106                mutex_unlock(&inode->i_mutex);
 107                /*
 108                 * If nfs_file_fsync_commit detected a server reboot, then
 109                 * resend all dirty pages that might have been covered by
 110                 * the NFS_CONTEXT_RESEND_WRITES flag
 111                 */
 112                start = 0;
 113                end = LLONG_MAX;
 114        } while (ret == -EAGAIN);
 115
 116        return ret;
 117}
 118
 119const struct file_operations nfs4_file_operations = {
 120        .llseek         = nfs_file_llseek,
 121        .read           = do_sync_read,
 122        .write          = do_sync_write,
 123        .aio_read       = nfs_file_read,
 124        .aio_write      = nfs_file_write,
 125        .mmap           = nfs_file_mmap,
 126        .open           = nfs4_file_open,
 127        .flush          = nfs_file_flush,
 128        .release        = nfs_file_release,
 129        .fsync          = nfs4_file_fsync,
 130        .lock           = nfs_lock,
 131        .flock          = nfs_flock,
 132        .splice_read    = nfs_file_splice_read,
 133        .splice_write   = nfs_file_splice_write,
 134        .check_flags    = nfs_check_flags,
 135        .setlease       = nfs_setlease,
 136};
 137