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 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 static void 175 nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata) 176 { 177 struct nfs42_layoutstat_data *data = calldata; 178 struct nfs_server *server = NFS_SERVER(data->args.inode); 179 180 nfs41_setup_sequence(nfs4_get_session(server), &data->args.seq_args, 181 &data->res.seq_res, task); 182 } 183 184 static void 185 nfs42_layoutstat_done(struct rpc_task *task, void *calldata) 186 { 187 struct nfs42_layoutstat_data *data = calldata; 188 189 if (!nfs4_sequence_done(task, &data->res.seq_res)) 190 return; 191 192 switch (task->tk_status) { 193 case 0: 194 break; 195 case -ENOTSUPP: 196 case -EOPNOTSUPP: 197 NFS_SERVER(data->inode)->caps &= ~NFS_CAP_LAYOUTSTATS; 198 default: 199 dprintk("%s server returns %d\n", __func__, task->tk_status); 200 } 201 } 202 203 static void 204 nfs42_layoutstat_release(void *calldata) 205 { 206 struct nfs42_layoutstat_data *data = calldata; 207 struct nfs_server *nfss = NFS_SERVER(data->args.inode); 208 209 if (nfss->pnfs_curr_ld->cleanup_layoutstats) 210 nfss->pnfs_curr_ld->cleanup_layoutstats(data); 211 212 pnfs_put_layout_hdr(NFS_I(data->args.inode)->layout); 213 smp_mb__before_atomic(); 214 clear_bit(NFS_INO_LAYOUTSTATS, &NFS_I(data->args.inode)->flags); 215 smp_mb__after_atomic(); 216 nfs_iput_and_deactive(data->inode); 217 kfree(data->args.devinfo); 218 kfree(data); 219 } 220 221 static const struct rpc_call_ops nfs42_layoutstat_ops = { 222 .rpc_call_prepare = nfs42_layoutstat_prepare, 223 .rpc_call_done = nfs42_layoutstat_done, 224 .rpc_release = nfs42_layoutstat_release, 225 }; 226 227 int nfs42_proc_layoutstats_generic(struct nfs_server *server, 228 struct nfs42_layoutstat_data *data) 229 { 230 struct rpc_message msg = { 231 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTSTATS], 232 .rpc_argp = &data->args, 233 .rpc_resp = &data->res, 234 }; 235 struct rpc_task_setup task_setup = { 236 .rpc_client = server->client, 237 .rpc_message = &msg, 238 .callback_ops = &nfs42_layoutstat_ops, 239 .callback_data = data, 240 .flags = RPC_TASK_ASYNC, 241 }; 242 struct rpc_task *task; 243 244 data->inode = nfs_igrab_and_active(data->args.inode); 245 if (!data->inode) { 246 nfs42_layoutstat_release(data); 247 return -EAGAIN; 248 } 249 nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); 250 task = rpc_run_task(&task_setup); 251 if (IS_ERR(task)) 252 return PTR_ERR(task); 253 return 0; 254 } 255