[PATCH 02/23] cred: add get_cred_rcu()

From: NeilBrown
Date: Sun Dec 02 2018 - 19:32:13 EST


Sometimes we want to opportunistically get a
ref to a cred in an rcu_read_lock protected section.
get_task_cred() does this, and NFS does as similar thing
with its own credential structures.
To prepare for NFS converting to use 'struct cred' more
uniformly, define get_cred_rcu(), and use it in
get_task_cred().

Signed-off-by: NeilBrown <neilb@xxxxxxxx>
---
include/linux/cred.h | 11 +++++++++++
kernel/cred.c | 2 +-
2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/include/linux/cred.h b/include/linux/cred.h
index f1085767e1b3..48979fcb95cf 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -252,6 +252,17 @@ static inline const struct cred *get_cred(const struct cred *cred)
return get_new_cred(nonconst_cred);
}

+static inline const struct cred *get_cred_rcu(const struct cred *cred)
+{
+ struct cred *nonconst_cred = (struct cred *) cred;
+ if (!cred)
+ return NULL;
+ if (!atomic_inc_not_zero(&nonconst_cred->usage))
+ return NULL;
+ validate_creds(cred);
+ return cred;
+}
+
/**
* put_cred - Release a reference to a set of credentials
* @cred: The credentials to release
diff --git a/kernel/cred.c b/kernel/cred.c
index 0b3ac72bd717..ba60162249e8 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -195,7 +195,7 @@ const struct cred *get_task_cred(struct task_struct *task)
do {
cred = __task_cred((task));
BUG_ON(!cred);
- } while (!atomic_inc_not_zero(&((struct cred *)cred)->usage));
+ } while (!get_cred_rcu(cred));

rcu_read_unlock();
return cred;