From patchwork Mon Dec 5 03:19:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: cuilifei X-Patchwork-Id: 9460253 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 022406071C for ; Mon, 5 Dec 2016 03:35:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ED9B32094F for ; Mon, 5 Dec 2016 03:35:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E0F3B209CD; Mon, 5 Dec 2016 03:35:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5FF7D2094F for ; Mon, 5 Dec 2016 03:35:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751364AbcLEDfX (ORCPT ); Sun, 4 Dec 2016 22:35:23 -0500 Received: from outboundhk.mxmail.xiaomi.com ([207.226.244.122]:25532 "EHLO xiaomi.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751261AbcLEDfV (ORCPT ); Sun, 4 Dec 2016 22:35:21 -0500 X-Greylist: delayed 937 seconds by postgrey-1.27 at vger.kernel.org; Sun, 04 Dec 2016 22:35:21 EST Received: from CNBOX4.mioffice.cn (10.237.8.144) by hkbox2.mioffice.cn (10.56.8.142) with Microsoft SMTP Server (TLS) id 15.0.1104.5; Mon, 5 Dec 2016 11:18:07 +0800 Received: from localhost (10.237.10.122) by cnbox4.mioffice.cn (10.237.8.144) with Microsoft SMTP Server (TLS) id 15.0.1104.5; Mon, 5 Dec 2016 11:18:07 +0800 From: cuilifei To: CC: , , , , , , , , cuilifei Subject: [PATCH] fuse: freezing abort when use wait_event_killable{, _exclusive}(). Date: Mon, 5 Dec 2016 11:19:45 +0800 Message-ID: <1480907985-1494-1-git-send-email-cuilifei@xiaomi.com> X-Mailer: git-send-email 1.9.1 MIME-Version: 1.0 X-Originating-IP: [10.237.10.122] X-ClientProxiedBy: CNCAS3.mioffice.cn (10.237.8.133) To cnbox4.mioffice.cn (10.237.8.144) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 #include #include +#include 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 */