On Thu, Oct 11, 2012 at 12:00 AM, Ming Lei <tom.leiming@xxxxxxxxx> wrote: > > Keeping allowed gfp_flag inside task_struct should be one solution, and > let that teach mm to allocate memory, see the draft idea below: > > diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c > index c0543c8..781447f 100644 > --- a/drivers/usb/storage/transport.c > +++ b/drivers/usb/storage/transport.c > @@ -1329,11 +1329,13 @@ EXPORT_SYMBOL_GPL(usb_stor_Bulk_reset); > int usb_stor_port_reset(struct us_data *us) > { > int result; > + gfp_t orig_gfp = tsk_get_allowd_gfp(current); > > /*for these devices we must use the class specific method */ > if (us->pusb_dev->quirks & USB_QUIRK_RESET) > return -EPERM; > > + tsk_set_allowd_gfp(current, orig_gfp & ~GFP_IOFS); > result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); > if (result < 0) > US_DEBUGP("unable to lock device for reset: %d\n", result); > @@ -1349,5 +1351,6 @@ int usb_stor_port_reset(struct us_data *us) > } > usb_unlock_device(us->pusb_dev); > } > + tsk_set_allowd_gfp(current, orig_gfp); > return result; In fact, the error handling case may be generalized to the context which is doing the actual IO transfer, and the change on mass storage should be as below. We can find other similar situations too, such as mmc thread(mmc_queue_thread). I will study the problem further so that more block drivers or subsystem can benefit from the idea, which may help to persuade LKML people to accept it. diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 12aa726..29ad4ac 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -297,7 +297,9 @@ static int usb_stor_control_thread(void * __us) { struct us_data *us = (struct us_data *)__us; struct Scsi_Host *host = us_to_host(us); + gfp_t orig_gfp = tsk_get_allowd_gfp(current); + tsk_set_allowd_gfp(current, orig_gfp & ~GFP_IOFS); for (;;) { US_DEBUGP("*** thread sleeping.\n"); if (wait_for_completion_interruptible(&us->cmnd_ready)) @@ -404,6 +406,7 @@ SkipForAbort: /* unlock the device pointers */ mutex_unlock(&us->dev_mutex); } /* for (;;) */ + tsk_set_allowd_gfp(current, orig_gfp); /* Wait until we are told to stop */ for (;;) { Thanks, -- Ming Lei -- 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