From patchwork Tue Oct 17 09:13:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10011395 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 7FA7560211 for ; Tue, 17 Oct 2017 09:13:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7506A28817 for ; Tue, 17 Oct 2017 09:13:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6A1052881B; Tue, 17 Oct 2017 09:13:32 +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=ham 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 CE81B28818 for ; Tue, 17 Oct 2017 09:13:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934675AbdJQJN2 (ORCPT ); Tue, 17 Oct 2017 05:13:28 -0400 Received: from victor.provo.novell.com ([137.65.250.26]:34517 "EHLO prv3-mh.provo.novell.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934664AbdJQJNU (ORCPT ); Tue, 17 Oct 2017 05:13:20 -0400 Received: from adam-pc.lan (prv-ext-foundry1int.gns.novell.com [137.65.251.240]) by prv3-mh.provo.novell.com with ESMTP (NOT encrypted); Tue, 17 Oct 2017 03:13:16 -0600 From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: dsterba@suse.cz Subject: [PATCH v2 1/6] btrfs-progs: Introduce function to fix unaligned device size Date: Tue, 17 Oct 2017 17:13:07 +0800 Message-Id: <20171017091312.31045-2-wqu@suse.com> X-Mailer: git-send-email 2.14.2 In-Reply-To: <20171017091312.31045-1-wqu@suse.com> References: <20171017091312.31045-1-wqu@suse.com> Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Recent kernel introduced alignment check for dev item, however older kernel doesn't align device size when adding new device or shrinking existing device. This makes noisy kernel warning every time when any DEV_ITEM get updated. Introduce function to fix device size in btrfs-progs to fix the problem offline. Reported-by: Asif Youssuff Reported-by: Rich Rauenzahn Signed-off-by: Qu Wenruo --- volumes.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ volumes.h | 2 ++ 2 files changed, 73 insertions(+) diff --git a/volumes.c b/volumes.c index 2209e5a9100b..5462bf71c611 100644 --- a/volumes.c +++ b/volumes.c @@ -2332,3 +2332,74 @@ u64 btrfs_stripe_length(struct btrfs_fs_info *fs_info, } return stripe_len; } + +/* + * Return 0 if size of @device is already good + * Return >0 if size of @device is not aligned but fixed without problem + * Return <0 if something wrong happened when aligning the size of @device + */ +int btrfs_fix_device_size(struct btrfs_fs_info *fs_info, + struct btrfs_device *device) +{ + struct btrfs_trans_handle *trans; + struct btrfs_key key; + struct btrfs_path path; + struct btrfs_root *chunk_root = fs_info->chunk_root; + struct btrfs_dev_item *di; + u64 old_bytes = device->total_bytes; + int ret; + + if (IS_ALIGNED(old_bytes, fs_info->sectorsize)) + return 0; + + /* Align the in-memory total_bytes first, and use it as correct size */ + device->total_bytes = round_down(device->total_bytes, + fs_info->sectorsize); + + key.objectid = BTRFS_DEV_ITEMS_OBJECTID; + key.type = BTRFS_DEV_ITEM_KEY; + key.offset = device->devid; + + trans = btrfs_start_transaction(chunk_root, 1); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + error("error starting transaction: %d (%s)", + ret, strerror(-ret)); + return ret; + } + + btrfs_init_path(&path); + ret = btrfs_search_slot(trans, chunk_root, &key, &path, 0, 1); + if (ret > 0) { + error("failed to find DEV_ITEM for devid %llu", + device->devid); + ret = -ENOENT; + goto err; + } + if (ret < 0) { + error("failed to search chunk root: %d (%s)", + ret, strerror(-ret)); + goto err; + } + di = btrfs_item_ptr(path.nodes[0], path.slots[0], + struct btrfs_dev_item); + btrfs_set_device_total_bytes(path.nodes[0], di, device->total_bytes); + btrfs_mark_buffer_dirty(path.nodes[0]); + ret = btrfs_commit_transaction(trans, chunk_root); + if (ret < 0) { + error("failed to commit current transaction: %d (%s)", + ret, strerror(-ret)); + btrfs_release_path(&path); + return ret; + } + btrfs_release_path(&path); + printf("Fixed device size for devid %llu, old size: %llu new size: %llu\n", + device->devid, old_bytes, device->total_bytes); + return 1; + +err: + /* We haven't modified anything, it's OK to commit current trans */ + btrfs_commit_transaction(trans, chunk_root); + btrfs_release_path(&path); + return ret; +} diff --git a/volumes.h b/volumes.h index d35a4e652b0d..89bd4aa81ae0 100644 --- a/volumes.h +++ b/volumes.h @@ -245,4 +245,6 @@ int btrfs_check_chunk_valid(struct btrfs_fs_info *fs_info, u64 btrfs_stripe_length(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf, struct btrfs_chunk *chunk); +int btrfs_fix_device_size(struct btrfs_fs_info *fs_info, + struct btrfs_device *device); #endif