1 /* 2 * linux/fs/nfs/delegation.c 3 * 4 * Copyright (C) 2004 Trond Myklebust 5 * 6 * NFS file delegation management 7 * 8 */ 9 #include <linux/completion.h> 10 #include <linux/kthread.h> 11 #include <linux/module.h> 12 #include <linux/sched.h> 13 #include <linux/spinlock.h> 14 15 #include <linux/nfs4.h> 16 #include <linux/nfs_fs.h> 17 #include <linux/nfs_xdr.h> 18 19 #include "nfs4_fs.h" 20 #include "delegation.h" 21 #include "internal.h" 22 23 static void nfs_free_delegation(struct nfs_delegation *delegation) 24 { 25 if (delegation->cred) 26 put_rpccred(delegation->cred); 27 kfree(delegation); 28 } 29 30 static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state) 31 { 32 struct inode *inode = state->inode; 33 struct file_lock *fl; 34 int status; 35 36 for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { 37 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) 38 continue; 39 if ((struct nfs_open_context *)fl->fl_file->private_data != ctx) 40 continue; 41 status = nfs4_lock_delegation_recall(state, fl); 42 if (status >= 0) 43 continue; 44 switch (status) { 45 default: 46 printk(KERN_ERR "%s: unhandled error %d.\n", 47 __FUNCTION__, status); 48 case -NFS4ERR_EXPIRED: 49 /* kill_proc(fl->fl_pid, SIGLOST, 1); */ 50 case -NFS4ERR_STALE_CLIENTID: 51 nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs_client); 52 goto out_err; 53 } 54 } 55 return 0; 56 out_err: 57 return status; 58 } 59 60 static void nfs_delegation_claim_opens(struct inode *inode) 61 { 62 struct nfs_inode *nfsi = NFS_I(inode); 63 struct nfs_open_context *ctx; 64 struct nfs4_state *state; 65 int err; 66 67 again: 68 spin_lock(&inode->i_lock); 69 list_for_each_entry(ctx, &nfsi->open_files, list) { 70 state = ctx->state; 71 if (state == NULL) 72 continue; 73 if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) 74 continue; 75 get_nfs_open_context(ctx); 76 spin_unlock(&inode->i_lock); 77 err = nfs4_open_delegation_recall(ctx->dentry, state); 78 if (err >= 0) 79 err = nfs_delegation_claim_locks(ctx, state); 80 put_nfs_open_context(ctx); 81 if (err != 0) 82 return; 83 goto again; 84 } 85 spin_unlock(&inode->i_lock); 86 } 87 88 /* 89 * Set up a delegation on an inode 90 */ 91 void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) 92 { 93 struct nfs_delegation *delegation = NFS_I(inode)->delegation; 94 95 if (delegation == NULL) 96 return; 97 memcpy(delegation->stateid.data, res->delegation.data, 98 sizeof(delegation->stateid.data)); 99 delegation->type = res->delegation_type; 100 delegation->maxsize = res->maxsize; 101 put_rpccred(cred); 102 delegation->cred = get_rpccred(cred); 103 delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM; 104 NFS_I(inode)->delegation_state = delegation->type; 105 smp_wmb(); 106 } 107 108 /* 109 * Set up a delegation on an inode 110 */ 111 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) 112 { 113 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 114 struct nfs_inode *nfsi = NFS_I(inode); 115 struct nfs_delegation *delegation; 116 int status = 0; 117 118 /* Ensure we first revalidate the attributes and page cache! */ 119 if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR))) 120 __nfs_revalidate_inode(NFS_SERVER(inode), inode); 121 122 delegation = kmalloc(sizeof(*delegation), GFP_KERNEL); 123 if (delegation == NULL) 124 return -ENOMEM; 125 memcpy(delegation->stateid.data, res->delegation.data, 126 sizeof(delegation->stateid.data)); 127 delegation->type = res->delegation_type; 128 delegation->maxsize = res->maxsize; 129 delegation->change_attr = nfsi->change_attr; 130 delegation->cred = get_rpccred(cred); 131 delegation->inode = inode; 132 133 spin_lock(&clp->cl_lock); 134 if (nfsi->delegation == NULL) { 135 list_add(&delegation->super_list, &clp->cl_delegations); 136 nfsi->delegation = delegation; 137 nfsi->delegation_state = delegation->type; 138 delegation = NULL; 139 } else { 140 if (memcmp(&delegation->stateid, &nfsi->delegation->stateid, 141 sizeof(delegation->stateid)) != 0 || 142 delegation->type != nfsi->delegation->type) { 143 printk("%s: server %u.%u.%u.%u, handed out a duplicate delegation!\n", 144 __FUNCTION__, NIPQUAD(clp->cl_addr.sin_addr)); 145 status = -EIO; 146 } 147 } 148 spin_unlock(&clp->cl_lock); 149 kfree(delegation); 150 return status; 151 } 152 153 static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation) 154 { 155 int res = 0; 156 157 res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid); 158 nfs_free_delegation(delegation); 159 return res; 160 } 161 162 /* Sync all data to disk upon delegation return */ 163 static void nfs_msync_inode(struct inode *inode) 164 { 165 filemap_fdatawrite(inode->i_mapping); 166 nfs_wb_all(inode); 167 filemap_fdatawait(inode->i_mapping); 168 } 169 170 /* 171 * Basic procedure for returning a delegation to the server 172 */ 173 int __nfs_inode_return_delegation(struct inode *inode) 174 { 175 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 176 struct nfs_inode *nfsi = NFS_I(inode); 177 struct nfs_delegation *delegation; 178 int res = 0; 179 180 nfs_msync_inode(inode); 181 down_read(&clp->cl_sem); 182 /* Guard against new delegated open calls */ 183 down_write(&nfsi->rwsem); 184 spin_lock(&clp->cl_lock); 185 delegation = nfsi->delegation; 186 if (delegation != NULL) { 187 list_del_init(&delegation->super_list); 188 nfsi->delegation = NULL; 189 nfsi->delegation_state = 0; 190 } 191 spin_unlock(&clp->cl_lock); 192 nfs_delegation_claim_opens(inode); 193 up_write(&nfsi->rwsem); 194 up_read(&clp->cl_sem); 195 nfs_msync_inode(inode); 196 197 if (delegation != NULL) 198 res = nfs_do_return_delegation(inode, delegation); 199 return res; 200 } 201 202 /* 203 * Return all delegations associated to a super block 204 */ 205 void nfs_return_all_delegations(struct super_block *sb) 206 { 207 struct nfs_client *clp = NFS_SB(sb)->nfs_client; 208 struct nfs_delegation *delegation; 209 struct inode *inode; 210 211 if (clp == NULL) 212 return; 213 restart: 214 spin_lock(&clp->cl_lock); 215 list_for_each_entry(delegation, &clp->cl_delegations, super_list) { 216 if (delegation->inode->i_sb != sb) 217 continue; 218 inode = igrab(delegation->inode); 219 if (inode == NULL) 220 continue; 221 spin_unlock(&clp->cl_lock); 222 nfs_inode_return_delegation(inode); 223 iput(inode); 224 goto restart; 225 } 226 spin_unlock(&clp->cl_lock); 227 } 228 229 int nfs_do_expire_all_delegations(void *ptr) 230 { 231 struct nfs_client *clp = ptr; 232 struct nfs_delegation *delegation; 233 struct inode *inode; 234 235 allow_signal(SIGKILL); 236 restart: 237 spin_lock(&clp->cl_lock); 238 if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0) 239 goto out; 240 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) 241 goto out; 242 list_for_each_entry(delegation, &clp->cl_delegations, super_list) { 243 inode = igrab(delegation->inode); 244 if (inode == NULL) 245 continue; 246 spin_unlock(&clp->cl_lock); 247 nfs_inode_return_delegation(inode); 248 iput(inode); 249 goto restart; 250 } 251 out: 252 spin_unlock(&clp->cl_lock); 253 nfs_put_client(clp); 254 module_put_and_exit(0); 255 } 256 257 void nfs_expire_all_delegations(struct nfs_client *clp) 258 { 259 struct task_struct *task; 260 261 __module_get(THIS_MODULE); 262 atomic_inc(&clp->cl_count); 263 task = kthread_run(nfs_do_expire_all_delegations, clp, 264 "%u.%u.%u.%u-delegreturn", 265 NIPQUAD(clp->cl_addr.sin_addr)); 266 if (!IS_ERR(task)) 267 return; 268 nfs_put_client(clp); 269 module_put(THIS_MODULE); 270 } 271 272 /* 273 * Return all delegations following an NFS4ERR_CB_PATH_DOWN error. 274 */ 275 void nfs_handle_cb_pathdown(struct nfs_client *clp) 276 { 277 struct nfs_delegation *delegation; 278 struct inode *inode; 279 280 if (clp == NULL) 281 return; 282 restart: 283 spin_lock(&clp->cl_lock); 284 list_for_each_entry(delegation, &clp->cl_delegations, super_list) { 285 inode = igrab(delegation->inode); 286 if (inode == NULL) 287 continue; 288 spin_unlock(&clp->cl_lock); 289 nfs_inode_return_delegation(inode); 290 iput(inode); 291 goto restart; 292 } 293 spin_unlock(&clp->cl_lock); 294 } 295 296 struct recall_threadargs { 297 struct inode *inode; 298 struct nfs_client *clp; 299 const nfs4_stateid *stateid; 300 301 struct completion started; 302 int result; 303 }; 304 305 static int recall_thread(void *data) 306 { 307 struct recall_threadargs *args = (struct recall_threadargs *)data; 308 struct inode *inode = igrab(args->inode); 309 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 310 struct nfs_inode *nfsi = NFS_I(inode); 311 struct nfs_delegation *delegation; 312 313 daemonize("nfsv4-delegreturn"); 314 315 nfs_msync_inode(inode); 316 down_read(&clp->cl_sem); 317 down_write(&nfsi->rwsem); 318 spin_lock(&clp->cl_lock); 319 delegation = nfsi->delegation; 320 if (delegation != NULL && memcmp(delegation->stateid.data, 321 args->stateid->data, 322 sizeof(delegation->stateid.data)) == 0) { 323 list_del_init(&delegation->super_list); 324 nfsi->delegation = NULL; 325 nfsi->delegation_state = 0; 326 args->result = 0; 327 } else { 328 delegation = NULL; 329 args->result = -ENOENT; 330 } 331 spin_unlock(&clp->cl_lock); 332 complete(&args->started); 333 nfs_delegation_claim_opens(inode); 334 up_write(&nfsi->rwsem); 335 up_read(&clp->cl_sem); 336 nfs_msync_inode(inode); 337 338 if (delegation != NULL) 339 nfs_do_return_delegation(inode, delegation); 340 iput(inode); 341 module_put_and_exit(0); 342 } 343 344 /* 345 * Asynchronous delegation recall! 346 */ 347 int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid) 348 { 349 struct recall_threadargs data = { 350 .inode = inode, 351 .stateid = stateid, 352 }; 353 int status; 354 355 init_completion(&data.started); 356 __module_get(THIS_MODULE); 357 status = kernel_thread(recall_thread, &data, CLONE_KERNEL); 358 if (status < 0) 359 goto out_module_put; 360 wait_for_completion(&data.started); 361 return data.result; 362 out_module_put: 363 module_put(THIS_MODULE); 364 return status; 365 } 366 367 /* 368 * Retrieve the inode associated with a delegation 369 */ 370 struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle) 371 { 372 struct nfs_delegation *delegation; 373 struct inode *res = NULL; 374 spin_lock(&clp->cl_lock); 375 list_for_each_entry(delegation, &clp->cl_delegations, super_list) { 376 if (nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) { 377 res = igrab(delegation->inode); 378 break; 379 } 380 } 381 spin_unlock(&clp->cl_lock); 382 return res; 383 } 384 385 /* 386 * Mark all delegations as needing to be reclaimed 387 */ 388 void nfs_delegation_mark_reclaim(struct nfs_client *clp) 389 { 390 struct nfs_delegation *delegation; 391 spin_lock(&clp->cl_lock); 392 list_for_each_entry(delegation, &clp->cl_delegations, super_list) 393 delegation->flags |= NFS_DELEGATION_NEED_RECLAIM; 394 spin_unlock(&clp->cl_lock); 395 } 396 397 /* 398 * Reap all unclaimed delegations after reboot recovery is done 399 */ 400 void nfs_delegation_reap_unclaimed(struct nfs_client *clp) 401 { 402 struct nfs_delegation *delegation, *n; 403 LIST_HEAD(head); 404 spin_lock(&clp->cl_lock); 405 list_for_each_entry_safe(delegation, n, &clp->cl_delegations, super_list) { 406 if ((delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0) 407 continue; 408 list_move(&delegation->super_list, &head); 409 NFS_I(delegation->inode)->delegation = NULL; 410 NFS_I(delegation->inode)->delegation_state = 0; 411 } 412 spin_unlock(&clp->cl_lock); 413 while(!list_empty(&head)) { 414 delegation = list_entry(head.next, struct nfs_delegation, super_list); 415 list_del(&delegation->super_list); 416 nfs_free_delegation(delegation); 417 } 418 } 419 420 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode) 421 { 422 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 423 struct nfs_inode *nfsi = NFS_I(inode); 424 struct nfs_delegation *delegation; 425 int res = 0; 426 427 if (nfsi->delegation_state == 0) 428 return 0; 429 spin_lock(&clp->cl_lock); 430 delegation = nfsi->delegation; 431 if (delegation != NULL) { 432 memcpy(dst->data, delegation->stateid.data, sizeof(dst->data)); 433 res = 1; 434 } 435 spin_unlock(&clp->cl_lock); 436 return res; 437 } 438