1 /* 2 * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com> 3 */ 4 #include <linux/fs.h> 5 #include <linux/sunrpc/sched.h> 6 #include <linux/nfs.h> 7 #include <linux/nfs3.h> 8 #include <linux/nfs4.h> 9 #include <linux/nfs_xdr.h> 10 #include <linux/nfs_fs.h> 11 #include "nfs4_fs.h" 12 #include "nfs42.h" 13 #include "iostat.h" 14 #include "pnfs.h" 15 #include "internal.h" 16 17 #define NFSDBG_FACILITY NFSDBG_PNFS 18 19 static int nfs42_set_rw_stateid(nfs4_stateid *dst, struct file *file, 20 fmode_t fmode) 21 { 22 struct nfs_open_context *open; 23 struct nfs_lock_context *lock; 24 int ret; 25 26 open = get_nfs_open_context(nfs_file_open_context(file)); 27 lock = nfs_get_lock_context(open); 28 if (IS_ERR(lock)) { 29 put_nfs_open_context(open); 30 return PTR_ERR(lock); 31 } 32 33 ret = nfs4_set_rw_stateid(dst, open, lock, fmode); 34 35 nfs_put_lock_context(lock); 36 put_nfs_open_context(open); 37 return ret; 38 } 39 40 static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, 41 loff_t offset, loff_t len) 42 { 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, 48 .falloc_length = len, 49 .falloc_bitmask = server->cache_consistency_bitmask, 50 }; 51 struct nfs42_falloc_res res = { 52 .falloc_server = server, 53 }; 54 int status; 55 56 msg->rpc_argp = &args; 57 msg->rpc_resp = &res; 58 59 status = nfs42_set_rw_stateid(&args.falloc_stateid, filep, FMODE_WRITE); 60 if (status) 61 return status; 62 63 res.falloc_fattr = nfs_alloc_fattr(); 64 if (!res.falloc_fattr) 65 return -ENOMEM; 66 67 status = nfs4_call_sync(server->client, server, msg, 68 &args.seq_args, &res.seq_res, 0); 69 if (status == 0) 70 status = nfs_post_op_update_inode(inode, res.falloc_fattr); 71 72 kfree(res.falloc_fattr); 73 return status; 74 } 75 76 static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, 77 loff_t offset, loff_t len) 78 { 79 struct nfs_server *server = NFS_SERVER(file_inode(filep)); 80 struct nfs4_exception exception = { }; 81 int err; 82 83 do { 84 err = _nfs42_proc_fallocate(msg, filep, offset, len); 85 if (err == -ENOTSUPP) 86 return -EOPNOTSUPP; 87 err = nfs4_handle_exception(server, err, &exception); 88 } while (exception.retry); 89 90 return err; 91 } 92 93 int nfs42_proc_allocate(struct file *filep, loff_t offset, loff_t len) 94 { 95 struct rpc_message msg = { 96 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ALLOCATE], 97 }; 98 struct inode *inode = file_inode(filep); 99 int err; 100 101 if (!nfs_server_capable(inode, NFS_CAP_ALLOCATE)) 102 return -EOPNOTSUPP; 103 104 mutex_lock(&inode->i_mutex); 105 106 err = nfs42_proc_fallocate(&msg, filep, offset, len); 107 if (err == -EOPNOTSUPP) 108 NFS_SERVER(inode)->caps &= ~NFS_CAP_ALLOCATE; 109 110 mutex_unlock(&inode->i_mutex); 111 return err; 112 } 113 114 int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len) 115 { 116 struct rpc_message msg = { 117 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DEALLOCATE], 118 }; 119 struct inode *inode = file_inode(filep); 120 int err; 121 122 if (!nfs_server_capable(inode, NFS_CAP_DEALLOCATE)) 123 return -EOPNOTSUPP; 124 125 nfs_wb_all(inode); 126 mutex_lock(&inode->i_mutex); 127 128 err = nfs42_proc_fallocate(&msg, filep, offset, len); 129 if (err == 0) 130 truncate_pagecache_range(inode, offset, (offset + len) -1); 131 if (err == -EOPNOTSUPP) 132 NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE; 133 134 mutex_unlock(&inode->i_mutex); 135 return err; 136 } 137 138 static loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) 139 { 140 struct inode *inode = file_inode(filep); 141 struct nfs42_seek_args args = { 142 .sa_fh = NFS_FH(inode), 143 .sa_offset = offset, 144 .sa_what = (whence == SEEK_HOLE) ? 145 NFS4_CONTENT_HOLE : NFS4_CONTENT_DATA, 146 }; 147 struct nfs42_seek_res res; 148 struct rpc_message msg = { 149 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEEK], 150 .rpc_argp = &args, 151 .rpc_resp = &res, 152 }; 153 struct nfs_server *server = NFS_SERVER(inode); 154 int status; 155 156 if (!nfs_server_capable(inode, NFS_CAP_SEEK)) 157 return -ENOTSUPP; 158 159 status = nfs42_set_rw_stateid(&args.sa_stateid, filep, FMODE_READ); 160 if (status) 161 return status; 162 163 nfs_wb_all(inode); 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; 168 if (status) 169 return status; 170 171 return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes); 172 } 173 174 loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) 175 { 176 struct nfs_server *server = NFS_SERVER(file_inode(filep)); 177 struct nfs4_exception exception = { }; 178 loff_t err; 179 180 do { 181 err = _nfs42_proc_llseek(filep, offset, whence); 182 if (err >= 0) 183 break; 184 if (err == -ENOTSUPP) 185 return -EOPNOTSUPP; 186 err = nfs4_handle_exception(server, err, &exception); 187 } while (exception.retry); 188 189 return err; 190 } 191 192 193 static void 194 nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata) 195 { 196 struct nfs42_layoutstat_data *data = calldata; 197 struct nfs_server *server = NFS_SERVER(data->args.inode); 198 199 nfs41_setup_sequence(nfs4_get_session(server), &data->args.seq_args, 200 &data->res.seq_res, task); 201 } 202 203 static void 204 nfs42_layoutstat_done(struct rpc_task *task, void *calldata) 205 { 206 struct nfs42_layoutstat_data *data = calldata; 207 208 if (!nfs4_sequence_done(task, &data->res.seq_res)) 209 return; 210 211 switch (task->tk_status) { 212 case 0: 213 break; 214 case -ENOTSUPP: 215 case -EOPNOTSUPP: 216 NFS_SERVER(data->inode)->caps &= ~NFS_CAP_LAYOUTSTATS; 217 default: 218 dprintk("%s server returns %d\n", __func__, task->tk_status); 219 } 220 } 221 222 static void 223 nfs42_layoutstat_release(void *calldata) 224 { 225 struct nfs42_layoutstat_data *data = calldata; 226 struct nfs_server *nfss = NFS_SERVER(data->args.inode); 227 228 if (nfss->pnfs_curr_ld->cleanup_layoutstats) 229 nfss->pnfs_curr_ld->cleanup_layoutstats(data); 230 231 pnfs_put_layout_hdr(NFS_I(data->args.inode)->layout); 232 smp_mb__before_atomic(); 233 clear_bit(NFS_INO_LAYOUTSTATS, &NFS_I(data->args.inode)->flags); 234 smp_mb__after_atomic(); 235 nfs_iput_and_deactive(data->inode); 236 kfree(data->args.devinfo); 237 kfree(data); 238 } 239 240 static const struct rpc_call_ops nfs42_layoutstat_ops = { 241 .rpc_call_prepare = nfs42_layoutstat_prepare, 242 .rpc_call_done = nfs42_layoutstat_done, 243 .rpc_release = nfs42_layoutstat_release, 244 }; 245 246 int nfs42_proc_layoutstats_generic(struct nfs_server *server, 247 struct nfs42_layoutstat_data *data) 248 { 249 struct rpc_message msg = { 250 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTSTATS], 251 .rpc_argp = &data->args, 252 .rpc_resp = &data->res, 253 }; 254 struct rpc_task_setup task_setup = { 255 .rpc_client = server->client, 256 .rpc_message = &msg, 257 .callback_ops = &nfs42_layoutstat_ops, 258 .callback_data = data, 259 .flags = RPC_TASK_ASYNC, 260 }; 261 struct rpc_task *task; 262 263 data->inode = nfs_igrab_and_active(data->args.inode); 264 if (!data->inode) { 265 nfs42_layoutstat_release(data); 266 return -EAGAIN; 267 } 268 nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); 269 task = rpc_run_task(&task_setup); 270 if (IS_ERR(task)) 271 return PTR_ERR(task); 272 return 0; 273 } 274