diff options
author | Jeff Layton <jlayton@primarydata.com> | 2014-07-23 16:17:41 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-07-23 16:35:24 -0400 |
commit | f9c00c3ab425ef04ca5a3caa5e9a9f5e0272bb8a (patch) | |
tree | 1a6137e597d1a9e0523834a865f34d683dd8a012 /fs/nfsd/nfs4state.c | |
parent | b07c54a4a3802f28b0ed7b40b4341b170a3ef78f (diff) |
nfsd: Do not let nfs4_file pin the struct inode
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.
The only place we still need to get to an inode is in check_for_locks,
so change it to use find_any_file and use the inode from any that it
finds. If it doesn't find one, then just assume there aren't any.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 49 |
1 files changed, 28 insertions, 21 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 6ced8d566c0b..1dfc8ee85c93 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -70,7 +70,7 @@ static u64 current_sessionid = 1; | |||
70 | #define CURRENT_STATEID(stateid) (!memcmp((stateid), ¤tstateid, sizeof(stateid_t))) | 70 | #define CURRENT_STATEID(stateid) (!memcmp((stateid), ¤tstateid, sizeof(stateid_t))) |
71 | 71 | ||
72 | /* forward declarations */ | 72 | /* forward declarations */ |
73 | static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner); | 73 | static bool check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner); |
74 | 74 | ||
75 | /* Locking: */ | 75 | /* Locking: */ |
76 | 76 | ||
@@ -259,7 +259,6 @@ put_nfs4_file(struct nfs4_file *fi) | |||
259 | if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) { | 259 | if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) { |
260 | hlist_del(&fi->fi_hash); | 260 | hlist_del(&fi->fi_hash); |
261 | spin_unlock(&state_lock); | 261 | spin_unlock(&state_lock); |
262 | iput(fi->fi_inode); | ||
263 | nfsd4_free_file(fi); | 262 | nfsd4_free_file(fi); |
264 | } | 263 | } |
265 | } | 264 | } |
@@ -2845,8 +2844,7 @@ static struct nfs4_file *nfsd4_alloc_file(void) | |||
2845 | } | 2844 | } |
2846 | 2845 | ||
2847 | /* OPEN Share state helper functions */ | 2846 | /* OPEN Share state helper functions */ |
2848 | static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino, | 2847 | static void nfsd4_init_file(struct nfs4_file *fp, struct knfsd_fh *fh) |
2849 | struct knfsd_fh *fh) | ||
2850 | { | 2848 | { |
2851 | unsigned int hashval = file_hashval(fh); | 2849 | unsigned int hashval = file_hashval(fh); |
2852 | 2850 | ||
@@ -2856,8 +2854,6 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino, | |||
2856 | spin_lock_init(&fp->fi_lock); | 2854 | spin_lock_init(&fp->fi_lock); |
2857 | INIT_LIST_HEAD(&fp->fi_stateids); | 2855 | INIT_LIST_HEAD(&fp->fi_stateids); |
2858 | INIT_LIST_HEAD(&fp->fi_delegations); | 2856 | INIT_LIST_HEAD(&fp->fi_delegations); |
2859 | ihold(ino); | ||
2860 | fp->fi_inode = ino; | ||
2861 | fh_copy_shallow(&fp->fi_fhandle, fh); | 2857 | fh_copy_shallow(&fp->fi_fhandle, fh); |
2862 | fp->fi_had_conflict = false; | 2858 | fp->fi_had_conflict = false; |
2863 | fp->fi_lease = NULL; | 2859 | fp->fi_lease = NULL; |
@@ -3063,14 +3059,14 @@ find_file(struct knfsd_fh *fh) | |||
3063 | } | 3059 | } |
3064 | 3060 | ||
3065 | static struct nfs4_file * | 3061 | static struct nfs4_file * |
3066 | find_or_add_file(struct inode *ino, struct nfs4_file *new, struct knfsd_fh *fh) | 3062 | find_or_add_file(struct nfs4_file *new, struct knfsd_fh *fh) |
3067 | { | 3063 | { |
3068 | struct nfs4_file *fp; | 3064 | struct nfs4_file *fp; |
3069 | 3065 | ||
3070 | spin_lock(&state_lock); | 3066 | spin_lock(&state_lock); |
3071 | fp = find_file_locked(fh); | 3067 | fp = find_file_locked(fh); |
3072 | if (fp == NULL) { | 3068 | if (fp == NULL) { |
3073 | nfsd4_init_file(new, ino, fh); | 3069 | nfsd4_init_file(new, fh); |
3074 | fp = new; | 3070 | fp = new; |
3075 | } | 3071 | } |
3076 | spin_unlock(&state_lock); | 3072 | spin_unlock(&state_lock); |
@@ -3714,7 +3710,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
3714 | struct nfsd4_compoundres *resp = rqstp->rq_resp; | 3710 | struct nfsd4_compoundres *resp = rqstp->rq_resp; |
3715 | struct nfs4_client *cl = open->op_openowner->oo_owner.so_client; | 3711 | struct nfs4_client *cl = open->op_openowner->oo_owner.so_client; |
3716 | struct nfs4_file *fp = NULL; | 3712 | struct nfs4_file *fp = NULL; |
3717 | struct inode *ino = current_fh->fh_dentry->d_inode; | ||
3718 | struct nfs4_ol_stateid *stp = NULL; | 3713 | struct nfs4_ol_stateid *stp = NULL; |
3719 | struct nfs4_delegation *dp = NULL; | 3714 | struct nfs4_delegation *dp = NULL; |
3720 | __be32 status; | 3715 | __be32 status; |
@@ -3724,7 +3719,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
3724 | * and check for delegations in the process of being recalled. | 3719 | * and check for delegations in the process of being recalled. |
3725 | * If not found, create the nfs4_file struct | 3720 | * If not found, create the nfs4_file struct |
3726 | */ | 3721 | */ |
3727 | fp = find_or_add_file(ino, open->op_file, ¤t_fh->fh_handle); | 3722 | fp = find_or_add_file(open->op_file, ¤t_fh->fh_handle); |
3728 | if (fp != open->op_file) { | 3723 | if (fp != open->op_file) { |
3729 | status = nfs4_check_deleg(cl, open, &dp); | 3724 | status = nfs4_check_deleg(cl, open, &dp); |
3730 | if (status) | 3725 | if (status) |
@@ -4663,7 +4658,9 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str | |||
4663 | } | 4658 | } |
4664 | 4659 | ||
4665 | static struct nfs4_ol_stateid * | 4660 | static struct nfs4_ol_stateid * |
4666 | alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct nfs4_ol_stateid *open_stp) | 4661 | alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, |
4662 | struct inode *inode, | ||
4663 | struct nfs4_ol_stateid *open_stp) | ||
4667 | { | 4664 | { |
4668 | struct nfs4_ol_stateid *stp; | 4665 | struct nfs4_ol_stateid *stp; |
4669 | struct nfs4_client *clp = lo->lo_owner.so_client; | 4666 | struct nfs4_client *clp = lo->lo_owner.so_client; |
@@ -4723,6 +4720,7 @@ static __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, s | |||
4723 | struct nfs4_file *fi = ost->st_file; | 4720 | struct nfs4_file *fi = ost->st_file; |
4724 | struct nfs4_openowner *oo = openowner(ost->st_stateowner); | 4721 | struct nfs4_openowner *oo = openowner(ost->st_stateowner); |
4725 | struct nfs4_client *cl = oo->oo_owner.so_client; | 4722 | struct nfs4_client *cl = oo->oo_owner.so_client; |
4723 | struct inode *inode = cstate->current_fh.fh_dentry->d_inode; | ||
4726 | struct nfs4_lockowner *lo; | 4724 | struct nfs4_lockowner *lo; |
4727 | unsigned int strhashval; | 4725 | unsigned int strhashval; |
4728 | struct nfsd_net *nn = net_generic(cl->net, nfsd_net_id); | 4726 | struct nfsd_net *nn = net_generic(cl->net, nfsd_net_id); |
@@ -4743,7 +4741,7 @@ static __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, s | |||
4743 | 4741 | ||
4744 | *lst = find_lock_stateid(lo, fi); | 4742 | *lst = find_lock_stateid(lo, fi); |
4745 | if (*lst == NULL) { | 4743 | if (*lst == NULL) { |
4746 | *lst = alloc_init_lock_stateid(lo, fi, ost); | 4744 | *lst = alloc_init_lock_stateid(lo, fi, inode, ost); |
4747 | if (*lst == NULL) { | 4745 | if (*lst == NULL) { |
4748 | release_lockowner_if_empty(lo); | 4746 | release_lockowner_if_empty(lo); |
4749 | return nfserr_jukebox; | 4747 | return nfserr_jukebox; |
@@ -5092,25 +5090,34 @@ out_nfserr: | |||
5092 | 5090 | ||
5093 | /* | 5091 | /* |
5094 | * returns | 5092 | * returns |
5095 | * 1: locks held by lockowner | 5093 | * true: locks held by lockowner |
5096 | * 0: no locks held by lockowner | 5094 | * false: no locks held by lockowner |
5097 | */ | 5095 | */ |
5098 | static int | 5096 | static bool |
5099 | check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner) | 5097 | check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) |
5100 | { | 5098 | { |
5101 | struct file_lock **flpp; | 5099 | struct file_lock **flpp; |
5102 | struct inode *inode = filp->fi_inode; | 5100 | int status = false; |
5103 | int status = 0; | 5101 | struct file *filp = find_any_file(fp); |
5102 | struct inode *inode; | ||
5103 | |||
5104 | if (!filp) { | ||
5105 | /* Any valid lock stateid should have some sort of access */ | ||
5106 | WARN_ON_ONCE(1); | ||
5107 | return status; | ||
5108 | } | ||
5109 | |||
5110 | inode = file_inode(filp); | ||
5104 | 5111 | ||
5105 | spin_lock(&inode->i_lock); | 5112 | spin_lock(&inode->i_lock); |
5106 | for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) { | 5113 | for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) { |
5107 | if ((*flpp)->fl_owner == (fl_owner_t)lowner) { | 5114 | if ((*flpp)->fl_owner == (fl_owner_t)lowner) { |
5108 | status = 1; | 5115 | status = true; |
5109 | goto out; | 5116 | break; |
5110 | } | 5117 | } |
5111 | } | 5118 | } |
5112 | out: | ||
5113 | spin_unlock(&inode->i_lock); | 5119 | spin_unlock(&inode->i_lock); |
5120 | fput(filp); | ||
5114 | return status; | 5121 | return status; |
5115 | } | 5122 | } |
5116 | 5123 | ||