/* Check for the common case first: We got back the same access as last *timewetriedandalreadyhaveitrecorded.
*/
permits = rcu_dereference(vnode->permit_cache); if (permits) { if (!permits->invalidated) { for (i = 0; i < permits->nr_permits; i++) { if (permits->permits[i].key < key) continue; if (permits->permits[i].key > key) break; if (permits->permits[i].access != caller_access) {
changed = true; break;
}
if (afs_cb_is_broken(cb_break, vnode)) {
changed = true; break;
}
/* The cache is still good. */
rcu_read_unlock(); return;
}
}
/* If this set of permits is now wrong, clear the permits *pointersothatnoonetriestousethestaleinformation.
*/ if (changed) {
spin_lock(&vnode->lock); if (permits != rcu_access_pointer(vnode->permit_cache)) goto someone_else_changed_it_unlock;
RCU_INIT_POINTER(vnode->permit_cache, NULL);
spin_unlock(&vnode->lock);
if (afs_cb_is_broken(cb_break, vnode)) goto someone_else_changed_it;
/* We need a ref on any permits list we want to copy as we'll have to *dropthelocktodomemoryallocation.
*/ if (permits && !refcount_inc_not_zero(&permits->usage)) goto someone_else_changed_it;
rcu_read_unlock();
/* Speculatively create a new list with the revised permission set. We *discardthisifwefindanextantmatchalreadyinthehash,but *it'seasiertocomparewithmemcmpthisway. * *Wefillinthekeypointersatthistime,butwedon'tgettherefs *yet.
*/
size++; new = kzalloc(struct_size(new, permits, size), GFP_NOFS); if (!new) goto out_put;
refcount_set(&new->usage, 1); new->nr_permits = size;
i = j = 0; if (permits) { for (i = 0; i < permits->nr_permits; i++) { if (j == i && permits->permits[i].key > key) { new->permits[j].key = key; new->permits[j].access = caller_access;
j++;
} new->permits[j].key = permits->permits[i].key; new->permits[j].access = permits->permits[i].access;
j++;
}
}
if (refcount_inc_not_zero(&xpermits->usage)) {
replacement = xpermits; goto found;
}
break;
}
for (i = 0; i < new->nr_permits; i++)
key_get(new->permits[i].key);
hash_add_rcu(afs_permits_cache, &new->hash_node, new->h);
replacement = new; new = NULL;
someone_else_changed_it_unlock:
spin_unlock(&vnode->lock);
someone_else_changed_it: /* Someone else changed the cache under us - don't recheck at this *time.
*/
rcu_read_unlock(); return;
}
/* check the permits to see if we've got one yet */ if (key == vnode->volume->cell->anonymous_key) {
*_access = vnode->status.anon_access;
_leave(" = t [anon %x]", *_access); returntrue;
}
permits = rcu_dereference(vnode->permit_cache); if (permits) { for (i = 0; i < permits->nr_permits; i++) { if (permits->permits[i].key < key) continue; if (permits->permits[i].key > key) break;
/* check the permits to see if we've got one yet */ if (key == vnode->volume->cell->anonymous_key) {
_debug("anon");
*_access = vnode->status.anon_access;
valid = true;
} else {
rcu_read_lock();
permits = rcu_dereference(vnode->permit_cache); if (permits) { for (i = 0; i < permits->nr_permits; i++) { if (permits->permits[i].key < key) continue; if (permits->permits[i].key > key) break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.