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);
}
/* 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)
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.
*/
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);
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);
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);
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.
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;
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;
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);
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)
used = wanted = 0;
}
- __ceph_mdsc_send_cap(mdsc, session, cap, used, wanted, 1, 0);
+ __ceph_mdsc_send_cap(mdsc, session, cap, used, wanted, 0);
}
}
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
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);