2 * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com>
5 #include <linux/sunrpc/sched.h>
7 #include <linux/nfs3.h>
8 #include <linux/nfs4.h>
9 #include <linux/nfs_xdr.h>
10 #include <linux/nfs_fs.h>
17 #define NFSDBG_FACILITY NFSDBG_PROC
19 static int nfs42_set_rw_stateid(nfs4_stateid
*dst
, struct file
*file
,
22 struct nfs_open_context
*open
;
23 struct nfs_lock_context
*lock
;
26 open
= get_nfs_open_context(nfs_file_open_context(file
));
27 lock
= nfs_get_lock_context(open
);
29 put_nfs_open_context(open
);
33 ret
= nfs4_set_rw_stateid(dst
, open
, lock
, fmode
);
35 nfs_put_lock_context(lock
);
36 put_nfs_open_context(open
);
40 static int _nfs42_proc_fallocate(struct rpc_message
*msg
, struct file
*filep
,
41 loff_t offset
, loff_t len
)
43 struct inode
*inode
= file_inode(filep
);
44 struct nfs_server
*server
= NFS_SERVER(inode
);
45 struct nfs42_falloc_args args
= {
46 .falloc_fh
= NFS_FH(inode
),
47 .falloc_offset
= offset
,
49 .falloc_bitmask
= server
->cache_consistency_bitmask
,
51 struct nfs42_falloc_res res
= {
52 .falloc_server
= server
,
56 msg
->rpc_argp
= &args
;
59 status
= nfs42_set_rw_stateid(&args
.falloc_stateid
, filep
, FMODE_WRITE
);
63 res
.falloc_fattr
= nfs_alloc_fattr();
64 if (!res
.falloc_fattr
)
67 status
= nfs4_call_sync(server
->client
, server
, msg
,
68 &args
.seq_args
, &res
.seq_res
, 0);
70 status
= nfs_post_op_update_inode(inode
, res
.falloc_fattr
);
72 kfree(res
.falloc_fattr
);
76 static int nfs42_proc_fallocate(struct rpc_message
*msg
, struct file
*filep
,
77 loff_t offset
, loff_t len
)
79 struct nfs_server
*server
= NFS_SERVER(file_inode(filep
));
80 struct nfs4_exception exception
= { };
84 err
= _nfs42_proc_fallocate(msg
, filep
, offset
, len
);
87 err
= nfs4_handle_exception(server
, err
, &exception
);
88 } while (exception
.retry
);
93 int nfs42_proc_allocate(struct file
*filep
, loff_t offset
, loff_t len
)
95 struct rpc_message msg
= {
96 .rpc_proc
= &nfs4_procedures
[NFSPROC4_CLNT_ALLOCATE
],
98 struct inode
*inode
= file_inode(filep
);
101 if (!nfs_server_capable(inode
, NFS_CAP_ALLOCATE
))
104 mutex_lock(&inode
->i_mutex
);
106 err
= nfs42_proc_fallocate(&msg
, filep
, offset
, len
);
107 if (err
== -EOPNOTSUPP
)
108 NFS_SERVER(inode
)->caps
&= ~NFS_CAP_ALLOCATE
;
110 mutex_unlock(&inode
->i_mutex
);
114 int nfs42_proc_deallocate(struct file
*filep
, loff_t offset
, loff_t len
)
116 struct rpc_message msg
= {
117 .rpc_proc
= &nfs4_procedures
[NFSPROC4_CLNT_DEALLOCATE
],
119 struct inode
*inode
= file_inode(filep
);
122 if (!nfs_server_capable(inode
, NFS_CAP_DEALLOCATE
))
126 mutex_lock(&inode
->i_mutex
);
128 err
= nfs42_proc_fallocate(&msg
, filep
, offset
, len
);
130 truncate_pagecache_range(inode
, offset
, (offset
+ len
) -1);
131 if (err
== -EOPNOTSUPP
)
132 NFS_SERVER(inode
)->caps
&= ~NFS_CAP_DEALLOCATE
;
134 mutex_unlock(&inode
->i_mutex
);
138 static loff_t
_nfs42_proc_llseek(struct file
*filep
, loff_t offset
, int whence
)
140 struct inode
*inode
= file_inode(filep
);
141 struct nfs42_seek_args args
= {
142 .sa_fh
= NFS_FH(inode
),
144 .sa_what
= (whence
== SEEK_HOLE
) ?
145 NFS4_CONTENT_HOLE
: NFS4_CONTENT_DATA
,
147 struct nfs42_seek_res res
;
148 struct rpc_message msg
= {
149 .rpc_proc
= &nfs4_procedures
[NFSPROC4_CLNT_SEEK
],
153 struct nfs_server
*server
= NFS_SERVER(inode
);
156 if (!nfs_server_capable(inode
, NFS_CAP_SEEK
))
159 status
= nfs42_set_rw_stateid(&args
.sa_stateid
, filep
, FMODE_READ
);
164 status
= nfs4_call_sync(server
->client
, server
, &msg
,
165 &args
.seq_args
, &res
.seq_res
, 0);
166 if (status
== -ENOTSUPP
)
167 server
->caps
&= ~NFS_CAP_SEEK
;
171 return vfs_setpos(filep
, res
.sr_offset
, inode
->i_sb
->s_maxbytes
);
174 loff_t
nfs42_proc_llseek(struct file
*filep
, loff_t offset
, int whence
)
176 struct nfs_server
*server
= NFS_SERVER(file_inode(filep
));
177 struct nfs4_exception exception
= { };
181 err
= _nfs42_proc_llseek(filep
, offset
, whence
);
184 if (err
== -ENOTSUPP
)
186 err
= nfs4_handle_exception(server
, err
, &exception
);
187 } while (exception
.retry
);
194 nfs42_layoutstat_prepare(struct rpc_task
*task
, void *calldata
)
196 struct nfs42_layoutstat_data
*data
= calldata
;
197 struct nfs_server
*server
= NFS_SERVER(data
->args
.inode
);
199 nfs41_setup_sequence(nfs4_get_session(server
), &data
->args
.seq_args
,
200 &data
->res
.seq_res
, task
);
204 nfs42_layoutstat_done(struct rpc_task
*task
, void *calldata
)
206 struct nfs42_layoutstat_data
*data
= calldata
;
207 struct inode
*inode
= data
->inode
;
208 struct pnfs_layout_hdr
*lo
;
210 if (!nfs4_sequence_done(task
, &data
->res
.seq_res
))
213 switch (task
->tk_status
) {
216 case -NFS4ERR_EXPIRED
:
217 case -NFS4ERR_STALE_STATEID
:
218 case -NFS4ERR_OLD_STATEID
:
219 case -NFS4ERR_BAD_STATEID
:
220 spin_lock(&inode
->i_lock
);
221 lo
= NFS_I(inode
)->layout
;
222 if (lo
&& nfs4_stateid_match(&data
->args
.stateid
,
227 * Mark the bad layout state as invalid, then retry
228 * with the current stateid.
230 set_bit(NFS_LAYOUT_INVALID_STID
, &lo
->plh_flags
);
231 pnfs_mark_matching_lsegs_invalid(lo
, &head
, NULL
);
232 spin_unlock(&inode
->i_lock
);
233 pnfs_free_lseg_list(&head
);
235 spin_unlock(&inode
->i_lock
);
239 NFS_SERVER(inode
)->caps
&= ~NFS_CAP_LAYOUTSTATS
;
244 dprintk("%s server returns %d\n", __func__
, task
->tk_status
);
248 nfs42_layoutstat_release(void *calldata
)
250 struct nfs42_layoutstat_data
*data
= calldata
;
251 struct nfs_server
*nfss
= NFS_SERVER(data
->args
.inode
);
253 if (nfss
->pnfs_curr_ld
->cleanup_layoutstats
)
254 nfss
->pnfs_curr_ld
->cleanup_layoutstats(data
);
256 pnfs_put_layout_hdr(NFS_I(data
->args
.inode
)->layout
);
257 smp_mb__before_atomic();
258 clear_bit(NFS_INO_LAYOUTSTATS
, &NFS_I(data
->args
.inode
)->flags
);
259 smp_mb__after_atomic();
260 nfs_iput_and_deactive(data
->inode
);
261 kfree(data
->args
.devinfo
);
265 static const struct rpc_call_ops nfs42_layoutstat_ops
= {
266 .rpc_call_prepare
= nfs42_layoutstat_prepare
,
267 .rpc_call_done
= nfs42_layoutstat_done
,
268 .rpc_release
= nfs42_layoutstat_release
,
271 int nfs42_proc_layoutstats_generic(struct nfs_server
*server
,
272 struct nfs42_layoutstat_data
*data
)
274 struct rpc_message msg
= {
275 .rpc_proc
= &nfs4_procedures
[NFSPROC4_CLNT_LAYOUTSTATS
],
276 .rpc_argp
= &data
->args
,
277 .rpc_resp
= &data
->res
,
279 struct rpc_task_setup task_setup
= {
280 .rpc_client
= server
->client
,
282 .callback_ops
= &nfs42_layoutstat_ops
,
283 .callback_data
= data
,
284 .flags
= RPC_TASK_ASYNC
,
286 struct rpc_task
*task
;
288 data
->inode
= nfs_igrab_and_active(data
->args
.inode
);
290 nfs42_layoutstat_release(data
);
293 nfs4_init_sequence(&data
->args
.seq_args
, &data
->res
.seq_res
, 0);
294 task
= rpc_run_task(&task_setup
);
296 return PTR_ERR(task
);
300 static int _nfs42_proc_clone(struct rpc_message
*msg
, struct file
*src_f
,
301 struct file
*dst_f
, loff_t src_offset
,
302 loff_t dst_offset
, loff_t count
)
304 struct inode
*src_inode
= file_inode(src_f
);
305 struct inode
*dst_inode
= file_inode(dst_f
);
306 struct nfs_server
*server
= NFS_SERVER(dst_inode
);
307 struct nfs42_clone_args args
= {
308 .src_fh
= NFS_FH(src_inode
),
309 .dst_fh
= NFS_FH(dst_inode
),
310 .src_offset
= src_offset
,
311 .dst_offset
= dst_offset
,
313 .dst_bitmask
= server
->cache_consistency_bitmask
,
315 struct nfs42_clone_res res
= {
320 msg
->rpc_argp
= &args
;
321 msg
->rpc_resp
= &res
;
323 status
= nfs42_set_rw_stateid(&args
.src_stateid
, src_f
, FMODE_READ
);
327 status
= nfs42_set_rw_stateid(&args
.dst_stateid
, dst_f
, FMODE_WRITE
);
331 res
.dst_fattr
= nfs_alloc_fattr();
335 status
= nfs4_call_sync(server
->client
, server
, msg
,
336 &args
.seq_args
, &res
.seq_res
, 0);
338 status
= nfs_post_op_update_inode(dst_inode
, res
.dst_fattr
);
340 kfree(res
.dst_fattr
);
344 int nfs42_proc_clone(struct file
*src_f
, struct file
*dst_f
,
345 loff_t src_offset
, loff_t dst_offset
, loff_t count
)
347 struct rpc_message msg
= {
348 .rpc_proc
= &nfs4_procedures
[NFSPROC4_CLNT_CLONE
],
350 struct inode
*inode
= file_inode(src_f
);
351 struct nfs_server
*server
= NFS_SERVER(file_inode(src_f
));
352 struct nfs4_exception exception
= { };
355 if (!nfs_server_capable(inode
, NFS_CAP_CLONE
))
359 err
= _nfs42_proc_clone(&msg
, src_f
, dst_f
, src_offset
,
361 if (err
== -ENOTSUPP
|| err
== -EOPNOTSUPP
) {
362 NFS_SERVER(inode
)->caps
&= ~NFS_CAP_CLONE
;
365 err
= nfs4_handle_exception(server
, err
, &exception
);
366 } while (exception
.retry
);