diff options
author | Zach Brown <zach.brown@oracle.com> | 2005-11-07 03:59:31 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-07 10:53:38 -0500 |
commit | d55b5fdaf40846221d543937b786956e27837fda (patch) | |
tree | ecdf572d7d2b08b4f7b31d804542a920934b6d9a /include | |
parent | 0f6ed7c2641fe4cea83cd09c21928ca30c0983ec (diff) |
[PATCH] aio: remove aio_max_nr accounting race
AIO was adding a new context's max requests to the global total before
testing if that resulting total was over the global limit. This let
innocent tasks get their new limit tested along with a racing guilty task
that was crossing the limit. This serializes the _nr accounting with a
spinlock It also switches to using unsigned long for the global totals.
Individual contexts are still limited to an unsigned int's worth of
requests by the syscall interface.
The problem and fix were verified with a simple program that spun creating
and destroying a context while holding on to another long lived context.
Before the patch a task creating a tiny context could get a spurious EAGAIN
if it raced with a task creating a very large context that overran the
limit.
Signed-off-by: Zach Brown <zach.brown@oracle.com>
Cc: Benjamin LaHaise <bcrl@kvack.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/aio.h | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/include/linux/aio.h b/include/linux/aio.h index 0decf66117c1..403d71dcb7c8 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h | |||
@@ -183,6 +183,7 @@ struct kioctx { | |||
183 | struct list_head active_reqs; /* used for cancellation */ | 183 | struct list_head active_reqs; /* used for cancellation */ |
184 | struct list_head run_list; /* used for kicked reqs */ | 184 | struct list_head run_list; /* used for kicked reqs */ |
185 | 185 | ||
186 | /* sys_io_setup currently limits this to an unsigned int */ | ||
186 | unsigned max_reqs; | 187 | unsigned max_reqs; |
187 | 188 | ||
188 | struct aio_ring_info ring_info; | 189 | struct aio_ring_info ring_info; |
@@ -234,7 +235,7 @@ static inline struct kiocb *list_kiocb(struct list_head *h) | |||
234 | } | 235 | } |
235 | 236 | ||
236 | /* for sysctl: */ | 237 | /* for sysctl: */ |
237 | extern atomic_t aio_nr; | 238 | extern unsigned long aio_nr; |
238 | extern unsigned aio_max_nr; | 239 | extern unsigned long aio_max_nr; |
239 | 240 | ||
240 | #endif /* __LINUX__AIO_H */ | 241 | #endif /* __LINUX__AIO_H */ |