* [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}().
@ 2016-12-01 5:37 cuilifei
2016-12-02 14:42 ` kbuild test robot
2016-12-02 14:51 ` kbuild test robot
0 siblings, 2 replies; 10+ messages in thread
From: cuilifei @ 2016-12-01 5:37 UTC (permalink / raw)
To: linux-kernel; +Cc: miklos, cuilifei
Freezing process can abort when a client is waiting uninterruptibly
for a response. Add new macro wait_fatal_freezable to try to fix it.
Signed-off-by: cuilifei <cuilifei@xiaomi.com>
---
fs/fuse/dev.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 42 insertions(+), 4 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 70ea57c..5c63518 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -23,6 +23,23 @@
MODULE_ALIAS_MISCDEV(FUSE_MINOR);
MODULE_ALIAS("devname:fuse");
+#define wait_fatal_freezable(wq, condition, exclusive) \
+({ \
+ int __ret = 0; \
+ do { \
+ if (exclusive) \
+ ret = wait_event_interruptible_exclusive(wq, \
+ condition); \
+ else \
+ ret = wait_event_interruptible(wq, condition); \
+ if (!__ret || fatal_signal_pending(current)) \
+ break; \
+ if (!freezing(current)) \
+ continue; \
+ } while (try_to_freeze()); \
+ __ret; \
+})
+
static struct kmem_cache *fuse_req_cachep;
static struct fuse_dev *fuse_get_dev(struct file *file)
@@ -99,6 +116,19 @@ void fuse_request_free(struct fuse_req *req)
kmem_cache_free(fuse_req_cachep, req);
}
+static void block_sigs(sigset_t *oldset)
+{
+ sigset_t mask;
+
+ siginitsetinv(&mask, sigmask(SIGKILL));
+ sigprocmask(SIG_BLOCK, &mask, oldset);
+}
+
+static void restore_sigs(sigset_t *oldset)
+{
+ sigprocmask(SIG_SETMASK, oldset, NULL);
+}
+
void __fuse_get_request(struct fuse_req *req)
{
atomic_inc(&req->count);
@@ -134,13 +164,18 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
bool for_background)
{
struct fuse_req *req;
+ sigset_t oldset;
+ int intr;
int err;
atomic_inc(&fc->num_waiting);
if (fuse_block_alloc(fc, for_background)) {
err = -EINTR;
- if (wait_event_killable_exclusive(fc->blocked_waitq,
- !fuse_block_alloc(fc, for_background)))
+ block_sigs(&oldset);
+ intr = wait_fatal_freezable(fc->blocked_waitq,
+ !fuse_block_alloc(fc, for_background), true);
+ restore_sigs(&oldset);
+ if (intr)
goto out;
}
/* Matches smp_wmb() in fuse_set_initialized() */
@@ -427,9 +462,12 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
}
if (!test_bit(FR_FORCE, &req->flags)) {
+ sigset_t oldset;
/* Only fatal signals may interrupt this */
- err = wait_event_killable(req->waitq,
- test_bit(FR_FINISHED, &req->flags));
+ block_sigs(&oldset);
+ err = wait_fatal_freezable(req->waitq,
+ test_bit(FR_FINISHED, &req->flags), false);
+ restore_sigs(&oldset);
if (!err)
return;
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}().
2016-12-01 5:37 [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}() cuilifei
@ 2016-12-02 14:42 ` kbuild test robot
2016-12-02 14:51 ` kbuild test robot
1 sibling, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2016-12-02 14:42 UTC (permalink / raw)
To: cuilifei; +Cc: kbuild-all, linux-kernel, miklos, cuilifei
[-- Attachment #1: Type: text/plain, Size: 7017 bytes --]
Hi cuilifei,
[auto build test ERROR on fuse/for-next]
[also build test ERROR on v4.9-rc7 next-20161202]
[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/cuilifei/fuse-freezing-abort-when-use-wait_event_killable-_exclusive/20161202-221508
base: https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git for-next
config: i386-randconfig-i0-201648 (attached as .config)
compiler: gcc-4.8 (Debian 4.8.4-1) 4.8.4
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
fs/fuse/dev.c: In function '__fuse_get_req':
>> fs/fuse/dev.c:31:4: error: 'ret' undeclared (first use in this function)
ret = wait_event_interruptible_exclusive(wq, \
^
fs/fuse/dev.c:175:10: note: in expansion of macro 'wait_fatal_freezable'
intr = wait_fatal_freezable(fc->blocked_waitq,
^
fs/fuse/dev.c:31:4: note: each undeclared identifier is reported only once for each function it appears in
ret = wait_event_interruptible_exclusive(wq, \
^
fs/fuse/dev.c:175:10: note: in expansion of macro 'wait_fatal_freezable'
intr = wait_fatal_freezable(fc->blocked_waitq,
^
>> fs/fuse/dev.c:175:3: error: implicit declaration of function 'freezing' [-Werror=implicit-function-declaration]
intr = wait_fatal_freezable(fc->blocked_waitq,
^
>> fs/fuse/dev.c:175:3: error: implicit declaration of function 'try_to_freeze' [-Werror=implicit-function-declaration]
fs/fuse/dev.c: In function 'request_wait_answer':
>> fs/fuse/dev.c:31:4: error: 'ret' undeclared (first use in this function)
ret = wait_event_interruptible_exclusive(wq, \
^
fs/fuse/dev.c:468:9: note: in expansion of macro 'wait_fatal_freezable'
err = wait_fatal_freezable(req->waitq,
^
cc1: some warnings being treated as errors
vim +/ret +31 fs/fuse/dev.c
25
26 #define wait_fatal_freezable(wq, condition, exclusive) \
27 ({ \
28 int __ret = 0; \
29 do { \
30 if (exclusive) \
> 31 ret = wait_event_interruptible_exclusive(wq, \
32 condition); \
33 else \
34 ret = wait_event_interruptible(wq, condition); \
35 if (!__ret || fatal_signal_pending(current)) \
36 break; \
37 if (!freezing(current)) \
38 continue; \
39 } while (try_to_freeze()); \
40 __ret; \
41 })
42
43 static struct kmem_cache *fuse_req_cachep;
44
45 static struct fuse_dev *fuse_get_dev(struct file *file)
46 {
47 /*
48 * Lockless access is OK, because file->private data is set
49 * once during mount and is valid until the file is released.
50 */
51 return ACCESS_ONCE(file->private_data);
52 }
53
54 static void fuse_request_init(struct fuse_req *req, struct page **pages,
55 struct fuse_page_desc *page_descs,
56 unsigned npages)
57 {
58 memset(req, 0, sizeof(*req));
59 memset(pages, 0, sizeof(*pages) * npages);
60 memset(page_descs, 0, sizeof(*page_descs) * npages);
61 INIT_LIST_HEAD(&req->list);
62 INIT_LIST_HEAD(&req->intr_entry);
63 init_waitqueue_head(&req->waitq);
64 atomic_set(&req->count, 1);
65 req->pages = pages;
66 req->page_descs = page_descs;
67 req->max_pages = npages;
68 __set_bit(FR_PENDING, &req->flags);
69 }
70
71 static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags)
72 {
73 struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, flags);
74 if (req) {
75 struct page **pages;
76 struct fuse_page_desc *page_descs;
77
78 if (npages <= FUSE_REQ_INLINE_PAGES) {
79 pages = req->inline_pages;
80 page_descs = req->inline_page_descs;
81 } else {
82 pages = kmalloc(sizeof(struct page *) * npages, flags);
83 page_descs = kmalloc(sizeof(struct fuse_page_desc) *
84 npages, flags);
85 }
86
87 if (!pages || !page_descs) {
88 kfree(pages);
89 kfree(page_descs);
90 kmem_cache_free(fuse_req_cachep, req);
91 return NULL;
92 }
93
94 fuse_request_init(req, pages, page_descs, npages);
95 }
96 return req;
97 }
98
99 struct fuse_req *fuse_request_alloc(unsigned npages)
100 {
101 return __fuse_request_alloc(npages, GFP_KERNEL);
102 }
103 EXPORT_SYMBOL_GPL(fuse_request_alloc);
104
105 struct fuse_req *fuse_request_alloc_nofs(unsigned npages)
106 {
107 return __fuse_request_alloc(npages, GFP_NOFS);
108 }
109
110 void fuse_request_free(struct fuse_req *req)
111 {
112 if (req->pages != req->inline_pages) {
113 kfree(req->pages);
114 kfree(req->page_descs);
115 }
116 kmem_cache_free(fuse_req_cachep, req);
117 }
118
119 static void block_sigs(sigset_t *oldset)
120 {
121 sigset_t mask;
122
123 siginitsetinv(&mask, sigmask(SIGKILL));
124 sigprocmask(SIG_BLOCK, &mask, oldset);
125 }
126
127 static void restore_sigs(sigset_t *oldset)
128 {
129 sigprocmask(SIG_SETMASK, oldset, NULL);
130 }
131
132 void __fuse_get_request(struct fuse_req *req)
133 {
134 atomic_inc(&req->count);
135 }
136
137 /* Must be called with > 1 refcount */
138 static void __fuse_put_request(struct fuse_req *req)
139 {
140 BUG_ON(atomic_read(&req->count) < 2);
141 atomic_dec(&req->count);
142 }
143
144 static void fuse_req_init_context(struct fuse_req *req)
145 {
146 req->in.h.uid = from_kuid_munged(&init_user_ns, current_fsuid());
147 req->in.h.gid = from_kgid_munged(&init_user_ns, current_fsgid());
148 req->in.h.pid = current->pid;
149 }
150
151 void fuse_set_initialized(struct fuse_conn *fc)
152 {
153 /* Make sure stores before this are seen on another CPU */
154 smp_wmb();
155 fc->initialized = 1;
156 }
157
158 static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
159 {
160 return !fc->initialized || (for_background && fc->blocked);
161 }
162
163 static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
164 bool for_background)
165 {
166 struct fuse_req *req;
167 sigset_t oldset;
168 int intr;
169 int err;
170 atomic_inc(&fc->num_waiting);
171
172 if (fuse_block_alloc(fc, for_background)) {
173 err = -EINTR;
174 block_sigs(&oldset);
> 175 intr = wait_fatal_freezable(fc->blocked_waitq,
176 !fuse_block_alloc(fc, for_background), true);
177 restore_sigs(&oldset);
178 if (intr)
---
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: 23011 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}().
2016-12-01 5:37 [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}() cuilifei
2016-12-02 14:42 ` kbuild test robot
@ 2016-12-02 14:51 ` kbuild test robot
1 sibling, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2016-12-02 14:51 UTC (permalink / raw)
To: cuilifei; +Cc: kbuild-all, linux-kernel, miklos, cuilifei
[-- Attachment #1: Type: text/plain, Size: 7189 bytes --]
Hi cuilifei,
[auto build test WARNING on fuse/for-next]
[also build test WARNING on v4.9-rc7 next-20161202]
[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/cuilifei/fuse-freezing-abort-when-use-wait_event_killable-_exclusive/20161202-221508
base: https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git for-next
config: m68k-sun3_defconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 4.9.0
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=m68k
All warnings (new ones prefixed by >>):
fs/fuse/dev.c: In function '__fuse_get_req':
fs/fuse/dev.c:31:4: error: 'ret' undeclared (first use in this function)
ret = wait_event_interruptible_exclusive(wq, \
^
>> fs/fuse/dev.c:175:10: note: in expansion of macro 'wait_fatal_freezable'
intr = wait_fatal_freezable(fc->blocked_waitq,
^
fs/fuse/dev.c:31:4: note: each undeclared identifier is reported only once for each function it appears in
ret = wait_event_interruptible_exclusive(wq, \
^
>> fs/fuse/dev.c:175:10: note: in expansion of macro 'wait_fatal_freezable'
intr = wait_fatal_freezable(fc->blocked_waitq,
^
fs/fuse/dev.c:175:3: error: implicit declaration of function 'freezing' [-Werror=implicit-function-declaration]
intr = wait_fatal_freezable(fc->blocked_waitq,
^
fs/fuse/dev.c:175:3: error: implicit declaration of function 'try_to_freeze' [-Werror=implicit-function-declaration]
fs/fuse/dev.c: In function 'request_wait_answer':
fs/fuse/dev.c:31:4: error: 'ret' undeclared (first use in this function)
ret = wait_event_interruptible_exclusive(wq, \
^
fs/fuse/dev.c:468:9: note: in expansion of macro 'wait_fatal_freezable'
err = wait_fatal_freezable(req->waitq,
^
cc1: some warnings being treated as errors
vim +/wait_fatal_freezable +175 fs/fuse/dev.c
25
26 #define wait_fatal_freezable(wq, condition, exclusive) \
27 ({ \
28 int __ret = 0; \
29 do { \
30 if (exclusive) \
> 31 ret = wait_event_interruptible_exclusive(wq, \
32 condition); \
33 else \
34 ret = wait_event_interruptible(wq, condition); \
35 if (!__ret || fatal_signal_pending(current)) \
36 break; \
37 if (!freezing(current)) \
38 continue; \
39 } while (try_to_freeze()); \
40 __ret; \
41 })
42
43 static struct kmem_cache *fuse_req_cachep;
44
45 static struct fuse_dev *fuse_get_dev(struct file *file)
46 {
47 /*
48 * Lockless access is OK, because file->private data is set
49 * once during mount and is valid until the file is released.
50 */
51 return ACCESS_ONCE(file->private_data);
52 }
53
54 static void fuse_request_init(struct fuse_req *req, struct page **pages,
55 struct fuse_page_desc *page_descs,
56 unsigned npages)
57 {
58 memset(req, 0, sizeof(*req));
59 memset(pages, 0, sizeof(*pages) * npages);
60 memset(page_descs, 0, sizeof(*page_descs) * npages);
61 INIT_LIST_HEAD(&req->list);
62 INIT_LIST_HEAD(&req->intr_entry);
63 init_waitqueue_head(&req->waitq);
64 atomic_set(&req->count, 1);
65 req->pages = pages;
66 req->page_descs = page_descs;
67 req->max_pages = npages;
68 __set_bit(FR_PENDING, &req->flags);
69 }
70
71 static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags)
72 {
73 struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, flags);
74 if (req) {
75 struct page **pages;
76 struct fuse_page_desc *page_descs;
77
78 if (npages <= FUSE_REQ_INLINE_PAGES) {
79 pages = req->inline_pages;
80 page_descs = req->inline_page_descs;
81 } else {
82 pages = kmalloc(sizeof(struct page *) * npages, flags);
83 page_descs = kmalloc(sizeof(struct fuse_page_desc) *
84 npages, flags);
85 }
86
87 if (!pages || !page_descs) {
88 kfree(pages);
89 kfree(page_descs);
90 kmem_cache_free(fuse_req_cachep, req);
91 return NULL;
92 }
93
94 fuse_request_init(req, pages, page_descs, npages);
95 }
96 return req;
97 }
98
99 struct fuse_req *fuse_request_alloc(unsigned npages)
100 {
101 return __fuse_request_alloc(npages, GFP_KERNEL);
102 }
103 EXPORT_SYMBOL_GPL(fuse_request_alloc);
104
105 struct fuse_req *fuse_request_alloc_nofs(unsigned npages)
106 {
107 return __fuse_request_alloc(npages, GFP_NOFS);
108 }
109
110 void fuse_request_free(struct fuse_req *req)
111 {
112 if (req->pages != req->inline_pages) {
113 kfree(req->pages);
114 kfree(req->page_descs);
115 }
116 kmem_cache_free(fuse_req_cachep, req);
117 }
118
119 static void block_sigs(sigset_t *oldset)
120 {
121 sigset_t mask;
122
123 siginitsetinv(&mask, sigmask(SIGKILL));
124 sigprocmask(SIG_BLOCK, &mask, oldset);
125 }
126
127 static void restore_sigs(sigset_t *oldset)
128 {
129 sigprocmask(SIG_SETMASK, oldset, NULL);
130 }
131
132 void __fuse_get_request(struct fuse_req *req)
133 {
134 atomic_inc(&req->count);
135 }
136
137 /* Must be called with > 1 refcount */
138 static void __fuse_put_request(struct fuse_req *req)
139 {
140 BUG_ON(atomic_read(&req->count) < 2);
141 atomic_dec(&req->count);
142 }
143
144 static void fuse_req_init_context(struct fuse_req *req)
145 {
146 req->in.h.uid = from_kuid_munged(&init_user_ns, current_fsuid());
147 req->in.h.gid = from_kgid_munged(&init_user_ns, current_fsgid());
148 req->in.h.pid = current->pid;
149 }
150
151 void fuse_set_initialized(struct fuse_conn *fc)
152 {
153 /* Make sure stores before this are seen on another CPU */
154 smp_wmb();
155 fc->initialized = 1;
156 }
157
158 static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
159 {
160 return !fc->initialized || (for_background && fc->blocked);
161 }
162
163 static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
164 bool for_background)
165 {
166 struct fuse_req *req;
167 sigset_t oldset;
168 int intr;
169 int err;
170 atomic_inc(&fc->num_waiting);
171
172 if (fuse_block_alloc(fc, for_background)) {
173 err = -EINTR;
174 block_sigs(&oldset);
> 175 intr = wait_fatal_freezable(fc->blocked_waitq,
176 !fuse_block_alloc(fc, for_background), true);
177 restore_sigs(&oldset);
178 if (intr)
---
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: 11509 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}().
@ 2016-12-01 5:43 cuilifei
2016-12-02 16:16 ` kbuild test robot
2016-12-02 18:42 ` kbuild test robot
0 siblings, 2 replies; 10+ messages in thread
From: cuilifei @ 2016-12-01 5:43 UTC (permalink / raw)
To: linux-kernel; +Cc: miklos, cuilifei
Freezing process can abort when a client is waiting uninterruptibly
for a response. Add new macro wait_fatal_freezable to try to fix it.
Signed-off-by: cuilifei <cuilifei@xiaomi.com>
---
fs/fuse/dev.c | 47 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 43 insertions(+), 4 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 70ea57c..40aea7d 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -23,6 +23,24 @@
MODULE_ALIAS_MISCDEV(FUSE_MINOR);
MODULE_ALIAS("devname:fuse");
+#define wait_fatal_freezable(wq, condition, exclusive) \
+({ \
+ int __ret = 0; \
+ do { \
+ if (exclusive) \
+ __ret = wait_event_interruptible_exclusive(wq, \
+ condition); \
+ else \
+ __ret = wait_event_interruptible(wq, \
+ condition); \
+ if (!__ret || fatal_signal_pending(current)) \
+ break; \
+ if (!freezing(current)) \
+ continue; \
+ } while (try_to_freeze()); \
+ __ret; \
+})
+
static struct kmem_cache *fuse_req_cachep;
static struct fuse_dev *fuse_get_dev(struct file *file)
@@ -99,6 +117,19 @@ void fuse_request_free(struct fuse_req *req)
kmem_cache_free(fuse_req_cachep, req);
}
+static void block_sigs(sigset_t *oldset)
+{
+ sigset_t mask;
+
+ siginitsetinv(&mask, sigmask(SIGKILL));
+ sigprocmask(SIG_BLOCK, &mask, oldset);
+}
+
+static void restore_sigs(sigset_t *oldset)
+{
+ sigprocmask(SIG_SETMASK, oldset, NULL);
+}
+
void __fuse_get_request(struct fuse_req *req)
{
atomic_inc(&req->count);
@@ -134,13 +165,18 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
bool for_background)
{
struct fuse_req *req;
+ sigset_t oldset;
+ int intr;
int err;
atomic_inc(&fc->num_waiting);
if (fuse_block_alloc(fc, for_background)) {
err = -EINTR;
- if (wait_event_killable_exclusive(fc->blocked_waitq,
- !fuse_block_alloc(fc, for_background)))
+ block_sigs(&oldset);
+ intr = wait_fatal_freezable(fc->blocked_waitq,
+ !fuse_block_alloc(fc, for_background), true);
+ restore_sigs(&oldset);
+ if (intr)
goto out;
}
/* Matches smp_wmb() in fuse_set_initialized() */
@@ -427,9 +463,12 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
}
if (!test_bit(FR_FORCE, &req->flags)) {
+ sigset_t oldset;
/* Only fatal signals may interrupt this */
- err = wait_event_killable(req->waitq,
- test_bit(FR_FINISHED, &req->flags));
+ block_sigs(&oldset);
+ err = wait_fatal_freezable(req->waitq,
+ test_bit(FR_FINISHED, &req->flags), false);
+ restore_sigs(&oldset);
if (!err)
return;
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}().
2016-12-01 5:43 cuilifei
@ 2016-12-02 16:16 ` kbuild test robot
2016-12-02 18:42 ` kbuild test robot
1 sibling, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2016-12-02 16:16 UTC (permalink / raw)
To: cuilifei; +Cc: kbuild-all, linux-kernel, miklos, cuilifei
[-- Attachment #1: Type: text/plain, Size: 3564 bytes --]
Hi cuilifei,
[auto build test WARNING on fuse/for-next]
[also build test WARNING on v4.9-rc7 next-20161202]
[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/cuilifei/fuse-freezing-abort-when-use-wait_event_killable-_exclusive/20161202-234345
base: https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git for-next
config: x86_64-randconfig-x013-201648 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All warnings (new ones prefixed by >>):
In file included from include/uapi/linux/stddef.h:1:0,
from include/linux/stddef.h:4,
from include/uapi/linux/posix_types.h:4,
from include/uapi/linux/types.h:13,
from include/linux/types.h:5,
from include/uapi/linux/fuse.h:121,
from fs/fuse/fuse_i.h:12,
from fs/fuse/dev.c:9:
fs/fuse/dev.c: In function '__fuse_get_req':
fs/fuse/dev.c:38:8: error: implicit declaration of function 'freezing' [-Werror=implicit-function-declaration]
if (!freezing(current)) \
^
include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
^~~~
>> fs/fuse/dev.c:38:3: note: in expansion of macro 'if'
if (!freezing(current)) \
^~
fs/fuse/dev.c:176:10: note: in expansion of macro 'wait_fatal_freezable'
intr = wait_fatal_freezable(fc->blocked_waitq,
^~~~~~~~~~~~~~~~~~~~
fs/fuse/dev.c:40:11: error: implicit declaration of function 'try_to_freeze' [-Werror=implicit-function-declaration]
} while (try_to_freeze()); \
^
fs/fuse/dev.c:176:10: note: in expansion of macro 'wait_fatal_freezable'
intr = wait_fatal_freezable(fc->blocked_waitq,
^~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +/if +38 fs/fuse/dev.c
3 Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7 */
8
> 9 #include "fuse_i.h"
10
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/poll.h>
14 #include <linux/uio.h>
15 #include <linux/miscdevice.h>
16 #include <linux/pagemap.h>
17 #include <linux/file.h>
18 #include <linux/slab.h>
19 #include <linux/pipe_fs_i.h>
20 #include <linux/swap.h>
21 #include <linux/splice.h>
22
23 MODULE_ALIAS_MISCDEV(FUSE_MINOR);
24 MODULE_ALIAS("devname:fuse");
25
26 #define wait_fatal_freezable(wq, condition, exclusive) \
27 ({ \
28 int __ret = 0; \
29 do { \
30 if (exclusive) \
31 __ret = wait_event_interruptible_exclusive(wq, \
32 condition); \
33 else \
34 __ret = wait_event_interruptible(wq, \
35 condition); \
36 if (!__ret || fatal_signal_pending(current)) \
37 break; \
> 38 if (!freezing(current)) \
39 continue; \
40 } while (try_to_freeze()); \
41 __ret; \
---
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: 18547 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}().
2016-12-01 5:43 cuilifei
2016-12-02 16:16 ` kbuild test robot
@ 2016-12-02 18:42 ` kbuild test robot
1 sibling, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2016-12-02 18:42 UTC (permalink / raw)
To: cuilifei; +Cc: kbuild-all, linux-kernel, miklos, cuilifei
[-- Attachment #1: Type: text/plain, Size: 1956 bytes --]
Hi cuilifei,
[auto build test ERROR on fuse/for-next]
[also build test ERROR on v4.9-rc7 next-20161202]
[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/cuilifei/fuse-freezing-abort-when-use-wait_event_killable-_exclusive/20161202-234345
base: https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git for-next
config: x86_64-kexec (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
fs/fuse/dev.c: In function '__fuse_get_req':
>> fs/fuse/dev.c:38:8: error: implicit declaration of function 'freezing' [-Werror=implicit-function-declaration]
if (!freezing(current)) \
^
fs/fuse/dev.c:176:10: note: in expansion of macro 'wait_fatal_freezable'
intr = wait_fatal_freezable(fc->blocked_waitq,
^~~~~~~~~~~~~~~~~~~~
>> fs/fuse/dev.c:40:11: error: implicit declaration of function 'try_to_freeze' [-Werror=implicit-function-declaration]
} while (try_to_freeze()); \
^
fs/fuse/dev.c:176:10: note: in expansion of macro 'wait_fatal_freezable'
intr = wait_fatal_freezable(fc->blocked_waitq,
^~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +/freezing +38 fs/fuse/dev.c
32 condition); \
33 else \
34 __ret = wait_event_interruptible(wq, \
35 condition); \
36 if (!__ret || fatal_signal_pending(current)) \
37 break; \
> 38 if (!freezing(current)) \
39 continue; \
> 40 } while (try_to_freeze()); \
41 __ret; \
42 })
43
---
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: 24266 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}().
@ 2016-12-02 7:26 cuilifei
2016-12-03 8:54 ` kbuild test robot
0 siblings, 1 reply; 10+ messages in thread
From: cuilifei @ 2016-12-02 7:26 UTC (permalink / raw)
To: linux-kernel; +Cc: miklos, cuilifei
Freezing process can abort when a client is waiting uninterruptibly
for a response. Add new macro wait_fatal_freezable to try to fix it.
Signed-off-by: cuilifei <cuilifei@xiaomi.com>
---
fs/fuse/dev.c | 45 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 41 insertions(+), 4 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 70ea57c..3447ecc 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -23,6 +23,22 @@
MODULE_ALIAS_MISCDEV(FUSE_MINOR);
MODULE_ALIAS("devname:fuse");
+#define wait_fatal_freezable(wq, condition, exclusive) \
+({ \
+ int __ret = 0; \
+ do { \
+ if (exclusive) \
+ __ret = wait_event_interruptible_exclusive(wq, \
+ condition); \
+ else \
+ __ret = wait_event_interruptible(wq, \
+ condition); \
+ if (!__ret || fatal_signal_pending(current)) \
+ break; \
+ } while (try_to_freeze()); \
+ __ret; \
+})
+
static struct kmem_cache *fuse_req_cachep;
static struct fuse_dev *fuse_get_dev(struct file *file)
@@ -99,6 +115,19 @@ void fuse_request_free(struct fuse_req *req)
kmem_cache_free(fuse_req_cachep, req);
}
+static void block_sigs(sigset_t *oldset)
+{
+ sigset_t mask;
+
+ siginitsetinv(&mask, sigmask(SIGKILL));
+ sigprocmask(SIG_BLOCK, &mask, oldset);
+}
+
+static void restore_sigs(sigset_t *oldset)
+{
+ sigprocmask(SIG_SETMASK, oldset, NULL);
+}
+
void __fuse_get_request(struct fuse_req *req)
{
atomic_inc(&req->count);
@@ -134,13 +163,18 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
bool for_background)
{
struct fuse_req *req;
+ sigset_t oldset;
+ int intr;
int err;
atomic_inc(&fc->num_waiting);
if (fuse_block_alloc(fc, for_background)) {
err = -EINTR;
- if (wait_event_killable_exclusive(fc->blocked_waitq,
- !fuse_block_alloc(fc, for_background)))
+ block_sigs(&oldset);
+ intr = wait_fatal_freezable(fc->blocked_waitq,
+ !fuse_block_alloc(fc, for_background), true);
+ restore_sigs(&oldset);
+ if (intr)
goto out;
}
/* Matches smp_wmb() in fuse_set_initialized() */
@@ -427,9 +461,12 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
}
if (!test_bit(FR_FORCE, &req->flags)) {
+ sigset_t oldset;
/* Only fatal signals may interrupt this */
- err = wait_event_killable(req->waitq,
- test_bit(FR_FINISHED, &req->flags));
+ block_sigs(&oldset);
+ err = wait_fatal_freezable(req->waitq,
+ test_bit(FR_FINISHED, &req->flags), false);
+ restore_sigs(&oldset);
if (!err)
return;
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}().
2016-12-02 7:26 cuilifei
@ 2016-12-03 8:54 ` kbuild test robot
0 siblings, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2016-12-03 8:54 UTC (permalink / raw)
To: cuilifei; +Cc: kbuild-all, linux-kernel, miklos, cuilifei
[-- Attachment #1: Type: text/plain, Size: 1573 bytes --]
Hi cuilifei,
[auto build test ERROR on fuse/for-next]
[also build test ERROR on v4.9-rc7 next-20161202]
[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/cuilifei/fuse-freezing-abort-when-use-wait_event_killable-_exclusive/20161203-120253
base: https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git for-next
config: x86_64-rhel-7.2 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
fs/fuse/dev.c: In function '__fuse_get_req':
>> fs/fuse/dev.c:38:11: error: implicit declaration of function 'try_to_freeze' [-Werror=implicit-function-declaration]
} while (try_to_freeze()); \
^
fs/fuse/dev.c:174:10: note: in expansion of macro 'wait_fatal_freezable'
intr = wait_fatal_freezable(fc->blocked_waitq,
^~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +/try_to_freeze +38 fs/fuse/dev.c
32 condition); \
33 else \
34 __ret = wait_event_interruptible(wq, \
35 condition); \
36 if (!__ret || fatal_signal_pending(current)) \
37 break; \
> 38 } while (try_to_freeze()); \
39 __ret; \
40 })
41
---
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: 37906 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}().
@ 2016-12-05 3:19 cuilifei
2016-12-06 22:15 ` Rafael J. Wysocki
0 siblings, 1 reply; 10+ messages in thread
From: cuilifei @ 2016-12-05 3:19 UTC (permalink / raw)
To: linux-kernel
Cc: miklos, rjw, pavel, len.brown, linux-fsdevel, viro, piaoyingmin,
liucai, cuilifei
Freezing process can abort when a client is waiting uninterruptibly
for a response. Add new macro wait_fatal_freezable to try to fix it.
Signed-off-by: cuilifei <cuilifei@xiaomi.com>
---
fs/fuse/dev.c | 30 ++++++++++++++++++++++++++----
include/linux/freezer.h | 26 ++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 70ea57c..e33a081 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -19,6 +19,7 @@
#include <linux/pipe_fs_i.h>
#include <linux/swap.h>
#include <linux/splice.h>
+#include <linux/freezer.h>
MODULE_ALIAS_MISCDEV(FUSE_MINOR);
MODULE_ALIAS("devname:fuse");
@@ -99,6 +100,19 @@ void fuse_request_free(struct fuse_req *req)
kmem_cache_free(fuse_req_cachep, req);
}
+static void block_sigs(sigset_t *oldset)
+{
+ sigset_t mask;
+
+ siginitsetinv(&mask, sigmask(SIGKILL));
+ sigprocmask(SIG_BLOCK, &mask, oldset);
+}
+
+static void restore_sigs(sigset_t *oldset)
+{
+ sigprocmask(SIG_SETMASK, oldset, NULL);
+}
+
void __fuse_get_request(struct fuse_req *req)
{
atomic_inc(&req->count);
@@ -134,13 +148,18 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
bool for_background)
{
struct fuse_req *req;
+ sigset_t oldset;
+ int intr;
int err;
atomic_inc(&fc->num_waiting);
if (fuse_block_alloc(fc, for_background)) {
err = -EINTR;
- if (wait_event_killable_exclusive(fc->blocked_waitq,
- !fuse_block_alloc(fc, for_background)))
+ block_sigs(&oldset);
+ intr = wait_fatal_freezable(fc->blocked_waitq,
+ !fuse_block_alloc(fc, for_background), true);
+ restore_sigs(&oldset);
+ if (intr)
goto out;
}
/* Matches smp_wmb() in fuse_set_initialized() */
@@ -427,9 +446,12 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
}
if (!test_bit(FR_FORCE, &req->flags)) {
+ sigset_t oldset;
/* Only fatal signals may interrupt this */
- err = wait_event_killable(req->waitq,
- test_bit(FR_FINISHED, &req->flags));
+ block_sigs(&oldset);
+ err = wait_fatal_freezable(req->waitq,
+ test_bit(FR_FINISHED, &req->flags), false);
+ restore_sigs(&oldset);
if (!err)
return;
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index dd03e83..2504cd0 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -256,6 +256,22 @@ static inline int freezable_schedule_hrtimeout_range(ktime_t *expires,
__retval; \
})
+#define wait_fatal_freezable(wq, condition, exclusive) \
+({ \
+ int __ret = 0; \
+ do { \
+ if (exclusive) \
+ __ret = wait_event_interruptible_exclusive(wq, \
+ condition); \
+ else \
+ __ret = wait_event_interruptible(wq, \
+ condition); \
+ if (!__ret || fatal_signal_pending(current)) \
+ break; \
+ } while (try_to_freeze()); \
+ __ret; \
+})
+
#else /* !CONFIG_FREEZER */
static inline bool frozen(struct task_struct *p) { return false; }
static inline bool freezing(struct task_struct *p) { return false; }
@@ -296,6 +312,16 @@ static inline void set_freezable(void) {}
#define wait_event_freezekillable_unsafe(wq, condition) \
wait_event_killable(wq, condition)
+#define wait_fatal_freezable(wq, condition, exclusive) \
+({ \
+ int __ret = 0; \
+ if (exclusive) \
+ __ret = wait_event_killable_exclusive(wq, condition); \
+ else \
+ __ret = wait_event_killable(wq, condition); \
+ __ret; \
+})
+
#endif /* !CONFIG_FREEZER */
#endif /* FREEZER_H_INCLUDED */
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}().
2016-12-05 3:19 cuilifei
@ 2016-12-06 22:15 ` Rafael J. Wysocki
0 siblings, 0 replies; 10+ messages in thread
From: Rafael J. Wysocki @ 2016-12-06 22:15 UTC (permalink / raw)
To: cuilifei
Cc: linux-kernel, miklos, pavel, len.brown, linux-fsdevel, viro,
piaoyingmin, liucai, Jiri Kosina
On Monday, December 05, 2016 11:19:45 AM cuilifei wrote:
> Freezing process can abort when a client is waiting uninterruptibly
> for a response. Add new macro wait_fatal_freezable to try to fix it.
>
> Signed-off-by: cuilifei <cuilifei@xiaomi.com>
I'm not a big fan of this to be honest.
Do we really want to suspend the system (or freeze tasks for other reasons)
if that happens?
> ---
> fs/fuse/dev.c | 30 ++++++++++++++++++++++++++----
> include/linux/freezer.h | 26 ++++++++++++++++++++++++++
> 2 files changed, 52 insertions(+), 4 deletions(-)
>
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index 70ea57c..e33a081 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -19,6 +19,7 @@
> #include <linux/pipe_fs_i.h>
> #include <linux/swap.h>
> #include <linux/splice.h>
> +#include <linux/freezer.h>
>
> MODULE_ALIAS_MISCDEV(FUSE_MINOR);
> MODULE_ALIAS("devname:fuse");
> @@ -99,6 +100,19 @@ void fuse_request_free(struct fuse_req *req)
> kmem_cache_free(fuse_req_cachep, req);
> }
>
> +static void block_sigs(sigset_t *oldset)
> +{
> + sigset_t mask;
> +
> + siginitsetinv(&mask, sigmask(SIGKILL));
> + sigprocmask(SIG_BLOCK, &mask, oldset);
> +}
> +
> +static void restore_sigs(sigset_t *oldset)
> +{
> + sigprocmask(SIG_SETMASK, oldset, NULL);
> +}
> +
> void __fuse_get_request(struct fuse_req *req)
> {
> atomic_inc(&req->count);
> @@ -134,13 +148,18 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
> bool for_background)
> {
> struct fuse_req *req;
> + sigset_t oldset;
> + int intr;
> int err;
> atomic_inc(&fc->num_waiting);
>
> if (fuse_block_alloc(fc, for_background)) {
> err = -EINTR;
> - if (wait_event_killable_exclusive(fc->blocked_waitq,
> - !fuse_block_alloc(fc, for_background)))
> + block_sigs(&oldset);
> + intr = wait_fatal_freezable(fc->blocked_waitq,
> + !fuse_block_alloc(fc, for_background), true);
> + restore_sigs(&oldset);
> + if (intr)
> goto out;
> }
> /* Matches smp_wmb() in fuse_set_initialized() */
> @@ -427,9 +446,12 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
> }
>
> if (!test_bit(FR_FORCE, &req->flags)) {
> + sigset_t oldset;
> /* Only fatal signals may interrupt this */
> - err = wait_event_killable(req->waitq,
> - test_bit(FR_FINISHED, &req->flags));
> + block_sigs(&oldset);
> + err = wait_fatal_freezable(req->waitq,
> + test_bit(FR_FINISHED, &req->flags), false);
> + restore_sigs(&oldset);
> if (!err)
> return;
>
> diff --git a/include/linux/freezer.h b/include/linux/freezer.h
> index dd03e83..2504cd0 100644
> --- a/include/linux/freezer.h
> +++ b/include/linux/freezer.h
> @@ -256,6 +256,22 @@ static inline int freezable_schedule_hrtimeout_range(ktime_t *expires,
> __retval; \
> })
>
> +#define wait_fatal_freezable(wq, condition, exclusive) \
> +({ \
> + int __ret = 0; \
> + do { \
> + if (exclusive) \
> + __ret = wait_event_interruptible_exclusive(wq, \
> + condition); \
> + else \
> + __ret = wait_event_interruptible(wq, \
> + condition); \
> + if (!__ret || fatal_signal_pending(current)) \
> + break; \
> + } while (try_to_freeze()); \
> + __ret; \
> +})
> +
> #else /* !CONFIG_FREEZER */
> static inline bool frozen(struct task_struct *p) { return false; }
> static inline bool freezing(struct task_struct *p) { return false; }
> @@ -296,6 +312,16 @@ static inline void set_freezable(void) {}
> #define wait_event_freezekillable_unsafe(wq, condition) \
> wait_event_killable(wq, condition)
>
> +#define wait_fatal_freezable(wq, condition, exclusive) \
> +({ \
> + int __ret = 0; \
> + if (exclusive) \
> + __ret = wait_event_killable_exclusive(wq, condition); \
> + else \
> + __ret = wait_event_killable(wq, condition); \
> + __ret; \
> +})
> +
> #endif /* !CONFIG_FREEZER */
>
> #endif /* FREEZER_H_INCLUDED */
>
Thanks,
Rafael
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2016-12-06 22:19 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-01 5:37 [PATCH] fuse: freezing abort when use wait_event_killable{,_exclusive}() cuilifei
2016-12-02 14:42 ` kbuild test robot
2016-12-02 14:51 ` kbuild test robot
2016-12-01 5:43 cuilifei
2016-12-02 16:16 ` kbuild test robot
2016-12-02 18:42 ` kbuild test robot
2016-12-02 7:26 cuilifei
2016-12-03 8:54 ` kbuild test robot
2016-12-05 3:19 cuilifei
2016-12-06 22:15 ` Rafael J. Wysocki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).