From d3dd2d5466a520f7ca866b478faecd1afd3de1f5 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 22 Jun 2004 18:46:02 +0000 Subject: [PATCH] request allocation improvements --- ChangeLog | 4 ++++ kernel/dev.c | 21 +++++++++------------ kernel/dir.c | 10 ++++++++-- kernel/file.c | 18 ++++++++++++++---- kernel/fuse_i.h | 18 +++++++++++++----- kernel/inode.c | 12 +++++++----- 6 files changed, 55 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index b6bb446..6a60661 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2004-06-22 Miklos Szeredi + + * No request allocation needed on inode and file release + 2004-06-21 Miklos Szeredi * Fix possible inode leak in userspace in case of unfinished diff --git a/kernel/dev.c b/kernel/dev.c index 84d4d99..72fdba4 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -109,6 +109,7 @@ static struct fuse_req *do_get_request(struct fuse_conn *fc) memset(req, 0, sizeof(*req)); INIT_LIST_HEAD(&req->list); init_waitqueue_head(&req->waitq); + req->preallocated = 1; return req; } @@ -139,20 +140,16 @@ struct fuse_req *fuse_get_request_nonblock(struct fuse_conn *fc) return req; } -struct fuse_req *fuse_get_request_nonint(struct fuse_conn *fc) -{ - down(&fc->unused_sem); - - return do_get_request(fc); -} - - void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) { - spin_lock(&fuse_lock); - list_add(&req->list, &fc->unused_list); - spin_unlock(&fuse_lock); - up(&fc->unused_sem); + if (!req->preallocated) + fuse_request_free(req); + else { + spin_lock(&fuse_lock); + list_add(&req->list, &fc->unused_list); + spin_unlock(&fuse_lock); + up(&fc->unused_sem); + } } /* Must be called with fuse_lock held, and unlocks it */ diff --git a/kernel/dir.c b/kernel/dir.c index 59cab49..af41ab5 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -78,8 +78,6 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) new_decode_dev(attr->rdev)); } else printk("fuse_init_inode: bad file type: %o\n", inode->i_mode); - - inode->u.generic_ip = inode; } struct inode *fuse_iget(struct super_block *sb, ino_t ino, int generation, @@ -90,6 +88,13 @@ struct inode *fuse_iget(struct super_block *sb, ino_t ino, int generation, inode = iget(sb, ino); if (inode) { if (!inode->u.generic_ip) { + struct fuse_req *req = fuse_request_alloc(); + if (!req) { + iput(inode); + inode = NULL; + goto out; + } + inode->u.generic_ip = req; inode->i_generation = generation; fuse_init_inode(inode, attr); } else if (inode->i_generation != generation) @@ -98,6 +103,7 @@ struct inode *fuse_iget(struct super_block *sb, ino_t ino, int generation, change_attributes(inode, attr); inode->i_version = version; } + out: return inode; } diff --git a/kernel/file.c b/kernel/file.c index 128c1b8..78ce854 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -16,19 +16,20 @@ #ifndef KERNEL_2_6 #define PageUptodate(page) Page_Uptodate(page) -#ifndef NO_MM #ifndef filemap_fdatawrite +#ifndef NO_MM #define filemap_fdatawrite filemap_fdatasync -#endif #else #define filemap_fdatawrite do {} while (0) #endif #endif +#endif static int fuse_open(struct inode *inode, struct file *file) { struct fuse_conn *fc = INO_FC(inode); struct fuse_req *req; + struct fuse_req *req2; struct fuse_open_in inarg; int err; @@ -48,6 +49,12 @@ static int fuse_open(struct inode *inode, struct file *file) if (!req) return -ERESTARTSYS; + req2 = fuse_request_alloc(); + if (!req2) { + fuse_put_request(fc, req); + return -ENOMEM; + } + memset(&inarg, 0, sizeof(inarg)); inarg.flags = file->f_flags & ~O_EXCL; req->in.h.opcode = FUSE_OPEN; @@ -64,6 +71,10 @@ static int fuse_open(struct inode *inode, struct file *file) invalidate_inode_pages(inode); #endif } + if (err) + fuse_request_free(req2); + else + file->private_data = req2; fuse_put_request(fc, req); return err; } @@ -72,12 +83,11 @@ static int fuse_release(struct inode *inode, struct file *file) { struct fuse_conn *fc = INO_FC(inode); struct fuse_open_in *inarg; - struct fuse_req *req; + struct fuse_req *req = file->private_data; if (file->f_mode & FMODE_WRITE) filemap_fdatawrite(inode->i_mapping); - req = fuse_get_request_nonint(fc); inarg = &req->misc.open_in; inarg->flags = file->f_flags & ~O_EXCL; req->in.h.opcode = FUSE_RELEASE; diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h index 7055d17..f83ac6a 100644 --- a/kernel/fuse_i.h +++ b/kernel/fuse_i.h @@ -113,6 +113,9 @@ struct fuse_req { /* The request has been sent to the client */ unsigned int sent:1; + /* The request is preallocated */ + unsigned int preallocated:1; + /* The request is finished */ unsigned int finished; @@ -266,18 +269,23 @@ int fuse_fs_init(void); void fuse_fs_cleanup(void); +/** + * Allocate a request + */ +struct fuse_req *fuse_request_alloc(void); + /** - * Reserve a request + * Free a request */ -struct fuse_req *fuse_get_request(struct fuse_conn *fc); +void fuse_request_free(struct fuse_req *req); /** - * Reserve a request, non-iterruptable + * Reserve a preallocated request */ -struct fuse_req *fuse_get_request_nonint(struct fuse_conn *fc); +struct fuse_req *fuse_get_request(struct fuse_conn *fc); /** - * Reserve a request, non-blocking + * Reserve a preallocated request, non-blocking */ struct fuse_req *fuse_get_request_nonblock(struct fuse_conn *fc); diff --git a/kernel/inode.c b/kernel/inode.c index 83ac407..afee16d 100644 --- a/kernel/inode.c +++ b/kernel/inode.c @@ -60,13 +60,15 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, ino_t ino, static void fuse_clear_inode(struct inode *inode) { struct fuse_conn *fc = INO_FC(inode); - struct fuse_req *req; + struct fuse_req *req = inode->u.generic_ip; - if (fc == NULL) + if (fc == NULL) { + if (req) + fuse_request_free(req); return; - - req = fuse_get_request_nonint(fc); - fuse_send_forget(fc, req, inode->i_ino, inode->i_version); + } + if (req != NULL) + fuse_send_forget(fc, req, inode->i_ino, inode->i_version); } static void fuse_put_super(struct super_block *sb) -- 2.30.2