struct ceph_cap *cap;
int mds = session->s_mds;
int is_first = 0;
- unsigned long duration;
dout(10, "add_cap %p mds%d cap %llx %s seq %d\n", inode,
session->s_mds, cap_id, ceph_cap_string(issued), seq);
cap->mseq = mseq;
cap->gen = session->s_cap_gen;
- duration = ttl_ms * HZ / 1000;
- cap->expires = ttl_from + duration;
- cap->renew_after = ttl_from + (duration >> 1);
- dout(30, " expires %lu, renew_after %lu (duration %lu, %u ms)\n",
- cap->expires, cap->renew_after, duration, ttl_ms);
-
if (fmode >= 0)
__ceph_get_fmode(ci, fmode);
spin_unlock(&inode->i_lock);
return 1;
}
+/*
+ * Touch cap timestamp and, if clean, move to end of lru.
+ */
+void __touch_cap(struct ceph_cap *cap)
+{
+ cap->last_used = jiffies;
+ if (!list_empty(&cap->session_clean_caps)) {
+ spin_lock(&cap->session->s_clean_caps_lock);
+ list_del_init(&cap->session_clean_caps);
+ list_add(&cap->session_clean_caps, &cap->session->s_clean_caps);
+ spin_unlock(&cap->session->s_clean_caps_lock);
+ }
+}
+
/*
* Return set of valid cap bits issued to us. Note that caps time
* out, and may be invalidated in bulk if the client session times out
have |= cap->issued;
if (implemented)
*implemented |= cap->implemented;
+
+ __touch_cap(cap);
}
return have;
}
struct ceph_cap *cap;
int file_wanted, used;
int took_snap_rwsem = 0; /* true if mdsc->snap_rwsem held */
+ int drop_session_lock = session ? 0:1;
int want, retain, revoking, dirty, op;
int mds = -1; /* keep track of how far we've gone through i_caps list
to avoid an infinite loop on retry */
}
spin_unlock(&inode->i_lock);
- if (session)
+ if (session && drop_session_lock)
mutex_unlock(&session->s_mutex);
if (took_snap_rwsem)
up_read(&mdsc->snap_rwsem);
ceph_send_msg_mds(mdsc, msg, mds);
} else if (r == 2) {
ceph_check_caps(ceph_inode(inode), 1, 0, session);
- goto done_unlocked;
}
break;
done:
mutex_unlock(&session->s_mutex);
-done_unlocked:
ceph_put_mds_session(session);
kfree(xattr_data);
struct inode *inode;
struct ceph_cap *cap;
struct list_head *p, *n;
+ unsigned long cutoff = jiffies - HZ * 30; /* fixme */
dout(10, "trim_clean_caps for mds%d\n", session->s_mds);
- /*
- spin_lock(&session->s_rdcaps_lock);
- list_for_each_safe(p, n, &session->s_rdcaps) {
- int wanted, last_cap;
-
- cap = list_entry(p, struct ceph_cap, session_rdcaps);
- spin_unlock(&session->s_rdcaps_lock);
-
+ spin_lock(&session->s_clean_caps_lock);
+ list_for_each_safe(p, n, &session->s_clean_caps) {
+ cap = list_entry(p, struct ceph_cap, session_clean_caps);
inode = &cap->ci->vfs_inode;
- spin_lock(&inode->i_lock);
+ igrab(inode);
+ spin_unlock(&session->s_clean_caps_lock);
- if (time_before(jiffies, cap->expires)) {
- dout(20, " stopping at %p cap %p expires %lu > %lu\n",
- inode, cap, cap->expires, jiffies);
+ spin_lock(&inode->i_lock);
+ if (time_before(cutoff, cap->last_used)) {
+ dout(20, " stopping at %p cap %p last_used %lu > %lu\n",
+ inode, cap, cap->last_used, cutoff);
spin_unlock(&inode->i_lock);
+ iput(inode);
return;
}
-
- wanted = __ceph_caps_wanted(cap->ci);
- dout(20, " dropping %p cap %p %s wanted %s\n", inode,
- cap, ceph_cap_string(cap->issued),
- ceph_cap_string(wanted));
- BUG_ON(wanted);
- last_cap = __ceph_remove_cap(cap);
spin_unlock(&inode->i_lock);
- if (last_cap)
- iput(inode);
-
- spin_lock(&session->s_rdcaps_lock);
+ ceph_check_caps(cap->ci, 1, CEPH_CAP_ANY, session);
+ iput(inode);
+ spin_lock(&session->s_clean_caps_lock);
}
- spin_unlock(&session->s_rdcaps_lock);
- */
+ spin_unlock(&session->s_clean_caps_lock);
}
/*