Commit c4a9d189 authored by Bob Peterson's avatar Bob Peterson

GFS2: Fix non-recursive truncate bug

Before this patch if you truncated a file to a smaller size it
wasn't freeing all the blocks properly. There are two reasons.

First, the metapath comparison was not comparing previous heights.
I added a function, mp_eq_to_hgt, which checks the metapath at
all heights prior to the target height.

Second, in function find_nonnull_ptr, it needed to zero out all
pointers for heights following the target height. Translated into
decimal integer terms, this way a number like 299, when incremented,
becomes 300, not 399. The 2 gets incremented to 3, and the following
digits need to be reset.

These two things allow the truncate state machine to properly find
the blocks it needs to delete.
Signed-off-by: default avatarBob Peterson <rpeterso@redhat.com>
parent d296b15e
...@@ -1104,8 +1104,15 @@ static bool find_nonnull_ptr(struct gfs2_sbd *sdp, struct metapath *mp, ...@@ -1104,8 +1104,15 @@ static bool find_nonnull_ptr(struct gfs2_sbd *sdp, struct metapath *mp,
while (true) { while (true) {
ptr = metapointer(h, mp); ptr = metapointer(h, mp);
if (*ptr) /* if we have a non-null pointer */ if (*ptr) { /* if we have a non-null pointer */
/* Now zero the metapath after the current height. */
h++;
if (h < GFS2_MAX_META_HEIGHT)
memset(&mp->mp_list[h], 0,
(GFS2_MAX_META_HEIGHT - h) *
sizeof(mp->mp_list[0]));
return true; return true;
}
if (mp->mp_list[h] < ptrs) if (mp->mp_list[h] < ptrs)
mp->mp_list[h]++; mp->mp_list[h]++;
...@@ -1121,6 +1128,13 @@ enum dealloc_states { ...@@ -1121,6 +1128,13 @@ enum dealloc_states {
DEALLOC_DONE = 3, /* process complete */ DEALLOC_DONE = 3, /* process complete */
}; };
static bool mp_eq_to_hgt(struct metapath *mp, __u16 *nbof, unsigned int h)
{
if (memcmp(mp->mp_list, nbof, h * sizeof(mp->mp_list[0])))
return false;
return true;
}
/** /**
* trunc_dealloc - truncate a file down to a desired size * trunc_dealloc - truncate a file down to a desired size
* @ip: inode to truncate * @ip: inode to truncate
...@@ -1198,8 +1212,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 newsize) ...@@ -1198,8 +1212,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 newsize)
/* If we're truncating to a non-zero size and the mp is /* If we're truncating to a non-zero size and the mp is
at the beginning of file for the strip height, we at the beginning of file for the strip height, we
need to preserve the first metadata pointer. */ need to preserve the first metadata pointer. */
preserve1 = (newsize && preserve1 = (newsize && mp_eq_to_hgt(&mp, nbof, mp_h));
(mp.mp_list[mp_h] == nbof[mp_h]));
bh = mp.mp_bh[mp_h]; bh = mp.mp_bh[mp_h];
gfs2_assert_withdraw(sdp, bh); gfs2_assert_withdraw(sdp, bh);
if (gfs2_assert_withdraw(sdp, if (gfs2_assert_withdraw(sdp,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment