Re: [PATCH] gadget: mass_storage: make mass_storage support multi-luns with different logic block size

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 11 Oct 2011, Barry Song wrote:

> From: YuPing Luo <yuping.luo@xxxxxxx>
> 
> With Peiyu's patch "gadget: mass_storage: adapt logic block size to bound block
> devices" (http://www.spinics.net/lists/linux-usb/msg50791.html), now mass storage
> can adjust logic block size dynamically based on real devices.
> Then there is one issue caused by it, if two luns have different logic block size,
> mass storage can't work.
> Let's check the current software flow:
> 1. get_next_command(): call received_cbw();
> 2. received_cbw(): update common->lun = cbw->Lun, but common->curlen is not updated;
> 3. do_scsi_command(): in READ_X and WRITE_X commands, common->data_size_from_cmnd is
> updated by common->curlun->blkbits;
> 4. check_command(): update common->curlun according to common->lun
> As you can see, the step 3 uses wrong common->curlun, then wrong common->curlun->blkbits.
> If the two luns have same blkbits, there isn't issue. Otherwise, both will fail.
> This patch moves the common->curlun update to step 2(received_cbw()), then make sure
> step 3 gets right blkbits and right data_size_from_cmnd.

Yes, this is a very real problem -- good work finding it!  However your 
solution could be improved.  Concentrating just on file_storage.c:

> @@ -2412,6 +2412,8 @@ static int do_scsi_command(struct fsg_dev *fsg)
>  		break;
>  
>  	case READ_6:
> +		if (unlikely(!fsg->curlun))
> +			goto unknown_cmnd;
>  		i = fsg->cmnd[4];
>  		fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << fsg->curlun->blkbits;

Instead of adding all theses checks, it would be better to add a new
flag: fsg->data_size_is_in_blocks.  Skip doing the bit shifts here and
set the flag instead.  Then have check_command() do the test and the
bit shift if the flag is set.

> @@ -2642,6 +2654,10 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
>  	if (fsg->data_size == 0)
>  		fsg->data_dir = DATA_DIR_NONE;
>  	fsg->lun = cbw->Lun;
> +	if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
> +		fsg->curlun = &fsg->luns[fsg->lun];
> +	else
> +		fsg->curlun = NULL;
>  	fsg->tag = cbw->Tag;
>  	return 0;
>  }

Instead of adding this here, it should be in get_next_command().  Then
it would be obvious that you missed the !transport_is_bbb() case, which
needs a similar change (and an assignment to fsg->lun).  In fact, this 
enw code can go outside the big "if" statement.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux