}
}
-bool CInode::split_need_snapflush(CInode *cowin, CInode *in)
+pair<bool,bool> CInode::split_need_snapflush(CInode *cowin, CInode *in)
{
dout(10) << __func__ << " [" << cowin->first << "," << cowin->last << "] for " << *cowin << dendl;
- bool need_flush = false;
- for (auto it = client_need_snapflush.lower_bound(cowin->first);
- it != client_need_snapflush.end() && it->first < in->first; ) {
+ bool cowin_need_flush = false;
+ bool orig_need_flush = false;
+ auto it = client_need_snapflush.lower_bound(cowin->first);
+ while (it != client_need_snapflush.end() && it->first < in->first) {
ceph_assert(!it->second.empty());
if (cowin->last >= it->first) {
cowin->auth_pin(this);
- need_flush = true;
+ cowin_need_flush = true;
++it;
} else {
it = client_need_snapflush.erase(it);
}
in->auth_unpin(this);
}
- return need_flush;
+
+ if (it != client_need_snapflush.end() && it->first <= in->last)
+ orig_need_flush = true;
+
+ return make_pair(cowin_need_flush, orig_need_flush);
}
void CInode::mark_dirty_rstat()
void add_need_snapflush(CInode *snapin, snapid_t snapid, client_t client);
void remove_need_snapflush(CInode *snapin, snapid_t snapid, client_t client);
- bool split_need_snapflush(CInode *cowin, CInode *in);
+ pair<bool,bool> split_need_snapflush(CInode *cowin, CInode *in);
protected:
if (in->last != CEPH_NOSNAP) {
CInode *head_in = get_inode(in->ino());
ceph_assert(head_in);
- if (head_in->split_need_snapflush(oldin, in)) {
+ auto ret = head_in->split_need_snapflush(oldin, in);
+ if (ret.first) {
oldin->client_snap_caps = in->client_snap_caps;
- for (const auto &p : in->client_snap_caps) {
+ for (const auto &p : oldin->client_snap_caps) {
SimpleLock *lock = oldin->get_lock(p.first);
ceph_assert(lock);
for (const auto &q : p.second) {
- oldin->auth_pin(lock);
- lock->set_state(LOCK_SNAP_SYNC); // gathering
+ if (lock->get_state() != LOCK_SNAP_SYNC) {
+ ceph_assert(lock->is_stable());
+ lock->set_state(LOCK_SNAP_SYNC); // gathering
+ oldin->auth_pin(lock);
+ }
lock->get_wrlock(true);
- (void)q; /* unused */
+ (void)q; /* unused */
}
}
}
+ if (!ret.second) {
+ auto client_snap_caps = std::move(in->client_snap_caps);
+ in->client_snap_caps.clear();
+ in->item_open_file.remove_myself();
+ in->item_caps.remove_myself();
+ for (const auto &p : client_snap_caps) {
+ SimpleLock *lock = in->get_lock(p.first);
+ ceph_assert(lock);
+ ceph_assert(lock->get_state() == LOCK_SNAP_SYNC); // gathering
+ for (const auto &q : p.second) {
+ lock->put_wrlock();
+ (void)q; /* unused */
+ }
+ ceph_assert(!lock->get_num_wrlocks());
+ lock->set_state(LOCK_SYNC);
+ in->auth_unpin(lock);
+ }
+ }
return oldin;
}
int lockid = cinode_lock_info[i].lock;
SimpleLock *lock = oldin->get_lock(lockid);
ceph_assert(lock);
- oldin->client_snap_caps[lockid].insert(client);
- oldin->auth_pin(lock);
- lock->set_state(LOCK_SNAP_SYNC); // gathering
+ if (lock->get_state() != LOCK_SNAP_SYNC) {
+ ceph_assert(lock->is_stable());
+ lock->set_state(LOCK_SNAP_SYNC); // gathering
+ oldin->auth_pin(lock);
+ }
lock->get_wrlock(true);
+ oldin->client_snap_caps[lockid].insert(client);
dout(10) << " client." << client << " cap " << ccap_string(issued & cinode_lock_info[i].wr_caps)
<< " wrlock lock " << *lock << " on " << *oldin << dendl;
}