[stgt] [PATCH] check for valid parameters when passing tgtadm commands
Doron Shoham
dorons at Voltaire.COM
Wed Oct 8 10:04:40 CEST 2008
FUJITA Tomonori wrote:
> On Wed, 08 Oct 2008 08:45:32 +0200
> Doron Shoham <dorons at voltaire.com> wrote:
>
>> FUJITA Tomonori wrote:
>>> On Tue, 07 Oct 2008 18:01:31 +0200
>>> Doron Shoham <dorons at Voltaire.COM> wrote:
>>>
>>>> check for valid parameters when passing tgtadm commands
>>>>
>>>> Signed-off-by: Doron Shoham <dorons at voltaire.com>
>>>> ---
>>>> usr/tgtadm.c | 65 +++++++++++++++++++++++++++++++++++++++++-----------------
>>>> 1 files changed, 46 insertions(+), 19 deletions(-)
>>>>
>>>> diff --git a/usr/tgtadm.c b/usr/tgtadm.c
>>>> index 9e90b40..21bb245 100644
>>>> --- a/usr/tgtadm.c
>>>> +++ b/usr/tgtadm.c
>>>> @@ -484,35 +484,38 @@ int main(int argc, char **argv)
>>>> /* exit(EINVAL); */
>>>> }
>>>>
>>>> - if ((name || value) && op != OP_UPDATE) {
>>>> - eprintf("only 'update' operation takes"
>>>> - " 'name' and 'value' options\n");
>>>> - exit(EINVAL);
>>>> - }
>>> Hm, I think that this is a valid checking. Why did you remove it?
>> My idea was to check that every option
>> receives its own valid parameters.
>
> But if you do, the code would have tons of duplications:
>
>
> case OP_SHOW:
> if (name || value)
> eprintf("only 'update' operation takes"
> " 'name' and 'value' options\n");
> exit(EINVAL);
> break;
> case OP_DELETE:
> if (name || value)
> eprintf("only 'update' operation takes"
> " 'name' and 'value' options\n");
> exit(EINVAL);
> break;
> case OP_BIND:
> if (name || value)
> eprintf("only 'update' operation takes"
> " 'name' and 'value' options\n");
> exit(EINVAL);
> break;
> case OP_UNBIND:
> if (name || value)
> eprintf("only 'update' operation takes"
> " 'name' and 'value' options\n");
> exit(EINVAL);
> break;
> case OP_UPDATE:
>
>
> Or
>
> void check_name_value(void)
> {
> if (name || value)
> eprintf("only 'update' operation takes"
> " 'name' and 'value' options\n");
> exit(EINVAL);
> }
>
> case OP_SHOW:
> check_name_value();
> break;
> case OP_BIND:
> check_name_value();
> break;
>
>
> Neither looks good.
>
>
>>>> - if ((!name && value) || (name && !value)) {
>>>> - eprintf("'name' and 'value' options are necessary\n");
>>>> - exit(EINVAL);
>>>> - }
>>> Ditto.
>> This check moved into the proper location -
>> in the switch under MODE_TARGET
>>
>>>> if (mode == MODE_TARGET) {
>>>> + if ((tid < 0 && (op != OP_SHOW))) {
>>>> + eprintf("'tid' option is necessary\n");
>>>> + exit(EINVAL);
>>>> + }
>>>> switch (op) {
>>>> case OP_NEW:
>>>> + if (!targetname) {
>>>> + eprintf("creating a new target needs --targetname\n");
>>>> + exit(EINVAL);
>>>> + }
>>>> + break;
>>>> + case OP_SHOW:
>>>> + break;
>>>> case OP_DELETE:
>>>> + break;
>>>> case OP_BIND:
>>>> case OP_UNBIND:
>>>> - case OP_UPDATE:
>>>> - if (op == OP_NEW && !targetname) {
>>>> - eprintf("creating a new target needs the name\n");
>>>> + if (!address) {
>>>> + eprintf("%s operation requires initiator-address\n", op==OP_BIND?"bind":"unbind");
>>>> exit(EINVAL);
>>>> }
>>>> -
>>>> - if (tid < 0) {
>>>> - eprintf("'tid' option is necessary\n");
>>>> + break;
>>>> + case OP_UPDATE:
>>>> + if ((!name || !value)) {
>>>> + eprintf("update operation requires 'name' and 'value' options\n");
>>>> exit(EINVAL);
>>>> }
>>>> break;
>> This is where the check move into.
>
> This checks only 'update' option. With your change, we can't catch a
> mistake like:
>
> tgtadm --op delete --mode target --name hoge --value xyz
>
>
this specific mistake will be caught because --tid isn't provided.
following your method we'll need to check many more combinations.
For example, why not checking:
tgtadm --mode target --op show --tid=1 --initiator-address=xyz
In my opinion, as long as the user has provided all of the valid options
the command is a valid command.
so it won't be a mistake to write
tgtadm --op delete --mode target --tid=1 --name hoge --value xyz
it will just delete tid 1.
>
>>>> default:
>>>> + eprintf("option %d not supported in target mode\n", op);
>>>> + exit(EINVAL);
>>>> break;
>>>> }
>>>> }
>>>> @@ -541,8 +544,32 @@ int main(int argc, char **argv)
>>>> }
>>>> break;
>>>> default:
>>>> - eprintf("the update operation can't"
>>>> - " handle accounts\n");
>>>> + eprintf("option %d not supported in account mode\n", op);
>>>> + exit(EINVAL);
>>>> + break;
>>>> + }
>>>> + }
>>>> +
>>>> + if (mode == MODE_DEVICE) {
>>>> + if (tid < 0) {
>>>> + eprintf("'tid' option is necessary\n");
>>>> + exit(EINVAL);
>>>> + }
>>>> + if (!lun) {
>>>> + eprintf("'lun' option is necessary\n");
>>>> + exit(EINVAL);
>>>> + }
>>>> + switch (op) {
>>>> + case OP_NEW:
>>>> + if (!path) {
>>>> + eprintf("'backing-store' option is necessary\n");
>>>> + exit(EINVAL);
>>>> + }
>>>> + break;
>>> The null backing store code doesn't the patch option. We can add a
>>> trick here. Feel free to do it in a different patch later.
>> I didn't understand what is the problem,
>> can you please explain?
>
> The null backing store code doesn't need the path option because it
> doesn't perform any I/O. It's just for performance measurements.
>
> Check out usr/bs_null.c
As far as I understand you have to use -b (path) option
in order to create a null backing store.
If I'll try to do something like this:
tgtadm --mode logicalunit --op new --tid=1 --lun=1 -E null
tgtadm: invalid request
and
tgtadm --mode logicalunit --op new --tid=1 --lun=1 -b xyz -E null
tgtadm --mode target --op show
Target 1: doron
System information:
Driver: iscsi
State: ready
I_T nexus information:
LUN information:
LUN: 0
Type: controller
SCSI ID: deadbeaf1:0
SCSI SN: beaf10
Size: 0 MB
Online: Yes
Removable media: No
Backing store: No backing store
LUN: 1
Type: disk
SCSI ID: deadbeaf1:1
SCSI SN: beaf11
Size: 1099512 MB
Online: Yes
Removable media: No
Backing store: xyz
Account information:
ACL information:
>
>
>>>> + case OP_DELETE:
>>>> + break;
>>>> + default:
>>>> + eprintf("option %d not supported in logicalunit mode\n", op);
>>>> exit(EINVAL);
>>>> break;
>>>> }
>>>> --
>>>> 1.5.3.8
>>>>
>>>>
>>>> I know that there many more commands which I didn't checked.
>>>> We still need to add some more testing for the different modes (SYSTEM,SESSION and CONNECTION).
>>>> And to document them as well.
>>> tgtadm is in a mess (the error check, a way to communicate with tgtd,
>>> etc). Any effort to clean up it are really welcome.
>> The first thing to do is to document all the "hidden" options -
>> that way it will be more clear what each option does and
>> what parameters it receives.
>
> Yeah, documenting is also great.
--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the stgt
mailing list