* [PATCH 1/4] knfsd: Store the filehandle with the struct nfs4_file @ 2014-07-21 22:54 Trond Myklebust 2014-07-21 22:54 ` [PATCH 2/4] knfsd: Use the filehandle to look up the struct nfs4_file instead of inode Trond Myklebust 0 siblings, 1 reply; 4+ messages in thread From: Trond Myklebust @ 2014-07-21 22:54 UTC (permalink / raw) To: Jeff Layton; +Cc: linux-nfs For use when we may not have a struct inode. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> --- fs/nfsd/nfs4state.c | 10 ++++++---- fs/nfsd/state.h | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 08ee9ca13cb1..55bc43674fce 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2805,7 +2805,8 @@ static struct nfs4_file *nfsd4_alloc_file(void) } /* OPEN Share state helper functions */ -static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino) +static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino, + struct knfsd_fh *fh) { unsigned int hashval = file_hashval(ino); @@ -2814,6 +2815,7 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino) INIT_LIST_HEAD(&fp->fi_stateids); INIT_LIST_HEAD(&fp->fi_delegations); fp->fi_inode = igrab(ino); + fh_copy_shallow(&fp->fi_fhandle, fh); fp->fi_had_conflict = false; fp->fi_lease = NULL; memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); @@ -3073,14 +3075,14 @@ find_file(struct inode *ino) } static struct nfs4_file * -find_or_add_file(struct inode *ino, struct nfs4_file *new) +find_or_add_file(struct inode *ino, struct nfs4_file *new, struct knfsd_fh *fh) { struct nfs4_file *fp; spin_lock(&state_lock); fp = find_file_locked(ino); if (fp == NULL) { - nfsd4_init_file(new, ino); + nfsd4_init_file(new, ino, fh); fp = new; } spin_unlock(&state_lock); @@ -3669,7 +3671,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf * and check for delegations in the process of being recalled. * If not found, create the nfs4_file struct */ - fp = find_or_add_file(ino, open->op_file); + fp = find_or_add_file(ino, open->op_file, ¤t_fh->fh_handle); if (fp != open->op_file) { if ((status = nfs4_check_open(fp, open, &stp))) goto out; diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index f11c74f3d40d..38c575c084e4 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -405,6 +405,7 @@ struct nfs4_file { struct file *fi_deleg_file; struct file_lock *fi_lease; atomic_t fi_delegees; + struct knfsd_fh fi_fhandle; struct inode *fi_inode; bool fi_had_conflict; }; -- 1.9.3 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/4] knfsd: Use the filehandle to look up the struct nfs4_file instead of inode 2014-07-21 22:54 [PATCH 1/4] knfsd: Store the filehandle with the struct nfs4_file Trond Myklebust @ 2014-07-21 22:54 ` Trond Myklebust 2014-07-21 22:54 ` [PATCH 3/4] knfsd: nfs4_check_fh - make it actually check the filehandle Trond Myklebust 0 siblings, 1 reply; 4+ messages in thread From: Trond Myklebust @ 2014-07-21 22:54 UTC (permalink / raw) To: Jeff Layton; +Cc: linux-nfs Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> --- fs/nfsd/nfs4state.c | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 55bc43674fce..2e9519db4927 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -346,10 +346,22 @@ static int nfs4_access_to_omode(u32 access) return O_RDONLY; } -static unsigned int file_hashval(struct inode *ino) +static unsigned int nfsd_fh_hashval(struct knfsd_fh *fh) { - /* XXX: why are we hashing on inode pointer, anyway? */ - return hash_ptr(ino, FILE_HASH_BITS); + return jhash2(fh->fh_base.fh_pad, XDR_QUADLEN(fh->fh_size), 0); +} + +static unsigned int file_hashval(struct knfsd_fh *fh) +{ + return nfsd_fh_hashval(fh) & (FILE_HASH_SIZE - 1); +} + +static bool nfsd_fh_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2) +{ + return fh1->fh_size == fh2->fh_size && + !memcmp(fh1->fh_base.fh_pad, + fh2->fh_base.fh_pad, + fh1->fh_size); } static struct hlist_head file_hashtbl[FILE_HASH_SIZE]; @@ -583,11 +595,13 @@ static void unhash_stid(struct nfs4_stid *s) static void hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp) { + struct inode *inode = fp->fi_deleg_file->f_dentry->d_inode; + atomic_inc(&dp->dl_stid.sc_count); dp->dl_stid.sc_type = NFS4_DELEG_STID; - spin_lock(&fp->fi_inode->i_lock); + spin_lock(&inode->i_lock); list_add(&dp->dl_perfile, &fp->fi_delegations); - spin_unlock(&fp->fi_inode->i_lock); + spin_unlock(&inode->i_lock); list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); } @@ -601,9 +615,10 @@ unhash_delegation_locked(struct nfs4_delegation *dp) list_del_init(&dp->dl_perclnt); list_del_init(&dp->dl_recall_lru); if (!list_empty(&dp->dl_perfile)) { - spin_lock(&fp->fi_inode->i_lock); + struct inode *inode = fp->fi_deleg_file->f_dentry->d_inode; + spin_lock(&inode->i_lock); list_del_init(&dp->dl_perfile); - spin_unlock(&fp->fi_inode->i_lock); + spin_unlock(&inode->i_lock); } nfs4_put_deleg_lease(fp); spin_unlock(&fp->fi_lock); @@ -2808,7 +2823,7 @@ static struct nfs4_file *nfsd4_alloc_file(void) static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino, struct knfsd_fh *fh) { - unsigned int hashval = file_hashval(ino); + unsigned int hashval = file_hashval(fh); atomic_set(&fp->fi_ref, 1); spin_lock_init(&fp->fi_lock); @@ -3047,15 +3062,15 @@ find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, /* search file_hashtbl[] for file */ static struct nfs4_file * -find_file_locked(struct inode *ino) +find_file_locked(struct knfsd_fh *fh) { - unsigned int hashval = file_hashval(ino); + unsigned int hashval = file_hashval(fh); struct nfs4_file *fp; assert_spin_locked(&state_lock); hlist_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) { - if (fp->fi_inode == ino) { + if (nfsd_fh_match(&fp->fi_fhandle, fh)) { get_nfs4_file(fp); return fp; } @@ -3064,12 +3079,12 @@ find_file_locked(struct inode *ino) } static struct nfs4_file * -find_file(struct inode *ino) +find_file(struct knfsd_fh *fh) { struct nfs4_file *fp; spin_lock(&state_lock); - fp = find_file_locked(ino); + fp = find_file_locked(fh); spin_unlock(&state_lock); return fp; } @@ -3080,7 +3095,7 @@ find_or_add_file(struct inode *ino, struct nfs4_file *new, struct knfsd_fh *fh) struct nfs4_file *fp; spin_lock(&state_lock); - fp = find_file_locked(ino); + fp = find_file_locked(fh); if (fp == NULL) { nfsd4_init_file(new, ino, fh); fp = new; @@ -3096,12 +3111,11 @@ find_or_add_file(struct inode *ino, struct nfs4_file *new, struct knfsd_fh *fh) static __be32 nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) { - struct inode *ino = current_fh->fh_dentry->d_inode; struct nfs4_file *fp; struct nfs4_ol_stateid *stp; __be32 ret; - fp = find_file(ino); + fp = find_file(¤t_fh->fh_handle); if (!fp) return nfs_ok; ret = nfserr_locked; -- 1.9.3 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/4] knfsd: nfs4_check_fh - make it actually check the filehandle 2014-07-21 22:54 ` [PATCH 2/4] knfsd: Use the filehandle to look up the struct nfs4_file instead of inode Trond Myklebust @ 2014-07-21 22:54 ` Trond Myklebust 2014-07-21 22:54 ` [PATCH 4/4] knfsd: Do not let nfs4_file pin the struct inode Trond Myklebust 0 siblings, 1 reply; 4+ messages in thread From: Trond Myklebust @ 2014-07-21 22:54 UTC (permalink / raw) To: Jeff Layton; +Cc: linux-nfs Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> --- fs/nfsd/nfs4state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 2e9519db4927..2b2cd6814615 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3958,7 +3958,7 @@ laundromat_main(struct work_struct *laundry) static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *stp) { - if (fhp->fh_dentry->d_inode != stp->st_stid.sc_file->fi_inode) + if (!nfsd_fh_match(&fhp->fh_handle, &stp->st_stid.sc_file->fi_fhandle)) return nfserr_bad_stateid; return nfs_ok; } -- 1.9.3 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 4/4] knfsd: Do not let nfs4_file pin the struct inode 2014-07-21 22:54 ` [PATCH 3/4] knfsd: nfs4_check_fh - make it actually check the filehandle Trond Myklebust @ 2014-07-21 22:54 ` Trond Myklebust 0 siblings, 0 replies; 4+ messages in thread From: Trond Myklebust @ 2014-07-21 22:54 UTC (permalink / raw) To: Jeff Layton; +Cc: linux-nfs Remove the fi_inode field in struct nfs4_file in order to remove the possibility of struct nfs4_file pinning the inode when it does not have any open state. Add a field to struct nfs4_ol_stateid, so that the lock stateid may continue to check for existing lock state before being released. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> --- fs/nfsd/nfs4state.c | 31 ++++++++++++++++--------------- fs/nfsd/state.h | 2 +- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 2b2cd6814615..2bc89bfc905a 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -69,7 +69,7 @@ static u64 current_sessionid = 1; #define CURRENT_STATEID(stateid) (!memcmp((stateid), ¤tstateid, sizeof(stateid_t))) /* forward declarations */ -static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner); +static int check_for_locks(struct inode *inode, struct nfs4_lockowner *lowner); static void nfs4_free_generic_stateid(struct nfs4_stid *stid); static struct nfs4_openowner *find_openstateowner_str_locked( unsigned int hashval, struct nfsd4_open *open, @@ -251,7 +251,6 @@ put_nfs4_file(struct nfs4_file *fi) if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) { hlist_del(&fi->fi_hash); spin_unlock(&state_lock); - iput(fi->fi_inode); nfsd4_free_file(fi); } } @@ -796,6 +795,8 @@ static void nfs4_free_generic_stateid(struct nfs4_stid *stid) release_all_access(stp); if (stp->st_stateowner) nfs4_put_stateowner(stp->st_stateowner); + if (stp->st_inode) + iput(stp->st_inode); nfs4_free_stid(stateid_slab, stid); } @@ -2820,8 +2821,7 @@ static struct nfs4_file *nfsd4_alloc_file(void) } /* OPEN Share state helper functions */ -static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino, - struct knfsd_fh *fh) +static void nfsd4_init_file(struct nfs4_file *fp, struct knfsd_fh *fh) { unsigned int hashval = file_hashval(fh); @@ -2829,7 +2829,6 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino, spin_lock_init(&fp->fi_lock); INIT_LIST_HEAD(&fp->fi_stateids); INIT_LIST_HEAD(&fp->fi_delegations); - fp->fi_inode = igrab(ino); fh_copy_shallow(&fp->fi_fhandle, fh); fp->fi_had_conflict = false; fp->fi_lease = NULL; @@ -3090,14 +3089,14 @@ find_file(struct knfsd_fh *fh) } static struct nfs4_file * -find_or_add_file(struct inode *ino, struct nfs4_file *new, struct knfsd_fh *fh) +find_or_add_file(struct nfs4_file *new, struct knfsd_fh *fh) { struct nfs4_file *fp; spin_lock(&state_lock); fp = find_file_locked(fh); if (fp == NULL) { - nfsd4_init_file(new, ino, fh); + nfsd4_init_file(new, fh); fp = new; } spin_unlock(&state_lock); @@ -3675,7 +3674,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf struct nfsd4_compoundres *resp = rqstp->rq_resp; struct nfs4_client *cl = open->op_openowner->oo_owner.so_client; struct nfs4_file *fp = NULL; - struct inode *ino = current_fh->fh_dentry->d_inode; struct nfs4_ol_stateid *stp = NULL; struct nfs4_delegation *dp = NULL; __be32 status; @@ -3685,7 +3683,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf * and check for delegations in the process of being recalled. * If not found, create the nfs4_file struct */ - fp = find_or_add_file(ino, open->op_file, ¤t_fh->fh_handle); + fp = find_or_add_file(open->op_file, ¤t_fh->fh_handle); if (fp != open->op_file) { if ((status = nfs4_check_open(fp, open, &stp))) goto out; @@ -4217,7 +4215,7 @@ unlock_state: static __be32 nfsd4_free_lock_stateid(struct nfs4_ol_stateid *stp) { - if (check_for_locks(stp->st_stid.sc_file, lockowner(stp->st_stateowner))) + if (check_for_locks(stp->st_inode, lockowner(stp->st_stateowner))) return nfserr_locks_held; release_lock_stateid(stp); return nfs_ok; @@ -4761,7 +4759,9 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str } static struct nfs4_ol_stateid * -alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct nfs4_ol_stateid *open_stp) +alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, + struct inode *inode, + struct nfs4_ol_stateid *open_stp) { struct nfs4_openowner *oo = openowner(open_stp->st_stateowner); struct nfs4_ol_stateid *stp; @@ -4775,6 +4775,7 @@ alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct stp->st_stateowner = &lo->lo_owner; atomic_inc(&lo->lo_owner.so_count); get_nfs4_file(fp); + stp->st_inode = igrab(inode); stp->st_stid.sc_file = fp; stp->st_access_bmap = 0; stp->st_deny_bmap = open_stp->st_deny_bmap; @@ -4828,6 +4829,7 @@ static __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, s struct nfs4_file *fi = ost->st_stid.sc_file; struct nfs4_openowner *oo = openowner(ost->st_stateowner); struct nfs4_client *cl = oo->oo_owner.so_client; + struct inode *inode = cstate->current_fh.fh_dentry->d_inode; struct nfs4_lockowner *lo; unsigned int strhashval; __be32 status; @@ -4844,7 +4846,7 @@ static __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, s goto out; *lst = find_lock_stateid(lo, fi); if (*lst == NULL) { - *lst = alloc_init_lock_stateid(lo, fi, ost); + *lst = alloc_init_lock_stateid(lo, fi, inode, ost); if (*lst == NULL) { status = nfserr_jukebox; release_lockowner_if_empty(lo); @@ -5201,10 +5203,9 @@ out_nfserr: * 0: no locks held by lockowner */ static int -check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner) +check_for_locks(struct inode *inode, struct nfs4_lockowner *lowner) { struct file_lock **flpp; - struct inode *inode = filp->fi_inode; int status = 0; spin_lock(&inode->i_lock); @@ -5256,7 +5257,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, list_for_each_entry(stp, &sop->so_stateids, st_perstateowner) { lo = lockowner(sop); - if (check_for_locks(stp->st_stid.sc_file, lo)) + if (check_for_locks(stp->st_inode, lo)) goto out; list_add(&lo->lo_list, &matches); } diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 38c575c084e4..5d2c327cb7df 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -406,7 +406,6 @@ struct nfs4_file { struct file_lock *fi_lease; atomic_t fi_delegees; struct knfsd_fh fi_fhandle; - struct inode *fi_inode; bool fi_had_conflict; }; @@ -420,6 +419,7 @@ struct nfs4_ol_stateid { unsigned long st_access_bmap; unsigned long st_deny_bmap; struct nfs4_ol_stateid * st_openstp; + struct inode * st_inode; }; static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) -- 1.9.3 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-07-21 22:54 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-07-21 22:54 [PATCH 1/4] knfsd: Store the filehandle with the struct nfs4_file Trond Myklebust 2014-07-21 22:54 ` [PATCH 2/4] knfsd: Use the filehandle to look up the struct nfs4_file instead of inode Trond Myklebust 2014-07-21 22:54 ` [PATCH 3/4] knfsd: nfs4_check_fh - make it actually check the filehandle Trond Myklebust 2014-07-21 22:54 ` [PATCH 4/4] knfsd: Do not let nfs4_file pin the struct inode Trond Myklebust
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).