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 nfs_server
*server
= NFS_SERVER(inode
);
40 struct nfs42_falloc_args args
= {
41 .falloc_fh
= NFS_FH(inode
),
42 .falloc_offset
= offset
,
44 .falloc_bitmask
= server
->cache_consistency_bitmask
,
46 struct nfs42_falloc_res res
= {
47 .falloc_server
= server
,
51 msg
->rpc_argp
= &args
;
54 status
= nfs42_set_rw_stateid(&args
.falloc_stateid
, filep
, FMODE_WRITE
);
58 res
.falloc_fattr
= nfs_alloc_fattr();
59 if (!res
.falloc_fattr
)
62 status
= nfs4_call_sync(server
->client
, server
, msg
,
63 &args
.seq_args
, &res
.seq_res
, 0);
65 status
= nfs_post_op_update_inode(inode
, res
.falloc_fattr
);
67 kfree(res
.falloc_fattr
);
71 static int nfs42_proc_fallocate(struct rpc_message
*msg
, struct file
*filep
,
72 loff_t offset
, loff_t len
)
74 struct nfs_server
*server
= NFS_SERVER(file_inode(filep
));
75 struct nfs4_exception exception
= { };
79 err
= _nfs42_proc_fallocate(msg
, filep
, offset
, len
);
82 err
= nfs4_handle_exception(server
, err
, &exception
);
83 } while (exception
.retry
);
88 int nfs42_proc_allocate(struct file
*filep
, loff_t offset
, loff_t len
)
90 struct rpc_message msg
= {
91 .rpc_proc
= &nfs4_procedures
[NFSPROC4_CLNT_ALLOCATE
],
93 struct inode
*inode
= file_inode(filep
);
96 if (!nfs_server_capable(inode
, NFS_CAP_ALLOCATE
))
99 mutex_lock(&inode
->i_mutex
);
101 err
= nfs42_proc_fallocate(&msg
, filep
, offset
, len
);
102 if (err
== -EOPNOTSUPP
)
103 NFS_SERVER(inode
)->caps
&= ~NFS_CAP_ALLOCATE
;
105 mutex_unlock(&inode
->i_mutex
);
109 int nfs42_proc_deallocate(struct file
*filep
, loff_t offset
, loff_t len
)
111 struct rpc_message msg
= {
112 .rpc_proc
= &nfs4_procedures
[NFSPROC4_CLNT_DEALLOCATE
],
114 struct inode
*inode
= file_inode(filep
);
117 if (!nfs_server_capable(inode
, NFS_CAP_DEALLOCATE
))
121 mutex_lock(&inode
->i_mutex
);
123 err
= nfs42_proc_fallocate(&msg
, filep
, offset
, len
);
125 truncate_pagecache_range(inode
, offset
, (offset
+ len
) -1);
126 if (err
== -EOPNOTSUPP
)
127 NFS_SERVER(inode
)->caps
&= ~NFS_CAP_DEALLOCATE
;
129 mutex_unlock(&inode
->i_mutex
);
133 loff_t
nfs42_proc_llseek(struct file
*filep
, loff_t offset
, int whence
)
135 struct inode
*inode
= file_inode(filep
);
136 struct nfs42_seek_args args
= {
137 .sa_fh
= NFS_FH(inode
),
139 .sa_what
= (whence
== SEEK_HOLE
) ?
140 NFS4_CONTENT_HOLE
: NFS4_CONTENT_DATA
,
142 struct nfs42_seek_res res
;
143 struct rpc_message msg
= {
144 .rpc_proc
= &nfs4_procedures
[NFSPROC4_CLNT_SEEK
],
148 struct nfs_server
*server
= NFS_SERVER(inode
);
151 if (!nfs_server_capable(inode
, NFS_CAP_SEEK
))
154 status
= nfs42_set_rw_stateid(&args
.sa_stateid
, filep
, FMODE_READ
);
159 status
= nfs4_call_sync(server
->client
, server
, &msg
,
160 &args
.seq_args
, &res
.seq_res
, 0);
161 if (status
== -ENOTSUPP
)
162 server
->caps
&= ~NFS_CAP_SEEK
;
166 return vfs_setpos(filep
, res
.sr_offset
, inode
->i_sb
->s_maxbytes
);