* [PATCH] fuse: return -ECONNABORTED on /dev/fuse read after abort
@ 2017-10-31 18:55 Szymon Lukasz
2017-11-03 15:04 ` [PATCH v2] " Szymon Lukasz
0 siblings, 1 reply; 10+ messages in thread
From: Szymon Lukasz @ 2017-10-31 18:55 UTC (permalink / raw)
To: miklos; +Cc: linux-fsdevel, Szymon Lukasz
Currently the userspace has no way of knowing whether the fuse
connection ended because of umount or abort via sysfs. It makes it hard
for filesystems to free the mountpoint after abort without worrying
about removing some new mount.
The patch fixes it by returning different errors when userspace reads
from /dev/fuse (-ENODEV for umount and -ECONNABORTED for abort).
Signed-off-by: Szymon Lukasz <noh4hss@gmail.com>
---
fs/fuse/control.c | 2 +-
fs/fuse/dev.c | 13 ++++++++-----
fs/fuse/fuse_i.h | 8 +++++++-
fs/fuse/inode.c | 4 ++--
4 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index b9ea99c5b5b3..eeda05a7c882 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -35,7 +35,7 @@ static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
{
struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
if (fc) {
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, 1);
fuse_conn_put(fc);
}
return count;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 13c65dd2d37d..b51da52b92b9 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1234,9 +1234,10 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
if (err)
goto err_unlock;
- err = -ENODEV;
- if (!fiq->connected)
+ if (!fiq->connected) {
+ err = fiq->aborted ? -ECONNABORTED : -ENODEV;
goto err_unlock;
+ }
if (!list_empty(&fiq->interrupts)) {
req = list_entry(fiq->interrupts.next, struct fuse_req,
@@ -1287,7 +1288,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
spin_lock(&fpq->lock);
clear_bit(FR_LOCKED, &req->flags);
if (!fpq->connected) {
- err = -ENODEV;
+ err = fpq->aborted ? -ECONNABORTED : -ENODEV;
goto out_end;
}
if (err) {
@@ -2076,7 +2077,7 @@ static void end_polls(struct fuse_conn *fc)
* is OK, the request will in that case be removed from the list before we touch
* it.
*/
-void fuse_abort_conn(struct fuse_conn *fc)
+void fuse_abort_conn(struct fuse_conn *fc, int is_abort)
{
struct fuse_iqueue *fiq = &fc->iq;
@@ -2095,6 +2096,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
spin_lock(&fpq->lock);
fpq->connected = 0;
+ fpq->aborted = is_abort;
list_for_each_entry_safe(req, next, &fpq->io, list) {
req->out.h.error = -ECONNABORTED;
spin_lock(&req->waitq.lock);
@@ -2113,6 +2115,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
spin_lock(&fiq->waitq.lock);
fiq->connected = 0;
+ fiq->aborted = is_abort;
list_splice_init(&fiq->pending, &to_end2);
list_for_each_entry(req, &to_end2, list)
clear_bit(FR_PENDING, &req->flags);
@@ -2151,7 +2154,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
/* Are we the last open device? */
if (atomic_dec_and_test(&fc->dev_count)) {
WARN_ON(fc->iq.fasync != NULL);
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, 0);
}
fuse_dev_free(fud);
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index d5773ca67ad2..650e72be4174 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -387,6 +387,9 @@ struct fuse_iqueue {
/** Connection established */
unsigned connected;
+ /** Connection aborted via sysfs */
+ int aborted;
+
/** Readers of the connection are waiting on this */
wait_queue_head_t waitq;
@@ -414,6 +417,9 @@ struct fuse_pqueue {
/** Connection established */
unsigned connected;
+ /** Connection aborted via sysfs */
+ int aborted;
+
/** Lock protecting accessess to members of this structure */
spinlock_t lock;
@@ -851,7 +857,7 @@ void fuse_request_send_background_locked(struct fuse_conn *fc,
struct fuse_req *req);
/* Abort all requests */
-void fuse_abort_conn(struct fuse_conn *fc);
+void fuse_abort_conn(struct fuse_conn *fc, int is_abort);
/**
* Invalidate inode attributes
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 94a745acaef8..8cc9de4ec16d 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -371,7 +371,7 @@ void fuse_unlock_inode(struct inode *inode)
static void fuse_umount_begin(struct super_block *sb)
{
- fuse_abort_conn(get_fuse_conn_super(sb));
+ fuse_abort_conn(get_fuse_conn_super(sb), 0);
}
static void fuse_send_destroy(struct fuse_conn *fc)
@@ -393,7 +393,7 @@ static void fuse_put_super(struct super_block *sb)
fuse_send_destroy(fc);
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, 0);
mutex_lock(&fuse_mutex);
list_del(&fc->entry);
fuse_ctl_remove_conn(fc);
--
2.14.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2] fuse: return -ECONNABORTED on /dev/fuse read after abort
2017-10-31 18:55 [PATCH] fuse: return -ECONNABORTED on /dev/fuse read after abort Szymon Lukasz
@ 2017-11-03 15:04 ` Szymon Lukasz
2017-11-06 9:51 ` Miklos Szeredi
0 siblings, 1 reply; 10+ messages in thread
From: Szymon Lukasz @ 2017-11-03 15:04 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: linux-fsdevel, fuse-devel, Szymon Lukasz
Return -ECONNABORTED when userspace tries to read from /dev/fuse after
the fuse connection was aborted via sysfs.
The patch increases FUSE_KERNEL_MINOR_VERSION. However -ECONNABORTED is
always returned, regardless of the minor version sent by userspace in
FUSE_INIT.
Info why this patch might be useful:
https://github.com/libfuse/libfuse/issues/122
Signed-off-by: Szymon Lukasz <noh4hss@gmail.com>
---
fs/fuse/control.c | 2 +-
fs/fuse/dev.c | 13 ++++++++-----
fs/fuse/fuse_i.h | 8 +++++++-
fs/fuse/inode.c | 4 ++--
include/uapi/linux/fuse.h | 5 ++++-
5 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index b9ea99c5b5b3..eeda05a7c882 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -35,7 +35,7 @@ static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
{
struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
if (fc) {
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, 1);
fuse_conn_put(fc);
}
return count;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 13c65dd2d37d..b51da52b92b9 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1234,9 +1234,10 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
if (err)
goto err_unlock;
- err = -ENODEV;
- if (!fiq->connected)
+ if (!fiq->connected) {
+ err = fiq->aborted ? -ECONNABORTED : -ENODEV;
goto err_unlock;
+ }
if (!list_empty(&fiq->interrupts)) {
req = list_entry(fiq->interrupts.next, struct fuse_req,
@@ -1287,7 +1288,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
spin_lock(&fpq->lock);
clear_bit(FR_LOCKED, &req->flags);
if (!fpq->connected) {
- err = -ENODEV;
+ err = fpq->aborted ? -ECONNABORTED : -ENODEV;
goto out_end;
}
if (err) {
@@ -2076,7 +2077,7 @@ static void end_polls(struct fuse_conn *fc)
* is OK, the request will in that case be removed from the list before we touch
* it.
*/
-void fuse_abort_conn(struct fuse_conn *fc)
+void fuse_abort_conn(struct fuse_conn *fc, int is_abort)
{
struct fuse_iqueue *fiq = &fc->iq;
@@ -2095,6 +2096,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
spin_lock(&fpq->lock);
fpq->connected = 0;
+ fpq->aborted = is_abort;
list_for_each_entry_safe(req, next, &fpq->io, list) {
req->out.h.error = -ECONNABORTED;
spin_lock(&req->waitq.lock);
@@ -2113,6 +2115,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
spin_lock(&fiq->waitq.lock);
fiq->connected = 0;
+ fiq->aborted = is_abort;
list_splice_init(&fiq->pending, &to_end2);
list_for_each_entry(req, &to_end2, list)
clear_bit(FR_PENDING, &req->flags);
@@ -2151,7 +2154,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
/* Are we the last open device? */
if (atomic_dec_and_test(&fc->dev_count)) {
WARN_ON(fc->iq.fasync != NULL);
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, 0);
}
fuse_dev_free(fud);
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index d5773ca67ad2..650e72be4174 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -387,6 +387,9 @@ struct fuse_iqueue {
/** Connection established */
unsigned connected;
+ /** Connection aborted via sysfs */
+ int aborted;
+
/** Readers of the connection are waiting on this */
wait_queue_head_t waitq;
@@ -414,6 +417,9 @@ struct fuse_pqueue {
/** Connection established */
unsigned connected;
+ /** Connection aborted via sysfs */
+ int aborted;
+
/** Lock protecting accessess to members of this structure */
spinlock_t lock;
@@ -851,7 +857,7 @@ void fuse_request_send_background_locked(struct fuse_conn *fc,
struct fuse_req *req);
/* Abort all requests */
-void fuse_abort_conn(struct fuse_conn *fc);
+void fuse_abort_conn(struct fuse_conn *fc, int is_abort);
/**
* Invalidate inode attributes
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 94a745acaef8..8cc9de4ec16d 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -371,7 +371,7 @@ void fuse_unlock_inode(struct inode *inode)
static void fuse_umount_begin(struct super_block *sb)
{
- fuse_abort_conn(get_fuse_conn_super(sb));
+ fuse_abort_conn(get_fuse_conn_super(sb), 0);
}
static void fuse_send_destroy(struct fuse_conn *fc)
@@ -393,7 +393,7 @@ static void fuse_put_super(struct super_block *sb)
fuse_send_destroy(fc);
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, 0);
mutex_lock(&fuse_mutex);
list_del(&fc->entry);
fuse_ctl_remove_conn(fc);
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index 42fa977e3b14..4025a5599b2b 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -112,6 +112,9 @@
* 7.26
* - add FUSE_HANDLE_KILLPRIV
* - add FUSE_POSIX_ACL
+ *
+ * 7.27
+ * - reading from /dev/fuse after sysfs abort returns -ECONNABORTED
*/
#ifndef _LINUX_FUSE_H
@@ -147,7 +150,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 26
+#define FUSE_KERNEL_MINOR_VERSION 27
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
--
2.15.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2] fuse: return -ECONNABORTED on /dev/fuse read after abort
2017-11-03 15:04 ` [PATCH v2] " Szymon Lukasz
@ 2017-11-06 9:51 ` Miklos Szeredi
2017-11-07 0:16 ` [PATCH v3] " Szymon Lukasz
0 siblings, 1 reply; 10+ messages in thread
From: Miklos Szeredi @ 2017-11-06 9:51 UTC (permalink / raw)
To: Szymon Lukasz; +Cc: linux-fsdevel, fuse-devel
On Fri, Nov 3, 2017 at 4:04 PM, Szymon Lukasz <noh4hss@gmail.com> wrote:
> Return -ECONNABORTED when userspace tries to read from /dev/fuse after
> the fuse connection was aborted via sysfs.
> The patch increases FUSE_KERNEL_MINOR_VERSION. However -ECONNABORTED is
> always returned, regardless of the minor version sent by userspace in
> FUSE_INIT.
I worry about that.
I'd rather have this enabled with a capability flag negotiated in INIT.
>
> Info why this patch might be useful:
> https://github.com/libfuse/libfuse/issues/122
>
> Signed-off-by: Szymon Lukasz <noh4hss@gmail.com>
> ---
> fs/fuse/control.c | 2 +-
> fs/fuse/dev.c | 13 ++++++++-----
> fs/fuse/fuse_i.h | 8 +++++++-
> fs/fuse/inode.c | 4 ++--
> include/uapi/linux/fuse.h | 5 ++++-
> 5 files changed, 22 insertions(+), 10 deletions(-)
>
> diff --git a/fs/fuse/control.c b/fs/fuse/control.c
> index b9ea99c5b5b3..eeda05a7c882 100644
> --- a/fs/fuse/control.c
> +++ b/fs/fuse/control.c
> @@ -35,7 +35,7 @@ static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
> {
> struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
> if (fc) {
> - fuse_abort_conn(fc);
> + fuse_abort_conn(fc, 1);
> fuse_conn_put(fc);
> }
> return count;
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index 13c65dd2d37d..b51da52b92b9 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -1234,9 +1234,10 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
> if (err)
> goto err_unlock;
>
> - err = -ENODEV;
> - if (!fiq->connected)
> + if (!fiq->connected) {
> + err = fiq->aborted ? -ECONNABORTED : -ENODEV;
> goto err_unlock;
> + }
>
> if (!list_empty(&fiq->interrupts)) {
> req = list_entry(fiq->interrupts.next, struct fuse_req,
> @@ -1287,7 +1288,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
> spin_lock(&fpq->lock);
> clear_bit(FR_LOCKED, &req->flags);
> if (!fpq->connected) {
> - err = -ENODEV;
> + err = fpq->aborted ? -ECONNABORTED : -ENODEV;
> goto out_end;
> }
> if (err) {
> @@ -2076,7 +2077,7 @@ static void end_polls(struct fuse_conn *fc)
> * is OK, the request will in that case be removed from the list before we touch
> * it.
> */
> -void fuse_abort_conn(struct fuse_conn *fc)
> +void fuse_abort_conn(struct fuse_conn *fc, int is_abort)
> {
> struct fuse_iqueue *fiq = &fc->iq;
>
> @@ -2095,6 +2096,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
>
> spin_lock(&fpq->lock);
> fpq->connected = 0;
> + fpq->aborted = is_abort;
> list_for_each_entry_safe(req, next, &fpq->io, list) {
> req->out.h.error = -ECONNABORTED;
> spin_lock(&req->waitq.lock);
> @@ -2113,6 +2115,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
>
> spin_lock(&fiq->waitq.lock);
> fiq->connected = 0;
> + fiq->aborted = is_abort;
> list_splice_init(&fiq->pending, &to_end2);
> list_for_each_entry(req, &to_end2, list)
> clear_bit(FR_PENDING, &req->flags);
> @@ -2151,7 +2154,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
> /* Are we the last open device? */
> if (atomic_dec_and_test(&fc->dev_count)) {
> WARN_ON(fc->iq.fasync != NULL);
> - fuse_abort_conn(fc);
> + fuse_abort_conn(fc, 0);
> }
> fuse_dev_free(fud);
> }
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index d5773ca67ad2..650e72be4174 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -387,6 +387,9 @@ struct fuse_iqueue {
> /** Connection established */
> unsigned connected;
>
> + /** Connection aborted via sysfs */
> + int aborted;
> +
Does it need to be a per-queue granularity? Isn't a single bool in
fuse_conn sufficient?
Thanks,
Miklos
> /** Readers of the connection are waiting on this */
> wait_queue_head_t waitq;
>
> @@ -414,6 +417,9 @@ struct fuse_pqueue {
> /** Connection established */
> unsigned connected;
>
> + /** Connection aborted via sysfs */
> + int aborted;
> +
> /** Lock protecting accessess to members of this structure */
> spinlock_t lock;
>
> @@ -851,7 +857,7 @@ void fuse_request_send_background_locked(struct fuse_conn *fc,
> struct fuse_req *req);
>
> /* Abort all requests */
> -void fuse_abort_conn(struct fuse_conn *fc);
> +void fuse_abort_conn(struct fuse_conn *fc, int is_abort);
>
> /**
> * Invalidate inode attributes
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index 94a745acaef8..8cc9de4ec16d 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -371,7 +371,7 @@ void fuse_unlock_inode(struct inode *inode)
>
> static void fuse_umount_begin(struct super_block *sb)
> {
> - fuse_abort_conn(get_fuse_conn_super(sb));
> + fuse_abort_conn(get_fuse_conn_super(sb), 0);
> }
>
> static void fuse_send_destroy(struct fuse_conn *fc)
> @@ -393,7 +393,7 @@ static void fuse_put_super(struct super_block *sb)
>
> fuse_send_destroy(fc);
>
> - fuse_abort_conn(fc);
> + fuse_abort_conn(fc, 0);
> mutex_lock(&fuse_mutex);
> list_del(&fc->entry);
> fuse_ctl_remove_conn(fc);
> diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
> index 42fa977e3b14..4025a5599b2b 100644
> --- a/include/uapi/linux/fuse.h
> +++ b/include/uapi/linux/fuse.h
> @@ -112,6 +112,9 @@
> * 7.26
> * - add FUSE_HANDLE_KILLPRIV
> * - add FUSE_POSIX_ACL
> + *
> + * 7.27
> + * - reading from /dev/fuse after sysfs abort returns -ECONNABORTED
> */
>
> #ifndef _LINUX_FUSE_H
> @@ -147,7 +150,7 @@
> #define FUSE_KERNEL_VERSION 7
>
> /** Minor version number of this interface */
> -#define FUSE_KERNEL_MINOR_VERSION 26
> +#define FUSE_KERNEL_MINOR_VERSION 27
>
> /** The node ID of the root inode */
> #define FUSE_ROOT_ID 1
> --
> 2.15.0
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3] fuse: return -ECONNABORTED on /dev/fuse read after abort
2017-11-06 9:51 ` Miklos Szeredi
@ 2017-11-07 0:16 ` Szymon Lukasz
2017-11-09 18:29 ` kbuild test robot
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Szymon Lukasz @ 2017-11-07 0:16 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: linux-fsdevel, fuse-devel, Szymon Lukasz
Adds a new capability flag FUSE_ABORT_ERROR. If set and the connection
is gone because of sysfs abort, reading from the device will return
-ECONNABORTED.
Signed-off-by: Szymon Lukasz <noh4hss@gmail.com>
---
fs/fuse/control.c | 2 +-
fs/fuse/dev.c | 12 +++++++-----
fs/fuse/fuse_i.h | 8 +++++++-
fs/fuse/inode.c | 9 ++++++---
include/uapi/linux/fuse.h | 7 ++++++-
5 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index b9ea99c5b5b3..78fb7a07c5ca 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -35,7 +35,7 @@ static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
{
struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
if (fc) {
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, true);
fuse_conn_put(fc);
}
return count;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 13c65dd2d37d..2e1beda0b82b 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1234,9 +1234,10 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
if (err)
goto err_unlock;
- err = -ENODEV;
- if (!fiq->connected)
+ if (!fiq->connected) {
+ err = (fc->aborted && fc->abort_err) ? -ECONNABORTED : -ENODEV;
goto err_unlock;
+ }
if (!list_empty(&fiq->interrupts)) {
req = list_entry(fiq->interrupts.next, struct fuse_req,
@@ -1287,7 +1288,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
spin_lock(&fpq->lock);
clear_bit(FR_LOCKED, &req->flags);
if (!fpq->connected) {
- err = -ENODEV;
+ err = (fc->aborted && fc->abort_err) ? -ECONNABORTED : -ENODEV;
goto out_end;
}
if (err) {
@@ -2076,7 +2077,7 @@ static void end_polls(struct fuse_conn *fc)
* is OK, the request will in that case be removed from the list before we touch
* it.
*/
-void fuse_abort_conn(struct fuse_conn *fc)
+void fuse_abort_conn(struct fuse_conn *fc, bool is_abort)
{
struct fuse_iqueue *fiq = &fc->iq;
@@ -2089,6 +2090,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
fc->connected = 0;
fc->blocked = 0;
+ fc->aborted = is_abort;
fuse_set_initialized(fc);
list_for_each_entry(fud, &fc->devices, entry) {
struct fuse_pqueue *fpq = &fud->pq;
@@ -2151,7 +2153,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
/* Are we the last open device? */
if (atomic_dec_and_test(&fc->dev_count)) {
WARN_ON(fc->iq.fasync != NULL);
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, false);
}
fuse_dev_free(fud);
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index d5773ca67ad2..2f8a261d8669 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -515,6 +515,9 @@ struct fuse_conn {
abort and device release */
unsigned connected;
+ /** Connection aborted via sysfs */
+ bool aborted;
+
/** Connection failed (version mismatch). Cannot race with
setting other bitfields since it is only set once in INIT
reply, before any other request, and never cleared */
@@ -526,6 +529,9 @@ struct fuse_conn {
/** Do readpages asynchronously? Only set in INIT */
unsigned async_read:1;
+ /** Return an unique read error after abort. Only set in INIT */
+ unsigned abort_err:1;
+
/** Do not send separate SETATTR request before open(O_TRUNC) */
unsigned atomic_o_trunc:1;
@@ -851,7 +857,7 @@ void fuse_request_send_background_locked(struct fuse_conn *fc,
struct fuse_req *req);
/* Abort all requests */
-void fuse_abort_conn(struct fuse_conn *fc);
+void fuse_abort_conn(struct fuse_conn *fc, bool is_abort);
/**
* Invalidate inode attributes
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 94a745acaef8..46a17de24e14 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -371,7 +371,7 @@ void fuse_unlock_inode(struct inode *inode)
static void fuse_umount_begin(struct super_block *sb)
{
- fuse_abort_conn(get_fuse_conn_super(sb));
+ fuse_abort_conn(get_fuse_conn_super(sb), false);
}
static void fuse_send_destroy(struct fuse_conn *fc)
@@ -393,7 +393,7 @@ static void fuse_put_super(struct super_block *sb)
fuse_send_destroy(fc);
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, false);
mutex_lock(&fuse_mutex);
list_del(&fc->entry);
fuse_ctl_remove_conn(fc);
@@ -918,6 +918,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
fc->posix_acl = 1;
fc->sb->s_xattr = fuse_acl_xattr_handlers;
}
+ if (arg->flags & FUSE_ABORT_ERROR)
+ fc->abort_err = 1;
} else {
ra_pages = fc->max_read / PAGE_SIZE;
fc->no_lock = 1;
@@ -948,7 +950,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
FUSE_FLOCK_LOCKS | FUSE_HAS_IOCTL_DIR | FUSE_AUTO_INVAL_DATA |
FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO |
FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT |
- FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL;
+ FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL |
+ FUSE_ABORT_ERROR;
req->in.h.opcode = FUSE_INIT;
req->in.numargs = 1;
req->in.args[0].size = sizeof(*arg);
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index 42fa977e3b14..f9b11c43c8f6 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -112,6 +112,9 @@
* 7.26
* - add FUSE_HANDLE_KILLPRIV
* - add FUSE_POSIX_ACL
+ *
+ * 7.27
+ * - add FUSE_ABORT_ERROR
*/
#ifndef _LINUX_FUSE_H
@@ -147,7 +150,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 26
+#define FUSE_KERNEL_MINOR_VERSION 27
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@@ -244,6 +247,7 @@ struct fuse_file_lock {
* FUSE_PARALLEL_DIROPS: allow parallel lookups and readdir
* FUSE_HANDLE_KILLPRIV: fs handles killing suid/sgid/cap on write/chown/trunc
* FUSE_POSIX_ACL: filesystem supports posix acls
+ * FUSE_ABORT_ERROR: reading the device after abort returns ECONNABORTED
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
@@ -266,6 +270,7 @@ struct fuse_file_lock {
#define FUSE_PARALLEL_DIROPS (1 << 18)
#define FUSE_HANDLE_KILLPRIV (1 << 19)
#define FUSE_POSIX_ACL (1 << 20)
+#define FUSE_ABORT_ERROR (1 << 21)
/**
* CUSE INIT request/reply flags
--
2.15.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3] fuse: return -ECONNABORTED on /dev/fuse read after abort
2017-11-07 0:16 ` [PATCH v3] " Szymon Lukasz
@ 2017-11-09 18:29 ` kbuild test robot
2017-11-09 19:44 ` kbuild test robot
2017-11-09 20:23 ` [PATCH v4] " Szymon Lukasz
2 siblings, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2017-11-09 18:29 UTC (permalink / raw)
To: Szymon Lukasz
Cc: kbuild-all, Miklos Szeredi, linux-fsdevel, fuse-devel, Szymon Lukasz
[-- Attachment #1: Type: text/plain, Size: 9439 bytes --]
Hi Szymon,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on fuse/for-next]
[also build test ERROR on v4.14-rc8 next-20171109]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Szymon-Lukasz/fuse-return-ECONNABORTED-on-dev-fuse-read-after-abort/20171110-013308
base: https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git for-next
config: blackfin-allyesconfig (attached as .config)
compiler: bfin-uclinux-gcc (GCC) 6.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=blackfin
All errors (new ones prefixed by >>):
fs//fuse/cuse.c: In function 'cuse_process_init_reply':
>> fs//fuse/cuse.c:409:2: error: too few arguments to function 'fuse_abort_conn'
fuse_abort_conn(fc);
^~~~~~~~~~~~~~~
In file included from fs//fuse/cuse.c:52:0:
fs//fuse/fuse_i.h:860:6: note: declared here
void fuse_abort_conn(struct fuse_conn *fc, bool is_abort);
^~~~~~~~~~~~~~~
fs//fuse/cuse.c: In function 'cuse_class_abort_store':
fs//fuse/cuse.c:584:2: error: too few arguments to function 'fuse_abort_conn'
fuse_abort_conn(&cc->fc);
^~~~~~~~~~~~~~~
In file included from fs//fuse/cuse.c:52:0:
fs//fuse/fuse_i.h:860:6: note: declared here
void fuse_abort_conn(struct fuse_conn *fc, bool is_abort);
^~~~~~~~~~~~~~~
vim +/fuse_abort_conn +409 fs//fuse/cuse.c
151060ac1 Tejun Heo 2009-04-14 299
151060ac1 Tejun Heo 2009-04-14 300 /**
151060ac1 Tejun Heo 2009-04-14 301 * cuse_process_init_reply - finish initializing CUSE channel
151060ac1 Tejun Heo 2009-04-14 302 *
151060ac1 Tejun Heo 2009-04-14 303 * This function creates the character device and sets up all the
151060ac1 Tejun Heo 2009-04-14 304 * required data structures for it. Please read the comment at the
151060ac1 Tejun Heo 2009-04-14 305 * top of this file for high level overview.
151060ac1 Tejun Heo 2009-04-14 306 */
151060ac1 Tejun Heo 2009-04-14 307 static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
151060ac1 Tejun Heo 2009-04-14 308 {
30783587b David Herrmann 2012-11-17 309 struct cuse_conn *cc = fc_to_cc(fc), *pos;
07d5f69b4 Miklos Szeredi 2011-03-21 310 struct cuse_init_out *arg = req->out.args[0].value;
151060ac1 Tejun Heo 2009-04-14 311 struct page *page = req->pages[0];
151060ac1 Tejun Heo 2009-04-14 312 struct cuse_devinfo devinfo = { };
151060ac1 Tejun Heo 2009-04-14 313 struct device *dev;
151060ac1 Tejun Heo 2009-04-14 314 struct cdev *cdev;
151060ac1 Tejun Heo 2009-04-14 315 dev_t devt;
30783587b David Herrmann 2012-11-17 316 int rc, i;
151060ac1 Tejun Heo 2009-04-14 317
151060ac1 Tejun Heo 2009-04-14 318 if (req->out.h.error ||
151060ac1 Tejun Heo 2009-04-14 319 arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) {
151060ac1 Tejun Heo 2009-04-14 320 goto err;
151060ac1 Tejun Heo 2009-04-14 321 }
151060ac1 Tejun Heo 2009-04-14 322
151060ac1 Tejun Heo 2009-04-14 323 fc->minor = arg->minor;
151060ac1 Tejun Heo 2009-04-14 324 fc->max_read = max_t(unsigned, arg->max_read, 4096);
151060ac1 Tejun Heo 2009-04-14 325 fc->max_write = max_t(unsigned, arg->max_write, 4096);
151060ac1 Tejun Heo 2009-04-14 326
151060ac1 Tejun Heo 2009-04-14 327 /* parse init reply */
151060ac1 Tejun Heo 2009-04-14 328 cc->unrestricted_ioctl = arg->flags & CUSE_UNRESTRICTED_IOCTL;
151060ac1 Tejun Heo 2009-04-14 329
151060ac1 Tejun Heo 2009-04-14 330 rc = cuse_parse_devinfo(page_address(page), req->out.args[1].size,
151060ac1 Tejun Heo 2009-04-14 331 &devinfo);
151060ac1 Tejun Heo 2009-04-14 332 if (rc)
151060ac1 Tejun Heo 2009-04-14 333 goto err;
151060ac1 Tejun Heo 2009-04-14 334
151060ac1 Tejun Heo 2009-04-14 335 /* determine and reserve devt */
151060ac1 Tejun Heo 2009-04-14 336 devt = MKDEV(arg->dev_major, arg->dev_minor);
151060ac1 Tejun Heo 2009-04-14 337 if (!MAJOR(devt))
151060ac1 Tejun Heo 2009-04-14 338 rc = alloc_chrdev_region(&devt, MINOR(devt), 1, devinfo.name);
151060ac1 Tejun Heo 2009-04-14 339 else
151060ac1 Tejun Heo 2009-04-14 340 rc = register_chrdev_region(devt, 1, devinfo.name);
151060ac1 Tejun Heo 2009-04-14 341 if (rc) {
151060ac1 Tejun Heo 2009-04-14 342 printk(KERN_ERR "CUSE: failed to register chrdev region\n");
151060ac1 Tejun Heo 2009-04-14 343 goto err;
151060ac1 Tejun Heo 2009-04-14 344 }
151060ac1 Tejun Heo 2009-04-14 345
151060ac1 Tejun Heo 2009-04-14 346 /* devt determined, create device */
151060ac1 Tejun Heo 2009-04-14 347 rc = -ENOMEM;
151060ac1 Tejun Heo 2009-04-14 348 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
151060ac1 Tejun Heo 2009-04-14 349 if (!dev)
151060ac1 Tejun Heo 2009-04-14 350 goto err_region;
151060ac1 Tejun Heo 2009-04-14 351
151060ac1 Tejun Heo 2009-04-14 352 device_initialize(dev);
151060ac1 Tejun Heo 2009-04-14 353 dev_set_uevent_suppress(dev, 1);
151060ac1 Tejun Heo 2009-04-14 354 dev->class = cuse_class;
151060ac1 Tejun Heo 2009-04-14 355 dev->devt = devt;
151060ac1 Tejun Heo 2009-04-14 356 dev->release = cuse_gendev_release;
151060ac1 Tejun Heo 2009-04-14 357 dev_set_drvdata(dev, cc);
151060ac1 Tejun Heo 2009-04-14 358 dev_set_name(dev, "%s", devinfo.name);
151060ac1 Tejun Heo 2009-04-14 359
30783587b David Herrmann 2012-11-17 360 mutex_lock(&cuse_lock);
30783587b David Herrmann 2012-11-17 361
30783587b David Herrmann 2012-11-17 362 /* make sure the device-name is unique */
30783587b David Herrmann 2012-11-17 363 for (i = 0; i < CUSE_CONNTBL_LEN; ++i) {
30783587b David Herrmann 2012-11-17 364 list_for_each_entry(pos, &cuse_conntbl[i], list)
30783587b David Herrmann 2012-11-17 365 if (!strcmp(dev_name(pos->dev), dev_name(dev)))
30783587b David Herrmann 2012-11-17 366 goto err_unlock;
30783587b David Herrmann 2012-11-17 367 }
30783587b David Herrmann 2012-11-17 368
151060ac1 Tejun Heo 2009-04-14 369 rc = device_add(dev);
151060ac1 Tejun Heo 2009-04-14 370 if (rc)
30783587b David Herrmann 2012-11-17 371 goto err_unlock;
151060ac1 Tejun Heo 2009-04-14 372
151060ac1 Tejun Heo 2009-04-14 373 /* register cdev */
151060ac1 Tejun Heo 2009-04-14 374 rc = -ENOMEM;
151060ac1 Tejun Heo 2009-04-14 375 cdev = cdev_alloc();
151060ac1 Tejun Heo 2009-04-14 376 if (!cdev)
30783587b David Herrmann 2012-11-17 377 goto err_unlock;
151060ac1 Tejun Heo 2009-04-14 378
151060ac1 Tejun Heo 2009-04-14 379 cdev->owner = THIS_MODULE;
151060ac1 Tejun Heo 2009-04-14 380 cdev->ops = &cuse_frontend_fops;
151060ac1 Tejun Heo 2009-04-14 381
151060ac1 Tejun Heo 2009-04-14 382 rc = cdev_add(cdev, devt, 1);
151060ac1 Tejun Heo 2009-04-14 383 if (rc)
151060ac1 Tejun Heo 2009-04-14 384 goto err_cdev;
151060ac1 Tejun Heo 2009-04-14 385
151060ac1 Tejun Heo 2009-04-14 386 cc->dev = dev;
151060ac1 Tejun Heo 2009-04-14 387 cc->cdev = cdev;
151060ac1 Tejun Heo 2009-04-14 388
151060ac1 Tejun Heo 2009-04-14 389 /* make the device available */
151060ac1 Tejun Heo 2009-04-14 390 list_add(&cc->list, cuse_conntbl_head(devt));
8ce03fd76 David Herrmann 2012-11-17 391 mutex_unlock(&cuse_lock);
151060ac1 Tejun Heo 2009-04-14 392
151060ac1 Tejun Heo 2009-04-14 393 /* announce device availability */
151060ac1 Tejun Heo 2009-04-14 394 dev_set_uevent_suppress(dev, 0);
151060ac1 Tejun Heo 2009-04-14 395 kobject_uevent(&dev->kobj, KOBJ_ADD);
151060ac1 Tejun Heo 2009-04-14 396 out:
07d5f69b4 Miklos Szeredi 2011-03-21 397 kfree(arg);
151060ac1 Tejun Heo 2009-04-14 398 __free_page(page);
151060ac1 Tejun Heo 2009-04-14 399 return;
151060ac1 Tejun Heo 2009-04-14 400
151060ac1 Tejun Heo 2009-04-14 401 err_cdev:
151060ac1 Tejun Heo 2009-04-14 402 cdev_del(cdev);
30783587b David Herrmann 2012-11-17 403 err_unlock:
30783587b David Herrmann 2012-11-17 404 mutex_unlock(&cuse_lock);
151060ac1 Tejun Heo 2009-04-14 405 put_device(dev);
151060ac1 Tejun Heo 2009-04-14 406 err_region:
151060ac1 Tejun Heo 2009-04-14 407 unregister_chrdev_region(devt, 1);
151060ac1 Tejun Heo 2009-04-14 408 err:
580640ba5 Miklos Szeredi 2014-12-12 @409 fuse_abort_conn(fc);
151060ac1 Tejun Heo 2009-04-14 410 goto out;
151060ac1 Tejun Heo 2009-04-14 411 }
151060ac1 Tejun Heo 2009-04-14 412
:::::: The code at line 409 was first introduced by commit
:::::: 580640ba5d331eb5631a5de46941c98f5ed90886 fuse: flush requests on umount
:::::: TO: Miklos Szeredi <mszeredi@suse.cz>
:::::: CC: Miklos Szeredi <mszeredi@suse.cz>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 46036 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3] fuse: return -ECONNABORTED on /dev/fuse read after abort
2017-11-07 0:16 ` [PATCH v3] " Szymon Lukasz
2017-11-09 18:29 ` kbuild test robot
@ 2017-11-09 19:44 ` kbuild test robot
2017-11-09 20:23 ` [PATCH v4] " Szymon Lukasz
2 siblings, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2017-11-09 19:44 UTC (permalink / raw)
To: Szymon Lukasz
Cc: kbuild-all, Miklos Szeredi, linux-fsdevel, fuse-devel, Szymon Lukasz
Hi Szymon,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on fuse/for-next]
[also build test WARNING on v4.14-rc8 next-20171109]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Szymon-Lukasz/fuse-return-ECONNABORTED-on-dev-fuse-read-after-abort/20171110-013308
base: https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git for-next
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
vim +409 fs/fuse/cuse.c
151060ac1 Tejun Heo 2009-04-14 299
151060ac1 Tejun Heo 2009-04-14 300 /**
151060ac1 Tejun Heo 2009-04-14 301 * cuse_process_init_reply - finish initializing CUSE channel
151060ac1 Tejun Heo 2009-04-14 302 *
151060ac1 Tejun Heo 2009-04-14 303 * This function creates the character device and sets up all the
151060ac1 Tejun Heo 2009-04-14 304 * required data structures for it. Please read the comment at the
151060ac1 Tejun Heo 2009-04-14 305 * top of this file for high level overview.
151060ac1 Tejun Heo 2009-04-14 306 */
151060ac1 Tejun Heo 2009-04-14 307 static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
151060ac1 Tejun Heo 2009-04-14 308 {
30783587b David Herrmann 2012-11-17 309 struct cuse_conn *cc = fc_to_cc(fc), *pos;
07d5f69b4 Miklos Szeredi 2011-03-21 310 struct cuse_init_out *arg = req->out.args[0].value;
151060ac1 Tejun Heo 2009-04-14 311 struct page *page = req->pages[0];
151060ac1 Tejun Heo 2009-04-14 312 struct cuse_devinfo devinfo = { };
151060ac1 Tejun Heo 2009-04-14 313 struct device *dev;
151060ac1 Tejun Heo 2009-04-14 314 struct cdev *cdev;
151060ac1 Tejun Heo 2009-04-14 315 dev_t devt;
30783587b David Herrmann 2012-11-17 316 int rc, i;
151060ac1 Tejun Heo 2009-04-14 317
151060ac1 Tejun Heo 2009-04-14 318 if (req->out.h.error ||
151060ac1 Tejun Heo 2009-04-14 319 arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) {
151060ac1 Tejun Heo 2009-04-14 320 goto err;
151060ac1 Tejun Heo 2009-04-14 321 }
151060ac1 Tejun Heo 2009-04-14 322
151060ac1 Tejun Heo 2009-04-14 323 fc->minor = arg->minor;
151060ac1 Tejun Heo 2009-04-14 324 fc->max_read = max_t(unsigned, arg->max_read, 4096);
151060ac1 Tejun Heo 2009-04-14 325 fc->max_write = max_t(unsigned, arg->max_write, 4096);
151060ac1 Tejun Heo 2009-04-14 326
151060ac1 Tejun Heo 2009-04-14 327 /* parse init reply */
151060ac1 Tejun Heo 2009-04-14 328 cc->unrestricted_ioctl = arg->flags & CUSE_UNRESTRICTED_IOCTL;
151060ac1 Tejun Heo 2009-04-14 329
151060ac1 Tejun Heo 2009-04-14 330 rc = cuse_parse_devinfo(page_address(page), req->out.args[1].size,
151060ac1 Tejun Heo 2009-04-14 331 &devinfo);
151060ac1 Tejun Heo 2009-04-14 332 if (rc)
151060ac1 Tejun Heo 2009-04-14 333 goto err;
151060ac1 Tejun Heo 2009-04-14 334
151060ac1 Tejun Heo 2009-04-14 335 /* determine and reserve devt */
151060ac1 Tejun Heo 2009-04-14 336 devt = MKDEV(arg->dev_major, arg->dev_minor);
151060ac1 Tejun Heo 2009-04-14 337 if (!MAJOR(devt))
151060ac1 Tejun Heo 2009-04-14 338 rc = alloc_chrdev_region(&devt, MINOR(devt), 1, devinfo.name);
151060ac1 Tejun Heo 2009-04-14 339 else
151060ac1 Tejun Heo 2009-04-14 340 rc = register_chrdev_region(devt, 1, devinfo.name);
151060ac1 Tejun Heo 2009-04-14 341 if (rc) {
151060ac1 Tejun Heo 2009-04-14 342 printk(KERN_ERR "CUSE: failed to register chrdev region\n");
151060ac1 Tejun Heo 2009-04-14 343 goto err;
151060ac1 Tejun Heo 2009-04-14 344 }
151060ac1 Tejun Heo 2009-04-14 345
151060ac1 Tejun Heo 2009-04-14 346 /* devt determined, create device */
151060ac1 Tejun Heo 2009-04-14 347 rc = -ENOMEM;
151060ac1 Tejun Heo 2009-04-14 348 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
151060ac1 Tejun Heo 2009-04-14 349 if (!dev)
151060ac1 Tejun Heo 2009-04-14 350 goto err_region;
151060ac1 Tejun Heo 2009-04-14 351
151060ac1 Tejun Heo 2009-04-14 352 device_initialize(dev);
151060ac1 Tejun Heo 2009-04-14 353 dev_set_uevent_suppress(dev, 1);
151060ac1 Tejun Heo 2009-04-14 354 dev->class = cuse_class;
151060ac1 Tejun Heo 2009-04-14 355 dev->devt = devt;
151060ac1 Tejun Heo 2009-04-14 356 dev->release = cuse_gendev_release;
151060ac1 Tejun Heo 2009-04-14 357 dev_set_drvdata(dev, cc);
151060ac1 Tejun Heo 2009-04-14 358 dev_set_name(dev, "%s", devinfo.name);
151060ac1 Tejun Heo 2009-04-14 359
30783587b David Herrmann 2012-11-17 360 mutex_lock(&cuse_lock);
30783587b David Herrmann 2012-11-17 361
30783587b David Herrmann 2012-11-17 362 /* make sure the device-name is unique */
30783587b David Herrmann 2012-11-17 363 for (i = 0; i < CUSE_CONNTBL_LEN; ++i) {
30783587b David Herrmann 2012-11-17 364 list_for_each_entry(pos, &cuse_conntbl[i], list)
30783587b David Herrmann 2012-11-17 365 if (!strcmp(dev_name(pos->dev), dev_name(dev)))
30783587b David Herrmann 2012-11-17 366 goto err_unlock;
30783587b David Herrmann 2012-11-17 367 }
30783587b David Herrmann 2012-11-17 368
151060ac1 Tejun Heo 2009-04-14 369 rc = device_add(dev);
151060ac1 Tejun Heo 2009-04-14 370 if (rc)
30783587b David Herrmann 2012-11-17 371 goto err_unlock;
151060ac1 Tejun Heo 2009-04-14 372
151060ac1 Tejun Heo 2009-04-14 373 /* register cdev */
151060ac1 Tejun Heo 2009-04-14 374 rc = -ENOMEM;
151060ac1 Tejun Heo 2009-04-14 375 cdev = cdev_alloc();
151060ac1 Tejun Heo 2009-04-14 376 if (!cdev)
30783587b David Herrmann 2012-11-17 377 goto err_unlock;
151060ac1 Tejun Heo 2009-04-14 378
151060ac1 Tejun Heo 2009-04-14 379 cdev->owner = THIS_MODULE;
151060ac1 Tejun Heo 2009-04-14 380 cdev->ops = &cuse_frontend_fops;
151060ac1 Tejun Heo 2009-04-14 381
151060ac1 Tejun Heo 2009-04-14 382 rc = cdev_add(cdev, devt, 1);
151060ac1 Tejun Heo 2009-04-14 383 if (rc)
151060ac1 Tejun Heo 2009-04-14 384 goto err_cdev;
151060ac1 Tejun Heo 2009-04-14 385
151060ac1 Tejun Heo 2009-04-14 386 cc->dev = dev;
151060ac1 Tejun Heo 2009-04-14 387 cc->cdev = cdev;
151060ac1 Tejun Heo 2009-04-14 388
151060ac1 Tejun Heo 2009-04-14 389 /* make the device available */
151060ac1 Tejun Heo 2009-04-14 390 list_add(&cc->list, cuse_conntbl_head(devt));
8ce03fd76 David Herrmann 2012-11-17 391 mutex_unlock(&cuse_lock);
151060ac1 Tejun Heo 2009-04-14 392
151060ac1 Tejun Heo 2009-04-14 393 /* announce device availability */
151060ac1 Tejun Heo 2009-04-14 394 dev_set_uevent_suppress(dev, 0);
151060ac1 Tejun Heo 2009-04-14 395 kobject_uevent(&dev->kobj, KOBJ_ADD);
151060ac1 Tejun Heo 2009-04-14 396 out:
07d5f69b4 Miklos Szeredi 2011-03-21 397 kfree(arg);
151060ac1 Tejun Heo 2009-04-14 398 __free_page(page);
151060ac1 Tejun Heo 2009-04-14 399 return;
151060ac1 Tejun Heo 2009-04-14 400
151060ac1 Tejun Heo 2009-04-14 401 err_cdev:
151060ac1 Tejun Heo 2009-04-14 402 cdev_del(cdev);
30783587b David Herrmann 2012-11-17 403 err_unlock:
30783587b David Herrmann 2012-11-17 404 mutex_unlock(&cuse_lock);
151060ac1 Tejun Heo 2009-04-14 405 put_device(dev);
151060ac1 Tejun Heo 2009-04-14 406 err_region:
151060ac1 Tejun Heo 2009-04-14 407 unregister_chrdev_region(devt, 1);
151060ac1 Tejun Heo 2009-04-14 408 err:
580640ba5 Miklos Szeredi 2014-12-12 @409 fuse_abort_conn(fc);
151060ac1 Tejun Heo 2009-04-14 410 goto out;
151060ac1 Tejun Heo 2009-04-14 411 }
151060ac1 Tejun Heo 2009-04-14 412
:::::: The code at line 409 was first introduced by commit
:::::: 580640ba5d331eb5631a5de46941c98f5ed90886 fuse: flush requests on umount
:::::: TO: Miklos Szeredi <mszeredi@suse.cz>
:::::: CC: Miklos Szeredi <mszeredi@suse.cz>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v4] fuse: return -ECONNABORTED on /dev/fuse read after abort
2017-11-07 0:16 ` [PATCH v3] " Szymon Lukasz
2017-11-09 18:29 ` kbuild test robot
2017-11-09 19:44 ` kbuild test robot
@ 2017-11-09 20:23 ` Szymon Lukasz
[not found] ` <20171109202335.19797-1-noh4hss-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
` (2 more replies)
2 siblings, 3 replies; 10+ messages in thread
From: Szymon Lukasz @ 2017-11-09 20:23 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: linux-fsdevel, fuse-devel, Szymon Lukasz
Adds a new capability flag FUSE_ABORT_ERROR. If set and the connection
is gone because of sysfs abort, reading from the device will return
-ECONNABORTED.
Signed-off-by: Szymon Lukasz <noh4hss@gmail.com>
---
fs/fuse/control.c | 2 +-
fs/fuse/cuse.c | 4 ++--
fs/fuse/dev.c | 12 +++++++-----
fs/fuse/fuse_i.h | 8 +++++++-
fs/fuse/inode.c | 9 ++++++---
include/uapi/linux/fuse.h | 7 ++++++-
6 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index b9ea99c5b5b3..78fb7a07c5ca 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -35,7 +35,7 @@ static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
{
struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
if (fc) {
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, true);
fuse_conn_put(fc);
}
return count;
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index e9e97803442a..31d33b69957f 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -406,7 +406,7 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
err_region:
unregister_chrdev_region(devt, 1);
err:
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, false);
goto out;
}
@@ -581,7 +581,7 @@ static ssize_t cuse_class_abort_store(struct device *dev,
{
struct cuse_conn *cc = dev_get_drvdata(dev);
- fuse_abort_conn(&cc->fc);
+ fuse_abort_conn(&cc->fc, false);
return count;
}
static DEVICE_ATTR(abort, 0200, NULL, cuse_class_abort_store);
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 13c65dd2d37d..2e1beda0b82b 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1234,9 +1234,10 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
if (err)
goto err_unlock;
- err = -ENODEV;
- if (!fiq->connected)
+ if (!fiq->connected) {
+ err = (fc->aborted && fc->abort_err) ? -ECONNABORTED : -ENODEV;
goto err_unlock;
+ }
if (!list_empty(&fiq->interrupts)) {
req = list_entry(fiq->interrupts.next, struct fuse_req,
@@ -1287,7 +1288,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
spin_lock(&fpq->lock);
clear_bit(FR_LOCKED, &req->flags);
if (!fpq->connected) {
- err = -ENODEV;
+ err = (fc->aborted && fc->abort_err) ? -ECONNABORTED : -ENODEV;
goto out_end;
}
if (err) {
@@ -2076,7 +2077,7 @@ static void end_polls(struct fuse_conn *fc)
* is OK, the request will in that case be removed from the list before we touch
* it.
*/
-void fuse_abort_conn(struct fuse_conn *fc)
+void fuse_abort_conn(struct fuse_conn *fc, bool is_abort)
{
struct fuse_iqueue *fiq = &fc->iq;
@@ -2089,6 +2090,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
fc->connected = 0;
fc->blocked = 0;
+ fc->aborted = is_abort;
fuse_set_initialized(fc);
list_for_each_entry(fud, &fc->devices, entry) {
struct fuse_pqueue *fpq = &fud->pq;
@@ -2151,7 +2153,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
/* Are we the last open device? */
if (atomic_dec_and_test(&fc->dev_count)) {
WARN_ON(fc->iq.fasync != NULL);
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, false);
}
fuse_dev_free(fud);
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index d5773ca67ad2..2f8a261d8669 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -515,6 +515,9 @@ struct fuse_conn {
abort and device release */
unsigned connected;
+ /** Connection aborted via sysfs */
+ bool aborted;
+
/** Connection failed (version mismatch). Cannot race with
setting other bitfields since it is only set once in INIT
reply, before any other request, and never cleared */
@@ -526,6 +529,9 @@ struct fuse_conn {
/** Do readpages asynchronously? Only set in INIT */
unsigned async_read:1;
+ /** Return an unique read error after abort. Only set in INIT */
+ unsigned abort_err:1;
+
/** Do not send separate SETATTR request before open(O_TRUNC) */
unsigned atomic_o_trunc:1;
@@ -851,7 +857,7 @@ void fuse_request_send_background_locked(struct fuse_conn *fc,
struct fuse_req *req);
/* Abort all requests */
-void fuse_abort_conn(struct fuse_conn *fc);
+void fuse_abort_conn(struct fuse_conn *fc, bool is_abort);
/**
* Invalidate inode attributes
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 94a745acaef8..46a17de24e14 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -371,7 +371,7 @@ void fuse_unlock_inode(struct inode *inode)
static void fuse_umount_begin(struct super_block *sb)
{
- fuse_abort_conn(get_fuse_conn_super(sb));
+ fuse_abort_conn(get_fuse_conn_super(sb), false);
}
static void fuse_send_destroy(struct fuse_conn *fc)
@@ -393,7 +393,7 @@ static void fuse_put_super(struct super_block *sb)
fuse_send_destroy(fc);
- fuse_abort_conn(fc);
+ fuse_abort_conn(fc, false);
mutex_lock(&fuse_mutex);
list_del(&fc->entry);
fuse_ctl_remove_conn(fc);
@@ -918,6 +918,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
fc->posix_acl = 1;
fc->sb->s_xattr = fuse_acl_xattr_handlers;
}
+ if (arg->flags & FUSE_ABORT_ERROR)
+ fc->abort_err = 1;
} else {
ra_pages = fc->max_read / PAGE_SIZE;
fc->no_lock = 1;
@@ -948,7 +950,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
FUSE_FLOCK_LOCKS | FUSE_HAS_IOCTL_DIR | FUSE_AUTO_INVAL_DATA |
FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO |
FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT |
- FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL;
+ FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL |
+ FUSE_ABORT_ERROR;
req->in.h.opcode = FUSE_INIT;
req->in.numargs = 1;
req->in.args[0].size = sizeof(*arg);
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index 42fa977e3b14..f9b11c43c8f6 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -112,6 +112,9 @@
* 7.26
* - add FUSE_HANDLE_KILLPRIV
* - add FUSE_POSIX_ACL
+ *
+ * 7.27
+ * - add FUSE_ABORT_ERROR
*/
#ifndef _LINUX_FUSE_H
@@ -147,7 +150,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 26
+#define FUSE_KERNEL_MINOR_VERSION 27
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@@ -244,6 +247,7 @@ struct fuse_file_lock {
* FUSE_PARALLEL_DIROPS: allow parallel lookups and readdir
* FUSE_HANDLE_KILLPRIV: fs handles killing suid/sgid/cap on write/chown/trunc
* FUSE_POSIX_ACL: filesystem supports posix acls
+ * FUSE_ABORT_ERROR: reading the device after abort returns ECONNABORTED
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
@@ -266,6 +270,7 @@ struct fuse_file_lock {
#define FUSE_PARALLEL_DIROPS (1 << 18)
#define FUSE_HANDLE_KILLPRIV (1 << 19)
#define FUSE_POSIX_ACL (1 << 20)
+#define FUSE_ABORT_ERROR (1 << 21)
/**
* CUSE INIT request/reply flags
--
2.15.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v4] fuse: return -ECONNABORTED on /dev/fuse read after abort
[not found] ` <20171109202335.19797-1-noh4hss-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2017-11-21 22:16 ` Szymon Łukasz
0 siblings, 0 replies; 10+ messages in thread
From: Szymon Łukasz @ 2017-11-21 22:16 UTC (permalink / raw)
To: Miklos Szeredi
Cc: linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
fuse-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Szymon Lukasz
[-- Attachment #1.1: Type: text/plain, Size: 8455 bytes --]
Bump
On Thu, Nov 9, 2017 at 9:23 PM, Szymon Lukasz <noh4hss-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> Adds a new capability flag FUSE_ABORT_ERROR. If set and the connection
> is gone because of sysfs abort, reading from the device will return
> -ECONNABORTED.
>
> Signed-off-by: Szymon Lukasz <noh4hss-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> fs/fuse/control.c | 2 +-
> fs/fuse/cuse.c | 4 ++--
> fs/fuse/dev.c | 12 +++++++-----
> fs/fuse/fuse_i.h | 8 +++++++-
> fs/fuse/inode.c | 9 ++++++---
> include/uapi/linux/fuse.h | 7 ++++++-
> 6 files changed, 29 insertions(+), 13 deletions(-)
>
> diff --git a/fs/fuse/control.c b/fs/fuse/control.c
> index b9ea99c5b5b3..78fb7a07c5ca 100644
> --- a/fs/fuse/control.c
> +++ b/fs/fuse/control.c
> @@ -35,7 +35,7 @@ static ssize_t fuse_conn_abort_write(struct file *file,
> const char __user *buf,
> {
> struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
> if (fc) {
> - fuse_abort_conn(fc);
> + fuse_abort_conn(fc, true);
> fuse_conn_put(fc);
> }
> return count;
> diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
> index e9e97803442a..31d33b69957f 100644
> --- a/fs/fuse/cuse.c
> +++ b/fs/fuse/cuse.c
> @@ -406,7 +406,7 @@ static void cuse_process_init_reply(struct fuse_conn
> *fc, struct fuse_req *req)
> err_region:
> unregister_chrdev_region(devt, 1);
> err:
> - fuse_abort_conn(fc);
> + fuse_abort_conn(fc, false);
> goto out;
> }
>
> @@ -581,7 +581,7 @@ static ssize_t cuse_class_abort_store(struct device
> *dev,
> {
> struct cuse_conn *cc = dev_get_drvdata(dev);
>
> - fuse_abort_conn(&cc->fc);
> + fuse_abort_conn(&cc->fc, false);
> return count;
> }
> static DEVICE_ATTR(abort, 0200, NULL, cuse_class_abort_store);
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index 13c65dd2d37d..2e1beda0b82b 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -1234,9 +1234,10 @@ static ssize_t fuse_dev_do_read(struct fuse_dev
> *fud, struct file *file,
> if (err)
> goto err_unlock;
>
> - err = -ENODEV;
> - if (!fiq->connected)
> + if (!fiq->connected) {
> + err = (fc->aborted && fc->abort_err) ? -ECONNABORTED :
> -ENODEV;
> goto err_unlock;
> + }
>
> if (!list_empty(&fiq->interrupts)) {
> req = list_entry(fiq->interrupts.next, struct fuse_req,
> @@ -1287,7 +1288,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev
> *fud, struct file *file,
> spin_lock(&fpq->lock);
> clear_bit(FR_LOCKED, &req->flags);
> if (!fpq->connected) {
> - err = -ENODEV;
> + err = (fc->aborted && fc->abort_err) ? -ECONNABORTED :
> -ENODEV;
> goto out_end;
> }
> if (err) {
> @@ -2076,7 +2077,7 @@ static void end_polls(struct fuse_conn *fc)
> * is OK, the request will in that case be removed from the list before
> we touch
> * it.
> */
> -void fuse_abort_conn(struct fuse_conn *fc)
> +void fuse_abort_conn(struct fuse_conn *fc, bool is_abort)
> {
> struct fuse_iqueue *fiq = &fc->iq;
>
> @@ -2089,6 +2090,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
>
> fc->connected = 0;
> fc->blocked = 0;
> + fc->aborted = is_abort;
> fuse_set_initialized(fc);
> list_for_each_entry(fud, &fc->devices, entry) {
> struct fuse_pqueue *fpq = &fud->pq;
> @@ -2151,7 +2153,7 @@ int fuse_dev_release(struct inode *inode, struct
> file *file)
> /* Are we the last open device? */
> if (atomic_dec_and_test(&fc->dev_count)) {
> WARN_ON(fc->iq.fasync != NULL);
> - fuse_abort_conn(fc);
> + fuse_abort_conn(fc, false);
> }
> fuse_dev_free(fud);
> }
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index d5773ca67ad2..2f8a261d8669 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -515,6 +515,9 @@ struct fuse_conn {
> abort and device release */
> unsigned connected;
>
> + /** Connection aborted via sysfs */
> + bool aborted;
> +
> /** Connection failed (version mismatch). Cannot race with
> setting other bitfields since it is only set once in INIT
> reply, before any other request, and never cleared */
> @@ -526,6 +529,9 @@ struct fuse_conn {
> /** Do readpages asynchronously? Only set in INIT */
> unsigned async_read:1;
>
> + /** Return an unique read error after abort. Only set in INIT */
> + unsigned abort_err:1;
> +
> /** Do not send separate SETATTR request before open(O_TRUNC) */
> unsigned atomic_o_trunc:1;
>
> @@ -851,7 +857,7 @@ void fuse_request_send_background_locked(struct
> fuse_conn *fc,
> struct fuse_req *req);
>
> /* Abort all requests */
> -void fuse_abort_conn(struct fuse_conn *fc);
> +void fuse_abort_conn(struct fuse_conn *fc, bool is_abort);
>
> /**
> * Invalidate inode attributes
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index 94a745acaef8..46a17de24e14 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -371,7 +371,7 @@ void fuse_unlock_inode(struct inode *inode)
>
> static void fuse_umount_begin(struct super_block *sb)
> {
> - fuse_abort_conn(get_fuse_conn_super(sb));
> + fuse_abort_conn(get_fuse_conn_super(sb), false);
> }
>
> static void fuse_send_destroy(struct fuse_conn *fc)
> @@ -393,7 +393,7 @@ static void fuse_put_super(struct super_block *sb)
>
> fuse_send_destroy(fc);
>
> - fuse_abort_conn(fc);
> + fuse_abort_conn(fc, false);
> mutex_lock(&fuse_mutex);
> list_del(&fc->entry);
> fuse_ctl_remove_conn(fc);
> @@ -918,6 +918,8 @@ static void process_init_reply(struct fuse_conn *fc,
> struct fuse_req *req)
> fc->posix_acl = 1;
> fc->sb->s_xattr = fuse_acl_xattr_handlers;
> }
> + if (arg->flags & FUSE_ABORT_ERROR)
> + fc->abort_err = 1;
> } else {
> ra_pages = fc->max_read / PAGE_SIZE;
> fc->no_lock = 1;
> @@ -948,7 +950,8 @@ static void fuse_send_init(struct fuse_conn *fc,
> struct fuse_req *req)
> FUSE_FLOCK_LOCKS | FUSE_HAS_IOCTL_DIR |
> FUSE_AUTO_INVAL_DATA |
> FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO |
> FUSE_ASYNC_DIO |
> FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT |
> - FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV |
> FUSE_POSIX_ACL;
> + FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV |
> FUSE_POSIX_ACL |
> + FUSE_ABORT_ERROR;
> req->in.h.opcode = FUSE_INIT;
> req->in.numargs = 1;
> req->in.args[0].size = sizeof(*arg);
> diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
> index 42fa977e3b14..f9b11c43c8f6 100644
> --- a/include/uapi/linux/fuse.h
> +++ b/include/uapi/linux/fuse.h
> @@ -112,6 +112,9 @@
> * 7.26
> * - add FUSE_HANDLE_KILLPRIV
> * - add FUSE_POSIX_ACL
> + *
> + * 7.27
> + * - add FUSE_ABORT_ERROR
> */
>
> #ifndef _LINUX_FUSE_H
> @@ -147,7 +150,7 @@
> #define FUSE_KERNEL_VERSION 7
>
> /** Minor version number of this interface */
> -#define FUSE_KERNEL_MINOR_VERSION 26
> +#define FUSE_KERNEL_MINOR_VERSION 27
>
> /** The node ID of the root inode */
> #define FUSE_ROOT_ID 1
> @@ -244,6 +247,7 @@ struct fuse_file_lock {
> * FUSE_PARALLEL_DIROPS: allow parallel lookups and readdir
> * FUSE_HANDLE_KILLPRIV: fs handles killing suid/sgid/cap on
> write/chown/trunc
> * FUSE_POSIX_ACL: filesystem supports posix acls
> + * FUSE_ABORT_ERROR: reading the device after abort returns ECONNABORTED
> */
> #define FUSE_ASYNC_READ (1 << 0)
> #define FUSE_POSIX_LOCKS (1 << 1)
> @@ -266,6 +270,7 @@ struct fuse_file_lock {
> #define FUSE_PARALLEL_DIROPS (1 << 18)
> #define FUSE_HANDLE_KILLPRIV (1 << 19)
> #define FUSE_POSIX_ACL (1 << 20)
> +#define FUSE_ABORT_ERROR (1 << 21)
>
> /**
> * CUSE INIT request/reply flags
> --
> 2.15.0
>
>
[-- Attachment #1.2: Type: text/html, Size: 10513 bytes --]
[-- Attachment #2: Type: text/plain, Size: 202 bytes --]
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
[-- Attachment #3: Type: text/plain, Size: 119 bytes --]
--
fuse-devel mailing list
To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4] fuse: return -ECONNABORTED on /dev/fuse read after abort
2017-11-09 20:23 ` [PATCH v4] " Szymon Lukasz
[not found] ` <20171109202335.19797-1-noh4hss-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2017-11-21 22:43 ` Szymon Lukasz
2018-03-21 11:57 ` Miklos Szeredi
2 siblings, 0 replies; 10+ messages in thread
From: Szymon Lukasz @ 2017-11-21 22:43 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: linux-fsdevel
Bump
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4] fuse: return -ECONNABORTED on /dev/fuse read after abort
2017-11-09 20:23 ` [PATCH v4] " Szymon Lukasz
[not found] ` <20171109202335.19797-1-noh4hss-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-11-21 22:43 ` Szymon Lukasz
@ 2018-03-21 11:57 ` Miklos Szeredi
2 siblings, 0 replies; 10+ messages in thread
From: Miklos Szeredi @ 2018-03-21 11:57 UTC (permalink / raw)
To: Szymon Lukasz; +Cc: linux-fsdevel, fuse-devel
On Thu, Nov 9, 2017 at 9:23 PM, Szymon Lukasz <noh4hss@gmail.com> wrote:
> Adds a new capability flag FUSE_ABORT_ERROR. If set and the connection
> is gone because of sysfs abort, reading from the device will return
> -ECONNABORTED.
Thanks, pushed to:
git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git for-next
Thanks,
Miklos
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2018-03-21 11:57 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-31 18:55 [PATCH] fuse: return -ECONNABORTED on /dev/fuse read after abort Szymon Lukasz
2017-11-03 15:04 ` [PATCH v2] " Szymon Lukasz
2017-11-06 9:51 ` Miklos Szeredi
2017-11-07 0:16 ` [PATCH v3] " Szymon Lukasz
2017-11-09 18:29 ` kbuild test robot
2017-11-09 19:44 ` kbuild test robot
2017-11-09 20:23 ` [PATCH v4] " Szymon Lukasz
[not found] ` <20171109202335.19797-1-noh4hss-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-11-21 22:16 ` Szymon Łukasz
2017-11-21 22:43 ` Szymon Lukasz
2018-03-21 11:57 ` Miklos Szeredi
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.