aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--kernel/dev.c17
-rw-r--r--kernel/file.c19
-rw-r--r--kernel/fuse_i.h4
-rw-r--r--lib/fuse_versionscript2
5 files changed, 33 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index fac446d..7a9fd98 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,8 @@
* Added missing symbols to versionscript (Joshua J. Berry)
+ * Do not limit number of file locks being waited upon
+
2005-07-28 Miklos Szeredi <miklos@szeredi.hu>
* kernel: invalidate attributes for read/readdir/readlink
diff --git a/kernel/dev.c b/kernel/dev.c
index 0f4de86..2c71a79 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -163,11 +163,13 @@ static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
else
fuse_request_free(req);
- /* If we are in debt decrease that first */
- if (fc->outstanding_debt)
- fc->outstanding_debt--;
- else
- up(&fc->outstanding_sem);
+ if (!req->unaccounted) {
+ /* If we are in debt decrease that first */
+ if (fc->outstanding_debt)
+ fc->outstanding_debt--;
+ else
+ up(&fc->outstanding_sem);
+ }
spin_unlock(&fuse_lock);
}
@@ -322,9 +324,10 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
req->in.h.unique = fc->reqctr;
req->in.h.len = sizeof(struct fuse_in_header) +
len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
- if (!req->preallocated) {
+ if (!req->preallocated && !req->unaccounted) {
/* If request is not preallocated (either FORGET or
- RELEASE), then still decrease outstanding_sem, so
+ RELEASE), and is not unaccounted (SETLKW),
+ then still decrease outstanding_sem, so
user can't open infinite number of files while not
processing the RELEASE requests. However for
efficiency do it without blocking, so if down()
diff --git a/kernel/file.c b/kernel/file.c
index 9cf7413..5ceea6e 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -686,18 +686,29 @@ static int fuse_setlk(struct file *file, struct file_lock *fl)
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
struct fuse_lk_in_out arg;
+ int sleep = fl->fl_flags & FL_SLEEP;
int err;
if (fc->no_lk)
return posix_lock_file_wait(file, fl);
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ if (!sleep) {
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+ } else {
+ /* SETLKW can wait indefinately so we do not use up a
+ request from the pool, but allocate an unaccounted
+ new one */
+ req = fuse_request_alloc();
+ if (!req)
+ return -ENOMEM;
+ req->unaccounted = 1;
+ }
memset(&arg, 0, sizeof(arg));
convert_file_lock(fl, &arg.lk);
- req->in.h.opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
+ req->in.h.opcode = sleep ? FUSE_SETLKW : FUSE_SETLK;
req->in.h.nodeid = get_node_id(inode);
req->inode = inode;
req->in.numargs = 1;
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index be20e74..7843a96 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -202,6 +202,9 @@ struct fuse_req {
/** The request is preallocated */
unsigned preallocated:1;
+ /** The request is not accounted via outstanding_{sem,debt} */
+ unsigned unaccounted:1;
+
/** The request was interrupted */
unsigned interrupted:1;
@@ -337,6 +340,7 @@ struct fuse_conn {
/** Is removexattr not implemented by fs? */
unsigned no_removexattr : 1;
+ /** Are file locking primitives implemented by fs? */
unsigned no_lk : 1;
#ifdef KERNEL_2_6
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 1068265..d097c77 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -12,6 +12,7 @@ FUSE_2.2 {
fuse_ll_destroy;
fuse_ll_is_lib_option;
fuse_ll_loop;
+ fuse_ll_loop_mnt;
fuse_ll_exited;
fuse_ll_read_cmd;
fuse_ll_process_cmd;
@@ -39,6 +40,7 @@ FUSE_2.2 {
fuse_reply_buf;
fuse_reply_statfs;
fuse_reply_xattr;
+ fuse_req_ctx;
fuse_set_getcontext_func;
fuse_setup;
fuse_setup_compat2;