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