Whamcloud - gitweb
b=16890 a build fix for --disable-quota
[fs/lustre-release.git] / lustre / mdt / mdt_idmap.c
index fb81041..ad1bdb5 100644 (file)
@@ -1,25 +1,42 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- * Copyright (C) 2004-2006 Cluster File Systems, Inc.
- *   Author: Lai Siyao <lsy@clusterfs.com>
- *   Author: Fan Yong <fanyong@clusterfs.com>
+ * GPL HEADER START
  *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *   This file is part of Lustre, http://www.lustre.org.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
  *
- *   Lustre is free software; you can redistribute it and/or
- *   modify it under the terms of version 2 of the GNU General Public
- *   License as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
  *
- *   Lustre is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
+ * 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
  *
- *   You should have received a copy of the GNU General Public License
- *   along with Lustre; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * lustre/mdt/mdt_idmap.c
+ *
+ * Author: Lai Siyao <lsy@clusterfs.com>
+ * Author: Fan Yong <fanyong@clusterfs.com>
  */
 
 #ifndef EXPORT_SYMTAB
@@ -27,7 +44,9 @@
 #endif
 #define DEBUG_SUBSYSTEM S_MDS
 
+#ifndef AUTOCONF_INCLUDED
 #include <linux/config.h>
+#endif
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -44,7 +63,7 @@
 #include <asm/uaccess.h>
 #include <linux/slab.h>
 
-#include <libcfs/kp30.h>
+#include <libcfs/libcfs.h>
 #include <obd.h>
 #include <obd_class.h>
 #include <obd_support.h>
 
 #include "mdt_internal.h"
 
-int mdt_init_idmap(struct mdt_thread_info *info)
+#define mdt_init_sec_none(reply, exp)                                   \
+do {                                                                    \
+        reply->ocd_connect_flags &= ~(OBD_CONNECT_RMT_CLIENT |          \
+                                      OBD_CONNECT_RMT_CLIENT_FORCE |    \
+                                      OBD_CONNECT_MDS_CAPA |            \
+                                      OBD_CONNECT_OSS_CAPA);            \
+        cfs_spin_lock(&exp->exp_lock);                                  \
+        exp->exp_connect_flags = reply->ocd_connect_flags;              \
+        cfs_spin_unlock(&exp->exp_lock);                                \
+} while (0)
+
+int mdt_init_sec_level(struct mdt_thread_info *info)
 {
+        struct mdt_device *mdt = info->mti_mdt;
         struct ptlrpc_request *req = mdt_info_req(info);
         char *client = libcfs_nid2str(req->rq_peer.nid);
-        struct mdt_export_data *med = mdt_req2med(req);
-        struct obd_device *obd = req->rq_export->exp_obd;
+        struct obd_export *exp = req->rq_export;
+        struct obd_device *obd = exp->exp_obd;
         struct obd_connect_data *data, *reply;
         int rc = 0, remote;
         ENTRY;
@@ -72,30 +103,120 @@ int mdt_init_idmap(struct mdt_thread_info *info)
         if (data == NULL || reply == NULL)
                 RETURN(-EFAULT);
 
-        if (!req->rq_auth_gss || req->rq_auth_usr_mdt) {
-                med->med_rmtclient = 0;
-                reply->ocd_connect_flags &= ~OBD_CONNECT_RMT_CLIENT;
+        /* connection from MDT is always trusted */
+        if (req->rq_auth_usr_mdt) {
+                mdt_init_sec_none(reply, exp);
                 RETURN(0);
         }
 
-        remote = data->ocd_connect_flags & OBD_CONNECT_RMT_CLIENT;
+        /* no GSS support case */
+        if (!req->rq_auth_gss) {
+                if (mdt->mdt_sec_level > LUSTRE_SEC_NONE) {
+                        CWARN("client %s -> target %s does not user GSS, "
+                              "can not run under security level %d.\n",
+                              client, obd->obd_name, mdt->mdt_sec_level);
+                        RETURN(-EACCES);
+                } else {
+                        mdt_init_sec_none(reply, exp);
+                        RETURN(0);
+                }
+        }
+
+        /* old version case */
+        if (unlikely(!(data->ocd_connect_flags & OBD_CONNECT_RMT_CLIENT) ||
+                     !(data->ocd_connect_flags & OBD_CONNECT_MDS_CAPA) ||
+                     !(data->ocd_connect_flags & OBD_CONNECT_OSS_CAPA))) {
+                if (mdt->mdt_sec_level > LUSTRE_SEC_NONE) {
+                        CWARN("client %s -> target %s uses old version, "
+                              "can not run under security level %d.\n",
+                              client, obd->obd_name, mdt->mdt_sec_level);
+                        RETURN(-EACCES);
+                } else {
+                        CWARN("client %s -> target %s uses old version, "
+                              "run under security level %d.\n",
+                              client, obd->obd_name, mdt->mdt_sec_level);
+                        mdt_init_sec_none(reply, exp);
+                        RETURN(0);
+                }
+        }
 
+        remote = data->ocd_connect_flags & OBD_CONNECT_RMT_CLIENT_FORCE;
         if (remote) {
-                med->med_rmtclient = 1;
                 if (!req->rq_auth_remote)
                         CDEBUG(D_SEC, "client (local realm) %s -> target %s "
-                               "asked to be remote!\n", client, obd->obd_name);
+                               "asked to be remote.\n", client, obd->obd_name);
         } else if (req->rq_auth_remote) {
-                med->med_rmtclient = 1;
-                CDEBUG(D_SEC, "client (remote realm) %s -> target %s forced "
-                       "to be remote!\n", client, obd->obd_name);
+                remote = 1;
+                CDEBUG(D_SEC, "client (remote realm) %s -> target %s is set "
+                       "as remote by default.\n", client, obd->obd_name);
         }
 
-        if (med->med_rmtclient) {
-                down(&med->med_idmap_sem);
+        if (remote) {
+                if (!mdt->mdt_opts.mo_oss_capa) {
+                        CDEBUG(D_SEC, "client %s -> target %s is set as remote,"
+                               " but OSS capabilities are not enabled: %d.\n",
+                               client, obd->obd_name, mdt->mdt_opts.mo_oss_capa);
+                        RETURN(-EACCES);
+                }
+        } else {
+                if (req->rq_auth_uid == INVALID_UID) {
+                        CDEBUG(D_SEC, "client %s -> target %s: user is not "
+                               "authenticated!\n", client, obd->obd_name);
+                        RETURN(-EACCES);
+                }
+        }
+
+        switch (mdt->mdt_sec_level) {
+        case LUSTRE_SEC_NONE:
+                if (!remote) {
+                        mdt_init_sec_none(reply, exp);
+                        break;
+                } else {
+                        CDEBUG(D_SEC, "client %s -> target %s is set as remote, "
+                               "can not run under security level %d.\n",
+                               client, obd->obd_name, mdt->mdt_sec_level);
+                        RETURN(-EACCES);
+                }
+        case LUSTRE_SEC_REMOTE:
+                if (!remote)
+                        mdt_init_sec_none(reply, exp);
+                break;
+        case LUSTRE_SEC_ALL:
+                if (!remote) {
+                        reply->ocd_connect_flags &= ~(OBD_CONNECT_RMT_CLIENT |
+                                                      OBD_CONNECT_RMT_CLIENT_FORCE);
+                        if (!mdt->mdt_opts.mo_mds_capa)
+                                reply->ocd_connect_flags &= ~OBD_CONNECT_MDS_CAPA;
+                        if (!mdt->mdt_opts.mo_oss_capa)
+                                reply->ocd_connect_flags &= ~OBD_CONNECT_OSS_CAPA;
+
+                        cfs_spin_lock(&exp->exp_lock);
+                        exp->exp_connect_flags = reply->ocd_connect_flags;
+                        cfs_spin_unlock(&exp->exp_lock);
+                }
+                break;
+        default:
+                RETURN(-EINVAL);
+        }
+
+        RETURN(rc);
+}
+
+int mdt_init_idmap(struct mdt_thread_info *info)
+{
+        struct ptlrpc_request *req = mdt_info_req(info);
+        struct mdt_export_data *med = mdt_req2med(req);
+        struct obd_export *exp = req->rq_export;
+        char *client = libcfs_nid2str(req->rq_peer.nid);
+        struct obd_device *obd = exp->exp_obd;
+        int rc = 0;
+        ENTRY;
+
+        if (exp_connect_rmtclient(exp)) {
+                cfs_down(&med->med_idmap_sem);
                 if (!med->med_idmap)
                         med->med_idmap = lustre_idmap_init();
-                up(&med->med_idmap_sem);
+                cfs_up(&med->med_idmap_sem);
 
                 if (IS_ERR(med->med_idmap)) {
                         long err = PTR_ERR(med->med_idmap);
@@ -112,34 +233,22 @@ int mdt_init_idmap(struct mdt_thread_info *info)
                         RETURN(-ENOMEM);
                 }
 
-                reply->ocd_connect_flags &= ~OBD_CONNECT_LCL_CLIENT;
                 CDEBUG(D_SEC, "client %s -> target %s is remote.\n",
                        client, obd->obd_name);
-
                 /* NB, MDS_CONNECT establish root idmap too! */
                 rc = mdt_handle_idmap(info);
-        } else {
-                if (req->rq_auth_uid == INVALID_UID) {
-                        CDEBUG(D_SEC, "client %s -> target %s: user is not "
-                               "authenticated!\n", client, obd->obd_name);
-                        RETURN(-EACCES);
-                }
-                reply->ocd_connect_flags &= ~OBD_CONNECT_RMT_CLIENT;
         }
-
         RETURN(rc);
 }
 
 void mdt_cleanup_idmap(struct mdt_export_data *med)
 {
-        LASSERT(med->med_rmtclient);
-
-        down(&med->med_idmap_sem);
+        cfs_down(&med->med_idmap_sem);
         if (med->med_idmap != NULL) {
                 lustre_idmap_fini(med->med_idmap);
                 med->med_idmap = NULL;
         }
-        up(&med->med_idmap_sem);
+        cfs_up(&med->med_idmap_sem);
 }
 
 static inline void mdt_revoke_export_locks(struct obd_export *exp)
@@ -166,7 +275,7 @@ int mdt_handle_idmap(struct mdt_thread_info *info)
                 RETURN(0);
 
         med = mdt_req2med(req);
-        if (!med->med_rmtclient)
+        if (!exp_connect_rmtclient(info->mti_exp))
                 RETURN(0);
 
         opc = lustre_msg_get_opc(req->rq_reqmsg);
@@ -243,7 +352,7 @@ int ptlrpc_user_desc_do_idmap(struct ptlrpc_request *req,
         gid_t gid, fsgid;
 
         /* Only remote client need desc_to_idmap. */
-        if (!med->med_rmtclient)
+        if (!exp_connect_rmtclient(req->rq_export))
                 return 0;
 
         uid = lustre_idmap_lookup_uid(NULL, idmap, 0, pud->pud_uid);
@@ -298,7 +407,7 @@ void mdt_body_reverse_idmap(struct mdt_thread_info *info, struct mdt_body *body)
         struct mdt_export_data    *med = mdt_req2med(req);
         struct lustre_idmap_table *idmap = med->med_idmap;
 
-        if (!med->med_rmtclient)
+        if (!exp_connect_rmtclient(info->mti_exp))
                 return;
 
         if (body->valid & OBD_MD_FLUID) {
@@ -347,7 +456,7 @@ int mdt_fix_attr_ucred(struct mdt_thread_info *info, __u32 op)
                  * done in cmm/mdd layer, here set all cases as uc->mu_fsgid. */
                 if ((attr->la_valid & LA_GID) && (attr->la_gid != -1))
                         attr->la_gid = uc->mu_fsgid;
-        } else if (med->med_rmtclient) {
+        } else if (exp_connect_rmtclient(info->mti_exp)) {
                 /* NB: -1 case will be handled by mdt_fix_attr() later. */
                 if ((attr->la_valid & LA_UID) && (attr->la_uid != -1)) {
                         uid_t uid = lustre_idmap_lookup_uid(uc, idmap, 0,