KAIO patch maintainer,
I am experiencing difficulty using the KAIO patch to do some relatively
simple operations. When I use it on my
Linux machine (kernel 2.2.17), I run out of file handles (verified by
checking /proc/sys/fs/file-nr ) . The program I'm
running is relatively simple. The process is basically....
- call socket to get file descriptor
- connect on fd
- use aio_write to send data
- use sigwaitinfo to wait on event notification
- close fd using pointer returned by sigwaitinfo
This sequence is called many times as I am trying to mimic the process a
client uses to connect to a server. This process
soaks up my system's resources, but it shouldn't. The pool of file handles
should not constantly increase after a certain maximum
number have been allocated.
Looking at the patch code there seems to be a bug, or unhandled case that
prevents file descriptors from being released
when aio_write completes. 'kaio_io_complete' is used to signal user
applications that IO is complete and to release file descriptors.
Apparently, the file descriptors are only released when used the lio_listio
command.
This statement 'gc |= (liocb && liocb->lio_mode == LIO_WAIT)' will only set
gc == 1 if the user application
is using listio to do asynchronous reads/writes. Otherwise gc == 0 since
it was passed to kaio_io_complete
as 0. When this code executes...
if (gc) {
kaio_fput(kaiocb->kaio_filp);
kfree(kaiocb);
}
the file decsriptor won't be released nor will the aio control block be
freed since gc == 0.
Is this the intended behavior for the KAIO patch? If so, aio_write will
eventually soak up system resources and leave the system unusable.
The correction is simple, but I wanted to know if you were aware of this
issue.
+static int
+kaio_io_complete(kaiocb_t *kaiocb, int nbytes, int ret, int gc)
+{
+ aiocb_t *uaiocb = kaiocb->kaio_uaiocb;
+ liocb_t *liocb = kaiocb->kaio_liocb;
+ int i;
+
+ if (kaiocb->kaio_pages) {
+
+ for (i = 0; i < kaiocb->kaio_npages; i++)
+ __free_page(kaiocb->kaio_pages[i]);
+ kfree(kaiocb->kaio_pages);
+ }
+
+#ifdef KAIO_STATS
+ if (copy_to_user(&uaiocb->aio_times, &kaiocb->kaio_times,
+ sizeof(unsigned long) * AIO_TIMES))
+ {
+ ret = -EFAULT;
+ } else
+#endif
+ if (put_user(nbytes, &uaiocb->aio_return))
+ ret = -EFAULT;
+ /* aio_error does not go through syscall so -ret */
+ else if (put_user(-ret, &uaiocb->aio_error))
+ ret = -EFAULT;
+ else {
+ send_signal(&kaiocb->kaio_sigevent,
kaiocb->kaio_task);
+ spin_lock(&kaio_hash_lock);
+ if (kaiocb->kaio_suspend_wait) {
+ lock_kernel();
+ kaiocb->kaio_error = -ret;
+ wake_up(kaiocb->kaio_suspend_wait);
+ unlock_kernel();
+ } else {
+ kaiocb->kaio_error = -ret;
+ gc |= (liocb && liocb->lio_mode ==
LIO_WAIT);
+ if (gc)
+ kaio_remove_hash(kaiocb);
+ }
+ spin_unlock(&kaio_hash_lock);
+ if (liocb)
+ lio_complete(liocb, 1, 1);
+ }
+ if (gc) {
+ kaio_fput(kaiocb->kaio_filp);
+ kfree(kaiocb);
+ }
+ return ret;
+}
Todd Merriweather
IBM
Software Developer
SWG - AIM Testing Tools
Phone: (919)254-2863
|