Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 29777
b: refs/heads/master
c: 33649c9
h: refs/heads/master
i:
  29775: 3ea8cca
v: v3
  • Loading branch information
Miklos Szeredi authored and Linus Torvalds committed Jun 25, 2006
1 parent c67eeaf commit 59d7c67
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7142125937e1482ad3ae4366594c6586153dfc86
refs/heads/master: 33649c91a3df57c1090a657637d44b896de367e7
88 changes: 84 additions & 4 deletions trunk/fs/fuse/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ static void __fuse_put_request(struct fuse_req *req)
atomic_dec(&req->count);
}

static void fuse_req_init_context(struct fuse_req *req)
{
req->in.h.uid = current->fsuid;
req->in.h.gid = current->fsgid;
req->in.h.pid = current->pid;
}

struct fuse_req *fuse_get_req(struct fuse_conn *fc)
{
struct fuse_req *req;
Expand All @@ -100,9 +107,7 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc)
if (!req)
goto out;

req->in.h.uid = current->fsuid;
req->in.h.gid = current->fsgid;
req->in.h.pid = current->pid;
fuse_req_init_context(req);
req->waiting = 1;
return req;

Expand All @@ -111,12 +116,87 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc)
return ERR_PTR(err);
}

/*
* Return request in fuse_file->reserved_req. However that may
* currently be in use. If that is the case, wait for it to become
* available.
*/
static struct fuse_req *get_reserved_req(struct fuse_conn *fc,
struct file *file)
{
struct fuse_req *req = NULL;
struct fuse_file *ff = file->private_data;

do {
wait_event(fc->blocked_waitq, ff->reserved_req);
spin_lock(&fc->lock);
if (ff->reserved_req) {
req = ff->reserved_req;
ff->reserved_req = NULL;
get_file(file);
req->stolen_file = file;
}
spin_unlock(&fc->lock);
} while (!req);

return req;
}

/*
* Put stolen request back into fuse_file->reserved_req
*/
static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req)
{
struct file *file = req->stolen_file;
struct fuse_file *ff = file->private_data;

spin_lock(&fc->lock);
fuse_request_init(req);
BUG_ON(ff->reserved_req);
ff->reserved_req = req;
wake_up(&fc->blocked_waitq);
spin_unlock(&fc->lock);
fput(file);
}

/*
* Gets a requests for a file operation, always succeeds
*
* This is used for sending the FLUSH request, which must get to
* userspace, due to POSIX locks which may need to be unlocked.
*
* If allocation fails due to OOM, use the reserved request in
* fuse_file.
*
* This is very unlikely to deadlock accidentally, since the
* filesystem should not have it's own file open. If deadlock is
* intentional, it can still be broken by "aborting" the filesystem.
*/
struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file)
{
struct fuse_req *req;

atomic_inc(&fc->num_waiting);
wait_event(fc->blocked_waitq, !fc->blocked);
req = fuse_request_alloc();
if (!req)
req = get_reserved_req(fc, file);

fuse_req_init_context(req);
req->waiting = 1;
return req;
}

void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
{
if (atomic_dec_and_test(&req->count)) {
if (req->waiting)
atomic_dec(&fc->num_waiting);
fuse_request_free(req);

if (req->stolen_file)
put_reserved_req(fc, req);
else
fuse_request_free(req);
}
}

Expand Down
13 changes: 5 additions & 8 deletions trunk/fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ struct fuse_file *fuse_file_alloc(void)
struct fuse_file *ff;
ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL);
if (ff) {
ff->release_req = fuse_request_alloc();
if (!ff->release_req) {
ff->reserved_req = fuse_request_alloc();
if (!ff->reserved_req) {
kfree(ff);
ff = NULL;
}
Expand All @@ -59,7 +59,7 @@ struct fuse_file *fuse_file_alloc(void)

void fuse_file_free(struct fuse_file *ff)
{
fuse_request_free(ff->release_req);
fuse_request_free(ff->reserved_req);
kfree(ff);
}

Expand Down Expand Up @@ -115,7 +115,7 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir)
struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags,
int opcode)
{
struct fuse_req *req = ff->release_req;
struct fuse_req *req = ff->reserved_req;
struct fuse_release_in *inarg = &req->misc.release_in;

inarg->fh = ff->fh;
Expand Down Expand Up @@ -187,10 +187,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
if (fc->no_flush)
return 0;

req = fuse_get_req(fc);
if (IS_ERR(req))
return PTR_ERR(req);

req = fuse_get_req_nofail(fc, file);
memset(&inarg, 0, sizeof(inarg));
inarg.fh = ff->fh;
inarg.lock_owner = fuse_lock_owner_id(id);
Expand Down
12 changes: 10 additions & 2 deletions trunk/fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ struct fuse_inode {
/** FUSE specific file data */
struct fuse_file {
/** Request reserved for flush and release */
struct fuse_req *release_req;
struct fuse_req *reserved_req;

/** File handle used by userspace */
u64 fh;
Expand Down Expand Up @@ -213,6 +213,9 @@ struct fuse_req {

/** Request completion callback */
void (*end)(struct fuse_conn *, struct fuse_req *);

/** Request is stolen from fuse_file->reserved_req */
struct file *stolen_file;
};

/**
Expand Down Expand Up @@ -456,10 +459,15 @@ struct fuse_req *fuse_request_alloc(void);
void fuse_request_free(struct fuse_req *req);

/**
* Reserve a preallocated request
* Get a request, may fail with -ENOMEM
*/
struct fuse_req *fuse_get_req(struct fuse_conn *fc);

/**
* Gets a requests for a file operation, always succeeds
*/
struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file);

/**
* Decrement reference count of a request. If count goes to zero free
* the request.
Expand Down

0 comments on commit 59d7c67

Please sign in to comment.