From 3bcc223bfddbb3873d317a21548dc452a3caf8a9 Mon Sep 17 00:00:00 2001 From: "cantab.net!aia21" Date: Sun, 29 Dec 2002 21:37:21 +0000 Subject: [PATCH] Change ntfs_inode_close() to disconnect extent inodes from their base inode when an extent inode is closed. This is needed byt ntfs_mft_record_free() in order to be able to free extent mft records. (Logical change 1.74) --- libntfs/inode.c | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/libntfs/inode.c b/libntfs/inode.c index 5108a556..056279f0 100644 --- a/libntfs/inode.c +++ b/libntfs/inode.c @@ -122,7 +122,8 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref) ctx = ntfs_attr_get_search_ctx(ni, NULL); if (!ctx) goto err_out; - if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { + if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0, + ctx)) { if (errno != ENOENT) goto put_err_out; /* Attribute list attribute not present so we are done. */ @@ -184,10 +185,8 @@ err_out: * then deallocate all memory attached to it, and finally free the ntfs inode * structure itself. * - * If it is an extent inode, we postpone to when the base inode is being closed - * with ntfs_inode_close() to tear down all structures and free all allocated - * memory. That way we keep the extent records cached in memory so we get an - * efficient ntfs_lookup_attr(). + * If it is an extent inode, we disconnect it from its base inode before we + * destroy it. * * Return 0 on success or -1 on error with errno set to the error code. On * error, @ni has not been freed. The user should attempt to handle the error @@ -200,13 +199,6 @@ err_out: */ int ntfs_inode_close(ntfs_inode *ni) { - /* If the inode is an extent inode, complain rudely! */ - if (ni->nr_extents == -1) { - Dprintf("%s(): BUG: Tried to close extent inode!\n", - __FUNCTION__); - errno = EINVAL; - return -1; - } /* If we have dirty metadata, write it out. */ if (NInoDirty(ni) || NInoAttrListDirty(ni)) { if (ntfs_inode_sync(ni)) { @@ -223,6 +215,37 @@ int ntfs_inode_close(ntfs_inode *ni) for (i = 0; i < ni->nr_extents; i++) __ntfs_inode_release(ni->extent_nis[i]); free(ni->extent_nis); + } else if (ni->nr_extents == -1) { + ntfs_inode **tmp_nis; + ntfs_inode *base_ni; + s32 i; + + /* + * If the inode is an extent inode, disconnect it from the + * base inode before destroying it. + */ + base_ni = ni->base_ni; + for (i = 0; i < base_ni->nr_extents; ++i) { + tmp_nis = base_ni->extent_nis; + if (tmp_nis[i] != ni) + continue; + /* Found it. Disconnect. */ + memmove(tmp_nis + i, tmp_nis + i + 1, + (base_ni->nr_extents - i - 1) * + sizeof(ntfs_inode *)); + base_ni->nr_extents--; + /* Resize the memory buffer. */ + tmp_nis = realloc(tmp_nis, base_ni->nr_extents * + sizeof(ntfs_inode *)); + /* Ignore errors, they don't really matter. */ + if (tmp_nis) + base_ni->extent_nis = tmp_nis; + /* Allow for error checking. */ + i = -1; + } + if (i != -1) + Dputs("Extent inode was not attached to base inode! " + "Weird! Continuing regardless."); } return __ntfs_inode_release(ni); }