Re: [ 04/21] target/pscsi: Fix page increment

2013-03-18 Thread Nicholas A. Bellinger
On Tue, 2013-03-19 at 01:18 +, Ben Hutchings wrote:
> On Tue, 2013-03-19 at 08:56 +0800, Asias He wrote:
> > On Mon, Mar 18, 2013 at 11:30:47PM +, Ben Hutchings wrote:
> > > On Mon, 2013-03-18 at 14:00 -0700, Nicholas A. Bellinger wrote:
> > > > On Mon, 2013-03-18 at 13:35 +0800, Asias He wrote:
> > > > > On Sat, Mar 16, 2013 at 02:10:22AM +, Ben Hutchings wrote:
> > > > > > On Tue, 2013-03-12 at 15:44 -0700, Greg Kroah-Hartman wrote:
> > > > > > > 3.0-stable review patch.  If anyone has any objections, please 
> > > > > > > let me know.
> > > > > > > 
> > > > > > > --
> > > > > > > 
> > > > > > > From: Asias He 
> > > > > > > 
> > > > > > > commit 472b72f2db7831d7dbe22ffdff4adee3bd49b05d upstream.
> > > > > > > 
> > > > > > > The page++ is wrong. It makes bio_add_pc_page() pointing to a 
> > > > > > > wrong page
> > > > > > > address if the 'while (len > 0 && data_len > 0) { ... }' loop is
> > > > > > > executed more than one once.
> > > > > > > 
> > > > > > > Signed-off-by: Asias He 
> > > > > > > Signed-off-by: Nicholas Bellinger 
> > > > > > > Signed-off-by: Greg Kroah-Hartman 
> > > > > > > 
> > > > > > > ---
> > > > > > >  drivers/target/target_core_pscsi.c |1 -
> > > > > > >  1 file changed, 1 deletion(-)
> > > > > > > 
> > > > > > > --- a/drivers/target/target_core_pscsi.c
> > > > > > > +++ b/drivers/target/target_core_pscsi.c
> > > > > > > @@ -1210,7 +1210,6 @@ static int __pscsi_map_task_SG(
> > > > > > >   bio = NULL;
> > > > > > >   }
> > > > > > >  
> > > > > > > - page++;
> > > > > > >   len -= bytes;
> > > > > > >   data_len -= bytes;
> > > > > > >   off = 0;
> > > > > > 
> > > > > > So in case a fragment crosses a page boundary, we wrap around to the
> > > > > > beginning of the same page?  That doesn't look right.
> > > > > 
> > > > > If the fragment crosses a page boundary, what is the correct page
> > > > > for it?
> > > > > 
> > > > > Nicholas, can we assume sg->length + sg->offset should be less than 
> > > > > PAGE_SIZE here?
> > > > > 
> > > > 
> > > > sg->length + sg->offset can be less than or equal to PAGE_SIZE here.
> > > >
> > > > For everything other than tcm_loop + tcm_vhost using externally
> > > > allocated SGLs, we can expect fragments to never cross the page
> > > > boundary.
> > > > 
> > > > For tcm_loop + tcm_vhost, there are a few special cases with control CDB
> > > > paylaods (usually going through scsi-generic) where we can have a non
> > > > zero sg->offset, but at least in the cases I've seen this is still not
> > > > using SGL elements that exceed PAGE_SIZE.
> > > >
> > > > So, I think this logic is OK for SGLs that cross page boundries, given
> > > > that it's done outside of the inner loop where *page is set during each
> > > > for_each_sg().
> > > 
> > > The page is set using sg_page() in the outer loop and was then
> > > incremented in the inner loop.
> > > 
> > >   for_each_sg(sgl, sg, sgl_nents, i) {
> > >   page = sg_page(sg);
> > >   off = sg->offset;
> > >   len = sg->length;
> > > 
> > >   while (len > 0 && data_len > 0) {
> > >   bytes = min_t(unsigned int, len, PAGE_SIZE - off);
> > >   bytes = min(bytes, data_len);
> > >   ...
> > >   /* page++; */
> > >   len -= bytes;
> > >   data_len -= bytes;
> > >   off = 0;
> > >   }
> > >   }
> > > 
> > > The inner loop is apparently meant to iterate over pages of a segment,
> > > but is now just wrapping around a single page.
> > 
> > Yes, but we never loop more than once in the inner loop.
> 
> If you're sure of that, then:
> 
> > So, how about
> > 1) fail on  sg->offset + sg->length > PAGE_SIZE (we can not find a
> > proper page address in this case)
> > 2) remove the inner while loop, run the code was in the loop only once.
> 
> this is fine, but then I don't understand why you sent a no-op change to
> stable in the first place.
> 

It's my fault for mis-understanding this patch, and putting this into
the queue as a stable bug-fix.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [ 04/21] target/pscsi: Fix page increment

2013-03-18 Thread Ben Hutchings
On Tue, 2013-03-19 at 08:56 +0800, Asias He wrote:
> On Mon, Mar 18, 2013 at 11:30:47PM +, Ben Hutchings wrote:
> > On Mon, 2013-03-18 at 14:00 -0700, Nicholas A. Bellinger wrote:
> > > On Mon, 2013-03-18 at 13:35 +0800, Asias He wrote:
> > > > On Sat, Mar 16, 2013 at 02:10:22AM +, Ben Hutchings wrote:
> > > > > On Tue, 2013-03-12 at 15:44 -0700, Greg Kroah-Hartman wrote:
> > > > > > 3.0-stable review patch.  If anyone has any objections, please let 
> > > > > > me know.
> > > > > > 
> > > > > > --
> > > > > > 
> > > > > > From: Asias He 
> > > > > > 
> > > > > > commit 472b72f2db7831d7dbe22ffdff4adee3bd49b05d upstream.
> > > > > > 
> > > > > > The page++ is wrong. It makes bio_add_pc_page() pointing to a wrong 
> > > > > > page
> > > > > > address if the 'while (len > 0 && data_len > 0) { ... }' loop is
> > > > > > executed more than one once.
> > > > > > 
> > > > > > Signed-off-by: Asias He 
> > > > > > Signed-off-by: Nicholas Bellinger 
> > > > > > Signed-off-by: Greg Kroah-Hartman 
> > > > > > 
> > > > > > ---
> > > > > >  drivers/target/target_core_pscsi.c |1 -
> > > > > >  1 file changed, 1 deletion(-)
> > > > > > 
> > > > > > --- a/drivers/target/target_core_pscsi.c
> > > > > > +++ b/drivers/target/target_core_pscsi.c
> > > > > > @@ -1210,7 +1210,6 @@ static int __pscsi_map_task_SG(
> > > > > > bio = NULL;
> > > > > > }
> > > > > >  
> > > > > > -   page++;
> > > > > > len -= bytes;
> > > > > > data_len -= bytes;
> > > > > > off = 0;
> > > > > 
> > > > > So in case a fragment crosses a page boundary, we wrap around to the
> > > > > beginning of the same page?  That doesn't look right.
> > > > 
> > > > If the fragment crosses a page boundary, what is the correct page
> > > > for it?
> > > > 
> > > > Nicholas, can we assume sg->length + sg->offset should be less than 
> > > > PAGE_SIZE here?
> > > > 
> > > 
> > > sg->length + sg->offset can be less than or equal to PAGE_SIZE here.
> > >
> > > For everything other than tcm_loop + tcm_vhost using externally
> > > allocated SGLs, we can expect fragments to never cross the page
> > > boundary.
> > > 
> > > For tcm_loop + tcm_vhost, there are a few special cases with control CDB
> > > paylaods (usually going through scsi-generic) where we can have a non
> > > zero sg->offset, but at least in the cases I've seen this is still not
> > > using SGL elements that exceed PAGE_SIZE.
> > >
> > > So, I think this logic is OK for SGLs that cross page boundries, given
> > > that it's done outside of the inner loop where *page is set during each
> > > for_each_sg().
> > 
> > The page is set using sg_page() in the outer loop and was then
> > incremented in the inner loop.
> > 
> > for_each_sg(sgl, sg, sgl_nents, i) {
> > page = sg_page(sg);
> > off = sg->offset;
> > len = sg->length;
> > 
> > while (len > 0 && data_len > 0) {
> > bytes = min_t(unsigned int, len, PAGE_SIZE - off);
> > bytes = min(bytes, data_len);
> > ...
> > /* page++; */
> > len -= bytes;
> > data_len -= bytes;
> > off = 0;
> > }
> > }
> > 
> > The inner loop is apparently meant to iterate over pages of a segment,
> > but is now just wrapping around a single page.
> 
> Yes, but we never loop more than once in the inner loop.

If you're sure of that, then:

> So, how about
> 1) fail on  sg->offset + sg->length > PAGE_SIZE (we can not find a
> proper page address in this case)
> 2) remove the inner while loop, run the code was in the loop only once.

this is fine, but then I don't understand why you sent a no-op change to
stable in the first place.

Ben.

-- 
Ben Hutchings
When you say `I wrote a program that crashed Windows', people just stare ...
and say `Hey, I got those with the system, *for free*'. - Linus Torvalds


signature.asc
Description: This is a digitally signed message part


Re: [ 04/21] target/pscsi: Fix page increment

2013-03-18 Thread Asias He
On Mon, Mar 18, 2013 at 11:30:47PM +, Ben Hutchings wrote:
> On Mon, 2013-03-18 at 14:00 -0700, Nicholas A. Bellinger wrote:
> > On Mon, 2013-03-18 at 13:35 +0800, Asias He wrote:
> > > On Sat, Mar 16, 2013 at 02:10:22AM +, Ben Hutchings wrote:
> > > > On Tue, 2013-03-12 at 15:44 -0700, Greg Kroah-Hartman wrote:
> > > > > 3.0-stable review patch.  If anyone has any objections, please let me 
> > > > > know.
> > > > > 
> > > > > --
> > > > > 
> > > > > From: Asias He 
> > > > > 
> > > > > commit 472b72f2db7831d7dbe22ffdff4adee3bd49b05d upstream.
> > > > > 
> > > > > The page++ is wrong. It makes bio_add_pc_page() pointing to a wrong 
> > > > > page
> > > > > address if the 'while (len > 0 && data_len > 0) { ... }' loop is
> > > > > executed more than one once.
> > > > > 
> > > > > Signed-off-by: Asias He 
> > > > > Signed-off-by: Nicholas Bellinger 
> > > > > Signed-off-by: Greg Kroah-Hartman 
> > > > > 
> > > > > ---
> > > > >  drivers/target/target_core_pscsi.c |1 -
> > > > >  1 file changed, 1 deletion(-)
> > > > > 
> > > > > --- a/drivers/target/target_core_pscsi.c
> > > > > +++ b/drivers/target/target_core_pscsi.c
> > > > > @@ -1210,7 +1210,6 @@ static int __pscsi_map_task_SG(
> > > > >   bio = NULL;
> > > > >   }
> > > > >  
> > > > > - page++;
> > > > >   len -= bytes;
> > > > >   data_len -= bytes;
> > > > >   off = 0;
> > > > 
> > > > So in case a fragment crosses a page boundary, we wrap around to the
> > > > beginning of the same page?  That doesn't look right.
> > > 
> > > If the fragment crosses a page boundary, what is the correct page
> > > for it?
> > > 
> > > Nicholas, can we assume sg->length + sg->offset should be less than 
> > > PAGE_SIZE here?
> > > 
> > 
> > sg->length + sg->offset can be less than or equal to PAGE_SIZE here.
> >
> > For everything other than tcm_loop + tcm_vhost using externally
> > allocated SGLs, we can expect fragments to never cross the page
> > boundary.
> > 
> > For tcm_loop + tcm_vhost, there are a few special cases with control CDB
> > paylaods (usually going through scsi-generic) where we can have a non
> > zero sg->offset, but at least in the cases I've seen this is still not
> > using SGL elements that exceed PAGE_SIZE.
> >
> > So, I think this logic is OK for SGLs that cross page boundries, given
> > that it's done outside of the inner loop where *page is set during each
> > for_each_sg().
> 
> The page is set using sg_page() in the outer loop and was then
> incremented in the inner loop.
> 
>   for_each_sg(sgl, sg, sgl_nents, i) {
>   page = sg_page(sg);
>   off = sg->offset;
>   len = sg->length;
> 
>   while (len > 0 && data_len > 0) {
>   bytes = min_t(unsigned int, len, PAGE_SIZE - off);
>   bytes = min(bytes, data_len);
>   ...
>   /* page++; */
>   len -= bytes;
>   data_len -= bytes;
>   off = 0;
>   }
>   }
> 
> The inner loop is apparently meant to iterate over pages of a segment,
> but is now just wrapping around a single page.

Yes, but we never loop more than once in the inner loop.

So, how about
1) fail on  sg->offset + sg->length > PAGE_SIZE (we can not find a
proper page address in this case)
2) remove the inner while loop, run the code was in the loop only once.

> > The case where this logic is broken, and that the 'page
> > ++' was addressing is when sg->length > PAGE_SIZE.
> 
> That is a sufficient but not a necessary condition for the increment.
> 
> Ben.
> 
> -- 
> Ben Hutchings
> Never attribute to conspiracy what can adequately be explained by stupidity.

-- 
Asias
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [ 04/21] target/pscsi: Fix page increment

2013-03-18 Thread Ben Hutchings
On Mon, 2013-03-18 at 14:00 -0700, Nicholas A. Bellinger wrote:
> On Mon, 2013-03-18 at 13:35 +0800, Asias He wrote:
> > On Sat, Mar 16, 2013 at 02:10:22AM +, Ben Hutchings wrote:
> > > On Tue, 2013-03-12 at 15:44 -0700, Greg Kroah-Hartman wrote:
> > > > 3.0-stable review patch.  If anyone has any objections, please let me 
> > > > know.
> > > > 
> > > > --
> > > > 
> > > > From: Asias He 
> > > > 
> > > > commit 472b72f2db7831d7dbe22ffdff4adee3bd49b05d upstream.
> > > > 
> > > > The page++ is wrong. It makes bio_add_pc_page() pointing to a wrong page
> > > > address if the 'while (len > 0 && data_len > 0) { ... }' loop is
> > > > executed more than one once.
> > > > 
> > > > Signed-off-by: Asias He 
> > > > Signed-off-by: Nicholas Bellinger 
> > > > Signed-off-by: Greg Kroah-Hartman 
> > > > 
> > > > ---
> > > >  drivers/target/target_core_pscsi.c |1 -
> > > >  1 file changed, 1 deletion(-)
> > > > 
> > > > --- a/drivers/target/target_core_pscsi.c
> > > > +++ b/drivers/target/target_core_pscsi.c
> > > > @@ -1210,7 +1210,6 @@ static int __pscsi_map_task_SG(
> > > > bio = NULL;
> > > > }
> > > >  
> > > > -   page++;
> > > > len -= bytes;
> > > > data_len -= bytes;
> > > > off = 0;
> > > 
> > > So in case a fragment crosses a page boundary, we wrap around to the
> > > beginning of the same page?  That doesn't look right.
> > 
> > If the fragment crosses a page boundary, what is the correct page
> > for it?
> > 
> > Nicholas, can we assume sg->length + sg->offset should be less than 
> > PAGE_SIZE here?
> > 
> 
> sg->length + sg->offset can be less than or equal to PAGE_SIZE here.
>
> For everything other than tcm_loop + tcm_vhost using externally
> allocated SGLs, we can expect fragments to never cross the page
> boundary.
> 
> For tcm_loop + tcm_vhost, there are a few special cases with control CDB
> paylaods (usually going through scsi-generic) where we can have a non
> zero sg->offset, but at least in the cases I've seen this is still not
> using SGL elements that exceed PAGE_SIZE.
>
> So, I think this logic is OK for SGLs that cross page boundries, given
> that it's done outside of the inner loop where *page is set during each
> for_each_sg().

The page is set using sg_page() in the outer loop and was then
incremented in the inner loop.

for_each_sg(sgl, sg, sgl_nents, i) {
page = sg_page(sg);
off = sg->offset;
len = sg->length;

while (len > 0 && data_len > 0) {
bytes = min_t(unsigned int, len, PAGE_SIZE - off);
bytes = min(bytes, data_len);
...
/* page++; */
len -= bytes;
data_len -= bytes;
off = 0;
}
}

The inner loop is apparently meant to iterate over pages of a segment,
but is now just wrapping around a single page.

> The case where this logic is broken, and that the 'page
> ++' was addressing is when sg->length > PAGE_SIZE.

That is a sufficient but not a necessary condition for the increment.

Ben.

-- 
Ben Hutchings
Never attribute to conspiracy what can adequately be explained by stupidity.


signature.asc
Description: This is a digitally signed message part


Re: [ 04/21] target/pscsi: Fix page increment

2013-03-18 Thread Nicholas A. Bellinger
On Mon, 2013-03-18 at 13:35 +0800, Asias He wrote:
> On Sat, Mar 16, 2013 at 02:10:22AM +, Ben Hutchings wrote:
> > On Tue, 2013-03-12 at 15:44 -0700, Greg Kroah-Hartman wrote:
> > > 3.0-stable review patch.  If anyone has any objections, please let me 
> > > know.
> > > 
> > > --
> > > 
> > > From: Asias He 
> > > 
> > > commit 472b72f2db7831d7dbe22ffdff4adee3bd49b05d upstream.
> > > 
> > > The page++ is wrong. It makes bio_add_pc_page() pointing to a wrong page
> > > address if the 'while (len > 0 && data_len > 0) { ... }' loop is
> > > executed more than one once.
> > > 
> > > Signed-off-by: Asias He 
> > > Signed-off-by: Nicholas Bellinger 
> > > Signed-off-by: Greg Kroah-Hartman 
> > > 
> > > ---
> > >  drivers/target/target_core_pscsi.c |1 -
> > >  1 file changed, 1 deletion(-)
> > > 
> > > --- a/drivers/target/target_core_pscsi.c
> > > +++ b/drivers/target/target_core_pscsi.c
> > > @@ -1210,7 +1210,6 @@ static int __pscsi_map_task_SG(
> > >   bio = NULL;
> > >   }
> > >  
> > > - page++;
> > >   len -= bytes;
> > >   data_len -= bytes;
> > >   off = 0;
> > 
> > So in case a fragment crosses a page boundary, we wrap around to the
> > beginning of the same page?  That doesn't look right.
> 
> If the fragment crosses a page boundary, what is the correct page
> for it?
> 
> Nicholas, can we assume sg->length + sg->offset should be less than PAGE_SIZE 
> here?
> 

sg->length + sg->offset can be less than or equal to PAGE_SIZE here.

For everything other than tcm_loop + tcm_vhost using externally
allocated SGLs, we can expect fragments to never cross the page
boundary.

For tcm_loop + tcm_vhost, there are a few special cases with control CDB
paylaods (usually going through scsi-generic) where we can have a non
zero sg->offset, but at least in the cases I've seen this is still not
using SGL elements that exceed PAGE_SIZE.

So, I think this logic is OK for SGLs that cross page boundries, given
that it's done outside of the inner loop where *page is set during each
for_each_sg().  The case where this logic is broken, and that the 'page
++' was addressing is when sg->length > PAGE_SIZE.

--nab

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [ 04/21] target/pscsi: Fix page increment

2013-03-17 Thread Asias He
On Sat, Mar 16, 2013 at 02:10:22AM +, Ben Hutchings wrote:
> On Tue, 2013-03-12 at 15:44 -0700, Greg Kroah-Hartman wrote:
> > 3.0-stable review patch.  If anyone has any objections, please let me know.
> > 
> > --
> > 
> > From: Asias He 
> > 
> > commit 472b72f2db7831d7dbe22ffdff4adee3bd49b05d upstream.
> > 
> > The page++ is wrong. It makes bio_add_pc_page() pointing to a wrong page
> > address if the 'while (len > 0 && data_len > 0) { ... }' loop is
> > executed more than one once.
> > 
> > Signed-off-by: Asias He 
> > Signed-off-by: Nicholas Bellinger 
> > Signed-off-by: Greg Kroah-Hartman 
> > 
> > ---
> >  drivers/target/target_core_pscsi.c |1 -
> >  1 file changed, 1 deletion(-)
> > 
> > --- a/drivers/target/target_core_pscsi.c
> > +++ b/drivers/target/target_core_pscsi.c
> > @@ -1210,7 +1210,6 @@ static int __pscsi_map_task_SG(
> > bio = NULL;
> > }
> >  
> > -   page++;
> > len -= bytes;
> > data_len -= bytes;
> > off = 0;
> 
> So in case a fragment crosses a page boundary, we wrap around to the
> beginning of the same page?  That doesn't look right.

If the fragment crosses a page boundary, what is the correct page
for it?

Nicholas, can we assume sg->length + sg->offset should be less than PAGE_SIZE 
here?

> Ben.
> 
> -- 
> Ben Hutchings
> It is easier to change the specification to fit the program than vice versa.

-- 
Asias
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [ 04/21] target/pscsi: Fix page increment

2013-03-15 Thread Ben Hutchings
On Tue, 2013-03-12 at 15:44 -0700, Greg Kroah-Hartman wrote:
> 3.0-stable review patch.  If anyone has any objections, please let me know.
> 
> --
> 
> From: Asias He 
> 
> commit 472b72f2db7831d7dbe22ffdff4adee3bd49b05d upstream.
> 
> The page++ is wrong. It makes bio_add_pc_page() pointing to a wrong page
> address if the 'while (len > 0 && data_len > 0) { ... }' loop is
> executed more than one once.
> 
> Signed-off-by: Asias He 
> Signed-off-by: Nicholas Bellinger 
> Signed-off-by: Greg Kroah-Hartman 
> 
> ---
>  drivers/target/target_core_pscsi.c |1 -
>  1 file changed, 1 deletion(-)
> 
> --- a/drivers/target/target_core_pscsi.c
> +++ b/drivers/target/target_core_pscsi.c
> @@ -1210,7 +1210,6 @@ static int __pscsi_map_task_SG(
>   bio = NULL;
>   }
>  
> - page++;
>   len -= bytes;
>   data_len -= bytes;
>   off = 0;

So in case a fragment crosses a page boundary, we wrap around to the
beginning of the same page?  That doesn't look right.

Ben.

-- 
Ben Hutchings
It is easier to change the specification to fit the program than vice versa.


signature.asc
Description: This is a digitally signed message part


[ 04/21] target/pscsi: Fix page increment

2013-03-12 Thread Greg Kroah-Hartman
3.0-stable review patch.  If anyone has any objections, please let me know.

--

From: Asias He 

commit 472b72f2db7831d7dbe22ffdff4adee3bd49b05d upstream.

The page++ is wrong. It makes bio_add_pc_page() pointing to a wrong page
address if the 'while (len > 0 && data_len > 0) { ... }' loop is
executed more than one once.

Signed-off-by: Asias He 
Signed-off-by: Nicholas Bellinger 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/target/target_core_pscsi.c |1 -
 1 file changed, 1 deletion(-)

--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -1210,7 +1210,6 @@ static int __pscsi_map_task_SG(
bio = NULL;
}
 
-   page++;
len -= bytes;
data_len -= bytes;
off = 0;


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/