On Thu, Feb 01, 2007 at 01:12:34PM +0300, Evgeniy Polyakov (johnpol@xxxxxxxxxxx) wrote: > > Kevent based AIO (aio_sendfile()/aio_sendfile_path()). > > aio_sendfile()/aio_sendfile_path() contains of two major parts: AIO > state machine and page processing code. > The former is just a small subsystem, which allows to queue callback > for theirs invocation in process' context on behalf of pool of kernel > threads. It allows to queue caches of callbacks to the local thread > or to any other specified. Each cache of callbacks is processed until > there are callbacks in it, callbacks can requeue themselfs into the > same cache. Below patch, casted by discussion in lkml@ about micro-thread AIO. Async sending and file closing are implemented already, I added kaio_open() into state machine as example of what it can do, it was sync before. It is an example only - kevent was asked to have feature-freeze time. Btw, could you please Cc: linux-fsdevel@ on AIO patchsets too. Thanks. diff --git a/kernel/kevent/kevent_aio.c b/kernel/kevent/kevent_aio.c index 9bb5e99..803e9ff 100644 --- a/kernel/kevent/kevent_aio.c +++ b/kernel/kevent/kevent_aio.c @@ -759,16 +759,15 @@ err_out_exit: return err; } -asmlinkage long sys_aio_sendfile_path(int kevent_fd, int sock_fd, - void __user *header, size_t header_size, - char __user *filename, off_t offset, size_t count) +static int kaio_open(struct kaio_req *req, int direct) { + struct kaio_private *priv = req->priv; + char *filename = priv->sptr; char *tmp = getname(filename); int fd = PTR_ERR(tmp); int flags = O_RDONLY, err; struct nameidata nd; struct file *file; - struct kaio_req *req; if (force_o_largefile()) flags = O_LARGEFILE; @@ -795,25 +794,12 @@ asmlinkage long sys_aio_sendfile_path(int kevent_fd, int sock_fd, if (!file) goto err_out_fdput; - /* One reference will be released in sys_close(), - * second one through req->destructor() - */ - atomic_inc(&file->f_count); - - req = kaio_sendfile(kevent_fd, sock_fd, header, header_size, - file, offset, count); - if (!req) { - err = -EINVAL; - goto err_out_fput; - } - fd_install(fd, file); - return fd; + priv->sptr = file; + + return 0; -err_out_fput: - fput(file); - fput(file); err_out_fdput: put_unused_fd(fd); err_out_put_name: @@ -822,6 +808,67 @@ err_out_exit: return err; } +asmlinkage long sys_aio_sendfile_path(int kevent_fd, int sock_fd, + void __user *header, size_t header_size, + char __user *filename, off_t offset, size_t count) +{ + struct kaio_req *req; + struct socket *sock; + struct kaio_private *priv; + int err; + + sock = sockfd_lookup(sock_fd, &err); + if (!sock) + goto err_out_exit; + + priv = kmem_cache_alloc(kaio_priv_cache, GFP_KERNEL); + if (!priv) + goto err_out_sput; + + priv->sptr = filename; + priv->dptr = sock; + priv->offset = offset; + priv->count = count; + priv->processed = offset; + priv->limit = 128; + priv->header = header; + priv->header_size = header_size; + + req = kaio_add_call(NULL, &kaio_open, -1, GFP_KERNEL); + if (!req) + goto err_out_free; + + kaio_append_call(req, &kaio_read_send_pages); + + req->destructor = kaio_destructor; + req->priv = priv; + + err = kaio_add_kevent(kevent_fd, req); + + dprintk("%s: req: %p, priv: %p, call: %p [%p], offset: %Lu, processed: %Lu, count: %Lu, err: %d.\n", + __func__, req, priv, &kaio_read_send_pages, + kaio_read_send_pages, priv->offset, priv->processed, priv->count, err); + + if (err) + goto err_out_remove; + + kaio_schedule_req(req); + + return (long)req; + +err_out_remove: + /* It is safe to just free the object since it is guaranteed that it was not + * queued for processing. + */ + kmem_cache_free(kaio_req_cache, req); +err_out_free: + kmem_cache_free(kaio_priv_cache, priv); +err_out_sput: + sockfd_put(sock); +err_out_exit: + return -1; +} + static int kevent_aio_callback(struct kevent *k) { struct kaio_req *req = k->event.ptr; -- Evgeniy Polyakov - To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html