From b12f6efa270529474f523fd67a3341ea2ce85561 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 19 Aug 2008 14:03:56 -0700 Subject: [PATCH] kclient: close out caps on RELEASED, not release request --- src/kernel/inode.c | 71 +++++++++++++++++++++++++++++++++++------ src/kernel/mds_client.c | 38 ++++++++-------------- src/kernel/mds_client.h | 2 +- src/kernel/super.h | 6 ++++ 4 files changed, 82 insertions(+), 35 deletions(-) diff --git a/src/kernel/inode.c b/src/kernel/inode.c index 44ee8acdede9d..ed81dd0942834 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -1339,7 +1339,6 @@ void ceph_check_caps(struct ceph_inode_info *ci, int is_delayed, int flush_snap) int wanted, used; struct ceph_mds_session *session = 0; /* if non-NULL, i hold s_mutex */ int took_snap_rwsem = 0; /* true if mdsc->snap_rwsem held */ - int removed_last; retry: spin_lock(&inode->i_lock); @@ -1432,19 +1431,15 @@ ack: } /* send_cap drops i_lock */ - removed_last = __ceph_mdsc_send_cap(mdsc, session, cap, - used, wanted, !is_delayed, - flush_snap); - if (removed_last) - goto out; - /* retake i_lock and restart our cap scan. */ - goto retry; + __ceph_mdsc_send_cap(mdsc, session, cap, + used, wanted, flush_snap); + + goto retry; /* retake i_lock and restart our cap scan. */ } /* okay */ spin_unlock(&inode->i_lock); -out: if (session) mutex_unlock(&session->s_mutex); if (took_snap_rwsem) @@ -1678,6 +1673,61 @@ void __ceph_do_pending_vmtruncate(struct inode *inode) dout(10, "__do_pending_vmtruncate %p nothing to do\n", inode); } +/* + * caller hold s_mutex, snap_rwsem. + */ +static void __cap_delay_cancel(struct ceph_mds_client *mdsc, + struct ceph_inode_info *ci) +{ + dout(10, "__cap_delay_cancel %p\n", &ci->vfs_inode); + if (list_empty(&ci->i_cap_delay_list)) + return; + spin_lock(&mdsc->cap_delay_lock); + list_del_init(&ci->i_cap_delay_list); + spin_unlock(&mdsc->cap_delay_lock); + iput(&ci->vfs_inode); +} + +void ceph_handle_cap_released(struct inode *inode, + struct ceph_mds_caps *m, + struct ceph_mds_session *session) +{ + struct ceph_inode_info *ci = ceph_inode(inode); + int seq = le32_to_cpu(m->seq); + int removed_last; + struct ceph_inode_cap *cap; + + dout(10, "handle_cap_released inode %p ci %p mds%d seq %d\n", inode, ci, + session->s_mds, seq); + + spin_lock(&inode->i_lock); + cap = __get_cap_for_mds(inode, session->s_mds); + BUG_ON(!cap); + removed_last = __ceph_remove_cap(cap); + if (removed_last) + __cap_delay_cancel(&ceph_inode_to_client(inode)->mdsc, ci); + spin_unlock(&inode->i_lock); + if (removed_last) + iput(inode); +} + +/* + * caller hold s_mutex, snap_rwsem. + */ +void ceph_handle_cap_flushedsnap(struct inode *inode, + struct ceph_mds_caps *m, + struct ceph_mds_session *session) +{ + struct ceph_inode_info *ci = ceph_inode(inode); + int seq = le32_to_cpu(m->seq); + + dout(10, "handle_cap_flushednsap inode %p ci %p mds%d seq %d\n", inode, + ci, session->s_mds, seq); + + /* **** WRITE ME **** */ +} + + /* * caller hold s_mutex, NOT snap_rwsem. */ @@ -1758,7 +1808,8 @@ void ceph_handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, ci->i_cap_exporting_mseq = mseq; ci->i_cap_exporting_issued = cap->issued; was_last = __ceph_remove_cap(cap); - } + } else + WARN_ON(!cap); out: spin_unlock(&inode->i_lock); diff --git a/src/kernel/mds_client.c b/src/kernel/mds_client.c index 6472263214d3a..0d4fd879bfd4c 100644 --- a/src/kernel/mds_client.c +++ b/src/kernel/mds_client.c @@ -1490,7 +1490,7 @@ static void send_cap_ack(struct ceph_mds_client *mdsc, __u64 ino, int op, memset(fc, 0, sizeof(*fc)); - fc->op = cpu_to_le32(CEPH_CAP_OP_ACK); /* misnomer */ + fc->op = cpu_to_le32(op); fc->seq = cpu_to_le64(seq); fc->migrate_seq = cpu_to_le64(mseq); fc->caps = cpu_to_le32(caps); @@ -1573,6 +1573,16 @@ void ceph_mdsc_handle_caps(struct ceph_mds_client *mdsc, ceph_handle_cap_trunc(inode, h, session); break; + case CEPH_CAP_OP_RELEASED: + ceph_handle_cap_released(inode, h, session); + up_write(&mdsc->snap_rwsem); + break; + + case CEPH_CAP_OP_FLUSHEDSNAP: + ceph_handle_cap_flushedsnap(inode, h, session); + up_write(&mdsc->snap_rwsem); + break; + case CEPH_CAP_OP_EXPORT: ceph_handle_cap_export(inode, h, session); up_write(&mdsc->snap_rwsem); @@ -1601,18 +1611,6 @@ bad: return; } -static void __cap_delay_cancel(struct ceph_mds_client *mdsc, - struct ceph_inode_info *ci) -{ - dout(10, "__cap_delay_cancel %p\n", &ci->vfs_inode); - if (list_empty(&ci->i_cap_delay_list)) - return; - spin_lock(&mdsc->cap_delay_lock); - list_del_init(&ci->i_cap_delay_list); - spin_unlock(&mdsc->cap_delay_lock); - iput(&ci->vfs_inode); -} - /* * called with i_lock, then drops it. * caller should hold snap_rwsem, s_mutex. @@ -1623,7 +1621,7 @@ int __ceph_mdsc_send_cap(struct ceph_mds_client *mdsc, struct ceph_mds_session *session, struct ceph_inode_cap *cap, int used, int wanted, - int cancel_work, int flush_snap) + int flush_snap) { struct ceph_inode_info *ci = cap->ci; struct inode *inode = &ci->vfs_inode; @@ -1633,7 +1631,6 @@ int __ceph_mdsc_send_cap(struct ceph_mds_client *mdsc, u64 seq, mseq, time_warp_seq, follows; u64 size, max_size; struct timespec mtime, atime; - int removed_last = 0; int wake = 0; int op = CEPH_CAP_OP_ACK; @@ -1662,11 +1659,6 @@ int __ceph_mdsc_send_cap(struct ceph_mds_client *mdsc, atime = inode->i_atime; time_warp_seq = ci->i_time_warp_seq; follows = ci->i_snaprealm->cached_context->seq; - if (wanted == 0 && !flush_snap) { - removed_last = __ceph_remove_cap(cap); - if (removed_last && cancel_work) - __cap_delay_cancel(mdsc, ci); - } if (flush_snap) cap->flushed_snap = follows; /* so we only flush it once */ spin_unlock(&inode->i_lock); @@ -1687,10 +1679,8 @@ int __ceph_mdsc_send_cap(struct ceph_mds_client *mdsc, if (wake) wake_up(&ci->i_cap_wq); - if (removed_last) - iput(inode); /* removed cap */ - return removed_last; + return 0; } static void check_delayed_caps(struct ceph_mds_client *mdsc) @@ -1744,7 +1734,7 @@ static void flush_write_caps(struct ceph_mds_client *mdsc, used = wanted = 0; } - __ceph_mdsc_send_cap(mdsc, session, cap, used, wanted, 1, 0); + __ceph_mdsc_send_cap(mdsc, session, cap, used, wanted, 0); } } diff --git a/src/kernel/mds_client.h b/src/kernel/mds_client.h index 7d9df4f3831eb..f15c9fe117bdb 100644 --- a/src/kernel/mds_client.h +++ b/src/kernel/mds_client.h @@ -185,7 +185,7 @@ extern int __ceph_mdsc_send_cap(struct ceph_mds_client *mdsc, struct ceph_mds_session *session, struct ceph_inode_cap *cap, int used, int wanted, - int cancel_work, int flush_snap); + int flush_snap); extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc); #endif diff --git a/src/kernel/super.h b/src/kernel/super.h index 05d591d87a9c3..d2fa359e9409f 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -552,6 +552,12 @@ extern int ceph_handle_cap_grant(struct inode *inode, extern void ceph_handle_cap_trunc(struct inode *inode, struct ceph_mds_caps *trunc, struct ceph_mds_session *session); +extern void ceph_handle_cap_released(struct inode *inode, + struct ceph_mds_caps *trunc, + struct ceph_mds_session *session); +extern void ceph_handle_cap_flushedsnap(struct inode *inode, + struct ceph_mds_caps *trunc, + struct ceph_mds_session *session); extern void ceph_handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, struct ceph_mds_session *session); -- 2.39.5