From cac547059462a58ec26159cdc408f5828cfe40e5 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 1 Aug 2005 10:44:45 +0000 Subject: [PATCH] fix --- ChangeLog | 2 ++ kernel/dev.c | 17 ++++++++++------- kernel/file.c | 19 +++++++++++++++---- kernel/fuse_i.h | 4 ++++ lib/fuse_versionscript | 2 ++ 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 * 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; -- 2.30.2