From patchwork Thu Jun 1 07:27:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mariusz Tkaczyk X-Patchwork-Id: 13263112 X-Patchwork-Delegate: jes@trained-monkey.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1CF8AC77B7E for ; Thu, 1 Jun 2023 07:29:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231626AbjFAH33 (ORCPT ); Thu, 1 Jun 2023 03:29:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46312 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231511AbjFAH32 (ORCPT ); Thu, 1 Jun 2023 03:29:28 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 37961136 for ; Thu, 1 Jun 2023 00:29:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1685604567; x=1717140567; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xDZHU71QpCP7/dg4gXk3GRKDPF2kj0AaXzENZe/Npv8=; b=PZEW3mKs3uVPnpLT8yv2WD/w28x8MxmaSselZCgU/XnymeKAT1tQIMOV 9fNhcERoNNk5oi8IzriIX5RtDLm5PRq6W8dh+Niz4O6TGkvqK++Q4ci5b /Sh1CbhormbgVePIfD0qdYU/TFtGHWiR5jiW1q8p+LJzLs98S5lGSmkpz k4i1cmZ6PUvbmVu4bDgdLBP0uzcJL/WXzoyLXPD/z5vTJy9TedfwKBFoc Y99qOJkUYFN9nuIMo5gZ4i5zACBjiI5M9O4oH7Yzo8bPtf9GWdtyygfmB f/oBJdnqeMIL3nUSD3EFDInKENYruOLEzsQJT9Rcdvw3UQFHEWjPtQyoJ Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="345007120" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="345007120" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:38 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="707221112" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="707221112" Received: from mtkaczyk-devel.igk.intel.com ([10.102.105.40]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:35 -0700 From: Mariusz Tkaczyk To: jes@trained-monkey.org Cc: linux-raid@vger.kernel.org, colyli@suse.de Subject: [PATCH 1/6] tests: create names_template Date: Thu, 1 Jun 2023 09:27:45 +0200 Message-Id: <20230601072750.20796-2-mariusz.tkaczyk@linux.intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> References: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-raid@vger.kernel.org Create templates directory and names_template. Move code from 00createnames. This code will be reused for 00confnames in next patch. Signed-off-by: Mariusz Tkaczyk --- tests/00createnames | 86 +++++++--------------------------- tests/templates/names_template | 53 +++++++++++++++++++++ 2 files changed, 70 insertions(+), 69 deletions(-) create mode 100644 tests/templates/names_template diff --git a/tests/00createnames b/tests/00createnames index 64b81b92..064eeef2 100644 --- a/tests/00createnames +++ b/tests/00createnames @@ -1,93 +1,41 @@ set -x -e +. tests/templates/names_template # Test how and --name= are handled for create mode. -# We need to check three properties, generated from those parameters: -# - devnode name -# - link in /dev/md/ (MD_DEVNAME property from --detail --export) -# - name in metadata (MD_NAME property from --examine --export) - -function _verify() { - local DEVNODE_NAME="$1" - local WANTED_LINK="$2" - local WANTED_NAME="$3" - - local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)" - if [[ "$?" != "0" ]]; then - echo "Cannot get details for $DEVNODE_NAME - unexpected devnode." - exit 1 - fi - - if [[ "$WANTED_LINK" != "empty" ]]; then - local EXPECTED="MD_DEVNAME=$WANTED_LINK" - if [[ "$RES" != "$EXPECTED" ]]; then - echo "$RES doesn't match $EXPECTED." - exit 1 - fi - fi - - - local RES="$(mdadm -E --export $dev0 | grep MD_NAME)" - if [[ "$?" != "0" ]]; then - echo "Cannot get metadata from $dev0." - exit 1 - fi - - local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME" - if [[ "$RES" != "$EXPECTED" ]]; then - echo "$RES doesn't match $EXPECTED." - exit 1 - fi -} - -function _create() { - local DEVNAME=$1 - local NAME=$2 - - if [[ -z "$NAME" ]]; then - mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force - else - mdadm -CR "$DEVNAME" --name="$NAME" -l0 -n 1 $dev0 --force - fi - - if [[ "$?" != "0" ]]; then - echo "Cannot create device." - exit 1 - fi -} # The most trivial case. -_create "/dev/md/name" -_verify "/dev/md127" "name" "name" +names_create "/dev/md/name" +names_verify "/dev/md127" "name" "name" mdadm -S "/dev/md127" -_create "name" -_verify "/dev/md127" "name" "name" +names_create "name" +names_verify "/dev/md127" "name" "name" mdadm -S "/dev/md127" # Use 'mdX' as name. -_create "/dev/md/md0" -_verify "/dev/md127" "md0" "md0" +names_create "/dev/md/md0" +names_verify "/dev/md127" "md0" "md0" mdadm -S "/dev/md127" -_create "md0" -_verify "/dev/md127" "md0" "md0" +names_create "md0" +names_verify "/dev/md127" "md0" "md0" mdadm -S "/dev/md127" # is used to create MD_DEVNAME but, name is used to create MD_NAME. -_create "/dev/md/devnode" "name" -_verify "/dev/md127" "devnode" "name" +names_create "/dev/md/devnode" "name" +names_verify "/dev/md127" "devnode" "name" mdadm -S "/dev/md127" -_create "devnode" "name" -_verify "/dev/md127" "devnode" "name" +names_create "devnode" "name" +names_verify "/dev/md127" "devnode" "name" mdadm -S "/dev/md127" # Devnode points to /dev/ directory. MD_DEVNAME doesn't exist. -_create "/dev/md0" -_verify "/dev/md0" "empty" "0" +names_create "/dev/md0" +names_verify "/dev/md0" "empty" "0" mdadm -S "/dev/md0" # Devnode points to /dev/ directory and name is set. -_create "/dev/md0" "name" -_verify "/dev/md0" "empty" "name" +names_create "/dev/md0" "name" +names_verify "/dev/md0" "empty" "name" mdadm -S "/dev/md0" diff --git a/tests/templates/names_template b/tests/templates/names_template new file mode 100644 index 00000000..9f09be9e --- /dev/null +++ b/tests/templates/names_template @@ -0,0 +1,53 @@ +# NAME is optional. Testing with native 1.2 superblock. +function names_create() { + local DEVNAME=$1 + local NAME=$2 + + if [[ -z "$NAME" ]]; then + mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force + else + mdadm -CR "$DEVNAME" --name="$NAME" --metadata=1.2 -l0 -n 1 $dev0 --force + fi + + if [[ "$?" != "0" ]]; then + echo "Cannot create device." + exit 1 + fi +} + +# Three properties to check: +# - devnode name +# - link in /dev/md/ (MD_DEVNAME property from --detail --export) +# - name in metadata (MD_NAME property from --detail --export)- that works only with 1.2 sb. +function names_verify() { + local DEVNODE_NAME="$1" + local WANTED_LINK="$2" + local WANTED_NAME="$3" + + local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)" + if [[ "$?" != "0" ]]; then + echo "Cannot get details for $DEVNODE_NAME - unexpected devnode." + exit 1 + fi + + if [[ "$WANTED_LINK" != "empty" ]]; then + local EXPECTED="MD_DEVNAME=$WANTED_LINK" + fi + + if [[ "$RES" != "$EXPECTED" ]]; then + echo "$RES doesn't match $EXPECTED." + exit 1 + fi + + local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_NAME)" + if [[ "$?" != "0" ]]; then + echo "Cannot get metadata from $dev0." + exit 1 + fi + + local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME" + if [[ "$RES" != "$EXPECTED" ]]; then + echo "$RES doesn't match $EXPECTED." + exit 1 + fi +} From patchwork Thu Jun 1 07:27:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mariusz Tkaczyk X-Patchwork-Id: 13263113 X-Patchwork-Delegate: jes@trained-monkey.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2B26EC7EE29 for ; Thu, 1 Jun 2023 07:29:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231911AbjFAH3b (ORCPT ); Thu, 1 Jun 2023 03:29:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46318 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231442AbjFAH33 (ORCPT ); Thu, 1 Jun 2023 03:29:29 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CED8413D for ; Thu, 1 Jun 2023 00:29:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1685604567; x=1717140567; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qy7a6pb3YsaeeHsAeJpNYCfHXMVF4+DtNSxIWCbqoQA=; b=VBgoO0bUSWnEuyQSGaFZQ3b7imEqzYaeFuGVZTVA78du25h20q9KFgR/ XTiKmDDAbGGW3GbYg4HHQ4DC+Nphp9Q3ICwblD7N06pH69XA99ej+m3KL Tk+1vb0X7Jot7t0DOCpVAZIMgjW4zlpRrxt1EtcfH6Xm/Xb+BX3C/MH9o mBApZZMXxHQVxqt6k0aX2DcNhnmZwpROpP772vVi/1NcF4DLhygFgGU7x bwunfmIooYIKfNRVC8JWKy+xlEiskRqgS0hbQ8O5U6sBhbSj04otebVsS N5CU37noq1J04T86Rh9HLG6NoZGzTN2Idefd1YrWvhw78c6ikaA6jO/2D g==; X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="345007130" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="345007130" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="707221120" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="707221120" Received: from mtkaczyk-devel.igk.intel.com ([10.102.105.40]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:37 -0700 From: Mariusz Tkaczyk To: jes@trained-monkey.org Cc: linux-raid@vger.kernel.org, colyli@suse.de Subject: [PATCH 2/6] tests: create 00confnames Date: Thu, 1 Jun 2023 09:27:46 +0200 Message-Id: <20230601072750.20796-3-mariusz.tkaczyk@linux.intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> References: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-raid@vger.kernel.org The test is an attempt to document current implementation of devnode and name handling for config entries. It is focused on incremental- default way of array assembling on boot. The expectations are aligned to current implementation for native metadata because it is the most complicated scenario- both variables can be set. Signed-off-by: Mariusz Tkaczyk --- tests/00confnames | 107 +++++++++++++++++++++++++++++++++ tests/templates/names_template | 20 ++++++ 2 files changed, 127 insertions(+) create mode 100644 tests/00confnames diff --git a/tests/00confnames b/tests/00confnames new file mode 100644 index 00000000..4990cb5e --- /dev/null +++ b/tests/00confnames @@ -0,0 +1,107 @@ +set -x -e +. tests/templates/names_template + +# Test how and from config are handled during Incremental assemblation. +# 1-6 only tests (no in config). +# 6-10 and combinations are tested. +# 11-13 corner cases. + +names_create "/dev/md/name" +local _UUID="$(mdadm -D --export /dev/md127 | grep MD_UUID | cut -d'=' -f2)" +[[ "$_UUID" == "" ]] && echo "Cannot obtain UUID for $DEVNODE_NAME" && exit 1 + + +# 1. definition consistent with metadata name. +names_make_conf $_UUID "/dev/md/name" "empty" $config +mdadm -S "/dev/md127" +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 2. Same as 1, but use short name form of . +names_make_conf $_UUID "name" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 3. Same as 1, but use different than metadata provides. +names_make_conf $_UUID "/dev/md/other" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "other" "name" +mdadm -S "/dev/md127" + +# 4. Same as 3, but use short name form of . +names_make_conf $_UUID "other" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "other" "name" +mdadm -S "/dev/md127" + +# 5. Force particular node creation by setting to /dev/mdX. Link is not created in this +# case. +names_make_conf $_UUID "/dev/md4" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md4" "empty" "name" +mdadm -S "/dev/md4" + +# 6. set to /dev/mdX, same as in metadata. +# Metadata name and default node used - controversial. Current behavior documented. +names_make_conf $_UUID "/dev/md22" "name" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 7. set to /dev/mdX, different than in metadata. +# Metadata name and default node used - controversial. Current behavior documented. +names_make_conf $_UUID "/dev/md8" "other" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 8. Both and different than in metadata. +# Metadata name and default node used - controversial. Current behavior documented. +names_make_conf $_UUID "devnode" "other_name" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 9. set to metadata name, different than in metadata. +# Metadata name and default node used - controversial. Current behavior documented. +names_make_conf $_UUID "name" "other_name" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 10. Bad set, no . +# Metadata name and default node used - expected. +names_make_conf $_UUID "/im/bad/devname" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 11. with some special symbols and locales, no . +# It needs to wait a while for timeout because udev cannot create a link - known issue. +names_make_conf $_UUID "tźż-\.,<>st+-" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "tźż-\.,<>st+-" "name" +mdadm -S "/dev/md127" + +# 12. No and set. +# Metadata name and default node used - expected. +names_make_conf $_UUID "empty" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 13. No , set to /dev/mdX. +# Entry should be ignored, it is not ignored but result is good anyway. +names_make_conf $_UUID "empty" "/dev/md12" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 13. No , with special symbols and locales. +# Entry should be ignored, it is not ignored but result is good anyway. +names_make_conf $_UUID "empty" "./\śćń#&" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" diff --git a/tests/templates/names_template b/tests/templates/names_template index 9f09be9e..8d2b5c81 100644 --- a/tests/templates/names_template +++ b/tests/templates/names_template @@ -51,3 +51,23 @@ function names_verify() { exit 1 fi } + +# Generate ARRAYLINE for tested array. +names_make_conf() { + local UUID="$1" + local WANTED_DEVNAME="$2" + local WANTED_NAME="$3" + local CONF="$4" + + local LINE="ARRAY metadata=1.2 UUID=$UUID" + + if [[ "$WANTED_DEVNAME" != "empty" ]]; then + LINE="$LINE $WANTED_DEVNAME" + fi + + if [[ "$WANTED_NAME" != "empty" ]]; then + LINE="$LINE name=$WANTED_NAME" + fi + + echo $LINE > $CONF +} From patchwork Thu Jun 1 07:27:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mariusz Tkaczyk X-Patchwork-Id: 13263114 X-Patchwork-Delegate: jes@trained-monkey.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 07086C7EE29 for ; Thu, 1 Jun 2023 07:29:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231511AbjFAH3h (ORCPT ); Thu, 1 Jun 2023 03:29:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46342 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231935AbjFAH3c (ORCPT ); Thu, 1 Jun 2023 03:29:32 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 777A3FB for ; Thu, 1 Jun 2023 00:29:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1685604568; x=1717140568; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ltQfMhwa5IQ5pylUFbtH1euXqsxkG4fKjeJaXAeNjng=; b=PHPzD+l2+q9CaQC9eRWDkx03l/WurAEYCafSlP/n9ssaslCeRrsfkApJ AAe3Y8hozf56x9IBXVNaf6A9ageAoliiFDhJadb7MoLpQxR5A+2WiHziA UvLFTPe/Ph4kCk5gIvKATL/lHMIV50wtFNGkmfez0TjTwyWw/x+9seAKP eTfhO87oQ6iLlEd7usNbbRzCkNbbPB53Oa+cH7hjL7w0SvJgXmDWCfZkh qecoCJJ+CHSY6DLAC8t3l+oED8chK/DL3zuaeJtGaeK9IDSaKCexJ+/IE v8N9GXyQgM5KvWS2MaZs34nIqgbN423BO5TRIhxdMfn+E8wiiJtwYsmKc g==; X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="345007138" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="345007138" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:43 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="707221125" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="707221125" Received: from mtkaczyk-devel.igk.intel.com ([10.102.105.40]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:39 -0700 From: Mariusz Tkaczyk To: jes@trained-monkey.org Cc: linux-raid@vger.kernel.org, colyli@suse.de Subject: [PATCH 3/6] mdadm: set ident.devname if applicable Date: Thu, 1 Jun 2023 09:27:47 +0200 Message-Id: <20230601072750.20796-4-mariusz.tkaczyk@linux.intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> References: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-raid@vger.kernel.org This patch tries to propagate the usage of struct mddev_ident for cmdline where it is applicable. To avoid regression, this value is derived from devlist->devname for applicable modes only. As a result, the whole structure is passed to some functions. It produces some changes for Build, Create and Assemble. No functional changes intended. The goal of the change is to unify devname validation which is done in next patches. Signed-off-by: Mariusz Tkaczyk --- Build.c | 21 +++++++++------------ Create.c | 35 ++++++++++++++++------------------ mdadm.c | 57 +++++++++++++++++++++++++------------------------------- mdadm.h | 13 +++++-------- 4 files changed, 55 insertions(+), 71 deletions(-) diff --git a/Build.c b/Build.c index 8d6f6f58..657ab315 100644 --- a/Build.c +++ b/Build.c @@ -24,8 +24,8 @@ #include "mdadm.h" -int Build(char *mddev, struct mddev_dev *devlist, - struct shape *s, struct context *c) +int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s, + struct context *c) { /* Build a linear or raid0 arrays without superblocks * We cannot really do any checks, we just do it. @@ -75,13 +75,12 @@ int Build(char *mddev, struct mddev_dev *devlist, /* We need to create the device. It can have no name. */ map_lock(&map); - mdfd = create_mddev(mddev, NULL, c->autof, LOCAL, + mdfd = create_mddev(ident->devname, NULL, c->autof, LOCAL, chosen_name, 0); if (mdfd < 0) { map_unlock(&map); return 1; } - mddev = chosen_name; map_update(&map, fd2devnm(mdfd), "none", uuid, chosen_name); map_unlock(&map); @@ -93,7 +92,7 @@ int Build(char *mddev, struct mddev_dev *devlist, array.nr_disks = s->raiddisks; array.raid_disks = s->raiddisks; array.md_minor = 0; - if (fstat_is_blkdev(mdfd, mddev, &rdev)) + if (fstat_is_blkdev(mdfd, chosen_name, &rdev)) array.md_minor = minor(rdev); array.not_persistent = 1; array.state = 0; /* not clean, but no errors */ @@ -108,8 +107,7 @@ int Build(char *mddev, struct mddev_dev *devlist, array.chunk_size = s->chunk*1024; array.layout = s->layout; if (md_set_array_info(mdfd, &array)) { - pr_err("md_set_array_info() failed for %s: %s\n", - mddev, strerror(errno)); + pr_err("md_set_array_info() failed for %s: %s\n", chosen_name, strerror(errno)); goto abort; } @@ -178,8 +176,8 @@ int Build(char *mddev, struct mddev_dev *devlist, } if (bitmap_fd >= 0) { if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) { - pr_err("Cannot set bitmap file for %s: %s\n", - mddev, strerror(errno)); + pr_err("Cannot set bitmap file for %s: %s\n", chosen_name, + strerror(errno)); goto abort; } } @@ -193,9 +191,8 @@ int Build(char *mddev, struct mddev_dev *devlist, } if (c->verbose >= 0) - pr_err("array %s built and started.\n", - mddev); - wait_for(mddev, mdfd); + pr_err("array %s built and started.\n", chosen_name); + wait_for(chosen_name, mdfd); close(mdfd); return 0; diff --git a/Create.c b/Create.c index ea6a4745..a280c7bc 100644 --- a/Create.c +++ b/Create.c @@ -471,11 +471,8 @@ out: return ret; } -int Create(struct supertype *st, char *mddev, - char *name, int *uuid, - int subdevs, struct mddev_dev *devlist, - struct shape *s, - struct context *c) +int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, + struct mddev_dev *devlist, struct shape *s, struct context *c) { /* * Create a new raid array. @@ -497,6 +494,8 @@ int Create(struct supertype *st, char *mddev, unsigned long long minsize = 0, maxsize = 0; char *mindisc = NULL; char *maxdisc = NULL; + char *name = ident->name; + int *uuid = ident->uuid_set == 1 ? ident->uuid : NULL; int dnum; struct mddev_dev *dv; dev_t rdev; @@ -1015,7 +1014,7 @@ int Create(struct supertype *st, char *mddev, /* We need to create the device */ map_lock(&map); - mdfd = create_mddev(mddev, name, c->autof, LOCAL, chosen_name, 1); + mdfd = create_mddev(ident->devname, ident->name, c->autof, LOCAL, chosen_name, 1); if (mdfd < 0) { map_unlock(&map); return 1; @@ -1032,7 +1031,6 @@ int Create(struct supertype *st, char *mddev, udev_unblock(); return 1; } - mddev = chosen_name; memset(&inf, 0, sizeof(inf)); md_get_array_info(mdfd, &inf); @@ -1050,7 +1048,7 @@ int Create(struct supertype *st, char *mddev, * with, but it chooses to trust me instead. Sigh */ info.array.md_minor = 0; - if (fstat_is_blkdev(mdfd, mddev, &rdev)) + if (fstat_is_blkdev(mdfd, chosen_name, &rdev)) info.array.md_minor = minor(rdev); info.array.not_persistent = 0; @@ -1102,8 +1100,8 @@ int Create(struct supertype *st, char *mddev, info.array.layout = s->layout; info.array.chunk_size = s->chunk*1024; - if (name == NULL || *name == 0) { - /* base name on mddev */ + if (*name == 0) { + /* base name on devname */ /* /dev/md0 -> 0 * /dev/md_d0 -> d0 * /dev/md_foo -> foo @@ -1113,15 +1111,16 @@ int Create(struct supertype *st, char *mddev, * /dev/mdhome -> home */ /* FIXME compare this with rules in create_mddev */ - name = strrchr(mddev, '/'); + name = strrchr(chosen_name, '/'); + if (name) { name++; if (strncmp(name, "md_", 3) == 0 && - strlen(name) > 3 && (name-mddev) == 5 /* /dev/ */) + strlen(name) > 3 && (name - chosen_name) == 5 /* /dev/ */) name += 3; else if (strncmp(name, "md", 2) == 0 && strlen(name) > 2 && isdigit(name[2]) && - (name-mddev) == 5 /* /dev/ */) + (name - chosen_name) == 5 /* /dev/ */) name += 2; } } @@ -1215,8 +1214,7 @@ int Create(struct supertype *st, char *mddev, } rv = set_array_info(mdfd, st, &info); if (rv) { - pr_err("failed to set array info for %s: %s\n", - mddev, strerror(errno)); + pr_err("failed to set array info for %s: %s\n", chosen_name, strerror(errno)); goto abort_locked; } @@ -1237,8 +1235,7 @@ int Create(struct supertype *st, char *mddev, goto abort_locked; } if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) { - pr_err("Cannot set bitmap file for %s: %s\n", - mddev, strerror(errno)); + pr_err("Cannot set bitmap file for %s: %s\n", chosen_name, strerror(errno)); goto abort_locked; } } @@ -1254,7 +1251,7 @@ int Create(struct supertype *st, char *mddev, * create links */ sysfs_uevent(&info, "change"); if (c->verbose >= 0) - pr_err("container %s prepared.\n", mddev); + pr_err("container %s prepared.\n", chosen_name); wait_for(chosen_name, mdfd); } else if (c->runstop == 1 || subdevs >= s->raiddisks) { if (st->ss->external) { @@ -1312,7 +1309,7 @@ int Create(struct supertype *st, char *mddev, ioctl(mdfd, RESTART_ARRAY_RW, NULL); } if (c->verbose >= 0) - pr_info("array %s started.\n", mddev); + pr_info("array %s started.\n", chosen_name); if (st->ss->external && st->container_devnm[0]) { if (need_mdmon) start_mdmon(st->container_devnm); diff --git a/mdadm.c b/mdadm.c index 076b45e0..14072ec1 100644 --- a/mdadm.c +++ b/mdadm.c @@ -1290,37 +1290,39 @@ int main(int argc, char *argv[]) pr_err("an md device must be given in this mode\n"); exit(2); } + ident.devname = devlist->devname; + if ((int)ident.super_minor == -2 && c.autof) { pr_err("--super-minor=dev is incompatible with --auto\n"); exit(2); } if (mode == MANAGE || mode == GROW) { - mdfd = open_mddev(devlist->devname, 1); + mdfd = open_mddev(ident.devname, 1); if (mdfd < 0) exit(1); ret = fstat(mdfd, &stb); if (ret) { - pr_err("fstat failed on %s.\n", devlist->devname); + pr_err("fstat failed on %s.\n", ident.devname); exit(1); } } else { - char *bname = basename(devlist->devname); + char *bname = basename(ident.devname); if (strlen(bname) > MD_NAME_MAX) { - pr_err("Name %s is too long.\n", devlist->devname); + pr_err("Name %s is too long.\n", ident.devname); exit(1); } - ret = stat(devlist->devname, &stb); + ret = stat(ident.devname, &stb); if (ident.super_minor == -2 && ret != 0) { pr_err("--super-minor=dev given, and listed device %s doesn't exist.\n", - devlist->devname); + ident.devname); exit(1); } if (!ret && !stat_is_md_dev(&stb)) { - pr_err("device %s exists but is not an md array.\n", devlist->devname); + pr_err("device %s exists but is not an md array.\n", ident.devname); exit(1); } } @@ -1409,17 +1411,17 @@ int main(int argc, char *argv[]) case MANAGE: /* readonly, add/remove, readwrite, runstop */ if (c.readonly > 0) - rv = Manage_ro(devlist->devname, mdfd, c.readonly); + rv = Manage_ro(ident.devname, mdfd, c.readonly); if (!rv && devs_found > 1) - rv = Manage_subdevs(devlist->devname, mdfd, + rv = Manage_subdevs(ident.devname, mdfd, devlist->next, c.verbose, c.test, c.update, c.force); if (!rv && c.readonly < 0) - rv = Manage_ro(devlist->devname, mdfd, c.readonly); + rv = Manage_ro(ident.devname, mdfd, c.readonly); if (!rv && c.runstop > 0) - rv = Manage_run(devlist->devname, mdfd, &c); + rv = Manage_run(ident.devname, mdfd, &c); if (!rv && c.runstop < 0) - rv = Manage_stop(devlist->devname, mdfd, c.verbose, 0); + rv = Manage_stop(ident.devname, mdfd, c.verbose, 0); break; case ASSEMBLE: if (!c.scan && c.runstop == -1) { @@ -1429,22 +1431,19 @@ int main(int argc, char *argv[]) ident.super_minor == UnSet && ident.name[0] == 0 && !c.scan) { /* Only a device has been given, so get details from config file */ - struct mddev_ident *array_ident = conf_get_ident(devlist->devname); + struct mddev_ident *array_ident = conf_get_ident(ident.devname); if (array_ident == NULL) { - pr_err("%s not identified in config file.\n", - devlist->devname); + pr_err("%s not identified in config file.\n", ident.devname); rv |= 1; if (mdfd >= 0) close(mdfd); } else { if (array_ident->autof == 0) array_ident->autof = c.autof; - rv |= Assemble(ss, devlist->devname, array_ident, - NULL, &c); + rv |= Assemble(ss, ident.devname, array_ident, NULL, &c); } } else if (!c.scan) - rv = Assemble(ss, devlist->devname, &ident, - devlist->next, &c); + rv = Assemble(ss, ident.devname, &ident, devlist->next, &c); else if (devs_found > 0) { if (c.update && devs_found > 1) { pr_err("can only update a single array at a time\n"); @@ -1502,7 +1501,7 @@ int main(int argc, char *argv[]) break; } } - rv = Build(devlist->devname, devlist->next, &s, &c); + rv = Build(&ident, devlist->next, &s, &c); break; case CREATE: if (c.delay == 0) @@ -1539,9 +1538,7 @@ int main(int argc, char *argv[]) break; } - rv = Create(ss, devlist->devname, - ident.name, ident.uuid_set ? ident.uuid : NULL, - devs_found - 1, devlist->next, &s, &c); + rv = Create(ss, &ident, devs_found - 1, devlist->next, &s, &c); break; case MISC: if (devmode == 'E') { @@ -1638,8 +1635,7 @@ int main(int argc, char *argv[]) break; } for (dv = devlist->next; dv; dv = dv->next) { - rv = Grow_Add_device(devlist->devname, mdfd, - dv->devname); + rv = Grow_Add_device(ident.devname, mdfd, dv->devname); if (rv) break; } @@ -1652,18 +1648,15 @@ int main(int argc, char *argv[]) } if (c.delay == 0) c.delay = DEFAULT_BITMAP_DELAY; - rv = Grow_addbitmap(devlist->devname, mdfd, &c, &s); + rv = Grow_addbitmap(ident.devname, mdfd, &c, &s); } else if (grow_continue) - rv = Grow_continue_command(devlist->devname, - mdfd, c.backup_file, - c.verbose); + rv = Grow_continue_command(ident.devname, mdfd, c.backup_file, c.verbose); else if (s.size > 0 || s.raiddisks || s.layout_str || s.chunk != 0 || s.level != UnSet || s.data_offset != INVALID_SECTORS) { - rv = Grow_reshape(devlist->devname, mdfd, - devlist->next, &c, &s); + rv = Grow_reshape(ident.devname, mdfd, devlist->next, &c, &s); } else if (s.consistency_policy != CONSISTENCY_POLICY_UNKNOWN) { - rv = Grow_consistency_policy(devlist->devname, mdfd, &c, &s); + rv = Grow_consistency_policy(ident.devname, mdfd, &c, &s); } else if (array_size == 0) pr_err("no changes to --grow\n"); break; diff --git a/mdadm.h b/mdadm.h index 83f2cf7f..782d7996 100644 --- a/mdadm.h +++ b/mdadm.h @@ -1531,14 +1531,11 @@ extern int Assemble(struct supertype *st, char *mddev, struct mddev_dev *devlist, struct context *c); -extern int Build(char *mddev, struct mddev_dev *devlist, - struct shape *s, struct context *c); - -extern int Create(struct supertype *st, char *mddev, - char *name, int *uuid, - int subdevs, struct mddev_dev *devlist, - struct shape *s, - struct context *c); +extern int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s, + struct context *c); + +extern int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, + struct mddev_dev *devlist, struct shape *s, struct context *c); extern int Detail(char *dev, struct context *c); extern int Detail_Platform(struct superswitch *ss, int scan, int verbose, int export, char *controller_path); From patchwork Thu Jun 1 07:27:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mariusz Tkaczyk X-Patchwork-Id: 13263115 X-Patchwork-Delegate: jes@trained-monkey.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C614C77B7A for ; Thu, 1 Jun 2023 07:29:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231935AbjFAH3i (ORCPT ); Thu, 1 Jun 2023 03:29:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46344 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231944AbjFAH3c (ORCPT ); Thu, 1 Jun 2023 03:29:32 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 39BA512F for ; Thu, 1 Jun 2023 00:29:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1685604569; x=1717140569; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=45s30sJIVSJq31Iqm6D1ch7ZljDLD2A2+1jDCdvNBOo=; b=LRTB8F5Tlglcbpow22s+hvivGC/cBkopyHGkyw1FGkYs6Br0Izg4D5Gr W113wu5MIY5HXk3S+EfOKWBSjNS4MJWTUMz5WfkD3WrXjyD9GosLr4wer 9XYlLzCdY80flTF1QZmFrubF3mw/lwXhAUcMwPap4Kzy1noVAc42oSPsr n7OhlxN4BO3Wa/9erJJy/b/C2YWfPmUKnBO9Q8x4kyKw/3nETZwkuTWnV 8Bv1aN3RrD1ZbLDoj8YoiC6DtlpLFMuR/YBAbXc6q45uOeaeKQBWX+yJ1 FcnQYiZafFFSUEe5Ar5CfVPDiXr5jxgN20tCTw8LgrxOKe7u4m+dkmQ64 w==; X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="345007155" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="345007155" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:45 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="707221133" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="707221133" Received: from mtkaczyk-devel.igk.intel.com ([10.102.105.40]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:42 -0700 From: Mariusz Tkaczyk To: jes@trained-monkey.org Cc: linux-raid@vger.kernel.org, colyli@suse.de Subject: [PATCH 4/6] mdadm: refactor ident->name handling Date: Thu, 1 Jun 2023 09:27:48 +0200 Message-Id: <20230601072750.20796-5-mariusz.tkaczyk@linux.intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> References: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-raid@vger.kernel.org Create dedicated setter for name in mddev_ident and propagate it. Following changes are made: - move duplicated code from config.c and mdadm.c into new function. - Add error enum in mdadm.h. - Use MD_NAME_MAX instead of hardcoded value in mddev_ident. - Use secure functions. - Add more detailed verification of the name. - make error messages reusable for cmdline and config: - for cmdline, these are errors so use pr_err(). - for config, these are just warnings, so use pr_info(). Signed-off-by: Mariusz Tkaczyk --- config.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++------ lib.c | 18 +++++++++++++ mdadm.c | 12 +++------ mdadm.h | 20 ++++++++++----- 4 files changed, 104 insertions(+), 23 deletions(-) diff --git a/config.c b/config.c index 450880e3..76a8384a 100644 --- a/config.c +++ b/config.c @@ -131,6 +131,34 @@ bool is_devname_ignore(char *devname) return false; } +/** + * ident_log() - generate and write message to the user. + * @param_name: name of the property. + * @value: value of the property. + * @reason: meaningful description. + * @cmdline: context dependent actions, see below. + * + * The function is made to provide similar error handling for both config and cmdline. The behavior + * is configurable via @cmdline. Message has following format: + * "Value "@value" cannot be set for @param_name. Reason: @reason." + * + * If cmdline is on: + * - message is written to stderr. + * otherwise: + * - message is written to stdout. + * - "Value ignored" is added at the end of the message. + */ +static void ident_log(const char *param_name, const char *value, const char *reason, + const bool cmdline) +{ + if (cmdline == true) + pr_err("Value \"%s\" cannot be set as %s. Reason: %s.\n", value, param_name, + reason); + else + pr_info("Value \"%s\" cannot be set as %s. Reason: %s. Value ignored.\n", value, + param_name, reason); +} + /** * ident_init() - Set defaults. * @ident: ident pointer, not NULL. @@ -159,6 +187,46 @@ inline void ident_init(struct mddev_ident *ident) ident->uuid_set = 0; } +/** + * _ident_set_name()- set name in &mddev_ident. + * @ident: pointer to &mddev_ident. + * @name: name to be set. + * @cmdline: context dependent actions. + * + * If criteria passed, set name in @ident. + * + * Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR. + */ +static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *name, + const bool cmdline) +{ + assert(name); + assert(ident); + + const char *prop_name = "name"; + + if (ident->name[0]) { + ident_log(prop_name, name, "Already defined", cmdline); + return MDADM_STATUS_ERROR; + } + + if (is_string_lq(name, MD_NAME_MAX + 1) == false) { + ident_log(prop_name, name, "Too long or empty", cmdline); + return MDADM_STATUS_ERROR; + } + + snprintf(ident->name, MD_NAME_MAX + 1, "%s", name); + return MDADM_STATUS_SUCCESS; +} + +/** + * ident_set_name()- exported, for cmdline. + */ +mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name) +{ + return _ident_set_name(ident, name, true); +} + struct conf_dev { struct conf_dev *next; char *name; @@ -444,14 +512,7 @@ void arrayline(char *line) mis.super_minor = minor; } } else if (strncasecmp(w, "name=", 5) == 0) { - if (mis.name[0]) - pr_err("only specify name once, %s ignored.\n", - w); - else if (strlen(w + 5) > 32) - pr_err("name too long, ignoring %s\n", w); - else - strcpy(mis.name, w + 5); - + _ident_set_name(&mis, w + 5, false); } else if (strncasecmp(w, "bitmap=", 7) == 0) { if (mis.bitmap_file) pr_err("only specify bitmap file once. %s ignored\n", diff --git a/lib.c b/lib.c index fe5c8d2c..999cd520 100644 --- a/lib.c +++ b/lib.c @@ -27,6 +27,24 @@ #include #include +/** + * is_string_lq() - Check if string length with NULL byte is lower or equal to requested. + * @str: string to check. + * @max_len: max length. + * + * @str length must be bigger than 0 and be lower or equal @max_len, including termination byte. + */ +bool is_string_lq(const char * const str, size_t max_len) +{ + assert(str); + + size_t _len = strnlen(str, max_len); + + if (_len > 0 && _len < max_len) + return true; + return false; +} + bool is_dev_alive(char *path) { if (!path) diff --git a/mdadm.c b/mdadm.c index 14072ec1..5084c348 100644 --- a/mdadm.c +++ b/mdadm.c @@ -690,20 +690,14 @@ int main(int argc, char *argv[]) case O(CREATE,'N'): case O(ASSEMBLE,'N'): case O(MISC,'N'): - if (ident.name[0]) { - pr_err("name cannot be set twice. Second value %s.\n", optarg); - exit(2); - } if (mode == MISC && !c.subarray) { pr_err("-N/--name only valid with --update-subarray in misc mode\n"); exit(2); } - if (strlen(optarg) > 32) { - pr_err("name '%s' is too long, 32 chars max.\n", - optarg); + + if (ident_set_name(&ident, optarg) != MDADM_STATUS_SUCCESS) exit(2); - } - strcpy(ident.name, optarg); + continue; case O(ASSEMBLE,'m'): /* super-minor for array */ diff --git a/mdadm.h b/mdadm.h index 782d7996..62e15dfa 100644 --- a/mdadm.h +++ b/mdadm.h @@ -294,6 +294,11 @@ static inline void __put_unaligned32(__u32 val, void *p) #define KIB_TO_BYTES(x) ((x) << 10) #define SEC_TO_BYTES(x) ((x) << 9) +/** + * This is true for native and DDF, IMSM allows 16. + */ +#define MD_NAME_MAX 32 + extern const char Name[]; struct md_bb_entry { @@ -425,6 +430,12 @@ struct spare_criteria { unsigned int sector_size; }; +typedef enum mdadm_status { + MDADM_STATUS_SUCCESS = 0, + MDADM_STATUS_ERROR, + MDADM_STATUS_UNDEF, +} mdadm_status_t; + enum mode { ASSEMBLE=1, BUILD, @@ -593,7 +604,7 @@ struct mddev_ident { int uuid_set; int uuid[4]; - char name[33]; + char name[MD_NAME_MAX + 1]; int super_minor; @@ -1609,6 +1620,7 @@ extern int check_partitions(int fd, char *dname, extern int fstat_is_blkdev(int fd, char *devname, dev_t *rdev); extern int stat_is_blkdev(char *devname, dev_t *rdev); +extern bool is_string_lq(const char * const str, size_t max_len); extern bool is_dev_alive(char *path); extern int get_mdp_major(void); extern int get_maj_min(char *dev, int *major, int *minor); @@ -1626,6 +1638,7 @@ extern void manage_fork_fds(int close_all); extern int continue_via_systemd(char *devnm, char *service_name, char *prefix); extern void ident_init(struct mddev_ident *ident); +extern mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name); extern int parse_auto(char *str, char *msg, int config); extern struct mddev_ident *conf_get_ident(char *dev); @@ -2001,11 +2014,6 @@ enum r0layout { /* And another special number needed for --data_offset=variable */ #define VARIABLE_OFFSET 3 -/** - * This is true for native and DDF, IMSM allows 16. - */ -#define MD_NAME_MAX 32 - /** * is_container() - check if @level is &LEVEL_CONTAINER * @level: level value From patchwork Thu Jun 1 07:27:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mariusz Tkaczyk X-Patchwork-Id: 13263116 X-Patchwork-Delegate: jes@trained-monkey.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6F106C77B7E for ; Thu, 1 Jun 2023 07:29:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231958AbjFAH3k (ORCPT ); Thu, 1 Jun 2023 03:29:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46376 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231969AbjFAH3g (ORCPT ); Thu, 1 Jun 2023 03:29:36 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D5B72136 for ; Thu, 1 Jun 2023 00:29:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1685604570; x=1717140570; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=sUJfoCvGu6zYyaYMefMVRMe3X4WR/umkU0lLzswG95I=; b=H9ZdrMJ8gPnTK8t9+nAQG/Bs5h0uk9VKs6j7NOZ35KMAvxJstRc197jo jLmFHKUWqLRMfUJO5sfU+/E+3oLwhqt8XMflw8V2FsKX3lPi1g1r/QIdF tMvQd9KadIo8Y9SV9KuKuXMEGs0gfDFwxenleBmdu4BLK+I5UXYdPgqf4 cEkSgNtkpdRdM36WLX8ds/DduiVzYhAAXvZw1U1RF+a5+BAwTXalv3Fmx NgeKGH0WrqnZ0Ap+gN+o/B1im660TwFl31AHPdqg6SIJpxnAH2H4fgLA7 Wll1CklWwiztg81Mrsa28OgzYumgRLmFI6HaMvSyyqkpmz4+HB2VJovwV Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="345007172" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="345007172" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:47 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="707221137" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="707221137" Received: from mtkaczyk-devel.igk.intel.com ([10.102.105.40]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:44 -0700 From: Mariusz Tkaczyk To: jes@trained-monkey.org Cc: linux-raid@vger.kernel.org, colyli@suse.de Subject: [PATCH 5/6] mdadm: define ident_set_devname() Date: Thu, 1 Jun 2023 09:27:49 +0200 Message-Id: <20230601072750.20796-6-mariusz.tkaczyk@linux.intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> References: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-raid@vger.kernel.org Use dedicated set method for ident->devname. Now, devname validation is done early for modes where device is created (Build, Create and Assemble). The rules, used for devname validation are derived from config file. It could cause regression with execeptional cases where existing device has name which doesn't match criteria for Manage and Grow modes. It is low risk and those modes are not omitted from early devname validation. Use can used main numbered devnode to avoid this problem. Messages exposed to user are changed so it might cause a regression in negative scenarios. Error codes are not changed. Signed-off-by: Mariusz Tkaczyk --- config.c | 102 +++++++++++++++++++++++++-------- mdadm.c | 10 +--- mdadm.h | 3 +- tests/00createnames | 3 + tests/templates/names_template | 7 +++ 5 files changed, 92 insertions(+), 33 deletions(-) diff --git a/config.c b/config.c index 76a8384a..d80747a2 100644 --- a/config.c +++ b/config.c @@ -122,7 +122,7 @@ int match_keyword(char *word) /** * is_devname_ignore() - check if &devname is a special "" keyword. */ -bool is_devname_ignore(char *devname) +bool is_devname_ignore(const char *devname) { static const char keyword[] = ""; @@ -187,6 +187,74 @@ inline void ident_init(struct mddev_ident *ident) ident->uuid_set = 0; } +/** + * _ident_set_devname()- verify devname and set it in &mddev_ident. + * @ident: pointer to &mddev_ident. + * @devname: devname to be set. + * @cmdline: context dependent actions. If set, ignore keyword is not allowed. + * + * @devname can have following forms: + * '' keyword (if allowed) + * /dev/md{number} + * /dev/md_d{number} (legacy) + * /dev/md_{name} + * /dev/md/{name} + * {name} - anything that doesn't start from '/' or '<'. + * + * {name} must follow name's criteria. + * If criteria passed, duplicate memory and set devname in @ident. + * + * Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR. + */ +mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname, + const bool cmdline) +{ + assert(ident); + assert(devname); + + static const char named_dev_pref[] = DEV_NUM_PREF "_"; + static const int named_dev_pref_size = sizeof(named_dev_pref) - 1; + const char *prop_name = "devname"; + const char *name; + + if (ident->devname) { + ident_log(prop_name, devname, "Already defined", cmdline); + return MDADM_STATUS_ERROR; + } + + if (is_devname_ignore(devname) == true) { + if (!cmdline) + goto pass; + + ident_log(prop_name, devname, "Special keyword is invalid in this context", + cmdline); + return MDADM_STATUS_ERROR; + } + + if (is_devname_md_numbered(devname) == true || is_devname_md_d_numbered(devname) == true) + goto pass; + + if (strncmp(devname, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) + name = devname + DEV_MD_DIR_LEN; + else if (strncmp(devname, named_dev_pref, named_dev_pref_size) == 0) + name = devname + named_dev_pref_size; + else + name = devname; + + if (*name == '/' || *name == '<') { + ident_log(prop_name, devname, "Cannot be started from \'/\' or \'<\'", cmdline); + return MDADM_STATUS_ERROR; + } + + if (is_string_lq(name, MD_NAME_MAX + 1) == false) { + ident_log(prop_name, devname, "Invalid length", cmdline); + return MDADM_STATUS_ERROR; + } +pass: + ident->devname = xstrdup(devname); + return MDADM_STATUS_SUCCESS; +} + /** * _ident_set_name()- set name in &mddev_ident. * @ident: pointer to &mddev_ident. @@ -219,6 +287,14 @@ static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *nam return MDADM_STATUS_SUCCESS; } +/** + * ident_set_devname()- exported, for cmdline. + */ +mdadm_status_t ident_set_devname(struct mddev_ident *ident, const char *name) +{ + return _ident_set_devname(ident, name, true); +} + /** * ident_set_name()- exported, for cmdline. */ @@ -464,29 +540,7 @@ void arrayline(char *line) for (w = dl_next(line); w != line; w = dl_next(w)) { if (w[0] == '/' || strchr(w, '=') == NULL) { - /* This names the device, or is ''. - * The rules match those in create_mddev. - * 'w' must be: - * /dev/md/{anything} - * /dev/mdNN - * /dev/md_dNN - * - * or anything that doesn't start '/' or '<' - */ - if (is_devname_ignore(w) == true || - strncmp(w, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 || - (w[0] != '/' && w[0] != '<') || - is_devname_md_numbered(w) == true || - is_devname_md_d_numbered(w) == true) { - /* This is acceptable */; - if (mis.devname) - pr_err("only give one device per ARRAY line: %s and %s\n", - mis.devname, w); - else - mis.devname = w; - }else { - pr_err("%s is an invalid name for an md device - ignored.\n", w); - } + _ident_set_devname(&mis, w, false); } else if (strncasecmp(w, "uuid=", 5) == 0) { if (mis.uuid_set) pr_err("only specify uuid once, %s ignored.\n", diff --git a/mdadm.c b/mdadm.c index 5084c348..5f8dc1a6 100644 --- a/mdadm.c +++ b/mdadm.c @@ -1284,7 +1284,8 @@ int main(int argc, char *argv[]) pr_err("an md device must be given in this mode\n"); exit(2); } - ident.devname = devlist->devname; + if (ident_set_devname(&ident, devlist->devname) != MDADM_STATUS_SUCCESS) + exit(1); if ((int)ident.super_minor == -2 && c.autof) { pr_err("--super-minor=dev is incompatible with --auto\n"); @@ -1301,13 +1302,6 @@ int main(int argc, char *argv[]) exit(1); } } else { - char *bname = basename(ident.devname); - - if (strlen(bname) > MD_NAME_MAX) { - pr_err("Name %s is too long.\n", ident.devname); - exit(1); - } - ret = stat(ident.devname, &stb); if (ident.super_minor == -2 && ret != 0) { pr_err("--super-minor=dev given, and listed device %s doesn't exist.\n", diff --git a/mdadm.h b/mdadm.h index 62e15dfa..92a0beb5 100644 --- a/mdadm.h +++ b/mdadm.h @@ -1638,6 +1638,7 @@ extern void manage_fork_fds(int close_all); extern int continue_via_systemd(char *devnm, char *service_name, char *prefix); extern void ident_init(struct mddev_ident *ident); +extern mdadm_status_t ident_set_devname(struct mddev_ident *ident, const char *devname); extern mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name); extern int parse_auto(char *str, char *msg, int config); @@ -1660,7 +1661,7 @@ extern void print_escape(char *str); extern int use_udev(void); extern unsigned long GCD(unsigned long a, unsigned long b); extern int conf_name_is_free(char *name); -extern bool is_devname_ignore(char *devname); +extern bool is_devname_ignore(const char *devname); extern bool is_devname_md_numbered(const char *devname); extern bool is_devname_md_d_numbered(const char *devname); extern int conf_verify_devnames(struct mddev_ident *array_list); diff --git a/tests/00createnames b/tests/00createnames index 064eeef2..a95e7d2b 100644 --- a/tests/00createnames +++ b/tests/00createnames @@ -39,3 +39,6 @@ mdadm -S "/dev/md0" names_create "/dev/md0" "name" names_verify "/dev/md0" "empty" "name" mdadm -S "/dev/md0" + +# Devnode is a special ignore keyword. Should be rejected. +names_create "" "name", "true" diff --git a/tests/templates/names_template b/tests/templates/names_template index 8d2b5c81..6181bfaa 100644 --- a/tests/templates/names_template +++ b/tests/templates/names_template @@ -2,6 +2,7 @@ function names_create() { local DEVNAME=$1 local NAME=$2 + local NEG_TEST=$3 if [[ -z "$NAME" ]]; then mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force @@ -9,6 +10,12 @@ function names_create() { mdadm -CR "$DEVNAME" --name="$NAME" --metadata=1.2 -l0 -n 1 $dev0 --force fi + if [[ "$NEG_TEST" == "true" ]]; then + [[ "$?" == "0" ]] && return 0 + echo "Negative verification failed" + exit 1 + fi + if [[ "$?" != "0" ]]; then echo "Cannot create device." exit 1 From patchwork Thu Jun 1 07:27:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mariusz Tkaczyk X-Patchwork-Id: 13263117 X-Patchwork-Delegate: jes@trained-monkey.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 21181C7EE2F for ; Thu, 1 Jun 2023 07:29:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231974AbjFAH3l (ORCPT ); Thu, 1 Jun 2023 03:29:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231983AbjFAH3g (ORCPT ); Thu, 1 Jun 2023 03:29:36 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 72FC213E for ; Thu, 1 Jun 2023 00:29:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1685604572; x=1717140572; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=33Slq9VHutbGkGvOaaHGTVAAWa8V2t3BXC89w4XKpEQ=; b=Guk9gCRMXMJivK7cABI4RVKgmXHBqokfUy0Ekjzn/ezkD9t6idwlWCWo 1J0tDDVXkkiYMCX3pUPbdxCkwtkzoSlR7XR6yROgFIyjsdy3DHQgP08r9 yWZ9V3XhsrA1Oc6Vt3xN0ZiZ7C0qNoAyA48E4XXVRQ5bRPwK05RxmAM/u EHgEYybeYrB2lY1Uu1g3sGPafU7nhdFN3PS5pKJea6NP8Cf//kK2+C6fW SLO7vU+p8tZCedhTejbGTTTIqxzQNri6sFRLQpmy92nyxFht25BZ8iob8 KLXEo6ySuo/kekJd2UQ37KyKq2BqeDay13/OIpH/j/OjIBXFIphGz4PLc g==; X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="345007181" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="345007181" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10727"; a="707221140" X-IronPort-AV: E=Sophos;i="6.00,209,1681196400"; d="scan'208";a="707221140" Received: from mtkaczyk-devel.igk.intel.com ([10.102.105.40]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jun 2023 00:28:46 -0700 From: Mariusz Tkaczyk To: jes@trained-monkey.org Cc: linux-raid@vger.kernel.org, colyli@suse.de Subject: [PATCH 6/6] mdadm: Follow POSIX Portable Character Set Date: Thu, 1 Jun 2023 09:27:50 +0200 Message-Id: <20230601072750.20796-7-mariusz.tkaczyk@linux.intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> References: <20230601072750.20796-1-mariusz.tkaczyk@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-raid@vger.kernel.org When the user creates a device with a name that contains whitespace, mdadm timeouts and throws an error. This issue is caused by udev, which truncates /dev/md link until the first whitespace. This patch introduces prohibition of characters other than A-Za-z0-9.-_ in the device name. Also, it prohibits using leading "-" in device name, so name won't be confused with cli parameter. Set of allowed characters is taken from POSIX 3.280 Portable Character Set. Also, device name length now is limited to NAME_MAX. In some places, there are other requirements for string length (e.g. size up to MD_NAME_MAX for device name). This routine is made to follow POSIX and other, more strict limitations should be checked separately. We are aware of the risk of regression in exceptional cases (as escape_devname function is removed) that should be fixed by updating the array name. The POSIX validation is added for: - 'name' parameter in every mode. - first devlist entry, for Build, Create, Assemble, Manage, Grow. - config entries, both devname and "name=". Additionally, some manual cleanups are made. Signed-off-by: Mariusz Tkaczyk --- Detail.c | 17 ++++-------- config.c | 13 ++++++--- lib.c | 58 ++++++++++++++++++++++++++++----------- mdadm.8.in | 70 ++++++++++++++++++++--------------------------- mdadm.conf.5.in | 4 --- mdadm.h | 2 +- super-intel.c | 47 ++++++++++++++++--------------- tests/00confnames | 4 +-- 8 files changed, 113 insertions(+), 102 deletions(-) diff --git a/Detail.c b/Detail.c index 206d88e3..57ac336f 100644 --- a/Detail.c +++ b/Detail.c @@ -254,11 +254,9 @@ int Detail(char *dev, struct context *c) fname_from_uuid(st, info, nbuf, ':'); printf("MD_UUID=%s\n", nbuf + 5); mp = map_by_uuid(&map, info->uuid); - if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) { - printf("MD_DEVNAME="); - print_escape(mp->path + DEV_MD_DIR_LEN); - putchar('\n'); - } + + if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) + printf("MD_DEVNAME=%s\n", mp->path + DEV_MD_DIR_LEN); if (st->ss->export_detail_super) st->ss->export_detail_super(st); @@ -271,12 +269,9 @@ int Detail(char *dev, struct context *c) __fname_from_uuid(mp->uuid, 0, nbuf, ':'); printf("MD_UUID=%s\n", nbuf+5); } - if (mp && mp->path && - strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) { - printf("MD_DEVNAME="); - print_escape(mp->path + DEV_MD_DIR_LEN); - putchar('\n'); - } + if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) + printf("MD_DEVNAME=%s\n", mp->path + DEV_MD_DIR_LEN); + map_free(map); } if (!c->no_devices && sra) { diff --git a/config.c b/config.c index d80747a2..38a903c5 100644 --- a/config.c +++ b/config.c @@ -199,9 +199,9 @@ inline void ident_init(struct mddev_ident *ident) * /dev/md_d{number} (legacy) * /dev/md_{name} * /dev/md/{name} - * {name} - anything that doesn't start from '/' or '<'. + * {name} * - * {name} must follow name's criteria. + * {name} must follow name's criteria and be POSIX compatible. * If criteria passed, duplicate memory and set devname in @ident. * * Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR. @@ -241,8 +241,8 @@ mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname else name = devname; - if (*name == '/' || *name == '<') { - ident_log(prop_name, devname, "Cannot be started from \'/\' or \'<\'", cmdline); + if (is_name_posix_compatible(name) == false) { + ident_log(prop_name, name, "Not POSIX compatible", cmdline); return MDADM_STATUS_ERROR; } @@ -283,6 +283,11 @@ static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *nam return MDADM_STATUS_ERROR; } + if (is_name_posix_compatible(name) == false) { + ident_log(prop_name, name, "Not POSIX compatible", cmdline); + return MDADM_STATUS_ERROR; + } + snprintf(ident->name, MD_NAME_MAX + 1, "%s", name); return MDADM_STATUS_SUCCESS; } diff --git a/lib.c b/lib.c index 999cd520..d40922d9 100644 --- a/lib.c +++ b/lib.c @@ -483,24 +483,50 @@ void print_quoted(char *str) putchar(q); } -void print_escape(char *str) +/** + * is_alphanum() - Check if sign is letter or digit. + * @c: char to analyze. + * + * Similar to isalnum() but additional locales are excluded. + * + * Return: %true on success, %false otherwise. + */ +bool is_alphanum(const char c) { - /* print str, but change space and tab to '_' - * as is suitable for device names - */ - for (; *str; str++) { - switch (*str) { - case ' ': - case '\t': - putchar('_'); - break; - case '/': - putchar('-'); - break; - default: - putchar(*str); - } + if (isupper(c) || islower(c) || isdigit(c) != 0) + return true; + return false; +} + +/** + * is_name_posix_compatible() - Check if name is POSIX compatible. + * @name: name to check. + * + * POSIX portable file name character set contains ASCII letters, + * digits, '_', '.', and '-'. Also forbid leading '-'. + * The length of the name cannot exceed NAME_MAX - 1 (ensure NULL ending). + * + * Return: %true on success, %false otherwise. + */ +bool is_name_posix_compatible(const char * const name) +{ + assert(name); + + char allowed_symbols[] = "-_."; + const char *n = name; + + if (!is_string_lq(name, NAME_MAX)) + return false; + + if (*n == '-') + return false; + + while (*n != '\0') { + if (!is_alphanum(*n) && !strchr(allowed_symbols, *n)) + return false; + n++; } + return true; } int check_env(char *name) diff --git a/mdadm.8.in b/mdadm.8.in index b7159509..3142436f 100644 --- a/mdadm.8.in +++ b/mdadm.8.in @@ -364,7 +364,7 @@ Use the Intel(R) Matrix Storage Manager metadata format. This creates a which is managed in a similar manner to DDF, and is supported by an option-rom on some platforms: .IP -.B https://www.intel.com/content/www/us/en/support/products/122484/memory-and-storage/ssd-software/intel-virtual-raid-on-cpu-intel-vroc.html +.B https://www.intel.com/content/www/us/en/support/products/122484 .PP .RE @@ -932,17 +932,14 @@ option will be ignored. .BR \-N ", " \-\-name= Set a .B name -for the array. This is currently only effective when creating an -array with a version-1 superblock, or an array in a DDF container. -The name is a simple textual string that can be used to identify array -components when assembling. If name is needed but not specified, it -is taken from the basename of the device that is being created. -e.g. when creating -.I /dev/md/home -the -.B name -will default to -.IR home . +for the array. It must be +.BR "POSIX PORTABLE NAME" +compatible and cannot be longer than 32 chars. This is effective when creating an array +with a v1 metadata, or an external array. + +If name is needed but not specified, it is taken from the basename of the device +that is being created. See +.BR "DEVICE NAMES" .TP .BR \-R ", " \-\-run @@ -1132,8 +1129,10 @@ is much safer. .TP .BR \-N ", " \-\-name= -Specify the name of the array to assemble. This must be the name -that was specified when creating the array. It must either match +Specify the name of the array to assemble. It must be +.BR "POSIX PORTABLE NAME" +compatible and cannot be longer than 32 chars. This must be the name +that was specified when creating the array. It must either match the name stored in the superblock exactly, or it must match with the current .I homehost @@ -2179,14 +2178,17 @@ Usage: .I md-device .BI \-\-chunk= X .BI \-\-level= Y -.br .BI \-\-raid\-devices= Z .I devices .PP -This usage will initialise a new md array, associate some devices with +This usage will initialize a new md array, associate some devices with it, and activate the array. +.I md-device +is a new device. This could be standard name or chosen name. For details see: +.BR "DEVICE NAMES" + The named device will normally not exist when .I "mdadm \-\-create" is run, but will be created by @@ -2227,24 +2229,6 @@ array. This feature can be overridden with the .B \-\-force option. -When creating an array with version-1 metadata a name for the array is -required. -If this is not given with the -.B \-\-name -option, -.I mdadm -will choose a name based on the last component of the name of the -device being created. So if -.B /dev/md3 -is being created, then the name -.B 3 -will be chosen. -If -.B /dev/md/home -is being created, then the name -.B home -will be used. - When creating a partition based array, using .I mdadm with version-1.x metadata, the partition type should be set to @@ -2429,12 +2413,10 @@ and The .B name -option updates the subarray name in the metadata, it may not affect the -device node name or the device node symlink until the subarray is -re\-assembled. If updating -.B name -would change the UUID of an active subarray this operation is blocked, -and the command will end in an error. +option updates the subarray name in the metadata. It must be +.BR "POSIX PORTABLE NAME" +compatible and cannot be longer than 32 chars. If successes, new value will be respected after +next assembly. The .B ppl @@ -3395,6 +3377,10 @@ When .B \-\-incremental mode is used, this file gets a list of arrays currently being created. +.SH POSIX PORTABLE NAME +A valid name can only consist of characters "A-Za-z0-9.-_". +The name cannot start with a leading "-" and cannot exceed 255 chars. + .SH DEVICE NAMES .I mdadm @@ -3416,6 +3402,10 @@ can be given, or just the suffix of the second sort of name, such as .I home can be given. +In every style, raw name must be compatible with +.BR "POSIX PORTABLE NAME" +and has to be no longer than 32 chars. + When .I mdadm chooses device names during auto-assembly or incremental assembly, it diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in index bc2295c2..94e23dd0 100644 --- a/mdadm.conf.5.in +++ b/mdadm.conf.5.in @@ -717,10 +717,6 @@ ARRAY /dev/md/home UUID=9187a482:5dde19d9:eea3cc4a:d646ab8b .br auto=part .br -# The name of this array contains a space. -.br -ARRAY /dev/md9 name='Data Storage' -.sp POLICY domain=domain1 metadata=imsm path=pci-0000:00:1f.2-scsi-* .br action=spare diff --git a/mdadm.h b/mdadm.h index 92a0beb5..db05d810 100644 --- a/mdadm.h +++ b/mdadm.h @@ -1617,6 +1617,7 @@ extern int check_raid(int fd, char *name); extern int check_partitions(int fd, char *dname, unsigned long long freesize, unsigned long long size); +extern bool is_name_posix_compatible(const char *path); extern int fstat_is_blkdev(int fd, char *devname, dev_t *rdev); extern int stat_is_blkdev(char *devname, dev_t *rdev); @@ -1657,7 +1658,6 @@ extern int conf_get_monitor_delay(void); extern char *conf_line(FILE *file); extern char *conf_word(FILE *file, int allow_key); extern void print_quoted(char *str); -extern void print_escape(char *str); extern int use_udev(void); extern unsigned long GCD(unsigned long a, unsigned long b); extern int conf_name_is_free(char *name); diff --git a/super-intel.c b/super-intel.c index ae0f4a8c..1aa5fec9 100644 --- a/super-intel.c +++ b/super-intel.c @@ -5533,40 +5533,37 @@ static void imsm_update_version_info(struct intel_super *super) } } -static int check_name(struct intel_super *super, char *name, int quiet) +/** + * imsm_check_name() - check imsm naming criteria. + * @super: &intel_super pointer, not NULL. + * @name: name to check. + * @verbose: verbose level. + * + * Name must be no longer than &MAX_RAID_SERIAL_LEN and must be unique across volumes. + * + * Returns: &true if @name matches, &false otherwise. + */ +static bool imsm_is_name_allowed(struct intel_super *super, const char * const name, + const int verbose) { struct imsm_super *mpb = super->anchor; - char *reason = NULL; - char *start = name; - size_t len = strlen(name); int i; - if (len > 0) { - while (isspace(start[len - 1])) - start[--len] = 0; - while (*start && isspace(*start)) - ++start, --len; - memmove(name, start, len + 1); + if (is_string_lq(name, MAX_RAID_SERIAL_LEN + 1) == false) { + pr_vrb("imsm: Name \"%s\" is too long\n", name); + return false; } - if (len > MAX_RAID_SERIAL_LEN) - reason = "must be 16 characters or less"; - else if (len == 0) - reason = "must be a non-empty string"; - for (i = 0; i < mpb->num_raid_devs; i++) { struct imsm_dev *dev = get_imsm_dev(super, i); if (strncmp((char *) dev->volume, name, MAX_RAID_SERIAL_LEN) == 0) { - reason = "already exists"; - break; + pr_vrb("imsm: Name \"%s\" already exists\n", name); + return false; } } - if (reason && !quiet) - pr_err("imsm volume name %s\n", reason); - - return !reason; + return true; } static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, @@ -5661,8 +5658,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, } } - if (!check_name(super, name, 0)) + if (imsm_is_name_allowed(super, name, 1) == false) return 0; + dv = xmalloc(sizeof(*dv)); dev = xcalloc(1, sizeof(*dev) + sizeof(__u32) * (info->raid_disks - 1)); /* @@ -7975,7 +7973,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray, char *ep; int vol; - if (!check_name(super, name, 0)) + if (imsm_is_name_allowed(super, name, 1) == false) return 2; vol = strtoul(subarray, &ep, 10); @@ -10302,7 +10300,8 @@ static void imsm_process_update(struct supertype *st, if (a->info.container_member == target) break; dev = get_imsm_dev(super, u->dev_idx); - if (a || !check_name(super, name, 1)) { + + if (a || !dev || imsm_is_name_allowed(super, name, 0) == false) { dprintf("failed to rename subarray-%d\n", target); break; } diff --git a/tests/00confnames b/tests/00confnames index 4990cb5e..9961772c 100644 --- a/tests/00confnames +++ b/tests/00confnames @@ -79,10 +79,10 @@ names_verify "/dev/md127" "name" "name" mdadm -S "/dev/md127" # 11. with some special symbols and locales, no . -# It needs to wait a while for timeout because udev cannot create a link - known issue. +# should be ignored. names_make_conf $_UUID "tźż-\.,<>st+-" "empty" $config mdadm -I $dev0 --config=$config -names_verify "/dev/md127" "tźż-\.,<>st+-" "name" +names_verify "/dev/md127" "name" "name" mdadm -S "/dev/md127" # 12. No and set.