Inode number treated as signed int in ffs_nodealloccg

Scott Burns scott at bqinternet.com
Mon Feb 1 00:25:25 UTC 2010


Hi guys,

While working with a 17TB UFS2 filesystem, g_vfs_done() was reporting 
write errors with negative offsets.  I modified bufwrite() to have it 
panic on a negative bp->b_blkno so that I could trace the source of the 
write.  The traces showed ffs_nodealloccg() as the source of the problem.

The negative number is coming from the ino_to_fsba(fs, x) macro used in 
ffs_nodealloccg().  In this case, the x is "cg * fs->fs_ipg + 
cgp->cg_initediblk".  The problem goes away if I cast cg as (unsigned 
int)cg.

I imagine that this hasn't been noticed up to now since most people are 
not exceeding the range of a signed int, even with multi-TB filesystems. 
  Is this issue likely to exist in other FFS code? Should I just 
recreate the filesystem with less inodes for now?

I made a crude example program to easily demonstrate the problem:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>

int main() {
	struct fs *fs;
	struct cg *cgp;
	int cg;

	fs = malloc(sizeof(struct fs));
	cgp = malloc(sizeof(struct cg));

	fs->fs_magic = 424935705;
	fs->fs_fsbtodb = 2;
	fs->fs_inopb = 64;
	fs->fs_fragshift = 3;
	fs->fs_ipg = 23552;
	fs->fs_iblkno = 56;
	fs->fs_fpg = 94064;
	cg = 96868;
	cgp->cg_initediblk = 21696;

	printf("ino_to_fsba #1: %lld\n",
		ino_to_fsba(fs, cg * fs->fs_ipg + cgp->cg_initediblk));
	printf("ino_to_fsba #2: %lld\n",
		ino_to_fsba(fs, (unsigned int)cg
			* fs->fs_ipg + cgp->cg_initediblk));

	return 0;
}

/* Observed output:
  ino_to_fsba #1: -8041719792
  ino_to_fsba #2: 9111794320
*/

--
Scott Burns
System Administrator
BQ Internet Corporation


More information about the freebsd-fs mailing list