Re: [PATCH] fuse: add a dev ioctl for recovery
From: Miklos Szeredi <miklos@szeredi.hu>
Date: 2021-09-07 09:34:48
On Mon, 6 Sept 2021 at 14:36, Hao Peng [off-list ref] wrote:
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?
quoted hunk ↗ jump to hunk
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.
quoted hunk ↗ jump to hunk
+ 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