From: Sebastien Buisson Date: Tue, 22 Apr 2025 13:08:17 +0000 (+0200) Subject: LU-18109 nodemap: map back root with offset X-Git-Tag: 2.16.56~46 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=b9cf7efcc6531e30797c96954fc343e06f004f2c;p=fs%2Flustre-release.git LU-18109 nodemap: map back root with offset When a nodemap is defined with admin=1 and an offset, root should be mapped back to id 0, independently from the map_mode property. sanity-sec test_77 is added to exercise this. Fixes: e3051ad0f1c8 ("LU-18109 utils: adding nodemap offset capability") Signed-off-by: Sebastien Buisson Change-Id: I5b220dc90104ceab5c874dfbee41d3e85aefeb5b Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/58895 Reviewed-by: Marc Vef Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Tested-by: jenkins Tested-by: Maloo --- diff --git a/lustre/ptlrpc/nodemap_handler.c b/lustre/ptlrpc/nodemap_handler.c index 2f7d5e8..897d595 100644 --- a/lustre/ptlrpc/nodemap_handler.c +++ b/lustre/ptlrpc/nodemap_handler.c @@ -866,44 +866,74 @@ __u32 nodemap_map_id(struct lu_nodemap *nodemap, ENTRY; if (!nodemap_active) - goto out; + GOTO(out, found_id); if (unlikely(nodemap == NULL)) - goto out; + GOTO(out, found_id); - if (id_type != NODEMAP_PROJID && id == 0) { + if (id_type == NODEMAP_UID) { + offset_start = nodemap->nm_offset_start_uid; + offset_limit = nodemap->nm_offset_limit_uid; + } else if (id_type == NODEMAP_GID) { + offset_start = nodemap->nm_offset_start_uid; + offset_limit = nodemap->nm_offset_limit_gid; + } else if (id_type == NODEMAP_PROJID) { + offset_start = nodemap->nm_offset_start_projid; + offset_limit = nodemap->nm_offset_limit_projid; + } else { + CERROR("%s: nodemap invalid id_type provided\n", + nodemap->nm_name); + GOTO(out, found_id); + } + + /* if mapping from fs to client id space, start by un-offsetting */ + if ((offset_start != 0 || offset_limit != 0) && + tree_type == NODEMAP_FS_TO_CLIENT) { + if (found_id < offset_start || + found_id >= offset_start + offset_limit) { + /* If we are outside boundaries, squash id */ + CDEBUG(D_SEC, + "%s: id %d for type %u is below nodemap start %u, squash\n", + nodemap->nm_name, found_id, id_type, + offset_start); + GOTO(squash, found_id); + } + found_id -= offset_start; + } + + if (id_type != NODEMAP_PROJID && found_id == 0) { /* root id is mapped and offset just as the other ids. This * means root cannot remain root as soon as offset is defined. */ if (nodemap->nmf_allow_root_access) - goto offset; - goto map; + GOTO(offset, found_id); + GOTO(map, found_id); } if (id_type == NODEMAP_UID && !(nodemap->nmf_map_mode & NODEMAP_MAP_UID)) - goto offset; + GOTO(offset, found_id); if (id_type == NODEMAP_GID && !(nodemap->nmf_map_mode & NODEMAP_MAP_GID)) - goto offset; + GOTO(offset, found_id); if (id_type == NODEMAP_PROJID && !(nodemap->nmf_map_mode & NODEMAP_MAP_PROJID)) - goto offset; + GOTO(offset, found_id); if (nodemap->nmf_trust_client_ids) - goto offset; + GOTO(offset, found_id); map: if (is_default_nodemap(nodemap)) - goto squash; + GOTO(squash, found_id); down_read(&nodemap->nm_idmap_lock); - idmap = idmap_search(nodemap, tree_type, id_type, id); + idmap = idmap_search(nodemap, tree_type, id_type, found_id); if (idmap == NULL) { up_read(&nodemap->nm_idmap_lock); - goto squash; + GOTO(squash, found_id); } if (tree_type == NODEMAP_FS_TO_CLIENT) @@ -921,47 +951,22 @@ squash: else if (id_type == NODEMAP_PROJID) found_id = nodemap->nm_squash_projid; attempted_squash = true; -offset: - if (id_type == NODEMAP_UID) { - offset_start = nodemap->nm_offset_start_uid; - offset_limit = nodemap->nm_offset_limit_uid; - } else if (id_type == NODEMAP_GID) { - offset_start = nodemap->nm_offset_start_uid; - offset_limit = nodemap->nm_offset_limit_gid; - } else if (id_type == NODEMAP_PROJID) { - offset_start = nodemap->nm_offset_start_projid; - offset_limit = nodemap->nm_offset_limit_projid; - } else { - CERROR("%s: nodemap invalid id_type provided\n", - nodemap->nm_name); - GOTO(out, id); - } - - if (offset_start == 0 && offset_limit == 0) - GOTO(out, found_id); - if (tree_type == NODEMAP_FS_TO_CLIENT) { - if (found_id < offset_start) { - /* If we are outside boundaries, try to squash before - * offsetting, and return unmapped otherwise. - */ - if (!attempted_squash) - GOTO(squash, found_id); - - CDEBUG(D_SEC, - "%s: squash_id for type %u is below nodemap start %u, use unmapped value %u\n", - nodemap->nm_name, id_type, offset_start, - found_id); - GOTO(out, found_id); - } - found_id -= offset_start; - } else { +offset: + /* if mapping from client to fs id space, end with offsetting */ + if ((offset_start != 0 || offset_limit != 0) && + tree_type == NODEMAP_CLIENT_TO_FS) { if (found_id >= offset_limit) { /* If we are outside boundaries, try to squash before * offsetting, and return unmapped otherwise. */ - if (!attempted_squash) + if (!attempted_squash) { + CDEBUG(D_SEC, + "%s: id %d for type %u is outside nodemap limit %u, squash\n", + nodemap->nm_name, found_id, id_type, + offset_limit); GOTO(squash, found_id); + } CDEBUG(D_SEC, "%s: squash_id for type %u is outside nodemap limit %u, use unmapped value %u\n", diff --git a/lustre/tests/sanity-sec.sh b/lustre/tests/sanity-sec.sh index 5b1eb4c..4c773b5 100755 --- a/lustre/tests/sanity-sec.sh +++ b/lustre/tests/sanity-sec.sh @@ -5516,7 +5516,7 @@ cleanup_local_client_nodemap() { fi } -cleanup_55() { +cleanup_local_client_nodemap_with_mounts() { # unmount client if is_mounted $MOUNT; then umount_client $MOUNT || error "umount $MOUNT failed" @@ -5556,7 +5556,7 @@ test_55() { do_nodes $(comma_list $(all_mdts_nodes)) \ $LCTL set_param mdt.*.identity_upcall=NONE - stack_trap cleanup_55 EXIT + stack_trap cleanup_local_client_nodemap_with_mounts EXIT setup_local_client_nodemap "c0" 0 1 @@ -8037,6 +8037,57 @@ test_76() { } run_test 76 "suppgroups and gid mapping" +test_77() { + local squash=100 + local nm=c0 + + (( $MDS1_VERSION >= $(version_code 2.16.54) )) || + skip "Need MDS version >= 2.16.54 for proper root offsetting" + + do_nodes $(comma_list $(all_mdts_nodes)) \ + $LCTL set_param mdt.*.identity_upcall=NONE + + stack_trap cleanup_local_client_nodemap_with_mounts EXIT + + # create dir before nodemap create + $LFS mkdir -i 0 -c 1 $DIR/$tdir || error "mkdir $DIR/$tdir failed" + + # unmount client completely + umount_client $MOUNT || error "umount $MOUNT failed" + if is_mounted $MOUNT2; then + umount_client $MOUNT2 || error "umount $MOUNT2 failed" + fi + + # setup nodemap with offset + setup_local_client_nodemap $nm 1 0 + do_facet mgs $LCTL nodemap_modify --name $nm \ + --property squash_uid --value $squash || + error "Setting squash_uid=$squash on $nm failed" + do_facet mgs $LCTL nodemap_modify --name $nm \ + --property squash_gid --value $squash || + error "Setting squash_gid=$squash on $nm failed" + do_facet mgs $LCTL nodemap_modify --name $nm \ + --property squash_projid --value $squash || + error "Setting squash_projid=$squash on $nm failed" + do_facet mgs $LCTL nodemap_add_offset --name $nm \ + --offset 100000 --limit 200000 || + error "nodemap_add_offset failed" + wait_nm_sync $nm offset + + # remount client to take nodemap into account + zconf_mount_clients $HOSTNAME $MOUNT $MOUNT_OPTS || + error "remount failed" + wait_ssk + + # create a file as root... + touch $DIR/$tdir/fileA + # the owner:group ids read back should be 0:0 + ls -ln $DIR/$tdir/fileA + [[ $(stat -c "%u:%g" $DIR/$tdir/fileA) == "0:0" ]] || + error "bad owner/group for root file" +} +run_test 77 "root offsetting" + log "cleanup: ======================================================" sec_unsetup() {