aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2004-06-22 18:46:02 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2004-06-22 18:46:02 +0000
commitd3dd2d5466a520f7ca866b478faecd1afd3de1f5 (patch)
tree4b26642d6057813ce5d3a18b37db1022207a91b6
parent2778f6cf5d27e40337f163f476fac8f0ffec1130 (diff)
downloadlibfuse-d3dd2d5466a520f7ca866b478faecd1afd3de1f5.tar.gz
request allocation improvements
-rw-r--r--ChangeLog4
-rw-r--r--kernel/dev.c21
-rw-r--r--kernel/dir.c10
-rw-r--r--kernel/file.c18
-rw-r--r--kernel/fuse_i.h18
-rw-r--r--kernel/inode.c12
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 <mszeredi@inf.bme.hu>
+
+ * No request allocation needed on inode and file release
+
2004-06-21 Miklos Szeredi <mszeredi@inf.bme.hu>
* 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)