struct inode *inode = &ci->vfs_inode;
int last = 0;
int last_snap = 0;
+ int snapc_cached = 0;
+ int found = 0;
spin_lock(&inode->i_lock);
ci->i_wrbuffer_ref -= nr;
last = !ci->i_wrbuffer_ref;
if (snapc == ci->i_snap_realm->cached_context) {
- ci->i_wrbuffer_ref_head -= nr;
- dout(30, "put_wrbuffer_cap_refs on %p head %d/%d -> %d/%d %s\n",
- inode,
- ci->i_wrbuffer_ref+nr, ci->i_wrbuffer_ref_head+nr,
- ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head,
- last ? " LAST":"");
+ snapc_cached = 1;
} else {
struct list_head *p;
struct ceph_cap_snap *capsnap = NULL;
list_for_each(p, &ci->i_cap_snaps) {
capsnap = list_entry(p, struct ceph_cap_snap, ci_item);
if (capsnap->context == snapc) {
+ found = 1;
capsnap->dirty -= nr;
last_snap = !capsnap->dirty;
break;
}
}
- BUG_ON(!capsnap);
- dout(30, "put_wrbuffer_cap_refs on %p cap_snap %p "
- " snap %lld %d/%d -> %d/%d %s%s\n",
- inode, capsnap, capsnap->context->seq,
- ci->i_wrbuffer_ref+nr, capsnap->dirty + nr,
- ci->i_wrbuffer_ref, capsnap->dirty,
- last ? " (wrbuffer last)":"",
- last_snap ? " (capsnap last)":"");
+ if (found) {
+ dout(30, "put_wrbuffer_cap_refs on %p cap_snap %p "
+ " snap %lld %d/%d -> %d/%d %s%s\n",
+ inode, capsnap, capsnap->context->seq,
+ ci->i_wrbuffer_ref+nr, capsnap->dirty + nr,
+ ci->i_wrbuffer_ref, capsnap->dirty,
+ last ? " (wrbuffer last)":"",
+ last_snap ? " (capsnap last)":"");
+ }
+ }
+
+ if (snapc_cached || !found) {
+ ci->i_wrbuffer_ref_head -= nr;
+ dout(30, "put_wrbuffer_cap_refs on %p head %d/%d -> %d/%d %s\n",
+ inode,
+ ci->i_wrbuffer_ref+nr, ci->i_wrbuffer_ref_head+nr,
+ ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head,
+ last ? " LAST":"");
}
+
spin_unlock(&inode->i_lock);
if (last) {