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