ports/84048: sysutils/ntfsprogs: partition device access requires 512 byte size

Andriy Gapon avg at icyb.net.ua
Mon Jul 25 10:40:08 UTC 2005


>Number:         84048
>Category:       ports
>Synopsis:       sysutils/ntfsprogs: partition device access requires 512 byte size
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jul 25 10:40:07 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Andriy Gapon
>Release:        FreeBSD 5.4-RELEASE-p3 i386
>Organization:
>Environment:
System: FreeBSD 5.4-RELEASE-p3 i386
ntfsprogs-1.9.4_1


	
>Description:
I unsuccessfully tried to use ntfsresize program from this port. ntfsresize -i
was failing early in its run, during verification of "device size" i.e. 
read access to the whole partition that hosted ntfs. The error was EINVAL.
Apparently the problem is that freebsd partition devices (e.g. ad0s2) allow
read/write operations only for sizes that are multiple of sector size. E.g.:
$ dd if=/dev/ad0s1e of=/dev/null bs=1 count=1
dd: /dev/ad0s1e: Invalid argument
0+0 records in
0+0 records out
0 bytes transferred in 0.000099 secs (0 bytes/sec)
$ dd if=/dev/ad0s1e of=/dev/null bs=512 count=1
1+0 records in
1+0 records out
512 bytes transferred in 0.008678 secs (59000 bytes/sec)

To make ntfsresize work on FreeBSD I had to change all read/write calls to use
n*512 byte counts.

The patches to ntfsclone.c and device.c are trivial - 1 byte was read to check
accessibility of a certain offset; 512 bytes are read now instead.
attrib.c patch works as follows: certain data structure is read from disk, its
size may be not multiple of 512, so we round up size before reading, but we
use actual size for bytes read.
ntfsresize.c: certain data structure needs to be written to disk, there is 
a certian algorithm for calculating its size, the result may be not 512*n,
so we round it up.

Probably there are other palces in the code that are affected by the same
restricition.

>How-To-Repeat:

try to use ntfsresize -i on ntfs partition

>Fix:

	

--- 512.patch begins here ---
--- libntfs/attrib.c	Sat Sep  4 13:16:32 2004
+++ libntfs/attrib.c	Fri Jul 22 01:05:09 2005
@@ -709,9 +709,9 @@
  */
 s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b)
 {
-	s64 br, to_read, ofs, total, total2;
+	s64 br, old_to_read, to_read, ofs, total, total2;
 	ntfs_volume *vol;
 	runlist_element *rl;
 
 	Dprintf("%s(): Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, "
 			"count 0x%llx.\n", __FUNCTION__,
@@ -741,6 +744,7 @@
 	if (pos + count > na->data_size) {
 		if (pos >= na->data_size)
 			return 0;
+		Dprintf("trunacting read pos=%lld, na->data_size=%lld, (old) count=%lld\n", pos, na->data_size, count);
 		count = na->data_size - pos;
 	}
 	vol = na->ni->vol;
@@ -820,6 +825,10 @@
 		/* It is a real lcn, read it into @dst. */
 		to_read = min(count, (rl->length << vol->cluster_size_bits) -
 				ofs);
+		old_to_read = to_read;
+		to_read = (to_read + 511) / 512 * 512;
+		if(old_to_read != to_read)
+			Dprintf("adjusted %lld->%lld\n", old_to_read, to_read);
 retry:
 		Dprintf("%s(): Reading 0x%llx bytes from vcn 0x%llx, lcn 0x%llx, "
 				"ofs 0x%llx.\n", __FUNCTION__, to_read,
@@ -828,6 +837,8 @@
 				ofs, to_read, b);
 		/* If everything ok, update progress counters and continue. */
 		if (br > 0) {
+			if(br > old_to_read)
+				br = old_to_read;
 			total += br;
 			count -= br;
 			b = (u8*)b + br;
--- libntfs/device.c	Sat Sep  4 13:16:32 2004
+++ libntfs/device.c	Mon Jul 11 23:27:55 2005
@@ -441,10 +441,10 @@
  */
 static inline int ntfs_device_offset_valid(struct ntfs_device *dev, s64 ofs)
 {
-	char ch;
+	char ch[512];
 
 	if (dev->d_ops->seek(dev, ofs, SEEK_SET) >= 0 &&
-			dev->d_ops->read(dev, &ch, 1) == 1)
+			dev->d_ops->read(dev, &ch, 512) > 0)
 		return 0;
 	return -1;
 }
--- ntfsprogs/ntfsclone.c	Mon Jul 25 12:31:30 2005
+++ ntfsprogs/ntfsclone.c	Mon Jul 25 12:33:32 2005
@@ -1080,9 +1080,9 @@
 
 static int device_offset_valid(int fd, s64 ofs)
 {
-	char ch;
+	char ch[512];
 
-	if (lseek(fd, ofs, SEEK_SET) >= 0 && read(fd, &ch, 1) == 1)
+	if (lseek(fd, ofs, SEEK_SET) >= 0 && read(fd, &ch, 512) > 0)
 		return 0;
 	return -1;
 }
--- ntfsprogs/ntfsresize.c	Sat Sep  4 13:16:32 2004
+++ ntfsprogs/ntfsresize.c	Tue Jul 12 01:15:30 2005
@@ -1783,6 +1783,10 @@
 
 	nr_clusters = resize->new_volume_size;
 	bm_bsize = nr_clusters_to_bitmap_byte_size(nr_clusters);
+	if(bm_bsize % 512 != 0) {
+		Dprintf("adjusted bm_bsize: %lld->%lld\n", bm_bsize, (bm_bsize + 511) / 512 * 512);
+		bm_bsize = (bm_bsize + 511) / 512 * 512;
+	}
 	nr_bm_clusters = rounded_up_division(bm_bsize, vol->cluster_size);
 
 	if (!(tmp = (u8 *)realloc(resize->lcn_bitmap.bm, bm_bsize)))
--- 512.patch ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list