aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c100
1 files changed, 51 insertions, 49 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index a84a80e8c0cf..6ba428afa433 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -111,7 +111,6 @@ opaque_hashval(const void *ptr, int nbytes)
111/* forward declarations */ 111/* forward declarations */
112static void release_stateowner(struct nfs4_stateowner *sop); 112static void release_stateowner(struct nfs4_stateowner *sop);
113static void release_stateid(struct nfs4_stateid *stp, int flags); 113static void release_stateid(struct nfs4_stateid *stp, int flags);
114static void release_file(struct nfs4_file *fp);
115 114
116/* 115/*
117 * Delegation state 116 * Delegation state
@@ -121,6 +120,27 @@ static void release_file(struct nfs4_file *fp);
121spinlock_t recall_lock; 120spinlock_t recall_lock;
122static struct list_head del_recall_lru; 121static struct list_head del_recall_lru;
123 122
123static void
124free_nfs4_file(struct kref *kref)
125{
126 struct nfs4_file *fp = container_of(kref, struct nfs4_file, fi_ref);
127 list_del(&fp->fi_hash);
128 iput(fp->fi_inode);
129 kmem_cache_free(file_slab, fp);
130}
131
132static inline void
133put_nfs4_file(struct nfs4_file *fi)
134{
135 kref_put(&fi->fi_ref, free_nfs4_file);
136}
137
138static inline void
139get_nfs4_file(struct nfs4_file *fi)
140{
141 kref_get(&fi->fi_ref);
142}
143
124static struct nfs4_delegation * 144static struct nfs4_delegation *
125alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type) 145alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
126{ 146{
@@ -136,6 +156,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
136 INIT_LIST_HEAD(&dp->dl_del_perclnt); 156 INIT_LIST_HEAD(&dp->dl_del_perclnt);
137 INIT_LIST_HEAD(&dp->dl_recall_lru); 157 INIT_LIST_HEAD(&dp->dl_recall_lru);
138 dp->dl_client = clp; 158 dp->dl_client = clp;
159 get_nfs4_file(fp);
139 dp->dl_file = fp; 160 dp->dl_file = fp;
140 dp->dl_flock = NULL; 161 dp->dl_flock = NULL;
141 get_file(stp->st_vfs_file); 162 get_file(stp->st_vfs_file);
@@ -163,6 +184,7 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
163{ 184{
164 if (atomic_dec_and_test(&dp->dl_count)) { 185 if (atomic_dec_and_test(&dp->dl_count)) {
165 dprintk("NFSD: freeing dp %p\n",dp); 186 dprintk("NFSD: freeing dp %p\n",dp);
187 put_nfs4_file(dp->dl_file);
166 kmem_cache_free(deleg_slab, dp); 188 kmem_cache_free(deleg_slab, dp);
167 } 189 }
168} 190}
@@ -953,6 +975,7 @@ alloc_init_file(struct inode *ino)
953 975
954 fp = kmem_cache_alloc(file_slab, GFP_KERNEL); 976 fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
955 if (fp) { 977 if (fp) {
978 kref_init(&fp->fi_ref);
956 INIT_LIST_HEAD(&fp->fi_hash); 979 INIT_LIST_HEAD(&fp->fi_hash);
957 INIT_LIST_HEAD(&fp->fi_stateids); 980 INIT_LIST_HEAD(&fp->fi_stateids);
958 INIT_LIST_HEAD(&fp->fi_delegations); 981 INIT_LIST_HEAD(&fp->fi_delegations);
@@ -965,24 +988,6 @@ alloc_init_file(struct inode *ino)
965} 988}
966 989
967static void 990static void
968release_all_files(void)
969{
970 int i;
971 struct nfs4_file *fp;
972
973 for (i=0;i<FILE_HASH_SIZE;i++) {
974 while (!list_empty(&file_hashtbl[i])) {
975 fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash);
976 /* this should never be more than once... */
977 if (!list_empty(&fp->fi_stateids) || !list_empty(&fp->fi_delegations)) {
978 printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
979 }
980 release_file(fp);
981 }
982 }
983}
984
985static void
986nfsd4_free_slab(kmem_cache_t **slab) 991nfsd4_free_slab(kmem_cache_t **slab)
987{ 992{
988 int status; 993 int status;
@@ -1141,6 +1146,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
1141 list_add(&stp->st_perfilestate, &sop->so_perfilestate); 1146 list_add(&stp->st_perfilestate, &sop->so_perfilestate);
1142 list_add(&stp->st_perfile, &fp->fi_stateids); 1147 list_add(&stp->st_perfile, &fp->fi_stateids);
1143 stp->st_stateowner = sop; 1148 stp->st_stateowner = sop;
1149 get_nfs4_file(fp);
1144 stp->st_file = fp; 1150 stp->st_file = fp;
1145 stp->st_stateid.si_boot = boot_time; 1151 stp->st_stateid.si_boot = boot_time;
1146 stp->st_stateid.si_stateownerid = sop->so_id; 1152 stp->st_stateid.si_stateownerid = sop->so_id;
@@ -1166,18 +1172,11 @@ release_stateid(struct nfs4_stateid *stp, int flags)
1166 nfsd_close(filp); 1172 nfsd_close(filp);
1167 } else if (flags & LOCK_STATE) 1173 } else if (flags & LOCK_STATE)
1168 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner); 1174 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
1175 put_nfs4_file(stp->st_file);
1169 kmem_cache_free(stateid_slab, stp); 1176 kmem_cache_free(stateid_slab, stp);
1170 stp = NULL; 1177 stp = NULL;
1171} 1178}
1172 1179
1173static void
1174release_file(struct nfs4_file *fp)
1175{
1176 list_del(&fp->fi_hash);
1177 iput(fp->fi_inode);
1178 kmem_cache_free(file_slab, fp);
1179}
1180
1181void 1180void
1182move_to_close_lru(struct nfs4_stateowner *sop) 1181move_to_close_lru(struct nfs4_stateowner *sop)
1183{ 1182{
@@ -1192,7 +1191,6 @@ void
1192release_state_owner(struct nfs4_stateid *stp, int flag) 1191release_state_owner(struct nfs4_stateid *stp, int flag)
1193{ 1192{
1194 struct nfs4_stateowner *sop = stp->st_stateowner; 1193 struct nfs4_stateowner *sop = stp->st_stateowner;
1195 struct nfs4_file *fp = stp->st_file;
1196 1194
1197 dprintk("NFSD: release_state_owner\n"); 1195 dprintk("NFSD: release_state_owner\n");
1198 release_stateid(stp, flag); 1196 release_stateid(stp, flag);
@@ -1203,10 +1201,6 @@ release_state_owner(struct nfs4_stateid *stp, int flag)
1203 */ 1201 */
1204 if (sop->so_confirmed && list_empty(&sop->so_perfilestate)) 1202 if (sop->so_confirmed && list_empty(&sop->so_perfilestate))
1205 move_to_close_lru(sop); 1203 move_to_close_lru(sop);
1206 /* unused nfs4_file's are releseed. XXX slab cache? */
1207 if (list_empty(&fp->fi_stateids) && list_empty(&fp->fi_delegations)) {
1208 release_file(fp);
1209 }
1210} 1204}
1211 1205
1212static int 1206static int
@@ -1236,8 +1230,10 @@ find_file(struct inode *ino)
1236 struct nfs4_file *fp; 1230 struct nfs4_file *fp;
1237 1231
1238 list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) { 1232 list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
1239 if (fp->fi_inode == ino) 1233 if (fp->fi_inode == ino) {
1234 get_nfs4_file(fp);
1240 return fp; 1235 return fp;
1236 }
1241 } 1237 }
1242 return NULL; 1238 return NULL;
1243} 1239}
@@ -1288,19 +1284,24 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
1288 struct inode *ino = current_fh->fh_dentry->d_inode; 1284 struct inode *ino = current_fh->fh_dentry->d_inode;
1289 struct nfs4_file *fp; 1285 struct nfs4_file *fp;
1290 struct nfs4_stateid *stp; 1286 struct nfs4_stateid *stp;
1287 int ret;
1291 1288
1292 dprintk("NFSD: nfs4_share_conflict\n"); 1289 dprintk("NFSD: nfs4_share_conflict\n");
1293 1290
1294 fp = find_file(ino); 1291 fp = find_file(ino);
1295 if (fp) { 1292 if (!fp)
1293 return nfs_ok;
1294 ret = nfserr_share_denied;
1296 /* Search for conflicting share reservations */ 1295 /* Search for conflicting share reservations */
1297 list_for_each_entry(stp, &fp->fi_stateids, st_perfile) { 1296 list_for_each_entry(stp, &fp->fi_stateids, st_perfile) {
1298 if (test_bit(deny_type, &stp->st_deny_bmap) || 1297 if (test_bit(deny_type, &stp->st_deny_bmap) ||
1299 test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap)) 1298 test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
1300 return nfserr_share_denied; 1299 goto out;
1301 }
1302 } 1300 }
1303 return nfs_ok; 1301 ret = nfs_ok;
1302out:
1303 put_nfs4_file(fp);
1304 return ret;
1304} 1305}
1305 1306
1306static inline void 1307static inline void
@@ -1829,10 +1830,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1829 stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid, 1830 stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
1830 stp->st_stateid.si_fileid, stp->st_stateid.si_generation); 1831 stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
1831out: 1832out:
1832 /* take the opportunity to clean up unused state */ 1833 if (fp)
1833 if (fp && list_empty(&fp->fi_stateids) && list_empty(&fp->fi_delegations)) 1834 put_nfs4_file(fp);
1834 release_file(fp);
1835
1836 /* CLAIM_PREVIOUS has different error returns */ 1835 /* CLAIM_PREVIOUS has different error returns */
1837 nfs4_set_claim_prev(open, &status); 1836 nfs4_set_claim_prev(open, &status);
1838 /* 1837 /*
@@ -2480,16 +2479,19 @@ find_stateid(stateid_t *stid, int flags)
2480static struct nfs4_delegation * 2479static struct nfs4_delegation *
2481find_delegation_stateid(struct inode *ino, stateid_t *stid) 2480find_delegation_stateid(struct inode *ino, stateid_t *stid)
2482{ 2481{
2483 struct nfs4_file *fp = NULL; 2482 struct nfs4_file *fp;
2483 struct nfs4_delegation *dl;
2484 2484
2485 dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n", 2485 dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
2486 stid->si_boot, stid->si_stateownerid, 2486 stid->si_boot, stid->si_stateownerid,
2487 stid->si_fileid, stid->si_generation); 2487 stid->si_fileid, stid->si_generation);
2488 2488
2489 fp = find_file(ino); 2489 fp = find_file(ino);
2490 if (fp) 2490 if (!fp)
2491 return find_delegation_file(fp, stid); 2491 return NULL;
2492 return NULL; 2492 dl = find_delegation_file(fp, stid);
2493 put_nfs4_file(fp);
2494 return dl;
2493} 2495}
2494 2496
2495/* 2497/*
@@ -2636,6 +2638,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
2636 list_add(&stp->st_perfile, &fp->fi_stateids); 2638 list_add(&stp->st_perfile, &fp->fi_stateids);
2637 list_add(&stp->st_perfilestate, &sop->so_perfilestate); 2639 list_add(&stp->st_perfilestate, &sop->so_perfilestate);
2638 stp->st_stateowner = sop; 2640 stp->st_stateowner = sop;
2641 get_nfs4_file(fp);
2639 stp->st_file = fp; 2642 stp->st_file = fp;
2640 stp->st_stateid.si_boot = boot_time; 2643 stp->st_stateid.si_boot = boot_time;
2641 stp->st_stateid.si_stateownerid = sop->so_id; 2644 stp->st_stateid.si_stateownerid = sop->so_id;
@@ -3287,7 +3290,6 @@ __nfs4_state_shutdown(void)
3287 unhash_delegation(dp); 3290 unhash_delegation(dp);
3288 } 3291 }
3289 3292
3290 release_all_files();
3291 cancel_delayed_work(&laundromat_work); 3293 cancel_delayed_work(&laundromat_work);
3292 flush_scheduled_work(); 3294 flush_scheduled_work();
3293 nfs4_init = 0; 3295 nfs4_init = 0;