Re: [PATCH] usbhid: use GFP_NOIO in reset code path

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

 



Oliver, sorry for missing list.

On Wed, Oct 10, 2012 at 10:12 PM, Oliver Neukum <oneukum@xxxxxxx> wrote:

> Which components? We generally don't do that. We may have
> a problem with locks being held though.

As I pointed out before, rebind may be involved to reset path, and probe(),
disconnect(), some sysfs things will call GFP_KERNEL allocation of course.

At least, in theory, one by one convert can't avoid it except that
all function calls can be controlled by its caller, but that is not
practical.

> This is much harder than it sounds.

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;
 }
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 7091bfa..fd82dc2 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -161,6 +161,7 @@ extern struct task_group root_task_group;
 	.stack		= &init_thread_info,				\
 	.usage		= ATOMIC_INIT(2),				\
 	.flags		= PF_KTHREAD,					\
+	.gfp_allowed_mask = 0xffffffff,					\
 	.prio		= MAX_PRIO-20,					\
 	.static_prio	= MAX_PRIO-20,					\
 	.normal_prio	= MAX_PRIO-20,					\
diff --git a/include/linux/sched.h b/include/linux/sched.h
index f6961c9..ac874b2 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1236,6 +1236,8 @@ struct task_struct {
 	unsigned int flags;	/* per process flags, defined below */
 	unsigned int ptrace;

+	gfp_t	gfp_allowed_mask;
+
 #ifdef CONFIG_SMP
 	struct llist_node wake_entry;
 	int on_cpu;
@@ -1613,6 +1615,16 @@ static inline int tsk_home_node(struct task_struct *p)
 #endif
 }

+static inline void tsk_set_allowd_gfp(struct task_struct *p, gfp_t gfp)
+{
+	p->gfp_allowed_mask = gfp;
+}
+
+static inline gfp_t tsk_get_allowd_gfp(struct task_struct *p)
+{
+	return p->gfp_allowed_mask;
+}
+
 /*
  * Priority of a process goes from 0..MAX_PRIO-1, valid RT
  * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
diff --git a/kernel/fork.c b/kernel/fork.c
index c34c7f0..69c2530 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -311,6 +311,7 @@ static struct task_struct *dup_task_struct(struct
task_struct *orig)

 	tsk->stack = ti;

+	tsk_set_allowd_gfp(tsk, 0xffffffff);
 	setup_thread_stack(tsk, orig);
 	clear_user_return_notifier(tsk);
 	clear_tsk_need_resched(tsk);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 8e1be1c..36a1e77 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2595,7 +2595,7 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
 	unsigned int cpuset_mems_cookie;
 	int alloc_flags = ALLOC_WMARK_LOW|ALLOC_CPUSET;

-	gfp_mask &= gfp_allowed_mask;
+	gfp_mask &= gfp_allowed_mask & tsk_get_allowd_gfp(current);

 	lockdep_trace_alloc(gfp_mask);

diff --git a/mm/slab.c b/mm/slab.c
index 33d3363..2c4ef9a 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3523,7 +3523,7 @@ slab_alloc_node(struct kmem_cache *cachep, gfp_t
flags, int nodeid,
 	void *ptr;
 	int slab_node = numa_mem_id();

-	flags &= gfp_allowed_mask;
+	flags &= gfp_allowed_mask & tsk_get_allowd_gfp(current);

 	lockdep_trace_alloc(flags);

@@ -3608,7 +3608,7 @@ slab_alloc(struct kmem_cache *cachep, gfp_t
flags, unsigned long caller)
 	unsigned long save_flags;
 	void *objp;

-	flags &= gfp_allowed_mask;
+	flags &= gfp_allowed_mask & tsk_get_allowd_gfp(current);

 	lockdep_trace_alloc(flags);

diff --git a/mm/slob.c b/mm/slob.c
index a08e468..42c0476 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -432,7 +432,7 @@ __do_kmalloc_node(size_t size, gfp_t gfp, int
node, unsigned long caller)
 	int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
 	void *ret;

-	gfp &= gfp_allowed_mask;
+	gfp &= gfp_allowed_mask & tsk_get_allowd_gfp(current);

 	lockdep_trace_alloc(gfp);

@@ -552,7 +552,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *c,
gfp_t flags, int node)
 {
 	void *b;

-	flags &= gfp_allowed_mask;
+	flags &= gfp_allowed_mask & tsk_get_allowd_gfp(current);

 	lockdep_trace_alloc(flags);

diff --git a/mm/slub.c b/mm/slub.c
index a0d6984..c90ca6e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -923,7 +923,7 @@ static void trace(struct kmem_cache *s, struct
page *page, void *object,
  */
 static inline int slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags)
 {
-	flags &= gfp_allowed_mask;
+	flags &= gfp_allowed_mask & tsk_get_allowd_gfp(current);
 	lockdep_trace_alloc(flags);
 	might_sleep_if(flags & __GFP_WAIT);

@@ -932,7 +932,7 @@ static inline int slab_pre_alloc_hook(struct
kmem_cache *s, gfp_t flags)

 static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t
flags, void *object)
 {
-	flags &= gfp_allowed_mask;
+	flags &= gfp_allowed_mask & tsk_get_allowd_gfp(current);
 	kmemcheck_slab_alloc(s, flags, object, slab_ksize(s));
 	kmemleak_alloc_recursive(object, s->object_size, 1, s->flags, flags);
 }
@@ -1278,7 +1278,7 @@ static struct page *allocate_slab(struct
kmem_cache *s, gfp_t flags, int node)
 	struct kmem_cache_order_objects oo = s->oo;
 	gfp_t alloc_gfp;

-	flags &= gfp_allowed_mask;
+	flags &= gfp_allowed_mask & tsk_get_allowd_gfp(current);

 	if (flags & __GFP_WAIT)
 		local_irq_enable();



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


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

  Powered by Linux