Changes by: antona
Update of /cvsroot/linux-ntfs/ntfs-driver-2.4/linux/fs/ntfs
In directory usw-pr-cvs1:/tmp/cvs-serv15139/fs/ntfs
Modified Files:
attr.c dir.c inode.c struct.h super.c super.h
Log Message:
!!!Work in progress snapshot!!! NOT functional!!!
- fixed race in cluster allocation
- fixed fixup stuff: problems with fixup corruption, uninitialized memory accesses, use NTFS_SECTOR_SIZE
- fixed several bugs in attribute handling (extension, resize, etc., read the patch!)
- hopefully fixed bug that used to cause sector zero and following being overwritten by mft
- loads of small fixes
- TODO: finish cluster allocation
- TODO: fix race in cluster deallocation
Index: attr.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-2.4/linux/fs/ntfs/attr.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -U2 -r1.2 -r1.3
--- attr.c 2001/06/11 17:50:25 1.2
+++ attr.c 2001/06/28 23:15:17 1.3
@@ -256,5 +256,6 @@
* *len: the desired new length of the attr (_not_ the amount to extend by)
*/
-int ntfs_extend_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 *len, int flags)
+int ntfs_extend_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 *len,
+ int flags)
{
int error = 0;
@@ -279,16 +280,27 @@
else
/* No preference for allocation space. */
- cluster = 0;
- /* Calculate the extra space we need, and round up to multiple of
- * cluster size to get number of new clusters needed */
- clen = ((*len - attr->allocated) + ino->vol->cluster_size - 1) >>
- ino->vol->cluster_size_bits;
+ cluster = (ntfs_cluster_t)-1;
+ /*
+ * Calculate the extra space we need, and round up to multiple of
+ * cluster size to get number of new clusters needed.
+ */
+ clen = (*len - attr->allocated + ino->vol->cluster_size - 1) >>
+ ino->vol->cluster_size_bits;
if (clen == 0)
return 0;
- /* FIXME: try to allocate smaller pieces */
error = ntfs_allocate_clusters(ino->vol, &cluster, &clen,
- flags | ALLOC_REQUIRE_SIZE);
- if (error)
+ flags | ALLOC_REQUIRE_SIZE);
+ if (error) {
+ if (error == -ENOSPC && !(flags & ALLOC_REQUIRE_LOCATION) &&
+ && !(flags & ALLOC_REQUIRE_SIZE) && clen > 0) {
+ /* FIXME: Try to allocate smaller pieces. */
+ printk(KERN_ERR "NTFS: ntfs_extend_attr() failed to "
+ "allocate single large block of "
+ "clusters. Allocation of multiple "
+ "smaller pieces is not implemented "
+ "yet.\n");
+ }
return error;
+ }
attr->allocated += (__s64)clen << ino->vol->cluster_size_bits;
*len = attr->allocated;
@@ -308,12 +320,17 @@
int ntfs_make_attr_nonresident(ntfs_inode *ino, ntfs_attribute *attr)
{
- void *data = attr->d.data;
- __s64 len = attr->size;
int error;
- __s64 alen;
ntfs_io io;
+ __s64 alen;
+ void *data = attr->d.data;
+ __s64 len = attr->size;
+
attr->d.r.len = 0;
attr->d.r.runlist = 0;
attr->resident = 0;
+ /*
+ * ->allocated is updated by ntfs_extend_attr() while ->initialized is
+ * updated by ntfs_readwrite_attr(). (AIA)
+ */
attr->allocated = attr->initialized = 0;
alen = len;
@@ -415,6 +432,5 @@
if (rl[i].cluster != (ntfs_cluster_t)-1) {
error = ntfs_deallocate_clusters(ino->vol,
- rl[i].cluster,
- (int)rl[i].len);
+ rl[i].cluster, (int)rl[i].len);
if (error)
return error; /* FIXME: Incomplete
@@ -426,5 +442,5 @@
newlen = newsize;
error = ntfs_extend_attr(ino, attr, &newlen,
- ALLOC_REQUIRE_SIZE);
+ ALLOC_REQUIRE_SIZE);
if (error)
return error; /* FIXME: Incomplete operation. */
@@ -434,5 +450,6 @@
attr->allocated = (__s64)newcount << clustersizebits;
attr->size = newsize;
- /* attr->initialized does not change. */
+ if (attr->initialized > newsize)
+ attr->initialized = newsize;
if (!newsize)
error = ntfs_make_attr_resident(ino, attr);
@@ -441,5 +458,5 @@
int ntfs_create_attr(ntfs_inode *ino, int anum, char *aname, void *data,
- int dsize, ntfs_attribute **rattr)
+ int dsize, ntfs_attribute **rattr)
{
void *name;
@@ -463,5 +480,5 @@
}
error = ntfs_new_attr(ino, anum, name, namelen, data, dsize, &i,
- &found);
+ &found);
if (error || found) {
ntfs_free(name);
@@ -498,5 +515,6 @@
}
-/* Non-resident attributes are stored in runs (intervals of clusters).
+/*
+ * Non-resident attributes are stored in runs (intervals of clusters).
*
* This function stores in the inode readable information about a non-resident
Index: dir.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-2.4/linux/fs/ntfs/dir.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -U2 -r1.2 -r1.3
--- dir.c 2001/06/11 17:50:25 1.2
+++ dir.c 2001/06/28 23:15:17 1.3
@@ -27,6 +27,5 @@
int ntfs_check_index_record(ntfs_inode *ino, char *record)
{
- return ntfs_fixup_record(ino->vol, record, "INDX",
- ino->u.index.recordsize);
+ return ntfs_fixup_record(record, "INDX", ino->u.index.recordsize);
}
@@ -268,10 +267,19 @@
} else {
NTFS_PUTU16(buf + 0x1C, used - 0x18);
- ntfs_insert_fixups(buf, vol->sector_size);
io.size = walk->dir->u.index.recordsize;
+ error = ntfs_insert_fixups(buf, io.size);
+ if (error) {
+ printk(KERN_ALERT "NTFS: ntfs_index_writeback() caught "
+ "corrupt index record ntfs record "
+ "header. Refusing to write corrupt "
+ "data to disk. Unmount and run chkdsk "
+ "immediately!\n");
+ return -EIO;
+ }
error = ntfs_write_attr(walk->dir, vol->at_index_allocation,
- I30, (__s64)block << vol->cluster_size_bits, &io);
+ I30, (__s64)block << vol->cluster_size_bits,
+ &io);
if (error || (io.size != walk->dir->u.index.recordsize &&
- (error = -EIO, 1)))
+ (error = -EIO, 1)))
return error;
}
@@ -467,5 +475,5 @@
error = ntfs_index_writeback(&walk, index, walk.newblock,
isize + NTFS_GETU16(index + 0x18) + 0x18);
- if(error)
+ if (error)
goto out;
/* Mark root as split. */
Index: inode.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-2.4/linux/fs/ntfs/inode.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -U2 -r1.5 -r1.6
--- inode.c 2001/06/22 15:22:27 1.5
+++ inode.c 2001/06/28 23:15:17 1.6
@@ -96,5 +96,5 @@
mdata = ntfs_find_attr(vol->mft_ino, vol->at_data, 0);
/* First check whether there is uninitialized space. */
- if (mdata->allocated < mdata->size + vol->mft_record_size) {
+ if (mdata->allocated < mdata->initialized + vol->mft_record_size) {
size = (__s64)ntfs_get_free_cluster_count(vol->bitmap) <<
vol->cluster_size_bits;
@@ -111,10 +111,9 @@
if (error == -ENOSPC) {
/* Round down to multiple of mft record size. */
- size = (__s64)(size >> vol->mft_record_size_bits) <<
- vol->mft_record_size_bits;
+ size = size & ~(__s64)(vol->mft_record_size - 1);
if (!size)
return -ENOSPC;
error = ntfs_extend_attr(vol->mft_ino, mdata, &size,
- ALLOC_REQUIRE_SIZE);
+ ALLOC_REQUIRE_SIZE);
}
if (error)
@@ -124,21 +123,23 @@
* only one record. */
mdata->size += vol->mft_record_size;
+ mdata->initialized += vol->mft_record_size;
/* Now extend the bitmap if necessary. */
rcount = mdata->size >> vol->mft_record_size_bits;
bmp = ntfs_find_attr(vol->mft_ino, vol->at_bitmap, 0);
if (bmp->size * 8 < rcount) { /* Less bits than MFT records. */
- ntfs_u8 buf[1];
- /* Extend bitmap by one byte. */
- error = ntfs_resize_attr(vol->mft_ino, bmp, bmp->size + 1);
+ int i;
+ ntfs_u8 *buf;
+ ntfs_u64 tbmp = 0ULL;
+ /* Extend bitmap by eight bytes. */
+ error = ntfs_resize_attr(vol->mft_ino, bmp, bmp->size + 8);
if (error)
return error;
- /* Write the single byte. */
- buf[0] = 0;
+ /* Write the eight bytes. */
io.fn_put = ntfs_put;
io.fn_get = ntfs_get;
- io.param = buf;
- io.size = 1;
+ io.param = &tbmp;
+ io.size = 8;
error = ntfs_write_attr(vol->mft_ino, vol->at_bitmap, 0,
- bmp->size - 1, &io);
+ bmp->size - 8, &io);
if (error)
return error;
@@ -151,5 +152,12 @@
return -ENOMEM;
ntfs_fill_mft_header(buf, vol->mft_record_size, vol->sector_size, 0);
- ntfs_insert_fixups(buf, vol->sector_size);
+ error = ntfs_insert_fixups(buf, vol->mft_record_size);
+ if (error) {
+ printk(KERN_ALERT "NTFS: ntfs_extend_mft() caught corrupt "
+ "mtf record ntfs record header. Refusing to "
+ "write corrupt data to disk. Unmount and run "
+ "chkdsk immediately!\n");
+ return -EIO;
+ }
io.param = buf;
io.size = vol->mft_record_size;
@@ -468,5 +476,5 @@
int ntfs_check_mft_record(ntfs_volume *vol, char *record)
{
- return ntfs_fixup_record(vol, record, "FILE", vol->mft_record_size);
+ return ntfs_fixup_record(record, "FILE", vol->mft_record_size);
}
@@ -671,11 +679,13 @@
return error;
}
- /* The amount of initialised data has increased: update. */
- /* FIXME: Shouldn't we zero-out the section between the old
- * initialised length and the write start? */
+ /* If amount of initialised data has increased: update. */
if (offset + l > attr->initialized) {
+ /* FIXME: Zero-out the section between the old
+ * initialised length and the write start. */
attr->initialized = offset + l;
- attr->size = offset + l;
}
+ /* If amount of data has increased: update. */
+ if (offset + l > attr->size)
+ attr->size = offset + l;
}
if (attr->resident) {
@@ -707,8 +717,7 @@
clustersizebits = ino->vol->cluster_size_bits;
s_vcn = offset >> clustersizebits;
- for (rnum = 0; rnum < attr->d.r.len &&
- vcn + attr->d.r.runlist[rnum].len <= s_vcn; rnum++) {
+ for (rnum = 0; rnum < attr->d.r.len &&
+ vcn + attr->d.r.runlist[rnum].len <= s_vcn; rnum++)
vcn += attr->d.r.runlist[rnum].len;
- }
if (rnum == attr->d.r.len) {
ntfs_debug(DEBUG_FILE3, "ntfs_readwrite_attr: EOPNOTSUPP: "
@@ -1147,12 +1156,22 @@
io.fn_put = 0;
for (i = 0; i < store.count; i++) {
- ntfs_insert_fixups(store.records[i].record,
- ino->vol->sector_size);
+ error = ntfs_insert_fixups(store.records[i].record,
+ ino->vol->mft_record_size);
+ if (error) {
+ printk(KERN_ALERT "NTFS: ntfs_update_inode() caught "
+ "corrupt %s mtf record ntfs record "
+ "header. Refusing to write corrupt "
+ "data to disk. Unmount and run chkdsk "
+ "immediately!\n", i ? "extension":
+ "base");
+ deallocate_store(&store);
+ return -EIO;
+ }
io.param = store.records[i].record;
io.size = ino->vol->mft_record_size;
/* FIXME: Is this the right way? */
error = ntfs_write_attr(ino->vol->mft_ino, ino->vol->at_data,
- 0, (__s64)store.records[i].recno <<
- ino->vol->mft_record_size_bits, &io);
+ 0, (__s64)store.records[i].recno <<
+ ino->vol->mft_record_size_bits, &io);
if (error || io.size != ino->vol->mft_record_size) {
/* Big trouble, partially written file. */
Index: struct.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-2.4/linux/fs/ntfs/struct.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -U2 -r1.2 -r1.3
--- struct.h 2001/06/11 17:50:25 1.2
+++ struct.h 2001/06/28 23:15:17 1.3
@@ -23,5 +23,5 @@
} ntfs_runlist;
-typedef struct ntfs_attribute{
+typedef struct ntfs_attribute {
int type;
ntfs_u16 *name;
Index: super.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-2.4/linux/fs/ntfs/super.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -U2 -r1.6 -r1.7
--- super.c 2001/06/28 12:08:53 1.6
+++ super.c 2001/06/28 23:15:17 1.7
@@ -11,4 +11,5 @@
#include "super.h"
+#include <linux/ntfs_fs.h>
#include <linux/errno.h>
#include <linux/bitops.h>
@@ -24,5 +25,7 @@
* sector, and if it is the case, must be replaced with the words following
* <n>. The value of <n> and the number of fixups is taken from the fields
- * at the offsets 4 and 6.
+ * at the offsets 4 and 6. Note that the sector size is defined as
+ * NTFS_SECTOR_SIZE and not as the hardware sector size (this is concordant
+ * with what the Windows NTFS driver does).
*
* This function perform these 2 checks, and _fails_ if:
@@ -32,10 +35,6 @@
* . the magic identifier is wrong
* . a fixup is invalid
- *
- * FIXME: This function is wrong. The vol->sector_size should be
- * NTFS_SECTOR_SIZE (defined as 512, always), as the Windows NTFS driver uses
- * the value of 512 hard coded into it, too. (AIA)
*/
-int ntfs_fixup_record(ntfs_volume *vol, char *record, char *magic, int size)
+int ntfs_fixup_record(char *record, char *magic, int size)
{
int start, count, offset;
@@ -46,9 +45,9 @@
start = NTFS_GETU16(record + 4);
count = NTFS_GETU16(record + 6) - 1;
- if (size & (vol->sector_size - 1) || start & 1 ||
+ if (size & (NTFS_SECTOR_SIZE - 1) || start & 1 ||
start + count * 2 > size || size >> 9 != count) {
if (size <= 0)
- printk(KERN_ERR "NTFS: ntfs_fixup_record() got zero "
- "size! Please report this to "
+ printk(KERN_ERR "NTFS: BUG: ntfs_fixup_record() got "
+ "zero size! Please report this to "
"lin...@li...\n");
return 0;
@@ -56,11 +55,11 @@
fixup = NTFS_GETU16(record + start);
start += 2;
- offset = vol->sector_size - 2;
- while (count--){
+ offset = NTFS_SECTOR_SIZE - 2;
+ while (count--) {
if (NTFS_GETU16(record + offset) != fixup)
return 0;
NTFS_PUTU16(record + offset, NTFS_GETU16(record + start));
start += 2;
- offset += vol->sector_size;
+ offset += NTFS_SECTOR_SIZE;
}
return 1;
@@ -76,5 +75,5 @@
__s64 ll;
- /* Historical default values, in case we don't load $AttrDef. */
+ /* System defined default values, in case we don't load $AttrDef. */
vol->at_standard_information = 0x10;
vol->at_attribute_list = 0x20;
@@ -89,5 +88,5 @@
vol->at_bitmap = 0xB0;
vol->at_symlink = 0xC0;
- /* Sector size */
+ /* Sector size. */
vol->sector_size = NTFS_GETU16(boot + 0xB);
ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->sector_size = 0x%x\n",
@@ -477,14 +476,35 @@
}
-/* Insert the fixups for the record. The number and location of the fixes
- * is obtained from the record header */
-void ntfs_insert_fixups(unsigned char *rec, int secsize)
+/*
+ * Insert the fixups for the record. The number and location of the fixes
+ * is obtained from the record header but we double check with @rec_size and
+ * use that as the upper boundary, if necessary overwritting the count value in
+ * the record header.
+ *
+ * We return 0 on success or -1 if fixup header indicated the beginning of the
+ * update sequence array to be beyond the valid limit.
+ */
+int ntfs_insert_fixups(unsigned char *rec, int rec_size)
{
- int first = NTFS_GETU16(rec + 4);
- int count = NTFS_GETU16(rec + 6);
+ int first;
+ int count;
int offset = -2;
- ntfs_u16 fix = NTFS_GETU16(rec + first);
+ ntfs_u16 fix;
- fix++;
+ first = NTFS_GETU16(rec + 4);
+ count = (rec_size >> NTFS_SECTOR_BITS) + 1;
+ if (first + count * 2 > NTFS_SECTOR_SIZE - 2) {
+ printk(KERN_CRIT "NTFS: ntfs_insert_fixups() detected corrupt "
+ "NTFS record update sequence array position. - "
+ "Cannot hotfix.\n");
+ return -1;
+ }
+ if (count != NTFS_GETU16(rec + 6)) {
+ printk(KERN_ERR "NTFS: ntfs_insert_fixups() detected corrupt "
+ "NTFS record update sequence array size. - "
+ "Applying hotfix.\n");
+ NTFS_PUTU16(rec + 6, count);
+ }
+ fix = (NTFS_GETU16(rec + first) + 1) & 0xffff;
if (fix == 0xffff || !fix)
fix = 1;
@@ -493,15 +513,19 @@
while (count--) {
first += 2;
- offset += secsize;
+ offset += NTFS_SECTOR_SIZE;
NTFS_PUTU16(rec + first, NTFS_GETU16(rec + offset));
NTFS_PUTU16(rec + offset, fix);
- };
+ }
+ return 0;
}
-/* Search the bitmap bits of l bytes for *cnt zero bits. Return the bit number
- * in *loc, which is initially set to the number of the first bit. Return the
- * largest block found in *cnt. Return 0 on success, -ENOSPC if all bits are
- * used. */
-static int search_bits(unsigned char* bits, ntfs_cluster_t *loc, int *cnt,int l)
+/*
+ * Search the bitmap @bits of length @l bytes for *@cnt zero bits.
+ * Return the bit number in *@loc, which is initially set to the number of the
+ * first bit. Return the largest block found in *@cnt. Return 0 on success,
+ * -ENOSPC if all bits are used.
+ */
+static int search_bits(unsigned char* bits, ntfs_cluster_t *loc, int *cnt,
+ int l)
{
unsigned char c = 0;
@@ -509,5 +533,6 @@
int bstart = 0, bstop = 0, found = 0;
int start, stop = 0, in = 0;
- /* special case searching for a single block */
+
+ /* Special case searching for a single block. */
if (*cnt == 1) {
while (l && *bits == 0xFF) {
@@ -535,5 +560,5 @@
if ((c & 1) == 0)
stop++;
- else { /* end of sequence of zeroes */
+ else { /* End of sequence of zeroes. */
in = 0;
if (!found || bstop-bstart < stop-start) {
@@ -548,5 +573,5 @@
if (c & 1)
start++;
- else { /*start of sequence*/
+ else { /* Start of sequence. */
in = 1;
stop = start + 1;
@@ -557,5 +582,7 @@
}
if (in && (!found || bstop - bstart < stop - start)) {
- bstop = stop; bstart = start; found = 1;
+ bstop = stop;
+ bstart = start;
+ found = 1;
}
if (!found)
@@ -575,5 +602,5 @@
io.fn_put = ntfs_put;
io.fn_get = ntfs_get;
- bsize = (cnt + (loc & 7) + 7) >> 3; /* round up to multiple of 8*/
+ bsize = (cnt + (loc & 7) + 7) >> 3; /* Round up to multiple of 8. */
bits = ntfs_malloc(bsize);
if (!bits)
@@ -582,5 +609,5 @@
io.size = bsize;
error = ntfs_read_attr(bitmap, bitmap->vol->at_data, 0, loc >> 3, &io);
- if (error || io.size != bsize){
+ if (error || io.size != bsize) {
ntfs_free(bits);
return error ? error : -EIO;
@@ -589,5 +616,5 @@
it = bits;
locit = loc;
- while (locit % 8 && cnt) { /* process first byte */
+ while (locit % 8 && cnt) { /* Process first byte. */
if (bit)
*it |= 1 << (locit % 8);
@@ -599,5 +626,5 @@
it++;
}
- while (cnt > 8) { /*process full bytes */
+ while (cnt > 8) { /* Process full bytes. */
*it = bit ? 0xFF : 0;
cnt -= 8;
@@ -605,5 +632,5 @@
it++;
}
- while (cnt) { /*process last byte */
+ while (cnt) { /* Process last byte. */
if (bit)
*it |= 1 << (locit % 8);
@@ -613,5 +640,5 @@
locit++;
}
- /* reset to start */
+ /* Reset to start. */
io.param = bits;
io.size = bsize;
@@ -625,16 +652,35 @@
}
-/* Allocate count clusters around location. If location is -1, it does not
- * matter where the clusters are. Result is 0 if success, in which case
- * location and count says what they really got. */
-int ntfs_search_bits(ntfs_inode* bitmap, ntfs_cluster_t *location, int *count,
- int flags)
+/*
+ * Allocate @count clusters (LCNs), preferably beginning at @location in the
+ * bitmap of the volume @vol, doing so according to the information passed by
+ * @flags. If @location is -1, it does not matter where the clusters are.
+ *
+ * Return 0 on success, or -errno on error. On success and on -ENOSPC,
+ * @location and @count say what was really allocated. If nothing was allocated,
+ * @location = -1 and @count = 0.
+ *
+ * Independent of @location, we _must_ obey the MFT zone size and dynamically
+ * decrement the MFT zone if we run out of space in the data zone.
+ *
+ * FIXME: Really need finer-grained locking but this will do for the
+ * moment. I just want to kill all races. When that is done, we can
+ * beautify... (AIA)
+ *
+ * FIXME: We should really be operating on pages and using PAGE_SIZE instead of
+ * doing silly kmalloc and using a fixed IO of 2048. (AIA)
+ *
+ * FIXME: We should be monitoring cluster allocation and increment the MFT zone
+ * size dynamically but this is something for the future. We will just cause
+ * heavier fragmentation by not doing it and I am not even sure Windows would
+ * grow the MFT zone dynamically, so might even be correct not doing this. (AIA)
+ */
+int OLD_ntfs_allocate_clusters(ntfs_volume *vol, ntfs_cluster_t *location,
+ int *count, int flags)
{
unsigned char *bits;
- ntfs_io io;
- int error = 0, found = 0;
- int cnt, bloc = -1, bcnt = 0;
- int start;
ntfs_cluster_t loc;
+ ntfs_io io;
+ int start, cnt, error = 0, found = 0, bloc = -1, bcnt = 0;
bits = ntfs_malloc(2048);
@@ -645,17 +691,19 @@
io.param = bits;
- /* first search within +/- 8192 clusters */
+ if (location < vol->mft_zone_end)
+ location = vol->mft_zone_end;
+ /* First search within the next 16384 (2048 * 8) clusters. */
start = *location >> 3;
- start = start > 1024 ? start - 1024 : 0;
io.size = 2048;
- error = ntfs_read_attr(bitmap, bitmap->vol->at_data, 0, start, &io);
+ lock_kernel();
+ error = ntfs_read_attr(vol->bitmap, vol->at_data, 0, start, &io);
if (error)
goto fail;
- loc = start * 8;
+ loc = start << 3;
cnt = *count;
error = search_bits(bits, &loc, &cnt, io.size);
if (error)
goto fail;
- if (*count == cnt){
+ if (*count == cnt) {
bloc = loc;
bcnt = cnt;
@@ -666,10 +714,10 @@
io.param = bits;
io.size = 2048;
- error = ntfs_read_attr(bitmap, bitmap->vol->at_data, 0, start,
- &io);
+ error = ntfs_read_attr(vol->bitmap, vol->at_data, 0, start,
+ &io);
if (error)
goto fail;
- if (io.size == 0) {
- if(found)
+ if (!io.size) {
+ if (found)
goto success;
else {
@@ -678,5 +726,5 @@
}
}
- loc = start * 8;
+ loc = start << 3;
cnt = *count;
error = search_bits(bits, &loc, &cnt, io.size);
@@ -691,35 +739,110 @@
}
}
- success:
- ntfs_free(bits);
- /* check flags */
- if ((flags & ALLOC_REQUIRE_LOCATION) && *location != bloc)
- error = -ENOSPC;
- else if ((flags & ALLOC_REQUIRE_SIZE) && *count != bcnt)
+success:
+ /* Check flags. */
+ if ((flags & ALLOC_REQUIRE_LOCATION && *location != bloc) ||
+ (flags & ALLOC_REQUIRE_SIZE && *count != bcnt))
error = -ENOSPC;
else
- ntfs_set_bitrange(bitmap, bloc, bcnt, 1);
- /* If allocation failed due to the flags, tell the caller what he could
- * have gotten */
+ ntfs_set_bitrange(vol->bitmap, bloc, bcnt, 1);
+ /*
+ * If allocation failed due to the flags, tell the caller what they
+ * could have gotten. Or if allocation was successful, tell the caller
+ * what they did get.
+ */
*location = bloc;
*count = bcnt;
- return 0;
- fail:
- *location = -1;
- *count = 0;
+ret_now:
+ unlock_kernel();
ntfs_free(bits);
return error;
+fail:
+ *location = -1;
+ *count = 0;
+ goto ret_now;
}
-
int ntfs_allocate_clusters(ntfs_volume *vol, ntfs_cluster_t *location,
- int *count, int flags)
+ int *count, int flags)
{
- int error;
- error = ntfs_search_bits(vol->bitmap, location, count, flags);
+ unsigned char *bits;
+ ntfs_cluster_t loc;
+ ntfs_io io;
+ int start, cnt, error = 0, found = 0, bloc = -1, bcnt = 0;
+
+ bits = ntfs_malloc(2048);
+ if (!bits)
+ return -ENOMEM;
+ io.fn_put = ntfs_put;
+ io.fn_get = ntfs_get;
+
+ if (location < vol->mft_zone_end)
+ location = vol->mft_zone_end;
+ lock_kernel();
+
+ This is in the middle of being written! Do not fix compile as the
+ function simply won't work.
+
+ if (*count == cnt) {
+ bloc = loc;
+ bcnt = cnt;
+ goto success;
+ }
+ /* Now search from the beginning. */
+ for (start = *location >> 3; 1; start += 2048) {
+ io.param = bits;
+ io.size = 2048;
+ error = ntfs_read_attr(vol->bitmap, vol->at_data, NULL, start,
+ &io);
+ if (error)
+ goto fail;
+ loc = start << 3;
+ cnt = *count;
+ if (!io.size) {
+ // if mft zone > 0 decrease mft zone, setup start and
+ // loop again
+ if (found)
+ goto success;
+ else {
+ error = -ENOSPC;
+ goto fail;
+ }
+ }
+ error = search_bits(bits, &loc, &cnt, io.size);
+ if (error)
+ goto fail;
+ if (*count == cnt)
+ goto success;
+ if (bcnt < cnt) {
+ bcnt = cnt;
+ bloc = loc;
+ found = 1;
+ }
+ }
+success:
+ /* Check flags. */
+ if ((flags & ALLOC_REQUIRE_LOCATION && *location != bloc) ||
+ (flags & ALLOC_REQUIRE_SIZE && *count != bcnt))
+ error = -ENOSPC;
+ else
+ ntfs_set_bitrange(vol->bitmap, bloc, bcnt, 1);
+ /*
+ * If allocation failed due to the flags, tell the caller what they
+ * could have gotten. Or if allocation was successful, tell the caller
+ * what they did get.
+ */
+ *location = bloc;
+ *count = bcnt;
+ret_now:
+ unlock_kernel();
+ ntfs_free(bits);
return error;
+fail:
+ *location = -1;
+ *count = 0;
+ goto ret_now;
}
int ntfs_deallocate_clusters(ntfs_volume *vol, ntfs_cluster_t location,
- int count)
+ int count)
{
int error;
Index: super.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-2.4/linux/fs/ntfs/super.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -U2 -r1.2 -r1.3
--- super.h 2001/06/11 17:50:25 1.2
+++ super.h 2001/06/28 23:15:17 1.3
@@ -1,6 +1,8 @@
-/* super.h - Header file for super.c
+/*
+ * super.h - Header file for super.c
*
* Copyright (C) 1995-1997 Martin von Löwis
* Copyright (C) 1996-1997 Régis Duchesne
+ * Copyright (c) 2001 Anton Altaparmakov
*/
@@ -18,12 +20,12 @@
int ntfs_release_volume(ntfs_volume *vol);
-void ntfs_insert_fixups(unsigned char *rec, int secsize);
+void ntfs_insert_fixups(unsigned char *rec, int rec_size);
-int ntfs_fixup_record(ntfs_volume *vol, char *record, char *magic, int size);
+int ntfs_fixup_record(char *record, char *magic, int size);
int ntfs_allocate_clusters(ntfs_volume *vol, ntfs_cluster_t *location,
- int *count, int flags);
+ int *count, int flags);
int ntfs_deallocate_clusters(ntfs_volume *vol, ntfs_cluster_t location,
- int count);
+ int count);
|