Re: [PATCH] memstick: add support for legacy memorysticks

2013-07-17 Thread Andrew Morton
On Mon,  8 Jul 2013 23:54:55 +0300 Maxim Levitsky  
wrote:

> Based partially on MS standard spec quotes from Alex Dubov.
> 
> As any code that works with user data this driver isn't
> recommended to use to write cards that contain valuable data.
> 
> It tries its best though to avoid data corruption
> and possible damage to the card.
> 
> Tested on MS DUO 64 MB card on Ricoh R592 card reader.
> 
> ...
>
> +config MS_BLOCK
> + tristate "MemoryStick Standard device driver"
> + depends on BLOCK
> + help
> +   Say Y here to enable the MemoryStick Standard device driver
> +   support. This provides a block device driver, which you can use
> +   to mount the filesystem.
> +   This driver works with old (bulky) MemoryStick and MemoryStick Duo
> +   but not PRO. Say Y if you have such card.
> +   Driver is new and not yet well tested, thus it can damage your card
> +   (even permanently)

Yikes.  How true is this?

> 
> ...
>
> +static size_t msb_sg_copy(struct scatterlist *sg_from,
> + struct scatterlist *sg_to, int to_nents, size_t offset, size_t len)
> +{
> + size_t copied = 0;
> +
> + while (offset > 0) {
> + if (offset >= sg_from->length) {
> + if (sg_is_last(sg_from))
> + return 0;
> +
> + offset -= sg_from->length;
> + sg_from = sg_next(sg_from);
> + continue;
> + }
> +
> + copied = min(len, sg_from->length - offset);
> + sg_set_page(sg_to, sg_page(sg_from),
> + copied, sg_from->offset + offset);
> +
> + len -= copied;
> + offset = 0;
> +
> + if (sg_is_last(sg_from) || !len)
> + goto out;
> +
> + sg_to = sg_next(sg_to);
> + to_nents--;
> + sg_from = sg_next(sg_from);
> + }
> +
> + while (len > sg_from->length && to_nents--) {
> + len -= sg_from->length;
> + copied += sg_from->length;
> +
> + sg_set_page(sg_to, sg_page(sg_from),
> + sg_from->length, sg_from->offset);
> +
> + if (sg_is_last(sg_from) || !len)
> + goto out;
> +
> + sg_from = sg_next(sg_from);
> + sg_to = sg_next(sg_to);
> + }
> +
> + if (len && to_nents) {
> + sg_set_page(sg_to, sg_page(sg_from), len, sg_from->offset);
> + copied += len;
> + }
> +out:
> + sg_mark_end(sg_to);
> + return copied;
> +}

There's nothing memstick-specific about this.  Did you consider placing
it in lib/?


> +/*
> + * Compares section of 'sg' starting from offset 'offset' and with length 
> 'len'
> + * to linear buffer of length 'len' at address 'buffer'
> + * Returns 0 if equal and  -1 otherwice
> + */
> +static int msb_sg_compare_to_buffer(struct scatterlist *sg,
> + size_t offset, u8 *buffer, size_t len)
> +{
> + int retval = 0, cmplen;
> + struct sg_mapping_iter miter;
> +
> + sg_miter_start(, sg, sg_nents(sg),
> + SG_MITER_ATOMIC | SG_MITER_FROM_SG);
> +
> + while (sg_miter_next() && len > 0) {
> + if (offset >= miter.length) {
> + offset -= miter.length;
> + continue;
> + }
> +
> + cmplen = min(miter.length - offset, len);
> + retval = memcmp(miter.addr + offset, buffer, cmplen) ? -1 : 0;
> + if (retval)
> + break;
> +
> + buffer += cmplen;
> + len -= cmplen;
> + offset = 0;
> + }
> +
> + if (!retval && len)
> + retval = -1;
> +
> + sg_miter_stop();
> + return retval;
> +}

And this, perhaps.

> 
> ...
>
> +static void msb_mark_block_used(struct msb_data *msb, int pba)
> +{
> + int zone = msb_get_zone_from_pba(pba);
> +
> + if (test_bit(pba, msb->used_blocks_bitmap)) {
> + pr_err(
> + "BUG: attempt to mark already used pba %d as used", pba);
> + msb->read_only = true;
> + return;
> + }
> +
> + if (msb_validate_used_block_bitmap(msb))
> + return;
> +
> + /* No races because all IO is single threaded */

What guarantees that all IO is single threaded?  Big lock?  All done by
a single kernel thread?

> + __set_bit(pba, msb->used_blocks_bitmap);
> + msb->free_block_count[zone]--;
> +}
> +
> 
> ...
>
> +static int msb_read_int_reg(struct msb_data *msb, long timeout)
> +{
> + struct memstick_request *mrq = >card->current_mrq;
> +
> + WARN_ON(msb->state == -1);
> +
> + if (!msb->int_polling) {
> + msb->int_timeout = jiffies +
> + msecs_to_jiffies(timeout == -1 ? 500 : timeout);

All callers pass timeout=-1, so there's some pointless code here.

> + msb->int_polling = true;
> 

Re: [PATCH] memstick: add support for legacy memorysticks

2013-07-17 Thread Andrew Morton
On Mon,  8 Jul 2013 23:54:55 +0300 Maxim Levitsky maximlevit...@gmail.com 
wrote:

 Based partially on MS standard spec quotes from Alex Dubov.
 
 As any code that works with user data this driver isn't
 recommended to use to write cards that contain valuable data.
 
 It tries its best though to avoid data corruption
 and possible damage to the card.
 
 Tested on MS DUO 64 MB card on Ricoh R592 card reader.
 
 ...

 +config MS_BLOCK
 + tristate MemoryStick Standard device driver
 + depends on BLOCK
 + help
 +   Say Y here to enable the MemoryStick Standard device driver
 +   support. This provides a block device driver, which you can use
 +   to mount the filesystem.
 +   This driver works with old (bulky) MemoryStick and MemoryStick Duo
 +   but not PRO. Say Y if you have such card.
 +   Driver is new and not yet well tested, thus it can damage your card
 +   (even permanently)

Yikes.  How true is this?

 
 ...

 +static size_t msb_sg_copy(struct scatterlist *sg_from,
 + struct scatterlist *sg_to, int to_nents, size_t offset, size_t len)
 +{
 + size_t copied = 0;
 +
 + while (offset  0) {
 + if (offset = sg_from-length) {
 + if (sg_is_last(sg_from))
 + return 0;
 +
 + offset -= sg_from-length;
 + sg_from = sg_next(sg_from);
 + continue;
 + }
 +
 + copied = min(len, sg_from-length - offset);
 + sg_set_page(sg_to, sg_page(sg_from),
 + copied, sg_from-offset + offset);
 +
 + len -= copied;
 + offset = 0;
 +
 + if (sg_is_last(sg_from) || !len)
 + goto out;
 +
 + sg_to = sg_next(sg_to);
 + to_nents--;
 + sg_from = sg_next(sg_from);
 + }
 +
 + while (len  sg_from-length  to_nents--) {
 + len -= sg_from-length;
 + copied += sg_from-length;
 +
 + sg_set_page(sg_to, sg_page(sg_from),
 + sg_from-length, sg_from-offset);
 +
 + if (sg_is_last(sg_from) || !len)
 + goto out;
 +
 + sg_from = sg_next(sg_from);
 + sg_to = sg_next(sg_to);
 + }
 +
 + if (len  to_nents) {
 + sg_set_page(sg_to, sg_page(sg_from), len, sg_from-offset);
 + copied += len;
 + }
 +out:
 + sg_mark_end(sg_to);
 + return copied;
 +}

There's nothing memstick-specific about this.  Did you consider placing
it in lib/?


 +/*
 + * Compares section of 'sg' starting from offset 'offset' and with length 
 'len'
 + * to linear buffer of length 'len' at address 'buffer'
 + * Returns 0 if equal and  -1 otherwice
 + */
 +static int msb_sg_compare_to_buffer(struct scatterlist *sg,
 + size_t offset, u8 *buffer, size_t len)
 +{
 + int retval = 0, cmplen;
 + struct sg_mapping_iter miter;
 +
 + sg_miter_start(miter, sg, sg_nents(sg),
 + SG_MITER_ATOMIC | SG_MITER_FROM_SG);
 +
 + while (sg_miter_next(miter)  len  0) {
 + if (offset = miter.length) {
 + offset -= miter.length;
 + continue;
 + }
 +
 + cmplen = min(miter.length - offset, len);
 + retval = memcmp(miter.addr + offset, buffer, cmplen) ? -1 : 0;
 + if (retval)
 + break;
 +
 + buffer += cmplen;
 + len -= cmplen;
 + offset = 0;
 + }
 +
 + if (!retval  len)
 + retval = -1;
 +
 + sg_miter_stop(miter);
 + return retval;
 +}

And this, perhaps.

 
 ...

 +static void msb_mark_block_used(struct msb_data *msb, int pba)
 +{
 + int zone = msb_get_zone_from_pba(pba);
 +
 + if (test_bit(pba, msb-used_blocks_bitmap)) {
 + pr_err(
 + BUG: attempt to mark already used pba %d as used, pba);
 + msb-read_only = true;
 + return;
 + }
 +
 + if (msb_validate_used_block_bitmap(msb))
 + return;
 +
 + /* No races because all IO is single threaded */

What guarantees that all IO is single threaded?  Big lock?  All done by
a single kernel thread?

 + __set_bit(pba, msb-used_blocks_bitmap);
 + msb-free_block_count[zone]--;
 +}
 +
 
 ...

 +static int msb_read_int_reg(struct msb_data *msb, long timeout)
 +{
 + struct memstick_request *mrq = msb-card-current_mrq;
 +
 + WARN_ON(msb-state == -1);
 +
 + if (!msb-int_polling) {
 + msb-int_timeout = jiffies +
 + msecs_to_jiffies(timeout == -1 ? 500 : timeout);

All callers pass timeout=-1, so there's some pointless code here.

 + msb-int_polling = true;
 + } else if (time_after(jiffies, msb-int_timeout)) {
 + mrq-data[0] = MEMSTICK_INT_CMDNAK;
 + return 0;
 + }
 +
 + 

Re: [PATCH] memstick: add support for legacy memorysticks

2013-07-11 Thread Andrew Morton
On Thu, 11 Jul 2013 03:28:37 +0300 Maxim Levitsky  
wrote:

> On Mon, 2013-07-08 at 23:54 +0300, Maxim Levitsky wrote: 
> > Based partially on MS standard spec quotes from Alex Dubov.
> > 
> > As any code that works with user data this driver isn't
> > recommended to use to write cards that contain valuable data.
> > 
> > It tries its best though to avoid data corruption
> > and possible damage to the card.
> > 
> > Tested on MS DUO 64 MB card on Ricoh R592 card reader.
> > 

(top-posting repaired.  Please don't do that).

> Any update?

You sent a large patch in the middle of the 3.11 merge window, when
nobody is looking at large new patches.

I have it saved away for consideration after -rc1.
--
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: [PATCH] memstick: add support for legacy memorysticks

2013-07-11 Thread Andrew Morton
On Thu, 11 Jul 2013 03:28:37 +0300 Maxim Levitsky maximlevit...@gmail.com 
wrote:

 On Mon, 2013-07-08 at 23:54 +0300, Maxim Levitsky wrote: 
  Based partially on MS standard spec quotes from Alex Dubov.
  
  As any code that works with user data this driver isn't
  recommended to use to write cards that contain valuable data.
  
  It tries its best though to avoid data corruption
  and possible damage to the card.
  
  Tested on MS DUO 64 MB card on Ricoh R592 card reader.
  

(top-posting repaired.  Please don't do that).

 Any update?

You sent a large patch in the middle of the 3.11 merge window, when
nobody is looking at large new patches.

I have it saved away for consideration after -rc1.
--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Tejun Heo
Hello,

On Mon, Sep 24, 2012 at 08:24:37PM +0200, Maxim Levitsky wrote:
> Should have looked through the source. Understand now.
> Just one quick question, should I create my own workqueue or use
> schedule_work? if I use the later and my work function sleeps, will it
> harmfully affect other users of this function?

If memstick can be in memory reclaim path (most block devices are),
you would want to create a dedicated workqueue w/ rescuer.  For
details, please read Documentation/workqueue.txt.

Thanks.

-- 
tejun
--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Tejun Heo
Hello,

On Mon, Sep 24, 2012 at 08:19:28PM +0200, Maxim Levitsky wrote:
> Except that if I schedule a same work item few times, these work items
> will be 'processed' in parallel, although there is just one work to do,
> work of pulling the requests from block queue until it has them, and
> dispatching them through my code.
> Or I can get a guarantee that work items wont be processed in parallel?

You need to use system_nrt_wq for that before 3.7-rc1.  After 3.7-rc1,
any workqueue will guarantee that.

> Stiil, even with that only first work item will do the actual work,
> others will wake the workqueue for nothing, but I am ok with that.

It's just like waking up spuriously.  The work item is guaranteed to
be executed at least once after any given schedule/queue_work() call.

Thanks.

-- 
tejun
--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Maxim Levitsky
On Mon, 2012-09-24 at 20:19 +0200, Maxim Levitsky wrote: 
> On Mon, 2012-09-24 at 11:05 -0700, Tejun Heo wrote: 
> > Hello,
> > 
> > On Mon, Sep 24, 2012 at 05:09:23PM +0200, Maxim Levitsky wrote:
> > > > Now that my exams done
> > > > Can you spare me from using a workqueue?
> > 
> > I'd much prefer if you convert to workqueue.
> > 
> > > > The point is that using current model I wake the worker thread as much
> > > > as I want to, and I know that it will be woken once an will do all the
> > > > work till request queue is empty.
> > 
> > You can do exactly the same thing by scheduling the same work item
> > multiple times.  "Waking up" just becomes "scheduling the work item".
> I don't believe that will work this way.
> I will dig through the source, and see how to do that.
> 
> 
> 
> > > > With workqueues, it doesn't work this way. I have to pass the request as
> > > > a work item or something like that.
> > > > Any pointers?
> > 
> > No, there's no reason to change the structure of the code in any way.
> > Just use a work item as you would use a kthread.
> Except that if I schedule a same work item few times, these work items
> will be 'processed' in parallel, although there is just one work to do,
> work of pulling the requests from block queue until it has them, and
> dispatching them through my code.
> Or I can get a guarantee that work items wont be processed in parallel?
> Stiil, even with that only first work item will do the actual work,
> others will wake the workqueue for nothing, but I am ok with that.
Should have looked through the source. Understand now.
Just one quick question, should I create my own workqueue or use
schedule_work? if I use the later and my work function sleeps, will it
harmfully affect other users of this function?


-- 
Best regards,
Maxim Levitsky



--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Maxim Levitsky
On Mon, 2012-09-24 at 11:05 -0700, Tejun Heo wrote: 
> Hello,
> 
> On Mon, Sep 24, 2012 at 05:09:23PM +0200, Maxim Levitsky wrote:
> > > Now that my exams done
> > > Can you spare me from using a workqueue?
> 
> I'd much prefer if you convert to workqueue.
> 
> > > The point is that using current model I wake the worker thread as much
> > > as I want to, and I know that it will be woken once an will do all the
> > > work till request queue is empty.
> 
> You can do exactly the same thing by scheduling the same work item
> multiple times.  "Waking up" just becomes "scheduling the work item".
I don't believe that will work this way.
I will dig through the source, and see how to do that.



> > > With workqueues, it doesn't work this way. I have to pass the request as
> > > a work item or something like that.
> > > Any pointers?
> 
> No, there's no reason to change the structure of the code in any way.
> Just use a work item as you would use a kthread.
Except that if I schedule a same work item few times, these work items
will be 'processed' in parallel, although there is just one work to do,
work of pulling the requests from block queue until it has them, and
dispatching them through my code.
Or I can get a guarantee that work items wont be processed in parallel?
Stiil, even with that only first work item will do the actual work,
others will wake the workqueue for nothing, but I am ok with that.



> 
> > Also probably due to that reason MMC doesn't use a workqueue ether, but
> > a raw kthread, in pretty much same way I do.
> 
> Mostly because I haven't gotten around to convert it yet.  The
> problems with direct kthread usage are that they're much more
> difficult to get completely correct with freeze and exit conditions -
Agreed, I had my own share of frustration with this. I got it right in
the end though.

> the last time I checked it was easier to spot broken ones than correct
> ones - and they create dedicated threads which usually are
> underutilized.
True too, although, a sleeping thread doesn't cost much. 
> 
> Thanks.
> 

-- 
Best regards,
Maxim Levitsky


--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Tejun Heo
Hello,

On Mon, Sep 24, 2012 at 05:09:23PM +0200, Maxim Levitsky wrote:
> > Now that my exams done
> > Can you spare me from using a workqueue?

I'd much prefer if you convert to workqueue.

> > The point is that using current model I wake the worker thread as much
> > as I want to, and I know that it will be woken once an will do all the
> > work till request queue is empty.

You can do exactly the same thing by scheduling the same work item
multiple times.  "Waking up" just becomes "scheduling the work item".

> > With workqueues, it doesn't work this way. I have to pass the request as
> > a work item or something like that.
> > Any pointers?

No, there's no reason to change the structure of the code in any way.
Just use a work item as you would use a kthread.

> Also probably due to that reason MMC doesn't use a workqueue ether, but
> a raw kthread, in pretty much same way I do.

Mostly because I haven't gotten around to convert it yet.  The
problems with direct kthread usage are that they're much more
difficult to get completely correct with freeze and exit conditions -
the last time I checked it was easier to spot broken ones than correct
ones - and they create dedicated threads which usually are
underutilized.

Thanks.

-- 
tejun
--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Maxim Levitsky
On Mon, 2012-09-24 at 16:59 +0200, Maxim Levitsky wrote: 
> On Thu, 2012-09-20 at 10:53 -0700, Tejun Heo wrote: 
> > On Thu, Sep 20, 2012 at 07:05:42AM +0300, Maxim Levitsky wrote:
> > > There can't be races in the driver, since it contains a single thread
> > > that does all the IO it got from block layer.
> > > The thread is awaken each time the request function of block device is
> > > called.
> > > This why I didn't do much locking in here. In addition I found out that
> > > this is quite common way to implement a block device driver.
> > 
> > Please use workqueue instead of raw kthread.
> > 
> > Thanks!
> Now that my exams done
> Can you spare me from using a workqueue?
> The point is that using current model I wake the worker thread as much
> as I want to, and I know that it will be woken once an will do all the
> work till request queue is empty.
> With workqueues, it doesn't work this way. I have to pass the request as
> a work item or something like that.
> Any pointers?
Also probably due to that reason MMC doesn't use a workqueue ether, but
a raw kthread, in pretty much same way I do.


-- 
Best regards,
Maxim Levitsky


--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Maxim Levitsky
On Thu, 2012-09-20 at 10:53 -0700, Tejun Heo wrote: 
> On Thu, Sep 20, 2012 at 07:05:42AM +0300, Maxim Levitsky wrote:
> > There can't be races in the driver, since it contains a single thread
> > that does all the IO it got from block layer.
> > The thread is awaken each time the request function of block device is
> > called.
> > This why I didn't do much locking in here. In addition I found out that
> > this is quite common way to implement a block device driver.
> 
> Please use workqueue instead of raw kthread.
> 
> Thanks!
Now that my exams done
Can you spare me from using a workqueue?
The point is that using current model I wake the worker thread as much
as I want to, and I know that it will be woken once an will do all the
work till request queue is empty.
With workqueues, it doesn't work this way. I have to pass the request as
a work item or something like that.
Any pointers?

Best regards,
Maxim Levitsky 

--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Maxim Levitsky
On Thu, 2012-09-20 at 10:53 -0700, Tejun Heo wrote: 
 On Thu, Sep 20, 2012 at 07:05:42AM +0300, Maxim Levitsky wrote:
  There can't be races in the driver, since it contains a single thread
  that does all the IO it got from block layer.
  The thread is awaken each time the request function of block device is
  called.
  This why I didn't do much locking in here. In addition I found out that
  this is quite common way to implement a block device driver.
 
 Please use workqueue instead of raw kthread.
 
 Thanks!
Now that my exams done
Can you spare me from using a workqueue?
The point is that using current model I wake the worker thread as much
as I want to, and I know that it will be woken once an will do all the
work till request queue is empty.
With workqueues, it doesn't work this way. I have to pass the request as
a work item or something like that.
Any pointers?

Best regards,
Maxim Levitsky 

--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Maxim Levitsky
On Mon, 2012-09-24 at 16:59 +0200, Maxim Levitsky wrote: 
 On Thu, 2012-09-20 at 10:53 -0700, Tejun Heo wrote: 
  On Thu, Sep 20, 2012 at 07:05:42AM +0300, Maxim Levitsky wrote:
   There can't be races in the driver, since it contains a single thread
   that does all the IO it got from block layer.
   The thread is awaken each time the request function of block device is
   called.
   This why I didn't do much locking in here. In addition I found out that
   this is quite common way to implement a block device driver.
  
  Please use workqueue instead of raw kthread.
  
  Thanks!
 Now that my exams done
 Can you spare me from using a workqueue?
 The point is that using current model I wake the worker thread as much
 as I want to, and I know that it will be woken once an will do all the
 work till request queue is empty.
 With workqueues, it doesn't work this way. I have to pass the request as
 a work item or something like that.
 Any pointers?
Also probably due to that reason MMC doesn't use a workqueue ether, but
a raw kthread, in pretty much same way I do.


-- 
Best regards,
Maxim Levitsky


--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Tejun Heo
Hello,

On Mon, Sep 24, 2012 at 05:09:23PM +0200, Maxim Levitsky wrote:
  Now that my exams done
  Can you spare me from using a workqueue?

I'd much prefer if you convert to workqueue.

  The point is that using current model I wake the worker thread as much
  as I want to, and I know that it will be woken once an will do all the
  work till request queue is empty.

You can do exactly the same thing by scheduling the same work item
multiple times.  Waking up just becomes scheduling the work item.

  With workqueues, it doesn't work this way. I have to pass the request as
  a work item or something like that.
  Any pointers?

No, there's no reason to change the structure of the code in any way.
Just use a work item as you would use a kthread.

 Also probably due to that reason MMC doesn't use a workqueue ether, but
 a raw kthread, in pretty much same way I do.

Mostly because I haven't gotten around to convert it yet.  The
problems with direct kthread usage are that they're much more
difficult to get completely correct with freeze and exit conditions -
the last time I checked it was easier to spot broken ones than correct
ones - and they create dedicated threads which usually are
underutilized.

Thanks.

-- 
tejun
--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Maxim Levitsky
On Mon, 2012-09-24 at 11:05 -0700, Tejun Heo wrote: 
 Hello,
 
 On Mon, Sep 24, 2012 at 05:09:23PM +0200, Maxim Levitsky wrote:
   Now that my exams done
   Can you spare me from using a workqueue?
 
 I'd much prefer if you convert to workqueue.
 
   The point is that using current model I wake the worker thread as much
   as I want to, and I know that it will be woken once an will do all the
   work till request queue is empty.
 
 You can do exactly the same thing by scheduling the same work item
 multiple times.  Waking up just becomes scheduling the work item.
I don't believe that will work this way.
I will dig through the source, and see how to do that.



   With workqueues, it doesn't work this way. I have to pass the request as
   a work item or something like that.
   Any pointers?
 
 No, there's no reason to change the structure of the code in any way.
 Just use a work item as you would use a kthread.
Except that if I schedule a same work item few times, these work items
will be 'processed' in parallel, although there is just one work to do,
work of pulling the requests from block queue until it has them, and
dispatching them through my code.
Or I can get a guarantee that work items wont be processed in parallel?
Stiil, even with that only first work item will do the actual work,
others will wake the workqueue for nothing, but I am ok with that.



 
  Also probably due to that reason MMC doesn't use a workqueue ether, but
  a raw kthread, in pretty much same way I do.
 
 Mostly because I haven't gotten around to convert it yet.  The
 problems with direct kthread usage are that they're much more
 difficult to get completely correct with freeze and exit conditions -
Agreed, I had my own share of frustration with this. I got it right in
the end though.

 the last time I checked it was easier to spot broken ones than correct
 ones - and they create dedicated threads which usually are
 underutilized.
True too, although, a sleeping thread doesn't cost much. 
 
 Thanks.
 

-- 
Best regards,
Maxim Levitsky


--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Maxim Levitsky
On Mon, 2012-09-24 at 20:19 +0200, Maxim Levitsky wrote: 
 On Mon, 2012-09-24 at 11:05 -0700, Tejun Heo wrote: 
  Hello,
  
  On Mon, Sep 24, 2012 at 05:09:23PM +0200, Maxim Levitsky wrote:
Now that my exams done
Can you spare me from using a workqueue?
  
  I'd much prefer if you convert to workqueue.
  
The point is that using current model I wake the worker thread as much
as I want to, and I know that it will be woken once an will do all the
work till request queue is empty.
  
  You can do exactly the same thing by scheduling the same work item
  multiple times.  Waking up just becomes scheduling the work item.
 I don't believe that will work this way.
 I will dig through the source, and see how to do that.
 
 
 
With workqueues, it doesn't work this way. I have to pass the request as
a work item or something like that.
Any pointers?
  
  No, there's no reason to change the structure of the code in any way.
  Just use a work item as you would use a kthread.
 Except that if I schedule a same work item few times, these work items
 will be 'processed' in parallel, although there is just one work to do,
 work of pulling the requests from block queue until it has them, and
 dispatching them through my code.
 Or I can get a guarantee that work items wont be processed in parallel?
 Stiil, even with that only first work item will do the actual work,
 others will wake the workqueue for nothing, but I am ok with that.
Should have looked through the source. Understand now.
Just one quick question, should I create my own workqueue or use
schedule_work? if I use the later and my work function sleeps, will it
harmfully affect other users of this function?


-- 
Best regards,
Maxim Levitsky



--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Tejun Heo
Hello,

On Mon, Sep 24, 2012 at 08:19:28PM +0200, Maxim Levitsky wrote:
 Except that if I schedule a same work item few times, these work items
 will be 'processed' in parallel, although there is just one work to do,
 work of pulling the requests from block queue until it has them, and
 dispatching them through my code.
 Or I can get a guarantee that work items wont be processed in parallel?

You need to use system_nrt_wq for that before 3.7-rc1.  After 3.7-rc1,
any workqueue will guarantee that.

 Stiil, even with that only first work item will do the actual work,
 others will wake the workqueue for nothing, but I am ok with that.

It's just like waking up spuriously.  The work item is guaranteed to
be executed at least once after any given schedule/queue_work() call.

Thanks.

-- 
tejun
--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-24 Thread Tejun Heo
Hello,

On Mon, Sep 24, 2012 at 08:24:37PM +0200, Maxim Levitsky wrote:
 Should have looked through the source. Understand now.
 Just one quick question, should I create my own workqueue or use
 schedule_work? if I use the later and my work function sleeps, will it
 harmfully affect other users of this function?

If memstick can be in memory reclaim path (most block devices are),
you would want to create a dedicated workqueue w/ rescuer.  For
details, please read Documentation/workqueue.txt.

Thanks.

-- 
tejun
--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-20 Thread Tejun Heo
On Thu, Sep 20, 2012 at 07:05:42AM +0300, Maxim Levitsky wrote:
> There can't be races in the driver, since it contains a single thread
> that does all the IO it got from block layer.
> The thread is awaken each time the request function of block device is
> called.
> This why I didn't do much locking in here. In addition I found out that
> this is quite common way to implement a block device driver.

Please use workqueue instead of raw kthread.

Thanks!

-- 
tejun
--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-20 Thread Tejun Heo
Hello, Andrew.

On Wed, Sep 19, 2012 at 02:52:28PM -0700, Andrew Morton wrote:
> I have a bunch of fairly trivial comments, and one head-scratcher for
> Tejun: what's up with the local-irqs-disabled requirement in sg_miter_next()?

> > +static bool sg_compare_to_buffer(struct scatterlist *sg,
> > +   int offset, u8 *buffer, size_t len)
> > +{
> > +   unsigned long flags;
> > +   int retval = 0;
> > +   struct sg_mapping_iter miter;
> > +
> > +   local_irq_save(flags);
> 
> hm, the "IRQ disabled if SG_MITER_ATOMIC" requirement of
> sg_miter_next() is weird and unexpected.
> 
> Tejun's 137d3edb48425f8 added the code whch has this strange
> requirement, but it is unexplained.  Wazzup?

Heh, that's long time ago.  Trying to remember... so it was written
before kmap_atomic() is converted to stack based implementation and
had to be supplied with the specific KMAP index.  Atomic mapping
iterator should be useable from irq context too (and there were other
irq handler paths using KM_BIO_SRC_IRQ as the name implies), so it
couldn't allow irq to happen while mapping is in use.  At the time,
having to disable IRQ to use any of KM_*_IRQs was rather self-evident.

I think we now can relax the requirement.  All that's required is not
to sleep or preempted while mapped.  Something like the following is
in order?

8<
Subject: scatterlist: atomic sg_mapping_iter no longer needs disabling IRQ

SG mapping iterator w/ SG_MITER_ATOMIC set required IRQ disabled
because it originally used KM_BIO_SRC_IRQ to allow use from IRQ
handlers.  kmap_atomic() has long been updated to handle stacking
atomic mapping requests on per-cpu basis and only requires not
sleeping while mapped.

Update sg_mapping_iter such that atomic iterators only require
disabling preemption instead of disabling IRQ.

While at it, convert wte weird @ARG@ notations to @ARG in the comment
of sg_miter_start().

Signed-off-by: Tejun Heo 
Cc: Andrew Morton 
---
 lib/scatterlist.c |   16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index fadae77..e76d85c 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -404,14 +404,13 @@ EXPORT_SYMBOL(sg_miter_start);
  * @miter: sg mapping iter to proceed
  *
  * Description:
- *   Proceeds @miter@ to the next mapping.  @miter@ should have been
- *   started using sg_miter_start().  On successful return,
- *   @miter@->page, @miter@->addr and @miter@->length point to the
- *   current mapping.
+ *   Proceeds @miter to the next mapping.  @miter should have been started
+ *   using sg_miter_start().  On successful return, @miter->page,
+ *   @miter->addr and @miter->length point to the current mapping.
  *
  * Context:
- *   IRQ disabled if SG_MITER_ATOMIC.  IRQ must stay disabled till
- *   @miter@ is stopped.  May sleep if !SG_MITER_ATOMIC.
+ *   Preemption disabled if SG_MITER_ATOMIC.  Preemption must stay disabled
+ *   till @miter is stopped.  May sleep if !SG_MITER_ATOMIC.
  *
  * Returns:
  *   true if @miter contains the next mapping.  false if end of sg
@@ -465,7 +464,8 @@ EXPORT_SYMBOL(sg_miter_next);
  *   resources (kmap) need to be released during iteration.
  *
  * Context:
- *   IRQ disabled if the SG_MITER_ATOMIC is set.  Don't care otherwise.
+ *   Preemption disabled if the SG_MITER_ATOMIC is set.  Don't care
+ *   otherwise.
  */
 void sg_miter_stop(struct sg_mapping_iter *miter)
 {
@@ -479,7 +479,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
flush_kernel_dcache_page(miter->page);
 
if (miter->__flags & SG_MITER_ATOMIC) {
-   WARN_ON(!irqs_disabled());
+   WARN_ON_ONCE(preemptible());
kunmap_atomic(miter->addr);
} else
kunmap(miter->page);
--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-20 Thread Tejun Heo
Hello, Andrew.

On Wed, Sep 19, 2012 at 02:52:28PM -0700, Andrew Morton wrote:
 I have a bunch of fairly trivial comments, and one head-scratcher for
 Tejun: what's up with the local-irqs-disabled requirement in sg_miter_next()?

  +static bool sg_compare_to_buffer(struct scatterlist *sg,
  +   int offset, u8 *buffer, size_t len)
  +{
  +   unsigned long flags;
  +   int retval = 0;
  +   struct sg_mapping_iter miter;
  +
  +   local_irq_save(flags);
 
 hm, the IRQ disabled if SG_MITER_ATOMIC requirement of
 sg_miter_next() is weird and unexpected.
 
 Tejun's 137d3edb48425f8 added the code whch has this strange
 requirement, but it is unexplained.  Wazzup?

Heh, that's long time ago.  Trying to remember... so it was written
before kmap_atomic() is converted to stack based implementation and
had to be supplied with the specific KMAP index.  Atomic mapping
iterator should be useable from irq context too (and there were other
irq handler paths using KM_BIO_SRC_IRQ as the name implies), so it
couldn't allow irq to happen while mapping is in use.  At the time,
having to disable IRQ to use any of KM_*_IRQs was rather self-evident.

I think we now can relax the requirement.  All that's required is not
to sleep or preempted while mapped.  Something like the following is
in order?

8
Subject: scatterlist: atomic sg_mapping_iter no longer needs disabling IRQ

SG mapping iterator w/ SG_MITER_ATOMIC set required IRQ disabled
because it originally used KM_BIO_SRC_IRQ to allow use from IRQ
handlers.  kmap_atomic() has long been updated to handle stacking
atomic mapping requests on per-cpu basis and only requires not
sleeping while mapped.

Update sg_mapping_iter such that atomic iterators only require
disabling preemption instead of disabling IRQ.

While at it, convert wte weird @ARG@ notations to @ARG in the comment
of sg_miter_start().

Signed-off-by: Tejun Heo t...@kernel.org
Cc: Andrew Morton a...@linux-foundation.org
---
 lib/scatterlist.c |   16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index fadae77..e76d85c 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -404,14 +404,13 @@ EXPORT_SYMBOL(sg_miter_start);
  * @miter: sg mapping iter to proceed
  *
  * Description:
- *   Proceeds @miter@ to the next mapping.  @miter@ should have been
- *   started using sg_miter_start().  On successful return,
- *   @miter@-page, @miter@-addr and @miter@-length point to the
- *   current mapping.
+ *   Proceeds @miter to the next mapping.  @miter should have been started
+ *   using sg_miter_start().  On successful return, @miter-page,
+ *   @miter-addr and @miter-length point to the current mapping.
  *
  * Context:
- *   IRQ disabled if SG_MITER_ATOMIC.  IRQ must stay disabled till
- *   @miter@ is stopped.  May sleep if !SG_MITER_ATOMIC.
+ *   Preemption disabled if SG_MITER_ATOMIC.  Preemption must stay disabled
+ *   till @miter is stopped.  May sleep if !SG_MITER_ATOMIC.
  *
  * Returns:
  *   true if @miter contains the next mapping.  false if end of sg
@@ -465,7 +464,8 @@ EXPORT_SYMBOL(sg_miter_next);
  *   resources (kmap) need to be released during iteration.
  *
  * Context:
- *   IRQ disabled if the SG_MITER_ATOMIC is set.  Don't care otherwise.
+ *   Preemption disabled if the SG_MITER_ATOMIC is set.  Don't care
+ *   otherwise.
  */
 void sg_miter_stop(struct sg_mapping_iter *miter)
 {
@@ -479,7 +479,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
flush_kernel_dcache_page(miter-page);
 
if (miter-__flags  SG_MITER_ATOMIC) {
-   WARN_ON(!irqs_disabled());
+   WARN_ON_ONCE(preemptible());
kunmap_atomic(miter-addr);
} else
kunmap(miter-page);
--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-20 Thread Tejun Heo
On Thu, Sep 20, 2012 at 07:05:42AM +0300, Maxim Levitsky wrote:
 There can't be races in the driver, since it contains a single thread
 that does all the IO it got from block layer.
 The thread is awaken each time the request function of block device is
 called.
 This why I didn't do much locking in here. In addition I found out that
 this is quite common way to implement a block device driver.

Please use workqueue instead of raw kthread.

Thanks!

-- 
tejun
--
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: [PATCH] memstick: add support for legacy memorysticks

2012-09-19 Thread Maxim Levitsky
On Wed, 2012-09-19 at 14:52 -0700, Andrew Morton wrote: 
> On Wed, 19 Sep 2012 16:19:02 +0300
> Maxim Levitsky  wrote:
> 
> > Based partially on MS standard spec quotes from Alex Dubov.
> > 
> > As any code that works with user data this driver isn't
> > recommended to use to write cards that contain valuable data.
> > 
> > It tries its best though to avoid data corruption
> > and possible damage to the card.
> > 
> > Tested on MS DUO 64 MB card on Ricoh R592 card reader..
> > 
> 
> Generally looks nice to me, although I wouldn't know a memstick if one
> stuck to my shoe.
> 
> I have a bunch of fairly trivial comments, and one head-scratcher for
> Tejun: what's up with the local-irqs-disabled requirement in sg_miter_next()?

Awesome, thanks for the review!
I will address all comments very soon.

> 
> > ...
> >
> > +static int sg_nents(struct scatterlist *sg)
> > +{
> > +   int nents = 0;
> > +   while (sg) {
> > +   nents++;
> > +   sg = sg_next(sg);
> > +   }
> > +
> > +   return nents;
> > +}
> 
> I think we may as well put this in scatterlist.c immediately.  It
> wouldn't surprise me if we already have open-coded copies of this lying
> around the tree.
I agree, but as usual afraid that it wont be accepted here.

> 
> > +/*
> > + * Copies section of 'sg_from' starting from offset 'offset' and with 
> > length
> > + * 'len' To another scatterlist of to_nents enties
> > + */
> > +static int sg_copy(struct scatterlist *sg_from, struct scatterlist *sg_to,
> > +   int to_nents, int offset, size_t len)
> 
> The should return a size_t, to match the type of `len'.  And the type
> of `offset' is fishy - there's nothing which intrinsically limits these
> things to 2G?
In my case, I will never have large offsets here, but I agree with you
completely. 
> 
> > +{
> > +   int copied = 0;
> > +
> > +   while (offset > 0) {
> > +
> > +   if (offset >= sg_from->length) {
> > +   if (sg_is_last(sg_from))
> > +   return 0;
> > +
> > +   offset -= sg_from->length;
> > +   sg_from = sg_next(sg_from);
> > +   continue;
> > +   }
> > +
> > +   copied = min(len, (size_t)(sg_from->length - offset));
> 
> min_t would be more conventional.  Or perhaps even min(), depending on
> `offset's new type (but probably not).
Agree. 
> 
> > +   sg_set_page(sg_to, sg_page(sg_from),
> > +   copied, sg_from->offset + offset);
> > +
> > +   len -= copied;
> > +   offset = 0;
> > +
> > +   if (sg_is_last(sg_from) || !len)
> > +   goto out;
> > +
> > +   sg_to = sg_next(sg_to);
> > +   to_nents--;
> > +   sg_from = sg_next(sg_from);
> > +   }
> > +
> > +   while (len > sg_from->length && to_nents--) {
> > +
> > +   len -= sg_from->length;
> > +   copied += sg_from->length;
> > +
> > +   sg_set_page(sg_to, sg_page(sg_from),
> > +   sg_from->length, sg_from->offset);
> > +
> > +   if (sg_is_last(sg_from) || !len)
> > +   goto out;
> > +
> > +   sg_from = sg_next(sg_from);
> > +   sg_to = sg_next(sg_to);
> > +   }
> > +
> > +   if (len && to_nents) {
> > +   sg_set_page(sg_to, sg_page(sg_from), len, sg_from->offset);
> > +   copied += len;
> > +   }
> > +
> > +out:
> > +   sg_mark_end(sg_to);
> > +   return copied;
> > +}
> > +
> > +/*
> > + * Compares section of 'sg' starting from offset 'offset' and with length 
> > 'len'
> > + * to linear buffer of length 'len' at address 'buffer'
> 
> The comment should document the return value.
> 
> > + */
> > +static bool sg_compare_to_buffer(struct scatterlist *sg,
> > +   int offset, u8 *buffer, size_t len)
> > +{
> > +   unsigned long flags;
> > +   int retval = 0;
> > +   struct sg_mapping_iter miter;
> > +
> > +   local_irq_save(flags);
> 
> hm, the "IRQ disabled if SG_MITER_ATOMIC" requirement of
> sg_miter_next() is weird and unexpected.
> 
> Tejun's 137d3edb48425f8 added the code whch has this strange
> requirement, but it is unexplained.  Wazzup?
> 
> > +   sg_miter_start(, sg, sg_nents(sg),
> > +   SG_MITER_ATOMIC | SG_MITER_FROM_SG);
> > +
> > +   while (sg_miter_next() && len > 0) {
> > +
> > +   int cmplen;
> > +
> > +   if (offset >= miter.length) {
> > +   offset -= miter.length;
> > +   continue;
> > +   }
> > +
> > +   cmplen = min(miter.length - offset, len);
> > +   retval = memcmp(miter.addr + offset, buffer, cmplen);
> > +   if (retval)
> > +   break;
> > +
> > +   buffer += cmplen;
> > +   len -= cmplen;
> > +   offset = 0;
> > +   }
> > +
> > +   if (!retval && len)
> > +   retval = -1;
> > +
> > +   sg_miter_stop();
> > +   local_irq_restore(flags);
> 

Re: [PATCH] memstick: add support for legacy memorysticks

2012-09-19 Thread Andrew Morton
On Wed, 19 Sep 2012 16:19:02 +0300
Maxim Levitsky  wrote:

> Based partially on MS standard spec quotes from Alex Dubov.
> 
> As any code that works with user data this driver isn't
> recommended to use to write cards that contain valuable data.
> 
> It tries its best though to avoid data corruption
> and possible damage to the card.
> 
> Tested on MS DUO 64 MB card on Ricoh R592 card reader..
> 

Generally looks nice to me, although I wouldn't know a memstick if one
stuck to my shoe.

I have a bunch of fairly trivial comments, and one head-scratcher for
Tejun: what's up with the local-irqs-disabled requirement in sg_miter_next()?

> ...
>
> +static int sg_nents(struct scatterlist *sg)
> +{
> + int nents = 0;
> + while (sg) {
> + nents++;
> + sg = sg_next(sg);
> + }
> +
> + return nents;
> +}

I think we may as well put this in scatterlist.c immediately.  It
wouldn't surprise me if we already have open-coded copies of this lying
around the tree.

> +/*
> + * Copies section of 'sg_from' starting from offset 'offset' and with length
> + * 'len' To another scatterlist of to_nents enties
> + */
> +static int sg_copy(struct scatterlist *sg_from, struct scatterlist *sg_to,
> + int to_nents, int offset, size_t len)

The should return a size_t, to match the type of `len'.  And the type
of `offset' is fishy - there's nothing which intrinsically limits these
things to 2G?

> +{
> + int copied = 0;
> +
> + while (offset > 0) {
> +
> + if (offset >= sg_from->length) {
> + if (sg_is_last(sg_from))
> + return 0;
> +
> + offset -= sg_from->length;
> + sg_from = sg_next(sg_from);
> + continue;
> + }
> +
> + copied = min(len, (size_t)(sg_from->length - offset));

min_t would be more conventional.  Or perhaps even min(), depending on
`offset's new type (but probably not).

> + sg_set_page(sg_to, sg_page(sg_from),
> + copied, sg_from->offset + offset);
> +
> + len -= copied;
> + offset = 0;
> +
> + if (sg_is_last(sg_from) || !len)
> + goto out;
> +
> + sg_to = sg_next(sg_to);
> + to_nents--;
> + sg_from = sg_next(sg_from);
> + }
> +
> + while (len > sg_from->length && to_nents--) {
> +
> + len -= sg_from->length;
> + copied += sg_from->length;
> +
> + sg_set_page(sg_to, sg_page(sg_from),
> + sg_from->length, sg_from->offset);
> +
> + if (sg_is_last(sg_from) || !len)
> + goto out;
> +
> + sg_from = sg_next(sg_from);
> + sg_to = sg_next(sg_to);
> + }
> +
> + if (len && to_nents) {
> + sg_set_page(sg_to, sg_page(sg_from), len, sg_from->offset);
> + copied += len;
> + }
> +
> +out:
> + sg_mark_end(sg_to);
> + return copied;
> +}
> +
> +/*
> + * Compares section of 'sg' starting from offset 'offset' and with length 
> 'len'
> + * to linear buffer of length 'len' at address 'buffer'

The comment should document the return value.

> + */
> +static bool sg_compare_to_buffer(struct scatterlist *sg,
> + int offset, u8 *buffer, size_t len)
> +{
> + unsigned long flags;
> + int retval = 0;
> + struct sg_mapping_iter miter;
> +
> + local_irq_save(flags);

hm, the "IRQ disabled if SG_MITER_ATOMIC" requirement of
sg_miter_next() is weird and unexpected.

Tejun's 137d3edb48425f8 added the code whch has this strange
requirement, but it is unexplained.  Wazzup?

> + sg_miter_start(, sg, sg_nents(sg),
> + SG_MITER_ATOMIC | SG_MITER_FROM_SG);
> +
> + while (sg_miter_next() && len > 0) {
> +
> + int cmplen;
> +
> + if (offset >= miter.length) {
> + offset -= miter.length;
> + continue;
> + }
> +
> + cmplen = min(miter.length - offset, len);
> + retval = memcmp(miter.addr + offset, buffer, cmplen);
> + if (retval)
> + break;
> +
> + buffer += cmplen;
> + len -= cmplen;
> + offset = 0;
> + }
> +
> + if (!retval && len)
> + retval = -1;
> +
> + sg_miter_stop();
> + local_irq_restore(flags);
> + return retval;
> +}
>
> ...
>
> +static void msb_mark_block_unused(struct msb_data *msb, int pba)
> +{
> + int zone = msb_get_zone_from_pba(pba);
> +
> + if (!test_bit(pba, msb->used_blocks_bitmap)) {
> + ms_printk("BUG: attempt to mark "
> + "already unused pba %d as unused" , pba);
> + msb->read_only = true;
> + return;
> + }
> +
> +#ifdef DEBUG
> + if 

Re: [PATCH] memstick: add support for legacy memorysticks

2012-09-19 Thread Andrew Morton
On Wed, 19 Sep 2012 16:19:02 +0300
Maxim Levitsky maximlevit...@gmail.com wrote:

 Based partially on MS standard spec quotes from Alex Dubov.
 
 As any code that works with user data this driver isn't
 recommended to use to write cards that contain valuable data.
 
 It tries its best though to avoid data corruption
 and possible damage to the card.
 
 Tested on MS DUO 64 MB card on Ricoh R592 card reader..
 

Generally looks nice to me, although I wouldn't know a memstick if one
stuck to my shoe.

I have a bunch of fairly trivial comments, and one head-scratcher for
Tejun: what's up with the local-irqs-disabled requirement in sg_miter_next()?

 ...

 +static int sg_nents(struct scatterlist *sg)
 +{
 + int nents = 0;
 + while (sg) {
 + nents++;
 + sg = sg_next(sg);
 + }
 +
 + return nents;
 +}

I think we may as well put this in scatterlist.c immediately.  It
wouldn't surprise me if we already have open-coded copies of this lying
around the tree.

 +/*
 + * Copies section of 'sg_from' starting from offset 'offset' and with length
 + * 'len' To another scatterlist of to_nents enties
 + */
 +static int sg_copy(struct scatterlist *sg_from, struct scatterlist *sg_to,
 + int to_nents, int offset, size_t len)

The should return a size_t, to match the type of `len'.  And the type
of `offset' is fishy - there's nothing which intrinsically limits these
things to 2G?

 +{
 + int copied = 0;
 +
 + while (offset  0) {
 +
 + if (offset = sg_from-length) {
 + if (sg_is_last(sg_from))
 + return 0;
 +
 + offset -= sg_from-length;
 + sg_from = sg_next(sg_from);
 + continue;
 + }
 +
 + copied = min(len, (size_t)(sg_from-length - offset));

min_t would be more conventional.  Or perhaps even min(), depending on
`offset's new type (but probably not).

 + sg_set_page(sg_to, sg_page(sg_from),
 + copied, sg_from-offset + offset);
 +
 + len -= copied;
 + offset = 0;
 +
 + if (sg_is_last(sg_from) || !len)
 + goto out;
 +
 + sg_to = sg_next(sg_to);
 + to_nents--;
 + sg_from = sg_next(sg_from);
 + }
 +
 + while (len  sg_from-length  to_nents--) {
 +
 + len -= sg_from-length;
 + copied += sg_from-length;
 +
 + sg_set_page(sg_to, sg_page(sg_from),
 + sg_from-length, sg_from-offset);
 +
 + if (sg_is_last(sg_from) || !len)
 + goto out;
 +
 + sg_from = sg_next(sg_from);
 + sg_to = sg_next(sg_to);
 + }
 +
 + if (len  to_nents) {
 + sg_set_page(sg_to, sg_page(sg_from), len, sg_from-offset);
 + copied += len;
 + }
 +
 +out:
 + sg_mark_end(sg_to);
 + return copied;
 +}
 +
 +/*
 + * Compares section of 'sg' starting from offset 'offset' and with length 
 'len'
 + * to linear buffer of length 'len' at address 'buffer'

The comment should document the return value.

 + */
 +static bool sg_compare_to_buffer(struct scatterlist *sg,
 + int offset, u8 *buffer, size_t len)
 +{
 + unsigned long flags;
 + int retval = 0;
 + struct sg_mapping_iter miter;
 +
 + local_irq_save(flags);

hm, the IRQ disabled if SG_MITER_ATOMIC requirement of
sg_miter_next() is weird and unexpected.

Tejun's 137d3edb48425f8 added the code whch has this strange
requirement, but it is unexplained.  Wazzup?

 + sg_miter_start(miter, sg, sg_nents(sg),
 + SG_MITER_ATOMIC | SG_MITER_FROM_SG);
 +
 + while (sg_miter_next(miter)  len  0) {
 +
 + int cmplen;
 +
 + if (offset = miter.length) {
 + offset -= miter.length;
 + continue;
 + }
 +
 + cmplen = min(miter.length - offset, len);
 + retval = memcmp(miter.addr + offset, buffer, cmplen);
 + if (retval)
 + break;
 +
 + buffer += cmplen;
 + len -= cmplen;
 + offset = 0;
 + }
 +
 + if (!retval  len)
 + retval = -1;
 +
 + sg_miter_stop(miter);
 + local_irq_restore(flags);
 + return retval;
 +}

 ...

 +static void msb_mark_block_unused(struct msb_data *msb, int pba)
 +{
 + int zone = msb_get_zone_from_pba(pba);
 +
 + if (!test_bit(pba, msb-used_blocks_bitmap)) {
 + ms_printk(BUG: attempt to mark 
 + already unused pba %d as unused , pba);
 + msb-read_only = true;
 + return;
 + }
 +
 +#ifdef DEBUG
 + if (msb_validate_used_block_bitmap(msb))
 + return;
 +#endif
 + clear_bit(pba, msb-used_blocks_bitmap);
 + msb-free_block_count[zone]++;

Re: [PATCH] memstick: add support for legacy memorysticks

2012-09-19 Thread Maxim Levitsky
On Wed, 2012-09-19 at 14:52 -0700, Andrew Morton wrote: 
 On Wed, 19 Sep 2012 16:19:02 +0300
 Maxim Levitsky maximlevit...@gmail.com wrote:
 
  Based partially on MS standard spec quotes from Alex Dubov.
  
  As any code that works with user data this driver isn't
  recommended to use to write cards that contain valuable data.
  
  It tries its best though to avoid data corruption
  and possible damage to the card.
  
  Tested on MS DUO 64 MB card on Ricoh R592 card reader..
  
 
 Generally looks nice to me, although I wouldn't know a memstick if one
 stuck to my shoe.
 
 I have a bunch of fairly trivial comments, and one head-scratcher for
 Tejun: what's up with the local-irqs-disabled requirement in sg_miter_next()?

Awesome, thanks for the review!
I will address all comments very soon.

 
  ...
 
  +static int sg_nents(struct scatterlist *sg)
  +{
  +   int nents = 0;
  +   while (sg) {
  +   nents++;
  +   sg = sg_next(sg);
  +   }
  +
  +   return nents;
  +}
 
 I think we may as well put this in scatterlist.c immediately.  It
 wouldn't surprise me if we already have open-coded copies of this lying
 around the tree.
I agree, but as usual afraid that it wont be accepted here.

 
  +/*
  + * Copies section of 'sg_from' starting from offset 'offset' and with 
  length
  + * 'len' To another scatterlist of to_nents enties
  + */
  +static int sg_copy(struct scatterlist *sg_from, struct scatterlist *sg_to,
  +   int to_nents, int offset, size_t len)
 
 The should return a size_t, to match the type of `len'.  And the type
 of `offset' is fishy - there's nothing which intrinsically limits these
 things to 2G?
In my case, I will never have large offsets here, but I agree with you
completely. 
 
  +{
  +   int copied = 0;
  +
  +   while (offset  0) {
  +
  +   if (offset = sg_from-length) {
  +   if (sg_is_last(sg_from))
  +   return 0;
  +
  +   offset -= sg_from-length;
  +   sg_from = sg_next(sg_from);
  +   continue;
  +   }
  +
  +   copied = min(len, (size_t)(sg_from-length - offset));
 
 min_t would be more conventional.  Or perhaps even min(), depending on
 `offset's new type (but probably not).
Agree. 
 
  +   sg_set_page(sg_to, sg_page(sg_from),
  +   copied, sg_from-offset + offset);
  +
  +   len -= copied;
  +   offset = 0;
  +
  +   if (sg_is_last(sg_from) || !len)
  +   goto out;
  +
  +   sg_to = sg_next(sg_to);
  +   to_nents--;
  +   sg_from = sg_next(sg_from);
  +   }
  +
  +   while (len  sg_from-length  to_nents--) {
  +
  +   len -= sg_from-length;
  +   copied += sg_from-length;
  +
  +   sg_set_page(sg_to, sg_page(sg_from),
  +   sg_from-length, sg_from-offset);
  +
  +   if (sg_is_last(sg_from) || !len)
  +   goto out;
  +
  +   sg_from = sg_next(sg_from);
  +   sg_to = sg_next(sg_to);
  +   }
  +
  +   if (len  to_nents) {
  +   sg_set_page(sg_to, sg_page(sg_from), len, sg_from-offset);
  +   copied += len;
  +   }
  +
  +out:
  +   sg_mark_end(sg_to);
  +   return copied;
  +}
  +
  +/*
  + * Compares section of 'sg' starting from offset 'offset' and with length 
  'len'
  + * to linear buffer of length 'len' at address 'buffer'
 
 The comment should document the return value.
 
  + */
  +static bool sg_compare_to_buffer(struct scatterlist *sg,
  +   int offset, u8 *buffer, size_t len)
  +{
  +   unsigned long flags;
  +   int retval = 0;
  +   struct sg_mapping_iter miter;
  +
  +   local_irq_save(flags);
 
 hm, the IRQ disabled if SG_MITER_ATOMIC requirement of
 sg_miter_next() is weird and unexpected.
 
 Tejun's 137d3edb48425f8 added the code whch has this strange
 requirement, but it is unexplained.  Wazzup?
 
  +   sg_miter_start(miter, sg, sg_nents(sg),
  +   SG_MITER_ATOMIC | SG_MITER_FROM_SG);
  +
  +   while (sg_miter_next(miter)  len  0) {
  +
  +   int cmplen;
  +
  +   if (offset = miter.length) {
  +   offset -= miter.length;
  +   continue;
  +   }
  +
  +   cmplen = min(miter.length - offset, len);
  +   retval = memcmp(miter.addr + offset, buffer, cmplen);
  +   if (retval)
  +   break;
  +
  +   buffer += cmplen;
  +   len -= cmplen;
  +   offset = 0;
  +   }
  +
  +   if (!retval  len)
  +   retval = -1;
  +
  +   sg_miter_stop(miter);
  +   local_irq_restore(flags);
  +   return retval;
  +}
 
  ...
 
  +static void msb_mark_block_unused(struct msb_data *msb, int pba)
  +{
  +   int zone = msb_get_zone_from_pba(pba);
  +
  +   if (!test_bit(pba, msb-used_blocks_bitmap)) {
  +   ms_printk(BUG: attempt to mark 
  +