Whamcloud - gitweb
LU-14521 flr: delete mirror without volatile file
[fs/lustre-release.git] / lustre / mdt / mdt_identity.c
index 595a6d0..e1bceee 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * GPL HEADER END
  */
@@ -27,7 +23,7 @@
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2012, Intel Corporation.
+ * Copyright (c) 2011, 2016, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
 
 #define DEBUG_SUBSYSTEM S_MDS
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/kmod.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/version.h>
-#include <linux/unistd.h>
-#include <asm/uaccess.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
-#include <linux/slab.h>
-
-#include <libcfs/libcfs.h>
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_dlm.h>
-#include <lustre_lib.h>
-
 #include "mdt_internal.h"
 
 static void mdt_identity_entry_init(struct upcall_cache_entry *entry,
-                                    void *unused)
+                                   void *unused)
 {
-        entry->u.identity.mi_uc_entry = entry;
+       entry->u.identity.mi_uc_entry = entry;
 }
 
 static void mdt_identity_entry_free(struct upcall_cache *cache,
@@ -85,64 +57,70 @@ static void mdt_identity_entry_free(struct upcall_cache *cache,
 
        if (identity->mi_nperms) {
                LASSERT(identity->mi_perms);
-               OBD_FREE(identity->mi_perms,
-                        identity->mi_nperms * sizeof(struct md_perm));
+               OBD_FREE_PTR_ARRAY(identity->mi_perms, identity->mi_nperms);
                identity->mi_nperms = 0;
        }
 }
 
 static int mdt_identity_do_upcall(struct upcall_cache *cache,
-                                  struct upcall_cache_entry *entry)
+                                 struct upcall_cache_entry *entry)
 {
-        char keystr[16];
-        char *argv[] = {
-                  [0] = cache->uc_upcall,
-                  [1] = cache->uc_name,
-                  [2] = keystr,
-                  [3] = NULL
-        };
-        char *envp[] = {
-                  [0] = "HOME=/",
-                  [1] = "PATH=/sbin:/usr/sbin",
-                  [2] = NULL
-        };
-        struct timeval start, end;
-        int rc;
-        ENTRY;
-
-        /* There is race condition:
-         * "uc_upcall" was changed just after "is_identity_get_disabled" check.
-         */
-       read_lock(&cache->uc_upcall_rwlock);
-        CDEBUG(D_INFO, "The upcall is: '%s'\n", cache->uc_upcall);
-
-        if (unlikely(!strcmp(cache->uc_upcall, "NONE"))) {
-                CERROR("no upcall set\n");
-                GOTO(out, rc = -EREMCHG);
-        }
-
-        argv[0] = cache->uc_upcall;
-        snprintf(keystr, sizeof(keystr), LPU64, entry->ue_key);
-
-       do_gettimeofday(&start);
+       char keystr[16];
+       char *argv[] = {
+               [0] = cache->uc_upcall,
+               [1] = cache->uc_name,
+               [2] = keystr,
+               [3] = NULL
+       };
+       char *envp[] = {
+               [0] = "HOME=/",
+               [1] = "PATH=/sbin:/usr/sbin",
+               [2] = NULL
+       };
+       ktime_t start, end;
+       int rc;
+
+       ENTRY;
+       /* There is race condition:
+        * "uc_upcall" was changed just after "is_identity_get_disabled" check.
+        */
+       down_read(&cache->uc_upcall_rwsem);
+       CDEBUG(D_INFO, "The upcall is: '%s'\n", cache->uc_upcall);
+
+       if (unlikely(!strcmp(cache->uc_upcall, "NONE"))) {
+               rc = -EREMCHG;
+               CERROR("%s: extended identity requested for user '%llu' called with 'NONE' upcall: rc = %d\n",
+                      cache->uc_name, entry->ue_key, rc);
+               GOTO(out, rc);
+       }
+
+       if (unlikely(cache->uc_upcall[0] == '\0')) {
+               rc = -EREMCHG;
+               CERROR("%s: extended identity requested for user '%llu' called with empty upcall: rc = %d\n",
+                      cache->uc_name, entry->ue_key, rc);
+               GOTO(out, rc);
+       }
+
+       argv[0] = cache->uc_upcall;
+       snprintf(keystr, sizeof(keystr), "%llu", entry->ue_key);
+
+       start = ktime_get();
        rc = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
-       do_gettimeofday(&end);
+       end = ktime_get();
        if (rc < 0) {
-                CERROR("%s: error invoking upcall %s %s %s: rc %d; "
-                       "check /proc/fs/lustre/mdt/%s/identity_upcall, "
-                       "time %ldus\n",
-                       cache->uc_name, argv[0], argv[1], argv[2], rc,
-                       cache->uc_name, cfs_timeval_sub(&end, &start, NULL));
-        } else {
-                CDEBUG(D_HA, "%s: invoked upcall %s %s %s, time %ldus\n",
-                       cache->uc_name, argv[0], argv[1], argv[2],
-                       cfs_timeval_sub(&end, &start, NULL));
-                rc = 0;
-        }
-        EXIT;
+               CERROR("%s: error invoking upcall %s %s %s: rc %d; check /proc/fs/lustre/mdt/%s/identity_upcall, time %ldus: rc = %d\n",
+                      cache->uc_name, argv[0], argv[1], argv[2], rc,
+                      cache->uc_name, (long)ktime_us_delta(end, start), rc);
+       } else {
+               CDEBUG(D_HA, "%s: invoked upcall %s %s %s, time %ldus\n",
+                      cache->uc_name, argv[0], argv[1], argv[2],
+                      (long)ktime_us_delta(end, start));
+               rc = 0;
+       }
+       EXIT;
 out:
-       read_unlock(&cache->uc_upcall_rwlock);
-        return rc;
+       up_read(&cache->uc_upcall_rwsem);
+       return rc;
 }
 
 static int mdt_identity_parse_downcall(struct upcall_cache *cache,
@@ -153,18 +131,24 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
        struct identity_downcall_data *data = args;
        struct group_info *ginfo = NULL;
        struct md_perm *perms = NULL;
-       int size, i;
-       ENTRY;
+       int size, i, rc = 0;
 
+       ENTRY;
        LASSERT(data);
-       if (data->idd_ngroups > NGROUPS_MAX)
-               RETURN(-E2BIG);
+       if (data->idd_ngroups > NGROUPS_MAX) {
+               rc = -E2BIG;
+               CERROR("%s: UID %u groups %u > maximum %u: rc = %d\n",
+                      cache->uc_name, data->idd_uid, data->idd_ngroups, NGROUPS_MAX, rc);
+               goto out;
+       }
 
        if (data->idd_ngroups > 0) {
                ginfo = groups_alloc(data->idd_ngroups);
                if (!ginfo) {
-                       CERROR("failed to alloc %d groups\n", data->idd_ngroups);
-                       RETURN(-ENOMEM);
+                       rc = -ENOMEM;
+                       CERROR("%s: failed to alloc %d groups: rc = %d\n",
+                              cache->uc_name, data->idd_ngroups, rc);
+                       goto out;
                }
 
                lustre_groups_from_list(ginfo, data->idd_groups);
@@ -175,11 +159,12 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
                size = data->idd_nperms * sizeof(*perms);
                OBD_ALLOC(perms, size);
                if (!perms) {
-                       CERROR("failed to alloc %d permissions\n",
-                              data->idd_nperms);
-                       if (ginfo != NULL)
+                       rc = -ENOMEM;
+                       CERROR("%s: failed to alloc %d permissions: rc = %d\n",
+                              cache->uc_name, data->idd_nperms, rc);
+                       if (ginfo)
                                put_group_info(ginfo);
-                       RETURN(-ENOMEM);
+                       goto out;
                }
 
                for (i = 0; i < data->idd_nperms; i++) {
@@ -198,111 +183,75 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
               identity, identity->mi_uid, identity->mi_gid,
               data->idd_ngroups, data->idd_nperms);
 
-       RETURN(0);
+out:
+       RETURN(rc);
 }
 
 struct md_identity *mdt_identity_get(struct upcall_cache *cache, __u32 uid)
 {
-        struct upcall_cache_entry *entry;
-
-        if (!cache)
-                return ERR_PTR(-ENOENT);
-
-        entry = upcall_cache_get_entry(cache, (__u64)uid, NULL);
-        if (IS_ERR(entry))
-                return ERR_PTR(PTR_ERR(entry));
-        else if (unlikely(!entry))
-                return ERR_PTR(-ENOENT);
-        else
-                return &entry->u.identity;
+       struct upcall_cache_entry *entry;
+
+       if (!cache)
+               return ERR_PTR(-ENOENT);
+
+       entry = upcall_cache_get_entry(cache, (__u64)uid, NULL);
+       if (unlikely(!entry))
+               return ERR_PTR(-ENOENT);
+       if (IS_ERR(entry))
+               return ERR_CAST(entry);
+
+       return &entry->u.identity;
 }
 
 void mdt_identity_put(struct upcall_cache *cache, struct md_identity *identity)
 {
-        if (!cache)
-                return;
+       if (!cache)
+               return;
 
-        LASSERT(identity);
-        upcall_cache_put_entry(cache, identity->mi_uc_entry);
+       LASSERT(identity);
+       upcall_cache_put_entry(cache, identity->mi_uc_entry);
 }
 
 struct upcall_cache_ops mdt_identity_upcall_cache_ops = {
-        .init_entry     = mdt_identity_entry_init,
-        .free_entry     = mdt_identity_entry_free,
-        .do_upcall      = mdt_identity_do_upcall,
-        .parse_downcall = mdt_identity_parse_downcall,
+       .init_entry     = mdt_identity_entry_init,
+       .free_entry     = mdt_identity_entry_free,
+       .do_upcall      = mdt_identity_do_upcall,
+       .parse_downcall = mdt_identity_parse_downcall,
 };
 
 void mdt_flush_identity(struct upcall_cache *cache, int uid)
 {
-        if (uid < 0)
-                upcall_cache_flush_idle(cache);
-        else
-                upcall_cache_flush_one(cache, (__u64)uid, NULL);
+       if (uid < 0)
+               upcall_cache_flush_idle(cache);
+       else
+               upcall_cache_flush_one(cache, (__u64)uid, NULL);
 }
 
 /*
  * 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_perm(struct md_identity *identity,
-                            __u32 is_rmtclient, lnet_nid_t nid)
-{
-        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)
-                        continue;
-                return perm[i].mp_perm;
-        }
-
-        /* check LNET_NID_ANY then */
-        if ((identity->mi_nperms > 0) &&
-            ((perm[0].mp_nid == nid) || (perm[0].mp_nid == LNET_NID_ANY)))
-                return perm[0].mp_perm;
-
-        /* return default last */
-        return is_rmtclient ? 0 : CFS_SETGRP_PERM;
-}
-
-int mdt_pack_remote_perm(struct mdt_thread_info *info, struct mdt_object *o,
-                         void *buf)
+__u32 mdt_identity_get_perm(struct md_identity *identity, lnet_nid_t nid)
 {
-       struct lu_ucred         *uc = mdt_ucred_check(info);
-        struct md_object        *next = mdt_object_child(o);
-        struct mdt_remote_perm  *perm = buf;
-
-        ENTRY;
-
-        /* remote client request always pack ptlrpc_user_desc! */
-        LASSERT(perm);
-
-        if (!exp_connect_rmtclient(info->mti_exp))
-                RETURN(-EBADE);
-
-       if (uc == NULL)
-               RETURN(-EINVAL);
-
-       perm->rp_uid = uc->uc_o_uid;
-       perm->rp_gid = uc->uc_o_gid;
-       perm->rp_fsuid = uc->uc_o_fsuid;
-       perm->rp_fsgid = uc->uc_o_fsgid;
+       struct md_perm *perm;
+       int i;
+
+       if (!identity)
+               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)
+                       continue;
+               return perm[i].mp_perm;
+       }
 
-        perm->rp_access_perm = 0;
-        if (mo_permission(info->mti_env, NULL, next, NULL, MAY_READ) == 0)
-                perm->rp_access_perm |= MAY_READ;
-        if (mo_permission(info->mti_env, NULL, next, NULL, MAY_WRITE) == 0)
-                perm->rp_access_perm |= MAY_WRITE;
-        if (mo_permission(info->mti_env, NULL, next, NULL, MAY_EXEC) == 0)
-                perm->rp_access_perm |= MAY_EXEC;
+       /* check LNET_NID_ANY then */
+       if ((identity->mi_nperms > 0) &&
+           ((perm[0].mp_nid == nid) || (perm[0].mp_nid == LNET_NID_ANY)))
+               return perm[0].mp_perm;
 
-        RETURN(0);
+       /* return default last */
+       return CFS_SETGRP_PERM;
 }