Branch data Line data Source code
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 : :
13 : : static int
14 : 0 : nfs4_file_open(struct inode *inode, struct file *filp)
15 : : {
16 : : struct nfs_open_context *ctx;
17 : 0 : struct dentry *dentry = filp->f_path.dentry;
18 : : struct dentry *parent = NULL;
19 : : struct inode *dir;
20 : 0 : unsigned openflags = filp->f_flags;
21 : : struct iattr attr;
22 : 0 : 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 [ # # ]: 0 : if ((openflags & O_ACCMODE) == 3)
37 : 0 : openflags--;
38 : :
39 : : /* We can't create new files here */
40 : 0 : openflags &= ~(O_CREAT|O_EXCL);
41 : :
42 : 0 : parent = dget_parent(dentry);
43 : 0 : dir = parent->d_inode;
44 : :
45 : 0 : ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
46 : : err = PTR_ERR(ctx);
47 [ # # ]: 0 : if (IS_ERR(ctx))
48 : : goto out;
49 : :
50 : 0 : attr.ia_valid = ATTR_OPEN;
51 [ # # ]: 0 : if (openflags & O_TRUNC) {
52 : 0 : attr.ia_valid |= ATTR_SIZE;
53 : 0 : attr.ia_size = 0;
54 : 0 : nfs_wb_all(inode);
55 : : }
56 : :
57 : 0 : inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, &opened);
58 [ # # ]: 0 : if (IS_ERR(inode)) {
59 : : err = PTR_ERR(inode);
60 [ # # ]: 0 : 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 [ # # ]: 0 : if (inode != dentry->d_inode)
72 : : goto out_drop;
73 : :
74 : : nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
75 : 0 : nfs_file_set_open_context(filp, ctx);
76 : : nfs_fscache_open_file(inode, filp);
77 : : err = 0;
78 : :
79 : : out_put_ctx:
80 : 0 : put_nfs_open_context(ctx);
81 : : out:
82 : 0 : dput(parent);
83 : 0 : return err;
84 : :
85 : : out_drop:
86 : 0 : d_drop(dentry);
87 : : err = -EOPENSTALE;
88 : 0 : goto out_put_ctx;
89 : : }
90 : :
91 : : static int
92 : 0 : nfs4_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 : 0 : ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
99 [ # # ]: 0 : if (ret != 0)
100 : : break;
101 : 0 : mutex_lock(&inode->i_mutex);
102 : 0 : ret = nfs_file_fsync_commit(file, start, end, datasync);
103 [ # # ]: 0 : if (!ret && !datasync)
104 : : /* application has asked for meta-data sync */
105 : : ret = pnfs_layoutcommit_inode(inode, true);
106 : 0 : 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 [ # # ]: 0 : } while (ret == -EAGAIN);
115 : :
116 : 0 : return ret;
117 : : }
118 : :
119 : : const 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 : : };
|