Whamcloud - gitweb
LU-14797 nodemap: map project id 19/44119/9
authorSebastien Buisson <sbuisson@ddn.com>
Wed, 30 Jun 2021 16:30:57 +0000 (18:30 +0200)
committerOleg Drokin <green@whamcloud.com>
Sun, 10 Oct 2021 03:35:06 +0000 (03:35 +0000)
Add calls to nodemap_map_id() in order to map project IDs from
client ID to server ID and conversely.
Also extend nodemap_can_setquota() to allow setquota on project
only if ID is not squashed or deny_unknown is not set.
Update sanity-sec test_27a to exercise the feature.

Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: Id66458550d312404b1993ead8940c3d12eaadccd
Reviewed-on: https://review.whamcloud.com/44119
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/lustre_nodemap.h
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_io.c
lustre/mdt/mdt_lib.c
lustre/ofd/ofd_dev.c
lustre/ofd/ofd_io.c
lustre/ptlrpc/nodemap_handler.c
lustre/target/tgt_handler.c
lustre/tests/sanity-sec.sh
lustre/utils/lfs.c
lustre/utils/obd.c

index 7ac2c14..8754a97 100644 (file)
@@ -155,7 +155,7 @@ int nodemap_set_squash_gid(const char *name, gid_t gid);
 int nodemap_set_squash_projid(const char *name, projid_t projid);
 int nodemap_set_audit_mode(const char *name, bool enable_audit);
 int nodemap_set_forbid_encryption(const char *name, bool forbid_encryption);
-bool nodemap_can_setquota(const struct lu_nodemap *nodemap);
+bool nodemap_can_setquota(struct lu_nodemap *nodemap, __u32 qc_type, __u32 id);
 int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type,
                      const __u32 map[2]);
 int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type,
index 9181c9a..82c7bee 100644 (file)
@@ -831,7 +831,7 @@ void mdt_pack_attr2body(struct mdt_thread_info *info, struct mdt_body *b,
                b->mbo_nlink = attr->la_nlink;
                b->mbo_valid |= OBD_MD_FLNLINK;
        }
-       if (attr->la_valid & (LA_UID|LA_GID)) {
+       if (attr->la_valid & (LA_UID|LA_GID|LA_PROJID)) {
                nodemap = nodemap_get_from_exp(exp);
                if (IS_ERR(nodemap))
                        goto out;
@@ -850,8 +850,9 @@ void mdt_pack_attr2body(struct mdt_thread_info *info, struct mdt_body *b,
        }
 
        if (attr->la_valid & LA_PROJID) {
-               /* TODO, nodemap for project id */
-               b->mbo_projid = attr->la_projid;
+               b->mbo_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
+                                              NODEMAP_FS_TO_CLIENT,
+                                              attr->la_projid);
                b->mbo_valid |= OBD_MD_FLPROJID;
        }
 
@@ -3143,7 +3144,8 @@ static int mdt_quotactl(struct tgt_session_info *tsi)
        case LUSTRE_Q_SETQUOTAPOOL:
        case LUSTRE_Q_SETINFOPOOL:
        case LUSTRE_Q_SETDEFAULT_POOL:
-               if (!nodemap_can_setquota(nodemap))
+               if (!nodemap_can_setquota(nodemap, oqctl->qc_type,
+                                         oqctl->qc_id))
                        GOTO(out_nodemap, rc = -EPERM);
                /* fallthrough */
        case Q_GETINFO:
@@ -3177,8 +3179,8 @@ static int mdt_quotactl(struct tgt_session_info *tsi)
                                    NODEMAP_CLIENT_TO_FS, id);
                break;
        case PRJQUOTA:
-               /* todo: check/map project id */
-               id = oqctl->qc_id;
+               id = nodemap_map_id(nodemap, NODEMAP_PROJID,
+                                   NODEMAP_CLIENT_TO_FS, id);
                break;
        default:
                GOTO(out_nodemap, rc = -EOPNOTSUPP);
index 2984d57..a0ae1b5 100644 (file)
@@ -767,7 +767,7 @@ int mdt_obd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp,
 
        if (cmd == OBD_BRW_WRITE) {
                struct lu_nodemap *nodemap;
-               __u32 mapped_uid, mapped_gid;
+               __u32 mapped_uid, mapped_gid, mapped_projid;
 
                nodemap = nodemap_get_from_exp(exp);
                if (IS_ERR(nodemap))
@@ -778,6 +778,9 @@ int mdt_obd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp,
                mapped_gid = nodemap_map_id(nodemap, NODEMAP_GID,
                                            NODEMAP_FS_TO_CLIENT,
                                            oa->o_gid);
+               mapped_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
+                                              NODEMAP_FS_TO_CLIENT,
+                                              oa->o_projid);
                if (!IS_ERR_OR_NULL(nodemap)) {
                        /* do not bypass quota enforcement if squashed uid */
                        if (unlikely(mapped_uid == nodemap->nm_squash_uid)) {
@@ -850,6 +853,7 @@ int mdt_obd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp,
                 */
                oa->o_uid = mapped_uid;
                oa->o_gid = mapped_gid;
+               oa->o_projid = mapped_projid;
        } else if (cmd == OBD_BRW_READ) {
                /* If oa != NULL then mdt_preprw_read updated the inode
                 * atime and we should update the lvb so that other glimpses
index b5c75e9..9b5693d 100644 (file)
@@ -1134,11 +1134,12 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
        if (IS_ERR(nodemap))
                RETURN(PTR_ERR(nodemap));
 
-       la->la_uid   = nodemap_map_id(nodemap, NODEMAP_UID,
-                                     NODEMAP_CLIENT_TO_FS, rec->sa_uid);
-       la->la_gid   = nodemap_map_id(nodemap, NODEMAP_GID,
-                                     NODEMAP_CLIENT_TO_FS, rec->sa_gid);
-       la->la_projid = rec->sa_projid;
+       la->la_uid = nodemap_map_id(nodemap, NODEMAP_UID,
+                                   NODEMAP_CLIENT_TO_FS, rec->sa_uid);
+       la->la_gid = nodemap_map_id(nodemap, NODEMAP_GID,
+                                   NODEMAP_CLIENT_TO_FS, rec->sa_gid);
+       la->la_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
+                                      NODEMAP_CLIENT_TO_FS, rec->sa_projid);
        nodemap_putref(nodemap);
 
        la->la_size  = rec->sa_size;
index 8b66c31..1261963 100644 (file)
@@ -2388,6 +2388,10 @@ static int ofd_quotactl(struct tgt_session_info *tsi)
                id = nodemap_map_id(nodemap, NODEMAP_GID,
                                    NODEMAP_CLIENT_TO_FS,
                                    repoqc->qc_id);
+       else if (oqctl->qc_type == PRJQUOTA)
+               id = nodemap_map_id(nodemap, NODEMAP_PROJID,
+                                   NODEMAP_CLIENT_TO_FS,
+                                   repoqc->qc_id);
 
        nodemap_putref(nodemap);
 
index ffb8a26..3b96d63 100644 (file)
@@ -1462,7 +1462,7 @@ int ofd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp,
 
        if (cmd == OBD_BRW_WRITE) {
                struct lu_nodemap *nodemap;
-               __u32 mapped_uid, mapped_gid;
+               __u32 mapped_uid, mapped_gid, mapped_projid;
 
                nodemap = nodemap_get_from_exp(exp);
                if (IS_ERR(nodemap))
@@ -1473,6 +1473,9 @@ int ofd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp,
                mapped_gid = nodemap_map_id(nodemap, NODEMAP_GID,
                                            NODEMAP_FS_TO_CLIENT,
                                            oa->o_gid);
+               mapped_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
+                                              NODEMAP_FS_TO_CLIENT,
+                                              oa->o_projid);
 
                if (!IS_ERR_OR_NULL(nodemap)) {
                        /* do not bypass quota enforcement if squashed uid */
@@ -1555,6 +1558,7 @@ int ofd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp,
                 * server ID will be returned back to client in that case. */
                oa->o_uid = mapped_uid;
                oa->o_gid = mapped_gid;
+               oa->o_projid = mapped_projid;
        } else if (cmd == OBD_BRW_READ) {
                rc = ofd_commitrw_read(env, ofd, fid, objcount,
                                       npages, lnb);
index 34d04b8..7fe568e 100644 (file)
@@ -1423,14 +1423,36 @@ out:
 EXPORT_SYMBOL(nodemap_set_squash_projid);
 
 /**
- * Returns true if this nodemap has root user access. Always returns true if
- * nodemaps are not active.
+ * Check if nodemap allows setting quota.
+ *
+ * If nodemap is not active, always allow.
+ * For user and group quota, allow if the nodemap allows root access.
+ * For project quota, allow if project id is not squashed or deny_unknown
+ * is not set.
  *
  * \param      nodemap         nodemap to check access for
+ * \param      qc_type         quota type
+ * \param      id              client id to map
+ * \retval     true is setquota is allowed, false otherwise
  */
-bool nodemap_can_setquota(const struct lu_nodemap *nodemap)
+bool nodemap_can_setquota(struct lu_nodemap *nodemap, __u32 qc_type, __u32 id)
 {
-       return !nodemap_active || (nodemap && nodemap->nmf_allow_root_access);
+       if (!nodemap_active)
+               return true;
+
+       if (!nodemap || !nodemap->nmf_allow_root_access)
+               return false;
+
+       if (qc_type == PRJQUOTA) {
+               id = nodemap_map_id(nodemap, NODEMAP_PROJID,
+                                   NODEMAP_CLIENT_TO_FS, id);
+
+               if (id == nodemap->nm_squash_projid &&
+                   nodemap->nmf_deny_unknown)
+                       return false;
+       }
+
+       return true;
 }
 EXPORT_SYMBOL(nodemap_can_setquota);
 
index 62e6f2e..5a53c4c 100644 (file)
@@ -265,6 +265,9 @@ static int tgt_ost_body_unpack(struct tgt_session_info *tsi, __u32 flags)
        body->oa.o_gid = nodemap_map_id(nodemap, NODEMAP_GID,
                                        NODEMAP_CLIENT_TO_FS,
                                        body->oa.o_gid);
+       body->oa.o_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
+                                          NODEMAP_CLIENT_TO_FS,
+                                          body->oa.o_projid);
        nodemap_putref(nodemap);
 
        tsi->tsi_ost_body = body;
index f0f26e2..c2987e0 100755 (executable)
@@ -1032,6 +1032,20 @@ test_15() {
        rc=$?
        [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
 
+       for (( i = 0; i < NODEMAP_COUNT; i++ )); do
+               local csum=${HOSTNAME_CHECKSUM}_${i}
+
+               if ! do_facet mgs $LCTL nodemap_modify --name $csum \
+                               --property admin --value 0; then
+                       rc=$((rc + 1))
+               fi
+               if ! do_facet mgs $LCTL nodemap_modify --name $csum \
+                               --property trusted --value 0; then
+                       rc=$((rc + 1))
+               fi
+       done
+       [[ $rc != 0 ]] && error "nodemap_modify failed with $rc" && return 1
+
        rc=0
        for ((i = 0; i < NODEMAP_COUNT; i++)); do
                if ! add_range ${HOSTNAME_CHECKSUM}_${i} $i; then
@@ -1940,11 +1954,15 @@ run_test 26 "test transferring very large nodemap"
 nodemap_exercise_fileset() {
        local nm="$1"
        local loop=0
+       local check_proj=true
+
+       (( $MDS1_VERSION >= $(version_code 2.14.52) )) || check_proj=false
 
        # setup
        if [ "$nm" == "default" ]; then
                do_facet mgs $LCTL nodemap_activate 1
                wait_nm_sync active
+               check_proj=false
        else
                nodemap_test_setup
        fi
@@ -1965,6 +1983,23 @@ nodemap_exercise_fileset() {
               error "unable to add fileset info to $nm nodemap for servers"
        wait_nm_sync $nm fileset "nodemap.${nm}.fileset=/$subdir"
 
+       if $check_proj; then
+               do_facet mgs $LCTL nodemap_modify --name $nm \
+                        --property admin --value 1
+               wait_nm_sync $nm admin_nodemap
+               do_facet mgs $LCTL nodemap_modify --name $nm \
+                        --property trusted --value 0
+               wait_nm_sync $nm trusted_nodemap
+               do_facet mgs $LCTL nodemap_modify --name $nm \
+                        --property map_mode --value projid
+               wait_nm_sync $nm map_mode
+               do_facet mgs $LCTL nodemap_add_idmap --name $nm \
+                        --idtype projid --idmap 1:1
+               do_facet mgs $LCTL nodemap_modify --name $nm \
+                        --property deny_unknown --value 1
+               wait_nm_sync $nm deny_unknown
+       fi
+
        # re-mount client
        zconf_umount_clients ${clients_arr[0]} $MOUNT ||
                error "unable to umount client ${clients_arr[0]}"
@@ -1978,6 +2013,13 @@ nodemap_exercise_fileset() {
        do_node ${clients_arr[0]} test -f $MOUNT/this_is_$subdir ||
                error "fileset not taken into account"
 
+       if $check_proj; then
+               $LFS setquota -p 1  -b 10000 -B 11000 -i 0 -I 0 $MOUNT ||
+                       error "setquota -p 1 failed"
+               $LFS setquota -p 2  -b 10000 -B 11000 -i 0 -I 0 $MOUNT &&
+                       error "setquota -p 2 should have failed"
+       fi
+
        # re-mount client with sub-subdir
        zconf_umount_clients ${clients_arr[0]} $MOUNT ||
                error "unable to umount client ${clients_arr[0]}"
index c68eb66..d160fa2 100644 (file)
@@ -8010,9 +8010,13 @@ quota_type_def:
        if (rc) {
                if (*obd_type)
                        fprintf(stderr,
-                               "%s setquota: cannot quotactl '%s' '%s': %s",
+                               "%s setquota: cannot quotactl '%s' '%s': %s\n",
                                progname, obd_type,
                                obd_uuid2str(&qctl->obd_uuid), strerror(-rc));
+               else
+                       fprintf(stderr,
+                               "%s setquota: quotactl failed: %s\n",
+                               progname, strerror(-rc));
        }
 out:
        if (rc)
index 416c4df..5a4ee67 100644 (file)
@@ -4155,7 +4155,7 @@ int jt_nodemap_test_id(int argc, char **argv)
        }
 
        rc = nodemap_cmd(LCFG_NODEMAP_TEST_ID, &rawbuf, sizeof(rawbuf),
-                        argv[0], nidstr, typestr, idstr);
+                        argv[0], nidstr, typestr, idstr, NULL);
        if (rc == 0)
                printf("%s\n", (char *)rawbuf);