diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
| -rw-r--r-- | fs/nfsd/nfs4state.c | 97 |
1 files changed, 49 insertions, 48 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3550a9c87616..f6b2a09f793f 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | #include "current_stateid.h" | 48 | #include "current_stateid.h" |
| 49 | 49 | ||
| 50 | #include "netns.h" | 50 | #include "netns.h" |
| 51 | #include "pnfs.h" | ||
| 51 | 52 | ||
| 52 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 53 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
| 53 | 54 | ||
| @@ -150,16 +151,6 @@ renew_client_locked(struct nfs4_client *clp) | |||
| 150 | clp->cl_time = get_seconds(); | 151 | clp->cl_time = get_seconds(); |
| 151 | } | 152 | } |
| 152 | 153 | ||
| 153 | static inline void | ||
| 154 | renew_client(struct nfs4_client *clp) | ||
| 155 | { | ||
| 156 | struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); | ||
| 157 | |||
| 158 | spin_lock(&nn->client_lock); | ||
| 159 | renew_client_locked(clp); | ||
| 160 | spin_unlock(&nn->client_lock); | ||
| 161 | } | ||
| 162 | |||
| 163 | static void put_client_renew_locked(struct nfs4_client *clp) | 154 | static void put_client_renew_locked(struct nfs4_client *clp) |
| 164 | { | 155 | { |
| 165 | struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); | 156 | struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); |
| @@ -282,7 +273,7 @@ static void nfsd4_free_file_rcu(struct rcu_head *rcu) | |||
| 282 | kmem_cache_free(file_slab, fp); | 273 | kmem_cache_free(file_slab, fp); |
| 283 | } | 274 | } |
| 284 | 275 | ||
| 285 | static inline void | 276 | void |
| 286 | put_nfs4_file(struct nfs4_file *fi) | 277 | put_nfs4_file(struct nfs4_file *fi) |
| 287 | { | 278 | { |
| 288 | might_lock(&state_lock); | 279 | might_lock(&state_lock); |
| @@ -295,12 +286,6 @@ put_nfs4_file(struct nfs4_file *fi) | |||
| 295 | } | 286 | } |
| 296 | } | 287 | } |
| 297 | 288 | ||
| 298 | static inline void | ||
| 299 | get_nfs4_file(struct nfs4_file *fi) | ||
| 300 | { | ||
| 301 | atomic_inc(&fi->fi_ref); | ||
| 302 | } | ||
| 303 | |||
| 304 | static struct file * | 289 | static struct file * |
| 305 | __nfs4_get_fd(struct nfs4_file *f, int oflag) | 290 | __nfs4_get_fd(struct nfs4_file *f, int oflag) |
| 306 | { | 291 | { |
| @@ -358,7 +343,7 @@ find_readable_file(struct nfs4_file *f) | |||
| 358 | return ret; | 343 | return ret; |
| 359 | } | 344 | } |
| 360 | 345 | ||
| 361 | static struct file * | 346 | struct file * |
| 362 | find_any_file(struct nfs4_file *f) | 347 | find_any_file(struct nfs4_file *f) |
| 363 | { | 348 | { |
| 364 | struct file *ret; | 349 | struct file *ret; |
| @@ -408,14 +393,6 @@ static unsigned int file_hashval(struct knfsd_fh *fh) | |||
| 408 | return nfsd_fh_hashval(fh) & (FILE_HASH_SIZE - 1); | 393 | return nfsd_fh_hashval(fh) & (FILE_HASH_SIZE - 1); |
| 409 | } | 394 | } |
| 410 | 395 | ||
| 411 | static bool nfsd_fh_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2) | ||
| 412 | { | ||
| 413 | return fh1->fh_size == fh2->fh_size && | ||
| 414 | !memcmp(fh1->fh_base.fh_pad, | ||
| 415 | fh2->fh_base.fh_pad, | ||
| 416 | fh1->fh_size); | ||
| 417 | } | ||
| 418 | |||
| 419 | static struct hlist_head file_hashtbl[FILE_HASH_SIZE]; | 396 | static struct hlist_head file_hashtbl[FILE_HASH_SIZE]; |
| 420 | 397 | ||
| 421 | static void | 398 | static void |
| @@ -494,7 +471,7 @@ static void nfs4_file_put_access(struct nfs4_file *fp, u32 access) | |||
| 494 | __nfs4_file_put_access(fp, O_RDONLY); | 471 | __nfs4_file_put_access(fp, O_RDONLY); |
| 495 | } | 472 | } |
| 496 | 473 | ||
| 497 | static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, | 474 | struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, |
| 498 | struct kmem_cache *slab) | 475 | struct kmem_cache *slab) |
| 499 | { | 476 | { |
| 500 | struct nfs4_stid *stid; | 477 | struct nfs4_stid *stid; |
| @@ -688,17 +665,17 @@ static void nfs4_put_deleg_lease(struct nfs4_file *fp) | |||
| 688 | struct file *filp = NULL; | 665 | struct file *filp = NULL; |
| 689 | 666 | ||
| 690 | spin_lock(&fp->fi_lock); | 667 | spin_lock(&fp->fi_lock); |
| 691 | if (fp->fi_deleg_file && atomic_dec_and_test(&fp->fi_delegees)) | 668 | if (fp->fi_deleg_file && --fp->fi_delegees == 0) |
| 692 | swap(filp, fp->fi_deleg_file); | 669 | swap(filp, fp->fi_deleg_file); |
| 693 | spin_unlock(&fp->fi_lock); | 670 | spin_unlock(&fp->fi_lock); |
| 694 | 671 | ||
| 695 | if (filp) { | 672 | if (filp) { |
| 696 | vfs_setlease(filp, F_UNLCK, NULL, NULL); | 673 | vfs_setlease(filp, F_UNLCK, NULL, (void **)&fp); |
| 697 | fput(filp); | 674 | fput(filp); |
| 698 | } | 675 | } |
| 699 | } | 676 | } |
| 700 | 677 | ||
| 701 | static void unhash_stid(struct nfs4_stid *s) | 678 | void nfs4_unhash_stid(struct nfs4_stid *s) |
| 702 | { | 679 | { |
| 703 | s->sc_type = 0; | 680 | s->sc_type = 0; |
| 704 | } | 681 | } |
| @@ -1006,7 +983,7 @@ static void unhash_lock_stateid(struct nfs4_ol_stateid *stp) | |||
| 1006 | 983 | ||
| 1007 | list_del_init(&stp->st_locks); | 984 | list_del_init(&stp->st_locks); |
| 1008 | unhash_ol_stateid(stp); | 985 | unhash_ol_stateid(stp); |
| 1009 | unhash_stid(&stp->st_stid); | 986 | nfs4_unhash_stid(&stp->st_stid); |
| 1010 | } | 987 | } |
| 1011 | 988 | ||
| 1012 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) | 989 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) |
| @@ -1518,7 +1495,12 @@ unhash_session(struct nfsd4_session *ses) | |||
| 1518 | static int | 1495 | static int |
| 1519 | STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn) | 1496 | STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn) |
| 1520 | { | 1497 | { |
| 1521 | if (clid->cl_boot == nn->boot_time) | 1498 | /* |
| 1499 | * We're assuming the clid was not given out from a boot | ||
| 1500 | * precisely 2^32 (about 136 years) before this one. That seems | ||
| 1501 | * a safe assumption: | ||
| 1502 | */ | ||
| 1503 | if (clid->cl_boot == (u32)nn->boot_time) | ||
| 1522 | return 0; | 1504 | return 0; |
| 1523 | dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n", | 1505 | dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n", |
| 1524 | clid->cl_boot, clid->cl_id, nn->boot_time); | 1506 | clid->cl_boot, clid->cl_id, nn->boot_time); |
| @@ -1558,6 +1540,9 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name) | |||
| 1558 | INIT_LIST_HEAD(&clp->cl_lru); | 1540 | INIT_LIST_HEAD(&clp->cl_lru); |
| 1559 | INIT_LIST_HEAD(&clp->cl_callbacks); | 1541 | INIT_LIST_HEAD(&clp->cl_callbacks); |
| 1560 | INIT_LIST_HEAD(&clp->cl_revoked); | 1542 | INIT_LIST_HEAD(&clp->cl_revoked); |
| 1543 | #ifdef CONFIG_NFSD_PNFS | ||
| 1544 | INIT_LIST_HEAD(&clp->cl_lo_states); | ||
| 1545 | #endif | ||
| 1561 | spin_lock_init(&clp->cl_lock); | 1546 | spin_lock_init(&clp->cl_lock); |
| 1562 | rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); | 1547 | rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); |
| 1563 | return clp; | 1548 | return clp; |
| @@ -1662,6 +1647,7 @@ __destroy_client(struct nfs4_client *clp) | |||
| 1662 | nfs4_get_stateowner(&oo->oo_owner); | 1647 | nfs4_get_stateowner(&oo->oo_owner); |
| 1663 | release_openowner(oo); | 1648 | release_openowner(oo); |
| 1664 | } | 1649 | } |
| 1650 | nfsd4_return_all_client_layouts(clp); | ||
| 1665 | nfsd4_shutdown_callback(clp); | 1651 | nfsd4_shutdown_callback(clp); |
| 1666 | if (clp->cl_cb_conn.cb_xprt) | 1652 | if (clp->cl_cb_conn.cb_xprt) |
| 1667 | svc_xprt_put(clp->cl_cb_conn.cb_xprt); | 1653 | svc_xprt_put(clp->cl_cb_conn.cb_xprt); |
| @@ -2145,8 +2131,11 @@ nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, | |||
| 2145 | static void | 2131 | static void |
| 2146 | nfsd4_set_ex_flags(struct nfs4_client *new, struct nfsd4_exchange_id *clid) | 2132 | nfsd4_set_ex_flags(struct nfs4_client *new, struct nfsd4_exchange_id *clid) |
| 2147 | { | 2133 | { |
| 2148 | /* pNFS is not supported */ | 2134 | #ifdef CONFIG_NFSD_PNFS |
| 2135 | new->cl_exchange_flags |= EXCHGID4_FLAG_USE_PNFS_MDS; | ||
| 2136 | #else | ||
| 2149 | new->cl_exchange_flags |= EXCHGID4_FLAG_USE_NON_PNFS; | 2137 | new->cl_exchange_flags |= EXCHGID4_FLAG_USE_NON_PNFS; |
| 2138 | #endif | ||
| 2150 | 2139 | ||
| 2151 | /* Referrals are supported, Migration is not. */ | 2140 | /* Referrals are supported, Migration is not. */ |
| 2152 | new->cl_exchange_flags |= EXCHGID4_FLAG_SUPP_MOVED_REFER; | 2141 | new->cl_exchange_flags |= EXCHGID4_FLAG_SUPP_MOVED_REFER; |
| @@ -3074,6 +3063,10 @@ static void nfsd4_init_file(struct knfsd_fh *fh, unsigned int hashval, | |||
| 3074 | fp->fi_share_deny = 0; | 3063 | fp->fi_share_deny = 0; |
| 3075 | memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); | 3064 | memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); |
| 3076 | memset(fp->fi_access, 0, sizeof(fp->fi_access)); | 3065 | memset(fp->fi_access, 0, sizeof(fp->fi_access)); |
| 3066 | #ifdef CONFIG_NFSD_PNFS | ||
| 3067 | INIT_LIST_HEAD(&fp->fi_lo_states); | ||
| 3068 | atomic_set(&fp->fi_lo_recalls, 0); | ||
| 3069 | #endif | ||
| 3077 | hlist_add_head_rcu(&fp->fi_hash, &file_hashtbl[hashval]); | 3070 | hlist_add_head_rcu(&fp->fi_hash, &file_hashtbl[hashval]); |
| 3078 | } | 3071 | } |
| 3079 | 3072 | ||
| @@ -3300,7 +3293,7 @@ find_file_locked(struct knfsd_fh *fh, unsigned int hashval) | |||
| 3300 | struct nfs4_file *fp; | 3293 | struct nfs4_file *fp; |
| 3301 | 3294 | ||
| 3302 | hlist_for_each_entry_rcu(fp, &file_hashtbl[hashval], fi_hash) { | 3295 | hlist_for_each_entry_rcu(fp, &file_hashtbl[hashval], fi_hash) { |
| 3303 | if (nfsd_fh_match(&fp->fi_fhandle, fh)) { | 3296 | if (fh_match(&fp->fi_fhandle, fh)) { |
| 3304 | if (atomic_inc_not_zero(&fp->fi_ref)) | 3297 | if (atomic_inc_not_zero(&fp->fi_ref)) |
| 3305 | return fp; | 3298 | return fp; |
| 3306 | } | 3299 | } |
| @@ -3308,7 +3301,7 @@ find_file_locked(struct knfsd_fh *fh, unsigned int hashval) | |||
| 3308 | return NULL; | 3301 | return NULL; |
| 3309 | } | 3302 | } |
| 3310 | 3303 | ||
| 3311 | static struct nfs4_file * | 3304 | struct nfs4_file * |
| 3312 | find_file(struct knfsd_fh *fh) | 3305 | find_file(struct knfsd_fh *fh) |
| 3313 | { | 3306 | { |
| 3314 | struct nfs4_file *fp; | 3307 | struct nfs4_file *fp; |
| @@ -3477,7 +3470,8 @@ nfsd_break_deleg_cb(struct file_lock *fl) | |||
| 3477 | } | 3470 | } |
| 3478 | 3471 | ||
| 3479 | static int | 3472 | static int |
| 3480 | nfsd_change_deleg_cb(struct file_lock **onlist, int arg, struct list_head *dispose) | 3473 | nfsd_change_deleg_cb(struct file_lock *onlist, int arg, |
| 3474 | struct list_head *dispose) | ||
| 3481 | { | 3475 | { |
| 3482 | if (arg & F_UNLCK) | 3476 | if (arg & F_UNLCK) |
| 3483 | return lease_modify(onlist, arg, dispose); | 3477 | return lease_modify(onlist, arg, dispose); |
| @@ -3855,12 +3849,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp) | |||
| 3855 | /* Race breaker */ | 3849 | /* Race breaker */ |
| 3856 | if (fp->fi_deleg_file) { | 3850 | if (fp->fi_deleg_file) { |
| 3857 | status = 0; | 3851 | status = 0; |
| 3858 | atomic_inc(&fp->fi_delegees); | 3852 | ++fp->fi_delegees; |
| 3859 | hash_delegation_locked(dp, fp); | 3853 | hash_delegation_locked(dp, fp); |
| 3860 | goto out_unlock; | 3854 | goto out_unlock; |
| 3861 | } | 3855 | } |
| 3862 | fp->fi_deleg_file = filp; | 3856 | fp->fi_deleg_file = filp; |
| 3863 | atomic_set(&fp->fi_delegees, 1); | 3857 | fp->fi_delegees = 1; |
| 3864 | hash_delegation_locked(dp, fp); | 3858 | hash_delegation_locked(dp, fp); |
| 3865 | spin_unlock(&fp->fi_lock); | 3859 | spin_unlock(&fp->fi_lock); |
| 3866 | spin_unlock(&state_lock); | 3860 | spin_unlock(&state_lock); |
| @@ -3897,11 +3891,11 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh, | |||
| 3897 | status = nfs4_setlease(dp); | 3891 | status = nfs4_setlease(dp); |
| 3898 | goto out; | 3892 | goto out; |
| 3899 | } | 3893 | } |
| 3900 | atomic_inc(&fp->fi_delegees); | ||
| 3901 | if (fp->fi_had_conflict) { | 3894 | if (fp->fi_had_conflict) { |
| 3902 | status = -EAGAIN; | 3895 | status = -EAGAIN; |
| 3903 | goto out_unlock; | 3896 | goto out_unlock; |
| 3904 | } | 3897 | } |
| 3898 | ++fp->fi_delegees; | ||
| 3905 | hash_delegation_locked(dp, fp); | 3899 | hash_delegation_locked(dp, fp); |
| 3906 | status = 0; | 3900 | status = 0; |
| 3907 | out_unlock: | 3901 | out_unlock: |
| @@ -4294,7 +4288,7 @@ laundromat_main(struct work_struct *laundry) | |||
| 4294 | 4288 | ||
| 4295 | static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *stp) | 4289 | static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *stp) |
| 4296 | { | 4290 | { |
| 4297 | if (!nfsd_fh_match(&fhp->fh_handle, &stp->st_stid.sc_file->fi_fhandle)) | 4291 | if (!fh_match(&fhp->fh_handle, &stp->st_stid.sc_file->fi_fhandle)) |
| 4298 | return nfserr_bad_stateid; | 4292 | return nfserr_bad_stateid; |
| 4299 | return nfs_ok; | 4293 | return nfs_ok; |
| 4300 | } | 4294 | } |
| @@ -4445,7 +4439,7 @@ out_unlock: | |||
| 4445 | return status; | 4439 | return status; |
| 4446 | } | 4440 | } |
| 4447 | 4441 | ||
| 4448 | static __be32 | 4442 | __be32 |
| 4449 | nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate, | 4443 | nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate, |
| 4450 | stateid_t *stateid, unsigned char typemask, | 4444 | stateid_t *stateid, unsigned char typemask, |
| 4451 | struct nfs4_stid **s, struct nfsd_net *nn) | 4445 | struct nfs4_stid **s, struct nfsd_net *nn) |
| @@ -4859,6 +4853,9 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4859 | update_stateid(&stp->st_stid.sc_stateid); | 4853 | update_stateid(&stp->st_stid.sc_stateid); |
| 4860 | memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); | 4854 | memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); |
| 4861 | 4855 | ||
| 4856 | nfsd4_return_all_file_layouts(stp->st_stateowner->so_client, | ||
| 4857 | stp->st_stid.sc_file); | ||
| 4858 | |||
| 4862 | nfsd4_close_open_stateid(stp); | 4859 | nfsd4_close_open_stateid(stp); |
| 4863 | 4860 | ||
| 4864 | /* put reference from nfs4_preprocess_seqid_op */ | 4861 | /* put reference from nfs4_preprocess_seqid_op */ |
| @@ -5556,10 +5553,11 @@ out_nfserr: | |||
| 5556 | static bool | 5553 | static bool |
| 5557 | check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) | 5554 | check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) |
| 5558 | { | 5555 | { |
| 5559 | struct file_lock **flpp; | 5556 | struct file_lock *fl; |
| 5560 | int status = false; | 5557 | int status = false; |
| 5561 | struct file *filp = find_any_file(fp); | 5558 | struct file *filp = find_any_file(fp); |
| 5562 | struct inode *inode; | 5559 | struct inode *inode; |
| 5560 | struct file_lock_context *flctx; | ||
| 5563 | 5561 | ||
| 5564 | if (!filp) { | 5562 | if (!filp) { |
| 5565 | /* Any valid lock stateid should have some sort of access */ | 5563 | /* Any valid lock stateid should have some sort of access */ |
| @@ -5568,15 +5566,18 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) | |||
| 5568 | } | 5566 | } |
| 5569 | 5567 | ||
| 5570 | inode = file_inode(filp); | 5568 | inode = file_inode(filp); |
| 5569 | flctx = inode->i_flctx; | ||
| 5571 | 5570 | ||
| 5572 | spin_lock(&inode->i_lock); | 5571 | if (flctx && !list_empty_careful(&flctx->flc_posix)) { |
| 5573 | for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) { | 5572 | spin_lock(&flctx->flc_lock); |
| 5574 | if ((*flpp)->fl_owner == (fl_owner_t)lowner) { | 5573 | list_for_each_entry(fl, &flctx->flc_posix, fl_list) { |
| 5575 | status = true; | 5574 | if (fl->fl_owner == (fl_owner_t)lowner) { |
| 5576 | break; | 5575 | status = true; |
| 5576 | break; | ||
| 5577 | } | ||
| 5577 | } | 5578 | } |
| 5579 | spin_unlock(&flctx->flc_lock); | ||
| 5578 | } | 5580 | } |
| 5579 | spin_unlock(&inode->i_lock); | ||
| 5580 | fput(filp); | 5581 | fput(filp); |
| 5581 | return status; | 5582 | return status; |
| 5582 | } | 5583 | } |
