Changes by: cha0smaster
Update of /cvsroot/linux-ntfs/ntfsprogs/libntfs
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15050/libntfs
Modified Files:
attrib.c collate.c index.c inode.c
Log Message:
- Implement FILE_NAME attributes update in index during inode sync and enable code that set/clean sparse bit. Also add new inode state bit FileNameDirty to indicate that FILE_NAME attributes need update. At least after attribute resize we leave absolutely consist volume.
- Bugfixes to collate.c and index.c.
- Minor formating fixed to ntfscp and ntfsinfo.
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfsprogs/libntfs/attrib.c,v
retrieving revision 1.157
retrieving revision 1.158
diff -u -p -r1.157 -r1.158
--- attrib.c 17 Feb 2005 18:01:56 -0000 1.157
+++ attrib.c 5 Jun 2005 14:55:09 -0000 1.158
@@ -3976,12 +3976,6 @@ static int ntfs_attr_make_resident(ntfs_
* function updates sparse bit and allocates/frees space for compressed_size,
* but doesn't change it, so caller should update it manually.
*
- * NOTE: Code that set/clean sparse bit currently disabled, because chkdsk
- * complain if we don't update index entry's for inode to which we set sparse
- * bit. But it doesn't if attribute's runlist has lcn holes and sparse bit
- * isn't set. So until we have no API for updating index entries it's the best
- * choice.
- *
* On success return 0 and on error return -1 with errno set to the error code.
* The following error codes are defined:
* ENOMEM - Not enough memory to complete operation.
@@ -4064,7 +4058,6 @@ retry:
goto put_err_out;
}
}
-#if 0
/* If we in the first extent, then set/clean sparse bit. */
if (!a->lowest_vcn) {
int sparse;
@@ -4130,6 +4123,13 @@ retry:
a->mapping_pairs_offset =
cpu_to_le16(le16_to_cpu(
a->mapping_pairs_offset) + 8);
+ /*
+ * Set FILE_NAME dirty flag, to update
+ * sparse bit in the index.
+ */
+ if (na->type == AT_DATA &&
+ na->name == AT_UNNAMED)
+ NInoFileNameSetDirty(na->ni);
}
if (!sparse && (a->flags & ATTR_IS_SPARSE) &&
!(a->flags & ATTR_IS_COMPRESSED)) {
@@ -4144,9 +4144,15 @@ retry:
a->mapping_pairs_offset =
cpu_to_le16(le16_to_cpu(
a->mapping_pairs_offset) - 8);
+ /*
+ * Set FILE_NAME dirty flag, to update
+ * sparse bit in the index.
+ */
+ if (na->type == AT_DATA &&
+ na->name == AT_UNNAMED)
+ NInoFileNameSetDirty(na->ni);
}
}
-#endif
/* Get the size for the rest of mapping pairs array. */
mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, na->rl,
stop_vcn);
@@ -4811,6 +4817,8 @@ put_err_out:
*/
int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
{
+ int ret;
+
if (!na || newsize < 0 ||
(na->ni->mft_no == FILE_MFT && na->type == AT_DATA)) {
Dprintf("%s(): Invalid aruments passed.\n", __FUNCTION__);
@@ -4837,9 +4845,24 @@ int ntfs_attr_truncate(ntfs_attr *na, co
}
if (NAttrNonResident(na)) {
if (newsize > na->data_size)
- return ntfs_non_resident_attr_expand(na, newsize);
+ ret = ntfs_non_resident_attr_expand(na, newsize);
+ else
+ ret = ntfs_non_resident_attr_shrink(na, newsize);
+ } else
+ ret = ntfs_resident_attr_resize(na, newsize);
+ /* Set FILE_NAME dirty flag, to update file length in the index. */
+ if (na->type == AT_DATA && na->name == AT_UNNAMED) {
+ NInoFileNameSetDirty(na->ni);
+ na->ni->data_size = na->data_size;
+ /*
+ * If attribute sparse or commpreseed then allocated size in
+ * index should be euqal to compressed size, not to allocated
+ * size.
+ */
+ if (NAttrCompressed(na) || NAttrSparse(na))
+ na->ni->allocated_size = na->compressed_size;
else
- return ntfs_non_resident_attr_shrink(na, newsize);
+ na->ni->allocated_size = na->allocated_size;
}
- return ntfs_resident_attr_resize(na, newsize);
+ return ret;
}
Index: collate.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfsprogs/libntfs/collate.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -p -r1.2 -r1.3
--- collate.c 4 Jun 2005 15:20:00 -0000 1.2
+++ collate.c 5 Jun 2005 14:55:09 -0000 1.3
@@ -79,7 +79,7 @@ static int ntfs_collate_file_name(ntfs_v
fn2 = (const FILE_NAME_ATTR *)data2;
rc = ntfs_names_collate(fn1->file_name, fn1->file_name_length,
fn2->file_name, fn2->file_name_length,
- NTFS_COLLATION_ERROR, CASE_SENSITIVE, vol->upcase,
+ NTFS_COLLATION_ERROR, IGNORE_CASE, vol->upcase,
vol->upcase_len);
ntfs_debug("Done, returning %i.", rc);
return rc;
Index: index.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfsprogs/libntfs/index.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -p -r1.2 -r1.3
--- index.c 4 Jun 2005 15:20:00 -0000 1.2
+++ index.c 5 Jun 2005 14:55:09 -0000 1.3
@@ -26,6 +26,7 @@
#include "collate.h"
#include "debug.h"
#include "index.h"
+#include "mst.h"
/**
* ntfs_index_ctx_get - allocate and initialize a new index context
@@ -71,14 +72,15 @@ void ntfs_index_ctx_put(ntfs_index_conte
ntfs_attr_put_search_ctx(ictx->actx);
} else {
/* Write out index block it it's dirty. */
- if (ictx->ia_dirty)
- if (ntfs_attr_pwrite(ictx->ia_na,
+ if (ictx->ia_dirty) {
+ if (ntfs_attr_mst_pwrite(ictx->ia_na,
ictx->ia_vcn <<
- ictx->ni->vol->cluster_size,
+ ictx->ni->vol->cluster_size, 1,
ictx->block_size, ictx->ia) !=
- ictx->block_size)
+ 1)
ntfs_error(, "Failed to write out "
"index block.");
+ }
/* Free resources. */
free(ictx->ia);
ntfs_attr_close(ictx->ia_na);
@@ -264,12 +266,13 @@ done:
goto err_out;
}
descend_into_child_node:
+ ntfs_debug("Descend into node with VCN %lld.", vcn);
/* Read index allocation block. */
- if (ntfs_attr_pread(na, vcn << vol->cluster_size_bits, ictx->block_size,
- ia) != ictx->block_size) {
+ if (ntfs_attr_mst_pread(na, vcn << vol->cluster_size_bits, 1,
+ ictx->block_size, ia) != 1) {
ntfs_error(, "Failed to read index allocation.");
goto err_out;
- }
+ }
/* Catch multi sector transfer fixup errors. */
if (!ntfs_is_indx_record(ia->magic)) {
ntfs_error(sb, "Index record with vcn 0x%llx is corrupt. "
@@ -392,3 +395,4 @@ idx_err_out:
ntfs_error(sb, "Corrupt index. Aborting lookup.");
goto err_out;
}
+
Index: inode.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfsprogs/libntfs/inode.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -p -r1.52 -r1.53
--- inode.c 27 Jan 2005 18:31:08 -0000 1.52
+++ inode.c 5 Jun 2005 14:55:09 -0000 1.53
@@ -36,6 +36,8 @@
#include "attrlist.h"
#include "runlist.h"
#include "lcnalloc.h"
+#include "index.h"
+#include "dir.h"
/**
* Internal:
@@ -123,6 +125,8 @@ ntfs_inode *ntfs_inode_open(ntfs_volume
if (!(ni->mrec->flags & MFT_RECORD_IN_USE))
goto err_out;
ni->mft_no = MREF(mref);
+ ni->data_size = -1;
+ ni->allocated_size = -1;
ctx = ntfs_attr_get_search_ctx(ni, NULL);
if (!ctx)
goto err_out;
@@ -454,6 +458,113 @@ static int ntfs_inode_sync_standard_info
}
/**
+ * ntfs_inode_sync_standard_information - update FILE_NAME attribute's
+ * @ni: ntfs inode to update FILE_NAME attribute's
+ *
+ * Update all FILE_NAME attribute's for inode @ni in the index.
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ */
+static int ntfs_inode_sync_file_name(ntfs_inode *ni) {
+ ntfs_attr_search_ctx *ctx = NULL;
+ ntfs_index_context *ictx;
+ ntfs_inode *index_ni;
+ FILE_NAME_ATTR *fn;
+ int err = 0;
+
+ ctx = ntfs_attr_get_search_ctx(ni, NULL);
+ if (!ctx) {
+ err = errno;
+ Dprintf("%s(): Failed to get attribute search context.\n",
+ __FUNCTION__);
+ goto err_out;
+ }
+ /* Walk through all FILE_NAME attributes and update them. */
+ while (!ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) {
+ fn = (FILE_NAME_ATTR *)((u8 *)ctx->attr +
+ le16_to_cpu(ctx->attr->value_offset));
+ if (MREF_LE(fn->parent_directory) == ni->mft_no) {
+ /*
+ * WARNING: We cheater here and obtain 2 attribute
+ * search contextes for one inode (first we obtained
+ * above, second will be obtained inside
+ * ntfs_index_lookup), it's acceptable for library,
+ * but will lock kernel.
+ */
+ index_ni = ni;
+ } else
+ index_ni = ntfs_inode_open(ni->vol,
+ le64_to_cpu(fn->parent_directory));
+ if (!index_ni) {
+ if (!err)
+ err = errno;
+ Dprintf("%s(): Failed to open inode with index.\n",
+ __FUNCTION__);
+ continue;
+ }
+ ictx = ntfs_index_ctx_get(index_ni, I30, 4);
+ if (!ictx) {
+ if (!err)
+ err = errno;
+ Dprintf("%s(): Failed to get index context.\n",
+ __FUNCTION__);
+ ntfs_inode_close(index_ni);
+ continue;
+ }
+ if (ntfs_index_lookup(fn, sizeof(FILE_NAME_ATTR), ictx)) {
+ if (!err) {
+ if (errno == ENOENT)
+ err = EIO;
+ else
+ err = errno;
+ }
+ Dprintf("%s(): Index lookup failed.\n", __FUNCTION__);
+ ntfs_index_ctx_put(ictx);
+ ntfs_inode_close(index_ni);
+ continue;
+ }
+ /* Update flags and file size. */
+ fn = (FILE_NAME_ATTR *)ictx->data;
+ if (NInoCompressed(ni))
+ fn->file_attributes |= FILE_ATTR_COMPRESSED;
+ else
+ fn->file_attributes &= ~FILE_ATTR_COMPRESSED;
+ if (NInoEncrypted(ni))
+ fn->file_attributes |= FILE_ATTR_ENCRYPTED;
+ else
+ fn->file_attributes &= ~FILE_ATTR_ENCRYPTED;
+ if (NInoSparse(ni))
+ fn->file_attributes |= FILE_ATTR_SPARSE_FILE;
+ else
+ fn->file_attributes &= ~FILE_ATTR_SPARSE_FILE;
+ if (ni->allocated_size != -1)
+ fn->allocated_size = cpu_to_sle64(ni->allocated_size);
+ if (ni->data_size != -1)
+ fn->data_size = cpu_to_sle64(ni->data_size);
+ ntfs_index_entry_mark_dirty(ictx);
+ ntfs_index_ctx_put(ictx);
+ ntfs_inode_close(index_ni);
+ }
+ /* Check for real error occured. */
+ if (errno != ENOENT) {
+ err = errno;
+ Dprintf("%s(): Attribute lookup failed.\n", __FUNCTION__);
+ goto err_out;
+ }
+ ntfs_attr_put_search_ctx(ctx);
+ if (err) {
+ errno = err;
+ return -1;
+ }
+ return 0;
+err_out:
+ if (ctx)
+ ntfs_attr_put_search_ctx(ctx);
+ errno = err;
+ return -1;
+}
+
+/**
* ntfs_inode_sync - write the inode (and its dirty extents) to disk
* @ni: ntfs inode to write
*
@@ -480,7 +591,7 @@ int ntfs_inode_sync(ntfs_inode *ni)
errno = EINVAL;
return -1;
}
-
+
Dprintf("%s(): Entering for inode 0x%llx.\n",
__FUNCTION__, (long long) ni->mft_no);
@@ -495,6 +606,19 @@ int ntfs_inode_sync(ntfs_inode *ni)
__FUNCTION__);
}
+ /* Update FILE_NAME's in the index. */
+ if (ni->nr_extents != -1 && NInoFileNameTestAndClearDirty(ni) &&
+ ntfs_inode_sync_file_name(ni)) {
+ if (!err || errno == EIO) {
+ err = errno;
+ if (err != EIO)
+ err = EBUSY;
+ }
+ Dprintf("%s(): Failed to sync FILE_NAME attributes.\n",
+ __FUNCTION__);
+ NInoFileNameSetDirty(ni);
+ }
+
/* Write out attribute list from cache to disk. */
if (ni->nr_extents != -1 && NInoAttrList(ni) &&
NInoAttrListTestAndClearDirty(ni)) {
@@ -522,7 +646,6 @@ int ntfs_inode_sync(ntfs_inode *ni)
Dprintf("%s(): Attribute list "
"sync failed (write failed).\n",
__FUNCTION__);
-
}
NInoAttrListSetDirty(ni);
}
@@ -574,8 +697,6 @@ int ntfs_inode_sync(ntfs_inode *ni)
}
}
- // TODO: Update FILE_NAME attribute in the index.
-
if (!err)
return 0;
errno = err;
|