From c6e1991749eb1e11547af540c7aeed01314b4b18 Mon Sep 17 00:00:00 2001 From: szaka Date: Sun, 29 Jun 2008 22:06:38 +0000 Subject: [PATCH] new: use tabulated logging; add ntfs_log_enter() and ntfs_log_leave() and convert the most commonly used functions --- include/ntfs-3g/logging.h | 6 ++ include/ntfs-3g/mft.h | 14 ++- libntfs-3g/attrib.c | 193 +++++++++++++++++++++++--------------- libntfs-3g/bitmap.c | 17 +++- libntfs-3g/inode.c | 56 +++++++---- libntfs-3g/lcnalloc.c | 53 +++++++---- libntfs-3g/logging.c | 32 ++++++- libntfs-3g/mft.c | 19 +++- libntfs-3g/runlist.c | 78 ++++++++------- 9 files changed, 306 insertions(+), 162 deletions(-) diff --git a/include/ntfs-3g/logging.h b/include/ntfs-3g/logging.h index ae36210a..af25dbf1 100644 --- a/include/ntfs-3g/logging.h +++ b/include/ntfs-3g/logging.h @@ -76,6 +76,8 @@ int ntfs_log_redirect(const char *function, const char *file, int line, #define NTFS_LOG_LEVEL_ERROR (1 << 7) /* Operation failed, no damage done */ #define NTFS_LOG_LEVEL_PERROR (1 << 8) /* Message : standard error description */ #define NTFS_LOG_LEVEL_CRITICAL (1 << 9) /* Operation failed,damage may have occurred */ +#define NTFS_LOG_LEVEL_ENTER (1 << 10) /* Enter a function */ +#define NTFS_LOG_LEVEL_LEAVE (1 << 11) /* Leave a function */ /* Logging style flags - Manage the style of the output */ #define NTFS_LOG_FLAG_PREFIX (1 << 0) /* Prefix messages with "ERROR: ", etc */ @@ -103,9 +105,13 @@ int ntfs_log_redirect(const char *function, const char *file, int line, #ifdef DEBUG #define ntfs_log_debug(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_DEBUG,NULL,FORMAT,##ARGS) #define ntfs_log_trace(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_TRACE,NULL,FORMAT,##ARGS) +#define ntfs_log_enter(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_ENTER,NULL,FORMAT,##ARGS) +#define ntfs_log_leave(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_LEAVE,NULL,FORMAT,##ARGS) #else #define ntfs_log_debug(FORMAT, ARGS...)do {} while (0) #define ntfs_log_trace(FORMAT, ARGS...)do {} while (0) +#define ntfs_log_enter(FORMAT, ARGS...)do {} while (0) +#define ntfs_log_leave(FORMAT, ARGS...)do {} while (0) #endif /* DEBUG */ #endif /* _LOGGING_H_ */ diff --git a/include/ntfs-3g/mft.h b/include/ntfs-3g/mft.h index 9b17b26b..24e71495 100644 --- a/include/ntfs-3g/mft.h +++ b/include/ntfs-3g/mft.h @@ -49,7 +49,12 @@ extern int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref, static __inline__ int ntfs_mft_record_read(const ntfs_volume *vol, const MFT_REF mref, MFT_RECORD *b) { - return ntfs_mft_records_read(vol, mref, 1, b); + int ret; + + ntfs_log_enter("Entering for inode %lld\n", MREF(mref)); + ret = ntfs_mft_records_read(vol, mref, 1, b); + ntfs_log_leave("\n"); + return ret; } extern int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref, @@ -79,7 +84,12 @@ extern int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref, static __inline__ int ntfs_mft_record_write(const ntfs_volume *vol, const MFT_REF mref, MFT_RECORD *b) { - return ntfs_mft_records_write(vol, mref, 1, b); + int ret; + + ntfs_log_enter("Entering for inode %lld\n", MREF(mref)); + ret = ntfs_mft_records_write(vol, mref, 1, b); + ntfs_log_leave("\n"); + return ret; } /** diff --git a/libntfs-3g/attrib.c b/libntfs-3g/attrib.c index 2e13a0f8..a9b7207e 100644 --- a/libntfs-3g/attrib.c +++ b/libntfs-3g/attrib.c @@ -374,19 +374,20 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name, u32 name_len) { ntfs_attr_search_ctx *ctx; - ntfs_attr *na; + ntfs_attr *na = NULL; ATTR_RECORD *a; BOOL cs; - ntfs_log_trace("Entering for inode %lld, attr 0x%x.\n", - (unsigned long long)ni->mft_no, type); + ntfs_log_enter("Entering for inode %lld, attr 0x%x.\n", + (unsigned long long)ni->mft_no, type); + if (!ni || !ni->vol || !ni->mrec) { errno = EINVAL; - return NULL; + goto out; } na = calloc(sizeof(ntfs_attr), 1); if (!na) - return NULL; + goto out; if (name && name != AT_UNNAMED && name != NTFS_INDEX_I30) { name = ntfs_ucsndup(name, name_len); if (!name) @@ -462,12 +463,16 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type, cs ? (l + 7) & ~7 : 0, 0); } ntfs_attr_put_search_ctx(ctx); +out: + ntfs_log_leave("\n"); return na; + put_err_out: ntfs_attr_put_search_ctx(ctx); err_out: free(na); - return NULL; + na = NULL; + goto out; } /** @@ -772,46 +777,16 @@ map_rl: } /** - * ntfs_attr_pread - read from an attribute specified by an ntfs_attr structure - * @na: ntfs attribute to read from - * @pos: byte position in the attribute to begin reading from - * @count: number of bytes to read - * @b: output data buffer - * - * This function will read @count bytes starting at offset @pos from the ntfs - * attribute @na into the data buffer @b. - * - * On success, return the number of successfully read bytes. If this number is - * lower than @count this means that the read reached end of file or that an - * error was encountered during the read so that the read is partial. 0 means - * end of file or nothing was read (also return 0 when @count is 0). - * - * On error and nothing has been read, return -1 with errno set appropriately - * to the return code of ntfs_pread(), or to EINVAL in case of invalid - * arguments. - */ -s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b) + * ntfs_attr_pread_i - see description at ntfs_attr_pread() + */ +static s64 ntfs_attr_pread_i(ntfs_attr *na, const s64 pos, s64 count, void *b) { s64 br, to_read, ofs, total, total2; ntfs_volume *vol; runlist_element *rl; - if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) { - errno = EINVAL; - ntfs_log_perror("%s: na=%p b=%p pos=%lld count=%lld", - __FUNCTION__, na, b, (long long)pos, - (long long)count); - return -1; - } + /* Sanity checking arguments is done in ntfs_attr_pread(). */ - ntfs_log_trace("Entering for inode %lld attr 0x%x pos %lld count " - "%lld flags: 0x%x\n", (unsigned long long)na->ni->mft_no, - na->type, (long long)pos, (long long)count, na->ni->flags); - - /* - * If this is a compressed attribute it needs special treatment, but - * only if it is non-resident. - */ if (NAttrCompressed(na) && NAttrNonResident(na)) return ntfs_compressed_attr_pread(na, pos, count, b); /* @@ -959,6 +934,47 @@ rl_err_out: return -1; } +/** + * ntfs_attr_pread - read from an attribute specified by an ntfs_attr structure + * @na: ntfs attribute to read from + * @pos: byte position in the attribute to begin reading from + * @count: number of bytes to read + * @b: output data buffer + * + * This function will read @count bytes starting at offset @pos from the ntfs + * attribute @na into the data buffer @b. + * + * On success, return the number of successfully read bytes. If this number is + * lower than @count this means that the read reached end of file or that an + * error was encountered during the read so that the read is partial. 0 means + * end of file or nothing was read (also return 0 when @count is 0). + * + * On error and nothing has been read, return -1 with errno set appropriately + * to the return code of ntfs_pread(), or to EINVAL in case of invalid + * arguments. + */ +s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b) +{ + int ret; + + if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) { + errno = EINVAL; + ntfs_log_perror("%s: na=%p b=%p pos=%lld count=%lld", + __FUNCTION__, na, b, (long long)pos, + (long long)count); + return -1; + } + + ntfs_log_enter("Entering for inode %lld attr 0x%x pos %lld count " + "%lld\n", (unsigned long long)na->ni->mft_no, + na->type, (long long)pos, (long long)count); + + ret = ntfs_attr_pread_i(na, pos, count, b); + + ntfs_log_leave("\n"); + return ret; +} + static int ntfs_attr_fill_zero(ntfs_attr *na, s64 pos, s64 count) { char *buf; @@ -1148,9 +1164,10 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) unsigned int undo_data_size : 1; } need_to = { 0, 0 }; - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, count " + ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, count " "0x%llx.\n", na->ni->mft_no, na->type, (long long)pos, (long long)count); + if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) { errno = EINVAL; ntfs_log_perror("%s", __FUNCTION__); @@ -1387,9 +1404,11 @@ done: * FIXME: trying to recover by goto rl_err_out; * could cause driver hang by infinite looping. */ - return -1; + total = -1; + goto out; } out: + ntfs_log_leave("\n"); return total; rl_err_out: eo = errno; @@ -1900,7 +1919,7 @@ static int ntfs_external_attr_find(ATTR_TYPES type, const ntfschar *name, ni = ctx->ntfs_ino; base_ni = ctx->base_ntfs_ino; - ntfs_log_trace("Entering for inode 0x%llx, attribute type 0x%x.\n", + ntfs_log_trace("Entering for inode %lld, attribute type 0x%x.\n", (unsigned long long)ni->mft_no, type); if (!base_ni) { /* First call happens with the base mft record. */ @@ -2299,22 +2318,29 @@ int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name, { ntfs_volume *vol; ntfs_inode *base_ni; + int ret = -1; + ntfs_log_enter("Entering for attribute type 0x%x\n", type); + if (!ctx || !ctx->mrec || !ctx->attr || (name && name != AT_UNNAMED && (!ctx->ntfs_ino || !(vol = ctx->ntfs_ino->vol) || !vol->upcase || !vol->upcase_len))) { errno = EINVAL; - return -1; + goto out; } + if (ctx->base_ntfs_ino) base_ni = ctx->base_ntfs_ino; else base_ni = ctx->ntfs_ino; if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST) - return ntfs_attr_find(type, name, name_len, ic, val, val_len, - ctx); - return ntfs_external_attr_find(type, name, name_len, ic, lowest_vcn, - val, val_len, ctx); + ret = ntfs_attr_find(type, name, name_len, ic, val, val_len, ctx); + else + ret = ntfs_external_attr_find(type, name, name_len, ic, + lowest_vcn, val, val_len, ctx); +out: + ntfs_log_leave("\n"); + return ret; } /** @@ -3617,10 +3643,8 @@ static int ntfs_attr_make_non_resident(ntfs_attr *na, /* Start by allocating clusters to hold the attribute value. */ rl = ntfs_cluster_alloc(vol, 0, new_allocated_size >> vol->cluster_size_bits, -1, DATA_ZONE); - if (!rl) { - ntfs_log_perror("Failed to allocate clusters"); + if (!rl) return -1; - } } else rl = NULL; /* @@ -4233,31 +4257,9 @@ error: ret = -3; goto out; #define NTFS_VCN_DELETE_MARK -2 /** - * ntfs_attr_update_mapping_pairs - update mapping pairs for ntfs attribute - * @na: non-resident ntfs open attribute for which we need update - * @from_vcn: update runlist starting this VCN - * - * Build mapping pairs from @na->rl and write them to the disk. Also, this - * function updates sparse bit, allocated and compressed size (allocates/frees - * space for this field if required). - * - * @na->allocated_size should be set to correct value for the new runlist before - * call to this function. Vice-versa @na->compressed_size will be calculated and - * set to correct value during this function. - * - * FIXME: This function does not update sparse bit and compressed size correctly - * if called with @from_vcn != 0. - * - * FIXME: Rewrite without using NTFS_VCN_DELETE_MARK define. - * - * On success return 0 and on error return -1 with errno set to the error code. - * The following error codes are defined: - * EINVAL - Invalid arguments passed. - * ENOMEM - Not enough memory to complete operation. - * ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST - * or there is no free MFT records left to allocate. + * ntfs_attr_update_mapping_pairs_i - see ntfs_attr_update_mapping_pairs */ -int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn) +static int ntfs_attr_update_mapping_pairs_i(ntfs_attr *na, VCN from_vcn) { ntfs_attr_search_ctx *ctx; ntfs_inode *ni, *base_ni; @@ -4547,6 +4549,41 @@ put_err_out: } #undef NTFS_VCN_DELETE_MARK +/** + * ntfs_attr_update_mapping_pairs - update mapping pairs for ntfs attribute + * @na: non-resident ntfs open attribute for which we need update + * @from_vcn: update runlist starting this VCN + * + * Build mapping pairs from @na->rl and write them to the disk. Also, this + * function updates sparse bit, allocated and compressed size (allocates/frees + * space for this field if required). + * + * @na->allocated_size should be set to correct value for the new runlist before + * call to this function. Vice-versa @na->compressed_size will be calculated and + * set to correct value during this function. + * + * FIXME: This function does not update sparse bit and compressed size correctly + * if called with @from_vcn != 0. + * + * FIXME: Rewrite without using NTFS_VCN_DELETE_MARK define. + * + * On success return 0 and on error return -1 with errno set to the error code. + * The following error codes are defined: + * EINVAL - Invalid arguments passed. + * ENOMEM - Not enough memory to complete operation. + * ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST + * or there is no free MFT records left to allocate. + */ +int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn) +{ + int ret; + + ntfs_log_enter("Entering\n"); + ret = ntfs_attr_update_mapping_pairs_i(na, from_vcn); + ntfs_log_leave("\n"); + return ret; +} + /** * ntfs_non_resident_attr_shrink - shrink a non-resident, open ntfs attribute * @na: non-resident ntfs attribute to shrink @@ -4980,12 +5017,12 @@ void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type, void *data, *ret = NULL; s64 size; - ntfs_log_trace("Entering\n"); + ntfs_log_enter("Entering\n"); na = ntfs_attr_open(ni, type, name, name_len); if (!na) { ntfs_log_perror("ntfs_attr_open failed"); - return NULL; + goto err_exit; } data = ntfs_malloc(na->data_size); if (!data) @@ -5002,6 +5039,8 @@ void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type, *data_size = size; out: ntfs_attr_close(na); +err_exit: + ntfs_log_leave("\n"); return ret; } diff --git a/libntfs-3g/bitmap.c b/libntfs-3g/bitmap.c index 097386c2..e2b4f01c 100644 --- a/libntfs-3g/bitmap.c +++ b/libntfs-3g/bitmap.c @@ -265,7 +265,13 @@ free_err_out: */ int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count) { - return ntfs_bitmap_set_bits_in_run(na, start_bit, count, 1); + int ret; + + ntfs_log_enter("Set from bit %lld, count %lld\n", + (long long)start_bit, (long long)count); + ret = ntfs_bitmap_set_bits_in_run(na, start_bit, count, 1); + ntfs_log_leave("\n"); + return ret; } /** @@ -281,9 +287,12 @@ int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count) */ int ntfs_bitmap_clear_run(ntfs_attr *na, s64 start_bit, s64 count) { - ntfs_log_trace("Dealloc from bit 0x%llx, count 0x%llx.\n", + int ret; + + ntfs_log_enter("Clear from bit %lld, count %lld\n", (long long)start_bit, (long long)count); - - return ntfs_bitmap_set_bits_in_run(na, start_bit, count, 0); + ret = ntfs_bitmap_set_bits_in_run(na, start_bit, count, 0); + ntfs_log_leave("\n"); + return ret; } diff --git a/libntfs-3g/inode.c b/libntfs-3g/inode.c index 9a8d61f1..718ac3ec 100644 --- a/libntfs-3g/inode.c +++ b/libntfs-3g/inode.c @@ -152,18 +152,18 @@ static void __ntfs_inode_release(ntfs_inode *ni) ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref) { s64 l; - ntfs_inode *ni; + ntfs_inode *ni = NULL; ntfs_attr_search_ctx *ctx; STANDARD_INFORMATION *std_info; - ntfs_log_trace("Entering for inode 0x%llx.\n", MREF(mref)); + ntfs_log_enter("Entering for inode %lld\n", MREF(mref)); if (!vol) { errno = EINVAL; - return NULL; + goto out; } ni = __ntfs_inode_allocate(vol); if (!ni) - return NULL; + goto out; if (ntfs_file_record_read(vol, mref, &ni->mrec, NULL)) goto err_out; if (!(ni->mrec->flags & MFT_RECORD_IN_USE)) { @@ -237,12 +237,16 @@ get_size: } } ntfs_attr_put_search_ctx(ctx); +out: + ntfs_log_leave("\n"); return ni; + put_err_out: ntfs_attr_put_search_ctx(ctx); err_out: __ntfs_inode_release(ni); - return NULL; + ni = NULL; + goto out; } /** @@ -269,17 +273,19 @@ err_out: */ int ntfs_inode_close(ntfs_inode *ni) { + int ret = -1; + if (!ni) return 0; - ntfs_log_trace("Entering for inode 0x%llx.\n", (long long)ni->mft_no); + ntfs_log_enter("Entering for inode %lld\n", (long long)ni->mft_no); /* If we have dirty metadata, write it out. */ if (NInoDirty(ni) || NInoAttrListDirty(ni)) { if (ntfs_inode_sync(ni)) { if (errno != EIO) errno = EBUSY; - return -1; + goto err; } } /* Is this a base inode with mapped extent inodes? */ @@ -288,7 +294,7 @@ int ntfs_inode_close(ntfs_inode *ni) if (ntfs_inode_close(ni->extent_nis[0])) { if (errno != EIO) errno = EBUSY; - return -1; + goto err; } } } else if (ni->nr_extents == -1) { @@ -342,7 +348,10 @@ int ntfs_inode_close(ntfs_inode *ni) } __ntfs_inode_release(ni); - return 0; + ret = 0; +err: + ntfs_log_leave("\n"); + return ret; } /** @@ -373,7 +382,7 @@ int ntfs_inode_close(ntfs_inode *ni) ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref) { u64 mft_no = MREF_LE(mref); - ntfs_inode *ni; + ntfs_inode *ni = NULL; ntfs_inode **extent_nis; int i; @@ -383,7 +392,7 @@ ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref) return NULL; } - ntfs_log_trace("Opening extent inode 0x%llx (base mft record 0x%llx).\n", + ntfs_log_enter("Opening extent inode %lld (base mft record %lld).\n", (unsigned long long)mft_no, (unsigned long long)base_ni->mft_no); @@ -404,15 +413,15 @@ ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref) ntfs_log_perror("Found stale extent mft " "reference mft=%lld", (long long)ni->mft_no); - return NULL; + goto out; } - return ni; + goto out; } } /* Wasn't there, we need to load the extent inode. */ ni = __ntfs_inode_allocate(base_ni->vol); if (!ni) - return NULL; + goto out; if (ntfs_file_record_read(base_ni->vol, le64_to_cpu(mref), &ni->mrec, NULL)) { ntfs_log_perror("ntfs_file_record_read failed #2"); @@ -436,10 +445,13 @@ ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref) base_ni->extent_nis = extent_nis; } base_ni->extent_nis[base_ni->nr_extents++] = ni; +out: + ntfs_log_leave("\n"); return ni; err_out: __ntfs_inode_release(ni); - return NULL; + ni = NULL; + goto out; } /** @@ -656,6 +668,7 @@ err_out: */ int ntfs_inode_sync(ntfs_inode *ni) { + int ret = 0; int err = 0; if (!ni) { @@ -664,7 +677,7 @@ int ntfs_inode_sync(ntfs_inode *ni) return -1; } - ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no); + ntfs_log_enter("Entering for inode %lld\n", (long long)ni->mft_no); /* Update STANDARD_INFORMATION. */ if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 && @@ -775,10 +788,13 @@ sync_inode: } } - if (!err) - return 0; - errno = err; - return -1; + if (err) { + errno = err; + ret = -1; + } + + ntfs_log_leave("\n"); + return ret; } /** diff --git a/libntfs-3g/lcnalloc.c b/libntfs-3g/lcnalloc.c index 88fb4730..fbdda328 100644 --- a/libntfs-3g/lcnalloc.c +++ b/libntfs-3g/lcnalloc.c @@ -195,16 +195,17 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count, u8 has_guess, used_zone_pos; int err = 0, rlpos, rlsize, buf_size; - ntfs_log_trace("Entering with count = 0x%llx, start_lcn = 0x%llx, " + ntfs_log_enter("Entering with count = 0x%llx, start_lcn = 0x%llx, " "zone = %s_ZONE.\n", (long long)count, (long long) start_lcn, zone == MFT_ZONE ? "MFT" : "DATA"); + if (!vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na || (s8)zone < FIRST_ZONE || zone > LAST_ZONE) { errno = EINVAL; ntfs_log_perror("%s: vcn: %lld, count: %lld, lcn: %lld", __FUNCTION__, (long long)start_vcn, (long long)count, (long long)start_lcn); - return NULL; + goto out; } /* Return empty runlist if @count == 0 */ @@ -215,12 +216,12 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count, rl[0].lcn = LCN_RL_NOT_MAPPED; rl[0].length = 0; } - return rl; + goto out; } buf = ntfs_malloc(NTFS_LCNALLOC_BSIZE); if (!buf) - return NULL; + goto out; /* * If no @start_lcn was requested, use the current zone * position otherwise use the requested @start_lcn. @@ -322,20 +323,30 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count, * Coalesce with previous run if adjacent LCNs. * Otherwise, append a new run. */ - if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) + if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) { + ntfs_log_debug("Cluster coalesce: prev_lcn: " + "%lld lcn: %lld bmp_pos: %lld " + "prev_run_len: %lld\n", prev_lcn, + lcn, bmp_pos, prev_run_len); rl[rlpos - 1].length = ++prev_run_len; - else { + } else { if (rlpos) rl[rlpos].vcn = rl[rlpos - 1].vcn + prev_run_len; - else + else { rl[rlpos].vcn = start_vcn; + ntfs_log_debug("Start_vcn: %lld\n", + start_vcn); + } rl[rlpos].lcn = prev_lcn = lcn + bmp_pos; rl[rlpos].length = prev_run_len = 1; rlpos++; } + ntfs_log_debug("RUN: %-16lld %-16lld %-16lld\n", + rl[rlpos - 1].vcn, rl[rlpos - 1].lcn, + rl[rlpos - 1].length); /* Done? */ if (!--clusters) { if (used_zone_pos) @@ -467,13 +478,15 @@ done_ret: goto err_ret; } done_err_ret: - ntfs_log_debug("At done_err_ret (follows done_ret).\n"); free(buf); - if (!err) - return rl; - ntfs_log_trace("Failed to allocate clusters (%d)", errno); - errno = err; - return NULL; + if (err) { + errno = err; + ntfs_log_perror("Failed to allocate clusters"); + rl = NULL; + } +out: + ntfs_log_leave("\n"); + return rl; wb_err_ret: ntfs_log_trace("At wb_err_ret.\n"); @@ -486,6 +499,7 @@ err_ret: rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length; rl[rlpos].lcn = LCN_RL_NOT_MAPPED; rl[rlpos].length = 0; + ntfs_debug_runlist_dump(rl); ntfs_cluster_free_from_rl(vol, rl); free(rl); rl = NULL; @@ -563,22 +577,23 @@ int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count) errno = EINVAL; return -1; } - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, count 0x%llx, " + + ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x, count 0x%llx, " "vcn 0x%llx.\n", (unsigned long long)na->ni->mft_no, na->type, (long long)count, (long long)start_vcn); rl = ntfs_attr_find_vcn(na, start_vcn); if (!rl) { if (errno == ENOENT) - return 0; - return -1; + ret = 0; + goto leave; } if (rl->lcn < 0 && rl->lcn != LCN_HOLE) { errno = EIO; ntfs_log_perror("%s: Unexpected lcn (%lld)", __FUNCTION__, (long long)rl->lcn); - return -1; + goto leave; } /* Find the starting cluster inside the run that needs freeing. */ @@ -593,7 +608,7 @@ int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count) /* Do the actual freeing of the clusters in this run. */ if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn + delta, to_free)) - return -1; + goto leave; nr_freed = to_free; } @@ -652,5 +667,7 @@ out: ntfs_log_error("Too many free clusters (%lld > %lld)!", (long long)vol->free_clusters, (long long)vol->nr_clusters); +leave: + ntfs_log_leave("\n"); return ret; } diff --git a/libntfs-3g/logging.c b/libntfs-3g/logging.c index beb96548..7e88c8a4 100644 --- a/libntfs-3g/logging.c +++ b/libntfs-3g/logging.c @@ -58,6 +58,10 @@ static const char *col_red = "\e[01;31m"; static const char *col_redinv = "\e[01;07;31m"; static const char *col_end = "\e[0m"; +#ifdef DEBUG +static int tab; +#endif + /* Some gcc 3.x, 4.[01].X crash with internal compiler error. */ #if __GNUC__ <= 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 1) # define BROKEN_GCC_FORMAT_ATTRIBUTE @@ -83,7 +87,8 @@ struct ntfs_logging { */ static struct ntfs_logging ntfs_log = { #ifdef DEBUG - NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE | + NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE | NTFS_LOG_LEVEL_ENTER | + NTFS_LOG_LEVEL_LEAVE | #endif NTFS_LOG_LEVEL_INFO | NTFS_LOG_LEVEL_QUIET | NTFS_LOG_LEVEL_WARNING | NTFS_LOG_LEVEL_ERROR | NTFS_LOG_LEVEL_PERROR | NTFS_LOG_LEVEL_CRITICAL | @@ -214,6 +219,8 @@ static FILE * ntfs_log_get_stream(u32 level) case NTFS_LOG_LEVEL_DEBUG: case NTFS_LOG_LEVEL_TRACE: + case NTFS_LOG_LEVEL_ENTER: + case NTFS_LOG_LEVEL_LEAVE: case NTFS_LOG_LEVEL_WARNING: case NTFS_LOG_LEVEL_ERROR: case NTFS_LOG_LEVEL_CRITICAL: @@ -413,6 +420,9 @@ out: int ntfs_log_handler_fprintf(const char *function, const char *file, int line, u32 level, void *data, const char *format, va_list args) { +#ifdef DEBUG + int i; +#endif int ret = 0; int olderr = errno; FILE *stream; @@ -423,6 +433,13 @@ int ntfs_log_handler_fprintf(const char *function, const char *file, return 0; /* If it's NULL, we can't do anything. */ stream = (FILE*)data; +#ifdef DEBUG + if (level == NTFS_LOG_LEVEL_LEAVE) { + if (tab) + tab--; + return 0; + } +#endif if (ntfs_log.flags & NTFS_LOG_FLAG_COLOUR) { /* Pick a colour determined by the log level */ switch (level) { @@ -449,7 +466,11 @@ int ntfs_log_handler_fprintf(const char *function, const char *file, break; } } - + +#ifdef DEBUG + for (i = 0; i < tab; i++) + ret += fprintf(stream, " "); +#endif if (col_prefix) ret += fprintf(stream, col_prefix); @@ -467,7 +488,7 @@ int ntfs_log_handler_fprintf(const char *function, const char *file, ret += fprintf(stream, "(%d) ", line); if ((ntfs_log.flags & NTFS_LOG_FLAG_FUNCTION) || /* Source function */ - (level & NTFS_LOG_LEVEL_TRACE)) + (level & NTFS_LOG_LEVEL_TRACE) || (level & NTFS_LOG_LEVEL_ENTER)) ret += fprintf(stream, "%s(): ", function); ret += vfprintf(stream, format, args); @@ -478,7 +499,10 @@ int ntfs_log_handler_fprintf(const char *function, const char *file, if (col_suffix) ret += fprintf(stream, col_suffix); - +#ifdef DEBUG + if (level == NTFS_LOG_LEVEL_ENTER) + tab++; +#endif fflush(stream); errno = olderr; return ret; diff --git a/libntfs-3g/mft.c b/libntfs-3g/mft.c index 7c633a98..6310bf75 100644 --- a/libntfs-3g/mft.c +++ b/libntfs-3g/mft.c @@ -147,7 +147,6 @@ int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref, void *bmirr = NULL; int cnt = 0, res = 0; - ntfs_log_trace("Entering for inode 0x%llx.\n", MREF(mref)); if (!vol || !vol->mft_na || vol->mftmirr_size <= 0 || !b || count < 0) { errno = EINVAL; return -1; @@ -410,9 +409,11 @@ int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref) MFT_RECORD *m; int ret = -1; + ntfs_log_enter("Entering\n"); + m = ntfs_calloc(vol->mft_record_size); if (!m) - return -1; + goto out; if (ntfs_mft_record_layout(vol, mref, m)) goto free_m; @@ -423,6 +424,8 @@ int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref) ret = 0; free_m: free(m); +out: + ntfs_log_leave("\n"); return ret; } @@ -794,11 +797,14 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol) ntfs_attr_search_ctx *ctx; ATTR_RECORD *a; int err; + int ret = -1; + ntfs_log_enter("Entering\n"); + mftbmp_na = vol->mftbmp_na; ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL); if (!ctx) - return -1; + goto out; if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name, mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) { @@ -825,7 +831,8 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol) if (ll == 8) { ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n"); vol->free_mft_records += (8 * 8); - return 0; + ret = 0; + goto out; } ntfs_log_error("Failed to write to mft bitmap.\n"); err = errno; @@ -860,7 +867,9 @@ put_err_out: (long long)mftbmp_na->initialized_size); err_out: errno = err; - return -1; +out: + ntfs_log_leave("\n"); + return ret; } /** diff --git a/libntfs-3g/runlist.c b/libntfs-3g/runlist.c index 27d08b31..40050624 100644 --- a/libntfs-3g/runlist.c +++ b/libntfs-3g/runlist.c @@ -463,39 +463,10 @@ static runlist_element *ntfs_rl_split(runlist_element *dst, int dsize, /** - * ntfs_runlists_merge - merge two runlists into one - * @drl: original runlist to be worked on - * @srl: new runlist to be merged into @drl - * - * First we sanity check the two runlists @srl and @drl to make sure that they - * are sensible and can be merged. The runlist @srl must be either after the - * runlist @drl or completely within a hole (or unmapped region) in @drl. - * - * Merging of runlists is necessary in two cases: - * 1. When attribute lists are used and a further extent is being mapped. - * 2. When new clusters are allocated to fill a hole or extend a file. - * - * There are four possible ways @srl can be merged. It can: - * - be inserted at the beginning of a hole, - * - split the hole in two and be inserted between the two fragments, - * - be appended at the end of a hole, or it can - * - replace the whole hole. - * It can also be appended to the end of the runlist, which is just a variant - * of the insert case. - * - * On success, return a pointer to the new, combined, runlist. Note, both - * runlists @drl and @srl are deallocated before returning so you cannot use - * the pointers for anything any more. (Strictly speaking the returned runlist - * may be the same as @dst but this is irrelevant.) - * - * On error, return NULL, with errno set to the error code. Both runlists are - * left unmodified. The following error codes are defined: - * ENOMEM Not enough memory to allocate runlist array. - * EINVAL Invalid parameters were passed in. - * ERANGE The runlists overlap and cannot be merged. + * ntfs_runlists_merge_i - see ntfs_runlists_merge */ -runlist_element *ntfs_runlists_merge(runlist_element *drl, - runlist_element *srl) +static runlist_element *ntfs_runlists_merge_i(runlist_element *drl, + runlist_element *srl) { int di, si; /* Current index into @[ds]rl. */ int sstart; /* First index with lcn > LCN_RL_NOT_MAPPED. */ @@ -701,6 +672,49 @@ critical_error: return drl; } +/** + * ntfs_runlists_merge - merge two runlists into one + * @drl: original runlist to be worked on + * @srl: new runlist to be merged into @drl + * + * First we sanity check the two runlists @srl and @drl to make sure that they + * are sensible and can be merged. The runlist @srl must be either after the + * runlist @drl or completely within a hole (or unmapped region) in @drl. + * + * Merging of runlists is necessary in two cases: + * 1. When attribute lists are used and a further extent is being mapped. + * 2. When new clusters are allocated to fill a hole or extend a file. + * + * There are four possible ways @srl can be merged. It can: + * - be inserted at the beginning of a hole, + * - split the hole in two and be inserted between the two fragments, + * - be appended at the end of a hole, or it can + * - replace the whole hole. + * It can also be appended to the end of the runlist, which is just a variant + * of the insert case. + * + * On success, return a pointer to the new, combined, runlist. Note, both + * runlists @drl and @srl are deallocated before returning so you cannot use + * the pointers for anything any more. (Strictly speaking the returned runlist + * may be the same as @dst but this is irrelevant.) + * + * On error, return NULL, with errno set to the error code. Both runlists are + * left unmodified. The following error codes are defined: + * ENOMEM Not enough memory to allocate runlist array. + * EINVAL Invalid parameters were passed in. + * ERANGE The runlists overlap and cannot be merged. + */ +runlist_element *ntfs_runlists_merge(runlist_element *drl, + runlist_element *srl) +{ + runlist_element *rl; + + ntfs_log_enter("Entering\n"); + rl = ntfs_runlists_merge_i(drl, srl); + ntfs_log_leave("\n"); + return rl; +} + /** * ntfs_mapping_pairs_decompress - convert mapping pairs array to runlist * @vol: ntfs volume on which the attribute resides