From patchwork Wed Feb 28 11:18:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kara X-Patchwork-Id: 10247293 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 6F88460211 for ; Wed, 28 Feb 2018 11:19:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6202728BAD for ; Wed, 28 Feb 2018 11:19:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 55CBD28CAA; Wed, 28 Feb 2018 11:19:24 +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=-1.9 required=2.0 tests=BAYES_00 autolearn=ham version=3.3.1 Received: from aserp2120.oracle.com (aserp2120.oracle.com [141.146.126.78]) (using TLSv1.2 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id AB0D928BAD for ; Wed, 28 Feb 2018 11:19:23 +0000 (UTC) Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.22/8.16.0.22) with SMTP id w1SBHT0i189589; Wed, 28 Feb 2018 11:18:44 GMT Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp2120.oracle.com with ESMTP id 2gdqju919b-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 28 Feb 2018 11:18:44 +0000 Received: from oss.oracle.com (oss-old-reserved.oracle.com [137.254.22.2]) by aserv0022.oracle.com (8.14.4/8.14.4) with ESMTP id w1SBIgSY023678 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 28 Feb 2018 11:18:44 GMT Received: from localhost ([127.0.0.1] helo=lb-oss.oracle.com) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1eqzkw-0000ic-UH; Wed, 28 Feb 2018 03:18:42 -0800 Received: from userv0022.oracle.com ([156.151.31.74]) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1eqzkY-0000fy-Ur for ocfs2-devel@oss.oracle.com; Wed, 28 Feb 2018 03:18:19 -0800 Received: from userp2040.oracle.com (userp2040.oracle.com [156.151.31.90]) by userv0022.oracle.com (8.14.4/8.14.4) with ESMTP id w1SBIIAI018050 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=FAIL) for ; Wed, 28 Feb 2018 11:18:18 GMT Received: from pps.filterd (userp2040.oracle.com [127.0.0.1]) by userp2040.oracle.com (8.16.0.22/8.16.0.22) with SMTP id w1SBHATr008201 for ; Wed, 28 Feb 2018 11:18:18 GMT Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by userp2040.oracle.com with ESMTP id 2gdtur8hy2-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 28 Feb 2018 11:18:18 +0000 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id CD460ADB9; Wed, 28 Feb 2018 11:18:10 +0000 (UTC) Received: by quack2.suse.cz (Postfix, from userid 1000) id 9FE371E0506; Wed, 28 Feb 2018 12:18:09 +0100 (CET) From: Jan Kara To: ocfs2-devel@oss.oracle.com Date: Wed, 28 Feb 2018 12:18:01 +0100 Message-Id: <20180228111802.23967-6-jack@suse.cz> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180228111802.23967-1-jack@suse.cz> References: <20180228111802.23967-1-jack@suse.cz> X-CLX-Shades: MLX X-CLX-Response: 1TFkXGBkSEQpMehcZGhEKWU0XZ2ZyEQpZSRcacRoQGncGGBsScRsfGxAadwY YGgYaEQpZXhdoY3kRCklGF0VYS0lGT3VaWEVOX0leQ0VEGXVPSxEKQ04XQXMHQm5ZS30fenBdWX haenpwfGUHe2h1e01rQEISeh0RClhcFx8EGgQbGBwHS0sYGB8eTxkFGxoEGxoaBB4SBB8QGx4aH xoRCl5ZF3hQbnl8EQpNXBcfGRkRCkxaF2lCTV0RCkxGF2xraxEKQ1oXGxMfBBsZHwQYGBoEGx8R CkJeFxsRCkRJFx8RCkJGF2Ncf11kG2x5ZH9hEQpCXBcaEQpCRRdgAWF7W1p7QAFibREKQk4XZRp 4GwUFcHN7U1kRCkJMF21keGJ8T3thQ19fEQpCbBdpfhh8QF9IHE5rUhEKQkAXYBJLTk9eTUEYYU sRCkJYF2J9b3kBTxgZcHB7EQpwaBdveB5OElxBWExwXhAaEQpwaBdma3tiT0VETXprEhAaEQpwa BdtfVhoZmtnYUxfRBAaEQpwaBdra2ZeUx9hYBhoGxAaEQpwaBdmWl9CX0NYR2VyGhAaEQpwbBdi QFptUEFDY3BfbRAZGhEKbX4XGhEKWE0XSxEg X-PDR: PASS X-Source-IP: 195.135.220.15 X-ServerName: mx2.suse.de X-Proofpoint-SPF-Result: pass X-Proofpoint-SPF-Record: v=spf1 ip4:137.65.0.0/16 ip4:151.155.28.0/17 ip4:149.44.0.0/16 ip4:147.2.0.0/16 ip4:164.99.0.0/16 ip4:130.57.0.0/16 ip4:192.31.114.0/24 ip4:195.135.221.0/24 ip4:195.135.220.0/24 ip4:69.7.179.0/24 ip4:150.215.214.0/24 include:mailcontrol.com ~all X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=8817 signatures=668681 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=30 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=238 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1711220000 definitions=main-1802280137 X-Spam: Clean Cc: Jan Kara Subject: [Ocfs2-devel] [PATCH 5/6] ocfs2: Fix quota recovery for read-only mounts X-BeenThere: ocfs2-devel@oss.oracle.com X-Mailman-Version: 2.1.9 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ocfs2-devel-bounces@oss.oracle.com Errors-To: ocfs2-devel-bounces@oss.oracle.com X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=8817 signatures=668681 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=1 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1711220000 definitions=main-1802280137 X-Virus-Scanned: ClamAV using ClamSMTP Currently quotas are either disabled or suspended when the filesystem is mounted read only. This results in quota recovery failing when in happens on such mount and as a result quota accounting is wrong. Fix the problem by enabling quotas even for read-only mounts. We just don't start periodic flushing of our local changes to the global quota file since that is pointless for read-only mounts. Signed-off-by: Jan Kara --- fs/ocfs2/super.c | 99 +++++++++++++++++++++++++------------------------------- 1 file changed, 44 insertions(+), 55 deletions(-) diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 39b62569e7ff..af4481b98c65 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -135,7 +135,8 @@ static int ocfs2_get_sector(struct super_block *sb, int sect_size); static struct inode *ocfs2_alloc_inode(struct super_block *sb); static void ocfs2_destroy_inode(struct inode *inode); -static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend); +static void ocfs2_enable_quota_sync(struct ocfs2_super *osb); +static void ocfs2_disable_quota_sync(struct ocfs2_super *osb); static int ocfs2_enable_quotas(struct ocfs2_super *osb); static void ocfs2_disable_quotas(struct ocfs2_super *osb); @@ -675,12 +676,9 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) /* We're going to/from readonly mode. */ if ((bool)(*flags & SB_RDONLY) != sb_rdonly(sb)) { - /* Disable quota accounting before remounting RO */ - if (*flags & SB_RDONLY) { - ret = ocfs2_susp_quotas(osb, 0); - if (ret < 0) - goto out; - } + /* Disable quota syncing before remounting RO */ + if (*flags & SB_RDONLY) + ocfs2_disable_quota_sync(osb); /* Lock here so the check of HARD_RO and the potential * setting of SOFT_RO is atomic. */ spin_lock(&osb->osb_lock); @@ -714,21 +712,9 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) trace_ocfs2_remount(sb->s_flags, osb->osb_flags, *flags); unlock_osb: spin_unlock(&osb->osb_lock); - /* Enable quota accounting after remounting RW */ - if (!ret && !(*flags & SB_RDONLY)) { - if (sb_any_quota_suspended(sb)) - ret = ocfs2_susp_quotas(osb, 1); - else - ret = ocfs2_enable_quotas(osb); - if (ret < 0) { - /* Return back changes... */ - spin_lock(&osb->osb_lock); - sb->s_flags |= SB_RDONLY; - osb->osb_flags |= OCFS2_OSB_SOFT_RO; - spin_unlock(&osb->osb_lock); - goto out; - } - } + /* Enable quota syncing after remounting RW */ + if (!ret && !(*flags & SB_RDONLY)) + ocfs2_enable_quota_sync(osb); } if (!ret) { @@ -902,38 +888,33 @@ static int ocfs2_verify_userspace_stack(struct ocfs2_super *osb, return 0; } -static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend) +static void ocfs2_enable_quota_sync(struct ocfs2_super *osb) { int type; struct super_block *sb = osb->sb; - unsigned int feature[OCFS2_MAXQUOTAS] = { - OCFS2_FEATURE_RO_COMPAT_USRQUOTA, - OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; - int status = 0; struct ocfs2_mem_dqinfo *oinfo; for (type = 0; type < OCFS2_MAXQUOTAS; type++) { - if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) + if (!sb_has_quota_active(sb, type)) continue; oinfo = sb_dqinfo(sb, type)->dqi_priv; - if (unsuspend) { - status = dquot_resume(sb, type); - if (status < 0) - break; - schedule_delayed_work(&oinfo->dqi_sync_work, - msecs_to_jiffies(oinfo->dqi_syncms)); - } else { - /* Cancel periodic syncing before suspending */ - cancel_delayed_work_sync(&oinfo->dqi_sync_work); - status = dquot_suspend(sb, type); - if (status < 0) - break; - } + schedule_delayed_work(&oinfo->dqi_sync_work, + msecs_to_jiffies(oinfo->dqi_syncms)); + } +} + +static void ocfs2_disable_quota_sync(struct ocfs2_super *osb) +{ + int type; + struct super_block *sb = osb->sb; + struct ocfs2_mem_dqinfo *oinfo; + + for (type = 0; type < OCFS2_MAXQUOTAS; type++) { + if (!sb_has_quota_active(sb, type)) + continue; + oinfo = sb_dqinfo(sb, type)->dqi_priv; + cancel_delayed_work_sync(&oinfo->dqi_sync_work); } - if (status < 0) - mlog(ML_ERROR, "Failed to suspend/unsuspend quotas on " - "remount (error = %d).\n", status); - return status; } static int ocfs2_enable_quotas(struct ocfs2_super *osb) @@ -946,11 +927,18 @@ static int ocfs2_enable_quotas(struct ocfs2_super *osb) unsigned int ino[OCFS2_MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE, LOCAL_GROUP_QUOTA_SYSTEM_INODE }; - struct ocfs2_mem_dqinfo *oinfo; int status; int type; + bool ro; sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NEGATIVE_USAGE; + /* + * We temporarily switch sb to read-write to allow quota setup to pass + * cleanly + */ + ro = sb_rdonly(sb); + if (ro) + sb->s_flags &= ~SB_RDONLY; for (type = 0; type < OCFS2_MAXQUOTAS; type++) { if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) continue; @@ -964,16 +952,19 @@ static int ocfs2_enable_quotas(struct ocfs2_super *osb) DQUOT_USAGE_ENABLED); if (status < 0) goto out_quota_off; - oinfo = sb_dqinfo(sb, type)->dqi_priv; - schedule_delayed_work(&oinfo->dqi_sync_work, - msecs_to_jiffies(oinfo->dqi_syncms)); } + if (!ro) + ocfs2_enable_quota_sync(osb); + else + sb->s_flags |= SB_RDONLY; for (type = 0; type < OCFS2_MAXQUOTAS; type++) iput(inode[type]); return 0; out_quota_off: ocfs2_disable_quotas(osb); + if (ro) + sb->s_flags |= SB_RDONLY; for (type = 0; type < OCFS2_MAXQUOTAS; type++) iput(inode[type]); mlog_errno(status); @@ -985,15 +976,13 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb) int type; struct inode *inode; struct super_block *sb = osb->sb; - struct ocfs2_mem_dqinfo *oinfo; /* We mostly ignore errors in this function because there's not much * we can do when we see them */ + ocfs2_disable_quota_sync(osb); for (type = 0; type < OCFS2_MAXQUOTAS; type++) { if (!sb_has_quota_loaded(sb, type)) continue; - oinfo = sb_dqinfo(sb, type)->dqi_priv; - cancel_delayed_work_sync(&oinfo->dqi_sync_work); inode = igrab(sb->s_dquot.files[type]); /* Turn off quotas. This will remove all dquot structures from * memory and so they will be automatically synced to global @@ -1185,7 +1174,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) /* Now we can initialize quotas because we can afford to wait * for cluster locks recovery now. That also means that truncation * log recovery can happen but that waits for proper quota setup */ - if (!sb_rdonly(sb)) { + if (!ocfs2_is_hard_readonly(osb)) { status = ocfs2_enable_quotas(osb); if (status < 0) { /* We have to err-out specially here because @@ -1195,9 +1184,9 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) wake_up(&osb->osb_mount_event); return status; } - } - ocfs2_complete_quota_recovery(osb); + ocfs2_complete_quota_recovery(osb); + } /* Now we wake up again for processes waiting for quotas */ atomic_set(&osb->vol_state, VOLUME_MOUNTED_QUOTAS);