From 15a39f6a151b4e37e8c482c76bdb4240d9b559a3 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 27 Mar 2008 18:46:54 -0700 Subject: [PATCH] kclient: drop dn lease before unlink/rmdir --- src/TODO | 8 ++++---- src/kernel/dir.c | 13 +++++++++---- src/kernel/inode.c | 12 ++++++++---- src/kernel/mds_client.c | 29 ++++++++++++++++++++++++++++- src/kernel/mds_client.h | 3 +++ src/kernel/super.h | 4 +++- 6 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/TODO b/src/TODO index bb279f89f1c6a..5c6c3c3a4ca70 100644 --- a/src/TODO +++ b/src/TODO @@ -4,8 +4,6 @@ code cleanup - probably kill base case in encoder.h, replace with int types, with appropriate swabbing? - addr=? -- switch to nsec in ceph_timespec - client leases - lease length heuristics - mds lock last_change stamp? @@ -18,6 +16,8 @@ client leases - lease renewals (to avoid blocking client ops?) userspace client +- pay attention to dn lease mds +- pay attention to inode lease mds - clean up ll_ interface, now that we have leases! - obey file_max - revoke own caps when they time out, @@ -28,8 +28,8 @@ userspace client - reference count lease validations on path lookup? kernel client -- strip i_wr_size etc out of ceph_inode_info - - take mds provided versions when appropriate +- pay attention to dn lease mds +- pay attention to inode lease mds - carry wrbuffer/rdcache caps until data is flushed - this should make the utimes bit kick in - make sure link/unlink results reflected by inode/dentry cache (let fill_trace do it? invalidate? do actual update?) diff --git a/src/kernel/dir.c b/src/kernel/dir.c index 1f441932cb7d2..5af1695dbd84e 100644 --- a/src/kernel/dir.c +++ b/src/kernel/dir.c @@ -97,7 +97,7 @@ static unsigned fpos_off(loff_t p) static int prepopulate_dir(struct dentry *parent, struct ceph_mds_reply_info *rinfo, - int from_time) + int from_mds, unsigned long from_time) { struct qstr dname; struct dentry *dn; @@ -122,7 +122,8 @@ static int prepopulate_dir(struct dentry *parent, } ceph_init_dentry(dn); } - ceph_update_dentry_lease(dn, rinfo->dir_dlease[i], from_time); + ceph_update_dentry_lease(dn, rinfo->dir_dlease[i], + from_mds, from_time); /* inode */ if (dn->d_inode == NULL) { @@ -204,6 +205,7 @@ nextfrag: /* pre-populate dentry cache */ prepopulate_dir(filp->f_dentry, &req->r_reply_info, + le32_to_cpu(req->r_reply->hdr.src.name.num), req->r_from_time); } @@ -504,6 +506,7 @@ static int ceph_dir_unlink(struct inode *dir, struct dentry *dentry) kfree(path); if (IS_ERR(req)) return PTR_ERR(req); + ceph_mdsc_lease_release(mdsc, dentry); err = ceph_mdsc_do_request(mdsc, req); ceph_mdsc_put_request(req); @@ -550,8 +553,10 @@ static int ceph_dir_rename(struct inode *old_dir, struct dentry *old_dentry, static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) { - dout(20, "d_revalidate ttl %lu now %lu\n", dentry->d_time, jiffies); - if (time_after(jiffies, dentry->d_time)) { + int mds = (long)dentry->d_fsdata; + dout(20, "d_revalidate ttl %lu mds %d now %lu\n", dentry->d_time, + mds, jiffies); + if (mds >= 0 && time_after(jiffies, dentry->d_time)) { dout(20, "d_revalidate - dentry %p expired\n", dentry); d_drop(dentry); return 0; diff --git a/src/kernel/inode.c b/src/kernel/inode.c index 4e678b5a4a74c..7de74b6688231 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -173,6 +173,7 @@ void ceph_update_inode_lease(struct inode *inode, void ceph_update_dentry_lease(struct dentry *dentry, struct ceph_mds_reply_lease *lease, + int from_mds, unsigned long from_time) { __u64 ttl = le32_to_cpu(lease->duration_ms) * HZ; @@ -184,14 +185,17 @@ void ceph_update_dentry_lease(struct dentry *dentry, dentry, le16_to_cpu(lease->mask), le32_to_cpu(lease->duration_ms), ttl); if (lease->mask) { - if (ttl > dentry->d_time) + if (ttl > dentry->d_time) { dentry->d_time = ttl; + dentry->d_fsdata = (void *)(long)from_mds; + } } else { - dentry->d_time = 0; /* invalidate */ + dentry->d_fsdata = (void *)(long)-1; /* invalidate */ } } -int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) +int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, + int mds) { struct ceph_mds_reply_info *rinfo = &req->r_reply_info; int err = 0; @@ -264,7 +268,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) } } ceph_update_dentry_lease(dn, rinfo->trace_dlease[d], - req->r_from_time); + mds, req->r_from_time); /* inode */ if (d+1 == rinfo->trace_numi) { diff --git a/src/kernel/mds_client.c b/src/kernel/mds_client.c index 83bd90f8e724d..f8b5e9c572c25 100644 --- a/src/kernel/mds_client.c +++ b/src/kernel/mds_client.c @@ -892,7 +892,7 @@ void ceph_mdsc_handle_reply(struct ceph_mds_client *mdsc, struct ceph_msg *msg) dout(10, "handle_reply tid %lld result %d\n", tid, result); /* insert trace into our cache */ - err = ceph_fill_trace(mdsc->client->sb, req); + err = ceph_fill_trace(mdsc->client->sb, req, mds); if (err) goto done; if (result == 0 && req->r_expects_cap) { @@ -1446,6 +1446,33 @@ bad: } +void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct dentry *dn) +{ + struct ceph_msg *msg; + struct ceph_mds_lease *lease; + int mds = (long)dn->d_fsdata; + + if (mds < 0) { + dout(10, "lease_release dentry %p -- no lease\n", dn); + return; + } + dout(10, "lease_release dentry %p to mds%d\n", dn, mds); + + msg = ceph_msg_new(CEPH_MSG_CLIENT_LEASE, sizeof(*lease) + + sizeof(__u32) + dn->d_name.len, 0, 0, 0); + if (IS_ERR(msg)) + return; + lease = msg->front.iov_base; + lease->action = CEPH_MDS_LEASE_RELEASE; + lease->mask = CEPH_LOCK_DN; + lease->ino = cpu_to_le64(dn->d_parent->d_inode->i_ino); /* ?? */ + *(__le32*)(lease+1) = cpu_to_le32(dn->d_name.len); + memcpy((void *)(lease + 1) + 4, dn->d_name.name, dn->d_name.len); + + send_msg_mds(mdsc, msg, mds); +} + + /* * delayed work -- renew caps with mds */ diff --git a/src/kernel/mds_client.h b/src/kernel/mds_client.h index c04d03174c316..5091006c4cafc 100644 --- a/src/kernel/mds_client.h +++ b/src/kernel/mds_client.h @@ -130,6 +130,9 @@ extern int ceph_mdsc_update_cap_wanted(struct ceph_inode_info *ci, int wanted); extern void ceph_mdsc_handle_lease(struct ceph_mds_client *mdsc, struct ceph_msg *msg); +extern void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, + struct dentry *dn); + extern struct ceph_mds_request * ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, ceph_ino_t ino1, const char *path1, diff --git a/src/kernel/super.h b/src/kernel/super.h index 8e09082547882..34741ee0de3db 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -322,6 +322,7 @@ extern void ceph_update_inode_lease(struct inode *inode, unsigned long from_time); extern void ceph_update_dentry_lease(struct dentry *dentry, struct ceph_mds_reply_lease *lease, + int from_mds, unsigned long from_time); extern struct ceph_inode_cap *ceph_find_cap(struct inode *inode, int want); @@ -363,7 +364,8 @@ extern const struct file_operations ceph_dir_fops; extern struct dentry_operations ceph_dentry_ops; extern char *ceph_build_dentry_path(struct dentry *dentry, int *len); -extern int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req); +extern int ceph_fill_trace(struct super_block *sb, + struct ceph_mds_request *req, int mds); extern int ceph_do_lookup(struct super_block *sb, struct dentry *dentry, int m); static inline void ceph_init_dentry(struct dentry *dentry) { -- 2.39.5