c |= it->second->issued;
i |= it->second->implemented;
}
+
+ // exclude caps issued by non-auth MDS, but are been revoking by
+ // the auth MDS. The non-auth MDS should be revoking/exporting
+ // these caps, but the message is delayed.
+ if (auth_cap)
+ c &= ~auth_cap->implemented | auth_cap->issued;
+
if (implemented)
*implemented = i;
return c;
touch_cap(caps[mds]);
}
-bool Inode::caps_issued_mask(unsigned mask)
+/**
+ * caps_issued_mask - check whether we have all of the caps in the mask
+ * @mask: mask to check against
+ * @allow_impl: whether the caller can also use caps that are implemented but not issued
+ *
+ * This is the bog standard "check whether we have the required caps" operation.
+ * Typically, we only check against the capset that is currently "issued".
+ * In other words, we ignore caps that have been revoked but not yet released.
+ *
+ * Some callers (particularly those doing attribute retrieval) can also make
+ * use of the full set of "implemented" caps to satisfy requests from the
+ * cache.
+ *
+ * Those callers should refrain from taking new references to implemented
+ * caps!
+ */
+bool Inode::caps_issued_mask(unsigned mask, bool allow_impl)
{
int c = snap_caps;
+ int i = 0;
+
if ((c & mask) == mask)
return true;
// prefer auth cap
return true;
}
c |= it->second->issued;
+ i |= it->second->implemented;
}
}
+
+ if (allow_impl)
+ c |= i;
+
if ((c & mask) == mask) {
// bah.. touch them all
for (map<mds_rank_t,Cap*>::iterator it = caps.begin();