Hi.
I just slightly modified /usr/src/linux/mm/filemap.c
in order to have file descriptor passed in
siginfo structure when using SIGEV_SIGNAL as notification method.
As I remember, someone asked for this feature some time in the past.
Maybe someone find it useful...
Sorry, I wont send another patch to the patch, to the patch , etc.:
here's my version of three modified routines from filemap.c:
Main modifiation is adding the third argument to send_signal()
which allows setting siginfo's si_fd field:
In lio_complete() I put zero as this argument (anyone has better idea?),
and in kaio_io_complete I get filedescriptor from the original
(passed by user) kaiocb->kaio_uaiocb->aio_fildes
-------------------------------------------------------------------------------
static void
send_signal(sigevent_t *sigev, struct task_struct *task, int fd)
{
if (sigev->sigev_notify == SIGEV_SIGNAL) {
struct siginfo sinfo;
memset(&sinfo, 0, sizeof(sinfo));
sinfo.si_signo = sigev->sigev_signo;
sinfo.si_code = SI_ASYNCIO;
sinfo.si_value = sigev->sigev_value;
sinfo.si_fd=fd;
send_sig_info(sigev->sigev_signo, &sinfo, task);
}
}
static int
lio_complete(liocb_t *liocb, int n, int wakeup)
{
spin_lock(&liocb->lio_lock);
liocb->lio_done += n;
if (liocb->lio_nent == liocb->lio_done) {
spin_unlock(&liocb->lio_lock);
if (wakeup) {
lock_kernel();
wake_up(&liocb->lio_wait);
unlock_kernel();
}
send_signal(&liocb->lio_sigevent, liocb->lio_task,0);
if (liocb->lio_mode == LIO_NOWAIT)
kfree(liocb);
return 1;
}
if (!wakeup)
lock_kernel();
spin_unlock(&liocb->lio_lock);
return 0;
}
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++)
page_cache_release(kaiocb->kaio_pages[i]);
if (kaiocb->kaio_pages != &kaiocb->kaio_page_inline)
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,
kaiocb->kaio_uaiocb->aio_fildes);
//kaiocb->kaio_filp->_fileno);
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); */
gc = 1;
if (gc)
kaio_remove_hash(kaiocb);
}
spin_unlock(&kaio_hash_lock);
if (liocb)
lio_complete(liocb, 1, 1);
}
if (gc) {
fput(kaiocb->kaio_filp);
kfree(kaiocb);
}
return ret;
}
--------------------------------------------
Ah, BTW: I use kernel 2.4.2, with
kaio-kern-1.3.1-2.4.2 patch
and a "patch to the patch" sent by
Christopher Smith <x@xxxxxxxx>
to this list on : Sun, 08 Apr 2001 06:32:25 -0700
I'm trying to get it work with TCP sockets and it seems
to be OK for SIGEV_SIGNAL notification method.
Would be nice if SIGEV_THREAD is implemented as well.
regards:
Piotr Golonka
CERN, European Laboratory for High Energy Physics,
ATLAS Experiment
e-mail:Piotr.Golonka@xxxxxxx
PS: This is my first hacking inside LINUX kernel, please be forbearing
for a beginner.
|