Re: [RFC] FC pass thru - Rev IV

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

 



FUJITA Tomonori wrote:
> On Thu, 27 Nov 2008 13:51:51 +0200
> Boaz Harrosh <bharrosh@xxxxxxxxxxx> wrote:
> 
>>>>>> +	spin_lock_irqsave(&job->job_lock, flags);
>>>>>> +	job->state_flags |= FC_RQST_STATE_DONE;
>>>>>> +	job->ref_cnt--;
>>>>>> +	spin_unlock_irqrestore(&job->job_lock, flags);
>>>>>> +
>>>>>> +	err = job->req->errors = job->reply->result;
>>>>>> +	if (err < 0)
>>>>>> +		/* we're only returning the result field in the reply */
>>>>>> +		job->req->sense_len = sizeof(uint32_t);
>>>>>> +	else
>>>>>> +		job->req->sense_len = job->reply_len;
>>>>>> +
>>>>>> +	/*
>>>>>> +	 * we'll cheat: tell blk layer all of the xmt data was sent.
>>>>>> +	 * but try to be honest about the amount of rcv data received
>>>>>> +	 */
>>>>>> +	if (rsp)
>>>>>> +		blk_end_bidi_request(job->req, err, blk_rq_bytes(job->req),
>>>>>> +	    			     job->reply->reply_payload_rcv_len);
>>>>>> +	else
>>>>>> +		blk_end_request(job->req, err, blk_rq_bytes(job->req));
>>>>> I think that you can use blk_end_bidi_request() for non-bidi requests:
>>>>>
>>>>> 	blk_end_bidi_request(job->req, err, blk_rq_bytes(job->req),
>>>>> 			rsp ?
>>>>> 			 job->reply->reply_payload_rcv_len : 0);
>>>>>
>>>>>
>>>>> I guess that it would be better to have one function to complete a
>>>>> request, instead of blk_end_bidi_request and blk_end_request.
>>>>>
>>>>>
>>>> +	/*
>>>> +	 * tell blk layer all of the xmt data was sent.
>>>> +	 * but set residual count to: requested - received
>>>> +	 */
>>>> +
>>>> +	if (rsp) {
>>>> +		bytes_requested = blk_rq_bytes(rsp);
>>>> +		rsp->data_len = bytes_requested - job->reply->reply_payload_rcv_len;
>>>> +	}
>>>> +
>>>> +	blk_end_bidi_request(job->req, err, blk_rq_bytes(job->req), bytes_requested);
>>>>
>>>> The residual count is left in req->data_len. Does bsg have a way to return the
>>>> residual to user-mode? It must, since Pete was using that for sure. Note that
>>>> you are looking for the bidi_read residual count.
>>> Yeah, bsg has. struct sg_io_v4 has:
>>>
>>> __s32 din_resid;	/* [o] din_xfer_len - actual_din_xfer_len */
>>> __s32 dout_resid;	/* [o] dout_xfer_len - actual_dout_xfer_len */
>>>
>>>
>>>> As was said by people. You must complete ALL bytes on both sides. Residual information
>>>> is passed through req->data_len. Other wise the request is still active.
>>>>
>>>> (And yes blk_end_request uses blk_end_bidi_request internally)
>>> We always complete all bytes on both sides. So why we do something
>>> like:
>>>
>>> int blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
>>> {
>>> 	unsigned int bidi_bytes	= 0;
>>>
>>> 	if (blk_bidi_rq(rq))
>>> 		bidi_bytes = req->next_rq->data_len;
>>>
>>> 	return blk_end_io(rq, error, nr_bytes, bidi_bytes, NULL);
>>> }
>>>
>>> The callers can do something like:
>>>
>>> blk_end_request(rq, err, rq->data_len);
>>> rq-->next_rq->data_len = resid;
>> Sorry TOMO, I do not understand what you mean. Do you say that we should
>> change blk_end_request() in blk-core.c ?
> 
> Having two kinds of functions (blk_end_request and
> blk_end_bidi_request) to complete requests confuse people. As we saw,
> developers tend to do something like this:
> 
> +	if (rsp)
> +		blk_end_bidi_request(job->req, err, blk_rq_bytes(job->req),
> +	    			     job->reply->reply_payload_rcv_len);
> +	else
> +		blk_end_request(job->req, err, blk_rq_bytes(job->req));
> 
> 
> The callers don't care about whether a request is bidi or not. It's be
> simpler to have a single function to complete a request (whether a
> request is bidi or not) rather than having two different functions.
> 
> We must complete all bytes on both sides with a bidi request. So why
> can't we modify blk_end_request to handle both bidi and non-bidi
> requests:
> 
> int blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
> {
>  	unsigned int bidi_bytes	= 0;
> 
> 	if (blk_bidi_rq(rq))
> 		bidi_bytes = blk_rq_bytes(rq->next_rq);
> 
> 	return blk_end_io(rq, error, nr_bytes, bidi_bytes, NULL);
> }
> 
> 
>> In anyway, the code you suggest has a bug you can not use rq-> after call to blk_end_io()
>> because it might not exist at this point. You must set residual before. And also
> 
> What is 'rq->' exactly?
> 
> We must set residual before calling blk_end_request? Really?
> 
> Note that scsi-ml and bsg (blk_execute_rq) work differently. For
> scsi-ml, blk_end_io frees request structure (end_that_request_last)
> but for blk_execute_rq, it doesn't.
> 

It does not matter if bsg or any other user has an extra reference
on the request (so end_that_request_last does not deallocate the
request). The end_io function is called from within the end_that_request_last
so setting the residual into req->data_len will be to late.

> 
> Anyway, it's fine to set bidi_resid before blk_end_request, I
> guess. FC pass thru code could do something like this if we modify
> blk_end_request in the above way:
> 
> /* we calculate bidi_resid here */
> 
> if (blk_bidi_rq(req))
> 	req->next_rq->data_len = bidi_resid;
> 

No that will not work. You lost the req->next_rq->data_len byte-count
and blk_end_request() will not be able to complete all bytes of req->next_rq.

Please see scsi_end_bidi_request() for the only way to complete a bidi
request with returned residual count on both sides.

> blk_end_request(req, 0, blk_rq_bytes(req));

The way blk_end_request() is now it cannot complete bidi requests.
because of residual count missing. I have shown above the only way
that you can complete both bidi or uni request with a single call to
blk_end_bidi_request(). If you want people not to get confused it is
blk_end_request() that should be dropped.

Boaz

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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux