1/*
2 *  linux/fs/nfs/file.c
3 *
4 *  Copyright (C) 1992  Rick Sladkey
5 */
6#include <linux/fs.h>
7#include <linux/falloc.h>
8#include <linux/nfs_fs.h>
9#include "internal.h"
10#include "fscache.h"
11#include "pnfs.h"
12
13#include "nfstrace.h"
14
15#ifdef CONFIG_NFS_V4_2
16#include "nfs42.h"
17#endif
18
19#define NFSDBG_FACILITY		NFSDBG_FILE
20
21static int
22nfs4_file_open(struct inode *inode, struct file *filp)
23{
24	struct nfs_open_context *ctx;
25	struct dentry *dentry = filp->f_path.dentry;
26	struct dentry *parent = NULL;
27	struct inode *dir;
28	unsigned openflags = filp->f_flags;
29	struct iattr attr;
30	int opened = 0;
31	int err;
32
33	/*
34	 * If no cached dentry exists or if it's negative, NFSv4 handled the
35	 * opens in ->lookup() or ->create().
36	 *
37	 * We only get this far for a cached positive dentry.  We skipped
38	 * revalidation, so handle it here by dropping the dentry and returning
39	 * -EOPENSTALE.  The VFS will retry the lookup/create/open.
40	 */
41
42	dprintk("NFS: open file(%pd2)\n", dentry);
43
44	if ((openflags & O_ACCMODE) == 3)
45		openflags--;
46
47	/* We can't create new files here */
48	openflags &= ~(O_CREAT|O_EXCL);
49
50	parent = dget_parent(dentry);
51	dir = d_inode(parent);
52
53	ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
54	err = PTR_ERR(ctx);
55	if (IS_ERR(ctx))
56		goto out;
57
58	attr.ia_valid = ATTR_OPEN;
59	if (openflags & O_TRUNC) {
60		attr.ia_valid |= ATTR_SIZE;
61		attr.ia_size = 0;
62		nfs_sync_inode(inode);
63	}
64
65	inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, &opened);
66	if (IS_ERR(inode)) {
67		err = PTR_ERR(inode);
68		switch (err) {
69		case -EPERM:
70		case -EACCES:
71		case -EDQUOT:
72		case -ENOSPC:
73		case -EROFS:
74			goto out_put_ctx;
75		default:
76			goto out_drop;
77		}
78	}
79	if (inode != d_inode(dentry))
80		goto out_drop;
81
82	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
83	nfs_file_set_open_context(filp, ctx);
84	nfs_fscache_open_file(inode, filp);
85	err = 0;
86
87out_put_ctx:
88	put_nfs_open_context(ctx);
89out:
90	dput(parent);
91	return err;
92
93out_drop:
94	d_drop(dentry);
95	err = -EOPENSTALE;
96	goto out_put_ctx;
97}
98
99static int
100nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
101{
102	int ret;
103	struct inode *inode = file_inode(file);
104
105	trace_nfs_fsync_enter(inode);
106
107	nfs_inode_dio_wait(inode);
108	do {
109		ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
110		if (ret != 0)
111			break;
112		mutex_lock(&inode->i_mutex);
113		ret = nfs_file_fsync_commit(file, start, end, datasync);
114		if (!ret)
115			ret = pnfs_sync_inode(inode, !!datasync);
116		mutex_unlock(&inode->i_mutex);
117		/*
118		 * If nfs_file_fsync_commit detected a server reboot, then
119		 * resend all dirty pages that might have been covered by
120		 * the NFS_CONTEXT_RESEND_WRITES flag
121		 */
122		start = 0;
123		end = LLONG_MAX;
124	} while (ret == -EAGAIN);
125
126	trace_nfs_fsync_exit(inode, ret);
127	return ret;
128}
129
130#ifdef CONFIG_NFS_V4_2
131static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)
132{
133	loff_t ret;
134
135	switch (whence) {
136	case SEEK_HOLE:
137	case SEEK_DATA:
138		ret = nfs42_proc_llseek(filep, offset, whence);
139		if (ret != -ENOTSUPP)
140			return ret;
141	default:
142		return nfs_file_llseek(filep, offset, whence);
143	}
144}
145
146static long nfs42_fallocate(struct file *filep, int mode, loff_t offset, loff_t len)
147{
148	struct inode *inode = file_inode(filep);
149	long ret;
150
151	if (!S_ISREG(inode->i_mode))
152		return -EOPNOTSUPP;
153
154	if ((mode != 0) && (mode != (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)))
155		return -EOPNOTSUPP;
156
157	ret = inode_newsize_ok(inode, offset + len);
158	if (ret < 0)
159		return ret;
160
161	if (mode & FALLOC_FL_PUNCH_HOLE)
162		return nfs42_proc_deallocate(filep, offset, len);
163	return nfs42_proc_allocate(filep, offset, len);
164}
165#endif /* CONFIG_NFS_V4_2 */
166
167const struct file_operations nfs4_file_operations = {
168#ifdef CONFIG_NFS_V4_2
169	.llseek		= nfs4_file_llseek,
170#else
171	.llseek		= nfs_file_llseek,
172#endif
173	.read_iter	= nfs_file_read,
174	.write_iter	= nfs_file_write,
175	.mmap		= nfs_file_mmap,
176	.open		= nfs4_file_open,
177	.flush		= nfs_file_flush,
178	.release	= nfs_file_release,
179	.fsync		= nfs4_file_fsync,
180	.lock		= nfs_lock,
181	.flock		= nfs_flock,
182	.splice_read	= nfs_file_splice_read,
183	.splice_write	= iter_file_splice_write,
184#ifdef CONFIG_NFS_V4_2
185	.fallocate	= nfs42_fallocate,
186#endif /* CONFIG_NFS_V4_2 */
187	.check_flags	= nfs_check_flags,
188	.setlease	= simple_nosetlease,
189};
190