#endif
#define DEBUG_SUBSYSTEM S_MDS
-#ifdef HAVE_KERNEL_CONFIG_H
+#ifndef AUTOCONF_INCLUDED
#include <linux/config.h>
#endif
#include <linux/module.h>
#include <linux/stat.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
-#include <asm/segment.h>
#include <libcfs/kp30.h>
#include <obd.h>
static void mdt_identity_entry_free(struct upcall_cache *cache,
struct upcall_cache_entry *entry)
{
- struct mdt_identity *identity = &entry->u.identity;
+ struct md_identity *identity = &entry->u.identity;
- if (identity->mi_ginfo)
+ if (identity->mi_ginfo) {
groups_free(identity->mi_ginfo);
+ identity->mi_ginfo = NULL;
+ }
if (identity->mi_nperms) {
LASSERT(identity->mi_perms);
OBD_FREE(identity->mi_perms,
- identity->mi_nperms * sizeof(struct mdt_setxid_perm));
+ identity->mi_nperms * sizeof(struct md_perm));
+ identity->mi_nperms = 0;
}
}
static int mdt_identity_do_upcall(struct upcall_cache *cache,
struct upcall_cache_entry *entry)
{
- char keystr[16];
+ char *upcall, keystr[16];
char *argv[] = {
[0] = cache->uc_upcall,
[1] = cache->uc_name,
[1] = "PATH=/sbin:/usr/sbin",
[2] = NULL
};
- int rc;
+ int size, rc;
ENTRY;
+ /* There is race condition:
+ * "uc_upcall" was changed just after "is_identity_get_disabled" check.
+ */
+ size = strlen(cache->uc_upcall) + 1;
+ OBD_ALLOC(upcall, size);
+ if (unlikely(!upcall))
+ RETURN(-ENOMEM);
+
+ read_lock(&cache->uc_upcall_rwlock);
+ memcpy(upcall, cache->uc_upcall, size - 1);
+ read_unlock(&cache->uc_upcall_rwlock);
+ upcall[size - 1] = 0;
+ if (unlikely(!strcmp(upcall, "NONE"))) {
+ CERROR("no upcall set\n");
+ GOTO(out, rc = -EREMCHG);
+ }
+
+ argv[0] = upcall;
+
snprintf(keystr, sizeof(keystr), LPU64, entry->ue_key);
- LASSERTF(strcmp(cache->uc_upcall, "NONE"), "no upcall set!");
CDEBUG(D_INFO, "The upcall is: %s \n", cache->uc_upcall);
rc = USERMODEHELPER(argv[0], argv, envp);
argv[0], argv[1], argv[2]);
rc = 0;
}
- RETURN(rc);
+ EXIT;
+out:
+ OBD_FREE(upcall, size);
+ return rc;
}
static int mdt_identity_parse_downcall(struct upcall_cache *cache,
struct upcall_cache_entry *entry,
void *args)
{
- struct mdt_identity *identity = &entry->u.identity;
+ struct md_identity *identity = &entry->u.identity;
struct identity_downcall_data *data = args;
struct group_info *ginfo;
- struct mdt_setxid_perm *perms = NULL;
+ struct md_perm *perms = NULL;
int size, i;
ENTRY;
RETURN(-ENOMEM);
}
- groups_from_list(ginfo, data->idd_groups);
- groups_sort(ginfo);
- identity->mi_ginfo = ginfo;
+ lustre_groups_from_list(ginfo, data->idd_groups);
+ lustre_groups_sort(ginfo);
if (data->idd_nperms) {
size = data->idd_nperms * sizeof(*perms);
if (!perms) {
CERROR("failed to alloc %d permissions\n",
data->idd_nperms);
- put_group_info(ginfo);
+ groups_free(ginfo);
RETURN(-ENOMEM);
}
+
for (i = 0; i < data->idd_nperms; i++) {
perms[i].mp_nid = data->idd_perms[i].pdd_nid;
perms[i].mp_perm = data->idd_perms[i].pdd_perm;
RETURN(0);
}
-struct mdt_identity *mdt_identity_get(struct upcall_cache *cache, __u32 uid)
+struct md_identity *mdt_identity_get(struct upcall_cache *cache, __u32 uid)
{
struct upcall_cache_entry *entry;
if (!cache)
- return NULL;
+ return ERR_PTR(-ENOENT);
entry = upcall_cache_get_entry(cache, (__u64)uid, NULL);
- if (IS_ERR(entry)) {
- CERROR("upcall_cache_get_entry failed: %ld\n", PTR_ERR(entry));
- return NULL;
- }
-
- return &entry->u.identity;
+ if (IS_ERR(entry))
+ return ERR_PTR(PTR_ERR(entry));
+ else if (unlikely(!entry))
+ return ERR_PTR(-ENOENT);
+ else
+ return &entry->u.identity;
}
-void mdt_identity_put(struct upcall_cache *cache, struct mdt_identity *identity)
+void mdt_identity_put(struct upcall_cache *cache, struct md_identity *identity)
{
if (!cache)
return;
* If there is LNET_NID_ANY in perm[i].mp_nid,
* it must be perm[0].mp_nid, and act as default perm.
*/
-__u32 mdt_identity_get_setxid_perm(struct mdt_identity *identity,
- __u32 is_rmtclient, lnet_nid_t nid)
+__u32 mdt_identity_get_perm(struct md_identity *identity,
+ __u32 is_rmtclient, lnet_nid_t nid)
{
- struct mdt_setxid_perm *perm = identity->mi_perms;
+ struct md_perm *perm;
int i;
+ if (!identity) {
+ LASSERT(is_rmtclient == 0);
+ return CFS_SETGRP_PERM;
+ }
+
+ perm = identity->mi_perms;
/* check exactly matched nid first */
for (i = identity->mi_nperms - 1; i > 0; i--) {
if (perm[i].mp_nid != nid)
return perm[0].mp_perm;
/* return default last */
- return is_rmtclient ? 0 : LUSTRE_SETGRP_PERM;
+ return is_rmtclient ? 0 : CFS_SETGRP_PERM;
}
int mdt_pack_remote_perm(struct mdt_thread_info *info, struct mdt_object *o,