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>
14 static int nfs42_set_rw_stateid(nfs4_stateid
*dst
, struct file
*file
,
17 struct nfs_open_context
*open
;
18 struct nfs_lock_context
*lock
;
21 open
= get_nfs_open_context(nfs_file_open_context(file
));
22 lock
= nfs_get_lock_context(open
);
24 put_nfs_open_context(open
);
28 ret
= nfs4_set_rw_stateid(dst
, open
, lock
, fmode
);
30 nfs_put_lock_context(lock
);
31 put_nfs_open_context(open
);
35 static int _nfs42_proc_fallocate(struct rpc_message
*msg
, struct file
*filep
,
36 loff_t offset
, loff_t len
)
38 struct inode
*inode
= file_inode(filep
);
39 struct nfs42_falloc_args args
= {
40 .falloc_fh
= NFS_FH(inode
),
41 .falloc_offset
= offset
,
44 struct nfs42_falloc_res res
;
45 struct nfs_server
*server
= NFS_SERVER(inode
);
48 msg
->rpc_argp
= &args
;
51 status
= nfs42_set_rw_stateid(&args
.falloc_stateid
, filep
, FMODE_WRITE
);
55 return nfs4_call_sync(server
->client
, server
, msg
,
56 &args
.seq_args
, &res
.seq_res
, 0);
59 static int nfs42_proc_fallocate(struct rpc_message
*msg
, struct file
*filep
,
60 loff_t offset
, loff_t len
)
62 struct nfs_server
*server
= NFS_SERVER(file_inode(filep
));
63 struct nfs4_exception exception
= { };
67 err
= _nfs42_proc_fallocate(msg
, filep
, offset
, len
);
70 err
= nfs4_handle_exception(server
, err
, &exception
);
71 } while (exception
.retry
);
76 int nfs42_proc_allocate(struct file
*filep
, loff_t offset
, loff_t len
)
78 struct rpc_message msg
= {
79 .rpc_proc
= &nfs4_procedures
[NFSPROC4_CLNT_ALLOCATE
],
81 struct inode
*inode
= file_inode(filep
);
84 if (!nfs_server_capable(inode
, NFS_CAP_ALLOCATE
))
87 err
= nfs42_proc_fallocate(&msg
, filep
, offset
, len
);
88 if (err
== -EOPNOTSUPP
)
89 NFS_SERVER(inode
)->caps
&= ~NFS_CAP_ALLOCATE
;
93 int nfs42_proc_deallocate(struct file
*filep
, loff_t offset
, loff_t len
)
95 struct rpc_message msg
= {
96 .rpc_proc
= &nfs4_procedures
[NFSPROC4_CLNT_DEALLOCATE
],
98 struct inode
*inode
= file_inode(filep
);
101 if (!nfs_server_capable(inode
, NFS_CAP_DEALLOCATE
))
104 err
= nfs42_proc_fallocate(&msg
, filep
, offset
, len
);
105 if (err
== -EOPNOTSUPP
)
106 NFS_SERVER(inode
)->caps
&= ~NFS_CAP_DEALLOCATE
;
110 loff_t
nfs42_proc_llseek(struct file
*filep
, loff_t offset
, int whence
)
112 struct inode
*inode
= file_inode(filep
);
113 struct nfs42_seek_args args
= {
114 .sa_fh
= NFS_FH(inode
),
116 .sa_what
= (whence
== SEEK_HOLE
) ?
117 NFS4_CONTENT_HOLE
: NFS4_CONTENT_DATA
,
119 struct nfs42_seek_res res
;
120 struct rpc_message msg
= {
121 .rpc_proc
= &nfs4_procedures
[NFSPROC4_CLNT_SEEK
],
125 struct nfs_server
*server
= NFS_SERVER(inode
);
128 if (!nfs_server_capable(inode
, NFS_CAP_SEEK
))
131 status
= nfs42_set_rw_stateid(&args
.sa_stateid
, filep
, FMODE_READ
);
136 status
= nfs4_call_sync(server
->client
, server
, &msg
,
137 &args
.seq_args
, &res
.seq_res
, 0);
138 if (status
== -ENOTSUPP
)
139 server
->caps
&= ~NFS_CAP_SEEK
;
143 return vfs_setpos(filep
, res
.sr_offset
, inode
->i_sb
->s_maxbytes
);