Whamcloud - gitweb
Added date for the 1.6.5 release.
[fs/lustre-release.git] / lustre / mdt / mdt_identity.c
index f196570..8312040 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/stat.h>
 #include <asm/uaccess.h>
 #include <linux/slab.h>
-#include <asm/segment.h>
 
 #include <libcfs/kp30.h>
 #include <obd.h>
@@ -67,22 +66,25 @@ static void mdt_identity_entry_init(struct upcall_cache_entry *entry,
 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,
@@ -94,12 +96,30 @@ static int mdt_identity_do_upcall(struct upcall_cache *cache,
                   [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);
@@ -113,17 +133,20 @@ static int mdt_identity_do_upcall(struct upcall_cache *cache,
                        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;
 
@@ -137,9 +160,8 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
                 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);
@@ -147,9 +169,10 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
                 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;
@@ -169,23 +192,23 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
         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;
@@ -213,12 +236,18 @@ void mdt_flush_identity(struct upcall_cache *cache, int uid)
  * 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)
@@ -232,7 +261,7 @@ __u32 mdt_identity_get_setxid_perm(struct mdt_identity *identity,
                 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,