diff options
author | Javier Martinez Canillas <martinez.javier@gmail.com> | 2010-11-28 03:49:26 +0100 |
---|---|---|
committer | Javier Martinez Canillas <martinez.javier@gmail.com> | 2010-11-28 03:49:26 +0100 |
commit | f0c09c6e5adbf9c35c49dc02594fcfaa64a42994 (patch) | |
tree | 8cdf6c936e74b13548994dc4ef3e0fd87e2bff7f | |
parent | c66395c972f3588db110f6545ccfe85318df19e8 (diff) | |
download | ldd3-f0c09c6e5adbf9c35c49dc02594fcfaa64a42994.tar.gz |
scullc: main: Change work_struct to delayed_work and change scullc_aio_[read | write] handlers
-rw-r--r-- | scullc/main.c | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/scullc/main.c b/scullc/main.c index abd43ea..0cfe219 100644 --- a/scullc/main.c +++ b/scullc/main.c @@ -400,31 +400,40 @@ loff_t scullc_llseek (struct file *filp, loff_t off, int whence) struct async_work { struct kiocb *iocb; int result; - struct work_struct work; + struct delayed_work work; }; /* * "Complete" an asynchronous operation. */ -static void scullc_do_deferred_op(void *p) +static void scullc_do_deferred_op(struct work_struct *work) { - struct async_work *stuff = (struct async_work *) p; + struct async_work *stuff = container_of(work, struct async_work, work.work); aio_complete(stuff->iocb, stuff->result, 0); kfree(stuff); } -static int scullc_defer_op(int write, struct kiocb *iocb, char __user *buf, - size_t count, loff_t pos) +static int scullc_defer_op(int write, struct kiocb *iocb, const struct iovec *iovec, + unsigned long nr_segs, loff_t pos) { struct async_work *stuff; - int result; + size_t result = 0; + size_t len = 0; + unsigned long seg = 0; /* Copy now while we can access the buffer */ - if (write) - result = scullc_write(iocb->ki_filp, buf, count, &pos); - else - result = scullc_read(iocb->ki_filp, buf, count, &pos); + for (seg = 0; seg < nr_segs; seg++) { + if (write) + len = scullc_write(iocb->ki_filp, iovec[seg].iov_base, iovec[seg].iov_len, &pos); + else + len = scullc_read(iocb->ki_filp, iovec[seg].iov_base, iovec[seg].iov_len, &pos); + + if (result < 0) + return result; + + result += len; + } /* If this is a synchronous IOCB, we return our status now. */ if (is_sync_kiocb(iocb)) @@ -436,22 +445,22 @@ static int scullc_defer_op(int write, struct kiocb *iocb, char __user *buf, return result; /* No memory, just complete now */ stuff->iocb = iocb; stuff->result = result; - INIT_WORK(&stuff->work, scullc_do_deferred_op, stuff); + INIT_DELAYED_WORK(&stuff->work, scullc_do_deferred_op); schedule_delayed_work(&stuff->work, HZ/100); return -EIOCBQUEUED; } -static ssize_t scullc_aio_read(struct kiocb *iocb, char __user *buf, size_t count, - loff_t pos) +static ssize_t scullc_aio_read(struct kiocb *iocb, const struct iovec *iovec, + unsigned long nr_segs, loff_t pos) { - return scullc_defer_op(0, iocb, buf, count, pos); + return scullc_defer_op(0, iocb, iovec, nr_segs, pos); } -static ssize_t scullc_aio_write(struct kiocb *iocb, const char __user *buf, - size_t count, loff_t pos) +static ssize_t scullc_aio_write(struct kiocb *iocb, const struct iovec *iovec, + unsigned long nr_segs, loff_t pos) { - return scullc_defer_op(1, iocb, (char __user *) buf, count, pos); + return scullc_defer_op(1, iocb, iovec, nr_segs, pos); } |