+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
memset(req, 0, sizeof(*req));
INIT_LIST_HEAD(&req->list);
init_waitqueue_head(&req->waitq);
+ req->preallocated = 1;
return req;
}
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 */
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,
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)
change_attributes(inode, attr);
inode->i_version = version;
}
+ out:
return inode;
}
#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;
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;
invalidate_inode_pages(inode);
#endif
}
+ if (err)
+ fuse_request_free(req2);
+ else
+ file->private_data = req2;
fuse_put_request(fc, req);
return err;
}
{
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;
/* 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;
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);
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)