Re: [PATCH] fuse: add a dev ioctl for recovery
From: Hao Peng <hidden>
Date: 2021-09-08 02:25:47
On Tue, Sep 7, 2021 at 5:34 PM Miklos Szeredi [off-list ref] wrote:
On Mon, 6 Sept 2021 at 14:36, Hao Peng [off-list ref] wrote:quoted
For a simple read-only file system, as long as the connection is not broken, the recovery of the user-mode read-only file system can be realized by putting the request of the processing list back into the pending list.Thanks for the patch. Do you have example userspace code for this?
Under development. When the fuse user-mode file system process is abnormal, the process does not terminate (/dev/fuse will not be closed), enter the reset procedure, and will not open /dev/fuse again during the reinitialization. Of course, this can only solve part of the abnormal problem.
quoted
Signed-off-by: Peng Hao <redacted> --- fs/fuse/dev.c | 38 +++++++++++++++++++++++++++++++++++++- include/uapi/linux/fuse.h | 1 + 2 files changed, 38 insertions(+), 1 deletion(-)diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 491c092d427b..8e1b69a5b503 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c@@ -2239,7 +2239,7 @@ static int fuse_device_clone(struct fuse_conn*fc, struct file *new) static long fuse_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int res; + int res = 0; int oldfd; struct fuse_dev *fud = NULL;@@ -2268,6 +2268,42 @@ static long fuse_dev_ioctl(struct file *file,unsigned int cmd, } } break; + + case FUSE_DEV_IOC_RECOVERY: + { + struct fuse_iqueue *fiq; + struct fuse_pqueue *fpq; + struct fuse_req *req, *next; + LIST_HEAD(recovery); + unsigned int i; + + fud = fuse_get_dev(file); + fiq = &fud->fc->iq; + fpq = &fud->pq; + + spin_lock(&fpq->lock); + list_for_each_entry_safe(req, next, &fpq->io, list) { + spin_lock(&req->waitq.lock); + clear_bit(FR_LOCKED, &req->flags); + list_move(&req->list, &recovery); + spin_unlock(&req->waitq.lock); + }I don't get it. Recovery means the previous server process is dead. If there are requests on the fpq->io queue, than that's obviously not true and having two processes messing with the same requests isn't going to do any good. So I suggest just erroring out if fpq->io is not empty.
I will modify it in the next version.
quoted
+ for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) + list_splice_tail_init(&fpq->processing[i], + &recovery); + list_for_each_entry_safe(req, next, &recovery, list) { + clear_bit(FR_SENT, &req->flags); + } + spin_unlock(&fpq->lock); + + spin_lock(&fiq->lock); + list_for_each_entry_safe(req, next, &recovery, list) { + set_bit(FR_PENDING, &req->flags); + } + list_splice(&recovery, &fiq->pending); + spin_unlock(&fiq->lock); + break; + } default: res = -ENOTTY; break;diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 36ed092227fa..fc07324efa9d 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h@@ -923,6 +923,7 @@ struct fuse_notify_retrieve_in { /* Device ioctls: */ #define FUSE_DEV_IOC_MAGIC 229 #define FUSE_DEV_IOC_CLONE _IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t) +#define FUSE_DEV_IOC_RECOVERY _IOR(FUSE_DEV_IOC_MAGIC+1, 0, uint32_t) struct fuse_lseek_in { uint64_t fh; --2.27.0