aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@primarydata.com>2014-07-23 16:17:41 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-07-23 16:35:24 -0400
commitf9c00c3ab425ef04ca5a3caa5e9a9f5e0272bb8a (patch)
tree1a6137e597d1a9e0523834a865f34d683dd8a012 /fs/nfsd/nfs4state.c
parentb07c54a4a3802f28b0ed7b40b4341b170a3ef78f (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.c49
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), &currentstateid, sizeof(stateid_t))) 70#define CURRENT_STATEID(stateid) (!memcmp((stateid), &currentstateid, sizeof(stateid_t)))
71 71
72/* forward declarations */ 72/* forward declarations */
73static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner); 73static 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 */
2848static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino, 2847static 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
3065static struct nfs4_file * 3061static struct nfs4_file *
3066find_or_add_file(struct inode *ino, struct nfs4_file *new, struct knfsd_fh *fh) 3062find_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, &current_fh->fh_handle); 3722 fp = find_or_add_file(open->op_file, &current_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
4665static struct nfs4_ol_stateid * 4660static struct nfs4_ol_stateid *
4666alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct nfs4_ol_stateid *open_stp) 4661alloc_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 */
5098static int 5096static bool
5099check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner) 5097check_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 }
5112out:
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