new: use tabulated logging; add ntfs_log_enter() and ntfs_log_leave()

and convert the most commonly used functions
master
szaka 2008-06-29 22:06:38 +00:00
parent dec6162b63
commit c6e1991749
9 changed files with 306 additions and 162 deletions

View File

@ -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_ */

View File

@ -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;
}
/**

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
/**

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}
/**

View File

@ -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