mm/dmapool.c: Do not create/destroy sysfs file while holding pools_lock
Subsystems (2)
PATCH 1/1 mm/dmapool.c: Do not create/destroy sysfs file while holding pools_lock
From: Shaun Ruffell <[email protected]>
Eliminates a circular lock dependency reported by lockdep. When reading the "pools" file from a PCI device via sysfs, the s_active lock is acquired before the pools_lock. When unloading the driver and destroying the pool, pools_lock is acquired before the s_active lock.
cat/12016 is trying to acquire lock:
(pools_lock){+.+.+.}, at: [<c04ef113>] show_pools+0x43/0x140
but task is already holding lock:
(s_active#82){++++.+}, at: [<c0554e1b>] sysfs_read_file+0xab/0x160
which lock already depends on the new lock.
--- mm/dmapool.c | 34 ++++++++++++++++++++++++---------- 1 files changed, 24 insertions(+), 10 deletions(-)
mm/dmapool.c +24 -10
@@ -174,21 +174,28 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,init_waitqueue_head (&retval->waitq);if (dev) { -int ret; +int first_pool;mutex_lock (&pools_lock);if (list_empty (&dev->dma_pools)) - ret =device_create_file (dev, &dev_attr_pools); + first_pool =1 ;else - ret =0 ; + first_pool =0 ;/* note: not currently insisting "name" be unique */ -if (!ret) -list_add (&retval->pools, &dev->dma_pools); -else { -kfree (retval); - retval =NULL ; - } +list_add (&retval->pools, &dev->dma_pools);mutex_unlock (&pools_lock); + +if (first_pool) { +int ret; + ret =device_create_file (dev, &dev_attr_pools); +if (ret) { +mutex_lock (&pools_lock); +list_del (&retval->pools); +mutex_unlock (&pools_lock); +kfree (retval); + retval =NULL ; + } + } }else INIT_LIST_HEAD (&retval->pools);
@@ -263,12 +270,19 @@ static void pool_free_page(struct dma_pool *pool, struct dma_page *page)*/ void dma_pool_destroy (struct dma_pool *pool) { +int last_pool; +mutex_lock (&pools_lock);list_del (&pool->pools);if (pool->dev &&list_empty (&pool->dev->dma_pools)) -device_remove_file (pool->dev, &dev_attr_pools); + last_pool =1 ; +else + last_pool =0 ;mutex_unlock (&pools_lock); +if (last_pool) +device_remove_file (pool->dev, &dev_attr_pools); +while (!list_empty (&pool->page_list)) {struct dma_page *page; page = list_entry(pool->page_list.next,
Signature · 8 lines
1.7.2.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrew Morton
maintainerQuoted 7 lines · On Mon, 28 Feb 2011 16:41:24 -0600 Russ Meyerriecks <[email protected]>…
From: Shaun Ruffell <[email protected]>
Eliminates a circular lock dependency reported by lockdep. When reading the "pools" file from a PCI device via sysfs, the
s_activelock is acquired before thepools_lock. When unloading the driver and destroying the pool,pools_lockis acquired before thes_activelock.
Quoted 7 lines
cat/12016 is trying to acquire lock:
(pools_lock){+.+.+.}, at: [<c04ef113>]show_pools+0x43/0x140but task is already holding lock:
(s_active#82){++++.+}, at: [<c0554e1b>]sysfs_read_file+0xab/0x160which lock already depends on the new lock.
sysfs_dirent_init_lockdep() and the 6992f53349 ("sysfs: Use one lockdep class per sysfs attribute") which added it are rather scary.
The alleged bug appears to be due to taking pools_lock outside device_create_file() (which takes magical sysfs PseudoVirtualLocks) versus show_pools(), which takes pools_lock but is called from inside magical sysfs PseudoVirtualLocks.
I don't know if this is actually a real bug or not. Probably not, as this device_create_file() does not match the reasons for 6992f53349:
"There is a sysfs idiom where writing to one sysfs file causes the addition or removal of other sysfs files". But that's a guess.
Quoted 27 lines
mm/dmapool.c +6
-9@@ -174,21 +174,28 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,init_waitqueue_head (&retval->waitq);if (dev) { -int ret; +int first_pool;mutex_lock (&pools_lock);if (list_empty (&dev->dma_pools)) - ret =device_create_file (dev, &dev_attr_pools); + first_pool =1 ;else - ret =0 ; + first_pool =0 ;/* note: not currently insisting "name" be unique */ -if (!ret) -list_add (&retval->pools, &dev->dma_pools); -else { -kfree (retval); - retval =NULL ; - } +list_add (&retval->pools, &dev->dma_pools);mutex_unlock (&pools_lock); + +if (first_pool) {
mm/dmapool.c struct dma_pool *dma_pool_create(const char *name, struct device *dev, · line 198
Quoted 10 lines
mm/dmapool.c +10
-0+int ret; + ret =device_create_file (dev, &dev_attr_pools); +if (ret) { +mutex_lock (&pools_lock); +list_del (&retval->pools); +mutex_unlock (&pools_lock); +kfree (retval); + retval =NULL ; + } + }
Not a good fix, IMO. The problem is that if two CPUs concurrently call dma_pool_create(), the first CPU will spend time creating the sysfs file. Meanwhile, the second CPU will whizz straight back to its caller. The caller now thinks that the sysfs file has been created and returns to userspace, which immediately tries to read the sysfs file. But the first CPU hasn't finished creating it yet. Userspace fails.
One way of fixing this would be to create another singleton lock:
{
static DEFINE_MUTEX(pools_sysfs_lock);
static bool pools_sysfs_done;
mutex_lock(&pools_sysfs_lock);
if (pools_sysfs_done == false) {
create_sysfs_stuff();
pools_sysfs_done = true;
}
mutex_unlock(&pools_sysfs_lock);
}That's not terribly pretty.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 26 lines · Andrew Morton
Quoted 7 lines · On Mon, 28 Feb 2011 16:41:24 -0600 Russ Meyerriecks <[email protected]>…
From: Shaun Ruffell <[email protected]>
Eliminates a circular lock dependency reported by lockdep. When reading the "pools" file from a PCI device via sysfs, the
s_activelock is acquired before thepools_lock. When unloading the driver and destroying the pool,pools_lockis acquired before thes_activelock.Quoted 7 lines
cat/12016 is trying to acquire lock:
(pools_lock){+.+.+.}, at: [<c04ef113>]show_pools+0x43/0x140but task is already holding lock:
(s_active#82){++++.+}, at: [<c0554e1b>]sysfs_read_file+0xab/0x160which lock already depends on the new lock.
sysfs_dirent_init_lockdep()and the6992f53349("sysfs: Use one lockdep class per sysfs attribute") which added it are rather scary.The alleged bug appears to be due to taking
pools_lockoutsidedevice_create_file()(which takes magical sysfs PseudoVirtualLocks) versusshow_pools(), which takespools_lockbut is called from inside magical sysfs PseudoVirtualLocks.
Quoted 4 lines
I don't know if this is actually a real bug or not. Probably not, as this
device_create_file()does not match the reasons for6992f53349:
"There is a sysfs idiom where writing to one sysfs file causes the addition or removal of other sysfs files". But that's a guess.
device_create_file is arguable But this also happens with device_remove_file, and that is exactly the deadlock scenario I added the lockdep annotation to catch. So the patch clearly does not fix the issue.
Eric
Quoted 60 lines
Quoted 27 lines
mm/dmapool.c +6
-9@@ -174,21 +174,28 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,init_waitqueue_head (&retval->waitq);if (dev) { -int ret; +int first_pool;mutex_lock (&pools_lock);if (list_empty (&dev->dma_pools)) - ret =device_create_file (dev, &dev_attr_pools); + first_pool =1 ;else - ret =0 ; + first_pool =0 ;/* note: not currently insisting "name" be unique */ -if (!ret) -list_add (&retval->pools, &dev->dma_pools); -else { -kfree (retval); - retval =NULL ; - } +list_add (&retval->pools, &dev->dma_pools);mutex_unlock (&pools_lock); + +if (first_pool) {mm/dmapool.c struct dma_pool *dma_pool_create(const char *name, struct device *dev, · line 198
Quoted 10 lines
mm/dmapool.c +10
-0+int ret; + ret =device_create_file (dev, &dev_attr_pools); +if (ret) { +mutex_lock (&pools_lock); +list_del (&retval->pools); +mutex_unlock (&pools_lock); +kfree (retval); + retval =NULL ; + } + }Not a good fix, IMO. The problem is that if two CPUs concurrently call
dma_pool_create(), the first CPU will spend time creating the sysfs file. Meanwhile, the second CPU will whizz straight back to its caller. The caller now thinks that the sysfs file has been created and returns to userspace, which immediately tries to read the sysfs file. But the first CPU hasn't finished creating it yet. Userspace fails.One way of fixing this would be to create another singleton lock:
{ static DEFINE_MUTEX(pools_sysfs_lock); static bool pools_sysfs_done; mutex_lock(&pools_sysfs_lock); if (pools_sysfs_done == false) { create_sysfs_stuff(); pools_sysfs_done = true; } mutex_unlock(&pools_sysfs_lock); }
Quoted 1 line
That's not terribly pretty.
Or possibly use module_init style magic. Where use module initialization and remove to trigger creation and deletion of the sysfs.
Eric
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 16 lines · Eric W. Biederman
Quoted 15 lines · Andrew Morton
One way of fixing this would be to create another singleton lock:
{ static DEFINE_MUTEX(pools_sysfs_lock); static bool pools_sysfs_done; mutex_lock(&pools_sysfs_lock); if (pools_sysfs_done == false) { create_sysfs_stuff(); pools_sysfs_done = true; } mutex_unlock(&pools_sysfs_lock); }
Quoted 5 lines
Quoted 1 line
That's not terribly pretty.
Or possibly use
module_initstyle magic. Where use module initialization and remove to trigger creation and deletion of the sysfs.
I'm not following how module initialization can help here. Are you suggesting that all devices get a 'pools' attribute regardless of whether any dma pools are actually created?
Shaun
Quoted 79 lines · Andrew Morton
Quoted 7 lines · On Mon, 28 Feb 2011 16:41:24 -0600 Russ Meyerriecks <[email protected]>…
From: Shaun Ruffell <[email protected]>
Eliminates a circular lock dependency reported by lockdep. When reading the "pools" file from a PCI device via sysfs, the
s_activelock is acquired before thepools_lock. When unloading the driver and destroying the pool,pools_lockis acquired before thes_activelock.Quoted 7 lines
cat/12016 is trying to acquire lock:
(pools_lock){+.+.+.}, at: [<c04ef113>]show_pools+0x43/0x140but task is already holding lock:
(s_active#82){++++.+}, at: [<c0554e1b>]sysfs_read_file+0xab/0x160which lock already depends on the new lock.
sysfs_dirent_init_lockdep()and the6992f53349("sysfs: Use one lockdep class per sysfs attribute") which added it are rather scary.The alleged bug appears to be due to taking
pools_lockoutsidedevice_create_file()(which takes magical sysfs PseudoVirtualLocks) versusshow_pools(), which takespools_lockbut is called from inside magical sysfs PseudoVirtualLocks.I don't know if this is actually a real bug or not. Probably not, as this
device_create_file()does not match the reasons for6992f53349:
"There is a sysfs idiom where writing to one sysfs file causes the addition or removal of other sysfs files". But that's a guess.Quoted 27 lines
mm/dmapool.c +6
-9@@ -174,21 +174,28 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,init_waitqueue_head (&retval->waitq);if (dev) { -int ret; +int first_pool;mutex_lock (&pools_lock);if (list_empty (&dev->dma_pools)) - ret =device_create_file (dev, &dev_attr_pools); + first_pool =1 ;else - ret =0 ; + first_pool =0 ;/* note: not currently insisting "name" be unique */ -if (!ret) -list_add (&retval->pools, &dev->dma_pools); -else { -kfree (retval); - retval =NULL ; - } +list_add (&retval->pools, &dev->dma_pools);mutex_unlock (&pools_lock); + +if (first_pool) {mm/dmapool.c struct dma_pool *dma_pool_create(const char *name, struct device *dev, · line 198
Quoted 10 lines
mm/dmapool.c +10
-0+int ret; + ret =device_create_file (dev, &dev_attr_pools); +if (ret) { +mutex_lock (&pools_lock); +list_del (&retval->pools); +mutex_unlock (&pools_lock); +kfree (retval); + retval =NULL ; + } + }Not a good fix, IMO. The problem is that if two CPUs concurrently call
dma_pool_create(), the first CPU will spend time creating the sysfs file. Meanwhile, the second CPU will whizz straight back to its caller. The caller now thinks that the sysfs file has been created and returns to userspace, which immediately tries to read the sysfs file. But the first CPU hasn't finished creating it yet. Userspace fails.One way of fixing this would be to create another singleton lock:
Quoted 12 lines
{
static DEFINE_MUTEX(pools_sysfs_lock);
static bool pools_sysfs_done;
mutex_lock(&pools_sysfs_lock);
if (pools_sysfs_done == false) {
create_sysfs_stuff();
pools_sysfs_done = true;
}
mutex_unlock(&pools_sysfs_lock);
}If I am following, I do not believe using a static pools_sysfs_done flag will not work since there is one pools file created in sysfs for each device that creates one or more dma pools. A static flag like that will fail for any aditional devices.
Assuming that lockdep has uncovered a real bug (I'm not 100% clear on all the reasons that sysfs PseudoVirtualLocks are needed as opposed to regular locks) what do you think about something like:
mm/dmapool.c: Do not create/destroy sysfs file while holding pools_lock
Eliminates a circular lock dependency reported by lockdep. When reading the "pools" file from a PCI device via sysfs, the s_active lock is acquired before the pools_lock. When unloading the driver and destroying the pool, pools_lock is acquired before the s_active lock.
cat/12016 is trying to acquire lock:
(pools_lock){+.+.+.}, at: [<c04ef113>] show_pools+0x43/0x140
but task is already holding lock:
(s_active#82){++++.+}, at: [<c0554e1b>] sysfs_read_file+0xab/0x160
which lock already depends on the new lock.
This introduces a new pools_sysfs_lock that is used to synchronize 'pools' attribute creation / destruction without requiring 'pools_lock' to be held.
--- mm/dmapool.c | 37 +++++++++++++++++++++++++++---------- 1 files changed, 27 insertions(+), 10 deletions(-)
mm/dmapool.c +27 -10
@@ -64,6 +64,7 @@ struct dma_page { /* cacheable header for 'allocation' bytes */ #define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)static DEFINE_MUTEX (pools_lock); +static DEFINE_MUTEX (pools_sysfs_lock);static ssize_t show_pools (struct device *dev,struct device_attribute *attr,char *buf)
@@ -174,21 +175,28 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,init_waitqueue_head (&retval->waitq);if (dev) { -int ret; +int first_pool; +mutex_lock (&pools_sysfs_lock);mutex_lock (&pools_lock);if (list_empty (&dev->dma_pools)) - ret =device_create_file (dev, &dev_attr_pools); + first_pool =1 ;else - ret =0 ; + first_pool =0 ;/* note: not currently insisting "name" be unique */ -if (!ret) -list_add (&retval->pools, &dev->dma_pools); -else { -kfree (retval); - retval =NULL ; - } +list_add (&retval->pools, &dev->dma_pools);mutex_unlock (&pools_lock); + +if (first_pool) { +if (device_create_file (dev, &dev_attr_pools)) { +mutex_lock (&pools_lock); +list_del (&retval->pools); +mutex_unlock (&pools_lock); +kfree (retval); + retval =NULL ; + } + } +mutex_unlock (&pools_sysfs_lock); }else INIT_LIST_HEAD (&retval->pools);
@@ -263,12 +271,21 @@ static void pool_free_page(struct dma_pool *pool, struct dma_page *page)*/ void dma_pool_destroy (struct dma_pool *pool) { +int last_pool; + +mutex_lock (&pools_sysfs_lock);mutex_lock (&pools_lock);list_del (&pool->pools);if (pool->dev &&list_empty (&pool->dev->dma_pools)) -device_remove_file (pool->dev, &dev_attr_pools); + last_pool =1 ; +else + last_pool =0 ;mutex_unlock (&pools_lock); +if (last_pool) +device_remove_file (pool->dev, &dev_attr_pools); +mutex_unlock (&pools_sysfs_lock); +while (!list_empty (&pool->page_list)) {struct dma_page *page; page = list_entry(pool->page_list.next,
Signature · 8 lines
1.7.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 112 lines · Shaun Ruffell
Quoted 79 lines · Andrew Morton
Quoted 7 lines · On Mon, 28 Feb 2011 16:41:24 -0600 Russ Meyerriecks <[email protected]>…
From: Shaun Ruffell <[email protected]>
Eliminates a circular lock dependency reported by lockdep. When reading the "pools" file from a PCI device via sysfs, the
s_activelock is acquired before thepools_lock. When unloading the driver and destroying the pool,pools_lockis acquired before thes_activelock.Quoted 7 lines
cat/12016 is trying to acquire lock:
(pools_lock){+.+.+.}, at: [<c04ef113>]show_pools+0x43/0x140but task is already holding lock:
(s_active#82){++++.+}, at: [<c0554e1b>]sysfs_read_file+0xab/0x160which lock already depends on the new lock.
sysfs_dirent_init_lockdep()and the6992f53349("sysfs: Use one lockdep class per sysfs attribute") which added it are rather scary.The alleged bug appears to be due to taking
pools_lockoutsidedevice_create_file()(which takes magical sysfs PseudoVirtualLocks) versusshow_pools(), which takespools_lockbut is called from inside magical sysfs PseudoVirtualLocks.I don't know if this is actually a real bug or not. Probably not, as this
device_create_file()does not match the reasons for6992f53349:
"There is a sysfs idiom where writing to one sysfs file causes the addition or removal of other sysfs files". But that's a guess.Quoted 27 lines
mm/dmapool.c +6
-9@@ -174,21 +174,28 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,init_waitqueue_head (&retval->waitq);if (dev) { -int ret; +int first_pool;mutex_lock (&pools_lock);if (list_empty (&dev->dma_pools)) - ret =device_create_file (dev, &dev_attr_pools); + first_pool =1 ;else - ret =0 ; + first_pool =0 ;/* note: not currently insisting "name" be unique */ -if (!ret) -list_add (&retval->pools, &dev->dma_pools); -else { -kfree (retval); - retval =NULL ; - } +list_add (&retval->pools, &dev->dma_pools);mutex_unlock (&pools_lock); + +if (first_pool) {mm/dmapool.c struct dma_pool *dma_pool_create(const char *name, struct device *dev, · line 198
Quoted 10 lines
mm/dmapool.c +10
-0+int ret; + ret =device_create_file (dev, &dev_attr_pools); +if (ret) { +mutex_lock (&pools_lock); +list_del (&retval->pools); +mutex_unlock (&pools_lock); +kfree (retval); + retval =NULL ; + } + }Not a good fix, IMO. The problem is that if two CPUs concurrently call
dma_pool_create(), the first CPU will spend time creating the sysfs file. Meanwhile, the second CPU will whizz straight back to its caller. The caller now thinks that the sysfs file has been created and returns to userspace, which immediately tries to read the sysfs file. But the first CPU hasn't finished creating it yet. Userspace fails.One way of fixing this would be to create another singleton lock:
Quoted 12 lines
{ static DEFINE_MUTEX(pools_sysfs_lock); static bool pools_sysfs_done; mutex_lock(&pools_sysfs_lock); if (pools_sysfs_done == false) { create_sysfs_stuff(); pools_sysfs_done = true; } mutex_unlock(&pools_sysfs_lock); }If I am following, I do not believe using a static
pools_sysfs_doneflag will not work since there is one pools file created in sysfs for each device that creates one or more dma pools. A static flag like that will fail for any aditional devices.Assuming that lockdep has uncovered a real bug (I'm not 100% clear on all the reasons that sysfs PseudoVirtualLocks are needed as opposed to regular locks) what do you think about something like:
mm/dmapool.c: Do not create/destroy sysfs file while holdingpools_lockEliminates a circular lock dependency reported by lockdep. When reading the "pools" file from a PCI device via sysfs, the
s_activelock is acquired before thepools_lock. When unloading the driver and destroying the pool,pools_lockis acquired before thes_activelock.cat/12016 is trying to acquire lock:
(pools_lock){+.+.+.}, at: [<c04ef113>]show_pools+0x43/0x140
Quoted 8 lines
but task is already holding lock:
(s_active#82){++++.+}, at: [<c0554e1b>]sysfs_read_file+0xab/0x160which lock already depends on the new lock.
This introduces a new
pools_sysfs_lockthat is used to synchronize 'pools' attribute creation / destruction without requiring 'pools_lock' to be held.
The deadlock scenario looks like this.
Process A: Process B:
mutex_lock(&pools_lock) s_active_down(); device_remove_pool_file(); show_pools(); s_active_down(); mutex_lock(&pools_lock);
What sysfs uses isn't strictly a lock implementation wise, but from a
deadlock perspective it is. And you very much have an AB BA deadlock
here.
If you read the sysfs file while trying to remove dma pool you will deadlock.
The patch below looks like it might work. The immediate symptom is fixed. But it is doing strange locking things and I am too tired to read through the rest of the code.
Quoted 66 lines
mm/dmapool.c | 37 +++++++++++++++++++++++++++---------- 1 files changed, 27 insertions(+), 10 deletions(-)mm/dmapool.c +22
-10@@ -64,6 +64,7 @@ struct dma_page { /* cacheable header for 'allocation' bytes */ #define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)static DEFINE_MUTEX (pools_lock); +static DEFINE_MUTEX (pools_sysfs_lock);static ssize_t show_pools (struct device *dev,struct device_attribute *attr,char *buf)@@ -174,21 +175,28 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,init_waitqueue_head (&retval->waitq);if (dev) { -int ret; +int first_pool; +mutex_lock (&pools_sysfs_lock);mutex_lock (&pools_lock);if (list_empty (&dev->dma_pools)) - ret =device_create_file (dev, &dev_attr_pools); + first_pool =1 ;else - ret =0 ; + first_pool =0 ;/* note: not currently insisting "name" be unique */ -if (!ret) -list_add (&retval->pools, &dev->dma_pools); -else { -kfree (retval); - retval =NULL ; - } +list_add (&retval->pools, &dev->dma_pools);mutex_unlock (&pools_lock); + +if (first_pool) { +if (device_create_file (dev, &dev_attr_pools)) { +mutex_lock (&pools_lock); +list_del (&retval->pools); +mutex_unlock (&pools_lock); +kfree (retval); + retval =NULL ; + } + } +mutex_unlock (&pools_sysfs_lock); }else INIT_LIST_HEAD (&retval->pools);@@ -263,12 +271,21 @@ static void pool_free_page(struct dma_pool *pool, struct dma_page *page)*/ void dma_pool_destroy (struct dma_pool *pool) { +int last_pool; + +mutex_lock (&pools_sysfs_lock);mutex_lock (&pools_lock);list_del (&pool->pools);if (pool->dev &&list_empty (&pool->dev->dma_pools)) -device_remove_file (pool->dev, &dev_attr_pools); + last_pool =1 ; +else
mm/dmapool.c static void pool_free_page(struct dma_pool *pool, struct dma_page *page) · line 291
Quoted 10 lines
mm/dmapool.c +5
-0+ last_pool =0 ;mutex_unlock (&pools_lock); +if (last_pool) +device_remove_file (pool->dev, &dev_attr_pools); +mutex_unlock (&pools_sysfs_lock); +while (!list_empty (&pool->page_list)) {struct dma_page *page; page = list_entry(pool->page_list.next,
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>