afs: Provide an RCU-capable key lookup
Provide an RCU-capable key lookup function. We don't want to call afs_request_key() in RCU-mode pathwalk as request_key() might sleep, even if we don't ask it to construct anything as it might find a key that is currently undergoing construction. Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
Родитель
23a289137a
Коммит
8b6a666a97
|
@ -1217,6 +1217,7 @@ extern void afs_cache_permit(struct afs_vnode *, struct key *, unsigned int,
|
|||
struct afs_status_cb *);
|
||||
extern void afs_zap_permits(struct rcu_head *);
|
||||
extern struct key *afs_request_key(struct afs_cell *);
|
||||
extern struct key *afs_request_key_rcu(struct afs_cell *);
|
||||
extern int afs_check_permit(struct afs_vnode *, struct key *, afs_access_t *);
|
||||
extern int afs_permission(struct inode *, int);
|
||||
extern void __exit afs_clean_up_permit_cache(void);
|
||||
|
|
|
@ -27,8 +27,37 @@ struct key *afs_request_key(struct afs_cell *cell)
|
|||
_enter("{%x}", key_serial(cell->anonymous_key));
|
||||
|
||||
_debug("key %s", cell->anonymous_key->description);
|
||||
key = request_key(&key_type_rxrpc, cell->anonymous_key->description,
|
||||
NULL);
|
||||
key = request_key_net(&key_type_rxrpc, cell->anonymous_key->description,
|
||||
cell->net->net, NULL);
|
||||
if (IS_ERR(key)) {
|
||||
if (PTR_ERR(key) != -ENOKEY) {
|
||||
_leave(" = %ld", PTR_ERR(key));
|
||||
return key;
|
||||
}
|
||||
|
||||
/* act as anonymous user */
|
||||
_leave(" = {%x} [anon]", key_serial(cell->anonymous_key));
|
||||
return key_get(cell->anonymous_key);
|
||||
} else {
|
||||
/* act as authorised user */
|
||||
_leave(" = {%x} [auth]", key_serial(key));
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a key when pathwalk is in rcuwalk mode.
|
||||
*/
|
||||
struct key *afs_request_key_rcu(struct afs_cell *cell)
|
||||
{
|
||||
struct key *key;
|
||||
|
||||
_enter("{%x}", key_serial(cell->anonymous_key));
|
||||
|
||||
_debug("key %s", cell->anonymous_key->description);
|
||||
key = request_key_net_rcu(&key_type_rxrpc,
|
||||
cell->anonymous_key->description,
|
||||
cell->net->net);
|
||||
if (IS_ERR(key)) {
|
||||
if (PTR_ERR(key) != -ENOKEY) {
|
||||
_leave(" = %ld", PTR_ERR(key));
|
||||
|
|
|
@ -324,7 +324,7 @@ static inline struct key *request_key(struct key_type *type,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_NET
|
||||
/*
|
||||
/**
|
||||
* request_key_net - Request a key for a net namespace and wait for construction
|
||||
* @type: Type of key.
|
||||
* @description: The searchable description of the key.
|
||||
|
@ -341,6 +341,18 @@ static inline struct key *request_key(struct key_type *type,
|
|||
*/
|
||||
#define request_key_net(type, description, net, callout_info) \
|
||||
request_key_tag(type, description, net->key_domain, callout_info);
|
||||
|
||||
/**
|
||||
* request_key_net_rcu - Request a key for a net namespace under RCU conditions
|
||||
* @type: Type of key.
|
||||
* @description: The searchable description of the key.
|
||||
* @net: The network namespace that is the key's domain of operation.
|
||||
*
|
||||
* As for request_key_rcu() except that only keys that operate the specified
|
||||
* network namespace are used.
|
||||
*/
|
||||
#define request_key_net_rcu(type, description, net) \
|
||||
request_key_rcu(type, description, net->key_domain);
|
||||
#endif /* CONFIG_NET */
|
||||
|
||||
extern int wait_for_key_construction(struct key *key, bool intr);
|
||||
|
|
Загрузка…
Ссылка в новой задаче