aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorNeil Brown <neilb@cse.unsw.edu.au>2005-01-04 05:50:03 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-04 05:50:03 -0800
commitea7b53a314e865dd420093a5ef62aabc94267afb (patch)
tree3ebda1a5dbe93438e6ea8206265a4ba36cfdc5c6 /fs
parent8f7a458b6cd20f8f28c1f2a1e0489dc23be2b40d (diff)
downloadhistory-ea7b53a314e865dd420093a5ef62aabc94267afb.tar.gz
[PATCH] knfsd: add the delegation release and free functions
Signed-off-by: Andy Adamson <andros@citi.umich.edu> Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/nfs4state.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f90f2407c545e1..40060c016eaa0e 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -82,6 +82,8 @@ u32 free_delegation= 0;
/* forward declarations */
struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
+static void release_delegation(struct nfs4_delegation *dp);
+static void release_stateid_lockowner(struct nfs4_stateid *open_stp);
/* Locking:
*
@@ -166,6 +168,67 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp, struct svc_fh *c
return dp;
}
+/*
+ * Free the delegation structure.
+ * Called with the recall_lock held.
+ */
+static void
+nfs4_free_delegation(struct nfs4_delegation *dp)
+{
+ dprintk("NFSD: nfs4_free_delegation freeing dp %p\n",dp);
+ list_del(&dp->dl_recall_lru);
+ kfree(dp);
+ free_delegation++;
+}
+
+/* release_delegation:
+ *
+ * Remove the associated file_lock first, then remove the delegation.
+ * lease_modify() is called to remove the FS_LEASE file_lock from
+ * the i_flock list, eventually calling nfsd's lock_manager
+ * fl_release_callback.
+ *
+ * call either:
+ * nfsd_close : if last close, locks_remove_flock calls lease_modify.
+ * otherwise, recalled state set to NFS4_RECALL_COMPLETE
+ * so that it will be reaped by the laundromat service.
+ * or
+ * remove_lease (calls time_out_lease which calls lease_modify).
+ * and nfs4_free_delegation.
+ *
+ * Called with nfs_lock_state() held.
+ * Called with the recall_lock held.
+ */
+
+static void
+release_delegation(struct nfs4_delegation *dp)
+{
+ /* delayed nfsd_close */
+ if (dp->dl_stp) {
+ struct file *filp = dp->dl_stp->st_vfs_file;
+
+ dprintk("NFSD: release_delegation CLOSE\n");
+ release_stateid_lockowner(dp->dl_stp);
+ kfree(dp->dl_stp);
+ dp->dl_stp = NULL;
+ atomic_set(&dp->dl_state, NFS4_RECALL_COMPLETE);
+ nfsd_close(filp);
+ vfsclose++;
+ } else {
+ dprintk("NFSD: release_delegation remove lease dl_flock %p\n",
+ dp->dl_flock);
+ remove_lease(dp->dl_flock);
+ list_del_init(&dp->dl_del_perfile);
+ list_del_init(&dp->dl_del_perclnt);
+ /* dl_count > 0 => outstanding recall rpc */
+ dprintk("NFSD: release_delegation free deleg dl_count %d\n",
+ atomic_read(&dp->dl_count));
+ if ((atomic_read(&dp->dl_state) == NFS4_REAP_DELEG)
+ || atomic_dec_and_test(&dp->dl_count))
+ nfs4_free_delegation(dp);
+ }
+}
+
/*
* SETCLIENTID state
*/