On Mon, 6 Sept 2021 at 14:36, Hao Peng <flyingpenghao@xxxxxxxxx> 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? > > Signed-off-by: Peng Hao <flyingpeng@xxxxxxxxxxx> > --- > 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. > + 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