Merge branch 'work.copy_file_range' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs copy_file_range updates from Al Viro: "Several series around copy_file_range/CLONE" * 'work.copy_file_range' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: btrfs: use new dedupe data function pointer vfs: hoist the btrfs deduplication ioctl to the vfs vfs: wire up compat ioctl for CLONE/CLONE_RANGE cifs: avoid unused variable and label nfsd: implement the NFSv4.2 CLONE operation nfsd: Pass filehandle to nfs4_preprocess_stateid_op() vfs: pull btrfs clone API to vfs layer locks: new locks_mandatory_area calling convention vfs: Add vfs_copy_file_range() support for pagecache copies btrfs: add .copy_file_range file operation x86: add sys_copy_file_range to syscall tables vfs: add copy_file_range syscall and vfs helper
This commit is contained in:
@@ -774,8 +774,9 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
|
||||
|
||||
/* check stateid */
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &read->rd_stateid,
|
||||
RD_STATE, &read->rd_filp, &read->rd_tmp_file);
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
|
||||
&read->rd_stateid, RD_STATE,
|
||||
&read->rd_filp, &read->rd_tmp_file);
|
||||
if (status) {
|
||||
dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
|
||||
goto out;
|
||||
@@ -921,7 +922,8 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
|
||||
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate,
|
||||
&setattr->sa_stateid, WR_STATE, NULL, NULL);
|
||||
&cstate->current_fh, &setattr->sa_stateid,
|
||||
WR_STATE, NULL, NULL);
|
||||
if (status) {
|
||||
dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
|
||||
return status;
|
||||
@@ -985,8 +987,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
if (write->wr_offset >= OFFSET_MAX)
|
||||
return nfserr_inval;
|
||||
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, stateid, WR_STATE,
|
||||
&filp, NULL);
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
|
||||
stateid, WR_STATE, &filp, NULL);
|
||||
if (status) {
|
||||
dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
|
||||
return status;
|
||||
@@ -1009,6 +1011,47 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
return status;
|
||||
}
|
||||
|
||||
static __be32
|
||||
nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
struct nfsd4_clone *clone)
|
||||
{
|
||||
struct file *src, *dst;
|
||||
__be32 status;
|
||||
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->save_fh,
|
||||
&clone->cl_src_stateid, RD_STATE,
|
||||
&src, NULL);
|
||||
if (status) {
|
||||
dprintk("NFSD: %s: couldn't process src stateid!\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
|
||||
&clone->cl_dst_stateid, WR_STATE,
|
||||
&dst, NULL);
|
||||
if (status) {
|
||||
dprintk("NFSD: %s: couldn't process dst stateid!\n", __func__);
|
||||
goto out_put_src;
|
||||
}
|
||||
|
||||
/* fix up for NFS-specific error code */
|
||||
if (!S_ISREG(file_inode(src)->i_mode) ||
|
||||
!S_ISREG(file_inode(dst)->i_mode)) {
|
||||
status = nfserr_wrong_type;
|
||||
goto out_put_dst;
|
||||
}
|
||||
|
||||
status = nfsd4_clone_file_range(src, clone->cl_src_pos,
|
||||
dst, clone->cl_dst_pos, clone->cl_count);
|
||||
|
||||
out_put_dst:
|
||||
fput(dst);
|
||||
out_put_src:
|
||||
fput(src);
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static __be32
|
||||
nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
struct nfsd4_fallocate *fallocate, int flags)
|
||||
@@ -1016,7 +1059,7 @@ nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
__be32 status = nfserr_notsupp;
|
||||
struct file *file;
|
||||
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate,
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
|
||||
&fallocate->falloc_stateid,
|
||||
WR_STATE, &file, NULL);
|
||||
if (status != nfs_ok) {
|
||||
@@ -1055,7 +1098,7 @@ nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
__be32 status;
|
||||
struct file *file;
|
||||
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate,
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
|
||||
&seek->seek_stateid,
|
||||
RD_STATE, &file, NULL);
|
||||
if (status) {
|
||||
@@ -2279,6 +2322,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
|
||||
.op_name = "OP_DEALLOCATE",
|
||||
.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
|
||||
},
|
||||
[OP_CLONE] = {
|
||||
.op_func = (nfsd4op_func)nfsd4_clone,
|
||||
.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
|
||||
.op_name = "OP_CLONE",
|
||||
.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
|
||||
},
|
||||
[OP_SEEK] = {
|
||||
.op_func = (nfsd4op_func)nfsd4_seek,
|
||||
.op_name = "OP_SEEK",
|
||||
|
@@ -4797,10 +4797,9 @@ nfs4_check_file(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfs4_stid *s,
|
||||
*/
|
||||
__be32
|
||||
nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
|
||||
struct nfsd4_compound_state *cstate, stateid_t *stateid,
|
||||
int flags, struct file **filpp, bool *tmp_file)
|
||||
struct nfsd4_compound_state *cstate, struct svc_fh *fhp,
|
||||
stateid_t *stateid, int flags, struct file **filpp, bool *tmp_file)
|
||||
{
|
||||
struct svc_fh *fhp = &cstate->current_fh;
|
||||
struct inode *ino = d_inode(fhp->fh_dentry);
|
||||
struct net *net = SVC_NET(rqstp);
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
|
@@ -1674,6 +1674,25 @@ nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
|
||||
DECODE_TAIL;
|
||||
}
|
||||
|
||||
static __be32
|
||||
nfsd4_decode_clone(struct nfsd4_compoundargs *argp, struct nfsd4_clone *clone)
|
||||
{
|
||||
DECODE_HEAD;
|
||||
|
||||
status = nfsd4_decode_stateid(argp, &clone->cl_src_stateid);
|
||||
if (status)
|
||||
return status;
|
||||
status = nfsd4_decode_stateid(argp, &clone->cl_dst_stateid);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
READ_BUF(8 + 8 + 8);
|
||||
p = xdr_decode_hyper(p, &clone->cl_src_pos);
|
||||
p = xdr_decode_hyper(p, &clone->cl_dst_pos);
|
||||
p = xdr_decode_hyper(p, &clone->cl_count);
|
||||
DECODE_TAIL;
|
||||
}
|
||||
|
||||
static __be32
|
||||
nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek)
|
||||
{
|
||||
@@ -1785,6 +1804,7 @@ static nfsd4_dec nfsd4_dec_ops[] = {
|
||||
[OP_READ_PLUS] = (nfsd4_dec)nfsd4_decode_notsupp,
|
||||
[OP_SEEK] = (nfsd4_dec)nfsd4_decode_seek,
|
||||
[OP_WRITE_SAME] = (nfsd4_dec)nfsd4_decode_notsupp,
|
||||
[OP_CLONE] = (nfsd4_dec)nfsd4_decode_clone,
|
||||
};
|
||||
|
||||
static inline bool
|
||||
@@ -4292,6 +4312,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
|
||||
[OP_READ_PLUS] = (nfsd4_enc)nfsd4_encode_noop,
|
||||
[OP_SEEK] = (nfsd4_enc)nfsd4_encode_seek,
|
||||
[OP_WRITE_SAME] = (nfsd4_enc)nfsd4_encode_noop,
|
||||
[OP_CLONE] = (nfsd4_enc)nfsd4_encode_noop,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@@ -578,8 +578,8 @@ struct nfsd4_compound_state;
|
||||
struct nfsd_net;
|
||||
|
||||
extern __be32 nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
|
||||
struct nfsd4_compound_state *cstate, stateid_t *stateid,
|
||||
int flags, struct file **filp, bool *tmp_file);
|
||||
struct nfsd4_compound_state *cstate, struct svc_fh *fhp,
|
||||
stateid_t *stateid, int flags, struct file **filp, bool *tmp_file);
|
||||
__be32 nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
|
||||
stateid_t *stateid, unsigned char typemask,
|
||||
struct nfs4_stid **s, struct nfsd_net *nn);
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#endif /* CONFIG_NFSD_V3 */
|
||||
|
||||
#ifdef CONFIG_NFSD_V4
|
||||
#include "../internal.h"
|
||||
#include "acl.h"
|
||||
#include "idmap.h"
|
||||
#endif /* CONFIG_NFSD_V4 */
|
||||
@@ -498,6 +499,13 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
}
|
||||
#endif
|
||||
|
||||
__be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
|
||||
u64 dst_pos, u64 count)
|
||||
{
|
||||
return nfserrno(vfs_clone_file_range(src, src_pos, dst, dst_pos,
|
||||
count));
|
||||
}
|
||||
|
||||
__be32 nfsd4_vfs_fallocate(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
struct file *file, loff_t offset, loff_t len,
|
||||
int flags)
|
||||
|
@@ -56,6 +56,8 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
|
||||
struct xdr_netobj *);
|
||||
__be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,
|
||||
struct file *, loff_t, loff_t, int);
|
||||
__be32 nfsd4_clone_file_range(struct file *, u64, struct file *,
|
||||
u64, u64);
|
||||
#endif /* CONFIG_NFSD_V4 */
|
||||
__be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
|
||||
char *name, int len, struct iattr *attrs,
|
||||
|
@@ -491,6 +491,15 @@ struct nfsd4_fallocate {
|
||||
u64 falloc_length;
|
||||
};
|
||||
|
||||
struct nfsd4_clone {
|
||||
/* request */
|
||||
stateid_t cl_src_stateid;
|
||||
stateid_t cl_dst_stateid;
|
||||
u64 cl_src_pos;
|
||||
u64 cl_dst_pos;
|
||||
u64 cl_count;
|
||||
};
|
||||
|
||||
struct nfsd4_seek {
|
||||
/* request */
|
||||
stateid_t seek_stateid;
|
||||
@@ -555,6 +564,7 @@ struct nfsd4_op {
|
||||
/* NFSv4.2 */
|
||||
struct nfsd4_fallocate allocate;
|
||||
struct nfsd4_fallocate deallocate;
|
||||
struct nfsd4_clone clone;
|
||||
struct nfsd4_seek seek;
|
||||
} u;
|
||||
struct nfs4_replay * replay;
|
||||
|
Reference in New Issue
Block a user