Remove vol->nr_mft_records and update all users. (Anton)

(Logical change 1.549)
edge.strict_endians
cantab.net!aia21 2004-09-13 10:28:54 +00:00
parent a5b6b89456
commit b82469ba50
11 changed files with 134 additions and 34 deletions

View File

@ -24,6 +24,7 @@ xx/xx/2004 - 2.0.0-WIP
all callers. This allows filling an attribute extent with mapping
pairs and then continuing in a different extent once the first extent
is full. (Yura)
- Remove vol->nr_mft_records and update all users. (Anton)
04/09/2004 - 1.9.4 - Urgent bug fixes.

View File

@ -140,9 +140,6 @@ struct _ntfs_volume {
lcn 0 and so on. A set bit means that the
cluster and vice versa. */
s64 nr_mft_records; /* Number of initialized records in the mft,
equals the number of bits in mft_bitmap that
may be set. */
LCN mft_lcn; /* Logical cluster number of the data attribute
for FILE_MFT. */
ntfs_inode *mft_ni; /* ntfs_inode structure for FILE_MFT. */

View File

@ -72,7 +72,8 @@ int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref,
}
m = MREF(mref);
/* Refuse to read non-allocated mft records. */
if (m + count > vol->nr_mft_records) {
if (m + count > vol->mft_na->initialized_size >>
vol->mft_record_size_bits) {
errno = ESPIPE;
return -1;
}
@ -129,7 +130,8 @@ int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref,
}
m = MREF(mref);
/* Refuse to write non-allocated mft records. */
if (m + count > vol->nr_mft_records) {
if (m + count > vol->mft_na->initialized_size >>
vol->mft_record_size_bits) {
errno = ESPIPE;
return -1;
}
@ -375,20 +377,88 @@ int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref)
* @start: starting mft record at which to allocate (or -1 if none)
*
* Allocate an mft record in $MFT/$DATA starting to search for a free record
* at mft record number @start or at the current allocator position if
* @start_mref is -1, on the mounted ntfs volume @vol.
* at mft record number @start or at the current allocator position if @start
* is -1, on the mounted ntfs volume @vol.
*
* On success return the now opened ntfs inode of the mft record.
*
* On error return NULL with errno set to the error code.
*
* To find a free mft record, we scan the mft bitmap for a zero bit. To
* optimize this we start scanning at the place specified by @start or if
* @start is -1 we start where we last stopped and we perform wrap around when
* we reach the end. Note, we do not try to allocate mft records below number
* 24 because numbers 0 to 15 are the defined system files anyway and 16 to 24
* are special in that they are used for storing extension mft records for the
* $DATA attribute of $MFT. This is required to avoid the possibility of
* creating a run list with a circular dependence which once written to disk
* can never be read in again. Windows will only use records 16 to 24 for
* normal files if the volume is completely out of space. We never use them
* which means that when the volume is really out of space we cannot create any
* more files while Windows can still create up to 8 small files. We can start
* doing this at some later time, it does not matter much for now.
*
* When scanning the mft bitmap, we only search up to the last allocated mft
* record. If there are no free records left in the range 24 to number of
* allocated mft records, then we extend the $MFT/$DATA attribute in order to
* create free mft records. We extend the allocated size of $MFT/$DATA by 16
* records at a time or one cluster, if cluster size is above 16kiB. If there
* is not sufficient space to do this, we try to extend by a single mft record
* or one cluster, if cluster size is above the mft record size, but we only do
* this if there is enough free space, which we know from the values returned
* by the failed cluster allocation function when we tried to do the first
* allocation.
*
* No matter how many mft records we allocate, we initialize only the first
* allocated mft record, incrementing mft data size and initialized size
* accordingly, open an ntfs_inode for it and return it to the caller, unless
* there are less than 24 mft records, in which case we allocate and initialize
* mft records until we reach record 24 which we consider as the first free mft
* record for use by normal files.
*
* If during any stage we overflow the initialized data in the mft bitmap, we
* extend the initialized size (and data size) by 8 bytes, allocating another
* cluster if required. The bitmap data size has to be at least equal to the
* number of mft records in the mft, but it can be bigger, in which case the
* superflous bits are padded with zeroes.
*
* Thus, when we return successfully (return value non-zero), we will have:
* - initialized / extended the mft bitmap if necessary,
* - initialized / extended the mft data if necessary,
* - set the bit corresponding to the mft record being allocated in the
* mft bitmap,
* - open an ntfs_inode for the allocated mft record, and we will
* - return the ntfs_inode.
*
* On error (return value zero), nothing will have changed. If we had changed
* anything before the error occured, we will have reverted back to the
* starting state before returning to the caller. Thus, except for bugs, we
* should always leave the volume in a consistent state when returning from
* this function.
*
* Note, this function cannot make use of most of the normal functions, like
* for example for attribute resizing, etc, because when the run list overflows
* the base mft record and an attribute list is used, it is very important that
* the extension mft records used to store the $DATA attribute of $MFT can be
* reached without having to read the information contained inside them, as
* this would make it impossible to find them in the first place after the
* volume is dismounted. $MFT/$BITMAP probably does not need to follow this
* rule because the bitmap is not essential for finding the mft records, but on
* the other hand, handling the bitmap in this special way would make life
* easier because otherwise there might be circular invocations of functions
* when reading the bitmap but if we are careful, we should be able to avoid
* all problems.
*/
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, s64 start)
{
if (!vol || !vol->mftbmp_na || start < -1) {
ntfs_debug("Entering (start 0x%llx).", (long long)start);
if (!vol || !vol->mft_na || !vol->mftbmp_na || start < -1) {
errno = EINVAL;
return NULL;
}
errno = ENOTSUP;
return NULL;
}

View File

@ -217,9 +217,6 @@ mft_has_no_attr_list:
Dperror("Failed to open ntfs attribute");
goto error_exit;
}
/* Set the number of initialized mft records. */
vol->nr_mft_records = vol->mft_na->initialized_size >>
vol->mft_record_size_bits;
/* Read all extents from the $DATA attribute in $MFT. */
ntfs_attr_reinit_search_ctx(ctx);
last_vcn = vol->mft_na->allocated_size >> vol->cluster_size_bits;

View File

@ -873,7 +873,8 @@ static int walk_clusters(ntfs_volume *volume, struct ntfs_walk_cluster *walk)
Printf("Scanning volume ...\n");
last_mft_rec = volume->nr_mft_records - 1;
last_mft_rec = (volume->mft_na->initialized_size >>
volume->mft_record_size_bits) - 1;
progress_init(&progress, inode, last_mft_rec, 100);
for (; inode <= last_mft_rec; inode++) {
@ -1331,7 +1332,8 @@ int main(int argc, char **argv)
walk_clusters(vol, &backup_clusters);
Printf("Num of MFT records = %8lld\n",
(long long)vol->nr_mft_records);
(long long)vol->mft_na->initialized_size >>
vol->mft_record_size_bits);
Printf("Num of used MFT records = %8d\n", nr_used_mft_records);
Printf("Wiped unused MFT data = %8d\n", wiped_unused_mft_data);

View File

@ -311,7 +311,7 @@ static int info (ntfs_volume *vol)
d = vol->nr_clusters << cb;
e = vol->nr_clusters;
f = vol->nr_clusters >> cps;
g = vol->nr_mft_records;
g = vol->mft_na->initialized_size >> vol->mft_record_size_bits;
h = inuse;
i = h * 100 / g;
j = fc;

View File

@ -339,8 +339,6 @@ static void ntfs_dump_volume(ntfs_volume *vol)
(long long)vol->data1_zone_pos);
printf("\tCurrent Position in Second Data Zone: %lld\n",
(long long)vol->data2_zone_pos);
printf("\tNumber of Initialized Records in MFT: %lld\n",
(long long)vol->nr_mft_records);
printf("\tLCN of Data Attribute for FILE_MFT: %lld\n",
(long long)vol->mft_lcn);
printf("\tFILE_MFTMirr Size: %d\n", vol->mftmirr_size);

View File

@ -953,7 +953,7 @@ static int inode_close(ntfs_inode *ni)
*/
static int build_allocation_bitmap(ntfs_volume *vol, ntfsck_t *fsck)
{
s64 inode = 0;
s64 nr_mft_records, inode = 0;
ntfs_inode *ni;
struct progress_bar progress;
int pb_flags = 0; /* progress bar flags */
@ -964,9 +964,12 @@ static int build_allocation_bitmap(ntfs_volume *vol, ntfsck_t *fsck)
if (fsck->flags & NTFSCK_PROGBAR)
pb_flags |= NTFS_PROGBAR;
progress_init(&progress, inode, vol->nr_mft_records - 1, pb_flags);
nr_mft_records = vol->mft_na->initialized_size >>
vol->mft_record_size_bits;
for (; inode < vol->nr_mft_records; inode++) {
progress_init(&progress, inode, nr_mft_records - 1, pb_flags);
for (; inode < nr_mft_records; inode++) {
progress_update(&progress, inode);
if ((ni = ntfs_inode_open(vol, (MFT_REF)inode)) == NULL) {
@ -1033,12 +1036,15 @@ static void resize_constrains_by_attributes(ntfs_resize_t *resize)
static void set_resize_constrains(ntfs_resize_t *resize)
{
s64 inode;
s64 nr_mft_records, inode;
ntfs_inode *ni;
printf("Collecting shrinkage constrains ...\n");
for (inode = 0; inode < resize->vol->nr_mft_records; inode++) {
nr_mft_records = resize->vol->mft_na->initialized_size >>
resize->vol->mft_record_size_bits;
for (inode = 0; inode < nr_mft_records; inode++) {
ni = ntfs_inode_open(resize->vol, (MFT_REF)inode);
if (ni == NULL) {
@ -1586,6 +1592,7 @@ static void relocate_inode(ntfs_resize_t *resize, MFT_REF mref)
static void relocate_inodes(ntfs_resize_t *resize)
{
s64 nr_mft_records;
MFT_REF mref;
printf("Relocating needed data ...\n");
@ -1597,7 +1604,10 @@ static void relocate_inodes(ntfs_resize_t *resize)
if (!resize->mrec)
perr_exit("malloc failed");
for (mref = 1; mref < (MFT_REF)resize->vol->nr_mft_records; mref++)
nr_mft_records = resize->vol->mft_na->initialized_size >>
resize->vol->mft_record_size_bits;
for (mref = 1; mref < (MFT_REF)nr_mft_records; mref++)
relocate_inode(resize, mref);
relocate_inode(resize, 0);

View File

@ -1553,6 +1553,7 @@ static int set_date (const char *pathname, time_t date)
*/
static int scan_disk (ntfs_volume *vol)
{
s64 nr_mft_records;
const int BUFSIZE = 8192;
char *buffer = NULL;
int results = 0;
@ -1592,6 +1593,9 @@ static int scan_disk (ntfs_volume *vol)
}
}
nr_mft_records = vol->mft_na->initialized_size >>
vol->mft_record_size_bits;
Qprintf ("Inode Flags %%age Date Size Filename\n");
Qprintf ("---------------------------------------------------------------\n");
for (i = 0; i < bmpsize; i += BUFSIZE) {
@ -1603,7 +1607,7 @@ static int scan_disk (ntfs_volume *vol)
for (j = 0; j < size; j++) {
b = buffer[j];
for (k = 0; k < 8; k++, b>>=1) {
if (((i+j)*8+k) >= vol->nr_mft_records)
if (((i+j)*8+k) >= nr_mft_records)
goto done;
if (b & 1)
continue;
@ -1907,6 +1911,7 @@ free:
*/
static int copy_mft (ntfs_volume *vol, long long mft_begin, long long mft_end)
{
s64 nr_mft_records;
char pathname[256];
ntfs_attr *mft;
char *buffer;
@ -1948,10 +1953,13 @@ static int copy_mft (ntfs_volume *vol, long long mft_begin, long long mft_end)
goto attr;
}
mft_end = min (mft_end, vol->nr_mft_records - 1);
nr_mft_records = vol->mft_na->initialized_size >>
vol->mft_record_size_bits;
mft_end = min (mft_end, nr_mft_records - 1);
Dprintf ("MFT records\n");
Dprintf (" Total: %8lld\n", vol->nr_mft_records);
Dprintf (" Total: %8lld\n", nr_mft_records);
Dprintf (" Begin: %8lld\n", mft_begin);
Dprintf (" End: %8lld\n", mft_end);
@ -1988,6 +1996,7 @@ free:
*/
int main (int argc, char *argv[])
{
s64 nr_mft_records;
ntfs_volume *vol;
int result = 1;
int i;
@ -2028,10 +2037,13 @@ int main (int argc, char *argv[])
}
break;
case MODE_COPY:
nr_mft_records = vol->mft_na->initialized_size >>
vol->mft_record_size_bits;
result = !copy_mft (vol, opts.mft_begin, opts.mft_end);
if (result)
Vprintf ("Failed to read MFT blocks %lld-%lld.\n",
opts.mft_begin, min(vol->nr_mft_records, opts.mft_end));
opts.mft_begin, min(nr_mft_records, opts.mft_end));
break;
default:
; /* Cannot happen */

View File

@ -566,14 +566,17 @@ static s64 wipe_attribute (ntfs_volume *vol, int byte, enum action act,
static s64 wipe_tails (ntfs_volume *vol, int byte, enum action act)
{
s64 total = 0;
s64 inode_num;
s64 nr_mft_records, inode_num;
ntfs_inode *ni;
ntfs_attr *na;
if (!vol || (byte < 0))
return -1;
for (inode_num = 16; inode_num < vol->nr_mft_records; inode_num++) {
nr_mft_records = vol->mft_na->initialized_size >>
vol->mft_record_size_bits;
for (inode_num = 16; inode_num < nr_mft_records; inode_num++) {
s64 wiped;
Vprintf ("Inode %lld - ", inode_num);
@ -646,7 +649,7 @@ static s64 wipe_mft (ntfs_volume *vol, int byte, enum action act)
{
// by considering the individual attributes we might be able to
// wipe a few more bytes at the attr's tail.
s64 i;
s64 nr_mft_records, i;
s64 total = 0;
s64 result = 0;
int size = 0;
@ -661,7 +664,10 @@ static s64 wipe_mft (ntfs_volume *vol, int byte, enum action act)
return -1;
}
for (i = 0; i < vol->nr_mft_records; i++) {
nr_mft_records = vol->mft_na->initialized_size >>
vol->mft_record_size_bits;
for (i = 0; i < nr_mft_records; i++) {
if (utils_mftrec_in_use (vol, i)) {
result = ntfs_attr_mst_pread (vol->mft_na, vol->mft_record_size * i,
1, vol->mft_record_size, buffer);
@ -920,7 +926,7 @@ static u32 get_indx_record_size (ntfs_attr *nar)
static s64 wipe_directory (ntfs_volume *vol, int byte, enum action act)
{
s64 total = 0;
s64 inode_num;
s64 nr_mft_records, inode_num;
ntfs_inode *ni;
ntfs_attr *naa;
ntfs_attr *nab;
@ -929,7 +935,10 @@ static s64 wipe_directory (ntfs_volume *vol, int byte, enum action act)
if (!vol || (byte < 0))
return -1;
for (inode_num = 5; inode_num < vol->nr_mft_records; inode_num++) {
nr_mft_records = vol->mft_na->initialized_size >>
vol->mft_record_size_bits;
for (inode_num = 5; inode_num < nr_mft_records; inode_num++) {
u32 indx_record_size;
s64 wiped;

View File

@ -963,6 +963,7 @@ void mft_put_search_ctx (struct mft_search_ctx *ctx)
*/
int mft_next_record (struct mft_search_ctx *ctx)
{
s64 nr_mft_records;
ATTR_RECORD *attr10 = NULL;
ATTR_RECORD *attr20 = NULL;
ATTR_RECORD *attr80 = NULL;
@ -978,7 +979,10 @@ int mft_next_record (struct mft_search_ctx *ctx)
ctx->inode = NULL;
}
for (ctx->mft_num++; (s64)ctx->mft_num < ctx->vol->nr_mft_records; ctx->mft_num++) {
nr_mft_records = ctx->vol->mft_na->initialized_size >>
ctx->vol->mft_record_size_bits;
for (ctx->mft_num++; (s64)ctx->mft_num < nr_mft_records; ctx->mft_num++) {
int in_use;
ctx->flags_match = 0;