Whamcloud - gitweb
b=24097 move upcall_cache from lvfs to libcfs
[fs/lustre-release.git] / lustre / mdt / mdt_idmap.c
index 16dc429..1d1005c 100644 (file)
@@ -16,8 +16,8 @@
  * in the LICENSE file that accompanied this code).
  *
  * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see [sun.com URL with a
- * copy of GPLv2].
+ * 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
@@ -26,7 +26,7 @@
  * GPL HEADER END
  */
 /*
- * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  */
 /*
@@ -64,6 +64,7 @@
 #include <linux/slab.h>
 
 #include <libcfs/libcfs.h>
+#include <libcfs/lucache.h>
 #include <obd.h>
 #include <obd_class.h>
 #include <obd_support.h>
 #include <lustre_dlm.h>
 #include <lustre_sec.h>
 #include <lustre_lib.h>
-#include <lustre_ucache.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;
@@ -91,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 (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);
+                }
         }
 
-        if (med->med_rmtclient) {
-                down(&med->med_idmap_sem);
+        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);
@@ -131,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)
@@ -185,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);
@@ -262,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);
@@ -317,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) {
@@ -366,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,