From cd68a084fce98e78e1fc56c232e714da8263a4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= Date: Fri, 14 Aug 2020 11:57:02 +0200 Subject: [PATCH] Recovered space when an index root is shortened In rare situations, removing an entry from an index root while rebalancing the index tree, its space was not recovered from the index root, causing chkdsk to complain. Truncate the index root when this happens. --- libntfs-3g/index.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/libntfs-3g/index.c b/libntfs-3g/index.c index 58568ded..6fc79d5d 100644 --- a/libntfs-3g/index.c +++ b/libntfs-3g/index.c @@ -5,7 +5,7 @@ * Copyright (c) 2004-2005 Richard Russon * Copyright (c) 2005-2006 Yura Pakhuchiy * Copyright (c) 2005-2008 Szabolcs Szakacsits - * Copyright (c) 2007 Jean-Pierre Andre + * Copyright (c) 2007-2020 Jean-Pierre Andre * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -1563,19 +1563,32 @@ static int ntfs_ih_takeout(ntfs_index_context *icx, INDEX_HEADER *ih, INDEX_ENTRY *ie, INDEX_BLOCK *ib) { INDEX_ENTRY *ie_roam; + int freed_space; + BOOL full; int ret = STATUS_ERROR; ntfs_log_trace("Entering\n"); + full = ih->index_length == ih->allocated_size; ie_roam = ntfs_ie_dup_novcn(ie); if (!ie_roam) return STATUS_ERROR; ntfs_ie_delete(ih, ie); - if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) + if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) { + /* + * Recover the space which may have been freed + * while deleting an entry from root index + */ + freed_space = le32_to_cpu(ih->allocated_size) + - le32_to_cpu(ih->index_length); + if (full && (freed_space > 0) && !(freed_space & 7)) { + ntfs_ir_truncate(icx, cpu_to_le32(ih->index_length)); + /* do nothing if truncation fails */ + } ntfs_inode_mark_dirty(icx->actx->ntfs_ino); - else + } else if (ntfs_ib_write(icx, ib)) goto out;