Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * linux/fs/nfs/file.c
4 : : *
5 : : * Copyright (C) 1992 Rick Sladkey
6 : : */
7 : : #include <linux/fs.h>
8 : : #include <linux/file.h>
9 : : #include <linux/falloc.h>
10 : : #include <linux/nfs_fs.h>
11 : : #include "delegation.h"
12 : : #include "internal.h"
13 : : #include "iostat.h"
14 : : #include "fscache.h"
15 : : #include "pnfs.h"
16 : :
17 : : #include "nfstrace.h"
18 : :
19 : : #ifdef CONFIG_NFS_V4_2
20 : : #include "nfs42.h"
21 : : #endif
22 : :
23 : : #define NFSDBG_FACILITY NFSDBG_FILE
24 : :
25 : : static int
26 : 0 : nfs4_file_open(struct inode *inode, struct file *filp)
27 : : {
28 : : struct nfs_open_context *ctx;
29 : : struct dentry *dentry = file_dentry(filp);
30 : : struct dentry *parent = NULL;
31 : : struct inode *dir;
32 : 0 : unsigned openflags = filp->f_flags;
33 : : struct iattr attr;
34 : : int err;
35 : :
36 : : /*
37 : : * If no cached dentry exists or if it's negative, NFSv4 handled the
38 : : * opens in ->lookup() or ->create().
39 : : *
40 : : * We only get this far for a cached positive dentry. We skipped
41 : : * revalidation, so handle it here by dropping the dentry and returning
42 : : * -EOPENSTALE. The VFS will retry the lookup/create/open.
43 : : */
44 : :
45 : : dprintk("NFS: open file(%pd2)\n", dentry);
46 : :
47 : 0 : err = nfs_check_flags(openflags);
48 : 0 : if (err)
49 : : return err;
50 : :
51 : 0 : if ((openflags & O_ACCMODE) == 3)
52 : 0 : return nfs_open(inode, filp);
53 : :
54 : : /* We can't create new files here */
55 : 0 : openflags &= ~(O_CREAT|O_EXCL);
56 : :
57 : 0 : parent = dget_parent(dentry);
58 : : dir = d_inode(parent);
59 : :
60 : 0 : ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode, filp);
61 : : err = PTR_ERR(ctx);
62 : 0 : if (IS_ERR(ctx))
63 : : goto out;
64 : :
65 : 0 : attr.ia_valid = ATTR_OPEN;
66 : 0 : if (openflags & O_TRUNC) {
67 : 0 : attr.ia_valid |= ATTR_SIZE;
68 : 0 : attr.ia_size = 0;
69 : 0 : filemap_write_and_wait(inode->i_mapping);
70 : : }
71 : :
72 : 0 : inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, NULL);
73 : 0 : if (IS_ERR(inode)) {
74 : : err = PTR_ERR(inode);
75 : 0 : switch (err) {
76 : : default:
77 : : goto out_put_ctx;
78 : : case -ENOENT:
79 : : case -ESTALE:
80 : : case -EISDIR:
81 : : case -ENOTDIR:
82 : : case -ELOOP:
83 : : goto out_drop;
84 : : }
85 : : }
86 : 0 : if (inode != d_inode(dentry))
87 : : goto out_drop;
88 : :
89 : 0 : nfs_file_set_open_context(filp, ctx);
90 : 0 : nfs_fscache_open_file(inode, filp);
91 : : err = 0;
92 : :
93 : : out_put_ctx:
94 : 0 : put_nfs_open_context(ctx);
95 : : out:
96 : 0 : dput(parent);
97 : 0 : return err;
98 : :
99 : : out_drop:
100 : 0 : d_drop(dentry);
101 : : err = -EOPENSTALE;
102 : 0 : goto out_put_ctx;
103 : : }
104 : :
105 : : /*
106 : : * Flush all dirty pages, and check for write errors.
107 : : */
108 : : static int
109 : 0 : nfs4_file_flush(struct file *file, fl_owner_t id)
110 : : {
111 : : struct inode *inode = file_inode(file);
112 : : errseq_t since;
113 : :
114 : : dprintk("NFS: flush(%pD2)\n", file);
115 : :
116 : 0 : nfs_inc_stats(inode, NFSIOS_VFSFLUSH);
117 : 0 : if ((file->f_mode & FMODE_WRITE) == 0)
118 : : return 0;
119 : :
120 : : /*
121 : : * If we're holding a write delegation, then check if we're required
122 : : * to flush the i/o on close. If not, then just start the i/o now.
123 : : */
124 : 0 : if (!nfs4_delegation_flush_on_close(inode))
125 : 0 : return filemap_fdatawrite(file->f_mapping);
126 : :
127 : : /* Flush writes to the server and return any errors */
128 : 0 : since = filemap_sample_wb_err(file->f_mapping);
129 : 0 : nfs_wb_all(inode);
130 : 0 : return filemap_check_wb_err(file->f_mapping, since);
131 : : }
132 : :
133 : : #ifdef CONFIG_NFS_V4_2
134 : 0 : static ssize_t __nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
135 : : struct file *file_out, loff_t pos_out,
136 : : size_t count, unsigned int flags)
137 : : {
138 : : /* Only offload copy if superblock is the same */
139 : 0 : if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb)
140 : : return -EXDEV;
141 : 0 : if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY))
142 : : return -EOPNOTSUPP;
143 : 0 : if (file_inode(file_in) == file_inode(file_out))
144 : : return -EOPNOTSUPP;
145 : 0 : return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
146 : : }
147 : :
148 : 0 : static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
149 : : struct file *file_out, loff_t pos_out,
150 : : size_t count, unsigned int flags)
151 : : {
152 : : ssize_t ret;
153 : :
154 : 0 : ret = __nfs4_copy_file_range(file_in, pos_in, file_out, pos_out, count,
155 : : flags);
156 : 0 : if (ret == -EOPNOTSUPP || ret == -EXDEV)
157 : 0 : ret = generic_copy_file_range(file_in, pos_in, file_out,
158 : : pos_out, count, flags);
159 : 0 : return ret;
160 : : }
161 : :
162 : 0 : static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)
163 : : {
164 : : loff_t ret;
165 : :
166 : 0 : switch (whence) {
167 : : case SEEK_HOLE:
168 : : case SEEK_DATA:
169 : 0 : ret = nfs42_proc_llseek(filep, offset, whence);
170 : 0 : if (ret != -ENOTSUPP)
171 : : return ret;
172 : : /* Fall through */
173 : : default:
174 : 0 : return nfs_file_llseek(filep, offset, whence);
175 : : }
176 : : }
177 : :
178 : 0 : static long nfs42_fallocate(struct file *filep, int mode, loff_t offset, loff_t len)
179 : : {
180 : : struct inode *inode = file_inode(filep);
181 : : long ret;
182 : :
183 : 0 : if (!S_ISREG(inode->i_mode))
184 : : return -EOPNOTSUPP;
185 : :
186 : 0 : if ((mode != 0) && (mode != (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)))
187 : : return -EOPNOTSUPP;
188 : :
189 : 0 : ret = inode_newsize_ok(inode, offset + len);
190 : 0 : if (ret < 0)
191 : : return ret;
192 : :
193 : 0 : if (mode & FALLOC_FL_PUNCH_HOLE)
194 : 0 : return nfs42_proc_deallocate(filep, offset, len);
195 : 0 : return nfs42_proc_allocate(filep, offset, len);
196 : : }
197 : :
198 : 0 : static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off,
199 : : struct file *dst_file, loff_t dst_off, loff_t count,
200 : : unsigned int remap_flags)
201 : : {
202 : : struct inode *dst_inode = file_inode(dst_file);
203 : : struct nfs_server *server = NFS_SERVER(dst_inode);
204 : : struct inode *src_inode = file_inode(src_file);
205 : 0 : unsigned int bs = server->clone_blksize;
206 : : bool same_inode = false;
207 : : int ret;
208 : :
209 : : /* NFS does not support deduplication. */
210 : 0 : if (remap_flags & REMAP_FILE_DEDUP)
211 : : return -EOPNOTSUPP;
212 : :
213 : 0 : if (remap_flags & ~REMAP_FILE_ADVISORY)
214 : : return -EINVAL;
215 : :
216 : 0 : if (IS_SWAPFILE(dst_inode) || IS_SWAPFILE(src_inode))
217 : : return -ETXTBSY;
218 : :
219 : : /* check alignment w.r.t. clone_blksize */
220 : : ret = -EINVAL;
221 : 0 : if (bs) {
222 : 0 : if (!IS_ALIGNED(src_off, bs) || !IS_ALIGNED(dst_off, bs))
223 : : goto out;
224 : 0 : if (!IS_ALIGNED(count, bs) && i_size_read(src_inode) != (src_off + count))
225 : : goto out;
226 : : }
227 : :
228 : 0 : if (src_inode == dst_inode)
229 : : same_inode = true;
230 : :
231 : : /* XXX: do we lock at all? what if server needs CB_RECALL_LAYOUT? */
232 : 0 : if (same_inode) {
233 : : inode_lock(src_inode);
234 : 0 : } else if (dst_inode < src_inode) {
235 : : inode_lock_nested(dst_inode, I_MUTEX_PARENT);
236 : : inode_lock_nested(src_inode, I_MUTEX_CHILD);
237 : : } else {
238 : : inode_lock_nested(src_inode, I_MUTEX_PARENT);
239 : : inode_lock_nested(dst_inode, I_MUTEX_CHILD);
240 : : }
241 : :
242 : : /* flush all pending writes on both src and dst so that server
243 : : * has the latest data */
244 : 0 : ret = nfs_sync_inode(src_inode);
245 : 0 : if (ret)
246 : : goto out_unlock;
247 : 0 : ret = nfs_sync_inode(dst_inode);
248 : 0 : if (ret)
249 : : goto out_unlock;
250 : :
251 : 0 : ret = nfs42_proc_clone(src_file, dst_file, src_off, dst_off, count);
252 : :
253 : : /* truncate inode page cache of the dst range so that future reads can fetch
254 : : * new data from server */
255 : 0 : if (!ret)
256 : 0 : truncate_inode_pages_range(&dst_inode->i_data, dst_off, dst_off + count - 1);
257 : :
258 : : out_unlock:
259 : 0 : if (same_inode) {
260 : : inode_unlock(src_inode);
261 : 0 : } else if (dst_inode < src_inode) {
262 : : inode_unlock(src_inode);
263 : : inode_unlock(dst_inode);
264 : : } else {
265 : : inode_unlock(dst_inode);
266 : : inode_unlock(src_inode);
267 : : }
268 : : out:
269 : 0 : return ret < 0 ? ret : count;
270 : : }
271 : : #endif /* CONFIG_NFS_V4_2 */
272 : :
273 : : const struct file_operations nfs4_file_operations = {
274 : : .read_iter = nfs_file_read,
275 : : .write_iter = nfs_file_write,
276 : : .mmap = nfs_file_mmap,
277 : : .open = nfs4_file_open,
278 : : .flush = nfs4_file_flush,
279 : : .release = nfs_file_release,
280 : : .fsync = nfs_file_fsync,
281 : : .lock = nfs_lock,
282 : : .flock = nfs_flock,
283 : : .splice_read = generic_file_splice_read,
284 : : .splice_write = iter_file_splice_write,
285 : : .check_flags = nfs_check_flags,
286 : : .setlease = simple_nosetlease,
287 : : #ifdef CONFIG_NFS_V4_2
288 : : .copy_file_range = nfs4_copy_file_range,
289 : : .llseek = nfs4_file_llseek,
290 : : .fallocate = nfs42_fallocate,
291 : : .remap_file_range = nfs42_remap_file_range,
292 : : #else
293 : : .llseek = nfs_file_llseek,
294 : : #endif
295 : : };
|