This commit adds basic support for the UFS2 filesystem. The UFS2

filesystem expands the inode to 256 bytes to make space for 64-bit
block pointers. It also adds a file-creation time field, an ability
to use jumbo blocks per inode to allow extent like pointer density,
and space for extended attributes (up to twice the filesystem block
size worth of attributes, e.g., on a 16K filesystem, there is space
for 32K of attributes). UFS2 fully supports and runs existing UFS1
filesystems. New filesystems built using newfs can be built in either
UFS1 or UFS2 format using the -O option. In this commit UFS1 is
the default format, so if you want to build UFS2 format filesystems,
you must specify -O 2. This default will be changed to UFS2 when
UFS2 proves itself to be stable. In this commit the boot code for
reading UFS2 filesystems is not compiled (see /sys/boot/common/ufsread.c)
as there is insufficient space in the boot block. Once the size of the
boot block is increased, this code can be defined.

Things to note: the definition of SBSIZE has changed to SBLOCKSIZE.
The header file <ufs/ufs/dinode.h> must be included before
<ufs/ffs/fs.h> so as to get the definitions of ufs2_daddr_t and
ufs_lbn_t.

Still TODO:
Verify that the first level bootstraps work for all the architectures.
Convert the utility ffsinfo to understand UFS2 and test growfs.
Add support for the extended attribute storage. Update soft updates
to ensure integrity of extended attribute storage. Switch the
current extended attribute interfaces to use the extended attribute
storage. Add the extent like functionality (framework is there,
but is currently never used).

Sponsored by: DARPA & NAI Labs.
Reviewed by:	Poul-Henning Kamp <phk@freebsd.org>
This commit is contained in:
Kirk McKusick 2002-06-21 06:18:05 +00:00
parent 27168693db
commit 1c85e6a35d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=98542
89 changed files with 5214 additions and 3384 deletions

View File

@ -64,20 +64,48 @@
#define OFS_MAGIC (int)60011
#define NFS_MAGIC (int)60012
#ifndef FS_UFS2_MAGIC
#define FS_UFS2_MAGIC (int)0x19540119
#endif
#define CHECKSUM (int)84446
union u_spcl {
char dummy[TP_BSIZE];
struct s_spcl {
int32_t c_type; /* record type (see below) */
int32_t c_date; /* date of this dump */
int32_t c_ddate; /* date of previous dump */
int32_t c_old_date; /* date of this dump */
int32_t c_old_ddate; /* date of previous dump */
int32_t c_volume; /* dump volume number */
int32_t c_tapea; /* logical block of this record */
int32_t c_old_tapea; /* logical block of this record */
ino_t c_inumber; /* number of inode */
int32_t c_magic; /* magic number (see above) */
int32_t c_checksum; /* record checksum */
struct dinode c_dinode; /* ownership and mode of inode */
/*
* Start old dinode structure, expanded for binary
* compatibility with UFS1.
*/
u_int16_t c_mode; /* file mode */
int16_t c_spare1[3]; /* old nlink, ids */
u_int64_t c_size; /* file byte count */
int32_t c_old_atime; /* old last access time, seconds */
int32_t c_atimensec; /* last access time, nanoseconds */
int32_t c_old_mtime; /* old last modified time, secs */
int32_t c_mtimensec; /* last modified time, nanosecs */
int32_t c_spare2[2]; /* old ctime */
int32_t c_rdev; /* for devices, device number */
int32_t c_createtimensec; /* creation time, nanosecs */
int64_t c_createtime; /* creation time, seconds */
int64_t c_atime; /* last access time, seconds */
int64_t c_mtime; /* last modified time, seconds */
int32_t c_spare4[7]; /* old block pointers */
u_int32_t c_file_flags; /* status flags (chflags) */
int32_t c_spare5[2]; /* old blocks, generation number */
u_int32_t c_uid; /* file owner */
u_int32_t c_gid; /* file group */
int32_t c_spare6[2]; /* previously unused spares */
/*
* End old dinode structure.
*/
int32_t c_count; /* number of valid c_addr entries */
char c_addr[TP_NINDIR]; /* 1 => data; 0 => hole in inode */
char c_label[LBLSIZE]; /* dump label */
@ -86,8 +114,12 @@ union u_spcl {
char c_dev[NAMELEN]; /* name of dumpped device */
char c_host[NAMELEN]; /* name of dumpped host */
int32_t c_flags; /* additional information */
int32_t c_firstrec; /* first record on volume */
int32_t c_spare[32]; /* reserved for future uses */
int32_t c_old_firstrec; /* first record on volume */
int64_t c_date; /* date of this dump */
int64_t c_ddate; /* date of previous dump */
int64_t c_tapea; /* logical block of this record */
int64_t c_firstrec; /* first record on volume */
int32_t c_spare[24]; /* reserved for future uses */
} s_spcl;
} u_spcl;
#define spcl u_spcl.s_spcl
@ -104,8 +136,7 @@ union u_spcl {
/*
* flag values
*/
#define DR_NEWHEADER 0x0001 /* new format tape header */
#define DR_NEWINODEFMT 0x0002 /* new format inodes on tape */
/* None at the moment */
#define DUMPOUTFMT "%-32s %c %s" /* for printf */
/* name, level, ctime(date) */

View File

@ -1,7 +1,16 @@
/* $NetBSD: ufs.c,v 1.20 1998/03/01 07:15:39 ross Exp $ */
/*-
* Copyright (c) 1993
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Marshall
* Kirk McKusick and Network Associates Laboratories, the Security
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
* research program
*
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@ -107,7 +116,10 @@ struct fs_ops ufs_fsops = {
struct file {
off_t f_seekp; /* seek pointer */
struct fs *f_fs; /* pointer to super-block */
struct dinode f_di; /* copy of on-disk inode */
union dinode {
struct ufs1_dinode di1;
struct ufs2_dinode di2;
} f_di; /* copy of on-disk inode */
int f_nindir[NIADDR];
/* number of blocks mapped by
indirect block at level i */
@ -115,20 +127,20 @@ struct file {
level i */
size_t f_blksize[NIADDR];
/* size of buffer */
daddr_t f_blkno[NIADDR];/* disk address of block in buffer */
ufs2_daddr_t f_blkno[NIADDR];/* disk address of block in buffer */
ufs2_daddr_t f_buf_blkno; /* block number of data block */
char *f_buf; /* buffer for data block */
size_t f_buf_size; /* size of data block */
daddr_t f_buf_blkno; /* block number of data block */
};
#define DIP(fp, field) \
((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \
(fp)->f_di.di1.field : (fp)->f_di.di2.field)
static int read_inode(ino_t, struct open_file *);
static int block_map(struct open_file *, daddr_t, daddr_t *);
static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *);
static int buf_read_file(struct open_file *, char **, size_t *);
static int buf_write_file(struct open_file *, char *, size_t *);
static int search_directory(char *, struct open_file *, ino_t *);
#ifdef COMPAT_UFS
static void ffs_oldfscompat(struct fs *);
#endif
/*
* Read a new inode into a file structure.
@ -162,12 +174,12 @@ read_inode(inumber, f)
goto out;
}
{
struct dinode *dp;
dp = (struct dinode *)buf;
fp->f_di = dp[ino_to_fsbo(fs, inumber)];
}
if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
fp->f_di.di1 = ((struct ufs1_dinode *)buf)
[ino_to_fsbo(fs, inumber)];
else
fp->f_di.di2 = ((struct ufs2_dinode *)buf)
[ino_to_fsbo(fs, inumber)];
/*
* Clear out the old buffers
@ -191,15 +203,14 @@ read_inode(inumber, f)
static int
block_map(f, file_block, disk_block_p)
struct open_file *f;
daddr_t file_block;
daddr_t *disk_block_p; /* out */
ufs2_daddr_t file_block;
ufs2_daddr_t *disk_block_p; /* out */
{
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
int level;
int idx;
daddr_t ind_block_num;
u_int32_t *ind_p;
ufs2_daddr_t ind_block_num;
int rc;
/*
@ -227,7 +238,7 @@ block_map(f, file_block, disk_block_p)
if (file_block < NDADDR) {
/* Direct block. */
*disk_block_p = fp->f_di.di_db[file_block];
*disk_block_p = DIP(fp, di_db[file_block]);
return (0);
}
@ -249,7 +260,7 @@ block_map(f, file_block, disk_block_p)
return (EFBIG);
}
ind_block_num = fp->f_di.di_ib[level];
ind_block_num = DIP(fp, di_ib[level]);
for (; level >= 0; level--) {
if (ind_block_num == 0) {
@ -274,15 +285,16 @@ block_map(f, file_block, disk_block_p)
fp->f_blkno[level] = ind_block_num;
}
ind_p = (u_int32_t *)fp->f_blk[level];
if (level > 0) {
idx = file_block / fp->f_nindir[level - 1];
file_block %= fp->f_nindir[level - 1];
} else
idx = file_block;
ind_block_num = ind_p[idx];
if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
ind_block_num = ((ufs1_daddr_t *)fp->f_blk[level])[idx];
else
ind_block_num = ((ufs2_daddr_t *)fp->f_blk[level])[idx];
}
*disk_block_p = ind_block_num;
@ -302,8 +314,8 @@ buf_write_file(f, buf_p, size_p)
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
long off;
daddr_t file_block;
daddr_t disk_block;
ufs_lbn_t file_block;
ufs2_daddr_t disk_block;
size_t block_size;
int rc;
@ -312,21 +324,22 @@ buf_write_file(f, buf_p, size_p)
*/
off = blkoff(fs, fp->f_seekp);
file_block = lblkno(fs, fp->f_seekp);
block_size = dblksize(fs, &fp->f_di, file_block);
block_size = sblksize(fs, DIP(fp, di_size), file_block);
rc = block_map(f, file_block, &disk_block);
if (rc)
return (rc);
if (disk_block == 0)
return (EFBIG); /* Because we can't allocate space on the drive */
/* Because we can't allocate space on the drive */
return (EFBIG);
/*
* Truncate buffer at end of file, and at the end of
* this block.
*/
if (*size_p > fp->f_di.di_size - fp->f_seekp)
*size_p = fp->f_di.di_size - fp->f_seekp;
if (*size_p > DIP(fp, di_size) - fp->f_seekp)
*size_p = DIP(fp, di_size) - fp->f_seekp;
if (*size_p > block_size - off)
*size_p = block_size - off;
@ -353,7 +366,7 @@ buf_write_file(f, buf_p, size_p)
/*
* Copy the user data into the cached block.
*/
bcopy(buf_p,fp->f_buf + off,*size_p);
bcopy(buf_p, fp->f_buf + off, *size_p);
/*
* Write the block out to storage.
@ -379,14 +392,14 @@ buf_read_file(f, buf_p, size_p)
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
long off;
daddr_t file_block;
daddr_t disk_block;
ufs_lbn_t file_block;
ufs2_daddr_t disk_block;
size_t block_size;
int rc;
off = blkoff(fs, fp->f_seekp);
file_block = lblkno(fs, fp->f_seekp);
block_size = dblksize(fs, &fp->f_di, file_block);
block_size = sblksize(fs, DIP(fp, di_size), file_block);
if (file_block != fp->f_buf_blkno) {
if (fp->f_buf == (char *)0)
@ -422,8 +435,8 @@ buf_read_file(f, buf_p, size_p)
/*
* But truncate buffer at end of file.
*/
if (*size_p > fp->f_di.di_size - fp->f_seekp)
*size_p = fp->f_di.di_size - fp->f_seekp;
if (*size_p > DIP(fp, di_size) - fp->f_seekp)
*size_p = DIP(fp, di_size) - fp->f_seekp;
return (0);
}
@ -449,7 +462,7 @@ search_directory(name, f, inumber_p)
length = strlen(name);
fp->f_seekp = 0;
while (fp->f_seekp < fp->f_di.di_size) {
while (fp->f_seekp < DIP(fp, di_size)) {
rc = buf_read_file(f, &buf, &buf_size);
if (rc)
return (rc);
@ -479,6 +492,8 @@ search_directory(name, f, inumber_p)
return (ENOENT);
}
static int sblock_try[] = SBLOCKSEARCH;
/*
* Open a file.
*/
@ -492,7 +507,7 @@ ufs_open(upath, f)
ino_t inumber, parent_inumber;
struct file *fp;
struct fs *fs;
int rc;
int i, rc;
size_t buf_size;
int nlinks = 0;
char namebuf[MAXPATHLEN+1];
@ -505,28 +520,35 @@ ufs_open(upath, f)
f->f_fsdata = (void *)fp;
/* allocate space and read super block */
fs = malloc(SBSIZE);
fs = malloc(SBLOCKSIZE);
fp->f_fs = fs;
twiddle();
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
SBLOCK, SBSIZE, (char *)fs, &buf_size);
if (rc)
goto out;
if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC ||
fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) {
/*
* Try reading the superblock in each of its possible locations.
*/
for (i = 0; sblock_try[i] != -1; i++) {
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
sblock_try[i] / DEV_BSIZE, SBLOCKSIZE,
(char *)fs, &buf_size);
if (rc)
goto out;
if ((fs->fs_magic == FS_UFS1_MAGIC ||
(fs->fs_magic == FS_UFS2_MAGIC &&
fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) &&
buf_size == SBLOCKSIZE &&
fs->fs_bsize <= MAXBSIZE &&
fs->fs_bsize >= sizeof(struct fs))
break;
}
if (sblock_try[i] == -1) {
rc = EINVAL;
goto out;
}
#ifdef COMPAT_UFS
ffs_oldfscompat(fs);
#endif
/*
* Calculate indirect block levels.
*/
{
int mult;
ufs2_daddr_t mult;
int level;
mult = 1;
@ -558,7 +580,7 @@ ufs_open(upath, f)
/*
* Check that current node is a directory.
*/
if ((fp->f_di.di_mode & IFMT) != IFDIR) {
if ((DIP(fp, di_mode) & IFMT) != IFDIR) {
rc = ENOTDIR;
goto out;
}
@ -600,8 +622,8 @@ ufs_open(upath, f)
/*
* Check for symbolic link.
*/
if ((fp->f_di.di_mode & IFMT) == IFLNK) {
int link_len = fp->f_di.di_size;
if ((DIP(fp, di_mode) & IFMT) == IFLNK) {
int link_len = DIP(fp, di_size);
int len;
len = strlen(cp);
@ -615,19 +637,22 @@ ufs_open(upath, f)
bcopy(cp, &namebuf[link_len], len + 1);
if (link_len < fs->fs_maxsymlinklen) {
bcopy(fp->f_di.di_shortlink, namebuf,
(unsigned) link_len);
if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
cp = (caddr_t)(fp->f_di.di1.di_db);
else
cp = (caddr_t)(fp->f_di.di2.di_db);
bcopy(cp, namebuf, (unsigned) link_len);
} else {
/*
* Read file for symbolic link
*/
size_t buf_size;
daddr_t disk_block;
ufs2_daddr_t disk_block;
struct fs *fs = fp->f_fs;
if (!buf)
buf = malloc(fs->fs_bsize);
rc = block_map(f, (daddr_t)0, &disk_block);
rc = block_map(f, (ufs2_daddr_t)0, &disk_block);
if (rc)
goto out;
@ -715,7 +740,7 @@ ufs_read(f, start, size, resid)
char *addr = start;
while (size != 0) {
if (fp->f_seekp >= fp->f_di.di_size)
if (fp->f_seekp >= DIP(fp, di_size))
break;
rc = buf_read_file(f, &buf, &buf_size);
@ -756,7 +781,7 @@ ufs_write(f, start, size, resid)
csize = size;
while ((size != 0) && (csize != 0)) {
if (fp->f_seekp >= fp->f_di.di_size)
if (fp->f_seekp >= DIP(fp, di_size))
break;
if (csize >= 512) csize = 512; /* XXX */
@ -790,7 +815,7 @@ ufs_seek(f, offset, where)
fp->f_seekp += offset;
break;
case SEEK_END:
fp->f_seekp = fp->f_di.di_size - offset;
fp->f_seekp = DIP(fp, di_size) - offset;
break;
default:
return (-1);
@ -806,10 +831,10 @@ ufs_stat(f, sb)
struct file *fp = (struct file *)f->f_fsdata;
/* only important stuff */
sb->st_mode = fp->f_di.di_mode;
sb->st_uid = fp->f_di.di_uid;
sb->st_gid = fp->f_di.di_gid;
sb->st_size = fp->f_di.di_size;
sb->st_mode = DIP(fp, di_mode);
sb->st_uid = DIP(fp, di_uid);
sb->st_gid = DIP(fp, di_gid);
sb->st_size = DIP(fp, di_size);
return (0);
}
@ -826,7 +851,7 @@ ufs_readdir(struct open_file *f, struct dirent *d)
* assume that a directory entry will not be split across blocks
*/
again:
if (fp->f_seekp >= fp->f_di.di_size)
if (fp->f_seekp >= DIP(fp, di_size))
return (ENOENT);
error = buf_read_file(f, &buf, &buf_size);
if (error)
@ -839,33 +864,3 @@ ufs_readdir(struct open_file *f, struct dirent *d)
strcpy(d->d_name, dp->d_name);
return (0);
}
#ifdef COMPAT_UFS
/*
* Sanity checks for old file systems.
*
* XXX - goes away some day.
*/
static void
ffs_oldfscompat(fs)
struct fs *fs;
{
int i;
fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
fs->fs_nrpos = 8; /* XXX */
if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
quad_t sizepb = fs->fs_bsize; /* XXX */
/* XXX */
fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
for (i = 0; i < NIADDR; i++) { /* XXX */
sizepb *= NINDIR(fs); /* XXX */
fs->fs_maxfilesize += sizepb; /* XXX */
} /* XXX */
fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
} /* XXX */
}
#endif

View File

@ -19,8 +19,11 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/disklabel.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
static int sblock_try[] = SBLOCKSEARCH;
static int force = 0; /* don't check for zeros, may corrupt kernel */
int
@ -29,7 +32,8 @@ main(int argc, char **argv)
unsigned char *buf_kernel, *buf_fs, *p,*q, *prog;
int fd_kernel, fd_fs, ch, errs=0;
struct stat st_kernel, st_fs;
u_long l;
struct fs *fs;
u_long l, sboff;
prog= *argv;
while ((ch = getopt(argc, argv, "f")) != EOF)
@ -68,17 +72,31 @@ main(int argc, char **argv)
fprintf(stderr,"MFS filesystem signature not found in %s\n",argv[1]);
exit(1);
found:
for (l = 0; sblock_try[l] != -1; l++) {
sboff = sblock_try[l];
fs = (struct fs *)(buf_fs + sboff);
if ((fs->fs_magic == FS_UFS1_MAGIC ||
(fs->fs_magic == FS_UFS2_MAGIC &&
fs->fs_sblockloc == numfrags(fs, sblock_try[l]))) &&
fs->fs_bsize <= MAXBSIZE &&
fs->fs_bsize >= sizeof(struct fs))
break;
}
if (sblock_try[l] == -1) {
fprintf(stderr, "Cannot find filesystem\n");
exit(2);
}
if (!force)
for(l=0,q= p + SBOFF; l < st_fs.st_size - SBOFF ; l++,q++ )
for(l=0,q= p + sboff; l < st_fs.st_size - sboff ; l++,q++ )
if (*q)
goto fail;
memcpy(p+SBOFF,buf_fs+SBOFF,st_fs.st_size-SBOFF);
memcpy(p+sboff,buf_fs+sboff,st_fs.st_size-sboff);
lseek(fd_kernel,0L,SEEK_SET);
if (st_kernel.st_size != write(fd_kernel,buf_kernel,st_kernel.st_size))
{ perror(argv[1]); exit(2); }
exit(0);
fail:
l += SBOFF;
l += sboff;
fprintf(stderr,"Obstruction in kernel after %ld bytes (%ld Kbyte)\n",
l, l/1024);
fprintf(stderr,"Filesystem is %ld bytes (%ld Kbyte)\n",

View File

@ -18,7 +18,6 @@ SUBDIR= adjkerntz \
dump \
dumpfs \
dumpon \
ffsinfo \
fsck \
fsck_ffs \
fsck_msdosfs \

View File

@ -59,8 +59,8 @@ static const char rcsid[] =
#include <sys/stat.h>
#include <sys/disklabel.h>
#include <ufs/ffs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <err.h>
#include <dirent.h>
@ -73,7 +73,7 @@ static const char rcsid[] =
union {
struct fs fs;
char fsx[SBSIZE];
char fsx[SBLOCKSIZE];
} ufs;
#define sblock ufs.fs
union {
@ -91,6 +91,11 @@ char buf[MAXBSIZE];
void rdfs(daddr_t, int, char *);
int chkuse(daddr_t, int);
/*
* Possible superblock locations ordered from most to least likely.
*/
static int sblock_try[] = SBLOCKSEARCH;
static void
usage(void)
{
@ -108,6 +113,7 @@ main(int argc, char *argv[])
DIR *dirp;
char name[2 * MAXPATHLEN];
char *name_dir_end;
int i;
if (argc < 3)
usage();
@ -134,7 +140,19 @@ main(int argc, char *argv[])
if ((fsi = open(name, O_RDONLY)) < 0)
err(6, "%s", name);
fs = &sblock;
rdfs(SBOFF, SBSIZE, (char *)fs);
for (i = 0; sblock_try[i] != -1; i++) {
rdfs(sblock_try[i] / dev_bsize, SBLOCKSIZE, (char *)fs);
if ((fs->fs_magic == FS_UFS1_MAGIC ||
(fs->fs_magic == FS_UFS2_MAGIC &&
fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) &&
fs->fs_bsize <= MAXBSIZE &&
fs->fs_bsize >= sizeof(struct fs))
break;
}
if (sblock_try[i] == -1) {
printf("Cannot find filesystem\n");
exit(7);
}
dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
for (argc -= 2, argv += 2; argc > 0; argc--, argv++) {
number = atol(*argv);

View File

@ -61,6 +61,11 @@ static const char rcsid[] =
#include <stdio.h>
#include <unistd.h>
/*
* Possible superblock locations ordered from most to least likely.
*/
static int sblock_try[] = SBLOCKSEARCH;
static void
usage(void)
{
@ -74,13 +79,13 @@ main(argc, argv)
char *argv[];
{
struct fs *sbp;
struct dinode *ip;
int fd;
struct dinode ibuf[MAXBSIZE / sizeof (struct dinode)];
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
char *ibuf[MAXBSIZE];
long generation, bsize;
off_t offset;
int inonum;
char *fs, sblock[SBSIZE];
int i, fd, inonum;
char *fs, sblock[SBLOCKSIZE];
if (argc < 3)
usage();
@ -90,15 +95,23 @@ main(argc, argv)
/* get the superblock. */
if ((fd = open(fs, O_RDWR, 0)) < 0)
err(1, "%s", fs);
if (lseek(fd, (off_t)(SBLOCK * DEV_BSIZE), SEEK_SET) < 0)
err(1, "%s", fs);
if (read(fd, sblock, sizeof(sblock)) != sizeof(sblock))
errx(1, "%s: can't read superblock", fs);
sbp = (struct fs *)sblock;
if (sbp->fs_magic != FS_MAGIC)
errx(1, "%s: superblock magic number 0x%x, not 0x%x",
fs, sbp->fs_magic, FS_MAGIC);
for (i = 0; sblock_try[i] != -1; i++) {
if (lseek(fd, (off_t)(sblock_try[i]), SEEK_SET) < 0)
err(1, "%s", fs);
if (read(fd, sblock, sizeof(sblock)) != sizeof(sblock))
errx(1, "%s: can't read superblock", fs);
sbp = (struct fs *)sblock;
if ((sbp->fs_magic == FS_UFS1_MAGIC ||
(sbp->fs_magic == FS_UFS2_MAGIC &&
sbp->fs_sblockloc == numfrags(sbp, sblock_try[i]))) &&
sbp->fs_bsize <= MAXBSIZE &&
sbp->fs_bsize >= sizeof(struct fs))
break;
}
if (sblock_try[i] == -1) {
fprintf(stderr, "Cannot find filesystem\n");
exit(2);
}
bsize = sbp->fs_bsize;
/* remaining arguments are inode numbers. */
@ -119,13 +132,25 @@ main(argc, argv)
if (read(fd, ibuf, bsize) != bsize)
err(1, "%s", fs);
/* get the inode within the block. */
ip = &ibuf[ino_to_fsbo(sbp, inonum)];
if (sbp->fs_magic == FS_UFS2_MAGIC) {
/* get the inode within the block. */
dp2 = &(((struct ufs2_dinode *)ibuf)
[ino_to_fsbo(sbp, inonum)]);
/* clear the inode, and bump the generation count. */
generation = ip->di_gen + 1;
memset(ip, 0, sizeof(*ip));
ip->di_gen = generation;
/* clear the inode, and bump the generation count. */
generation = dp2->di_gen + 1;
memset(dp2, 0, sizeof(*dp2));
dp2->di_gen = generation;
} else {
/* get the inode within the block. */
dp1 = &(((struct ufs1_dinode *)ibuf)
[ino_to_fsbo(sbp, inonum)]);
/* clear the inode, and bump the generation count. */
generation = dp1->di_gen + 1;
memset(dp1, 0, sizeof(*dp1));
dp1->di_gen = generation;
}
/* backup and write the block */
if (lseek(fd, (off_t)-bsize, SEEK_CUR) < 0)

View File

@ -35,9 +35,6 @@
* $FreeBSD$
*/
#define MAXINOPB (MAXBSIZE / sizeof(struct dinode))
#define MAXNINDIR (MAXBSIZE / sizeof(ufs_daddr_t))
/*
* Dump maps used to describe what is to be dumped.
*/
@ -102,22 +99,23 @@ void timeest(void);
time_t unctime(char *str);
/* mapping rouintes */
struct dinode;
long blockest(struct dinode *dp);
union dinode;
long blockest(union dinode *dp);
int mapfiles(ino_t maxino, long *tapesize);
int mapdirs(ino_t maxino, long *tapesize);
/* file dumping routines */
void blksout(ufs_daddr_t *blkp, int frags, ino_t ino);
void bread(ufs_daddr_t blkno, char *buf, int size);
void dumpino(struct dinode *dp, ino_t ino);
void ufs1_blksout(ufs1_daddr_t *blkp, int frags, ino_t ino);
void ufs2_blksout(ufs2_daddr_t *blkp, int frags, ino_t ino);
void bread(ufs2_daddr_t blkno, char *buf, int size);
void dumpino(union dinode *dp, ino_t ino);
void dumpmap(char *map, int type, ino_t ino);
void writeheader(ino_t ino);
/* tape writing routines */
int alloctape(void);
void close_rewind(void);
void dumpblock(ufs_daddr_t blkno, int size);
void dumpblock(ufs2_daddr_t blkno, int size);
void startnewtape(int top);
void trewind(void);
void writerec(char *dp, int isspcl);
@ -127,7 +125,7 @@ void dumpabort(int signo);
void getfstab(void);
char *rawname(char *cp);
struct dinode *getino(ino_t inum);
union dinode *getino(ino_t inum, int *mode);
/* rdump routines */
#ifdef RDUMP

View File

@ -152,9 +152,9 @@ getdumptime(void)
continue;
if (ddp->dd_level >= level)
continue;
if (ddp->dd_ddate <= _time32_to_time(spcl.c_ddate))
if (ddp->dd_ddate <= _time64_to_time(spcl.c_ddate))
continue;
spcl.c_ddate = _time_to_time32(ddp->dd_ddate);
spcl.c_ddate = _time_to_time64(ddp->dd_ddate);
lastlevel = ddp->dd_level;
}
}
@ -202,7 +202,7 @@ putdumptime(void)
found:
(void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name));
dtwalk->dd_level = level;
dtwalk->dd_ddate = _time32_to_time(spcl.c_date);
dtwalk->dd_ddate = _time64_to_time(spcl.c_date);
ITITERATE(i, dtwalk) {
dumprecout(df, dtwalk);
@ -215,7 +215,7 @@ putdumptime(void)
if (spcl.c_date == 0) {
tmsg = "the epoch\n";
} else {
time_t t = _time32_to_time(spcl.c_date);
time_t t = _time64_to_time(spcl.c_date);
tmsg = ctime(&t);
}
msg("level %c dump on %s", level, tmsg);

View File

@ -68,10 +68,6 @@ static const char rcsid[] =
#include "dump.h"
#include "pathnames.h"
#ifndef SBOFF
#define SBOFF (SBLOCK * DEV_BSIZE)
#endif
int notify = 0; /* notify operator flag */
int blockswritten = 0; /* number of blocks written on current tape */
int tapeno = 0; /* current tape number */
@ -83,6 +79,11 @@ long dev_bsize = 1; /* recalculated below */
long blocksperfile; /* output blocks per file */
char *host = NULL; /* remote host (if any) */
/*
* Possible superblock locations ordered from most to least likely.
*/
static int sblock_try[] = SBLOCKSEARCH;
static long numarg(const char *, long, long);
static void obsolete(int *, char **[]);
static void usage(void) __dead2;
@ -93,17 +94,17 @@ main(int argc, char *argv[])
struct stat sb;
ino_t ino;
int dirty;
struct dinode *dp;
union dinode *dp;
struct fstab *dt;
char *map;
int ch;
int ch, mode;
int i, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1;
int just_estimate = 0;
ino_t maxino;
char *tmsg;
time_t t;
spcl.c_date = _time_to_time32(time(NULL));
spcl.c_date = _time_to_time64(time(NULL));
tsize = 0; /* Default later, based on 'c' option for cart tapes */
if ((tape = getenv("TAPE")) == NULL)
@ -316,14 +317,14 @@ main(int argc, char *argv[])
if (spcl.c_date == 0) {
tmsg = "the epoch\n";
} else {
time_t t = _time32_to_time(spcl.c_date);
time_t t = _time64_to_time(spcl.c_date);
tmsg = ctime(&t);
}
msg("Date of this level %c dump: %s", level, tmsg);
if (spcl.c_ddate == 0) {
tmsg = "the epoch\n";
} else {
time_t t = _time32_to_time(spcl.c_ddate);
time_t t = _time64_to_time(spcl.c_ddate);
tmsg = ctime(&t);
}
msg("Date of last level %c dump: %s", lastlevel, tmsg);
@ -343,9 +344,18 @@ main(int argc, char *argv[])
errx(X_STARTUP, "%s: unknown filesystem", disk);
sync();
sblock = (struct fs *)sblock_buf;
bread(SBOFF, (char *) sblock, SBSIZE);
if (sblock->fs_magic != FS_MAGIC)
quit("bad sblock magic number\n");
for (i = 0; sblock_try[i] != -1; i++) {
bread(sblock_try[i] >> dev_bshift, (char *) sblock, SBLOCKSIZE);
if ((sblock->fs_magic == FS_UFS1_MAGIC ||
(sblock->fs_magic == FS_UFS2_MAGIC &&
sblock->fs_sblockloc ==
numfrags(sblock, sblock_try[i]))) &&
sblock->fs_bsize <= MAXBSIZE &&
sblock->fs_bsize >= sizeof(struct fs))
break;
}
if (sblock_try[i] == -1)
quit("Cannot find filesystem superblock\n");
dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1);
dev_bshift = ffs(dev_bsize) - 1;
if (dev_bsize != (1 << dev_bshift))
@ -353,10 +363,6 @@ main(int argc, char *argv[])
tp_bshift = ffs(TP_BSIZE) - 1;
if (TP_BSIZE != (1 << tp_bshift))
quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE);
#ifdef FS_44INODEFMT
if (sblock->fs_inodefmt >= FS_44INODEFMT)
spcl.c_flags |= DR_NEWINODEFMT;
#endif
maxino = sblock->fs_ipg * sblock->fs_ncg;
mapsize = roundup(howmany(maxino, NBBY), TP_BSIZE);
usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
@ -456,8 +462,8 @@ main(int argc, char *argv[])
/*
* Skip directory inodes deleted and maybe reallocated
*/
dp = getino(ino);
if ((dp->di_mode & IFMT) != IFDIR)
dp = getino(ino, &mode);
if (mode != IFDIR)
continue;
(void)dumpino(dp, ino);
}
@ -466,8 +472,6 @@ main(int argc, char *argv[])
setproctitle("%s: pass 4: regular files", disk);
msg("dumping (Pass IV) [regular files]\n");
for (map = dumpinomap, ino = 1; ino < maxino; ino++) {
int mode;
if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */
dirty = *map++;
else
@ -477,8 +481,7 @@ main(int argc, char *argv[])
/*
* Skip inodes deleted and reallocated as directories.
*/
dp = getino(ino);
mode = dp->di_mode & IFMT;
dp = getino(ino, &mode);
if (mode == IFDIR)
continue;
(void)dumpino(dp, ino);
@ -489,9 +492,9 @@ main(int argc, char *argv[])
for (i = 0; i < ntrec; i++)
writeheader(maxino - 1);
if (pipeout)
msg("DUMP: %ld tape blocks\n", spcl.c_tapea);
msg("DUMP: %qd tape blocks\n", spcl.c_tapea);
else
msg("DUMP: %ld tape blocks on %d volume%s\n",
msg("DUMP: %qd tape blocks on %d volume%s\n",
spcl.c_tapea, spcl.c_volume,
(spcl.c_volume == 1) ? "" : "s");
@ -499,7 +502,7 @@ main(int argc, char *argv[])
if (tend_writing - tstart_writing == 0)
msg("finished in less than a second\n");
else
msg("finished in %d seconds, throughput %d KBytes/sec\n",
msg("finished in %d seconds, throughput %qd KBytes/sec\n",
tend_writing - tstart_writing,
spcl.c_tapea / (tend_writing - tstart_writing));

View File

@ -44,6 +44,8 @@ static const char rcsid[] =
#include <sys/wait.h>
#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <errno.h>
#include <fstab.h>
#include <grp.h>

View File

@ -62,7 +62,7 @@ static const char rcsid[] =
#include "dump.h"
int writesize; /* size of malloc()ed buffer for tape */
long lastspclrec = -1; /* tape block number of last written header */
int64_t lastspclrec = -1; /* tape block number of last written header */
int trecno = 0; /* next record to write in current block */
extern long blocksperfile; /* number of blocks per output file */
long blocksthisvol; /* number of blocks on current output file */
@ -87,21 +87,21 @@ static void rollforward(void);
* The following structure defines the instruction packets sent to slaves.
*/
struct req {
ufs_daddr_t dblk;
ufs2_daddr_t dblk;
int count;
};
int reqsiz;
#define SLAVES 3 /* 1 slave writing, 1 reading, 1 for slack */
struct slave {
int tapea; /* header number at start of this chunk */
int64_t tapea; /* header number at start of this chunk */
int64_t firstrec; /* record number of this block */
int count; /* count to next header (used for TS_TAPE */
/* after EOT) */
int inode; /* inode that we are currently dealing with */
int fd; /* FD for this slave */
int pid; /* PID for this slave */
int sent; /* 1 == we've sent this slave requests */
int firstrec; /* record number of this block */
char (*tblock)[TP_BSIZE]; /* buffer for data blocks */
struct req *req; /* buffer for requests */
} slaves[SLAVES+1];
@ -161,7 +161,7 @@ void
writerec(char *dp, int isspcl)
{
slp->req[trecno].dblk = (ufs_daddr_t)0;
slp->req[trecno].dblk = (ufs2_daddr_t)0;
slp->req[trecno].count = 1;
/* Can't do a structure assignment due to alignment problems */
bcopy(dp, *(nextblock)++, sizeof (union u_spcl));
@ -174,9 +174,10 @@ writerec(char *dp, int isspcl)
}
void
dumpblock(ufs_daddr_t blkno, int size)
dumpblock(ufs2_daddr_t blkno, int size)
{
int avail, tpblks, dblkno;
int avail, tpblks;
ufs2_daddr_t dblkno;
dblkno = fsbtodb(sblock, blkno);
tpblks = size >> tp_bshift;
@ -226,7 +227,7 @@ static void
flushtape(void)
{
int i, blks, got;
long lastfirstrec;
int64_t lastfirstrec;
int siz = (char *)nextblock - (char *)slp->req;
@ -385,7 +386,8 @@ rollforward(void)
{
struct req *p, *q, *prev;
struct slave *tslp;
int i, size, savedtapea, got;
int i, size, got;
int64_t savedtapea;
union u_spcl *ntb, *otb;
tslp = &slaves[SLAVES];
ntb = (union u_spcl *)tslp->tblock[1];
@ -618,9 +620,7 @@ startnewtape(int top)
spcl.c_firstrec = slp->firstrec;
spcl.c_volume++;
spcl.c_type = TS_TAPE;
spcl.c_flags |= DR_NEWHEADER;
writeheader((ino_t)slp->inode);
spcl.c_flags &=~ DR_NEWHEADER;
if (tapeno > 1)
msg("Volume %d begins with blocks from inode %d\n",
tapeno, slp->inode);

View File

@ -53,22 +53,25 @@ static const char rcsid[] =
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "dump.h"
union dinode {
struct ufs1_dinode dp1;
struct ufs2_dinode dp2;
};
#define DIP(dp, field) \
((sblock->fs_magic == FS_UFS1_MAGIC) ? \
(dp)->dp1.field : (dp)->dp2.field)
#define HASDUMPEDFILE 0x1
#define HASSUBDIRS 0x2
#ifdef FS_44INODEFMT
typedef quad_t fsizeT;
#else
typedef long fsizeT;
#endif
static int dirindir(ino_t ino, ufs_daddr_t blkno, int level, long *size,
static int dirindir(ino_t ino, ufs2_daddr_t blkno, int level, long *size,
long *tapesize, int nodump);
static void dmpindir(ino_t ino, ufs_daddr_t blk, int level, fsizeT *size);
static int searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
static void dmpindir(ino_t ino, ufs2_daddr_t blk, int level, off_t *size);
static int searchdir(ino_t ino, ufs2_daddr_t blkno, long size, long filesize,
long *tapesize, int nodump);
/*
@ -79,7 +82,7 @@ static int searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
* hence the estimate may be high.
*/
long
blockest(struct dinode *dp)
blockest(union dinode *dp)
{
long blkest, sizeest;
@ -97,11 +100,11 @@ blockest(struct dinode *dp)
* dump blocks (sizeest vs. blkest in the indirect block
* calculation).
*/
blkest = howmany(dbtob(dp->di_blocks), TP_BSIZE);
sizeest = howmany(dp->di_size, TP_BSIZE);
blkest = howmany(dbtob(DIP(dp, di_blocks)), TP_BSIZE);
sizeest = howmany(DIP(dp, di_size), TP_BSIZE);
if (blkest > sizeest)
blkest = sizeest;
if (dp->di_size > sblock->fs_bsize * NDADDR) {
if (DIP(dp, di_size) > sblock->fs_bsize * NDADDR) {
/* calculate the number of indirect blocks on the dump tape */
blkest +=
howmany(sizeest - NDADDR * sblock->fs_bsize / TP_BSIZE,
@ -112,13 +115,13 @@ blockest(struct dinode *dp)
/* Auxiliary macro to pick up files changed since previous dump. */
#define CHANGEDSINCE(dp, t) \
((dp)->di_mtime >= (t) || (dp)->di_ctime >= (t))
(DIP(dp, di_mtime) >= (t) || DIP(dp, di_ctime) >= (t))
/* The WANTTODUMP macro decides whether a file should be dumped. */
#ifdef UF_NODUMP
#define WANTTODUMP(dp) \
(CHANGEDSINCE(dp, spcl.c_ddate) && \
(nonodump || ((dp)->di_flags & UF_NODUMP) != UF_NODUMP))
(nonodump || (DIP(dp, di_flags) & UF_NODUMP) != UF_NODUMP))
#else
#define WANTTODUMP(dp) CHANGEDSINCE(dp, spcl.c_ddate)
#endif
@ -135,12 +138,12 @@ mapfiles(ino_t maxino, long *tapesize)
{
int mode;
ino_t ino;
struct dinode *dp;
union dinode *dp;
int anydirskipped = 0;
for (ino = ROOTINO; ino < maxino; ino++) {
dp = getino(ino);
if ((mode = (dp->di_mode & IFMT)) == 0)
dp = getino(ino, &mode);
if (mode == 0)
continue;
/*
* Everything must go in usedinomap so that a check
@ -160,7 +163,7 @@ mapfiles(ino_t maxino, long *tapesize)
continue;
}
if (mode == IFDIR) {
if (!nonodump && (dp->di_flags & UF_NODUMP))
if (!nonodump && (DIP(dp, di_flags) & UF_NODUMP))
CLRINO(ino, usedinomap);
anydirskipped = 1;
}
@ -188,11 +191,11 @@ mapfiles(ino_t maxino, long *tapesize)
int
mapdirs(ino_t maxino, long *tapesize)
{
struct dinode *dp;
union dinode *dp;
int i, isdir, nodump;
char *map;
ino_t ino;
struct dinode di;
union dinode di;
long filesize;
int ret, change = 0;
@ -212,23 +215,29 @@ mapdirs(ino_t maxino, long *tapesize)
nodump = !nonodump && (TSTINO(ino, usedinomap) == 0);
if ((isdir & 1) == 0 || (TSTINO(ino, dumpinomap) && !nodump))
continue;
dp = getino(ino);
di = *dp; /* inode buf may change in searchdir(). */
filesize = di.di_size;
dp = getino(ino, &i);
/*
* inode buf may change in searchdir().
*/
if (sblock->fs_magic == FS_UFS1_MAGIC)
di.dp1 = dp->dp1;
else
di.dp2 = dp->dp2;
filesize = DIP(&di, di_size);
for (ret = 0, i = 0; filesize > 0 && i < NDADDR; i++) {
if (di.di_db[i] != 0)
ret |= searchdir(ino, di.di_db[i],
(long)dblksize(sblock, dp, i),
filesize, tapesize, nodump);
if (DIP(&di, di_db[i]) != 0)
ret |= searchdir(ino, DIP(&di, di_db[i]),
(long)sblksize(sblock, DIP(dp, di_size), i),
filesize, tapesize, nodump);
if (ret & HASDUMPEDFILE)
filesize = 0;
else
filesize -= sblock->fs_bsize;
}
for (i = 0; filesize > 0 && i < NIADDR; i++) {
if (di.di_ib[i] == 0)
if (DIP(&di, di_ib[i]) == 0)
continue;
ret |= dirindir(ino, di.di_ib[i], i, &filesize,
ret |= dirindir(ino, DIP(&di, di_ib[i]), i, &filesize,
tapesize, nodump);
}
if (ret & HASDUMPEDFILE) {
@ -256,17 +265,27 @@ mapdirs(ino_t maxino, long *tapesize)
* require the directory to be dumped.
*/
static int
dirindir(ino_t ino, ufs_daddr_t blkno, int ind_level, long *filesize,
long *tapesize, int nodump)
dirindir(
ino_t ino,
ufs2_daddr_t blkno,
int ind_level,
long *filesize,
long *tapesize,
int nodump)
{
int ret = 0;
int i;
ufs_daddr_t idblk[MAXNINDIR];
static caddr_t idblk;
bread(fsbtodb(sblock, blkno), (char *)idblk, (int)sblock->fs_bsize);
if (idblk == NULL && (idblk = malloc(sblock->fs_bsize)) == NULL)
quit("dirindir: cannot allocate indirect memory.\n");
bread(fsbtodb(sblock, blkno), idblk, (int)sblock->fs_bsize);
if (ind_level <= 0) {
for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) {
blkno = idblk[i];
if (sblock->fs_magic == FS_UFS1_MAGIC)
blkno = ((ufs1_daddr_t *)idblk)[i];
else
blkno = ((ufs2_daddr_t *)idblk)[i];
if (blkno != 0)
ret |= searchdir(ino, blkno, sblock->fs_bsize,
*filesize, tapesize, nodump);
@ -279,7 +298,10 @@ dirindir(ino_t ino, ufs_daddr_t blkno, int ind_level, long *filesize,
}
ind_level--;
for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) {
blkno = idblk[i];
if (sblock->fs_magic == FS_UFS1_MAGIC)
blkno = ((ufs1_daddr_t *)idblk)[i];
else
blkno = ((ufs2_daddr_t *)idblk)[i];
if (blkno != 0)
ret |= dirindir(ino, blkno, ind_level, filesize,
tapesize, nodump);
@ -293,14 +315,22 @@ dirindir(ino_t ino, ufs_daddr_t blkno, int ind_level, long *filesize,
* contains any subdirectories.
*/
static int
searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
long *tapesize, int nodump)
searchdir(
ino_t ino,
ufs2_daddr_t blkno,
long size,
long filesize,
long *tapesize,
int nodump)
{
int mode;
struct direct *dp;
struct dinode *ip;
union dinode *ip;
long loc, ret = 0;
char dblk[MAXBSIZE];
static caddr_t dblk;
if (dblk == NULL && (dblk = malloc(sblock->fs_bsize)) == NULL)
quit("searchdir: cannot allocate indirect memory.\n");
bread(fsbtodb(sblock, blkno), dblk, (int)size);
if (filesize < size)
size = filesize;
@ -320,7 +350,7 @@ searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
continue;
}
if (nodump) {
ip = getino(dp->d_ino);
ip = getino(dp->d_ino, &mode);
if (TSTINO(dp->d_ino, dumpinomap)) {
CLRINO(dp->d_ino, dumpinomap);
*tapesize -= blockest(ip);
@ -329,7 +359,7 @@ searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
* Add back to dumpdirmap and remove from usedinomap
* to propagate nodump.
*/
if ((ip->di_mode & IFMT) == IFDIR) {
if (mode == IFDIR) {
SETINO(dp->d_ino, dumpdirmap);
CLRINO(dp->d_ino, usedinomap);
ret |= HASSUBDIRS;
@ -356,10 +386,12 @@ searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
* Dump the contents of an inode to tape.
*/
void
dumpino(struct dinode *dp, ino_t ino)
dumpino(union dinode *dp, ino_t ino)
{
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
int ind_level, cnt;
fsizeT size;
off_t size;
char buf[TP_BSIZE];
if (newtape) {
@ -367,10 +399,36 @@ dumpino(struct dinode *dp, ino_t ino)
dumpmap(dumpinomap, TS_BITS, ino);
}
CLRINO(ino, dumpinomap);
spcl.c_dinode = *dp;
if (sblock->fs_magic == FS_UFS1_MAGIC) {
spcl.c_mode = dp->dp1.di_mode;
spcl.c_size = dp->dp1.di_size;
spcl.c_atime = _time32_to_time(dp->dp1.di_atime);
spcl.c_atimensec = dp->dp1.di_atimensec;
spcl.c_mtime = _time32_to_time(dp->dp1.di_mtime);
spcl.c_mtimensec = dp->dp1.di_mtimensec;
spcl.c_createtime = 0;
spcl.c_createtimensec = 0;
spcl.c_rdev = dp->dp1.di_rdev;
spcl.c_file_flags = dp->dp1.di_flags;
spcl.c_uid = dp->dp1.di_uid;
spcl.c_gid = dp->dp1.di_gid;
} else {
spcl.c_mode = dp->dp2.di_mode;
spcl.c_size = dp->dp2.di_size;
spcl.c_atime = _time64_to_time(dp->dp2.di_atime);
spcl.c_atimensec = dp->dp2.di_atimensec;
spcl.c_mtime = _time64_to_time(dp->dp2.di_mtime);
spcl.c_mtimensec = dp->dp2.di_mtimensec;
spcl.c_createtime = _time64_to_time(dp->dp2.di_createtime);
spcl.c_createtimensec = dp->dp2.di_creatensec;
spcl.c_rdev = dp->dp2.di_rdev;
spcl.c_file_flags = dp->dp2.di_flags;
spcl.c_uid = dp->dp2.di_uid;
spcl.c_gid = dp->dp2.di_gid;
}
spcl.c_type = TS_INODE;
spcl.c_count = 0;
switch (dp->di_mode & S_IFMT) {
switch (DIP(dp, di_mode) & S_IFMT) {
case 0:
/*
@ -383,13 +441,18 @@ dumpino(struct dinode *dp, ino_t ino)
* Check for short symbolic link.
*/
#ifdef FS_44INODEFMT
if (dp->di_size > 0 &&
dp->di_size < sblock->fs_maxsymlinklen) {
if (DIP(dp, di_size) > 0 &&
DIP(dp, di_size) < sblock->fs_maxsymlinklen) {
spcl.c_addr[0] = 1;
spcl.c_count = 1;
writeheader(ino);
memmove(buf, dp->di_shortlink, (u_long)dp->di_size);
buf[dp->di_size] = '\0';
if (sblock->fs_magic == FS_UFS1_MAGIC)
memmove(buf, (caddr_t)dp->dp1.di_db,
(u_long)DIP(dp, di_size));
else
memmove(buf, (caddr_t)dp->dp2.di_db,
(u_long)DIP(dp, di_size));
buf[DIP(dp, di_size)] = '\0';
writerec(buf, 0);
return;
}
@ -398,7 +461,7 @@ dumpino(struct dinode *dp, ino_t ino)
case S_IFDIR:
case S_IFREG:
if (dp->di_size > 0)
if (DIP(dp, di_size) > 0)
break;
/* fall through */
@ -410,18 +473,22 @@ dumpino(struct dinode *dp, ino_t ino)
return;
default:
msg("Warning: undefined file type 0%o\n", dp->di_mode & IFMT);
msg("Warning: undefined file type 0%o\n",
DIP(dp, di_mode) & IFMT);
return;
}
if (dp->di_size > NDADDR * sblock->fs_bsize)
if (DIP(dp, di_size) > NDADDR * sblock->fs_bsize)
cnt = NDADDR * sblock->fs_frag;
else
cnt = howmany(dp->di_size, sblock->fs_fsize);
blksout(&dp->di_db[0], cnt, ino);
if ((size = dp->di_size - NDADDR * sblock->fs_bsize) <= 0)
cnt = howmany(DIP(dp, di_size), sblock->fs_fsize);
if (sblock->fs_magic == FS_UFS1_MAGIC)
ufs1_blksout(&dp->dp1.di_db[0], cnt, ino);
else
ufs2_blksout(&dp->dp2.di_db[0], cnt, ino);
if ((size = DIP(dp, di_size) - NDADDR * sblock->fs_bsize) <= 0)
return;
for (ind_level = 0; ind_level < NIADDR; ind_level++) {
dmpindir(ino, dp->di_ib[ind_level], ind_level, &size);
dmpindir(ino, DIP(dp, di_ib[ind_level]), ind_level, &size);
if (size <= 0)
return;
}
@ -431,13 +498,15 @@ dumpino(struct dinode *dp, ino_t ino)
* Read indirect blocks, and pass the data blocks to be dumped.
*/
static void
dmpindir(ino_t ino, ufs_daddr_t blk, int ind_level, fsizeT *size)
dmpindir(ino_t ino, ufs2_daddr_t blk, int ind_level, off_t *size)
{
int i, cnt;
ufs_daddr_t idblk[MAXNINDIR];
static caddr_t idblk;
if (idblk == NULL && (idblk = malloc(sblock->fs_bsize)) == NULL)
quit("dmpindir: cannot allocate indirect memory.\n");
if (blk != 0)
bread(fsbtodb(sblock, blk), (char *)idblk, (int) sblock->fs_bsize);
bread(fsbtodb(sblock, blk), idblk, (int) sblock->fs_bsize);
else
memset(idblk, 0, (int)sblock->fs_bsize);
if (ind_level <= 0) {
@ -446,12 +515,20 @@ dmpindir(ino_t ino, ufs_daddr_t blk, int ind_level, fsizeT *size)
else
cnt = NINDIR(sblock) * sblock->fs_frag;
*size -= NINDIR(sblock) * sblock->fs_bsize;
blksout(&idblk[0], cnt, ino);
if (sblock->fs_magic == FS_UFS1_MAGIC)
ufs1_blksout((ufs1_daddr_t *)idblk, cnt, ino);
else
ufs2_blksout((ufs2_daddr_t *)idblk, cnt, ino);
return;
}
ind_level--;
for (i = 0; i < NINDIR(sblock); i++) {
dmpindir(ino, idblk[i], ind_level, size);
if (sblock->fs_magic == FS_UFS1_MAGIC)
dmpindir(ino, ((ufs1_daddr_t *)idblk)[i], ind_level,
size);
else
dmpindir(ino, ((ufs2_daddr_t *)idblk)[i], ind_level,
size);
if (*size <= 0)
return;
}
@ -461,9 +538,44 @@ dmpindir(ino_t ino, ufs_daddr_t blk, int ind_level, fsizeT *size)
* Collect up the data into tape record sized buffers and output them.
*/
void
blksout(ufs_daddr_t *blkp, int frags, ino_t ino)
ufs1_blksout(ufs1_daddr_t *blkp, int frags, ino_t ino)
{
ufs_daddr_t *bp;
ufs1_daddr_t *bp;
int i, j, count, blks, tbperdb;
blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
tbperdb = sblock->fs_bsize >> tp_bshift;
for (i = 0; i < blks; i += TP_NINDIR) {
if (i + TP_NINDIR > blks)
count = blks;
else
count = i + TP_NINDIR;
for (j = i; j < count; j++)
if (blkp[j / tbperdb] != 0)
spcl.c_addr[j - i] = 1;
else
spcl.c_addr[j - i] = 0;
spcl.c_count = count - i;
writeheader(ino);
bp = &blkp[i / tbperdb];
for (j = i; j < count; j += tbperdb, bp++)
if (*bp != 0) {
if (j + tbperdb <= count)
dumpblock(*bp, (int)sblock->fs_bsize);
else
dumpblock(*bp, (count - j) * TP_BSIZE);
}
spcl.c_type = TS_ADDR;
}
}
/*
* Collect up the data into tape record sized buffers and output them.
*/
void
ufs2_blksout(ufs2_daddr_t *blkp, int frags, ino_t ino)
{
ufs2_daddr_t *bp;
int i, j, count, blks, tbperdb;
blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
@ -517,7 +629,7 @@ writeheader(ino_t ino)
int32_t sum, cnt, *lp;
spcl.c_inumber = ino;
spcl.c_magic = NFS_MAGIC;
spcl.c_magic = FS_UFS2_MAGIC;
spcl.c_checksum = 0;
lp = (int32_t *)&spcl;
sum = 0;
@ -532,20 +644,32 @@ writeheader(ino_t ino)
writerec((char *)&spcl, 1);
}
struct dinode *
getino(ino_t inum)
union dinode *
getino(ino_t inum, int *modep)
{
static ufs_daddr_t minino, maxino;
static struct dinode inoblock[MAXINOPB];
static ino_t minino, maxino;
static caddr_t inoblock;
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
if (inoblock == NULL && (inoblock = malloc(sblock->fs_bsize)) == NULL)
quit("cannot allocate inode memory.\n");
curino = inum;
if (inum >= minino && inum < maxino)
return (&inoblock[inum - minino]);
bread(fsbtodb(sblock, ino_to_fsba(sblock, inum)), (char *)inoblock,
goto gotit;
bread(fsbtodb(sblock, ino_to_fsba(sblock, inum)), inoblock,
(int)sblock->fs_bsize);
minino = inum - (inum % INOPB(sblock));
maxino = minino + INOPB(sblock);
return (&inoblock[inum - minino]);
gotit:
if (sblock->fs_magic == FS_UFS1_MAGIC) {
dp1 = &((struct ufs1_dinode *)inoblock)[inum - minino];
*modep = (dp1->di_mode & IFMT);
return ((union dinode *)dp1);
}
dp2 = &((struct ufs2_dinode *)inoblock)[inum - minino];
*modep = (dp2->di_mode & IFMT);
return ((union dinode *)dp2);
}
/*
@ -558,7 +682,7 @@ int breaderrors = 0;
#define BREADEMAX 32
void
bread(ufs_daddr_t blkno, char *buf, int size)
bread(ufs2_daddr_t blkno, char *buf, int size)
{
int cnt, i;

View File

@ -1,4 +1,16 @@
/*
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Marshall
* Kirk McKusick and Network Associates Laboratories, the Security
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
* research program
*
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* Copyright (c) 1983, 1992, 1993
* The Regents of the University of California. All rights reserved.
*
@ -49,6 +61,7 @@ static const char rcsid[] =
#include <sys/time.h>
#include <sys/disklabel.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <err.h>
@ -72,6 +85,11 @@ union {
long dev_bsize = 1;
/*
* Possible superblock locations ordered from most to least likely.
*/
static int sblock_try[] = SBLOCKSEARCH;
int dumpfs(const char *);
int dumpcg(const char *, int, int);
void pbits(void *, int);
@ -107,67 +125,94 @@ int
dumpfs(const char *name)
{
ssize_t n;
time_t time;
int64_t fssize;
int fd, c, i, j, k, size;
if ((fd = open(name, O_RDONLY, 0)) < 0)
goto err;
if (lseek(fd, (off_t)SBOFF, SEEK_SET) == (off_t)-1)
goto err;
if ((n = read(fd, &afs, SBSIZE)) == -1)
goto err;
if (n != SBSIZE) {
warnx("%s: non-existent or truncated superblock, skipped",
name);
(void)close(fd);
return (1);
for (i = 0; sblock_try[i] != -1; i++) {
if (lseek(fd, (off_t)sblock_try[i], SEEK_SET) == (off_t)-1)
goto err;
if ((n = read(fd, &afs, SBLOCKSIZE)) == -1)
goto err;
if ((afs.fs_magic == FS_UFS1_MAGIC ||
(afs.fs_magic == FS_UFS2_MAGIC &&
afs.fs_sblockloc == numfrags(&afs, sblock_try[i]))) &&
afs.fs_bsize <= MAXBSIZE &&
afs.fs_bsize >= sizeof(struct fs))
break;
}
if (sblock_try[i] == -1) {
fprintf(stderr, "Cannot find filesystem superblock\n");
return (1);
}
if (afs.fs_magic != FS_MAGIC) {
warnx("%s: superblock has bad magic number, skipped", name);
(void)close(fd);
return (1);
}
if (afs.fs_postblformat == FS_42POSTBLFMT)
afs.fs_nrpos = 8;
dev_bsize = afs.fs_fsize / fsbtodb(&afs, 1);
printf("magic\t%x\ttime\t%s", afs.fs_magic,
ctime(&afs.fs_time));
printf("id\t[ %x %x ]\n", afs.fs_id[0], afs.fs_id[1]);
printf("cylgrp\t%s\tinodes\t%s\n",
afs.fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic",
afs.fs_inodefmt < FS_44INODEFMT ? "4.2/4.3BSD" : "4.4BSD");
printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_ndir,
afs.fs_cstotal.cs_nifree, afs.fs_cstotal.cs_nffree);
printf("ncg\t%d\tncyl\t%d\tsize\t%d\tblocks\t%d\n",
afs.fs_ncg, afs.fs_ncyl, afs.fs_size, afs.fs_dsize);
if (afs.fs_magic == FS_UFS2_MAGIC) {
fssize = afs.fs_size;
time = afs.fs_time;
printf("magic\t%x (UFS2)\ttime\t%s",
afs.fs_magic, ctime(&time));
printf("offset\t%qd\tid\t[ %x %x ]\n",
afs.fs_sblockloc, afs.fs_id[0], afs.fs_id[1]);
printf("ncg\t%d\tsize\t%qd\tblocks\t%d\n",
afs.fs_ncg, fssize, afs.fs_dsize);
} else {
fssize = afs.fs_old_size;
printf("magic\t%x (UFS1)\ttime\t%s",
afs.fs_magic, ctime(&afs.fs_old_time));
printf("id\t[ %x %x ]\n", afs.fs_id[0], afs.fs_id[1]);
printf("ncg\t%d\tsize\t%qd\tblocks\t%d\n",
afs.fs_ncg, fssize, afs.fs_dsize);
}
printf("bsize\t%d\tshift\t%d\tmask\t0x%08x\n",
afs.fs_bsize, afs.fs_bshift, afs.fs_bmask);
printf("fsize\t%d\tshift\t%d\tmask\t0x%08x\n",
afs.fs_fsize, afs.fs_fshift, afs.fs_fmask);
printf("frag\t%d\tshift\t%d\tfsbtodb\t%d\n",
afs.fs_frag, afs.fs_fragshift, afs.fs_fsbtodb);
printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n",
afs.fs_cpg, afs.fs_fpg / afs.fs_frag, afs.fs_fpg, afs.fs_ipg);
printf("minfree\t%d%%\toptim\t%s\tmaxcontig %d\tmaxbpg\t%d\n",
printf("minfree\t%d%%\toptim\t%s\tsymlinklen %d\n",
afs.fs_minfree, afs.fs_optim == FS_OPTSPACE ? "space" : "time",
afs.fs_maxcontig, afs.fs_maxbpg);
printf("rotdelay %dms\trps\t%d\n",
afs.fs_rotdelay, afs.fs_rps);
printf("ntrak\t%d\tnsect\t%d\tnpsect\t%d\tspc\t%d\n",
afs.fs_ntrak, afs.fs_nsect, afs.fs_npsect, afs.fs_spc);
printf("symlinklen %d\ttrackskew %d\tinterleave %d\tcontigsumsize %d\n",
afs.fs_maxsymlinklen, afs.fs_trackskew, afs.fs_interleave,
afs.fs_contigsumsize);
printf("nindir\t%d\tinopb\t%d\tnspf\t%d\tmaxfilesize\t%qu\n",
afs.fs_nindir, afs.fs_inopb, afs.fs_nspf, afs.fs_maxfilesize);
afs.fs_maxsymlinklen);
if (afs.fs_magic == FS_UFS2_MAGIC) {
printf("%s %d\tmaxbpg\t%d\tmaxcontig %d\tcontigsumsize %d\n",
"maxbsize", afs.fs_maxbsize, afs.fs_maxbpg,
afs.fs_maxcontig, afs.fs_contigsumsize);
printf("nbfree\t%qd\tndir\t%qd\tnifree\t%qd\tnffree\t%qd\n",
afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_ndir,
afs.fs_cstotal.cs_nifree, afs.fs_cstotal.cs_nffree);
printf("bpg\t%d\tfpg\t%d\tipg\t%d\n",
afs.fs_fpg / afs.fs_frag, afs.fs_fpg, afs.fs_ipg);
printf("nindir\t%d\tinopb\t%d\tmaxfilesize\t%qu\n",
afs.fs_nindir, afs.fs_inopb, afs.fs_maxfilesize);
printf("sbsize\t%d\tcgsize\t%d\tcsaddr\t%d\tcssize\t%d\n",
afs.fs_sbsize, afs.fs_cgsize, afs.fs_csaddr, afs.fs_cssize);
} else {
printf("maxbpg\t%d\tmaxcontig %d\tcontigsumsize %d\n",
afs.fs_maxbpg, afs.fs_maxcontig, afs.fs_contigsumsize);
printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
afs.fs_old_cstotal.cs_nbfree, afs.fs_old_cstotal.cs_ndir,
afs.fs_old_cstotal.cs_nifree, afs.fs_old_cstotal.cs_nffree);
printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n",
afs.fs_old_cpg, afs.fs_fpg / afs.fs_frag, afs.fs_fpg,
afs.fs_ipg);
printf("nindir\t%d\tinopb\t%d\tnspf\t%d\tmaxfilesize\t%qu\n",
afs.fs_nindir, afs.fs_inopb, afs.fs_old_nspf,
afs.fs_maxfilesize);
printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n",
afs.fs_sbsize, afs.fs_cgsize, afs.fs_old_cgoffset,
afs.fs_old_cgmask);
printf("csaddr\t%d\tcssize\t%d\n",
afs.fs_old_csaddr, afs.fs_cssize);
printf("rotdelay %dms\trps\t%d\ttrackskew %d\tinterleave %d\n",
afs.fs_old_rotdelay, afs.fs_old_rps, afs.fs_old_trackskew,
afs.fs_old_interleave);
printf("nsect\t%d\tnpsect\t%d\tspc\t%d\n",
afs.fs_old_nsect, afs.fs_old_npsect, afs.fs_old_spc);
}
printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n",
afs.fs_sblkno, afs.fs_cblkno, afs.fs_iblkno, afs.fs_dblkno);
printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n",
afs.fs_sbsize, afs.fs_cgsize, afs.fs_cgoffset, afs.fs_cgmask);
printf("csaddr\t%d\tcssize\t%d\tshift\t%d\tmask\t0x%08x\n",
afs.fs_csaddr, afs.fs_cssize, afs.fs_csshift, afs.fs_csmask);
printf("cgrotor\t%d\tfmod\t%d\tronly\t%d\tclean\t%d\n",
afs.fs_cgrotor, afs.fs_fmod, afs.fs_ronly, afs.fs_clean);
printf("flags\t");
@ -177,43 +222,24 @@ dumpfs(const char *name)
printf("unclean ");
if (afs.fs_flags & FS_DOSOFTDEP)
printf("soft-updates ");
if ((afs.fs_flags & ~(FS_UNCLEAN | FS_DOSOFTDEP)) != 0)
printf("unknown flags (%#x)",
afs.fs_flags & ~(FS_UNCLEAN | FS_DOSOFTDEP));
if (afs.fs_flags & FS_NEEDSFSCK)
printf("needs fsck run ");
if (afs.fs_flags & FS_INDEXDIRS)
printf("indexed directories ");
if ((afs.fs_flags &
~(FS_UNCLEAN | FS_DOSOFTDEP | FS_NEEDSFSCK | FS_INDEXDIRS)) != 0)
printf("unknown flags (%#x)", afs.fs_flags &
~(FS_UNCLEAN | FS_DOSOFTDEP |
FS_NEEDSFSCK | FS_INDEXDIRS));
putchar('\n');
if (afs.fs_cpc != 0)
printf("blocks available in each of %d rotational positions",
afs.fs_nrpos);
else
printf("(no rotational position table)\n");
for (c = 0; c < afs.fs_cpc; c++) {
printf("\ncylinder number %d:", c);
for (i = 0; i < afs.fs_nrpos; i++) {
if (fs_postbl(&afs, c)[i] == -1)
continue;
printf("\n position %d:\t", i);
for (j = fs_postbl(&afs, c)[i], k = 1; ;
j += fs_rotbl(&afs)[j], k++) {
printf("%5d", j);
if (k % 12 == 0)
printf("\n\t\t");
if (fs_rotbl(&afs)[j] == 0)
break;
}
}
}
printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t");
afs.fs_csp = calloc(1, afs.fs_cssize);
for (i = 0, j = 0; i < afs.fs_cssize; i += afs.fs_bsize, j++) {
size = afs.fs_cssize - i < afs.fs_bsize ?
afs.fs_cssize - i : afs.fs_bsize;
if (lseek(fd,
(off_t)(fsbtodb(&afs, (afs.fs_csaddr + j * afs.fs_frag))) *
(off_t)dev_bsize, SEEK_SET) == (off_t)-1)
goto err;
if (read(fd, (char *)afs.fs_csp + i, size) != size)
goto err;
}
if (lseek(fd,
(off_t)(fsbtodb(&afs, afs.fs_csaddr)) * (off_t)dev_bsize,
SEEK_SET) == (off_t)-1)
goto err;
if (read(fd, (char *)afs.fs_csp, afs.fs_cssize) != afs.fs_cssize)
goto err;
for (i = 0; i < afs.fs_ncg; i++) {
struct csum *cs = &afs.fs_cs(&afs, i);
if (i && i % 4 == 0)
@ -222,13 +248,14 @@ dumpfs(const char *name)
cs->cs_nbfree, cs->cs_ndir, cs->cs_nifree, cs->cs_nffree);
}
printf("\n");
if (afs.fs_ncyl % afs.fs_cpg) {
printf("cylinders in last group %d\n",
i = afs.fs_ncyl % afs.fs_cpg);
printf("blocks in last group %d\n",
i * afs.fs_spc / NSPB(&afs));
if (fssize % afs.fs_fpg) {
if (afs.fs_magic == FS_UFS1_MAGIC)
printf("cylinders in last group %d\n",
howmany(afs.fs_old_size % afs.fs_fpg,
afs.fs_old_spc / afs.fs_old_nspf));
printf("blocks in last group %d\n\n",
(fssize % afs.fs_fpg) / afs.fs_frag);
}
printf("\n");
for (i = 0; i < afs.fs_ncg; i++)
if (dumpcg(name, fd, i))
goto err;
@ -244,6 +271,7 @@ err: if (fd != -1)
int
dumpcg(const char *name, int fd, int c)
{
time_t time;
off_t cur;
int i, j;
@ -255,12 +283,19 @@ dumpcg(const char *name, int fd, int c)
warnx("%s: error reading cg", name);
return (1);
}
printf("magic\t%x\ttell\t%qx\ttime\t%s",
afs.fs_postblformat == FS_42POSTBLFMT ?
((struct ocg *)&acg)->cg_magic : acg.cg_magic,
cur, ctime(&acg.cg_time));
printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n",
acg.cg_cgx, acg.cg_ncyl, acg.cg_niblk, acg.cg_ndblk);
if (afs.fs_magic == FS_UFS2_MAGIC) {
time = acg.cg_time;
printf("magic\t%x\ttell\t%qx\ttime\t%s",
acg.cg_magic, cur, ctime(&time));
printf("cgx\t%d\tndblk\t%d\tniblk\t%d\tinitiblk %d\n",
acg.cg_cgx, acg.cg_ndblk, acg.cg_niblk, acg.cg_initediblk);
} else {
printf("magic\t%x\ttell\t%qx\ttime\t%s",
acg.cg_magic, cur, ctime(&acg.cg_old_time));
printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n",
acg.cg_cgx, acg.cg_old_ncyl, acg.cg_old_niblk,
acg.cg_ndblk);
}
printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
acg.cg_cs.cs_nbfree, acg.cg_cs.cs_ndir,
acg.cg_cs.cs_nifree, acg.cg_cs.cs_nffree);
@ -286,23 +321,10 @@ dumpcg(const char *name, int fd, int c)
pbits(cg_clustersfree(&acg), acg.cg_nclusterblks);
} else
printf("\n");
printf("iused:\t");
printf("inodes used:\t");
pbits(cg_inosused(&acg), afs.fs_ipg);
printf("free:\t");
printf("blks free:\t");
pbits(cg_blksfree(&acg), afs.fs_fpg);
printf("b:\n");
for (i = 0; i < afs.fs_cpg; i++) {
if (cg_blktot(&acg)[i] == 0)
continue;
printf(" c%d:\t(%d)\t", i, cg_blktot(&acg)[i]);
for (j = 0; j < afs.fs_nrpos; j++) {
if (afs.fs_cpc > 0 &&
fs_postbl(&afs, i % afs.fs_cpc)[j] == -1)
continue;
printf(" %d", cg_blks(&afs, &acg, i)[j]);
}
printf("\n");
}
return (0);
};

View File

@ -69,10 +69,10 @@ struct odirtemplate odirhead = {
static int chgino(struct inodesc *);
static int dircheck(struct inodesc *, struct direct *);
static int expanddir(struct dinode *dp, char *name);
static int expanddir(union dinode *dp, char *name);
static void freedir(ino_t ino, ino_t parent);
static struct direct *fsck_readdir(struct inodesc *);
static struct bufarea *getdirblk(ufs_daddr_t blkno, long size);
static struct bufarea *getdirblk(ufs2_daddr_t blkno, long size);
static int lftempname(char *bufp, ino_t ino);
static int mkentry(struct inodesc *);
@ -255,7 +255,7 @@ direrror(ino_t ino, char *errmesg)
void
fileerror(ino_t cwd, ino_t ino, char *errmesg)
{
struct dinode *dp;
union dinode *dp;
char pathbuf[MAXPATHLEN + 1];
pwarn("%s ", errmesg);
@ -269,7 +269,8 @@ fileerror(ino_t cwd, ino_t ino, char *errmesg)
dp = ginode(ino);
if (ftypeok(dp))
pfatal("%s=%s\n",
(dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf);
(DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE",
pathbuf);
else
pfatal("NAME=%s\n", pathbuf);
}
@ -277,11 +278,11 @@ fileerror(ino_t cwd, ino_t ino, char *errmesg)
void
adjust(struct inodesc *idesc, int lcnt)
{
struct dinode *dp;
union dinode *dp;
int saveresolved;
dp = ginode(idesc->id_number);
if (dp->di_nlink == lcnt) {
if (DIP(dp, di_nlink) == lcnt) {
/*
* If we have not hit any unresolved problems, are running
* in preen mode, and are on a filesystem using soft updates,
@ -312,10 +313,10 @@ adjust(struct inodesc *idesc, int lcnt)
}
if (lcnt != 0) {
pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname :
((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"));
((DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE"));
pinode(idesc->id_number);
printf(" COUNT %d SHOULD BE %d",
dp->di_nlink, dp->di_nlink - lcnt);
DIP(dp, di_nlink), DIP(dp, di_nlink) - lcnt);
if (preen || usedsoftdep) {
if (lcnt < 0) {
printf("\n");
@ -326,7 +327,7 @@ adjust(struct inodesc *idesc, int lcnt)
}
if (preen || reply("ADJUST") == 1) {
if (bkgrdflag == 0) {
dp->di_nlink -= lcnt;
DIP(dp, di_nlink) -= lcnt;
inodirty();
} else {
cmd.value = idesc->id_number;
@ -383,7 +384,7 @@ chgino(struct inodesc *idesc)
int
linkup(ino_t orphan, ino_t parentdir, char *name)
{
struct dinode *dp;
union dinode *dp;
int lostdir;
ino_t oldlfdir;
struct inodesc idesc;
@ -391,10 +392,10 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
memset(&idesc, 0, sizeof(struct inodesc));
dp = ginode(orphan);
lostdir = (dp->di_mode & IFMT) == IFDIR;
lostdir = (DIP(dp, di_mode) & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
pinode(orphan);
if (preen && dp->di_size == 0)
if (preen && DIP(dp, di_size) == 0)
return (0);
if (cursnapshot != 0) {
pfatal("FILE LINKUP IN SNAPSHOT");
@ -438,7 +439,7 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
}
}
dp = ginode(lfdir);
if ((dp->di_mode & IFMT) != IFDIR) {
if ((DIP(dp, di_mode) & IFMT) != IFDIR) {
pfatal("lost+found IS NOT A DIRECTORY");
if (reply("REALLOCATE") == 0)
return (0);
@ -475,7 +476,7 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
parentdir != (ino_t)-1)
(void)makeentry(orphan, lfdir, "..");
dp = ginode(lfdir);
dp->di_nlink++;
DIP(dp, di_nlink)++;
inodirty();
inoinfo(lfdir)->ino_linkcnt++;
pwarn("DIR I=%lu CONNECTED. ", (u_long)orphan);
@ -520,7 +521,7 @@ changeino(ino_t dir, char *name, ino_t newnum)
int
makeentry(ino_t parent, ino_t ino, char *name)
{
struct dinode *dp;
union dinode *dp;
struct inodesc idesc;
char pathbuf[MAXPATHLEN + 1];
@ -535,8 +536,8 @@ makeentry(ino_t parent, ino_t ino, char *name)
idesc.id_fix = DONTKNOW;
idesc.id_name = name;
dp = ginode(parent);
if (dp->di_size % DIRBLKSIZ) {
dp->di_size = roundup(dp->di_size, DIRBLKSIZ);
if (DIP(dp, di_size) % DIRBLKSIZ) {
DIP(dp, di_size) = roundup(DIP(dp, di_size), DIRBLKSIZ);
inodirty();
}
if ((ckinode(dp, &idesc) & ALTERED) != 0)
@ -552,23 +553,24 @@ makeentry(ino_t parent, ino_t ino, char *name)
* Attempt to expand the size of a directory
*/
static int
expanddir(struct dinode *dp, char *name)
expanddir(union dinode *dp, char *name)
{
ufs_daddr_t lastbn, newblk;
ufs2_daddr_t lastbn, newblk;
struct bufarea *bp;
char *cp, firstblk[DIRBLKSIZ];
lastbn = lblkno(&sblock, dp->di_size);
if (lastbn >= NDADDR - 1 || dp->di_db[lastbn] == 0 || dp->di_size == 0)
lastbn = lblkno(&sblock, DIP(dp, di_size));
if (lastbn >= NDADDR - 1 || DIP(dp, di_db[lastbn]) == 0 ||
DIP(dp, di_size) == 0)
return (0);
if ((newblk = allocblk(sblock.fs_frag)) == 0)
return (0);
dp->di_db[lastbn + 1] = dp->di_db[lastbn];
dp->di_db[lastbn] = newblk;
dp->di_size += sblock.fs_bsize;
dp->di_blocks += btodb(sblock.fs_bsize);
bp = getdirblk(dp->di_db[lastbn + 1],
(long)dblksize(&sblock, dp, lastbn + 1));
DIP(dp, di_db[lastbn + 1]) = DIP(dp, di_db[lastbn]);
DIP(dp, di_db[lastbn]) = newblk;
DIP(dp, di_size) += sblock.fs_bsize;
DIP(dp, di_blocks) += btodb(sblock.fs_bsize);
bp = getdirblk(DIP(dp, di_db[lastbn + 1]),
sblksize(&sblock, DIP(dp, di_size), lastbn + 1));
if (bp->b_errs)
goto bad;
memmove(firstblk, bp->b_un.b_buf, DIRBLKSIZ);
@ -581,8 +583,8 @@ expanddir(struct dinode *dp, char *name)
cp += DIRBLKSIZ)
memmove(cp, &emptydir, sizeof emptydir);
dirty(bp);
bp = getdirblk(dp->di_db[lastbn + 1],
(long)dblksize(&sblock, dp, lastbn + 1));
bp = getdirblk(DIP(dp, di_db[lastbn + 1]),
sblksize(&sblock, DIP(dp, di_size), lastbn + 1));
if (bp->b_errs)
goto bad;
memmove(bp->b_un.b_buf, &emptydir, sizeof emptydir);
@ -595,10 +597,10 @@ expanddir(struct dinode *dp, char *name)
inodirty();
return (1);
bad:
dp->di_db[lastbn] = dp->di_db[lastbn + 1];
dp->di_db[lastbn + 1] = 0;
dp->di_size -= sblock.fs_bsize;
dp->di_blocks -= btodb(sblock.fs_bsize);
DIP(dp, di_db[lastbn]) = DIP(dp, di_db[lastbn + 1]);
DIP(dp, di_db[lastbn + 1]) = 0;
DIP(dp, di_size) -= sblock.fs_bsize;
DIP(dp, di_blocks) -= btodb(sblock.fs_bsize);
freeblk(newblk, sblock.fs_frag);
return (0);
}
@ -611,7 +613,7 @@ allocdir(ino_t parent, ino_t request, int mode)
{
ino_t ino;
char *cp;
struct dinode *dp;
union dinode *dp;
struct bufarea *bp;
struct inoinfo *inp;
struct dirtemplate *dirp;
@ -621,7 +623,7 @@ allocdir(ino_t parent, ino_t request, int mode)
dirp->dot_ino = ino;
dirp->dotdot_ino = parent;
dp = ginode(ino);
bp = getdirblk(dp->di_db[0], sblock.fs_fsize);
bp = getdirblk(DIP(dp, di_db[0]), sblock.fs_fsize);
if (bp->b_errs) {
freeino(ino);
return (0);
@ -632,10 +634,10 @@ allocdir(ino_t parent, ino_t request, int mode)
cp += DIRBLKSIZ)
memmove(cp, &emptydir, sizeof emptydir);
dirty(bp);
dp->di_nlink = 2;
DIP(dp, di_nlink) = 2;
inodirty();
if (ino == ROOTINO) {
inoinfo(ino)->ino_linkcnt = dp->di_nlink;
inoinfo(ino)->ino_linkcnt = DIP(dp, di_nlink);
cacheino(dp, ino);
return(ino);
}
@ -650,11 +652,11 @@ allocdir(ino_t parent, ino_t request, int mode)
inp->i_dotdot = parent;
inoinfo(ino)->ino_state = inoinfo(parent)->ino_state;
if (inoinfo(ino)->ino_state == DSTATE) {
inoinfo(ino)->ino_linkcnt = dp->di_nlink;
inoinfo(ino)->ino_linkcnt = DIP(dp, di_nlink);
inoinfo(parent)->ino_linkcnt++;
}
dp = ginode(parent);
dp->di_nlink++;
DIP(dp, di_nlink)++;
inodirty();
return (ino);
}
@ -665,11 +667,11 @@ allocdir(ino_t parent, ino_t request, int mode)
static void
freedir(ino_t ino, ino_t parent)
{
struct dinode *dp;
union dinode *dp;
if (ino != parent) {
dp = ginode(parent);
dp->di_nlink--;
DIP(dp, di_nlink)--;
inodirty();
}
freeino(ino);
@ -704,7 +706,7 @@ lftempname(char *bufp, ino_t ino)
* Insure that it is held until another is requested.
*/
static struct bufarea *
getdirblk(ufs_daddr_t blkno, long size)
getdirblk(ufs2_daddr_t blkno, long size)
{
if (pdirbp != 0)

View File

@ -1,4 +1,16 @@
/*
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Marshall
* Kirk McKusick and Network Associates Laboratories, the Security
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
* research program
*
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
@ -43,6 +55,14 @@
#define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */
#define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */
union dinode {
struct ufs1_dinode dp1;
struct ufs2_dinode dp2;
};
#define DIP(dp, field) \
((sblock.fs_magic == FS_UFS1_MAGIC) ? \
(dp)->dp1.field : (dp)->dp2.field)
/*
* Each inode on the filesystem is described by the following structure.
* The linkcnt is initially set to the value in the inode. Each time it
@ -79,19 +99,24 @@ struct inostatlist {
struct bufarea {
struct bufarea *b_next; /* free list queue */
struct bufarea *b_prev; /* free list queue */
ufs_daddr_t b_bno;
ufs2_daddr_t b_bno;
int b_size;
int b_errs;
int b_flags;
union {
char *b_buf; /* buffer space */
ufs_daddr_t *b_indir; /* indirect block */
ufs1_daddr_t *b_indir1; /* UFS1 indirect block */
ufs2_daddr_t *b_indir2; /* UFS2 indirect block */
struct fs *b_fs; /* super block */
struct cg *b_cg; /* cylinder group */
struct dinode *b_dinode; /* inode block */
struct ufs1_dinode *b_dinode1; /* UFS1 inode block */
struct ufs2_dinode *b_dinode2; /* UFS2 inode block */
} b_un;
char b_dirty;
};
#define IBLK(bp, i) \
((sblock.fs_magic == FS_UFS1_MAGIC) ? \
(bp)->b_un.b_indir1[i] : (bp)->b_un.b_indir2[i])
#define B_INUSE 1
@ -110,7 +135,7 @@ struct bufarea *pbp; /* current inode block */
} while (0)
#define initbarea(bp) do { \
(bp)->b_dirty = 0; \
(bp)->b_bno = (ufs_daddr_t)-1; \
(bp)->b_bno = (ufs2_daddr_t)-1; \
(bp)->b_flags = 0; \
} while (0)
@ -127,12 +152,12 @@ struct inodesc {
int (*id_func)(); /* function to be applied to blocks of inode */
ino_t id_number; /* inode number described */
ino_t id_parent; /* for DATA nodes, their parent */
int id_lbn; /* logical block number of current block */
ufs_daddr_t id_blkno; /* current block number being examined */
ufs_lbn_t id_lbn; /* logical block number of current block */
ufs2_daddr_t id_blkno; /* current block number being examined */
int id_numfrags; /* number of frags contained in block */
quad_t id_filesize; /* for DATA nodes, the size of the directory */
off_t id_filesize; /* for DATA nodes, the size of the directory */
ufs2_daddr_t id_entryno;/* for DATA nodes, current entry number */
int id_loc; /* for DATA nodes, current location in dir */
int id_entryno; /* for DATA nodes, current entry number */
struct direct *id_dirp; /* for DATA nodes, ptr to current entry */
char *id_name; /* for DATA nodes, name to find or enter */
char id_type; /* type of descriptor, DATA or ADDR */
@ -165,7 +190,7 @@ struct inodesc {
*/
struct dups {
struct dups *next;
ufs_daddr_t dup;
ufs2_daddr_t dup;
};
struct dups *duplist; /* head of dup list */
struct dups *muldup; /* end of unique duplicate dup block numbers */
@ -189,7 +214,7 @@ struct inoinfo {
ino_t i_dotdot; /* inode number of `..' */
size_t i_isize; /* size of inode */
u_int i_numblks; /* size of block array in bytes */
ufs_daddr_t i_blks[1]; /* actually longer */
ufs2_daddr_t i_blks[1]; /* actually longer */
} **inphead, **inpsort;
long numdirs, dirhash, listmax, inplast;
long countdirs; /* number of directories we actually found */
@ -223,7 +248,7 @@ int fsmodified; /* 1 => write done to filesystem */
int fsreadfd; /* file descriptor for reading filesystem */
int fswritefd; /* file descriptor for writing filesystem */
ufs_daddr_t maxfsblock; /* number of blocks in the filesystem */
ufs2_daddr_t maxfsblock; /* number of blocks in the filesystem */
char *blockmap; /* ptr to primary blk allocation map */
ino_t maxino; /* number of inodes in filesystem */
@ -231,13 +256,19 @@ ino_t lfdir; /* lost & found directory inode number */
char *lfname; /* lost & found directory name */
int lfmode; /* lost & found directory creation mode */
ufs_daddr_t n_blks; /* number of blocks in use */
ufs_daddr_t n_files; /* number of files in use */
ufs2_daddr_t n_blks; /* number of blocks in use */
ino_t n_files; /* number of files in use */
int got_siginfo; /* received a SIGINFO */
#define clearinode(dp) (*(dp) = zino)
struct dinode zino;
#define clearinode(dp) \
if (sblock.fs_magic == FS_UFS1_MAGIC) { \
(dp)->dp1 = ufs1_zino; \
} else { \
(dp)->dp2 = ufs2_zino; \
}
struct ufs1_dinode ufs1_zino;
struct ufs2_dinode ufs2_zino;
#define setbmap(blkno) setbit(blockmap, blkno)
#define testbmap(blkno) isset(blockmap, blkno)
@ -255,44 +286,44 @@ struct fstab;
void adjust(struct inodesc *, int lcnt);
ufs_daddr_t allocblk(long frags);
ufs2_daddr_t allocblk(long frags);
ino_t allocdir(ino_t parent, ino_t request, int mode);
ino_t allocino(ino_t request, int type);
void blkerror(ino_t ino, char *type, ufs_daddr_t blk);
void blkerror(ino_t ino, char *type, ufs2_daddr_t blk);
char *blockcheck(char *name);
int bread(int fd, char *buf, ufs_daddr_t blk, long size);
int bread(int fd, char *buf, ufs2_daddr_t blk, long size);
void bufinit(void);
void bwrite(int fd, char *buf, ufs_daddr_t blk, long size);
void cacheino(struct dinode *dp, ino_t inumber);
void bwrite(int fd, char *buf, ufs2_daddr_t blk, long size);
void cacheino(union dinode *dp, ino_t inumber);
void catch(int);
void catchquit(int);
int changeino(ino_t dir, char *name, ino_t newnum);
int chkrange(ufs_daddr_t blk, int cnt);
int chkrange(ufs2_daddr_t blk, int cnt);
void ckfini(int markclean);
int ckinode(struct dinode *dp, struct inodesc *);
int ckinode(union dinode *dp, struct inodesc *);
void clri(struct inodesc *, char *type, int flag);
int clearentry(struct inodesc *);
void direrror(ino_t ino, char *errmesg);
int dirscan(struct inodesc *);
int dofix(struct inodesc *, char *msg);
void ffs_clrblock(struct fs *, u_char *, ufs_daddr_t);
void ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t);
void ffs_fragacct(struct fs *, int, int32_t [], int);
int ffs_isblock(struct fs *, u_char *, ufs_daddr_t);
void ffs_setblock(struct fs *, u_char *, ufs_daddr_t);
int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
void fileerror(ino_t cwd, ino_t ino, char *errmesg);
int findino(struct inodesc *);
int findname(struct inodesc *);
void flush(int fd, struct bufarea *bp);
void freeblk(ufs_daddr_t blkno, long frags);
void freeblk(ufs2_daddr_t blkno, long frags);
void freeino(ino_t ino);
void freeinodebuf(void);
int ftypeok(struct dinode *dp);
void getblk(struct bufarea *bp, ufs_daddr_t blk, long size);
struct bufarea *getdatablk(ufs_daddr_t blkno, long size);
int ftypeok(union dinode *dp);
void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size);
struct bufarea *getdatablk(ufs2_daddr_t blkno, long size);
struct inoinfo *getinoinfo(ino_t inumber);
struct dinode *getnextinode(ino_t inumber);
union dinode *getnextinode(ino_t inumber);
void getpathname(char *namebuf, ino_t curdir, ino_t ino);
struct dinode *ginode(ino_t inumber);
union dinode *ginode(ino_t inumber);
void infohandler(int sig);
void inocleanup(void);
void inodirty(void);
@ -314,7 +345,7 @@ void propagate(void);
void pwarn(const char *fmt, ...) __printflike(1, 2);
int readsb(int listerr);
int reply(char *question);
void rwerror(char *mesg, ufs_daddr_t blk);
void rwerror(char *mesg, ufs2_daddr_t blk);
void sblock_init(void);
void setinodebuf(ino_t);
int setup(char *dev);

View File

@ -42,6 +42,7 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/disklabel.h>
#include <sys/stat.h>
#include <sys/disklabel.h>
@ -63,9 +64,9 @@ static const char rcsid[] =
long diskreads, totalreads; /* Disk cache statistics */
int
ftypeok(struct dinode *dp)
ftypeok(union dinode *dp)
{
switch (dp->di_mode & IFMT) {
switch (DIP(dp, di_mode) & IFMT) {
case IFDIR:
case IFREG:
@ -78,7 +79,7 @@ ftypeok(struct dinode *dp)
default:
if (debug)
printf("bad file type 0%o\n", dp->di_mode);
printf("bad file type 0%o\n", DIP(dp, di_mode));
return (0);
}
}
@ -181,7 +182,7 @@ bufinit(void)
* Manage a cache of directory blocks.
*/
struct bufarea *
getdatablk(ufs_daddr_t blkno, long size)
getdatablk(ufs2_daddr_t blkno, long size)
{
struct bufarea *bp;
@ -207,9 +208,9 @@ getdatablk(ufs_daddr_t blkno, long size)
}
void
getblk(struct bufarea *bp, ufs_daddr_t blk, long size)
getblk(struct bufarea *bp, ufs2_daddr_t blk, long size)
{
ufs_daddr_t dblk;
ufs2_daddr_t dblk;
totalreads++;
dblk = fsbtodb(&sblock, blk);
@ -251,7 +252,7 @@ flush(int fd, struct bufarea *bp)
}
void
rwerror(char *mesg, ufs_daddr_t blk)
rwerror(char *mesg, ufs2_daddr_t blk)
{
if (bkgrdcheck)
@ -293,9 +294,10 @@ ckfini(int markclean)
return;
}
flush(fswritefd, &sblk);
if (havesb && sblk.b_bno != SBOFF / dev_bsize && cursnapshot == 0 &&
if (havesb && cursnapshot == 0 && sblock.fs_magic == FS_UFS2_MAGIC &&
sblk.b_bno != fsbtodb(&sblock, sblock.fs_sblockloc) &&
!preen && reply("UPDATE STANDARD SUPERBLOCK")) {
sblk.b_bno = SBOFF / dev_bsize;
sblk.b_bno = fsbtodb(&sblock, sblock.fs_sblockloc);
sbdirty();
flush(fswritefd, &sblk);
}
@ -336,7 +338,7 @@ ckfini(int markclean)
}
int
bread(int fd, char *buf, ufs_daddr_t blk, long size)
bread(int fd, char *buf, ufs2_daddr_t blk, long size)
{
char *cp;
int i, errs;
@ -373,7 +375,7 @@ bread(int fd, char *buf, ufs_daddr_t blk, long size)
}
void
bwrite(int fd, char *buf, ufs_daddr_t blk, long size)
bwrite(int fd, char *buf, ufs2_daddr_t blk, long size)
{
int i;
char *cp;
@ -406,7 +408,7 @@ bwrite(int fd, char *buf, ufs_daddr_t blk, long size)
/*
* allocate a data block with the specified number of fragments
*/
ufs_daddr_t
ufs2_daddr_t
allocblk(long frags)
{
int i, j, k, cg, baseblk;
@ -450,7 +452,7 @@ allocblk(long frags)
* Free a previously allocated block
*/
void
freeblk(ufs_daddr_t blkno, long frags)
freeblk(ufs2_daddr_t blkno, long frags)
{
struct inodesc idesc;

View File

@ -40,6 +40,7 @@ static const char rcsid[] =
#endif /* not lint */
#include <sys/param.h>
#include <sys/stdint.h>
#include <sys/time.h>
#include <sys/sysctl.h>
@ -55,16 +56,15 @@ static const char rcsid[] =
static ino_t startinum;
static int iblock(struct inodesc *, long ilevel, quad_t isize);
static int iblock(struct inodesc *, long ilevel, off_t isize);
int
ckinode(struct dinode *dp, struct inodesc *idesc)
ckinode(union dinode *dp, struct inodesc *idesc)
{
ufs_daddr_t *ap;
int ret;
long n, ndb, offset;
struct dinode dino;
quad_t remsize, sizepb;
off_t remsize, sizepb;
int i, offset, ret;
union dinode dino;
ufs2_daddr_t ndb;
mode_t mode;
char pathbuf[MAXPATHLEN + 1];
@ -72,21 +72,25 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
idesc->id_fix = DONTKNOW;
idesc->id_lbn = -1;
idesc->id_entryno = 0;
idesc->id_filesize = dp->di_size;
mode = dp->di_mode & IFMT;
idesc->id_filesize = DIP(dp, di_size);
mode = DIP(dp, di_mode) & IFMT;
if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
dp->di_size < (unsigned)sblock.fs_maxsymlinklen))
DIP(dp, di_size) < (unsigned)sblock.fs_maxsymlinklen))
return (KEEPON);
dino = *dp;
ndb = howmany(dino.di_size, sblock.fs_bsize);
for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
if (sblock.fs_magic == FS_UFS1_MAGIC)
dino.dp1 = dp->dp1;
else
dino.dp2 = dp->dp2;
ndb = howmany(DIP(&dino, di_size), sblock.fs_bsize);
for (i = 0; i < NDADDR; i++) {
idesc->id_lbn++;
if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
if (--ndb == 0 &&
(offset = blkoff(&sblock, DIP(&dino, di_size))) != 0)
idesc->id_numfrags =
numfrags(&sblock, fragroundup(&sblock, offset));
else
idesc->id_numfrags = sblock.fs_frag;
if (*ap == 0) {
if (DIP(&dino, di_db[i]) == 0) {
if (idesc->id_type == DATA && ndb >= 0) {
/* An empty block in a directory XXX */
getpathname(pathbuf, idesc->id_number,
@ -95,8 +99,7 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
dp->di_size = (ap - &dino.di_db[0]) *
sblock.fs_bsize;
DIP(dp, di_size) = i * sblock.fs_bsize;
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
rerun = 1;
@ -106,7 +109,7 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
}
continue;
}
idesc->id_blkno = *ap;
idesc->id_blkno = DIP(&dino, di_db[i]);
if (idesc->id_type != DATA)
ret = (*idesc->id_func)(idesc);
else
@ -115,13 +118,13 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
return (ret);
}
idesc->id_numfrags = sblock.fs_frag;
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
remsize = DIP(&dino, di_size) - sblock.fs_bsize * NDADDR;
sizepb = sblock.fs_bsize;
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
for (i = 0; i < NIADDR; i++) {
sizepb *= NINDIR(&sblock);
if (*ap) {
idesc->id_blkno = *ap;
ret = iblock(idesc, n, remsize);
if (DIP(&dino, di_ib[i])) {
idesc->id_blkno = DIP(&dino, di_ib[i]);
ret = iblock(idesc, i + 1, remsize);
if (ret & STOP)
return (ret);
} else {
@ -134,7 +137,7 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
dp->di_size -= remsize;
DIP(dp, di_size) -= remsize;
remsize = 0;
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
@ -150,16 +153,14 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
}
static int
iblock(struct inodesc *idesc, long ilevel, quad_t isize)
iblock(struct inodesc *idesc, long ilevel, off_t isize)
{
ufs_daddr_t *ap;
ufs_daddr_t *aplim;
struct bufarea *bp;
int i, n, (*func)(), nif;
quad_t sizepb;
off_t sizepb;
char buf[BUFSIZ];
char pathbuf[MAXPATHLEN + 1];
struct dinode *dp;
union dinode *dp;
if (idesc->id_type != DATA) {
func = idesc->id_func;
@ -173,31 +174,30 @@ iblock(struct inodesc *idesc, long ilevel, quad_t isize)
ilevel--;
for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
sizepb *= NINDIR(&sblock);
nif = howmany(isize , sizepb);
if (nif > NINDIR(&sblock))
if (howmany(isize, sizepb) > NINDIR(&sblock))
nif = NINDIR(&sblock);
else
nif = howmany(isize, sizepb);
if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
aplim = &bp->b_un.b_indir[NINDIR(&sblock)];
for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) {
if (*ap == 0)
for (i = nif; i < NINDIR(&sblock); i++) {
if (IBLK(bp, i) == 0)
continue;
(void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu",
(u_long)idesc->id_number);
if (preen) {
pfatal("%s", buf);
} else if (dofix(idesc, buf)) {
*ap = 0;
IBLK(bp, i) = 0;
dirty(bp);
}
}
flush(fswritefd, bp);
}
aplim = &bp->b_un.b_indir[nif];
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
for (i = 0; i < nif; i++) {
if (ilevel == 0)
idesc->id_lbn++;
if (*ap) {
idesc->id_blkno = *ap;
if (IBLK(bp, i)) {
idesc->id_blkno = IBLK(bp, i);
if (ilevel == 0)
n = (*func)(idesc);
else
@ -215,7 +215,7 @@ iblock(struct inodesc *idesc, long ilevel, quad_t isize)
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
dp->di_size -= isize;
DIP(dp, di_size) -= isize;
isize = 0;
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
@ -237,7 +237,7 @@ iblock(struct inodesc *idesc, long ilevel, quad_t isize)
* Return 0 if in range, 1 if out of range.
*/
int
chkrange(ufs_daddr_t blk, int cnt)
chkrange(ufs2_daddr_t blk, int cnt)
{
int c;
@ -280,10 +280,10 @@ chkrange(ufs_daddr_t blk, int cnt)
/*
* General purpose interface for reading inodes.
*/
struct dinode *
union dinode *
ginode(ino_t inumber)
{
ufs_daddr_t iblk;
ufs2_daddr_t iblk;
if (inumber < ROOTINO || inumber > maxino)
errx(EEXIT, "bad inode number %d to ginode", inumber);
@ -295,7 +295,10 @@ ginode(ino_t inumber)
pbp = getdatablk(iblk, sblock.fs_bsize);
startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
}
return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]);
if (sblock.fs_magic == FS_UFS1_MAGIC)
return ((union dinode *)
&pbp->b_un.b_dinode1[inumber % INOPB(&sblock)]);
return ((union dinode *)&pbp->b_un.b_dinode2[inumber % INOPB(&sblock)]);
}
/*
@ -304,14 +307,15 @@ ginode(ino_t inumber)
*/
static ino_t nextino, lastinum, lastvalidinum;
static long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
static struct dinode *inodebuf;
static caddr_t inodebuf;
struct dinode *
union dinode *
getnextinode(ino_t inumber)
{
long size;
ufs_daddr_t dblk;
static struct dinode *dp;
ufs2_daddr_t dblk;
union dinode *dp;
static caddr_t nextinop;
if (inumber != nextino++ || inumber > lastvalidinum)
errx(EEXIT, "bad inode number %d to nextinode", inumber);
@ -329,10 +333,15 @@ getnextinode(ino_t inumber)
* If bread returns an error, it will already have zeroed
* out the buffer, so we do not need to do so here.
*/
(void)bread(fsreadfd, (char *)inodebuf, dblk, size);
dp = inodebuf;
(void)bread(fsreadfd, inodebuf, dblk, size);
nextinop = inodebuf;
}
return (dp++);
dp = (union dinode *)nextinop;
if (sblock.fs_magic == FS_UFS1_MAGIC)
nextinop += sizeof(struct ufs1_dinode);
else
nextinop += sizeof(struct ufs2_dinode);
return (dp);
}
void
@ -349,17 +358,19 @@ setinodebuf(ino_t inum)
if (inodebuf != NULL)
return;
inobufsize = blkroundup(&sblock, INOBUFSIZE);
fullcnt = inobufsize / sizeof(struct dinode);
fullcnt = inobufsize / ((sblock.fs_magic == FS_UFS1_MAGIC) ?
sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode));
readpercg = sblock.fs_ipg / fullcnt;
partialcnt = sblock.fs_ipg % fullcnt;
partialsize = partialcnt * sizeof(struct dinode);
partialsize = partialcnt * ((sblock.fs_magic == FS_UFS1_MAGIC) ?
sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode));
if (partialcnt != 0) {
readpercg++;
} else {
partialcnt = fullcnt;
partialsize = inobufsize;
}
if ((inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
if ((inodebuf = malloc((unsigned)inobufsize)) == NULL)
errx(EEXIT, "cannot allocate space for inode buffer");
}
@ -380,17 +391,17 @@ freeinodebuf(void)
* Enter inodes into the cache.
*/
void
cacheino(struct dinode *dp, ino_t inumber)
cacheino(union dinode *dp, ino_t inumber)
{
struct inoinfo *inp;
struct inoinfo **inpp;
int blks;
struct inoinfo *inp, **inpp;
int i, blks;
blks = howmany(dp->di_size, sblock.fs_bsize);
if (blks > NDADDR)
if (howmany(DIP(dp, di_size), sblock.fs_bsize) > NDADDR)
blks = NDADDR + NIADDR;
else
blks = howmany(DIP(dp, di_size), sblock.fs_bsize);
inp = (struct inoinfo *)
malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t));
malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs2_daddr_t));
if (inp == NULL)
errx(EEXIT, "cannot increase directory list");
inpp = &inphead[inumber % dirhash];
@ -399,9 +410,13 @@ cacheino(struct dinode *dp, ino_t inumber)
inp->i_parent = inumber == ROOTINO ? ROOTINO : (ino_t)0;
inp->i_dotdot = (ino_t)0;
inp->i_number = inumber;
inp->i_isize = dp->di_size;
inp->i_numblks = blks * sizeof(ufs_daddr_t);
memmove(&inp->i_blks[0], &dp->di_db[0], (size_t)inp->i_numblks);
inp->i_isize = DIP(dp, di_size);
inp->i_numblks = blks;
for (i = 0; i < (blks < NDADDR ? blks : NDADDR); i++)
inp->i_blks[i] = DIP(dp, di_db[i]);
if (blks > NDADDR)
for (i = 0; i < NIADDR; i++)
inp->i_blks[NDADDR + i] = DIP(dp, di_ib[i]);
if (inplast == listmax) {
listmax += 100;
inpsort = (struct inoinfo **)realloc((char *)inpsort,
@ -456,12 +471,12 @@ inodirty(void)
void
clri(struct inodesc *idesc, char *type, int flag)
{
struct dinode *dp;
union dinode *dp;
dp = ginode(idesc->id_number);
if (flag == 1) {
pwarn("%s %s", type,
(dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE");
(DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE");
pinode(idesc->id_number);
}
if (preen || reply("CLEAR") == 1) {
@ -475,7 +490,7 @@ clri(struct inodesc *idesc, char *type, int flag)
inodirty();
} else {
cmd.value = idesc->id_number;
cmd.size = -dp->di_nlink;
cmd.size = -DIP(dp, di_nlink);
if (debug)
printf("adjrefcnt ino %ld amt %ld\n",
(long)cmd.value, cmd.size);
@ -530,7 +545,7 @@ clearentry(struct inodesc *idesc)
void
pinode(ino_t ino)
{
struct dinode *dp;
union dinode *dp;
char *p;
struct passwd *pw;
time_t t;
@ -540,24 +555,24 @@ pinode(ino_t ino)
return;
dp = ginode(ino);
printf(" OWNER=");
if ((pw = getpwuid((int)dp->di_uid)) != 0)
if ((pw = getpwuid((int)DIP(dp, di_uid))) != 0)
printf("%s ", pw->pw_name);
else
printf("%u ", (unsigned)dp->di_uid);
printf("MODE=%o\n", dp->di_mode);
printf("%u ", (unsigned)DIP(dp, di_uid));
printf("MODE=%o\n", DIP(dp, di_mode));
if (preen)
printf("%s: ", cdevname);
printf("SIZE=%qu ", dp->di_size);
t = dp->di_mtime;
printf("SIZE=%qu ", DIP(dp, di_size));
t = DIP(dp, di_mtime);
p = ctime(&t);
printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]);
}
void
blkerror(ino_t ino, char *type, ufs_daddr_t blk)
blkerror(ino_t ino, char *type, ufs2_daddr_t blk)
{
pfatal("%ld %s I=%lu", (long)blk, type, (u_long)ino);
pfatal("%lld %s I=%lu", (intmax_t)blk, type, (u_long)ino);
printf("\n");
switch (inoinfo(ino)->ino_state) {
@ -586,7 +601,7 @@ ino_t
allocino(ino_t request, int type)
{
ino_t ino;
struct dinode *dp;
union dinode *dp;
struct cg *cgp = &cgrp;
int cg;
@ -619,18 +634,20 @@ allocino(ino_t request, int type)
}
cgdirty();
dp = ginode(ino);
dp->di_db[0] = allocblk((long)1);
if (dp->di_db[0] == 0) {
DIP(dp, di_db[0]) = allocblk((long)1);
if (DIP(dp, di_db[0]) == 0) {
inoinfo(ino)->ino_state = USTATE;
return (0);
}
dp->di_mode = type;
dp->di_flags = 0;
dp->di_atime = time(NULL);
dp->di_mtime = dp->di_ctime = dp->di_atime;
dp->di_mtimensec = dp->di_ctimensec = dp->di_atimensec = 0;
dp->di_size = sblock.fs_fsize;
dp->di_blocks = btodb(sblock.fs_fsize);
DIP(dp, di_mode) = type;
DIP(dp, di_flags) = 0;
DIP(dp, di_atime) = time(NULL);
DIP(dp, di_mtime) = DIP(dp, di_ctime) = DIP(dp, di_atime);
DIP(dp, di_mtimensec) = 0;
DIP(dp, di_ctimensec) = 0;
DIP(dp, di_atimensec) = 0;
DIP(dp, di_size) = sblock.fs_fsize;
DIP(dp, di_blocks) = btodb(sblock.fs_fsize);
n_files++;
inodirty();
inoinfo(ino)->ino_type = IFTODT(type);
@ -644,7 +661,7 @@ void
freeino(ino_t ino)
{
struct inodesc idesc;
struct dinode *dp;
union dinode *dp;
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;

View File

@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mount.h>
#include <sys/resource.h>
#include <sys/sysctl.h>
#include <sys/disklabel.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/ufsmount.h>
@ -95,6 +96,9 @@ main(int argc, char *argv[])
case 'c':
skipclean = 0;
cvtlevel = argtoi('c', "conversion level", optarg, 10);
if (cvtlevel < 3)
errx(EEXIT, "cannot do level %d conversion",
cvtlevel);
break;
case 'd':
@ -180,14 +184,14 @@ argtoi(int flag, char *req, char *str, int base)
static int
checkfilesys(char *filesys)
{
ufs_daddr_t n_ffree, n_bfree;
ufs2_daddr_t n_ffree, n_bfree;
struct ufs_args args;
struct dups *dp;
struct statfs *mntp;
struct zlncnt *zlnp;
ufs_daddr_t blks;
ufs_daddr_t files;
ufs2_daddr_t blks;
int cylno, size;
ino_t files;
cdevname = filesys;
if (debug && preen)
@ -367,10 +371,9 @@ checkfilesys(char *filesys)
pwarn("Reclaimed: %ld directories, %ld files, %d fragments\n",
countdirs, (long)files - countdirs, blks);
}
pwarn("%ld files, %ld used, %ld free ",
(long)n_files, (long)n_blks, (long)(n_ffree +
sblock.fs_frag * n_bfree));
printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
pwarn("%ld files, %ld used, %qu free ",
(long)n_files, (long)n_blks, n_ffree + sblock.fs_frag * n_bfree);
printf("(%qu frags, %qu blocks, %.1f%% fragmentation)\n",
n_ffree, n_bfree, n_ffree * 100.0 / sblock.fs_dsize);
if (debug) {
if (files < 0)
@ -404,7 +407,8 @@ checkfilesys(char *filesys)
*/
for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
bwrite(fswritefd, (char *)&sblock,
fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE);
fsbtodb(&sblock, cgsblock(&sblock, cylno)),
SBLOCKSIZE);
}
if (rerun)
resolved = 0;

View File

@ -52,8 +52,8 @@ static const char rcsid[] =
#include "fsck.h"
static ufs_daddr_t badblk;
static ufs_daddr_t dupblk;
static ufs2_daddr_t badblk;
static ufs2_daddr_t dupblk;
static ino_t lastino; /* last inode in use */
static void checkinode(ino_t inumber, struct inodesc *);
@ -61,11 +61,12 @@ static void checkinode(ino_t inumber, struct inodesc *);
void
pass1(void)
{
u_int8_t *cp;
ino_t inumber;
int c, i, cgd, inosused;
struct inostat *info;
struct inodesc idesc;
ino_t inumber, inosused;
ufs2_daddr_t i, cgd;
u_int8_t *cp;
int c;
/*
* Set filesystem reserved blocks in used block map.
@ -93,7 +94,11 @@ pass1(void)
for (c = 0; c < sblock.fs_ncg; c++) {
inumber = c * sblock.fs_ipg;
setinodebuf(inumber);
inosused = sblock.fs_ipg;
getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize);
if (sblock.fs_magic == FS_UFS2_MAGIC)
inosused = cgrp.cg_initediblk;
else
inosused = sblock.fs_ipg;
if (got_siginfo) {
printf("%s: phase 1: cyl group %d of %d (%d%%)\n",
cdevname, c, sblock.fs_ncg,
@ -108,10 +113,9 @@ pass1(void)
* read only those inodes in from disk.
*/
if (preen && usedsoftdep) {
getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize);
if (!cg_chkmagic(&cgrp))
pfatal("CG %d: BAD MAGIC NUMBER\n", c);
cp = &cg_inosused(&cgrp)[(sblock.fs_ipg - 1) / NBBY];
cp = &cg_inosused(&cgrp)[(inosused - 1) / NBBY];
for ( ; inosused > 0; inosused -= NBBY, cp--) {
if (*cp == 0)
continue;
@ -157,9 +161,10 @@ pass1(void)
* to the size necessary to describe the inodes that we
* really found.
*/
inosused = lastino - (c * sblock.fs_ipg);
if (inosused < 0)
if (lastino < (c * sblock.fs_ipg))
inosused = 0;
else
inosused = lastino - (c * sblock.fs_ipg);
inostathead[c].il_numalloced = inosused;
if (inosused == 0) {
free(inostathead[c].il_stat);
@ -180,21 +185,29 @@ pass1(void)
static void
checkinode(ino_t inumber, struct inodesc *idesc)
{
struct dinode *dp;
union dinode *dp;
struct zlncnt *zlnp;
u_int64_t kernmaxfilesize;
ufs_daddr_t ndb, j;
off_t kernmaxfilesize;
ufs2_daddr_t ndb;
mode_t mode;
char *symbuf;
int j;
dp = getnextinode(inumber);
mode = dp->di_mode & IFMT;
mode = DIP(dp, di_mode) & IFMT;
if (mode == 0) {
if (memcmp(dp->di_db, zino.di_db,
NDADDR * sizeof(ufs_daddr_t)) ||
memcmp(dp->di_ib, zino.di_ib,
NIADDR * sizeof(ufs_daddr_t)) ||
dp->di_mode || dp->di_size) {
if ((sblock.fs_magic == FS_UFS1_MAGIC &&
(memcmp(dp->dp1.di_db, ufs1_zino.di_db,
NDADDR * sizeof(ufs1_daddr_t)) ||
memcmp(dp->dp1.di_ib, ufs1_zino.di_ib,
NIADDR * sizeof(ufs1_daddr_t)) ||
dp->dp1.di_mode || dp->dp1.di_size)) ||
(sblock.fs_magic == FS_UFS2_MAGIC &&
(memcmp(dp->dp2.di_db, ufs2_zino.di_db,
NDADDR * sizeof(ufs2_daddr_t)) ||
memcmp(dp->dp2.di_ib, ufs2_zino.di_ib,
NIADDR * sizeof(ufs2_daddr_t)) ||
dp->dp2.di_mode || dp->dp2.di_size))) {
pfatal("PARTIALLY ALLOCATED INODE I=%lu",
(u_long)inumber);
if (reply("CLEAR") == 1) {
@ -208,36 +221,37 @@ checkinode(ino_t inumber, struct inodesc *idesc)
}
lastino = inumber;
/* This should match the file size limit in ffs_mountfs(). */
kernmaxfilesize = (u_int64_t)0x40000000 * sblock.fs_bsize - 1;
if (dp->di_size > kernmaxfilesize ||
dp->di_size > sblock.fs_maxfilesize ||
(mode == IFDIR && dp->di_size > MAXDIRSIZE)) {
kernmaxfilesize = (off_t)0x40000000 * sblock.fs_bsize - 1;
if (DIP(dp, di_size) > kernmaxfilesize ||
DIP(dp, di_size) > sblock.fs_maxfilesize ||
(mode == IFDIR && DIP(dp, di_size) > MAXDIRSIZE)) {
if (debug)
printf("bad size %qu:", dp->di_size);
printf("bad size %qu:", DIP(dp, di_size));
goto unknown;
}
if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) {
dp = ginode(inumber);
dp->di_size = sblock.fs_fsize;
dp->di_mode = IFREG|0600;
DIP(dp, di_size) = sblock.fs_fsize;
DIP(dp, di_mode) = IFREG|0600;
inodirty();
}
if ((mode == IFBLK || mode == IFCHR || mode == IFIFO ||
mode == IFSOCK) && dp->di_size != 0) {
mode == IFSOCK) && DIP(dp, di_size) != 0) {
if (debug)
printf("bad special-file size %qu:", dp->di_size);
printf("bad special-file size %qu:", DIP(dp, di_size));
goto unknown;
}
if ((mode == IFBLK || mode == IFCHR) && (dev_t)dp->di_rdev == NODEV) {
if ((mode == IFBLK || mode == IFCHR) &&
(dev_t)DIP(dp, di_rdev) == NODEV) {
if (debug)
printf("bad special-file rdev NODEV:");
goto unknown;
}
ndb = howmany(dp->di_size, sblock.fs_bsize);
ndb = howmany(DIP(dp, di_size), sblock.fs_bsize);
if (ndb < 0) {
if (debug)
printf("bad size %qu ndb %d:",
dp->di_size, ndb);
printf("bad size %qu ndb %qu:",
DIP(dp, di_size), ndb);
goto unknown;
}
if (mode == IFBLK || mode == IFCHR)
@ -247,8 +261,13 @@ checkinode(ino_t inumber, struct inodesc *idesc)
* Fake ndb value so direct/indirect block checks below
* will detect any garbage after symlink string.
*/
if (dp->di_size < (u_int64_t)sblock.fs_maxsymlinklen) {
ndb = howmany(dp->di_size, sizeof(ufs_daddr_t));
if (DIP(dp, di_size) < (off_t)sblock.fs_maxsymlinklen) {
if (sblock.fs_magic == FS_UFS1_MAGIC)
ndb = howmany(DIP(dp, di_size),
sizeof(ufs1_daddr_t));
else
ndb = howmany(DIP(dp, di_size),
sizeof(ufs2_daddr_t));
if (ndb > NDADDR) {
j = ndb - NDADDR;
for (ndb = 1; j > 1; j--)
@ -258,26 +277,26 @@ checkinode(ino_t inumber, struct inodesc *idesc)
}
}
for (j = ndb; j < NDADDR; j++)
if (dp->di_db[j] != 0) {
if (DIP(dp, di_db[j]) != 0) {
if (debug)
printf("bad direct addr: %ld\n",
(long)dp->di_db[j]);
printf("bad direct addr[%d]: %qu\n", j,
(ufs2_daddr_t)DIP(dp, di_db[j]));
goto unknown;
}
for (j = 0, ndb -= NDADDR; ndb > 0; j++)
ndb /= NINDIR(&sblock);
for (; j < NIADDR; j++)
if (dp->di_ib[j] != 0) {
if (DIP(dp, di_ib[j]) != 0) {
if (debug)
printf("bad indirect addr: %ld\n",
(long)dp->di_ib[j]);
printf("bad indirect addr: %qu\n",
DIP(dp, di_ib[j]));
goto unknown;
}
if (ftypeok(dp) == 0)
goto unknown;
n_files++;
inoinfo(inumber)->ino_linkcnt = dp->di_nlink;
if (dp->di_nlink <= 0) {
inoinfo(inumber)->ino_linkcnt = DIP(dp, di_nlink);
if (DIP(dp, di_nlink) <= 0) {
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
pfatal("LINK COUNT TABLE OVERFLOW");
@ -292,7 +311,7 @@ checkinode(ino_t inumber, struct inodesc *idesc)
}
}
if (mode == IFDIR) {
if (dp->di_size == 0)
if (DIP(dp, di_size) == 0)
inoinfo(inumber)->ino_state = DCLEAR;
else
inoinfo(inumber)->ino_state = DSTATE;
@ -303,30 +322,30 @@ checkinode(ino_t inumber, struct inodesc *idesc)
inoinfo(inumber)->ino_type = IFTODT(mode);
badblk = dupblk = 0;
idesc->id_number = inumber;
if (dp->di_flags & SF_SNAPSHOT)
if (DIP(dp, di_flags) & SF_SNAPSHOT)
idesc->id_type = SNAP;
else
idesc->id_type = ADDR;
(void)ckinode(dp, idesc);
idesc->id_entryno *= btodb(sblock.fs_fsize);
if (dp->di_blocks != idesc->id_entryno) {
pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)",
(u_long)inumber, (long)dp->di_blocks,
(long)idesc->id_entryno);
if (DIP(dp, di_blocks) != idesc->id_entryno) {
pwarn("INCORRECT BLOCK COUNT I=%lu (%qu should be %qu)",
(u_long)inumber, DIP(dp, di_blocks),
idesc->id_entryno);
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
return;
if (bkgrdflag == 0) {
dp = ginode(inumber);
dp->di_blocks = idesc->id_entryno;
DIP(dp, di_blocks) = idesc->id_entryno;
inodirty();
} else {
cmd.value = idesc->id_number;
cmd.size = idesc->id_entryno - dp->di_blocks;
cmd.size = idesc->id_entryno - DIP(dp, di_blocks);
if (debug)
printf("adjblkcnt ino %ld amount %ld\n",
(long)cmd.value, cmd.size);
printf("adjblkcnt ino %qu amount %ld\n",
cmd.value, cmd.size);
if (sysctl(adjblkcnt, MIBSIZE, 0, 0,
&cmd, sizeof cmd) == -1)
rwerror("ADJUST INODE BLOCK COUNT", cmd.value);
@ -349,7 +368,7 @@ pass1check(struct inodesc *idesc)
{
int res = KEEPON;
int anyout, nfrags;
ufs_daddr_t blkno = idesc->id_blkno;
ufs2_daddr_t blkno = idesc->id_blkno;
struct dups *dlp;
struct dups *new;

View File

@ -55,7 +55,7 @@ void
pass1b(void)
{
int c, i;
struct dinode *dp;
union dinode *dp;
struct inodesc idesc;
ino_t inumber;
@ -90,7 +90,7 @@ pass1bcheck(struct inodesc *idesc)
{
struct dups *dlp;
int nfrags, res = KEEPON;
ufs_daddr_t blkno = idesc->id_blkno;
ufs2_daddr_t blkno = idesc->id_blkno;
for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
if (chkrange(blkno, 1))

View File

@ -58,11 +58,12 @@ static int pass2check(struct inodesc *);
void
pass2(void)
{
struct dinode *dp;
union dinode *dp;
struct inoinfo **inpp, *inp;
struct inoinfo **inpend;
struct inodesc curino;
struct dinode dino;
union dinode dino;
int i;
char pathbuf[MAXPATHLEN + 1];
switch (inoinfo(ROOTINO)->ino_state) {
@ -105,8 +106,8 @@ pass2(void)
exit(EEXIT);
}
dp = ginode(ROOTINO);
dp->di_mode &= ~IFMT;
dp->di_mode |= IFDIR;
DIP(dp, di_mode) &= ~IFMT;
DIP(dp, di_mode) |= IFDIR;
inodirty();
break;
@ -130,7 +131,6 @@ pass2(void)
memset(&curino, 0, sizeof(struct inodesc));
curino.id_type = DATA;
curino.id_func = pass2check;
dp = &dino;
inpend = &inpsort[inplast];
for (inpp = inpsort; inpp < inpend; inpp++) {
if (got_siginfo) {
@ -147,9 +147,8 @@ pass2(void)
inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ);
if (reply("FIX") == 1) {
dp = ginode(inp->i_number);
dp->di_size = inp->i_isize;
DIP(dp, di_size) = inp->i_isize;
inodirty();
dp = &dino;
}
} else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) {
getpathname(pathbuf, inp->i_number, inp->i_number);
@ -166,15 +165,22 @@ pass2(void)
inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ);
if (preen || reply("ADJUST") == 1) {
dp = ginode(inp->i_number);
dp->di_size = roundup(inp->i_isize, DIRBLKSIZ);
DIP(dp, di_size) =
roundup(inp->i_isize, DIRBLKSIZ);
inodirty();
dp = &dino;
}
}
memset(&dino, 0, sizeof(struct dinode));
dino.di_mode = IFDIR;
dp->di_size = inp->i_isize;
memmove(&dp->di_db[0], &inp->i_blks[0], (size_t)inp->i_numblks);
dp = &dino;
memset(dp, 0, sizeof(struct ufs2_dinode));
DIP(dp, di_mode) = IFDIR;
DIP(dp, di_size) = inp->i_isize;
for (i = 0;
i < (inp->i_numblks<NDADDR ? inp->i_numblks : NDADDR);
i++)
DIP(dp, di_db[i]) = inp->i_blks[i];
if (inp->i_numblks > NDADDR)
for (i = 0; i < NIADDR; i++)
DIP(dp, di_ib[i]) = inp->i_blks[NDADDR + i];
curino.id_number = inp->i_number;
curino.id_parent = inp->i_parent;
(void)ckinode(dp, &curino);
@ -223,7 +229,7 @@ pass2check(struct inodesc *idesc)
struct direct *dirp = idesc->id_dirp;
struct inoinfo *inp;
int n, entrysize, ret = 0;
struct dinode *dp;
union dinode *dp;
char *errmsg;
struct direct proto;
char namebuf[MAXPATHLEN + 1];
@ -392,8 +398,8 @@ pass2check(struct inodesc *idesc)
break;
dp = ginode(dirp->d_ino);
inoinfo(dirp->d_ino)->ino_state =
(dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
inoinfo(dirp->d_ino)->ino_linkcnt = dp->di_nlink;
(DIP(dp, di_mode) & IFMT) == IFDIR ? DSTATE : FSTATE;
inoinfo(dirp->d_ino)->ino_linkcnt = DIP(dp, di_nlink);
goto again;
case DSTATE:

View File

@ -54,7 +54,7 @@ pass4(void)
{
ino_t inumber;
struct zlncnt *zlnp;
struct dinode *dp;
union dinode *dp;
struct inodesc idesc;
int i, n, cg;
@ -100,7 +100,7 @@ pass4(void)
case DCLEAR:
dp = ginode(inumber);
if (dp->di_size == 0) {
if (DIP(dp, di_size) == 0) {
clri(&idesc, "ZERO LENGTH", 1);
break;
}
@ -125,7 +125,7 @@ pass4check(struct inodesc *idesc)
{
struct dups *dlp;
int nfrags, res = KEEPON;
ufs_daddr_t blkno = idesc->id_blkno;
ufs2_daddr_t blkno = idesc->id_blkno;
for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
if (chkrange(blkno, 1)) {

View File

@ -55,18 +55,17 @@ static void check_maps(u_char *, u_char *, int, int, char *, int *, int, int);
void
pass5(void)
{
int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
int c, i, j, blk, frags, basesize, mapsize;
int inomapsize, blkmapsize;
struct fs *fs = &sblock;
struct cg *cg = &cgrp;
ufs_daddr_t dbase, dmax, d;
int i, j, excessdirs, rewritecg = 0;
ufs2_daddr_t d, dbase, dmax;
int excessdirs, rewritecg = 0;
struct csum *cs;
struct csum cstotal;
struct csum_total cstotal;
struct inodesc idesc[3];
char buf[MAXBSIZE];
struct cg *newcg = (struct cg *)buf;
struct ocg *ocg = (struct ocg *)buf;
inoinfo(WINO)->ino_state = USTATE;
memset(newcg, 0, (size_t)fs->fs_cgsize);
@ -110,63 +109,46 @@ pass5(void)
}
}
}
switch ((int)fs->fs_postblformat) {
case FS_42POSTBLFMT:
basesize = (char *)(&ocg->cg_btot[0]) -
(char *)(&ocg->cg_firstfield);
sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
(u_char *)&ocg->cg_iused[0];
blkmapsize = howmany(fs->fs_fpg, NBBY);
inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0];
ocg->cg_magic = CG_MAGIC;
savednrpos = fs->fs_nrpos;
fs->fs_nrpos = 8;
break;
case FS_DYNAMICPOSTBLFMT:
newcg->cg_btotoff =
&newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
newcg->cg_boff =
newcg->cg_btotoff + fs->fs_cpg * sizeof(int32_t);
newcg->cg_iusedoff = newcg->cg_boff +
fs->fs_cpg * fs->fs_nrpos * sizeof(u_int16_t);
newcg->cg_freeoff =
newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff;
newcg->cg_nextfreeoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff;
if (fs->fs_contigsumsize > 0) {
newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
sizeof(u_int32_t);
newcg->cg_clustersumoff =
roundup(newcg->cg_clustersumoff, sizeof(u_int32_t));
newcg->cg_clusteroff = newcg->cg_clustersumoff +
(fs->fs_contigsumsize + 1) * sizeof(u_int32_t);
newcg->cg_nextfreeoff = newcg->cg_clusteroff +
howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY);
}
newcg->cg_magic = CG_MAGIC;
basesize = &newcg->cg_space[0] -
(u_char *)(&newcg->cg_firstfield);
sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
break;
default:
inomapsize = blkmapsize = sumsize = 0; /* keep lint happy */
errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d",
fs->fs_postblformat);
basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
if (sblock.fs_magic == FS_UFS2_MAGIC) {
newcg->cg_iusedoff = basesize;
} else {
/*
* We reserve the space for the old rotation summary
* tables for the benefit of old kernels, but do not
* maintain them in modern kernels. In time, they can
* go away.
*/
newcg->cg_old_btotoff = basesize;
newcg->cg_old_boff = newcg->cg_old_btotoff +
fs->fs_old_cpg * sizeof(int32_t);
newcg->cg_iusedoff = newcg->cg_old_boff +
fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t);
memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize);
}
inomapsize = howmany(fs->fs_ipg, NBBY);
newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize;
blkmapsize = howmany(fs->fs_fpg, NBBY);
newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize;
if (fs->fs_contigsumsize > 0) {
newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
sizeof(u_int32_t);
newcg->cg_clustersumoff =
roundup(newcg->cg_clustersumoff, sizeof(u_int32_t));
newcg->cg_clusteroff = newcg->cg_clustersumoff +
(fs->fs_contigsumsize + 1) * sizeof(u_int32_t);
newcg->cg_nextfreeoff = newcg->cg_clusteroff +
howmany(fragstoblks(fs, fs->fs_fpg), NBBY);
}
newcg->cg_magic = CG_MAGIC;
mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
memset(&idesc[0], 0, sizeof idesc);
for (i = 0; i < 3; i++)
idesc[i].id_type = ADDR;
memset(&cstotal, 0, sizeof(struct csum));
j = blknum(fs, fs->fs_size + fs->fs_frag - 1);
for (i = fs->fs_size; i < j; i++)
setbmap(i);
memset(&cstotal, 0, sizeof(struct csum_total));
dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1);
for (d = fs->fs_size; d < dmax; d++)
setbmap(d);
for (c = 0; c < fs->fs_ncg; c++) {
if (got_siginfo) {
printf("%s: phase 5: cyl group %d of %d (%d%%)\n",
@ -177,17 +159,23 @@ pass5(void)
getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
if (!cg_chkmagic(cg))
pfatal("CG %d: BAD MAGIC NUMBER\n", c);
newcg->cg_time = cg->cg_time;
newcg->cg_old_time = cg->cg_old_time;
newcg->cg_cgx = c;
dbase = cgbase(fs, c);
dmax = dbase + fs->fs_fpg;
if (dmax > fs->fs_size)
dmax = fs->fs_size;
newcg->cg_time = cg->cg_time;
newcg->cg_cgx = c;
if (c == fs->fs_ncg - 1 && fs->fs_ncyl % fs->fs_cpg > 0)
newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
else
newcg->cg_ncyl = fs->fs_cpg;
newcg->cg_ndblk = dmax - dbase;
if (fs->fs_magic == FS_UFS1_MAGIC) {
if (c == fs->fs_ncg - 1)
newcg->cg_old_ncyl = howmany(newcg->cg_ndblk,
fs->fs_fpg / fs->fs_old_cpg);
else
newcg->cg_old_ncyl = fs->fs_old_cpg;
newcg->cg_old_niblk = fs->fs_ipg;
newcg->cg_niblk = 0;
}
if (fs->fs_contigsumsize > 0)
newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
newcg->cg_cs.cs_ndir = 0;
@ -206,11 +194,16 @@ pass5(void)
newcg->cg_irotor = cg->cg_irotor;
else
newcg->cg_irotor = 0;
if (fs->fs_magic == FS_UFS1_MAGIC) {
newcg->cg_initediblk = 0;
} else {
if ((unsigned)cg->cg_initediblk > fs->fs_ipg)
newcg->cg_initediblk = fs->fs_ipg;
else
newcg->cg_initediblk = cg->cg_initediblk;
}
memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
memset(&cg_blktot(newcg)[0], 0,
(size_t)(sumsize + mapsize));
if (fs->fs_postblformat == FS_42POSTBLFMT)
ocg->cg_magic = CG_MAGIC;
memset(cg_inosused(newcg), 0, (size_t)(mapsize));
j = fs->fs_ipg * c;
for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
switch (inoinfo(j)->ino_state) {
@ -254,9 +247,6 @@ pass5(void)
}
if (frags == fs->fs_frag) {
newcg->cg_cs.cs_nbfree++;
j = cbtocylno(fs, i);
cg_blktot(newcg)[j]++;
cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++;
if (fs->fs_contigsumsize > 0)
setbit(cg_clustersfree(newcg),
i / fs->fs_frag);
@ -312,13 +302,9 @@ pass5(void)
continue;
}
if (cursnapshot == 0 &&
(memcmp(newcg, cg, basesize) != 0 ||
memcmp(&cg_blktot(newcg)[0],
&cg_blktot(cg)[0], sumsize) != 0) &&
memcmp(newcg, cg, basesize) != 0 &&
dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
memmove(cg, newcg, (size_t)basesize);
memmove(&cg_blktot(cg)[0],
&cg_blktot(newcg)[0], (size_t)sumsize);
cgdirty();
}
if (bkgrdflag != 0 || usedsoftdep || debug) {
@ -346,12 +332,10 @@ pass5(void)
cgdirty();
}
}
if (fs->fs_postblformat == FS_42POSTBLFMT)
fs->fs_nrpos = savednrpos;
if (cursnapshot == 0 &&
memcmp(&cstotal, &fs->fs_cstotal, sizeof *cs) != 0
&& dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
memmove(&fs->fs_cstotal, &cstotal, sizeof *cs);
memcmp(&cstotal, &fs->fs_cstotal, sizeof cstotal) != 0
&& dofix(&idesc[0], "SUMMARY BLK COUNT(S) WRONG IN SUPERBLK")) {
memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal);
fs->fs_ronly = 0;
fs->fs_fmod = 0;
sbdirty();
@ -398,6 +382,7 @@ check_maps(
aend = n;
continue;
}
returntosingle = 1;
if (astart == aend)
(*msg)("ALLOCATED %s %d MARKED FREE\n",
name, astart);
@ -434,6 +419,7 @@ check_maps(
pwarn("%s %sS %d-%ld MARKED USED\n",
"UNALLOCATED", name, ustart,
ustart + size - 1);
returntosingle = 1;
if (bkgrdflag != 0) {
cmd.value = ustart;
cmd.size = size;
@ -476,6 +462,7 @@ check_maps(
pwarn("UNALLOCATED %sS %d-%ld MARKED USED\n",
name, ustart, ustart + size - 1);
}
returntosingle = 1;
if (bkgrdflag != 0) {
cmd.value = ustart;
cmd.size = size;

View File

@ -210,7 +210,8 @@ setup(char *dev)
sbdirty();
}
}
if (sblock.fs_inodefmt < FS_44INODEFMT) {
if (sblock.fs_magic == FS_UFS1_MAGIC &&
sblock.fs_old_inodefmt < FS_44INODEFMT) {
pwarn("Format of filesystem is too old.\n");
pwarn("Must update to modern format using a version of fsck\n");
pfatal("from before 2002 with the command ``fsck -c 2''\n");
@ -285,29 +286,44 @@ setup(char *dev)
return (0);
}
/*
* Possible superblock locations ordered from most to least likely.
*/
static int sblock_try[] = SBLOCKSEARCH;
/*
* Read in the super block and its summary info.
*/
int
readsb(int listerr)
{
ufs_daddr_t super = bflag ? bflag : SBOFF / dev_bsize;
ufs2_daddr_t super;
int i;
if (bread(fsreadfd, (char *)&sblock, super, (long)SBSIZE) != 0)
return (0);
sblk.b_bno = super;
sblk.b_size = SBSIZE;
/*
* run a few consistency checks of the super block
*/
if (sblock.fs_magic != FS_MAGIC)
{ badsb(listerr, "MAGIC NUMBER WRONG"); return (0); }
if (sblock.fs_ncg < 1)
{ badsb(listerr, "NCG OUT OF RANGE"); return (0); }
if (sblock.fs_cpg < 1)
{ badsb(listerr, "CPG OUT OF RANGE"); return (0); }
if (sblock.fs_sbsize > SBSIZE)
{ badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); return (0); }
if (bflag) {
super = bflag;
if ((bread(fsreadfd, (char *)&sblock, super, (long)SBLOCKSIZE)))
return (0);
} else {
for (i = 0; sblock_try[i] != -1; i++) {
super = sblock_try[i] / dev_bsize;
if ((bread(fsreadfd, (char *)&sblock, super,
(long)SBLOCKSIZE)))
return (0);
if ((sblock.fs_magic == FS_UFS1_MAGIC ||
(sblock.fs_magic == FS_UFS2_MAGIC &&
sblock.fs_sblockloc ==
numfrags(&sblock, sblock_try[i]))) &&
sblock.fs_ncg >= 1 &&
sblock.fs_bsize >= SBLOCKSIZE &&
sblock.fs_bsize >= sizeof(struct fs))
break;
}
if (sblock_try[i] == -1) {
fprintf(stderr, "Cannot find filesystem superblock\n");
return (0);
}
}
/*
* Compute block size that the filesystem is based on,
* according to fsbtodb, and adjust superblock block number
@ -316,6 +332,7 @@ readsb(int listerr)
super *= dev_bsize;
dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
sblk.b_bno = super / dev_bsize;
sblk.b_size = SBLOCKSIZE;
if (bflag) {
havesb = 1;
return (1);
@ -331,8 +348,6 @@ readsb(int listerr)
altsblock.fs_cblkno != sblock.fs_cblkno ||
altsblock.fs_iblkno != sblock.fs_iblkno ||
altsblock.fs_dblkno != sblock.fs_dblkno ||
altsblock.fs_cgoffset != sblock.fs_cgoffset ||
altsblock.fs_cgmask != sblock.fs_cgmask ||
altsblock.fs_ncg != sblock.fs_ncg ||
altsblock.fs_bsize != sblock.fs_bsize ||
altsblock.fs_fsize != sblock.fs_fsize ||
@ -347,7 +362,6 @@ readsb(int listerr)
altsblock.fs_nindir != sblock.fs_nindir ||
altsblock.fs_inopb != sblock.fs_inopb ||
altsblock.fs_cssize != sblock.fs_cssize ||
altsblock.fs_cpg != sblock.fs_cpg ||
altsblock.fs_ipg != sblock.fs_ipg ||
altsblock.fs_fpg != sblock.fs_fpg ||
altsblock.fs_magic != sblock.fs_magic) {
@ -355,6 +369,21 @@ readsb(int listerr)
"VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE");
return (0);
}
/*
* If not yet done, update UFS1 superblock with new wider fields.
*/
if (sblock.fs_magic == FS_UFS1_MAGIC &&
sblock.fs_maxbsize != sblock.fs_bsize) {
sblock.fs_maxbsize = sblock.fs_bsize;
sblock.fs_time = sblock.fs_old_time;
sblock.fs_size = sblock.fs_old_size;
sblock.fs_dsize = sblock.fs_old_dsize;
sblock.fs_csaddr = sblock.fs_old_csaddr;
sblock.fs_cstotal.cs_ndir = sblock.fs_old_cstotal.cs_ndir;
sblock.fs_cstotal.cs_nbfree = sblock.fs_old_cstotal.cs_nbfree;
sblock.fs_cstotal.cs_nifree = sblock.fs_old_cstotal.cs_nifree;
sblock.fs_cstotal.cs_nffree = sblock.fs_old_cstotal.cs_nffree;
}
havesb = 1;
return (1);
}
@ -380,8 +409,8 @@ sblock_init(void)
lfdir = 0;
initbarea(&sblk);
initbarea(&asblk);
sblk.b_un.b_buf = malloc(SBSIZE);
asblk.b_un.b_buf = malloc(SBSIZE);
sblk.b_un.b_buf = malloc(SBLOCKSIZE);
asblk.b_un.b_buf = malloc(SBLOCKSIZE);
if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
errx(EEXIT, "cannot allocate space for superblock");
if ((lp = getdisklabel(NULL, fsreadfd)))
@ -402,7 +431,7 @@ calcsb(char *dev, int devfd, struct fs *fs)
struct disklabel *lp;
struct partition *pp;
char *cp;
int i;
int i, nspf;
cp = strchr(dev, '\0') - 1;
if (cp == (char *)-1 || ((*cp < 'a' || *cp > 'h') && !isdigit(*cp))) {
@ -430,24 +459,30 @@ calcsb(char *dev, int devfd, struct fs *fs)
memset(fs, 0, sizeof(struct fs));
fs->fs_fsize = pp->p_fsize;
fs->fs_frag = pp->p_frag;
fs->fs_cpg = pp->p_cpg;
fs->fs_size = pp->p_size;
fs->fs_ntrak = lp->d_ntracks;
fs->fs_nsect = lp->d_nsectors;
fs->fs_spc = lp->d_secpercyl;
fs->fs_nspf = fs->fs_fsize / lp->d_secsize;
fs->fs_cgmask = 0xffffffff;
for (i = fs->fs_ntrak; i > 1; i >>= 1)
fs->fs_cgmask <<= 1;
if (!POWEROF2(fs->fs_ntrak))
fs->fs_cgmask <<= 1;
fs->fs_cgoffset = roundup(
howmany(fs->fs_nsect, NSPF(fs)), fs->fs_frag);
fs->fs_fpg = (fs->fs_cpg * fs->fs_spc) / NSPF(fs);
fs->fs_ncg = howmany(fs->fs_size / fs->fs_spc, fs->fs_cpg);
for (fs->fs_fsbtodb = 0, i = NSPF(fs); i > 1; i >>= 1)
fs->fs_sblkno = roundup(
howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize),
fs->fs_frag);
nspf = fs->fs_fsize / lp->d_secsize;
for (fs->fs_fsbtodb = 0, i = nspf; i > 1; i >>= 1)
fs->fs_fsbtodb++;
dev_bsize = lp->d_secsize;
if (fs->fs_magic == FS_UFS2_MAGIC) {
fs->fs_fpg = pp->p_cpg;
fs->fs_ncg = howmany(fs->fs_size, fs->fs_fpg);
} else /* if (fs->fs_magic == FS_UFS1_MAGIC) */ {
fs->fs_old_cpg = pp->p_cpg;
fs->fs_old_cgmask = 0xffffffff;
for (i = lp->d_ntracks; i > 1; i >>= 1)
fs->fs_old_cgmask <<= 1;
if (!POWEROF2(lp->d_ntracks))
fs->fs_old_cgmask <<= 1;
fs->fs_old_cgoffset = roundup(howmany(lp->d_nsectors, nspf),
fs->fs_frag);
fs->fs_fpg = (fs->fs_old_cpg * lp->d_secpercyl) / nspf;
fs->fs_ncg = howmany(fs->fs_size / lp->d_secpercyl,
fs->fs_old_cpg);
}
return (1);
}

View File

@ -280,7 +280,7 @@ cmdloop(void)
return rval;
}
struct dinode *curinode;
union dinode *curinode;
ino_t curinum, ocurrent;
#define GETINUM(ac,inum) inum = strtoul(argv[ac], &cp, 0); \
@ -317,7 +317,7 @@ CMDFUNCSTART(back)
CMDFUNCSTART(zapi)
{
ino_t inum;
struct dinode *dp;
union dinode *dp;
char *cp;
GETINUM(1,inum);
@ -350,7 +350,8 @@ CMDFUNCSTART(uplink)
{
if (!checkactive())
return 1;
printf("inode %d link count now %d\n", curinum, ++curinode->di_nlink);
DIP(curinode, di_nlink) += 1;
printf("inode %d link count now %d\n", curinum, DIP(curinode, di_nlink));
inodirty();
return 0;
}
@ -359,7 +360,8 @@ CMDFUNCSTART(downlink)
{
if (!checkactive())
return 1;
printf("inode %d link count now %d\n", curinum, --curinode->di_nlink);
DIP(curinode, di_nlink) -= 1;
printf("inode %d link count now %d\n", curinum, DIP(curinode, di_nlink));
inodirty();
return 0;
}
@ -617,7 +619,7 @@ CMDFUNCSTART(newtype)
if (!checkactive())
return 1;
type = curinode->di_mode & IFMT;
type = DIP(curinode, di_mode) & IFMT;
for (tp = typenamemap;
tp < &typenamemap[sizeof(typenamemap)/sizeof(*typenamemap)];
tp++) {
@ -632,8 +634,8 @@ CMDFUNCSTART(newtype)
warnx("try one of `file', `dir', `socket', `fifo'");
return 1;
}
curinode->di_mode &= ~IFMT;
curinode->di_mode |= type;
DIP(curinode, di_mode) &= ~IFMT;
DIP(curinode, di_mode) |= type;
inodirty();
printactive(0);
return 0;
@ -654,7 +656,7 @@ CMDFUNCSTART(chlen)
return 1;
}
curinode->di_size = len;
DIP(curinode, di_size) = len;
inodirty();
printactive(0);
return rval;
@ -675,8 +677,8 @@ CMDFUNCSTART(chmode)
return 1;
}
curinode->di_mode &= ~07777;
curinode->di_mode |= modebits;
DIP(curinode, di_mode) &= ~07777;
DIP(curinode, di_mode) |= modebits;
inodirty();
printactive(0);
return rval;
@ -701,7 +703,7 @@ CMDFUNCSTART(chaflags)
warnx("flags set beyond 32-bit range of field (%lx)\n", flags);
return(1);
}
curinode->di_flags = flags;
DIP(curinode, di_flags) = flags;
inodirty();
printactive(0);
return rval;
@ -726,7 +728,7 @@ CMDFUNCSTART(chgen)
warnx("gen set beyond 32-bit range of field (%lx)\n", gen);
return(1);
}
curinode->di_gen = gen;
DIP(curinode, di_gen) = gen;
inodirty();
printactive(0);
return rval;
@ -751,7 +753,7 @@ CMDFUNCSTART(linkcount)
return 1;
}
curinode->di_nlink = lcnt;
DIP(curinode, di_nlink) = lcnt;
inodirty();
printactive(0);
return rval;
@ -778,7 +780,7 @@ CMDFUNCSTART(chowner)
}
}
curinode->di_uid = uid;
DIP(curinode, di_uid) = uid;
inodirty();
printactive(0);
return rval;
@ -804,18 +806,17 @@ CMDFUNCSTART(chgroup)
}
}
curinode->di_gid = gid;
DIP(curinode, di_gid) = gid;
inodirty();
printactive(0);
return rval;
}
int
dotime(char *name, struct timespec *rts)
dotime(char *name, time_t *secp, int32_t *nsecp)
{
char *p, *val;
struct tm t;
int32_t sec;
int32_t nsec;
p = strchr(name, '.');
if (p) {
@ -832,6 +833,7 @@ dotime(char *name, struct timespec *rts)
warnx("date format: YYYYMMDDHHMMSS[.nsec]");
return 1;
}
*nsecp = nsec;
for (p = name; *p; p++)
if (*p < '0' || *p > '9')
@ -855,20 +857,26 @@ dotime(char *name, struct timespec *rts)
t.tm_sec = VAL() + t.tm_sec * 10;
t.tm_isdst = -1;
sec = mktime(&t);
if (sec == -1) {
*secp = mktime(&t);
if (*secp == -1) {
warnx("date/time out of range");
return 1;
}
rts->tv_sec = sec;
rts->tv_nsec = nsec;
return 0;
}
CMDFUNCSTART(chmtime)
{
if (dotime(argv[1], &curinode->di_ctime))
time_t secs;
int32_t nsecs;
if (dotime(argv[1], &secs, &nsecs))
return 1;
if (sblock.fs_magic == FS_UFS1_MAGIC)
curinode->dp1.di_mtime = _time_to_time32(secs);
else
curinode->dp2.di_mtime = _time_to_time64(secs);
DIP(curinode, di_mtimensec) = nsecs;
inodirty();
printactive(0);
return 0;
@ -876,8 +884,16 @@ CMDFUNCSTART(chmtime)
CMDFUNCSTART(chatime)
{
if (dotime(argv[1], &curinode->di_ctime))
time_t secs;
int32_t nsecs;
if (dotime(argv[1], &secs, &nsecs))
return 1;
if (sblock.fs_magic == FS_UFS1_MAGIC)
curinode->dp1.di_atime = _time_to_time32(secs);
else
curinode->dp2.di_atime = _time_to_time64(secs);
DIP(curinode, di_atimensec) = nsecs;
inodirty();
printactive(0);
return 0;
@ -885,8 +901,16 @@ CMDFUNCSTART(chatime)
CMDFUNCSTART(chctime)
{
if (dotime(argv[1], &curinode->di_ctime))
time_t secs;
int32_t nsecs;
if (dotime(argv[1], &secs, &nsecs))
return 1;
if (sblock.fs_magic == FS_UFS1_MAGIC)
curinode->dp1.di_ctime = _time_to_time32(secs);
else
curinode->dp2.di_ctime = _time_to_time64(secs);
DIP(curinode, di_ctimensec) = nsecs;
inodirty();
printactive(0);
return 0;

View File

@ -30,9 +30,9 @@
* $FreeBSD$
*/
extern int bread(int fd, char *buf, ufs_daddr_t blk, long size);
extern void bwrite(int fd, char *buf, ufs_daddr_t blk, long size);
extern void rwerror(char *mesg, ufs_daddr_t blk);
extern int bread(int fd, char *buf, ufs2_daddr_t blk, long size);
extern void bwrite(int fd, char *buf, ufs2_daddr_t blk, long size);
extern void rwerror(char *mesg, ufs2_daddr_t blk);
extern int reply(char *question);
extern long dev_bsize;
@ -50,13 +50,13 @@ struct cmdtable {
#define FL_WR 0x0001 /* wants to write */
int (*handler)(int argc, char *argv[]);
};
extern struct dinode *curinode;
extern union dinode *curinode;
extern ino_t curinum;
int argcount(struct cmdtable *cmdp, int argc, char *argv[]);
char **crack(char *line, int *argc);
char **recrack(char *line, int *argc, int argc_max);
void printstat(const char *cp, ino_t inum, struct dinode *dp);
void printstat(const char *cp, ino_t inum, union dinode *dp);
int printactive(int doblocks);
int checkactive(void);
int checkactivedir(void);

View File

@ -50,8 +50,8 @@ static const char rcsid[] =
#include "fsck.h"
static int charsperline(void);
static int printindir(ufs_daddr_t blk, int level, char *bufp);
static void printblocks(ino_t inum, struct dinode *dp);
static int printindir(ufs2_daddr_t blk, int level, char *bufp);
static void printblocks(ino_t inum, union dinode *dp);
char **
crack(char *line, int *argc)
@ -106,15 +106,17 @@ argcount(struct cmdtable *cmdp, int argc, char *argv[])
}
void
printstat(const char *cp, ino_t inum, struct dinode *dp)
printstat(const char *cp, ino_t inum, union dinode *dp)
{
struct group *grp;
struct passwd *pw;
ufs2_daddr_t blocks;
int64_t gen;
char *p;
time_t t;
printf("%s: ", cp);
switch (dp->di_mode & IFMT) {
switch (DIP(dp, di_mode) & IFMT) {
case IFDIR:
puts("directory");
break;
@ -123,19 +125,25 @@ printstat(const char *cp, ino_t inum, struct dinode *dp)
break;
case IFBLK:
printf("block special (%d,%d)",
major(dp->di_rdev), minor(dp->di_rdev));
major(DIP(dp, di_rdev)), minor(DIP(dp, di_rdev)));
break;
case IFCHR:
printf("character special (%d,%d)",
major(dp->di_rdev), minor(dp->di_rdev));
major(DIP(dp, di_rdev)), minor(DIP(dp, di_rdev)));
break;
case IFLNK:
fputs("symlink",stdout);
if (dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN &&
dp->di_blocks == 0)
printf(" to `%.*s'\n", (int) dp->di_size, (char *)dp->di_shortlink);
else
putchar('\n');
if (DIP(dp, di_size) > 0 &&
DIP(dp, di_size) < sblock.fs_maxsymlinklen &&
DIP(dp, di_blocks) == 0) {
if (sblock.fs_magic == FS_UFS1_MAGIC)
p = (caddr_t)dp->dp1.di_db;
else
p = (caddr_t)dp->dp2.di_db;
printf(" to `%.*s'\n", (int) DIP(dp, di_size), p);
} else {
putchar('\n');
}
break;
case IFSOCK:
puts("socket");
@ -144,31 +152,43 @@ printstat(const char *cp, ino_t inum, struct dinode *dp)
puts("fifo");
break;
}
printf("I=%lu MODE=%o SIZE=%qu", (u_long)inum, dp->di_mode, dp->di_size);
t = dp->di_mtime;
printf("I=%lu MODE=%o SIZE=%qu", (u_long)inum, DIP(dp, di_mode),
DIP(dp, di_size));
if (sblock.fs_magic == FS_UFS1_MAGIC)
t = _time32_to_time(dp->dp1.di_mtime);
else
t = _time64_to_time(dp->dp2.di_mtime);
p = ctime(&t);
printf("\n\tMTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
dp->di_mtimensec);
t = dp->di_ctime;
DIP(dp, di_mtimensec));
if (sblock.fs_magic == FS_UFS1_MAGIC)
t = _time32_to_time(dp->dp1.di_ctime);
else
t = _time64_to_time(dp->dp2.di_ctime);
p = ctime(&t);
printf("\n\tCTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
dp->di_ctimensec);
t = dp->di_atime;
DIP(dp, di_ctimensec));
if (sblock.fs_magic == FS_UFS1_MAGIC)
t = _time32_to_time(dp->dp1.di_atime);
else
t = _time64_to_time(dp->dp2.di_atime);
p = ctime(&t);
printf("\n\tATIME=%15.15s %4.4s [%d nsec]\n", &p[4], &p[20],
dp->di_atimensec);
DIP(dp, di_atimensec));
if ((pw = getpwuid(dp->di_uid)))
if ((pw = getpwuid(DIP(dp, di_uid))))
printf("OWNER=%s ", pw->pw_name);
else
printf("OWNUID=%u ", dp->di_uid);
if ((grp = getgrgid(dp->di_gid)))
printf("OWNUID=%u ", DIP(dp, di_uid));
if ((grp = getgrgid(DIP(dp, di_gid))))
printf("GRP=%s ", grp->gr_name);
else
printf("GID=%u ", dp->di_gid);
printf("GID=%u ", DIP(dp, di_gid));
printf("LINKCNT=%hd FLAGS=%#x BLKCNT=%x GEN=%x\n", dp->di_nlink, dp->di_flags,
dp->di_blocks, dp->di_gen);
blocks = DIP(dp, di_blocks);
gen = DIP(dp, di_gen);
printf("LINKCNT=%hd FLAGS=%#x BLKCNT=%qx GEN=%qx\n", DIP(dp, di_nlink),
DIP(dp, di_flags), blocks, gen);
}
@ -199,12 +219,12 @@ charsperline(void)
* Recursively print a list of indirect blocks.
*/
static int
printindir(ufs_daddr_t blk, int level, char *bufp)
printindir(ufs2_daddr_t blk, int level, char *bufp)
{
struct bufarea buf, *bp;
char tempbuf[32]; /* enough to print an ufs_daddr_t */
char tempbuf[32]; /* enough to print an ufs2_daddr_t */
int i, j, cpl, charssofar;
ufs_daddr_t blkno;
ufs2_daddr_t blkno;
if (level == 0) {
/* for the final indirect level, don't use the cache */
@ -219,13 +239,16 @@ printindir(ufs_daddr_t blk, int level, char *bufp)
cpl = charsperline();
for (i = charssofar = 0; i < NINDIR(&sblock); i++) {
blkno = bp->b_un.b_indir[i];
if (sblock.fs_magic == FS_UFS1_MAGIC)
blkno = bp->b_un.b_indir1[i];
else
blkno = bp->b_un.b_indir2[i];
if (blkno == 0) {
if (level == 0)
putchar('\n');
return 0;
}
j = sprintf(tempbuf, "%d", blkno);
j = sprintf(tempbuf, "%qd", blkno);
if (level == 0) {
charssofar += j;
if (charssofar >= cpl - 2) {
@ -253,30 +276,32 @@ printindir(ufs_daddr_t blk, int level, char *bufp)
* Print the block pointers for one inode.
*/
static void
printblocks(ino_t inum, struct dinode *dp)
printblocks(ino_t inum, union dinode *dp)
{
char *bufp;
int i, j, nfrags;
long ndb, offset;
ufs2_daddr_t blkno;
printf("Blocks for inode %d:\n", inum);
printf("Direct blocks:\n");
ndb = howmany(dp->di_size, sblock.fs_bsize);
ndb = howmany(DIP(dp, di_size), sblock.fs_bsize);
for (i = 0; i < NDADDR; i++) {
if (dp->di_db[i] == 0) {
if (DIP(dp, di_db[i]) == 0) {
putchar('\n');
return;
}
if (i > 0)
printf(", ");
printf("%d", dp->di_db[i]);
if (--ndb == 0 && (offset = blkoff(&sblock, dp->di_size)) != 0) {
blkno = DIP(dp, di_db[i]);
printf("%qd", blkno);
if (--ndb == 0 && (offset = blkoff(&sblock, DIP(dp, di_size))) != 0) {
nfrags = numfrags(&sblock, fragroundup(&sblock, offset));
printf(" (%d frag%s)", nfrags, nfrags > 1? "s": "");
}
}
putchar('\n');
if (dp->di_ib[0] == 0)
if (DIP(dp, di_ib[0]) == 0)
return;
bufp = malloc((unsigned int)sblock.fs_bsize);
@ -284,7 +309,7 @@ printblocks(ino_t inum, struct dinode *dp)
errx(EEXIT, "cannot allocate indirect block buffer");
printf("Indirect blocks:\n");
for (i = 0; i < NIADDR; i++)
if (printindir(dp->di_ib[i], i, bufp) == 0)
if (printindir(DIP(dp, di_ib[i]), i, bufp) == 0)
break;
free(bufp);
}
@ -307,7 +332,7 @@ checkactivedir(void)
warnx("no current inode\n");
return 0;
}
if ((curinode->di_mode & IFMT) != IFDIR) {
if ((DIP(curinode, di_mode) & IFMT) != IFDIR) {
warnx("inode %d not a directory", curinum);
return 0;
}
@ -319,7 +344,7 @@ printactive(int doblocks)
{
if (!checkactive())
return 1;
switch (curinode->di_mode & IFMT) {
switch (DIP(curinode, di_mode) & IFMT) {
case IFDIR:
case IFREG:
case IFBLK:
@ -337,7 +362,7 @@ printactive(int doblocks)
break;
default:
printf("current inode %d: screwy itype 0%o (mode 0%o)?\n",
curinum, curinode->di_mode & IFMT, curinode->di_mode);
curinum, DIP(curinode, di_mode) & IFMT, DIP(curinode, di_mode));
break;
}
return 0;

View File

@ -40,8 +40,8 @@ static const char rcsid[] =
#include <sys/time.h>
#include <sys/resource.h>
#include <ufs/ffs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <err.h>
#include <errno.h>
@ -54,6 +54,11 @@ static const char rcsid[] =
static void usage(void) __dead2;
int fsirand(char *);
/*
* Possible superblock locations ordered from most to least likely.
*/
static int sblock_try[] = SBLOCKSEARCH;
int printonly = 0, force = 0, ignorelabel = 0;
int
@ -104,14 +109,15 @@ main(int argc, char *argv[])
int
fsirand(char *device)
{
static struct dinode *inodebuf;
static size_t oldibufsize;
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
caddr_t inodebuf;
size_t ibufsize;
struct fs *sblock;
ino_t inumber, maxino;
daddr_t dblk;
char sbuf[SBSIZE], sbuftmp[SBSIZE];
int devfd, n, cg;
ufs2_daddr_t sblockloc, dblk;
char sbuf[SBLOCKSIZE], sbuftmp[SBLOCKSIZE];
int i, devfd, n, cg;
u_int32_t bsize = DEV_BSIZE;
struct disklabel label;
@ -132,27 +138,34 @@ fsirand(char *device)
/* Read in master superblock */
(void)memset(&sbuf, 0, sizeof(sbuf));
sblock = (struct fs *)&sbuf;
if (lseek(devfd, SBOFF, SEEK_SET) == -1) {
warn("can't seek to superblock (%qd) on %s", SBOFF, device);
return (1);
for (i = 0; sblock_try[i] != -1; i++) {
sblockloc = sblock_try[i];
if (lseek(devfd, sblockloc, SEEK_SET) == -1) {
warn("can't seek to superblock (%qd) on %s",
sblockloc, device);
return (1);
}
if ((n = read(devfd, (void *)sblock, SBLOCKSIZE))!=SBLOCKSIZE) {
warnx("can't read superblock on %s: %s", device,
(n < SBLOCKSIZE) ? "short read" : strerror(errno));
return (1);
}
if ((sblock->fs_magic == FS_UFS1_MAGIC ||
(sblock->fs_magic == FS_UFS2_MAGIC &&
sblock->fs_sblockloc ==
numfrags(sblock, sblock_try[i]))) &&
sblock->fs_bsize <= MAXBSIZE &&
sblock->fs_bsize >= sizeof(struct fs))
break;
}
if ((n = read(devfd, (void *)sblock, SBSIZE)) != SBSIZE) {
warnx("can't read superblock on %s: %s", device,
(n < SBSIZE) ? "short read" : strerror(errno));
if (sblock_try[i] == -1) {
fprintf(stderr, "Cannot find filesystem superblock\n");
return (1);
}
maxino = sblock->fs_ncg * sblock->fs_ipg;
/* Simple sanity checks on the superblock */
if (sblock->fs_magic != FS_MAGIC) {
warnx("bad magic number in superblock");
return (1);
}
if (sblock->fs_sbsize > SBSIZE) {
warnx("superblock size is preposterous");
return (1);
}
if (sblock->fs_postblformat == FS_42POSTBLFMT) {
if (sblock->fs_magic == FS_UFS1_MAGIC &&
sblock->fs_old_inodefmt < FS_44INODEFMT) {
warnx("filesystem format is too old, sorry");
return (1);
}
@ -168,18 +181,19 @@ fsirand(char *device)
if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) {
warn("can't seek to %qd", (off_t)dblk * bsize);
return (1);
} else if ((n = write(devfd, (void *)sblock, SBSIZE)) != SBSIZE) {
} else if ((n = write(devfd, (void *)sblock, SBLOCKSIZE)) != SBLOCKSIZE) {
warn("can't read backup superblock %d on %s: %s",
cg + 1, device, (n < SBSIZE) ? "short write"
cg + 1, device, (n < SBLOCKSIZE) ? "short write"
: strerror(errno));
return (1);
}
if (sblock->fs_magic != FS_MAGIC) {
if (sblock->fs_magic != FS_UFS1_MAGIC &&
sblock->fs_magic != FS_UFS2_MAGIC) {
warnx("bad magic number in backup superblock %d on %s",
cg + 1, device);
return (1);
}
if (sblock->fs_sbsize > SBSIZE) {
if (sblock->fs_sbsize > SBLOCKSIZE) {
warnx("size of backup superblock %d on %s is preposterous",
cg + 1, device);
return (1);
@ -188,15 +202,15 @@ fsirand(char *device)
sblock = (struct fs *)&sbuf;
/* XXX - should really cap buffer at 512kb or so */
ibufsize = sizeof(struct dinode) * sblock->fs_ipg;
if (oldibufsize < ibufsize) {
if ((inodebuf = realloc(inodebuf, ibufsize)) == NULL)
errx(1, "can't allocate memory for inode buffer");
oldibufsize = ibufsize;
}
if (sblock->fs_magic == FS_UFS1_MAGIC)
ibufsize = sizeof(struct ufs1_dinode) * sblock->fs_ipg;
else
ibufsize = sizeof(struct ufs2_dinode) * sblock->fs_ipg;
if ((inodebuf = malloc(ibufsize)) == NULL)
errx(1, "can't allocate memory for inode buffer");
if (printonly && (sblock->fs_id[0] || sblock->fs_id[1])) {
if (sblock->fs_inodefmt >= FS_44INODEFMT && sblock->fs_id[0])
if (sblock->fs_id[0])
(void)printf("%s was randomized on %s", device,
ctime((const time_t *)&(sblock->fs_id[0])));
(void)printf("fsid: %x %x\n", sblock->fs_id[0],
@ -204,19 +218,20 @@ fsirand(char *device)
}
/* Randomize fs_id unless old 4.2BSD filesystem */
if ((sblock->fs_inodefmt >= FS_44INODEFMT) && !printonly) {
if (!printonly) {
/* Randomize fs_id and write out new sblock and backups */
sblock->fs_id[0] = (u_int32_t)time(NULL);
sblock->fs_id[1] = random();
if (lseek(devfd, SBOFF, SEEK_SET) == -1) {
warn("can't seek to superblock (%qd) on %s", SBOFF,
if (lseek(devfd, sblockloc, SEEK_SET) == -1) {
warn("can't seek to superblock (%qd) on %s", sblockloc,
device);
return (1);
}
if ((n = write(devfd, (void *)sblock, SBSIZE)) != SBSIZE) {
warn("can't read superblock on %s: %s", device,
(n < SBSIZE) ? "short write" : strerror(errno));
if ((n = write(devfd, (void *)sblock, SBLOCKSIZE)) !=
SBLOCKSIZE) {
warn("can't write superblock on %s: %s", device,
(n < SBLOCKSIZE) ? "short write" : strerror(errno));
return (1);
}
}
@ -224,15 +239,16 @@ fsirand(char *device)
/* For each cylinder group, randomize inodes and update backup sblock */
for (cg = 0, inumber = 0; cg < sblock->fs_ncg; cg++) {
/* Update superblock if appropriate */
if ((sblock->fs_inodefmt >= FS_44INODEFMT) && !printonly) {
if (!printonly) {
dblk = fsbtodb(sblock, cgsblock(sblock, cg));
if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) {
warn("can't seek to %qd", (off_t)dblk * bsize);
return (1);
} else if ((n = write(devfd, (void *)sblock, SBSIZE)) != SBSIZE) {
warn("can't read backup superblock %d on %s: %s",
cg + 1, device, (n < SBSIZE) ? "short write"
: strerror(errno));
} else if ((n = write(devfd, (void *)sblock,
SBLOCKSIZE)) != SBLOCKSIZE) {
warn("can't write backup superblock %d on %s: %s",
cg + 1, device, (n < SBLOCKSIZE) ?
"short write" : strerror(errno));
return (1);
}
}
@ -249,12 +265,19 @@ fsirand(char *device)
}
for (n = 0; n < sblock->fs_ipg; n++, inumber++) {
if (sblock->fs_magic == FS_UFS1_MAGIC)
dp1 = &((struct ufs1_dinode *)inodebuf)[n];
else
dp2 = &((struct ufs2_dinode *)inodebuf)[n];
if (inumber >= ROOTINO) {
if (printonly)
(void)printf("ino %d gen %x\n", inumber,
inodebuf[n].di_gen);
(void)printf("ino %d gen %qx\n",
inumber,
sblock->fs_magic == FS_UFS1_MAGIC ?
(quad_t)dp1->di_gen : dp2->di_gen);
else
inodebuf[n].di_gen = random();
(sblock->fs_magic == FS_UFS1_MAGIC ?
dp1->di_gen : dp2->di_gen) = random();
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@
.\" @(#)newfs.8 8.6 (Berkeley) 5/3/95
.\" $FreeBSD$
.\"
.Dd May 29, 2001
.Dd May 18, 2002
.Dt NEWFS 8
.Os
.Sh NAME
@ -40,12 +40,14 @@
.Nd construct a new filesystem
.Sh SYNOPSIS
.Nm
.Op Fl NOU
.Op Fl NU
.Op Fl O Ar filesystem-type
.Op Fl S Ar sector-size
.Op Fl T Ar disktype
.Op Fl a Ar maxcontig
.Op Fl b Ar block-size
.Op Fl c Ar cylinders
.Op Fl c Ar blocks-per-cylinder-group
.Op Fl d Ar max-extent-size
.Op Fl e Ar maxbpg
.Op Fl f Ar frag-size
.Op Fl g Ar avgfilesize
@ -54,7 +56,6 @@
.Op Fl m Ar free space
.Op Fl o Ar optimization
.Op Fl s Ar size
.Op Fl u Ar sectors
.Ar special
.Sh DESCRIPTION
.Nm Newfs
@ -82,12 +83,16 @@ For backward compatibility.
.It Fl N
Cause the filesystem parameters to be printed out
without really creating the filesystem.
.It Fl O
Use 1 to specify that a UFS1 format filesystem be built;
use 2 to specify that a UFS2 format filesystem be built.
The default is UFS1 format, but will eventually be changed to UFS2.
.It Fl U
Enables soft updates on the new filesystem.
.It Fl a Ar maxcontig
Specify the maximum number of contiguous blocks that will be
laid out before forcing a rotational delay.
The default value is 1.
The default value is 16.
See
.Xr tunefs 8
for more details on how to set this option.
@ -96,12 +101,17 @@ The block size of the filesystem, in bytes. It must be a power of 2. The
default size is 16384 bytes, and the smallest allowable size is 4096 bytes.
The optimal block:fragment ratio is 8:1.
Other ratios are possible, but are not recommended,
and may produce unpredictable results.
.It Fl c Ar #cylinders/group
The number of cylinders per cylinder group in a filesystem. The default
and may produce poor results.
.It Fl c Ar number of blocks per cylinders group
The number of blocks per cylinder group in a filesystem. The default
is to compute the maximum allowed by the other parameters. This value is
dependent on a number of other parameters, in particular the block size
and the number of bytes per inode.
.It Fl d Ar max extent size
The filesystem may choose to store large files using extents.
This parameter specifies the largest extent size that may be used.
It is presently limited to its default value which is 16 times
the filesystem blocksize.
.It Fl e Ar maxbpg
Indicate the maximum number of blocks any single file can
allocate out of a cylinder group before it is forced to begin
@ -178,11 +188,6 @@ to find the alternate superblocks if the standard superblock is lost.
.Bl -tag -width indent
.It Fl S Ar sector-size
The size of a sector in bytes (almost never anything but 512).
.It Fl u Ar sectors/cylinders
The number of sectors per cylinder available for data allocation by the file
system.
The default is 4096.
If zero is specified, the value from the disklabel will be used.
.El
.Sh EXAMPLES
.Dl newfs /dev/ad3s1a
@ -191,13 +196,12 @@ Creates a new ufs filesystem on
.Pa ad3s1a .
.Nm
will use a block size of 16384 bytes, a fragment size of 2048 bytes
and the largest possible number of cylinders per group.
and the largest possible number of blocks per cylinders group.
These values tend to produce better performance for most applications
than the historical defaults
(8192 byte block size and 1024 byte fragment size).
This large fragment size
may lead to large amounts of wasted space
on filesystems that contain a large number of small files.
This large fragment size may lead to much wasted space
on filesystems that contain many small files.
.Sh SEE ALSO
.Xr fdformat 1 ,
.Xr disktab 5 ,

View File

@ -1,4 +1,16 @@
/*
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Marshall
* Kirk McKusick and Network Associates Laboratories, the Security
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
* research program
*
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* Copyright (c) 1983, 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
@ -84,19 +96,19 @@ static const char rcsid[] =
#define DFL_BLKSIZE 16384
/*
* Cylinder groups may have up to many cylinders. The actual
* Cylinder groups may have up to MAXBLKSPERCG blocks. The actual
* number used depends upon how much information can be stored
* on a single cylinder. The default is to use as many as possible
* cylinders per group.
* in a cylinder group map which must fit in a single filesystem
* block. The default is to use as many as possible blocks per group.
*/
#define DESCPG 65536 /* desired fs_cpg ("infinity") */
#define MAXBLKSPERCG 0x7fffffff /* desired fs_fpg ("infinity") */
/*
* MAXBLKPG determines the maximum number of data blocks which are
* placed in a single cylinder group. The default is one indirect
* block worth of data blocks.
*/
#define MAXBLKPG(bsize) ((bsize) / sizeof(daddr_t))
#define MAXBLKPG(bsize) ((bsize) / sizeof(ufs2_daddr_t))
/*
* Each filesystem has a number of inodes statically allocated.
@ -105,26 +117,17 @@ static const char rcsid[] =
*/
#define NFPI 4
/*
* About the same time as the above, we knew what went where on the disks.
* no longer so, so kill the code which finds the different platters too...
* We do this by saying one head, with a lot of sectors on it.
* The number of sectors are used to determine the size of a cyl-group.
* Kirk suggested one or two meg per "cylinder" so we say two.
*/
#define NSECTORS 4096 /* number of sectors */
int Nflag; /* run without writing filesystem */
int Oflag = 1; /* filesystem format (1 => UFS1, 2 => UFS2) */
int Rflag; /* regression test */
int Uflag; /* enable soft updates for filesystem */
u_int fssize; /* filesystem size */
u_int secpercyl = NSECTORS; /* sectors per cylinder */
u_int sectorsize; /* bytes/sector */
quad_t fssize; /* file system size */
int sectorsize; /* bytes/sector */
int realsectorsize; /* bytes/sector in hardware */
int fsize = 0; /* fragment size */
int bsize = 0; /* block size */
int cpg = DESCPG; /* cylinders/cylinder group */
int cpgflg; /* cylinders/cylinder group flag was given */
int maxbsize = 0; /* maximum clustering */
int maxblkspercg = MAXBLKSPERCG; /* maximum blocks per cylinder group */
int minfree = MINFREE; /* free space threshold */
int opt = DEFAULTOPT; /* optimization preference (space or time) */
int density; /* number of bytes per inode */
@ -136,7 +139,6 @@ int fso; /* filedescriptor to device */
static char device[MAXPATHLEN];
static char *disktype;
static int t_or_u_flag; /* user has specified -t or -u */
static int unlabeled;
static struct disklabel *getdisklabel(char *s);
@ -151,15 +153,20 @@ main(int argc, char *argv[])
struct partition oldpartition;
struct stat st;
char *cp, *special;
int ch, n;
int ch;
off_t mediasize;
while ((ch = getopt(argc, argv,
"NRS:T:Ua:b:c:e:f:g:h:i:m:o:s:u:")) != -1)
"NO:RS:T:Ua:b:c:d:e:f:g:h:i:m:o:s:")) != -1)
switch (ch) {
case 'N':
Nflag = 1;
break;
case 'O':
if ((Oflag = atoi(optarg)) < 1 || Oflag > 2)
errx(1, "%s: bad filesystem format value",
optarg);
break;
case 'R':
Rflag = 1;
break;
@ -183,13 +190,17 @@ main(int argc, char *argv[])
errx(1, "%s: bad block size", optarg);
break;
case 'c':
if ((cpg = atoi(optarg)) <= 0)
errx(1, "%s: bad cylinders/group", optarg);
cpgflg++;
if ((maxblkspercg = atoi(optarg)) <= 0)
errx(1, "%s: bad blocks per cylinder group",
optarg);
break;
case 'd':
if ((maxbsize = atoi(optarg)) < MINBSIZE)
errx(1, "%s: bad extent block size", optarg);
break;
case 'e':
if ((maxbpg = atoi(optarg)) <= 0)
errx(1, "%s: bad blocks per file in a cylinder group",
errx(1, "%s: bad blocks per file in a cylinder group",
optarg);
break;
case 'f':
@ -202,7 +213,7 @@ main(int argc, char *argv[])
break;
case 'h':
if ((avgfilesperdir = atoi(optarg)) <= 0)
errx(1, "%s: bad average files per dir", optarg);
errx(1, "%s: bad average files per dir", optarg);
break;
case 'i':
if ((density = atoi(optarg)) <= 0)
@ -226,12 +237,6 @@ main(int argc, char *argv[])
if ((fssize = atoi(optarg)) <= 0)
errx(1, "%s: bad filesystem size", optarg);
break;
case 'u':
t_or_u_flag++;
if ((n = atoi(optarg)) < 0)
errx(1, "%s: bad sectors/track", optarg);
secpercyl = n;
break;
case '?':
default:
usage();
@ -293,8 +298,6 @@ main(int argc, char *argv[])
if (fssize > pp->p_size)
errx(1,
"%s: maximum filesystem size %d", special, pp->p_size);
if (secpercyl == 0)
secpercyl = lp->d_nsectors;
if (sectorsize == 0)
sectorsize = lp->d_secsize;
if (fsize == 0)
@ -308,8 +311,8 @@ main(int argc, char *argv[])
fsize = MAX(DFL_FRAGSIZE, sectorsize);
if (bsize <= 0)
bsize = MIN(DFL_BLKSIZE, 8 * fsize);
if (secpercyl <= 0)
errx(1, "%s: no default #sectors/track", special);
if (maxbsize == 0)
maxbsize = bsize;
/*
* Maxcontig sets the default for the maximum number of blocks
* that may be allocated sequentially. With filesystem clustering
@ -317,7 +320,7 @@ main(int argc, char *argv[])
* transfer size permitted by the controller or buffering.
*/
if (maxcontig == 0)
maxcontig = MAX(1, MAXPHYS / bsize - 1);
maxcontig = MAX(1, MAXPHYS / bsize);
if (density == 0)
density = NFPI * fsize;
if (minfree < MINFREE && opt != FS_OPTSPACE) {
@ -325,15 +328,6 @@ main(int argc, char *argv[])
fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
opt = FS_OPTSPACE;
}
/*
* Only complain if -t or -u have been specified; the default
* case (4096 sectors per cylinder) is intended to disagree
* with the disklabel.
*/
if (t_or_u_flag && lp != NULL && secpercyl != lp->d_secpercyl)
fprintf(stderr, "%s (%d) %s (%lu)\n",
"Warning: calculated sectors per cylinder", secpercyl,
"disagrees with disk label", (u_long)lp->d_secpercyl);
if (maxbpg == 0)
maxbpg = MAXBLKPG(bsize);
realsectorsize = sectorsize;
@ -341,7 +335,6 @@ main(int argc, char *argv[])
int secperblk = sectorsize / DEV_BSIZE;
sectorsize = DEV_BSIZE;
secpercyl *= secperblk;
fssize *= secperblk;
if (pp != NULL);
pp->p_size *= secperblk;
@ -349,7 +342,7 @@ main(int argc, char *argv[])
mkfs(pp, special);
if (!unlabeled) {
if (realsectorsize != DEV_BSIZE)
pp->p_size /= realsectorsize /DEV_BSIZE;
pp->p_size /= realsectorsize / DEV_BSIZE;
if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
rewritelabel(special, lp);
}
@ -357,8 +350,6 @@ main(int argc, char *argv[])
exit(0);
}
const char lmsg[] = "%s: can't read disk label; disk type must be specified";
struct disklabel *
getdisklabel(char *s)
{
@ -399,13 +390,15 @@ usage()
fprintf(stderr, "where fsoptions are:\n");
fprintf(stderr,
"\t-N do not create filesystem, just print out parameters\n");
fprintf(stderr, "\t-O filesystem format: 1 => UFS1, 2 => UFS2\n");
fprintf(stderr, "\t-R regression test, supress random factors\n");
fprintf(stderr, "\t-S sector size\n");
fprintf(stderr, "\t-T disktype\n");
fprintf(stderr, "\t-U enable soft updates\n");
fprintf(stderr, "\t-a maximum contiguous blocks\n");
fprintf(stderr, "\t-b block size\n");
fprintf(stderr, "\t-c cylinders/group\n");
fprintf(stderr, "\t-c blocks per cylinders group\n");
fprintf(stderr, "\t-d maximum extent size\n");
fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
fprintf(stderr, "\t-f frag size\n");
fprintf(stderr, "\t-g average file size\n");
@ -413,9 +406,6 @@ usage()
fprintf(stderr, "\t-i number of bytes per inode\n");
fprintf(stderr, "\t-m minimum free space %%\n");
fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
fprintf(stderr, "\t-s filesystem size (sectors)\n");
fprintf(stderr, "\t-u sectors/cylinder\n");
fprintf(stderr,
"\t-v do not attempt to determine partition name from device name\n");
fprintf(stderr, "\t-s file systemsize (sectors)\n");
exit(1);
}

View File

@ -1,4 +1,16 @@
/*
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Marshall
* Kirk McKusick and Network Associates Laboratories, the Security
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
* research program
*
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* Copyright (c) 1980, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
@ -38,16 +50,16 @@
* variables set up by front end.
*/
extern int Nflag; /* run mkfs without writing filesystem */
extern int Oflag; /* build UFS1 format filesystem */
extern int Rflag; /* regression test */
extern int Uflag; /* enable soft updates for filesystem */
extern u_int fssize; /* filesystem size */
extern u_int secpercyl; /* sectors per cylinder */
extern u_int sectorsize; /* bytes/sector */
extern quad_t fssize; /* file system size */
extern int sectorsize; /* bytes/sector */
extern int realsectorsize; /* bytes/sector in hardware*/
extern int fsize; /* fragment size */
extern int bsize; /* block size */
extern int cpg; /* cylinders/cylinder group */
extern int cpgflg; /* cylinders/cylinder group flag was given */
extern int maxbsize; /* maximum clustering */
extern int maxblkspercg; /* maximum blocks per cylinder group */
extern int minfree; /* free space threshold */
extern int opt; /* optimization preference (space or time) */
extern int density; /* number of bytes per inode */

View File

@ -82,6 +82,14 @@ union {
long dev_bsize = 1;
ino_t maxino;
union dinode {
struct ufs1_dinode dp1;
struct ufs2_dinode dp2;
};
#define DIP(dp, field) \
((sblock.fs_magic == FS_UFS1_MAGIC) ? \
(dp)->dp1.field : (dp)->dp2.field)
struct quotaname {
long flags;
char grpqfname[MAXPATHLEN + 1];
@ -116,7 +124,7 @@ extern int checkfstab(int, int, void * (*)(struct fstab *),
int (*)(char *, char *, struct quotaname *));
int chkquota(char *, char *, struct quotaname *);
void freeinodebuf(void);
struct dinode *
union dinode *
getnextinode(ino_t);
int getquotagid(void);
int hasquota(struct fstab *, int, char **);
@ -240,6 +248,11 @@ needchk(fs)
return (NULL);
}
/*
* Possible superblock locations ordered from most to least likely.
*/
static int sblock_try[] = SBLOCKSEARCH;
/*
* Scan the specified filesystem to check quota(s) present on it.
*/
@ -249,7 +262,7 @@ chkquota(fsname, mntpt, qnp)
struct quotaname *qnp;
{
struct fileusage *fup;
struct dinode *dp;
union dinode *dp;
int cg, i, mode, errs = 0;
ino_t ino;
@ -268,7 +281,20 @@ chkquota(fsname, mntpt, qnp)
}
sync();
dev_bsize = 1;
bread(SBOFF, (char *)&sblock, (long)SBSIZE);
for (i = 0; sblock_try[i] != -1; i++) {
bread(sblock_try[i], (char *)&sblock, (long)SBLOCKSIZE);
if ((sblock.fs_magic == FS_UFS1_MAGIC ||
(sblock.fs_magic == FS_UFS2_MAGIC &&
sblock.fs_sblockloc ==
numfrags(&sblock, sblock_try[i]))) &&
sblock.fs_bsize <= MAXBSIZE &&
sblock.fs_bsize >= sizeof(struct fs))
break;
}
if (sblock_try[i] == -1) {
warn("Cannot find filesystem superblock");
return (1);
}
dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
maxino = sblock.fs_ncg * sblock.fs_ipg;
resetinodebuf();
@ -278,23 +304,23 @@ chkquota(fsname, mntpt, qnp)
continue;
if ((dp = getnextinode(ino)) == NULL)
continue;
if ((mode = dp->di_mode & IFMT) == 0)
if ((mode = DIP(dp, di_mode) & IFMT) == 0)
continue;
if (qnp->flags & HASGRP) {
fup = addid((u_long)dp->di_gid, GRPQUOTA,
fup = addid((u_long)DIP(dp, di_gid), GRPQUOTA,
(char *)0);
fup->fu_curinodes++;
if (mode == IFREG || mode == IFDIR ||
mode == IFLNK)
fup->fu_curblocks += dp->di_blocks;
fup->fu_curblocks += DIP(dp, di_blocks);
}
if (qnp->flags & HASUSR) {
fup = addid((u_long)dp->di_uid, USRQUOTA,
fup = addid((u_long)DIP(dp, di_uid), USRQUOTA,
(char *)0);
fup->fu_curinodes++;
if (mode == IFREG || mode == IFDIR ||
mode == IFLNK)
fup->fu_curblocks += dp->di_blocks;
fup->fu_curblocks += DIP(dp, di_blocks);
}
}
}
@ -536,20 +562,21 @@ addid(id, type, name)
* Special purpose version of ginode used to optimize pass
* over all the inodes in numerical order.
*/
ino_t nextino, lastinum;
long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
struct dinode *inodebuf;
#define INOBUFSIZE 56*1024 /* size of buffer to read inodes */
static ino_t nextino, lastinum, lastvalidinum;
static long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
static caddr_t inodebuf;
#define INOBUFSIZE 56*1024 /* size of buffer to read inodes */
struct dinode *
union dinode *
getnextinode(inumber)
ino_t inumber;
{
long size;
daddr_t dblk;
static struct dinode *dp;
ufs2_daddr_t dblk;
union dinode *dp;
static caddr_t nextinop;
if (inumber != nextino++ || inumber > maxino)
if (inumber != nextino++ || inumber > lastvalidinum)
errx(1, "bad inode number %d to nextinode", inumber);
if (inumber >= lastinum) {
readcnt++;
@ -561,10 +588,19 @@ getnextinode(inumber)
size = inobufsize;
lastinum += fullcnt;
}
bread(dblk, (char *)inodebuf, size);
dp = inodebuf;
/*
* If bread returns an error, it will already have zeroed
* out the buffer, so we do not need to do so here.
*/
bread(dblk, inodebuf, size);
nextinop = inodebuf;
}
return (dp++);
dp = (union dinode *)nextinop;
if (sblock.fs_magic == FS_UFS1_MAGIC)
nextinop += sizeof(struct ufs1_dinode);
else
nextinop += sizeof(struct ufs2_dinode);
return (dp);
}
/*
@ -578,10 +614,12 @@ resetinodebuf()
lastinum = 0;
readcnt = 0;
inobufsize = blkroundup(&sblock, INOBUFSIZE);
fullcnt = inobufsize / sizeof(struct dinode);
fullcnt = inobufsize / ((sblock.fs_magic == FS_UFS1_MAGIC) ?
sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode));
readpercg = sblock.fs_ipg / fullcnt;
partialcnt = sblock.fs_ipg % fullcnt;
partialsize = partialcnt * sizeof(struct dinode);
partialsize = partialcnt * ((sblock.fs_magic == FS_UFS1_MAGIC) ?
sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode));
if (partialcnt != 0) {
readpercg++;
} else {

View File

@ -120,7 +120,7 @@ struct odirect {
char d_name[ODIRSIZ];
};
static struct inotab *allocinotab(ino_t, struct dinode *, long);
static struct inotab *allocinotab(struct context *, long);
static void dcvt(struct odirect *, struct direct *);
static void flushent(void);
static struct inotab *inotablookup(ino_t);
@ -140,11 +140,9 @@ static struct direct *searchdir(ino_t, char *);
void
extractdirs(int genmode)
{
int i;
struct dinode *ip;
struct inotab *itp;
struct direct nulldir;
int fd;
int i, fd;
const char *tmpdir;
vprintf(stdout, "Extract directories from tape\n");
@ -184,8 +182,7 @@ extractdirs(int genmode)
for (;;) {
curfile.name = "<directory file - name unknown>";
curfile.action = USING;
ip = curfile.dip;
if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) {
if (curfile.mode == 0 || (curfile.mode & IFMT) != IFDIR) {
(void) fclose(df);
dirp = opendirfile(dirfile);
if (dirp == NULL)
@ -198,7 +195,7 @@ extractdirs(int genmode)
panic("Root directory is not on tape\n");
return;
}
itp = allocinotab(curfile.ino, ip, seekpt);
itp = allocinotab(&curfile, seekpt);
getfile(putdir, xtrnull);
putent(&nulldir);
flushent();
@ -213,7 +210,7 @@ void
skipdirs(void)
{
while (curfile.dip && (curfile.dip->di_mode & IFMT) == IFDIR) {
while (curfile.ino && (curfile.mode & IFMT) == IFDIR) {
skipfile();
}
}
@ -343,53 +340,34 @@ putdir(char *buf, long size)
struct direct *dp;
long loc, i;
if (cvtflag) {
eodp = (struct odirect *)&buf[size];
for (odp = (struct odirect *)buf; odp < eodp; odp++)
if (odp->d_ino != 0) {
dcvt(odp, &cvtbuf);
putent(&cvtbuf);
}
} else {
for (loc = 0; loc < size; ) {
dp = (struct direct *)(buf + loc);
if (Bcvt)
swabst((u_char *)"ls", (u_char *) dp);
if (oldinofmt && dp->d_ino != 0) {
# if BYTE_ORDER == BIG_ENDIAN
if (Bcvt)
dp->d_namlen = dp->d_type;
# else
if (!Bcvt)
dp->d_namlen = dp->d_type;
# endif
dp->d_type = DT_UNKNOWN;
}
i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
if ((dp->d_reclen & 0x3) != 0 ||
dp->d_reclen > i ||
dp->d_reclen < DIRSIZ(0, dp) ||
dp->d_namlen > NAME_MAX) {
vprintf(stdout, "Mangled directory: ");
if ((dp->d_reclen & 0x3) != 0)
vprintf(stdout,
"reclen not multiple of 4 ");
if (dp->d_reclen < DIRSIZ(0, dp))
vprintf(stdout,
"reclen less than DIRSIZ (%d < %d) ",
dp->d_reclen, DIRSIZ(0, dp));
if (dp->d_namlen > NAME_MAX)
vprintf(stdout,
"reclen name too big (%d > %d) ",
dp->d_namlen, NAME_MAX);
vprintf(stdout, "\n");
loc += i;
continue;
}
loc += dp->d_reclen;
if (dp->d_ino != 0) {
putent(dp);
}
for (loc = 0; loc < size; ) {
dp = (struct direct *)(buf + loc);
if (Bcvt)
swabst((u_char *)"ls", (u_char *) dp);
i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
if ((dp->d_reclen & 0x3) != 0 ||
dp->d_reclen > i ||
dp->d_reclen < DIRSIZ(0, dp) ||
dp->d_namlen > NAME_MAX) {
vprintf(stdout, "Mangled directory: ");
if ((dp->d_reclen & 0x3) != 0)
vprintf(stdout,
"reclen not multiple of 4 ");
if (dp->d_reclen < DIRSIZ(0, dp))
vprintf(stdout,
"reclen less than DIRSIZ (%d < %d) ",
dp->d_reclen, DIRSIZ(0, dp));
if (dp->d_namlen > NAME_MAX)
vprintf(stdout,
"reclen name too big (%d > %d) ",
dp->d_namlen, NAME_MAX);
vprintf(stdout, "\n");
loc += i;
continue;
}
loc += dp->d_reclen;
if (dp->d_ino != 0) {
putent(dp);
}
}
}
@ -692,7 +670,7 @@ inodetype(ino_t ino)
* If requested, save its pertinent mode, owner, and time info.
*/
static struct inotab *
allocinotab(ino_t ino, struct dinode *dip, long seekpt)
allocinotab(struct context *ctxp, long seekpt)
{
struct inotab *itp;
struct modeinfo node;
@ -700,21 +678,21 @@ allocinotab(ino_t ino, struct dinode *dip, long seekpt)
itp = calloc(1, sizeof(struct inotab));
if (itp == NULL)
panic("no memory directory table\n");
itp->t_next = inotab[INOHASH(ino)];
inotab[INOHASH(ino)] = itp;
itp->t_ino = ino;
itp->t_next = inotab[INOHASH(ctxp->ino)];
inotab[INOHASH(ctxp->ino)] = itp;
itp->t_ino = ctxp->ino;
itp->t_seekpt = seekpt;
if (mf == NULL)
return (itp);
node.ino = ino;
node.timep[0].tv_sec = dip->di_atime;
node.timep[0].tv_usec = dip->di_atimensec / 1000;
node.timep[1].tv_sec = dip->di_mtime;
node.timep[1].tv_usec = dip->di_mtimensec / 1000;
node.mode = dip->di_mode;
node.flags = dip->di_flags;
node.uid = dip->di_uid;
node.gid = dip->di_gid;
node.ino = ctxp->ino;
node.timep[0].tv_sec = ctxp->atime_sec;
node.timep[0].tv_usec = ctxp->atime_nsec / 1000;
node.timep[1].tv_sec = ctxp->mtime_sec;
node.timep[1].tv_usec = ctxp->mtime_nsec / 1000;
node.mode = ctxp->mode;
node.flags = ctxp->file_flags;
node.uid = ctxp->uid;
node.gid = ctxp->gid;
(void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf);
return (itp);
}

View File

@ -98,9 +98,9 @@ main(int argc, char *argv[])
inputdev = _PATH_DEFTAPE;
obsolete(&argc, &argv);
#ifdef KERBEROS
#define optlist "b:cdf:hikmNRrs:tuvxy"
#define optlist "b:df:hikmNRrs:tuvxy"
#else
#define optlist "b:cdf:himNRrs:tuvxy"
#define optlist "b:df:himNRrs:tuvxy"
#endif
while ((ch = getopt(argc, argv, optlist)) != -1)
switch(ch) {
@ -113,9 +113,6 @@ main(int argc, char *argv[])
if (ntrec <= 0)
errx(1, "block size must be greater than 0");
break;
case 'c':
cvtflag = 1;
break;
case 'd':
dflag = 1;
break;

View File

@ -41,11 +41,11 @@ static const char rcsid[] =
#include <sys/types.h>
#include <ufs/ufs/dinode.h>
#include <stdio.h>
#include <string.h>
#include <ufs/ufs/dinode.h>
#include "restore.h"
#include "extern.h"

View File

@ -42,7 +42,6 @@
/*
* Flags
*/
extern int cvtflag; /* convert from old to new tape format */
extern int bflag; /* set input block size */
extern int dflag; /* print out debugging info */
extern int hflag; /* restore heirarchies */
@ -64,7 +63,6 @@ extern time_t dumptime; /* time that this dump begins */
extern time_t dumpdate; /* time that this dump was made */
extern char command; /* opration being performed */
extern FILE *terminal; /* file descriptor for the terminal input */
extern int oldinofmt; /* reading tape with old format inodes */
extern int Bcvt; /* need byte swapping on inodes and dirs */
/*
@ -106,10 +104,19 @@ struct entry {
* The entry describes the next file available on the tape
*/
struct context {
char *name; /* name of file */
short action; /* action being taken on this file */
mode_t mode; /* mode of file */
ino_t ino; /* inumber of file */
struct dinode *dip; /* pointer to inode */
char action; /* action being taken on this file */
uid_t uid; /* file owner */
gid_t gid; /* file group */
int file_flags; /* status flags (chflags) */
int rdev; /* device number of file */
time_t atime_sec; /* access time seconds */
time_t mtime_sec; /* modified time seconds */
int atime_nsec; /* access time nanoseconds */
int mtime_nsec; /* modified time nanoseconds */
off_t size; /* size of file */
char *name; /* name of file */
} curfile;
/* actions */
#define USING 1 /* extracting from the tape */

View File

@ -74,20 +74,19 @@ static int numtrec;
static char *tapebuf;
static union u_spcl endoftapemark;
static long blksread; /* blocks read since last header */
static long tapeaddr = 0; /* current TP_BSIZE tape record */
static int64_t tapeaddr = 0; /* current TP_BSIZE tape record */
static long tapesread;
static jmp_buf restart;
static int gettingfile = 0; /* restart has a valid frame */
static char *host = NULL;
static int readmapflag;
static int ofile;
static char *map;
static char lnkbuf[MAXPATHLEN + 1];
static int pathlen;
int oldinofmt; /* old inode format conversion required */
int Bcvt; /* Swap Bytes (for CCI or sun) */
static int Qcvt; /* Swap quads (for sun) */
int Bcvt; /* Swap Bytes */
#define FLUSHTAPEBUF() blkcnt = ntrec + 1
@ -109,8 +108,6 @@ static void xtrmap(char *, long);
static void xtrmapskip(char *, long);
static void xtrskip(char *, long);
static int readmapflag;
/*
* Set up an input source
*/
@ -207,17 +204,11 @@ setup(void)
if (!pipein && !bflag)
findtapeblksize();
if (gethead(&spcl) == FAIL) {
blkcnt--; /* push back this block */
blksread--;
cvtflag++;
if (gethead(&spcl) == FAIL) {
fprintf(stderr, "Tape is not a dump tape\n");
done(1);
}
fprintf(stderr, "Converting to new filesystem format.\n");
fprintf(stderr, "Tape is not a dump tape\n");
done(1);
}
if (pipein) {
endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC;
endoftapemark.s_spcl.c_magic = FS_UFS2_MAGIC;
endoftapemark.s_spcl.c_type = TS_END;
ip = (int *)&endoftapemark;
j = sizeof(union u_spcl) / sizeof(int);
@ -229,8 +220,8 @@ setup(void)
}
if (vflag || command == 't')
printdumpinfo();
dumptime = _time32_to_time(spcl.c_ddate);
dumpdate = _time32_to_time(spcl.c_date);
dumptime = _time64_to_time(spcl.c_ddate);
dumpdate = _time64_to_time(spcl.c_date);
if (stat(".", &stbuf) < 0) {
fprintf(stderr, "cannot stat .: %s\n", strerror(errno));
done(1);
@ -279,8 +270,7 @@ setup(void)
* whiteout inode exists, so that the whiteout entries can be
* extracted.
*/
if (oldinofmt == 0)
SETINO(WINO, dumpmap);
SETINO(WINO, dumpmap);
/* 'r' restores don't call getvol() for tape 1, so mark it as read. */
if (command == 'r')
tapesread = 1;
@ -296,7 +286,8 @@ setup(void)
void
getvol(long nextvol)
{
long newvol, prevtapea, savecnt, i;
int64_t prevtapea;
long i, newvol, savecnt;
union u_spcl tmpspcl;
# define tmpbuf tmpspcl.s_spcl
char buf[TP_BSIZE];
@ -403,9 +394,9 @@ getvol(long nextvol)
volno = 0;
goto again;
}
if (_time32_to_time(tmpbuf.c_date) != dumpdate ||
_time32_to_time(tmpbuf.c_ddate) != dumptime) {
time_t t = _time32_to_time(tmpbuf.c_date);
if (_time64_to_time(tmpbuf.c_date) != dumpdate ||
_time64_to_time(tmpbuf.c_ddate) != dumptime) {
time_t t = _time64_to_time(tmpbuf.c_date);
fprintf(stderr, "Wrong dump date\n\tgot: %s", ctime(&t));
fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
volno = 0;
@ -420,9 +411,9 @@ getvol(long nextvol)
* If coming to this volume at random, skip to the beginning
* of the next record.
*/
dprintf(stdout, "last rec %ld, tape starts with %ld\n", prevtapea,
dprintf(stdout, "last rec %qd, tape starts with %qd\n", prevtapea,
tmpbuf.c_tapea);
if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) {
if (tmpbuf.c_type == TS_TAPE) {
if (curfile.action != USING) {
/*
* XXX Dump incorrectly sets c_count to 1 in the
@ -475,7 +466,7 @@ terminateinput(void)
}
curfile.name = "<name unknown>";
curfile.action = UNKNOWN;
curfile.dip = NULL;
curfile.mode = 0;
curfile.ino = maxino;
if (gettingfile) {
gettingfile = 0;
@ -513,9 +504,9 @@ void
printdumpinfo(void)
{
time_t t;
t = _time32_to_time(spcl.c_date);
t = _time64_to_time(spcl.c_date);
fprintf(stdout, "Dump date: %s", ctime(&t));
t = _time32_to_time(spcl.c_ddate);
t = _time64_to_time(spcl.c_ddate);
fprintf(stdout, "Dumped from: %s",
(spcl.c_ddate == 0) ? "the epoch\n" : ctime(&t));
if (spcl.c_host[0] == '\0')
@ -529,22 +520,18 @@ int
extractfile(char *name)
{
int flags;
uid_t uid;
gid_t gid;
mode_t mode;
struct timeval timep[2];
struct entry *ep;
curfile.name = name;
curfile.action = USING;
timep[0].tv_sec = curfile.dip->di_atime;
timep[0].tv_usec = curfile.dip->di_atimensec / 1000;
timep[1].tv_sec = curfile.dip->di_mtime;
timep[1].tv_usec = curfile.dip->di_mtimensec / 1000;
uid = curfile.dip->di_uid;
gid = curfile.dip->di_gid;
mode = curfile.dip->di_mode;
flags = curfile.dip->di_flags;
timep[0].tv_sec = curfile.atime_sec;
timep[0].tv_usec = curfile.atime_nsec / 1000;
timep[1].tv_sec = curfile.mtime_sec;
timep[1].tv_usec = curfile.mtime_nsec / 1000;
mode = curfile.mode;
flags = curfile.file_flags;
switch (mode & IFMT) {
default:
@ -578,7 +565,7 @@ extractfile(char *name)
return (GOOD);
}
if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
(void) lchown(name, uid, gid);
(void) lchown(name, curfile.uid, curfile.gid);
(void) lchmod(name, mode);
(void) lutimes(name, timep);
return (GOOD);
@ -599,7 +586,7 @@ extractfile(char *name)
skipfile();
return (FAIL);
}
(void) chown(name, uid, gid);
(void) chown(name, curfile.uid, curfile.gid);
(void) chmod(name, mode);
(void) utimes(name, timep);
(void) chflags(name, flags);
@ -615,13 +602,13 @@ extractfile(char *name)
}
if (uflag)
(void)unlink(name);
if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
if (mknod(name, mode, (int)curfile.rdev) < 0) {
fprintf(stderr, "%s: cannot create special file: %s\n",
name, strerror(errno));
skipfile();
return (FAIL);
}
(void) chown(name, uid, gid);
(void) chown(name, curfile.uid, curfile.gid);
(void) chmod(name, mode);
(void) utimes(name, timep);
(void) chflags(name, flags);
@ -643,7 +630,7 @@ extractfile(char *name)
skipfile();
return (FAIL);
}
(void) fchown(ofile, uid, gid);
(void) fchown(ofile, curfile.uid, curfile.gid);
(void) fchmod(ofile, mode);
getfile(xtrfile, xtrskip);
(void) close(ofile);
@ -687,14 +674,14 @@ getfile(void (*fill)(char *, long), void (*skip)(char *, long))
{
int i;
int curblk = 0;
quad_t size = spcl.c_dinode.di_size;
quad_t size = spcl.c_size;
static char clearedbuf[MAXBSIZE];
char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
char junk[TP_BSIZE];
if (spcl.c_type == TS_END)
panic("ran off end of tape\n");
if (spcl.c_magic != NFS_MAGIC)
if (spcl.c_magic != FS_UFS2_MAGIC)
panic("not at beginning of a file\n");
if (!gettingfile && setjmp(restart) != 0)
return;
@ -1000,106 +987,43 @@ closemt(void)
/*
* Read the next block from the tape.
* Check to see if it is one of several vintage headers.
* If it is an old style header, convert it to a new style header.
* If it is not any valid header, return an error.
*/
static int
gethead(struct s_spcl *buf)
{
long i;
union {
quad_t qval;
int32_t val[2];
} qcvt;
union u_ospcl {
char dummy[TP_BSIZE];
struct s_ospcl {
int32_t c_type;
int32_t c_date;
int32_t c_ddate;
int32_t c_volume;
int32_t c_tapea;
u_short c_inumber;
int32_t c_magic;
int32_t c_checksum;
struct odinode {
unsigned short odi_mode;
u_short odi_nlink;
u_short odi_uid;
u_short odi_gid;
int32_t odi_size;
int32_t odi_rdev;
char odi_addr[36];
int32_t odi_atime;
int32_t odi_mtime;
int32_t odi_ctime;
} c_dinode;
int32_t c_count;
char c_addr[256];
} s_ospcl;
} u_ospcl;
if (!cvtflag) {
readtape((char *)buf);
if (buf->c_magic != NFS_MAGIC) {
if (swabl(buf->c_magic) != NFS_MAGIC)
return (FAIL);
if (!Bcvt) {
vprintf(stdout, "Note: Doing Byte swapping\n");
Bcvt = 1;
}
}
if (checksum((int *)buf) == FAIL)
readtape((char *)buf);
if (buf->c_magic != FS_UFS2_MAGIC && buf->c_magic != NFS_MAGIC) {
if (buf->c_magic == OFS_MAGIC) {
fprintf(stderr,
"Format of dump tape is too old. Must use\n");
fprintf(stderr,
"a version of restore from before 2002.\n");
return (FAIL);
if (Bcvt) {
swabst((u_char *)"8l4s31l", (u_char *)buf);
swabst((u_char *)"l",(u_char *) &buf->c_level);
swabst((u_char *)"2l",(u_char *) &buf->c_flags);
}
goto good;
}
readtape((char *)(&u_ospcl.s_ospcl));
memset(buf, 0, (long)TP_BSIZE);
buf->c_type = u_ospcl.s_ospcl.c_type;
buf->c_date = u_ospcl.s_ospcl.c_date;
buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
buf->c_volume = u_ospcl.s_ospcl.c_volume;
buf->c_tapea = u_ospcl.s_ospcl.c_tapea;
buf->c_inumber = u_ospcl.s_ospcl.c_inumber;
buf->c_checksum = u_ospcl.s_ospcl.c_checksum;
buf->c_magic = u_ospcl.s_ospcl.c_magic;
buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;
buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;
buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;
buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;
buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size;
buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev;
buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime;
buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime;
buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime;
buf->c_count = u_ospcl.s_ospcl.c_count;
memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256);
if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||
checksum((int *)(&u_ospcl.s_ospcl)) == FAIL)
return(FAIL);
buf->c_magic = NFS_MAGIC;
good:
if ((buf->c_dinode.di_size == 0 || buf->c_dinode.di_size > 0xfffffff) &&
(buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) {
qcvt.qval = buf->c_dinode.di_size;
if (qcvt.val[0] || qcvt.val[1]) {
printf("Note: Doing Quad swapping\n");
Qcvt = 1;
if (swabl(buf->c_magic) != FS_UFS2_MAGIC &&
buf->c_magic != NFS_MAGIC) {
if (buf->c_magic == OFS_MAGIC) {
fprintf(stderr,
"Format of dump tape is too old. Must use\n");
fprintf(stderr,
"a version of restore from before 2002.\n");
}
return (FAIL);
}
if (!Bcvt) {
vprintf(stdout, "Note: Doing Byte swapping\n");
Bcvt = 1;
}
}
if (Qcvt) {
qcvt.qval = buf->c_dinode.di_size;
i = qcvt.val[1];
qcvt.val[1] = qcvt.val[0];
qcvt.val[0] = i;
buf->c_dinode.di_size = qcvt.qval;
if (checksum((int *)buf) == FAIL)
return (FAIL);
if (Bcvt) {
swabst((u_char *)"8l4s1q8l2q17l", (u_char *)buf);
swabst((u_char *)"l",(u_char *) &buf->c_level);
swabst((u_char *)"2l4q",(u_char *) &buf->c_flags);
}
readmapflag = 0;
@ -1111,7 +1035,7 @@ gethead(struct s_spcl *buf)
* Have to patch up missing information in bit map headers
*/
buf->c_inumber = 0;
buf->c_dinode.di_size = buf->c_count * TP_BSIZE;
buf->c_size = buf->c_count * TP_BSIZE;
if (buf->c_count > TP_NINDIR)
readmapflag = 1;
else
@ -1120,14 +1044,25 @@ gethead(struct s_spcl *buf)
break;
case TS_TAPE:
if ((buf->c_flags & DR_NEWINODEFMT) == 0)
oldinofmt = 1;
/* fall through */
case TS_END:
buf->c_inumber = 0;
break;
case TS_INODE:
/*
* For old dump tapes, have to copy up old fields to
* new locations.
*/
if (buf->c_magic == NFS_MAGIC) {
buf->c_tapea = buf->c_old_tapea;
buf->c_firstrec = buf->c_old_firstrec;
buf->c_date = _time32_to_time(buf->c_old_date);
buf->c_ddate = _time32_to_time(buf->c_old_ddate);
buf->c_atime = _time32_to_time(buf->c_old_atime);
buf->c_mtime = _time32_to_time(buf->c_old_mtime);
}
break;
case TS_ADDR:
break;
@ -1135,14 +1070,7 @@ gethead(struct s_spcl *buf)
panic("gethead: unknown inode type %d\n", buf->c_type);
break;
}
/*
* If we are restoring a filesystem with old format inodes,
* copy the uid/gid to the new location.
*/
if (oldinofmt) {
buf->c_dinode.di_uid = buf->c_dinode.di_ouid;
buf->c_dinode.di_gid = buf->c_dinode.di_ogid;
}
buf->c_magic = FS_UFS2_MAGIC;
tapeaddr = buf->c_tapea;
if (dflag)
accthdr(buf);
@ -1161,10 +1089,9 @@ accthdr(struct s_spcl *header)
long blks, i;
if (header->c_type == TS_TAPE) {
fprintf(stderr, "Volume header (%s inode format) ",
oldinofmt ? "old" : "new");
fprintf(stderr, "Volume header ");
if (header->c_firstrec)
fprintf(stderr, "begins with record %ld",
fprintf(stderr, "begins with record %qd",
header->c_firstrec);
fprintf(stderr, "\n");
previno = 0x7fffffff;
@ -1219,15 +1146,9 @@ findinode(struct s_spcl *header)
curfile.name = "<name unknown>";
curfile.action = UNKNOWN;
curfile.dip = NULL;
curfile.mode = 0;
curfile.ino = 0;
do {
if (header->c_magic != NFS_MAGIC) {
skipcnt++;
while (gethead(header) == FAIL ||
_time32_to_time(header->c_date) != dumpdate)
skipcnt++;
}
htype = header->c_type;
switch (htype) {
@ -1239,12 +1160,21 @@ findinode(struct s_spcl *header)
if (header->c_addr[i])
readtape(buf);
while (gethead(header) == FAIL ||
_time32_to_time(header->c_date) != dumpdate)
_time64_to_time(header->c_date) != dumpdate)
skipcnt++;
break;
case TS_INODE:
curfile.dip = &header->c_dinode;
curfile.mode = header->c_mode;
curfile.uid = header->c_uid;
curfile.gid = header->c_gid;
curfile.file_flags = header->c_file_flags;
curfile.rdev = header->c_rdev;
curfile.atime_sec = header->c_atime;
curfile.atime_nsec = header->c_atimensec;
curfile.mtime_sec = header->c_mtime;
curfile.mtime_nsec = header->c_mtimensec;
curfile.size = header->c_size;
curfile.ino = header->c_inumber;
break;
@ -1288,7 +1218,7 @@ checksum(int *buf)
j = sizeof(union u_spcl) / sizeof(int);
i = 0;
if(!Bcvt) {
if (!Bcvt) {
do
i += *buf++;
while (--j);
@ -1346,6 +1276,21 @@ swablong(u_char *sp, int n)
return (sp);
}
static u_char *
swabquad(u_char *sp, int n)
{
char c;
while (--n >= 0) {
c = sp[0]; sp[0] = sp[7]; sp[7] = c;
c = sp[1]; sp[1] = sp[6]; sp[6] = c;
c = sp[2]; sp[2] = sp[5]; sp[5] = c;
c = sp[3]; sp[3] = sp[4]; sp[4] = c;
sp += 8;
}
return (sp);
}
void
swabst(u_char *cp, u_char *sp)
{
@ -1370,11 +1315,23 @@ swabst(u_char *cp, u_char *sp)
sp = swablong(sp, n);
break;
default: /* Any other character, like 'b' counts as byte. */
case 'q':
if (n == 0)
n = 1;
sp = swabquad(sp, n);
break;
case 'b':
if (n == 0)
n = 1;
sp += n;
break;
default:
fprintf(stderr, "Unknown conversion character: %c\n",
*cp);
done(0);
break;
}
cp++;
n = 0;

View File

@ -32,7 +32,7 @@
.\" @(#)tunefs.8 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
.Dd December 11, 1993
.Dd May 18, 2002
.Dt TUNEFS 8
.Os
.Sh NAME
@ -42,7 +42,6 @@
.Nm
.Op Fl A
.Op Fl a Ar maxcontig
.Op Fl d Ar rotdelay
.Op Fl e Ar maxbpg
.Op Fl f Ar avgfilesize
.Op Fl m Ar minfree
@ -57,6 +56,13 @@
.Nm Tunefs
is designed to change the dynamic parameters of a filesystem
which affect the layout policies.
The
.Nm
program cannot be run on an active filesystem.
To change an active filesystem,
you must either downgrade the filesystem to read-only
or unmount it.
.Pp
The parameters which are to be changed are indicated by the flags
given below:
.Bl -tag -width indent
@ -66,19 +72,8 @@ this option will cause all backups to be modified as well as the
primary super-block. This is potentially dangerous - use with caution.
.It Fl a Ar maxcontig
Specify the maximum number of contiguous blocks that will
be laid out before forcing a rotational delay (see
.Fl d
below).
The default value is one, since most device drivers require
an interrupt per disk transfer.
Device drivers that can chain several buffers together in a single
transfer should set this to the maximum chain length.
.It Fl d Ar rotdelay
Specify the expected time (in milliseconds)
to service a transfer completion
interrupt and initiate a new transfer on the same disk.
It is used to decide how much rotational spacing to place between
successive blocks in a file.
be laid out before allowing a rotational delay.
The default value is 16.
.It Fl e Ar maxbpg
Indicate the maximum number of blocks any single file can
allocate out of a cylinder group before it is forced to begin
@ -131,9 +126,11 @@ the percent fragmentation changes on the filesystem.
.It Fl p
Show a summary of what the current tunable settings
are on the selected filesystem. More detailed information can be
obtained in the
obtained from the
.Xr dumpfs 8
manual page.
or
.Xr ffsinfo 8
programs.
.It Fl s Ar avgfpdir
Specify the expected number of files per directory.
.El
@ -148,6 +145,7 @@ specified mount point.
.Sh SEE ALSO
.Xr fs 5 ,
.Xr dumpfs 8 ,
.Xr ffsinfo 8 ,
.Xr newfs 8
.Rs
.%A M. McKusick
@ -162,13 +160,8 @@ specified mount point.
.%O "(reprinted in the BSD System Manager's Manual, SMM:5)"
.Re
.Sh BUGS
This program should work on mounted and active filesystems.
Because the super-block is not kept in the buffer cache,
the changes will only take effect if the program
is run on dismounted filesystems.
To change the root filesystem, the system must be rebooted
after the filesystem is tuned.
.\" Take this out and a Unix Demon will dog your steps from now until
This program should work on active filesystems.
.\" Take this out and a Unix Daemon will dog your steps from now until
.\" the time_t's wrap around.
.Pp
You can tune a filesystem, but you can't tune a fish.

View File

@ -53,8 +53,9 @@ static const char rcsid[] =
#include <sys/disklabel.h>
#include <sys/stat.h>
#include <ufs/ffs/fs.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <err.h>
#include <fcntl.h>
@ -77,8 +78,8 @@ union {
int fi;
long dev_bsize = 1;
void bwrite(daddr_t, const char *, int);
int bread(daddr_t, char *, int);
void bwrite(ufs2_daddr_t, const char *, int);
int bread(ufs2_daddr_t, char *, int);
void getsb(struct fs *, const char *);
void putsb(struct fs *, const char *, int);
void usage(void);
@ -93,9 +94,9 @@ main(argc, argv)
const char *name;
struct stat st;
int Aflag = 0, active = 0;
int aflag = 0, dflag = 0, eflag = 0, fflag = 0, mflag = 0;
int aflag = 0, eflag = 0, fflag = 0, mflag = 0;
int nflag = 0, oflag = 0, pflag = 0, sflag = 0;
int avalue = 0, dvalue = 0, evalue = 0, fvalue = 0;
int avalue = 0, evalue = 0, fvalue = 0;
int mvalue = 0, ovalue = 0, svalue = 0;
char *nvalue = NULL;
struct fstab *fs;
@ -108,7 +109,7 @@ main(argc, argv)
if (argc < 3)
usage();
found_arg = 0; /* at least one arg is required */
while ((ch = getopt(argc, argv, "Aa:d:e:f:m:n:o:ps:")) != -1)
while ((ch = getopt(argc, argv, "Aa:e:f:m:n:o:ps:")) != -1)
switch (ch) {
case 'A':
found_arg = 1;
@ -122,12 +123,6 @@ main(argc, argv)
errx(10, "%s must be >= 1 (was %s)", name, optarg);
aflag = 1;
break;
case 'd':
found_arg = 1;
name = "rotational delay between contiguous blocks";
dvalue = atoi(optarg);
dflag = 1;
break;
case 'e':
found_arg = 1;
name = "maximum blocks per file in a cylinder group";
@ -237,17 +232,6 @@ main(argc, argv)
sblock.fs_maxcontig = avalue;
}
}
if (dflag) {
name = "rotational delay between contiguous blocks";
if (sblock.fs_rotdelay == dvalue) {
warnx("%s remains unchanged as %dms", name, dvalue);
}
else {
warnx("%s changes from %dms to %dms",
name, sblock.fs_rotdelay, dvalue);
sblock.fs_rotdelay = dvalue;
}
}
if (eflag) {
name = "maximum blocks per file in a cylinder group";
if (sblock.fs_maxbpg == evalue) {
@ -358,20 +342,36 @@ usage()
exit(2);
}
/*
* Possible superblock locations ordered from most to least likely.
*/
static int sblock_try[] = SBLOCKSEARCH;
static ufs2_daddr_t sblockloc;
void
getsb(fs, file)
struct fs *fs;
const char *file;
{
int i;
fi = open(file, O_RDONLY);
if (fi < 0)
err(3, "cannot open %s", file);
if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE))
err(4, "%s: bad super block", file);
if (fs->fs_magic != FS_MAGIC)
errx(5, "%s: bad magic number", file);
for (i = 0; sblock_try[i] != -1; i++) {
if (bread(sblock_try[i], (char *)fs, SBLOCKSIZE))
err(4, "%s: bad super block", file);
if ((fs->fs_magic == FS_UFS1_MAGIC ||
(fs->fs_magic == FS_UFS2_MAGIC &&
fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) &&
fs->fs_bsize <= MAXBSIZE &&
fs->fs_bsize >= sizeof(struct fs))
break;
}
if (sblock_try[i] == -1)
err(5, "Cannot find filesystem superblock");
dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
sblockloc = sblock_try[i] / dev_bsize;
}
void
@ -392,11 +392,11 @@ putsb(fs, file, all)
close(i);
if (fi < 0)
err(3, "cannot open %s", file);
bwrite((daddr_t)SBOFF / dev_bsize, (const char *)fs, SBSIZE);
bwrite(sblockloc, (const char *)fs, SBLOCKSIZE);
if (all)
for (i = 0; i < fs->fs_ncg; i++)
bwrite(fsbtodb(fs, cgsblock(fs, i)),
(const char *)fs, SBSIZE);
(const char *)fs, SBLOCKSIZE);
close(fi);
}
@ -407,8 +407,6 @@ printfs()
(sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled");
warnx("maximum contiguous block count: (-a) %d",
sblock.fs_maxcontig);
warnx("rotational delay between contiguous blocks: (-d) %d ms",
sblock.fs_rotdelay);
warnx("maximum blocks per file in a cylinder group: (-e) %d",
sblock.fs_maxbpg);
warnx("average file size: (-f) %d",
@ -429,7 +427,7 @@ printfs()
void
bwrite(blk, buf, size)
daddr_t blk;
ufs2_daddr_t blk;
const char *buf;
int size;
{
@ -442,7 +440,7 @@ bwrite(blk, buf, size)
int
bread(bno, buf, cnt)
daddr_t bno;
ufs2_daddr_t bno;
char *buf;
int cnt;
{

View File

@ -5,6 +5,7 @@
# SYS is normally set in Make.tags.inc
# SYS=/sys
SYS=/nsys
TAGDIR= i386

View File

@ -1,4 +1,13 @@
/*
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Marshall
* Kirk McKusick and Network Associates Laboratories, the Security
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
* research program
*
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
*
@ -17,31 +26,33 @@
* $FreeBSD$
*/
#include <ufs/ffs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
/*
* We use 4k `virtual' blocks for filesystem data, whatever the actual
* filesystem block size. FFS blocks are always a multiple of 4k.
*/
#define VBLKSIZE 4096
#define VBLKSHIFT 12
#define VBLKMASK (VBLKSIZE - 1)
#define DBPERVBLK (VBLKSIZE / DEV_BSIZE)
#define IPERVBLK (VBLKSIZE / sizeof(struct dinode))
#define INDIRPERVBLK (VBLKSIZE / sizeof(ufs_daddr_t))
#define INO_TO_VBA(fs, x) (fsbtodb(fs, ino_to_fsba(fs, x)) + \
(ino_to_fsbo(fs, x) / IPERVBLK) * DBPERVBLK)
#define INO_TO_VBO(fs, x) (ino_to_fsbo(fs, x) % IPERVBLK)
#define INDIRPERVBLK(fs) (NINDIR(fs) / ((fs)->fs_bsize / VBLKSIZE))
#define IPERVBLK(fs) (INOPB(fs) / ((fs)->fs_bsize / VBLKSIZE))
#define INO_TO_VBA(fs, ipervblk, x) \
(fsbtodb(fs, cgimin(fs, ino_to_cg(fs, x))) + \
(((x) % (fs)->fs_ipg) / (ipervblk) * DBPERVBLK))
#define INO_TO_VBO(ipervblk, x) ((x) % ipervblk)
#define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \
((off) / VBLKSIZE) * DBPERVBLK)
#define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK)
/* Buffers that must not span a 64k boundary. */
struct dmadat {
char blkbuf[VBLKSIZE]; /* filesystem blocks */
ufs_daddr_t indbuf[VBLKSIZE / sizeof(ufs_daddr_t)]; /* indir blocks */
char sbbuf[SBSIZE]; /* superblock */
char secbuf[DEV_BSIZE]; /* for MBR/disklabel */
char blkbuf[VBLKSIZE]; /* filesystem blocks */
char indbuf[VBLKSIZE]; /* indir blocks */
char sbbuf[SBLOCKSIZE]; /* superblock */
char secbuf[DEV_BSIZE]; /* for MBR/disklabel */
};
static struct dmadat *dmadat;
@ -61,16 +72,16 @@ fsfind(const char *name, ino_t * ino)
fs_off = 0;
while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0)
for (s = buf; s < buf + DEV_BSIZE;) {
d = (void *)s;
if (ls)
printf("%s ", d->d_name);
else if (!strcmp(name, d->d_name)) {
*ino = d->d_fileno;
return d->d_type;
for (s = buf; s < buf + DEV_BSIZE;) {
d = (void *)s;
if (ls)
printf("%s ", d->d_name);
else if (!strcmp(name, d->d_name)) {
*ino = d->d_fileno;
return d->d_type;
}
s += d->d_reclen;
}
s += d->d_reclen;
}
if (n != -1 && ls)
printf("\n");
return 0;
@ -95,8 +106,8 @@ lookup(const char *path)
if (!*path)
break;
for (s = path; *s && *s != '/'; s++);
if ((n = s - path) > MAXNAMLEN)
return 0;
if ((n = s - path) > MAXNAMLEN)
return 0;
ls = *path == '?' && n == 1 && !*s;
memcpy(name, path, n);
name[n] = 0;
@ -111,28 +122,31 @@ lookup(const char *path)
return dt == DT_REG ? ino : 0;
}
#define UFS1_ONLY
#ifdef UFS1_ONLY
static ssize_t
fsread(ino_t inode, void *buf, size_t nbyte)
{
static struct dinode din;
static struct ufs1_dinode dp1;
static ino_t inomap;
static daddr_t blkmap, indmap;
char *blkbuf;
ufs_daddr_t *indbuf;
caddr_t indbuf;
struct fs *fs;
char *s;
ufs_daddr_t lbn, addr;
daddr_t vbaddr;
size_t n, nb, off, vboff;
size_t n, nb, size, off, vboff;
long lbn;
ufs1_daddr_t addr, vbaddr;
static ufs1_daddr_t blkmap, indmap;
blkbuf = dmadat->blkbuf;
indbuf = dmadat->indbuf;
fs = (struct fs *)dmadat->sbbuf;
if (!dsk_meta) {
inomap = 0;
if (dskread(fs, SBOFF / DEV_BSIZE, SBSIZE / DEV_BSIZE))
if (dskread(fs, SBLOCK_UFS1 / DEV_BSIZE, SBLOCKSIZE / DEV_BSIZE))
return -1;
if (fs->fs_magic != FS_MAGIC) {
if (fs->fs_magic != FS_UFS1_MAGIC) {
printf("Not ufs\n");
return -1;
}
@ -141,35 +155,40 @@ fsread(ino_t inode, void *buf, size_t nbyte)
if (!inode)
return 0;
if (inomap != inode) {
if (dskread(blkbuf, INO_TO_VBA(fs, inode), DBPERVBLK))
n = IPERVBLK(fs);
if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK))
return -1;
din = ((struct dinode *)blkbuf)[INO_TO_VBO(fs, inode)];
dp1 = ((struct ufs1_dinode *)blkbuf)[INO_TO_VBO(n, inode)];
inomap = inode;
fs_off = 0;
blkmap = indmap = 0;
}
s = buf;
if (nbyte > (n = din.di_size - fs_off))
size = dp1.di_size;
n = size - fs_off;
if (nbyte > n)
nbyte = n;
nb = nbyte;
while (nb) {
lbn = lblkno(fs, fs_off);
off = blkoff(fs, fs_off);
if (lbn < NDADDR)
addr = din.di_db[lbn];
else {
vbaddr = FS_TO_VBA(fs, din.di_ib[0], sizeof(indbuf[0]) *
((lbn - NDADDR) % NINDIR(fs)));
if (lbn < NDADDR) {
addr = dp1.di_db[lbn];
} else {
n = INDIRPERVBLK(fs);
addr = dp1.di_ib[0];
vbaddr = fsbtodb(fs, addr) +
(lbn - NDADDR) / n * DBPERVBLK;
if (indmap != vbaddr) {
if (dskread(indbuf, vbaddr, DBPERVBLK))
return -1;
indmap = vbaddr;
}
addr = indbuf[(lbn - NDADDR) % INDIRPERVBLK];
addr = ((ufs1_daddr_t *)indbuf)[(lbn - NDADDR) % n];
}
vbaddr = FS_TO_VBA(fs, addr, off);
vboff = FS_TO_VBO(fs, addr, off);
n = dblksize(fs, &din, lbn) - (off & ~VBLKMASK);
vbaddr = fsbtodb(fs, addr) + (off >> VBLKSHIFT) * DBPERVBLK;
vboff = off & VBLKMASK;
n = sblksize(fs, size, lbn) - (off & ~VBLKMASK);
if (n > VBLKSIZE)
n = VBLKSIZE;
if (blkmap != vbaddr) {
@ -187,3 +206,117 @@ fsread(ino_t inode, void *buf, size_t nbyte)
}
return nbyte;
}
#else /* UFS1_AND_UFS2 */
/*
* Possible superblock locations ordered from most to least likely.
*/
static int sblock_try[] = SBLOCKSEARCH;
#define DIP(field) fs->fs_magic == FS_UFS1_MAGIC ? dp1.field : dp2.field
static ssize_t
fsread(ino_t inode, void *buf, size_t nbyte)
{
static struct ufs1_dinode dp1;
static struct ufs2_dinode dp2;
static ino_t inomap;
char *blkbuf;
caddr_t indbuf;
struct fs *fs;
char *s;
size_t n, nb, size, off, vboff;
ufs_lbn_t lbn;
ufs2_daddr_t addr, vbaddr;
static ufs2_daddr_t blkmap, indmap;
blkbuf = dmadat->blkbuf;
indbuf = dmadat->indbuf;
fs = (struct fs *)dmadat->sbbuf;
if (!dsk_meta) {
inomap = 0;
for (n = 0; sblock_try[n] != -1; n++) {
if (dskread(fs, sblock_try[n] / DEV_BSIZE,
SBLOCKSIZE / DEV_BSIZE))
return -1;
if ((fs->fs_magic == FS_UFS1_MAGIC ||
(fs->fs_magic == FS_UFS2_MAGIC &&
fs->fs_sblockloc == numfrags(fs, sblock_try[n]))) &&
fs->fs_bsize <= MAXBSIZE &&
fs->fs_bsize >= sizeof(struct fs))
break;
}
if (sblock_try[n] == -1) {
printf("Not ufs\n");
return -1;
}
dsk_meta++;
}
if (!inode)
return 0;
if (inomap != inode) {
n = IPERVBLK(fs);
if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK))
return -1;
n = INO_TO_VBO(n, inode);
if (fs->fs_magic == FS_UFS1_MAGIC)
dp1 = ((struct ufs1_dinode *)blkbuf)[n];
else
dp2 = ((struct ufs2_dinode *)blkbuf)[n];
inomap = inode;
fs_off = 0;
blkmap = indmap = 0;
}
s = buf;
size = DIP(di_size);
n = size - fs_off;
if (nbyte > n)
nbyte = n;
nb = nbyte;
while (nb) {
lbn = lblkno(fs, fs_off);
off = blkoff(fs, fs_off);
if (lbn < NDADDR) {
addr = DIP(di_db[lbn]);
} else if (lbn < NDADDR + NINDIR(fs)) {
n = INDIRPERVBLK(fs);
addr = DIP(di_ib[0]);
vbaddr = fsbtodb(fs, addr) +
(lbn - NDADDR) / n * DBPERVBLK;
if (indmap != vbaddr) {
if (dskread(indbuf, vbaddr, DBPERVBLK))
return -1;
indmap = vbaddr;
}
n = (lbn - NDADDR) % n;
if (fs->fs_magic == FS_UFS1_MAGIC)
addr = ((ufs1_daddr_t *)indbuf)[n];
else
addr = ((ufs2_daddr_t *)indbuf)[n];
} else {
printf("file too big\n");
return -1;
}
vbaddr = fsbtodb(fs, addr) + (off >> VBLKSHIFT) * DBPERVBLK;
vboff = off & VBLKMASK;
n = sblksize(fs, size, lbn) - (off & ~VBLKMASK);
if (n > VBLKSIZE)
n = VBLKSIZE;
if (blkmap != vbaddr) {
if (dskread(blkbuf, vbaddr, n >> DEV_BSHIFT))
return -1;
blkmap = vbaddr;
}
n -= vboff;
if (n > nb)
n = nb;
memcpy(s, blkbuf + vboff, n);
s += n;
fs_off += n;
nb -= n;
}
return nbyte;
}
#endif /* UFS1_AND_UFS2 */

View File

@ -1,6 +1,6 @@
# $FreeBSD$
SUBDIR= mbr boot0 btx boot2 cdboot kgzldr libi386 loader
SUBDIR= libi386 mbr boot0 btx boot2 cdboot kgzldr loader
# special boot programs, 'self-extracting boot2+loader'
SUBDIR+= pxeldr

View File

@ -75,7 +75,7 @@ boot2.bin: boot2.out
boot2.out: boot2.o sio.o
${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} \
${BTX}/lib/crt0.o boot2.o sio.o
${BTX}/lib/crt0.o boot2.o sio.o ../libi386/libi386.a
boot2.o: boot2.h

View File

@ -73,9 +73,10 @@
#define TYPE_AD 0
#define TYPE_WD 1
#define TYPE_WFD 2
#define TYPE_FD 3
#define TYPE_DA 4
#define TYPE_DA 2
#define TYPE_MAXHARD TYPE_DA
#define TYPE_WFD 3
#define TYPE_FD 4
extern uint32_t _end;
@ -97,8 +98,8 @@ static const unsigned char flags[NOPT] = {
RBX_VERBOSE
};
static const char *const dev_nm[] = {"ad", "wd", " ", "fd", "da"};
static const unsigned dev_maj[] = {30, 0, 1, 2, 4};
static const char *const dev_nm[NDEV] = {"ad", "wd", "da", " ", "fd"};
static const unsigned char dev_maj[NDEV] = {30, 0, 4, 1, 2};
static struct dsk {
unsigned drive;
@ -111,16 +112,14 @@ static struct dsk {
} dsk;
static char cmd[512];
static char kname[1024];
static uint32_t opts;
static uint32_t opts = RB_BOOTINFO;
static struct bootinfo bootinfo;
static uint8_t ioctrl = IO_KEYBOARD;
void exit(int);
static void load(const char *);
static int parse(char *);
static ino_t lookup(const char *);
static int xfsread(ino_t, void *, size_t);
static ssize_t fsread(ino_t, void *, size_t);
static int dskread(void *, unsigned, unsigned);
static int printf(const char *,...);
static int putchar(int);
@ -131,16 +130,17 @@ static int xputc(int);
static int xgetc(int);
static int getc(int);
#if 1
#define memcpy __builtin_memcpy
static inline void
readfile(const char *fname, void *buf, size_t size)
#else
static void memcpy(char *, const char *, int);
static void
memcpy(char *dst, const char *src, int len)
{
ino_t ino;
if ((ino = lookup(fname)))
fsread(ino, buf, size);
while (len--)
*dst++ = *src++;
}
#endif
static inline int
strcmp(const char *s1, const char *s2)
@ -151,15 +151,14 @@ strcmp(const char *s1, const char *s2)
#include "ufsread.c"
static inline int
getchar(void)
static int
xfsread(ino_t inode, void *buf, size_t nbyte)
{
int c;
c = xgetc(0);
if (c == '\r')
c = '\n';
return c;
if (fsread(inode, buf, nbyte) != nbyte) {
printf("Invalid %s\n", "format");
return -1;
}
return 0;
}
static inline void
@ -169,12 +168,13 @@ getstr(char *str, int size)
int c;
s = str;
do {
switch (c = getchar()) {
for (;;) {
switch (c = xgetc(0)) {
case 0:
break;
case '\b':
case '\177':
c = '\b';
case '\b':
if (s > str) {
s--;
putchar('\b');
@ -183,15 +183,16 @@ getstr(char *str, int size)
c = 0;
break;
case '\n':
case '\r':
*s = 0;
break;
return;
default:
if (s - str < size - 1)
*s++ = c;
}
if (c)
putchar(c);
} while (c != '\n');
}
}
static inline uint32_t
@ -220,6 +221,7 @@ int
main(void)
{
int autoboot, i;
ino_t ino;
dmadat = (void *)(roundup2(__base + _end, 0x10000) - __base);
v86.ctl = V86_FLAGS;
@ -238,7 +240,10 @@ main(void)
/* Process configuration file */
autoboot = 1;
readfile(PATH_CONFIG, cmd, sizeof(cmd));
if ((ino = lookup(PATH_CONFIG)))
fsread(ino, cmd, sizeof(cmd));
if (*cmd) {
printf("%s: %s", PATH_CONFIG, cmd);
if (parse(cmd))
@ -328,7 +333,7 @@ load(const char *fname)
return;
p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE);
bootinfo.bi_symtab = VTOP(p);
memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
memcpy(p, (char *)&hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
p += sizeof(hdr.ex.a_syms);
if (hdr.ex.a_syms) {
if (xfsread(ino, p, hdr.ex.a_syms))
@ -365,7 +370,7 @@ load(const char *fname)
if (xfsread(ino, &es, sizeof(es)))
return;
for (i = 0; i < 2; i++) {
memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size));
memcpy(p, (char *)&es[i].sh_size, sizeof(es[i].sh_size));
p += sizeof(es[i].sh_size);
fs_off = es[i].sh_offset;
if (xfsread(ino, p, es[i].sh_size))
@ -378,7 +383,7 @@ load(const char *fname)
bootinfo.bi_esymtab = VTOP(p);
bootinfo.bi_kernelname = VTOP(fname);
bootinfo.bi_bios_dev = dsk.drive;
__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
__exec((caddr_t)addr, opts & RBX_MASK,
MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part),
0, 0, 0, VTOP(&bootinfo));
}
@ -449,9 +454,8 @@ parse(char *arg)
arg += 2;
if (drv == -1)
drv = dsk.unit;
dsk.drive = (dsk.type == TYPE_WD ||
dsk.type == TYPE_AD ||
dsk.type == TYPE_DA ? DRV_HARD : 0) + drv;
dsk.drive = (dsk.type <= TYPE_MAXHARD
? DRV_HARD : 0) + drv;
dsk_meta = 0;
fsread(0, NULL, 0);
}
@ -466,16 +470,6 @@ parse(char *arg)
return 0;
}
static int
xfsread(ino_t inode, void *buf, size_t nbyte)
{
if (fsread(inode, buf, nbyte) != nbyte) {
printf("Invalid %s\n", "format");
return -1;
}
return 0;
}
static int
dskread(void *buf, unsigned lba, unsigned nblk)
{

View File

@ -75,7 +75,7 @@ boot2.bin: boot2.out
boot2.out: boot2.o sio.o
${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} \
${BTX}/lib/crt0.o boot2.o sio.o
${BTX}/lib/crt0.o boot2.o sio.o ../libi386/libi386.a
boot2.o: boot2.h

View File

@ -73,9 +73,10 @@
#define TYPE_AD 0
#define TYPE_WD 1
#define TYPE_WFD 2
#define TYPE_FD 3
#define TYPE_DA 4
#define TYPE_DA 2
#define TYPE_MAXHARD TYPE_DA
#define TYPE_WFD 3
#define TYPE_FD 4
extern uint32_t _end;
@ -97,8 +98,8 @@ static const unsigned char flags[NOPT] = {
RBX_VERBOSE
};
static const char *const dev_nm[] = {"ad", "wd", " ", "fd", "da"};
static const unsigned dev_maj[] = {30, 0, 1, 2, 4};
static const char *const dev_nm[NDEV] = {"ad", "wd", "da", " ", "fd"};
static const unsigned char dev_maj[NDEV] = {30, 0, 4, 1, 2};
static struct dsk {
unsigned drive;
@ -111,16 +112,14 @@ static struct dsk {
} dsk;
static char cmd[512];
static char kname[1024];
static uint32_t opts;
static uint32_t opts = RB_BOOTINFO;
static struct bootinfo bootinfo;
static uint8_t ioctrl = IO_KEYBOARD;
void exit(int);
static void load(const char *);
static int parse(char *);
static ino_t lookup(const char *);
static int xfsread(ino_t, void *, size_t);
static ssize_t fsread(ino_t, void *, size_t);
static int dskread(void *, unsigned, unsigned);
static int printf(const char *,...);
static int putchar(int);
@ -131,16 +130,17 @@ static int xputc(int);
static int xgetc(int);
static int getc(int);
#if 1
#define memcpy __builtin_memcpy
static inline void
readfile(const char *fname, void *buf, size_t size)
#else
static void memcpy(char *, const char *, int);
static void
memcpy(char *dst, const char *src, int len)
{
ino_t ino;
if ((ino = lookup(fname)))
fsread(ino, buf, size);
while (len--)
*dst++ = *src++;
}
#endif
static inline int
strcmp(const char *s1, const char *s2)
@ -151,15 +151,14 @@ strcmp(const char *s1, const char *s2)
#include "ufsread.c"
static inline int
getchar(void)
static int
xfsread(ino_t inode, void *buf, size_t nbyte)
{
int c;
c = xgetc(0);
if (c == '\r')
c = '\n';
return c;
if (fsread(inode, buf, nbyte) != nbyte) {
printf("Invalid %s\n", "format");
return -1;
}
return 0;
}
static inline void
@ -169,12 +168,13 @@ getstr(char *str, int size)
int c;
s = str;
do {
switch (c = getchar()) {
for (;;) {
switch (c = xgetc(0)) {
case 0:
break;
case '\b':
case '\177':
c = '\b';
case '\b':
if (s > str) {
s--;
putchar('\b');
@ -183,15 +183,16 @@ getstr(char *str, int size)
c = 0;
break;
case '\n':
case '\r':
*s = 0;
break;
return;
default:
if (s - str < size - 1)
*s++ = c;
}
if (c)
putchar(c);
} while (c != '\n');
}
}
static inline uint32_t
@ -220,6 +221,7 @@ int
main(void)
{
int autoboot, i;
ino_t ino;
dmadat = (void *)(roundup2(__base + _end, 0x10000) - __base);
v86.ctl = V86_FLAGS;
@ -238,7 +240,10 @@ main(void)
/* Process configuration file */
autoboot = 1;
readfile(PATH_CONFIG, cmd, sizeof(cmd));
if ((ino = lookup(PATH_CONFIG)))
fsread(ino, cmd, sizeof(cmd));
if (*cmd) {
printf("%s: %s", PATH_CONFIG, cmd);
if (parse(cmd))
@ -328,7 +333,7 @@ load(const char *fname)
return;
p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE);
bootinfo.bi_symtab = VTOP(p);
memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
memcpy(p, (char *)&hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
p += sizeof(hdr.ex.a_syms);
if (hdr.ex.a_syms) {
if (xfsread(ino, p, hdr.ex.a_syms))
@ -365,7 +370,7 @@ load(const char *fname)
if (xfsread(ino, &es, sizeof(es)))
return;
for (i = 0; i < 2; i++) {
memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size));
memcpy(p, (char *)&es[i].sh_size, sizeof(es[i].sh_size));
p += sizeof(es[i].sh_size);
fs_off = es[i].sh_offset;
if (xfsread(ino, p, es[i].sh_size))
@ -378,7 +383,7 @@ load(const char *fname)
bootinfo.bi_esymtab = VTOP(p);
bootinfo.bi_kernelname = VTOP(fname);
bootinfo.bi_bios_dev = dsk.drive;
__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
__exec((caddr_t)addr, opts & RBX_MASK,
MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part),
0, 0, 0, VTOP(&bootinfo));
}
@ -449,9 +454,8 @@ parse(char *arg)
arg += 2;
if (drv == -1)
drv = dsk.unit;
dsk.drive = (dsk.type == TYPE_WD ||
dsk.type == TYPE_AD ||
dsk.type == TYPE_DA ? DRV_HARD : 0) + drv;
dsk.drive = (dsk.type <= TYPE_MAXHARD
? DRV_HARD : 0) + drv;
dsk_meta = 0;
fsread(0, NULL, 0);
}
@ -466,16 +470,6 @@ parse(char *arg)
return 0;
}
static int
xfsread(ino_t inode, void *buf, size_t nbyte)
{
if (fsread(inode, buf, nbyte) != nbyte) {
printf("Invalid %s\n", "format");
return -1;
}
return 0;
}
static int
dskread(void *buf, unsigned lba, unsigned nblk)
{

View File

@ -4,9 +4,9 @@ LIB= i386
INTERNALLIB= true
SRCS= aout_freebsd.c biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \
biospci.c bootinfo.c comconsole.c devicename.c elf_freebsd.c gatea20.c \
i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \
time.c vidconsole.c
biospci.c bootinfo.c comconsole.c devicename.c divdi3.c elf_freebsd.c \
gatea20.c i386_copy.c i386_module.c moddi3.c nullconsole.c pxe.c \
pxetramp.s qdivrem.c time.c vidconsole.c
CFLAGS+= -ffreestanding
BOOT_COMCONSOLE_PORT?= 0x3f8
@ -39,9 +39,12 @@ beforedepend ${OBJS}: machine
machine:
ln -sf ${.CURDIR}/../../../i386/include machine
ln -sf ${.CURDIR}/../../../../lib/libc/quad/divdi3.c divdi3.c
ln -sf ${.CURDIR}/../../../../lib/libc/quad/moddi3.c moddi3.c
ln -sf ${.CURDIR}/../../../../lib/libc/quad/qdivrem.c qdivrem.c
.endif
CLEANFILES+= machine
CLEANFILES+= machine divdi3.c moddi3.c qdivrem.c
.include <bsd.lib.mk>

View File

@ -119,7 +119,7 @@ FILES+= loader.rc
${BASE}.sym: ${OBJS} ${LIBI386} ${LIBSTAND} ${LIBFICL} vers.o
${CC} ${LDFLAGS} -o ${.TARGET} ${BTXCRT} ${OBJS} vers.o \
${LIBFICL} ${LIBI386} ${LIBSTAND}
${LIBFICL} ${LIBI386} ${LIBSTAND} ${LIBI386}
# If it's not there, don't consider it a target
.if exists(${.CURDIR}/../../../i386/include)

View File

@ -5,6 +5,7 @@
# SYS is normally set in Make.tags.inc
# SYS=/sys
SYS=/nsys
TAGDIR= i386

View File

@ -41,6 +41,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/stdint.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
@ -398,11 +399,11 @@ diskerr(bp, what, blkdone, lp)
bp->bio_cmd == BIO_READ ? "read" : "writ");
sn = bp->bio_blkno;
if (bp->bio_bcount <= DEV_BSIZE)
printf("%ld", (long)sn);
printf("%lld", (intmax_t)sn);
else {
if (blkdone >= 0) {
sn += blkdone;
printf("%ld of ", (long)sn);
printf("%lld of ", (intmax_t)sn);
}
printf("%ld-%ld", (long)bp->bio_blkno,
(long)(bp->bio_blkno + (bp->bio_bcount - 1) / DEV_BSIZE));
@ -416,9 +417,9 @@ diskerr(bp, what, blkdone, lp)
* independent of slices, labels and bad sector remapping,
* but some drivers don't set bp->b_pblkno.
*/
printf(" (%s bn %ld; cn %ld", sname, (long)sn,
(long)(sn / lp->d_secpercyl));
sn %= (long)lp->d_secpercyl;
printf(" (%s bn %lld; cn %lld", sname, (intmax_t)sn,
(intmax_t)(sn / lp->d_secpercyl));
sn %= lp->d_secpercyl;
printf(" tn %ld sn %ld)", (long)(sn / lp->d_nsectors),
(long)(sn % lp->d_nsectors));
}

View File

@ -152,15 +152,15 @@ dscheck(bp, ssp)
struct bio *bp;
struct diskslices *ssp;
{
daddr_t blkno;
u_long endsecno;
daddr_t labelsect;
daddr_t blkno;
daddr_t endsecno;
daddr_t labelsect;
struct disklabel *lp;
char *msg;
long nsec;
struct partition *pp;
daddr_t secno;
daddr_t slicerel_secno;
daddr_t secno;
daddr_t slicerel_secno;
struct diskslice *sp;
blkno = bp->bio_blkno;

View File

@ -29,6 +29,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/stdint.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/eventhandler.h>
@ -2368,7 +2369,7 @@ getblk(struct vnode * vp, daddr_t blkno, int size, int slpflag, int slptimeo)
else
bsize = size;
offset = (off_t)blkno * bsize;
offset = blkno * bsize;
vmio = (VOP_GETVOBJECT(vp, NULL) == 0) && (vp->v_flag & VOBJBUF);
maxsize = vmio ? size + (offset & PAGE_MASK) : size;
maxsize = imax(maxsize, bsize);
@ -2946,13 +2947,13 @@ bufdone(struct buf *bp)
(int) m->pindex, (int)(foff >> 32),
(int) foff & 0xffffffff, resid, i);
if (!vn_isdisk(vp, NULL))
printf(" iosize: %ld, lblkno: %d, flags: 0x%lx, npages: %d\n",
printf(" iosize: %ld, lblkno: %lld, flags: 0x%lx, npages: %d\n",
bp->b_vp->v_mount->mnt_stat.f_iosize,
(int) bp->b_lblkno,
(intmax_t) bp->b_lblkno,
bp->b_flags, bp->b_npages);
else
printf(" VDEV, lblkno: %d, flags: 0x%lx, npages: %d\n",
(int) bp->b_lblkno,
printf(" VDEV, lblkno: %lld, flags: 0x%lx, npages: %d\n",
(intmax_t) bp->b_lblkno,
bp->b_flags, bp->b_npages);
printf(" valid: 0x%x, dirty: 0x%x, wired: %d\n",
m->valid, m->dirty, m->wire_count);
@ -3336,8 +3337,8 @@ vm_hold_free_pages(struct buf * bp, vm_offset_t from, vm_offset_t to)
if (p->busy) {
printf(
"vm_hold_free_pages: blkno: %lld, lblkno: %lld\n",
(long long)bp->b_blkno,
(long long)bp->b_lblkno);
(intmax_t)bp->b_blkno,
(intmax_t)bp->b_lblkno);
}
bp->b_pages[index] = NULL;
pmap_qremove(pg, 1);
@ -3371,7 +3372,7 @@ DB_SHOW_COMMAND(buffer, db_show_buffer)
"b_dev = (%d,%d), b_data = %p, b_blkno = %lld, b_pblkno = %lld\n",
bp->b_error, bp->b_bufsize, bp->b_bcount, bp->b_resid,
major(bp->b_dev), minor(bp->b_dev), bp->b_data,
(long long)bp->b_blkno, (long long)bp->b_pblkno);
(intmax_t)bp->b_blkno, (intmax_t)bp->b_pblkno);
if (bp->b_npages) {
int i;
db_printf("b_npages = %d, pages(OBJ, IDX, PA): ", bp->b_npages);

View File

@ -40,6 +40,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/stdint.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/bio.h>
@ -280,15 +281,13 @@ cluster_read(vp, filesize, lblkno, size, cred, totread, seqcount, bpp)
#if defined(CLUSTERDEBUG)
if (rcluster) {
if (bp)
printf("A+(%ld,%ld,%ld,%d) ",
(long)rbp->b_lblkno, rbp->b_bcount,
(long)(rbp->b_lblkno - origblkno),
seqcount);
printf("A+");
else
printf("A(%ld,%ld,%ld,%d) ",
(long)rbp->b_lblkno, rbp->b_bcount,
(long)(rbp->b_lblkno - origblkno),
seqcount);
printf("A");
printf("(%lld,%ld,%lld,%d) ",
(intmax_t)rbp->b_lblkno, rbp->b_bcount,
(intmax_t)(rbp->b_lblkno - origblkno),
seqcount);
}
#endif

View File

@ -2631,8 +2631,8 @@ cvtnstat(sb, nsb)
nsb->st_blksize = sb->st_blksize;
nsb->st_flags = sb->st_flags;
nsb->st_gen = sb->st_gen;
nsb->st_qspare[0] = sb->st_qspare[0];
nsb->st_qspare[1] = sb->st_qspare[1];
nsb->st_createtimespec = sb->st_createtimespec;
nsb->st_qspare = sb->st_qspare;
}
#ifndef _SYS_SYSPROTO_H_

View File

@ -2631,8 +2631,8 @@ cvtnstat(sb, nsb)
nsb->st_blksize = sb->st_blksize;
nsb->st_flags = sb->st_flags;
nsb->st_gen = sb->st_gen;
nsb->st_qspare[0] = sb->st_qspare[0];
nsb->st_qspare[1] = sb->st_qspare[1];
nsb->st_createtimespec = sb->st_createtimespec;
nsb->st_qspare = sb->st_qspare;
}
#ifndef _SYS_SYSPROTO_H_

View File

@ -563,8 +563,7 @@ vn_stat(vp, sb, td)
* Zero the spare stat fields
*/
sb->st_lspare = 0;
sb->st_qspare[0] = 0;
sb->st_qspare[1] = 0;
sb->st_qspare = 0;
/*
* Copy from vattr table
@ -616,6 +615,7 @@ vn_stat(vp, sb, td)
sb->st_atimespec = vap->va_atime;
sb->st_mtimespec = vap->va_mtime;
sb->st_ctimespec = vap->va_ctime;
sb->st_createtimespec = vap->va_createtime;
/*
* According to www.opengroup.org, the meaning of st_blksize is

View File

@ -109,8 +109,9 @@ struct stat {
u_int32_t st_blksize; /* optimal blocksize for I/O */
fflags_t st_flags; /* user defined flags for file */
u_int32_t st_gen; /* file generation number */
struct timespec st_createtimespec; /* time of file creation */
int32_t st_lspare;
int64_t st_qspare[2];
int64_t st_qspare;
};
#ifndef _POSIX_SOURCE
@ -139,7 +140,8 @@ struct nstat {
u_int32_t st_blksize; /* optimal blocksize for I/O */
fflags_t st_flags; /* user defined flags for file */
u_int32_t st_gen; /* file generation number */
int64_t st_qspare[2];
struct timespec st_createtimespec; /* time of file creation */
int64_t st_qspare;
};
#endif

View File

@ -148,8 +148,6 @@ typedef _BSD_SEGSZ_T_ segsz_t; /* segment size (in pages) */
#endif
typedef int32_t swblk_t; /* swap offset */
typedef int32_t ufs_daddr_t;
typedef int32_t ufs_time_t;
#ifdef _BSD_UID_T_
typedef _BSD_UID_T_ uid_t; /* user id */

View File

@ -203,6 +203,7 @@ struct vattr {
struct timespec va_atime; /* time of last access */
struct timespec va_mtime; /* time of last modification */
struct timespec va_ctime; /* time file changed */
struct timespec va_createtime; /* time file created */
u_long va_gen; /* generation number of file */
u_long va_flags; /* flags defined for file */
udev_t va_rdev; /* device the special file represents */

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,16 @@
/*
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Marshall
* Kirk McKusick and Network Associates Laboratories, the Security
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
* research program
*
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
@ -53,60 +65,60 @@
* Balloc defines the structure of filesystem storage
* by allocating the physical blocks on a device given
* the inode and the logical block number in a file.
* This is the allocation strategy for UFS1. Below is
* the allocation strategy for UFS2.
*/
int
ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
struct ucred *a_cred, int a_flags, struct buf **a_bpp)
ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
struct ucred *cred, int flags, struct buf **bpp)
{
struct inode *ip;
ufs_daddr_t lbn;
int size;
struct ucred *cred;
int flags;
ufs_lbn_t lbn, lastlbn;
struct fs *fs;
ufs_daddr_t nb;
ufs1_daddr_t nb;
struct buf *bp, *nbp;
struct vnode *vp;
struct indir indirs[NIADDR + 2];
ufs_daddr_t newb, *bap, pref;
int deallocated, osize, nsize, num, i, error;
ufs_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
ufs2_daddr_t newb;
ufs1_daddr_t *bap, pref;
ufs1_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
int unwindidx = -1;
struct thread *td = curthread; /* XXX */
vp = a_vp;
ip = VTOI(vp);
fs = ip->i_fs;
lbn = lblkno(fs, a_startoffset);
size = blkoff(fs, a_startoffset) + a_size;
lbn = lblkno(fs, startoffset);
size = blkoff(fs, startoffset) + size;
if (size > fs->fs_bsize)
panic("ffs_balloc: blk too big");
*a_bpp = NULL;
panic("ffs_balloc_ufs1: blk too big");
*bpp = NULL;
if (lbn < 0)
return (EFBIG);
cred = a_cred;
flags = a_flags;
/*
* If the next write will extend the file into a new block,
* and the file is currently composed of a fragment
* this fragment has to be extended to be a full block.
*/
nb = lblkno(fs, ip->i_size);
if (nb < NDADDR && nb < lbn) {
lastlbn = lblkno(fs, ip->i_size);
if (lastlbn < NDADDR && lastlbn < lbn) {
nb = lastlbn;
osize = blksize(fs, ip, nb);
if (osize < fs->fs_bsize && osize > 0) {
error = ffs_realloccg(ip, nb,
ffs_blkpref(ip, nb, (int)nb, &ip->i_db[0]),
ffs_blkpref_ufs1(ip, lastlbn, (int)nb,
&ip->i_din1->di_db[0]),
osize, (int)fs->fs_bsize, cred, &bp);
if (error)
return (error);
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, nb,
dbtofsb(fs, bp->b_blkno), ip->i_db[nb],
dbtofsb(fs, bp->b_blkno),
ip->i_din1->di_db[nb],
fs->fs_bsize, osize, bp);
ip->i_size = smalllblktosize(fs, nb + 1);
ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
ip->i_din1->di_size = ip->i_size;
ip->i_din1->di_db[nb] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (flags & B_SYNC)
bwrite(bp);
@ -119,8 +131,8 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
*/
if (lbn < NDADDR) {
if (flags & B_METAONLY)
panic("ffs_balloc: B_METAONLY for direct block");
nb = ip->i_db[lbn];
panic("ffs_balloc_ufs1: B_METAONLY for direct block");
nb = ip->i_din1->di_db[lbn];
if (nb != 0 && ip->i_size >= smalllblktosize(fs, lbn + 1)) {
error = bread(vp, lbn, fs->fs_bsize, NOCRED, &bp);
if (error) {
@ -128,7 +140,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
return (error);
}
bp->b_blkno = fsbtodb(fs, nb);
*a_bpp = bp;
*bpp = bp;
return (0);
}
if (nb != 0) {
@ -146,8 +158,9 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
bp->b_blkno = fsbtodb(fs, nb);
} else {
error = ffs_realloccg(ip, lbn,
ffs_blkpref(ip, lbn, (int)lbn,
&ip->i_db[0]), osize, nsize, cred, &bp);
ffs_blkpref_ufs1(ip, lbn, (int)lbn,
&ip->i_din1->di_db[0]),
osize, nsize, cred, &bp);
if (error)
return (error);
if (DOINGSOFTDEP(vp))
@ -161,7 +174,8 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
else
nsize = fs->fs_bsize;
error = ffs_alloc(ip, lbn,
ffs_blkpref(ip, lbn, (int)lbn, &ip->i_db[0]),
ffs_blkpref_ufs1(ip, lbn, (int)lbn,
&ip->i_din1->di_db[0]),
nsize, cred, &newb);
if (error)
return (error);
@ -173,9 +187,9 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
softdep_setup_allocdirect(ip, lbn, newb, 0,
nsize, 0, bp);
}
ip->i_db[lbn] = dbtofsb(fs, bp->b_blkno);
ip->i_din1->di_db[lbn] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
*a_bpp = bp;
*bpp = bp;
return (0);
}
/*
@ -186,17 +200,17 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
return(error);
#ifdef DIAGNOSTIC
if (num < 1)
panic ("ffs_balloc: ufs_bmaparray returned indirect block");
panic ("ffs_balloc_ufs1: ufs_getlbns returned indirect block");
#endif
/*
* Fetch the first indirect block allocating if necessary.
*/
--num;
nb = ip->i_ib[indirs[0].in_off];
nb = ip->i_din1->di_ib[indirs[0].in_off];
allocib = NULL;
allocblk = allociblk;
if (nb == 0) {
pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
pref = ffs_blkpref_ufs1(ip, lbn, 0, (ufs1_daddr_t *)0);
if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
cred, &newb)) != 0)
return (error);
@ -219,7 +233,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
else if ((error = bwrite(bp)) != 0)
goto fail;
}
allocib = &ip->i_ib[indirs[0].in_off];
allocib = &ip->i_din1->di_ib[indirs[0].in_off];
*allocib = nb;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
@ -233,7 +247,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
brelse(bp);
goto fail;
}
bap = (ufs_daddr_t *)bp->b_data;
bap = (ufs1_daddr_t *)bp->b_data;
nb = bap[indirs[i].in_off];
if (i == num)
break;
@ -243,7 +257,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
continue;
}
if (pref == 0)
pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
pref = ffs_blkpref_ufs1(ip, lbn, 0, (ufs1_daddr_t *)0);
if ((error =
ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) != 0) {
brelse(bp);
@ -287,14 +301,14 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
* If asked only for the indirect block, then return it.
*/
if (flags & B_METAONLY) {
*a_bpp = bp;
*bpp = bp;
return (0);
}
/*
* Get the data block, allocating if necessary.
*/
if (nb == 0) {
pref = ffs_blkpref(ip, lbn, indirs[i].in_off, &bap[0]);
pref = ffs_blkpref_ufs1(ip, lbn, indirs[i].in_off, &bap[0]);
error = ffs_alloc(ip,
lbn, pref, (int)fs->fs_bsize, cred, &newb);
if (error) {
@ -322,7 +336,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
}
*a_bpp = nbp;
*bpp = nbp;
return (0);
}
brelse(bp);
@ -336,7 +350,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
}
*a_bpp = nbp;
*bpp = nbp;
return (0);
fail:
/*
@ -366,7 +380,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
panic("Could not unwind indirect block, error %d", r);
brelse(bp);
} else {
bap = (ufs_daddr_t *)bp->b_data;
bap = (ufs1_daddr_t *)bp->b_data;
bap[indirs[unwindidx].in_off] = 0;
if (flags & B_SYNC) {
bwrite(bp);
@ -382,9 +396,351 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
/*
* Restore user's disk quota because allocation failed.
*/
(void) chkdq(ip, (long)-btodb(deallocated), cred, FORCE);
(void) chkdq(ip, -btodb(deallocated), cred, FORCE);
#endif
ip->i_blocks -= btodb(deallocated);
ip->i_din1->di_blocks -= btodb(deallocated);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
(void) VOP_FSYNC(vp, cred, MNT_WAIT, td);
return (error);
}
/*
* Balloc defines the structure of file system storage
* by allocating the physical blocks on a device given
* the inode and the logical block number in a file.
* This is the allocation strategy for UFS2. Above is
* the allocation strategy for UFS1.
*/
int
ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
struct ucred *cred, int flags, struct buf **bpp)
{
struct inode *ip;
ufs_lbn_t lbn, lastlbn;
struct fs *fs;
struct buf *bp, *nbp;
struct indir indirs[NIADDR + 2];
ufs2_daddr_t nb, newb, *bap, pref;
ufs2_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
int deallocated, osize, nsize, num, i, error;
int unwindidx = -1;
struct thread *td = curthread; /* XXX */
ip = VTOI(vp);
fs = ip->i_fs;
lbn = lblkno(fs, startoffset);
size = blkoff(fs, startoffset) + size;
if (size > fs->fs_bsize)
panic("ffs_balloc_ufs2: blk too big");
*bpp = NULL;
if (lbn < 0)
return (EFBIG);
/*
* If the next write will extend the file into a new block,
* and the file is currently composed of a fragment
* this fragment has to be extended to be a full block.
*/
lastlbn = lblkno(fs, ip->i_size);
if (lastlbn < NDADDR && lastlbn < lbn) {
nb = lastlbn;
osize = blksize(fs, ip, nb);
if (osize < fs->fs_bsize && osize > 0) {
error = ffs_realloccg(ip, nb,
ffs_blkpref_ufs2(ip, lastlbn, (int)nb,
&ip->i_din2->di_db[0]),
osize, (int)fs->fs_bsize, cred, &bp);
if (error)
return (error);
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, nb,
dbtofsb(fs, bp->b_blkno),
ip->i_din2->di_db[nb],
fs->fs_bsize, osize, bp);
ip->i_size = smalllblktosize(fs, nb + 1);
ip->i_din2->di_size = ip->i_size;
ip->i_din2->di_db[nb] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (flags & B_SYNC)
bwrite(bp);
else
bawrite(bp);
}
}
/*
* The first NDADDR blocks are direct blocks
*/
if (lbn < NDADDR) {
if (flags & B_METAONLY)
panic("ffs_balloc_ufs2: B_METAONLY for direct block");
nb = ip->i_din2->di_db[lbn];
if (nb != 0 && ip->i_size >= smalllblktosize(fs, lbn + 1)) {
error = bread(vp, lbn, fs->fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
bp->b_blkno = fsbtodb(fs, nb);
*bpp = bp;
return (0);
}
if (nb != 0) {
/*
* Consider need to reallocate a fragment.
*/
osize = fragroundup(fs, blkoff(fs, ip->i_size));
nsize = fragroundup(fs, size);
if (nsize <= osize) {
error = bread(vp, lbn, osize, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
bp->b_blkno = fsbtodb(fs, nb);
} else {
error = ffs_realloccg(ip, lbn,
ffs_blkpref_ufs2(ip, lbn, (int)lbn,
&ip->i_din2->di_db[0]),
osize, nsize, cred, &bp);
if (error)
return (error);
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, lbn,
dbtofsb(fs, bp->b_blkno), nb,
nsize, osize, bp);
}
} else {
if (ip->i_size < smalllblktosize(fs, lbn + 1))
nsize = fragroundup(fs, size);
else
nsize = fs->fs_bsize;
error = ffs_alloc(ip, lbn,
ffs_blkpref_ufs2(ip, lbn, (int)lbn,
&ip->i_din2->di_db[0]),
nsize, cred, &newb);
if (error)
return (error);
bp = getblk(vp, lbn, nsize, 0, 0);
bp->b_blkno = fsbtodb(fs, newb);
if (flags & B_CLRBUF)
vfs_bio_clrbuf(bp);
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, lbn, newb, 0,
nsize, 0, bp);
}
ip->i_din2->di_db[lbn] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
*bpp = bp;
return (0);
}
/*
* Determine the number of levels of indirection.
*/
pref = 0;
if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0)
return(error);
#ifdef DIAGNOSTIC
if (num < 1)
panic ("ffs_balloc_ufs2: ufs_getlbns returned indirect block");
#endif
/*
* Fetch the first indirect block allocating if necessary.
*/
--num;
nb = ip->i_din2->di_ib[indirs[0].in_off];
allocib = NULL;
allocblk = allociblk;
if (nb == 0) {
pref = ffs_blkpref_ufs2(ip, lbn, 0, (ufs2_daddr_t *)0);
if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
cred, &newb)) != 0)
return (error);
nb = newb;
*allocblk++ = nb;
bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
bp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(bp);
if (DOINGSOFTDEP(vp)) {
softdep_setup_allocdirect(ip, NDADDR + indirs[0].in_off,
newb, 0, fs->fs_bsize, 0, bp);
bdwrite(bp);
} else {
/*
* Write synchronously so that indirect blocks
* never point at garbage.
*/
if (DOINGASYNC(vp))
bdwrite(bp);
else if ((error = bwrite(bp)) != 0)
goto fail;
}
allocib = &ip->i_din2->di_ib[indirs[0].in_off];
*allocib = nb;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
/*
* Fetch through the indirect blocks, allocating as necessary.
*/
for (i = 1;;) {
error = bread(vp,
indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
goto fail;
}
bap = (ufs2_daddr_t *)bp->b_data;
nb = bap[indirs[i].in_off];
if (i == num)
break;
i += 1;
if (nb != 0) {
bqrelse(bp);
continue;
}
if (pref == 0)
pref = ffs_blkpref_ufs2(ip, lbn, 0, (ufs2_daddr_t *)0);
if ((error =
ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) != 0) {
brelse(bp);
goto fail;
}
nb = newb;
*allocblk++ = nb;
nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(nbp);
if (DOINGSOFTDEP(vp)) {
softdep_setup_allocindir_meta(nbp, ip, bp,
indirs[i - 1].in_off, nb);
bdwrite(nbp);
} else {
/*
* Write synchronously so that indirect blocks
* never point at garbage.
*/
if ((error = bwrite(nbp)) != 0) {
brelse(bp);
goto fail;
}
}
bap[indirs[i - 1].in_off] = nb;
if (allocib == NULL && unwindidx < 0)
unwindidx = i - 1;
/*
* If required, write synchronously, otherwise use
* delayed write.
*/
if (flags & B_SYNC) {
bwrite(bp);
} else {
if (bp->b_bufsize == fs->fs_bsize)
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
}
}
/*
* If asked only for the indirect block, then return it.
*/
if (flags & B_METAONLY) {
*bpp = bp;
return (0);
}
/*
* Get the data block, allocating if necessary.
*/
if (nb == 0) {
pref = ffs_blkpref_ufs2(ip, lbn, indirs[i].in_off, &bap[0]);
error = ffs_alloc(ip,
lbn, pref, (int)fs->fs_bsize, cred, &newb);
if (error) {
brelse(bp);
goto fail;
}
nb = newb;
*allocblk++ = nb;
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
if (flags & B_CLRBUF)
vfs_bio_clrbuf(nbp);
if (DOINGSOFTDEP(vp))
softdep_setup_allocindir_page(ip, lbn, bp,
indirs[i].in_off, nb, 0, nbp);
bap[indirs[i].in_off] = nb;
/*
* If required, write synchronously, otherwise use
* delayed write.
*/
if (flags & B_SYNC) {
bwrite(bp);
} else {
if (bp->b_bufsize == fs->fs_bsize)
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
}
*bpp = nbp;
return (0);
}
brelse(bp);
if (flags & B_CLRBUF) {
error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
if (error) {
brelse(nbp);
goto fail;
}
} else {
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
}
*bpp = nbp;
return (0);
fail:
/*
* If we have failed part way through block allocation, we
* have to deallocate any indirect blocks that we have allocated.
* We have to fsync the file before we start to get rid of all
* of its dependencies so that we do not leave them dangling.
* We have to sync it at the end so that the soft updates code
* does not find any untracked changes. Although this is really
* slow, running out of disk space is not expected to be a common
* occurence. The error return from fsync is ignored as we already
* have an error to return to the user.
*/
(void) VOP_FSYNC(vp, cred, MNT_WAIT, td);
for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
ffs_blkfree(fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number);
deallocated += fs->fs_bsize;
}
if (allocib != NULL) {
*allocib = 0;
} else if (unwindidx >= 0) {
int r;
r = bread(vp, indirs[unwindidx].in_lbn,
(int)fs->fs_bsize, NOCRED, &bp);
if (r) {
panic("Could not unwind indirect block, error %d", r);
brelse(bp);
} else {
bap = (ufs2_daddr_t *)bp->b_data;
bap[indirs[unwindidx].in_off] = 0;
if (flags & B_SYNC) {
bwrite(bp);
} else {
if (bp->b_bufsize == fs->fs_bsize)
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
}
}
}
if (deallocated) {
#ifdef QUOTA
/*
* Restore user's disk quota because allocation failed.
*/
(void) chkdq(ip, -btodb(deallocated), cred, FORCE);
#endif
ip->i_din2->di_blocks -= btodb(deallocated);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
(void) VOP_FSYNC(vp, cred, MNT_WAIT, td);

View File

@ -49,26 +49,30 @@ struct sockaddr;
struct statfs;
struct ucred;
struct vnode;
struct vop_balloc_args;
struct vop_fsync_args;
struct vop_reallocblks_args;
struct vop_copyonwrite_args;
int ffs_alloc(struct inode *,
ufs_daddr_t, ufs_daddr_t, int, struct ucred *, ufs_daddr_t *);
int ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
ufs2_daddr_t, ufs2_daddr_t, int, struct ucred *, ufs2_daddr_t *);
int ffs_balloc_ufs1(struct vnode *a_vp, off_t a_startoffset, int a_size,
struct ucred *a_cred, int a_flags, struct buf **a_bpp);
int ffs_balloc_ufs2(struct vnode *a_vp, off_t a_startoffset, int a_size,
struct ucred *a_cred, int a_flags, struct buf **a_bpp);
int ffs_blkatoff(struct vnode *, off_t, char **, struct buf **);
void ffs_blkfree(struct fs *, struct vnode *, ufs_daddr_t, long, ino_t);
ufs_daddr_t ffs_blkpref(struct inode *, ufs_daddr_t, int, ufs_daddr_t *);
void ffs_clrblock(struct fs *, u_char *, ufs_daddr_t);
void ffs_clusteracct (struct fs *, struct cg *, ufs_daddr_t, int);
void ffs_blkfree(struct fs *, struct vnode *, ufs2_daddr_t, long, ino_t);
ufs2_daddr_t ffs_blkpref_ufs1(struct inode *, ufs_lbn_t, int, ufs1_daddr_t *);
ufs2_daddr_t ffs_blkpref_ufs2(struct inode *, ufs_lbn_t, int, ufs2_daddr_t *);
void ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t);
void ffs_clusteracct (struct fs *, struct cg *, ufs1_daddr_t, int);
int ffs_fhtovp(struct mount *, struct fid *, struct vnode **);
int ffs_flushfiles(struct mount *, int, struct thread *);
void ffs_fragacct(struct fs *, int, int32_t [], int);
int ffs_freefile(struct fs *, struct vnode *, ino_t, int );
int ffs_isblock(struct fs *, u_char *, ufs_daddr_t);
int ffs_isfreeblock(struct fs *, unsigned char *, ufs_daddr_t);
int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
int ffs_isfreeblock(struct fs *, unsigned char *, ufs1_daddr_t);
void ffs_load_inode(struct buf *, struct inode *, struct malloc_type *,
struct fs *, ino_t);
int ffs_mountfs(struct vnode *, struct mount *, struct thread *,
struct malloc_type *);
int ffs_mountroot(void);
@ -76,9 +80,9 @@ int ffs_mount(struct mount *, char *, caddr_t, struct nameidata *,
struct thread *);
int ffs_reallocblks(struct vop_reallocblks_args *);
int ffs_realloccg(struct inode *,
ufs_daddr_t, ufs_daddr_t, int, int, struct ucred *, struct buf **);
void ffs_setblock(struct fs *, u_char *, ufs_daddr_t);
int ffs_snapblkfree(struct fs *, struct vnode *, ufs_daddr_t, long, ino_t);
ufs2_daddr_t, ufs2_daddr_t, int, int, struct ucred *, struct buf **);
void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
int ffs_snapblkfree(struct fs *, struct vnode *, ufs2_daddr_t, long, ino_t);
void ffs_snapremove(struct vnode *vp);
int ffs_snapshot(struct mount *mp, char *snapfile);
void ffs_snapshot_mount(struct mount *mp);
@ -112,13 +116,13 @@ void softdep_freefile(struct vnode *, ino_t, int);
int softdep_request_cleanup(struct fs *, struct vnode *);
void softdep_setup_freeblocks(struct inode *, off_t);
void softdep_setup_inomapdep(struct buf *, struct inode *, ino_t);
void softdep_setup_blkmapdep(struct buf *, struct fs *, ufs_daddr_t);
void softdep_setup_allocdirect(struct inode *, ufs_lbn_t, ufs_daddr_t,
ufs_daddr_t, long, long, struct buf *);
void softdep_setup_blkmapdep(struct buf *, struct fs *, ufs2_daddr_t);
void softdep_setup_allocdirect(struct inode *, ufs_lbn_t, ufs2_daddr_t,
ufs2_daddr_t, long, long, struct buf *);
void softdep_setup_allocindir_meta(struct buf *, struct inode *,
struct buf *, int, ufs_daddr_t);
struct buf *, int, ufs2_daddr_t);
void softdep_setup_allocindir_page(struct inode *, ufs_lbn_t,
struct buf *, int, ufs_daddr_t, ufs_daddr_t, struct buf *);
struct buf *, int, ufs2_daddr_t, ufs2_daddr_t, struct buf *);
void softdep_fsync_mountdev(struct vnode *);
int softdep_sync_metadata(struct vop_fsync_args *);
/* XXX incorrectly moved to mount.h - should be indirect function */

View File

@ -60,8 +60,8 @@
#include <ufs/ffs/fs.h>
#include <ufs/ffs/ffs_extern.h>
static int ffs_indirtrunc(struct inode *, ufs_daddr_t, ufs_daddr_t,
ufs_daddr_t, int, long *);
static int ffs_indirtrunc(struct inode *, ufs2_daddr_t, ufs2_daddr_t,
ufs2_daddr_t, int, ufs2_daddr_t *);
/*
* Update the access, modified, and inode change times as specified by the
@ -94,9 +94,10 @@ ffs_update(vp, waitfor)
* Ensure that uid and gid are correct. This is a temporary
* fix until fsck has been changed to do the update.
*/
if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
ip->i_din.di_ouid = ip->i_uid; /* XXX */
ip->i_din.di_ogid = ip->i_gid; /* XXX */
if (fs->fs_magic == FS_UFS1_MAGIC && /* XXX */
fs->fs_old_inodefmt < FS_44INODEFMT) { /* XXX */
ip->i_din1->di_ouid = ip->i_uid; /* XXX */
ip->i_din1->di_ogid = ip->i_gid; /* XXX */
} /* XXX */
error = bread(ip->i_devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
(int)fs->fs_bsize, NOCRED, &bp);
@ -108,8 +109,12 @@ ffs_update(vp, waitfor)
softdep_update_inodeblock(ip, bp, waitfor);
else if (ip->i_effnlink != ip->i_nlink)
panic("ffs_update: bad link cnt");
*((struct dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = ip->i_din;
if (ip->i_ump->um_fstype == UFS1)
*((struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1;
else
*((struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
if (waitfor && !DOINGASYNC(vp)) {
return (bwrite(bp));
} else if (vm_page_count_severe() || buf_dirty_count_severe()) {
@ -138,16 +143,14 @@ ffs_truncate(vp, length, flags, cred, td)
struct thread *td;
{
struct vnode *ovp = vp;
ufs_daddr_t lastblock;
struct inode *oip;
ufs_daddr_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR];
ufs_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
ufs2_daddr_t bn, lbn, lastblock, lastiblock[NIADDR], indir_lbn[NIADDR];
ufs2_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
ufs2_daddr_t count, blocksreleased = 0;
struct fs *fs;
struct buf *bp;
int offset, size, level;
long count, nblocks, blocksreleased = 0;
int i;
int aflags, error, allerror;
int offset, size, level, nblocks;
int i, aflags, error, allerror;
off_t osize;
oip = VTOI(ovp);
@ -157,13 +160,15 @@ ffs_truncate(vp, length, flags, cred, td)
if (length > fs->fs_maxfilesize)
return (EFBIG);
if (ovp->v_type == VLNK &&
(oip->i_size < ovp->v_mount->mnt_maxsymlinklen || oip->i_din.di_blocks == 0)) {
(oip->i_size < ovp->v_mount->mnt_maxsymlinklen ||
DIP(oip, i_blocks) == 0)) {
#ifdef DIAGNOSTIC
if (length != 0)
panic("ffs_truncate: partial truncate of symlink");
#endif
bzero((char *)&oip->i_shortlink, (u_int)oip->i_size);
bzero(SHORTLINK(oip), (u_int)oip->i_size);
oip->i_size = 0;
DIP(oip, i_size) = 0;
oip->i_flag |= IN_CHANGE | IN_UPDATE;
return (UFS_UPDATE(ovp, 1));
}
@ -196,10 +201,10 @@ ffs_truncate(vp, length, flags, cred, td)
td)) != 0)
return (error);
if (oip->i_flag & IN_SPACECOUNTED)
fs->fs_pendingblocks -= oip->i_blocks;
fs->fs_pendingblocks -= DIP(oip, i_blocks);
} else {
#ifdef QUOTA
(void) chkdq(oip, -oip->i_blocks, NOCRED, 0);
(void) chkdq(oip, -DIP(oip, i_blocks), NOCRED, 0);
#endif
softdep_setup_freeblocks(oip, length);
vinvalbuf(ovp, 0, cred, td, 0, 0);
@ -223,6 +228,7 @@ ffs_truncate(vp, length, flags, cred, td)
if (error)
return (error);
oip->i_size = length;
DIP(oip, i_size) = length;
if (bp->b_bufsize == fs->fs_bsize)
bp->b_flags |= B_CLUSTEROK;
if (aflags & B_SYNC)
@ -243,6 +249,7 @@ ffs_truncate(vp, length, flags, cred, td)
offset = blkoff(fs, length);
if (offset == 0) {
oip->i_size = length;
DIP(oip, i_size) = length;
} else {
lbn = lblkno(fs, length);
aflags = B_CLRBUF;
@ -265,6 +272,7 @@ ffs_truncate(vp, length, flags, cred, td)
(error = VOP_FSYNC(ovp, cred, MNT_WAIT, td)) != 0)
return (error);
oip->i_size = length;
DIP(oip, i_size) = length;
size = blksize(fs, oip, lbn);
if (ovp->v_type != VDIR)
bzero((char *)bp->b_data + offset,
@ -295,14 +303,18 @@ ffs_truncate(vp, length, flags, cred, td)
* will be returned to the free list. lastiblock values are also
* normalized to -1 for calls to ffs_indirtrunc below.
*/
bcopy((caddr_t)&oip->i_db[0], (caddr_t)oldblks, sizeof oldblks);
for (level = TRIPLE; level >= SINGLE; level--)
for (level = TRIPLE; level >= SINGLE; level--) {
oldblks[NDADDR + level] = DIP(oip, i_ib[level]);
if (lastiblock[level] < 0) {
oip->i_ib[level] = 0;
DIP(oip, i_ib[level]) = 0;
lastiblock[level] = -1;
}
for (i = NDADDR - 1; i > lastblock; i--)
oip->i_db[i] = 0;
}
for (i = 0; i < NDADDR; i++) {
oldblks[i] = DIP(oip, i_db[i]);
if (i > lastblock)
DIP(oip, i_db[i]) = 0;
}
oip->i_flag |= IN_CHANGE | IN_UPDATE;
allerror = UFS_UPDATE(ovp, 1);
@ -312,9 +324,16 @@ ffs_truncate(vp, length, flags, cred, td)
* Note that we save the new block configuration so we can check it
* when we are done.
*/
bcopy((caddr_t)&oip->i_db[0], (caddr_t)newblks, sizeof newblks);
bcopy((caddr_t)oldblks, (caddr_t)&oip->i_db[0], sizeof oldblks);
for (i = 0; i < NDADDR; i++) {
newblks[i] = DIP(oip, i_db[i]);
DIP(oip, i_db[i]) = oldblks[i];
}
for (i = 0; i < NIADDR; i++) {
newblks[NDADDR + i] = DIP(oip, i_ib[i]);
DIP(oip, i_ib[i]) = oldblks[NDADDR + i];
}
oip->i_size = osize;
DIP(oip, i_size) = osize;
error = vtruncbuf(ovp, cred, td, length, fs->fs_bsize);
if (error && (allerror == 0))
@ -327,7 +346,7 @@ ffs_truncate(vp, length, flags, cred, td)
indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1;
indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1;
for (level = TRIPLE; level >= SINGLE; level--) {
bn = oip->i_ib[level];
bn = DIP(oip, i_ib[level]);
if (bn != 0) {
error = ffs_indirtrunc(oip, indir_lbn[level],
fsbtodb(fs, bn), lastiblock[level], level, &count);
@ -335,7 +354,7 @@ ffs_truncate(vp, length, flags, cred, td)
allerror = error;
blocksreleased += count;
if (lastiblock[level] < 0) {
oip->i_ib[level] = 0;
DIP(oip, i_ib[level]) = 0;
ffs_blkfree(fs, oip->i_devvp, bn, fs->fs_bsize,
oip->i_number);
blocksreleased += nblocks;
@ -351,10 +370,10 @@ ffs_truncate(vp, length, flags, cred, td)
for (i = NDADDR - 1; i > lastblock; i--) {
long bsize;
bn = oip->i_db[i];
bn = DIP(oip, i_db[i]);
if (bn == 0)
continue;
oip->i_db[i] = 0;
DIP(oip, i_db[i]) = 0;
bsize = blksize(fs, oip, i);
ffs_blkfree(fs, oip->i_devvp, bn, bsize, oip->i_number);
blocksreleased += btodb(bsize);
@ -366,7 +385,7 @@ ffs_truncate(vp, length, flags, cred, td)
* Finally, look for a change in size of the
* last direct block; release any frags.
*/
bn = oip->i_db[lastblock];
bn = DIP(oip, i_db[lastblock]);
if (bn != 0) {
long oldspace, newspace;
@ -376,6 +395,7 @@ ffs_truncate(vp, length, flags, cred, td)
*/
oldspace = blksize(fs, oip, lastblock);
oip->i_size = length;
DIP(oip, i_size) = length;
newspace = blksize(fs, oip, lastblock);
if (newspace == 0)
panic("ffs_truncate: newspace");
@ -394,10 +414,10 @@ ffs_truncate(vp, length, flags, cred, td)
done:
#ifdef DIAGNOSTIC
for (level = SINGLE; level <= TRIPLE; level++)
if (newblks[NDADDR + level] != oip->i_ib[level])
if (newblks[NDADDR + level] != DIP(oip, i_ib[level]))
panic("ffs_truncate1");
for (i = 0; i < NDADDR; i++)
if (newblks[i] != oip->i_db[i])
if (newblks[i] != DIP(oip, i_db[i]))
panic("ffs_truncate2");
if (length == 0 &&
(!TAILQ_EMPTY(&ovp->v_dirtyblkhd) ||
@ -408,10 +428,11 @@ ffs_truncate(vp, length, flags, cred, td)
* Put back the real size.
*/
oip->i_size = length;
oip->i_blocks -= blocksreleased;
DIP(oip, i_size) = length;
DIP(oip, i_blocks) -= blocksreleased;
if (oip->i_blocks < 0) /* sanity */
oip->i_blocks = 0;
if (DIP(oip, i_blocks) < 0) /* sanity */
DIP(oip, i_blocks) = 0;
oip->i_flag |= IN_CHANGE;
#ifdef QUOTA
(void) chkdq(oip, -blocksreleased, NOCRED, 0);
@ -425,26 +446,25 @@ ffs_truncate(vp, length, flags, cred, td)
* lastbn. If level is greater than SINGLE, the block is an indirect block
* and recursive calls to indirtrunc must be used to cleanse other indirect
* blocks.
*
* NB: triple indirect blocks are untested.
*/
static int
ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
struct inode *ip;
ufs_daddr_t lbn, lastbn;
ufs_daddr_t dbn;
ufs2_daddr_t lbn, lastbn;
ufs2_daddr_t dbn;
int level;
long *countp;
ufs2_daddr_t *countp;
{
int i;
struct buf *bp;
struct fs *fs = ip->i_fs;
ufs_daddr_t *bap;
struct vnode *vp;
ufs_daddr_t *copy = NULL, nb, nlbn, last;
long blkcount, factor;
int nblocks, blocksreleased = 0;
int error = 0, allerror = 0;
caddr_t copy = NULL;
int i, nblocks, error = 0, allerror = 0;
ufs2_daddr_t nb, nlbn, last;
ufs2_daddr_t blkcount, factor, blocksreleased = 0;
ufs1_daddr_t *bap1 = NULL;
ufs2_daddr_t *bap2 = NULL;
# define BAP(ip, i) (((ip)->i_ump->um_fstype == UFS1) ? bap1[i] : bap2[i])
/*
* Calculate index in current block of last
@ -486,12 +506,15 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
return (error);
}
bap = (ufs_daddr_t *)bp->b_data;
if (ip->i_ump->um_fstype == UFS1)
bap1 = (ufs1_daddr_t *)bp->b_data;
else
bap2 = (ufs2_daddr_t *)bp->b_data;
if (lastbn != -1) {
MALLOC(copy, ufs_daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK);
bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize);
bzero((caddr_t)&bap[last + 1],
(u_int)(NINDIR(fs) - (last + 1)) * sizeof (ufs_daddr_t));
MALLOC(copy, caddr_t, fs->fs_bsize, M_TEMP, M_WAITOK);
bcopy((caddr_t)bp->b_data, copy, (u_int)fs->fs_bsize);
for (i = last + 1; i < NINDIR(fs); i++)
BAP(ip, i) = 0;
if (DOINGASYNC(vp)) {
bawrite(bp);
} else {
@ -499,7 +522,10 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
if (error)
allerror = error;
}
bap = copy;
if (ip->i_ump->um_fstype == UFS1)
bap1 = (ufs1_daddr_t *)copy;
else
bap2 = (ufs2_daddr_t *)copy;
}
/*
@ -507,12 +533,12 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
*/
for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last;
i--, nlbn += factor) {
nb = bap[i];
nb = BAP(ip, i);
if (nb == 0)
continue;
if (level > SINGLE) {
if ((error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
(ufs_daddr_t)-1, level - 1, &blkcount)) != 0)
(ufs2_daddr_t)-1, level - 1, &blkcount)) != 0)
allerror = error;
blocksreleased += blkcount;
}
@ -525,7 +551,7 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
*/
if (level > SINGLE && lastbn >= 0) {
last = lastbn % factor;
nb = bap[i];
nb = BAP(ip, i);
if (nb != 0) {
error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
last, level - 1, &blkcount);
@ -540,7 +566,7 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
bp->b_flags |= B_INVAL | B_NOCACHE;
brelse(bp);
}
*countp = blocksreleased;
return (allerror);
}

View File

@ -35,6 +35,7 @@
*/
#include <sys/param.h>
#include <sys/stdint.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/disklabel.h>
@ -47,6 +48,7 @@
#include <sys/mount.h>
#include <sys/resource.h>
#include <sys/resourcevar.h>
#include <sys/disklabel.h>
#include <sys/vnode.h>
#include <ufs/ufs/extattr.h>
@ -62,20 +64,34 @@
#define DEBUG 1
static int cgaccount(int, struct vnode *, struct buf *, int);
static int expunge(struct vnode *, struct inode *, struct fs *,
int (*)(struct vnode *, ufs_daddr_t *, ufs_daddr_t *, struct fs *,
ufs_daddr_t, int), int);
static int indiracct(struct vnode *, struct vnode *, int, ufs_daddr_t,
int, int, int, int, struct fs *, int (*)(struct vnode *,
ufs_daddr_t *, ufs_daddr_t *, struct fs *, ufs_daddr_t, int), int);
static int fullacct(struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
struct fs *, ufs_daddr_t, int);
static int snapacct(struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
struct fs *, ufs_daddr_t, int);
static int mapacct(struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
struct fs *, ufs_daddr_t, int);
static int expunge_ufs1(struct vnode *, struct inode *, struct fs *,
int (*)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *, struct fs *,
ufs_lbn_t, int), int);
static int indiracct_ufs1(struct vnode *, struct vnode *, int,
ufs1_daddr_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, struct fs *,
int (*)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *, struct fs *,
ufs_lbn_t, int), int);
static int fullacct_ufs1(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
struct fs *, ufs_lbn_t, int);
static int snapacct_ufs1(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
struct fs *, ufs_lbn_t, int);
static int mapacct_ufs1(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
struct fs *, ufs_lbn_t, int);
static int expunge_ufs2(struct vnode *, struct inode *, struct fs *,
int (*)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *, struct fs *,
ufs_lbn_t, int), int);
static int indiracct_ufs2(struct vnode *, struct vnode *, int,
ufs2_daddr_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, struct fs *,
int (*)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *, struct fs *,
ufs_lbn_t, int), int);
static int fullacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
struct fs *, ufs_lbn_t, int);
static int snapacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
struct fs *, ufs_lbn_t, int);
static int mapacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
struct fs *, ufs_lbn_t, int);
static int ffs_copyonwrite(struct vnode *, struct buf *);
static int readblock(struct buf *, daddr_t);
static int readblock(struct buf *, ufs2_daddr_t);
/*
* To ensure the consistency of snapshots across crashes, we must
@ -104,8 +120,8 @@ ffs_snapshot(mp, snapfile)
struct mount *mp;
char *snapfile;
{
ufs_daddr_t blkno;
int error, cg, snaploc, numblks;
ufs2_daddr_t numblks, blkno;
int error, cg, snaploc;
int i, size, len, loc;
int flag = mp->mnt_flag;
struct timespec starttime = {0, 0}, endtime;
@ -191,6 +207,7 @@ ffs_snapshot(mp, snapfile)
if (error)
goto out;
ip->i_size = lblktosize(fs, (off_t)numblks);
DIP(ip, i_size) = ip->i_size;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if ((error = readblock(bp, numblks - 1)) != 0)
goto out;
@ -216,7 +233,8 @@ ffs_snapshot(mp, snapfile)
/*
* Allocate copies for the superblock and its summary information.
*/
error = UFS_BALLOC(vp, (off_t)(SBOFF), SBSIZE, KERNCRED, 0, &nbp);
error = UFS_BALLOC(vp, lfragtosize(fs, fs->fs_sblockloc),
fs->fs_sbsize, KERNCRED, 0, &nbp);
if (error)
goto out;
bawrite(nbp);
@ -266,6 +284,7 @@ ffs_snapshot(mp, snapfile)
* Change inode to snapshot type file.
*/
ip->i_flags |= SF_SNAPSHOT;
DIP(ip, i_flags) = ip->i_flags;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
/*
* Ensure that the snapshot is completely on disk.
@ -315,19 +334,21 @@ ffs_snapshot(mp, snapfile)
* Grab a copy of the superblock and its summary information.
* We delay writing it until the suspension is released below.
*/
error = bread(vp, lblkno(fs, SBOFF), fs->fs_bsize, KERNCRED, &sbp);
error = bread(vp, fragstoblks(fs, fs->fs_sblockloc), fs->fs_bsize,
KERNCRED, &sbp);
if (error) {
brelse(sbp);
sbp = NULL;
goto out1;
}
copy_fs = (struct fs *)(sbp->b_data + blkoff(fs, SBOFF));
loc = blkoff(fs, lfragtosize(fs, fs->fs_sblockloc));
copy_fs = (struct fs *)(sbp->b_data + loc);
bcopy(fs, copy_fs, fs->fs_sbsize);
if ((fs->fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) == 0)
copy_fs->fs_clean = 1;
if (fs->fs_sbsize < SBSIZE)
bzero(&sbp->b_data[blkoff(fs, SBOFF) + fs->fs_sbsize],
SBSIZE - fs->fs_sbsize);
if (fs->fs_sbsize < SBLOCKSIZE)
bzero(&sbp->b_data[loc + fs->fs_sbsize],
SBLOCKSIZE - fs->fs_sbsize);
size = blkroundup(fs, fs->fs_cssize);
if (fs->fs_contigsumsize > 0)
size += fs->fs_ncg * sizeof(int32_t);
@ -399,15 +420,20 @@ ffs_snapshot(mp, snapfile)
if (loc < NDADDR) {
len = fragroundup(fs, blkoff(fs, xp->i_size));
if (len < fs->fs_bsize) {
ffs_blkfree(copy_fs, vp, xp->i_db[loc], len,
xp->i_number);
blkno = xp->i_db[loc];
xp->i_db[loc] = 0;
ffs_blkfree(copy_fs, vp, DIP(xp, i_db[loc]),
len, xp->i_number);
blkno = DIP(xp, i_db[loc]);
DIP(xp, i_db[loc]) = 0;
}
}
error = expunge(vp, xp, copy_fs, fullacct, BLK_NOCOPY);
if (xp->i_ump->um_fstype == UFS1)
error = expunge_ufs1(vp, xp, copy_fs, fullacct_ufs1,
BLK_NOCOPY);
else
error = expunge_ufs2(vp, xp, copy_fs, fullacct_ufs2,
BLK_NOCOPY);
if (blkno)
xp->i_db[loc] = blkno;
DIP(xp, i_db[loc]) = blkno;
if (!error)
error = ffs_freefile(copy_fs, vp, xp->i_number,
xp->i_mode);
@ -458,7 +484,13 @@ ffs_snapshot(mp, snapfile)
TAILQ_FOREACH(xp, snaphead, i_nextsnap) {
if (xp == ip)
break;
if ((error = expunge(vp, xp, fs, snapacct, BLK_SNAP)) != 0) {
if (xp->i_ump->um_fstype == UFS1)
error = expunge_ufs1(vp, xp, fs, snapacct_ufs1,
BLK_SNAP);
else
error = expunge_ufs2(vp, xp, fs, snapacct_ufs2,
BLK_SNAP);
if (error) {
fs->fs_snapinum[snaploc] = 0;
goto done;
}
@ -467,7 +499,11 @@ ffs_snapshot(mp, snapfile)
* Expunge the blocks used by the snapshots from the set of
* blocks marked as used in the snapshot bitmaps.
*/
if ((error = expunge(vp, ip, copy_fs, mapacct, BLK_SNAP)) != 0) {
if (ip->i_ump->um_fstype == UFS1)
error = expunge_ufs1(vp, ip, copy_fs, mapacct_ufs1, BLK_SNAP);
else
error = expunge_ufs2(vp, ip, copy_fs, mapacct_ufs2, BLK_SNAP);
if (error) {
fs->fs_snapinum[snaploc] = 0;
goto done;
}
@ -528,7 +564,8 @@ cgaccount(cg, vp, nbp, passno)
struct inode *ip;
struct cg *cgp;
struct fs *fs;
int error, numblks, base, len, loc, indiroff;
ufs2_daddr_t base, numblks;
int error, len, loc, indiroff;
ip = VTOI(vp);
fs = ip->i_fs;
@ -559,10 +596,10 @@ cgaccount(cg, vp, nbp, passno)
if (base < NDADDR) {
for ( ; loc < NDADDR; loc++) {
if (ffs_isblock(fs, cg_blksfree(cgp), loc))
ip->i_db[loc] = BLK_NOCOPY;
else if (passno == 2 && ip->i_db[loc] == BLK_NOCOPY)
ip->i_db[loc] = 0;
else if (passno == 1 && ip->i_db[loc] == BLK_NOCOPY)
DIP(ip, i_db[loc]) = BLK_NOCOPY;
else if (passno == 2 && DIP(ip, i_db[loc])== BLK_NOCOPY)
DIP(ip, i_db[loc]) = 0;
else if (passno == 1 && DIP(ip, i_db[loc])== BLK_NOCOPY)
panic("ffs_snapshot: lost direct block");
}
}
@ -587,13 +624,25 @@ cgaccount(cg, vp, nbp, passno)
}
indiroff = 0;
}
if (ip->i_ump->um_fstype == UFS1) {
if (ffs_isblock(fs, cg_blksfree(cgp), loc))
((ufs1_daddr_t *)(ibp->b_data))[indiroff] =
BLK_NOCOPY;
else if (passno == 2 && ((ufs1_daddr_t *)(ibp->b_data))
[indiroff] == BLK_NOCOPY)
((ufs1_daddr_t *)(ibp->b_data))[indiroff] = 0;
else if (passno == 1 && ((ufs1_daddr_t *)(ibp->b_data))
[indiroff] == BLK_NOCOPY)
panic("ffs_snapshot: lost indirect block");
continue;
}
if (ffs_isblock(fs, cg_blksfree(cgp), loc))
((ufs_daddr_t *)(ibp->b_data))[indiroff] = BLK_NOCOPY;
((ufs2_daddr_t *)(ibp->b_data))[indiroff] = BLK_NOCOPY;
else if (passno == 2 &&
((ufs_daddr_t *)(ibp->b_data))[indiroff] == BLK_NOCOPY)
((ufs_daddr_t *)(ibp->b_data))[indiroff] = 0;
((ufs2_daddr_t *)(ibp->b_data)) [indiroff] == BLK_NOCOPY)
((ufs2_daddr_t *)(ibp->b_data))[indiroff] = 0;
else if (passno == 1 &&
((ufs_daddr_t *)(ibp->b_data))[indiroff] == BLK_NOCOPY)
((ufs2_daddr_t *)(ibp->b_data)) [indiroff] == BLK_NOCOPY)
panic("ffs_snapshot: lost indirect block");
}
bqrelse(bp);
@ -608,34 +657,37 @@ cgaccount(cg, vp, nbp, passno)
* blocks that it claims with BLK_SNAP so that fsck will
* be able to account for those blocks properly and so
* that this snapshot knows that it need not copy them
* if the other snapshot holding them is freed.
* if the other snapshot holding them is freed. This code
* is reproduced once each for UFS1 and UFS2.
*/
static int
expunge(snapvp, cancelip, fs, acctfunc, expungetype)
expunge_ufs1(snapvp, cancelip, fs, acctfunc, expungetype)
struct vnode *snapvp;
struct inode *cancelip;
struct fs *fs;
int (*acctfunc)(struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
struct fs *, ufs_daddr_t, int);
int (*acctfunc)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
struct fs *, ufs_lbn_t, int);
int expungetype;
{
int i, len, error, numblks, blksperindir;
ufs_daddr_t lbn, rlbn, blkno, indiroff;
int i, error, indiroff;
ufs_lbn_t lbn, rlbn;
ufs2_daddr_t len, blkno, numblks, blksperindir;
struct ufs1_dinode *dip;
struct thread *td = curthread;
struct dinode *dip;
struct buf *bp;
numblks = howmany(cancelip->i_size, fs->fs_bsize);
if ((error = (*acctfunc)(snapvp, &cancelip->i_db[0],
&cancelip->i_ib[NIADDR], fs, 0, expungetype)))
if ((error = (*acctfunc)(snapvp, &cancelip->i_din1->di_db[0],
&cancelip->i_din1->di_ib[NIADDR], fs, 0, expungetype)))
return (error);
blksperindir = 1;
lbn = -NDADDR;
len = numblks - NDADDR;
rlbn = NDADDR;
for (i = 0; len > 0 && i < NIADDR; i++) {
error = indiracct(snapvp, ITOV(cancelip), i, cancelip->i_ib[i],
lbn, rlbn, len, blksperindir, fs, acctfunc, expungetype);
error = indiracct_ufs1(snapvp, ITOV(cancelip), i,
cancelip->i_din1->di_ib[i], lbn, rlbn, len,
blksperindir, fs, acctfunc, expungetype);
if (error)
return (error);
blksperindir *= NINDIR(fs);
@ -650,7 +702,7 @@ expunge(snapvp, cancelip, fs, acctfunc, expungetype)
lbn = fragstoblks(fs, ino_to_fsba(fs, cancelip->i_number));
blkno = 0;
if (lbn < NDADDR) {
blkno = cancelip->i_db[lbn];
blkno = cancelip->i_din1->di_db[lbn];
} else {
td->td_proc->p_flag |= P_COWINPROGRESS;
error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn),
@ -659,7 +711,7 @@ expunge(snapvp, cancelip, fs, acctfunc, expungetype)
if (error)
return (error);
indiroff = (lbn - NDADDR) % NINDIR(fs);
blkno = ((ufs_daddr_t *)(bp->b_data))[indiroff];
blkno = ((ufs1_daddr_t *)(bp->b_data))[indiroff];
bqrelse(bp);
}
error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn),
@ -672,13 +724,14 @@ expunge(snapvp, cancelip, fs, acctfunc, expungetype)
* Set a snapshot inode to be a zero length file, regular files
* to be completely unallocated.
*/
dip = (struct dinode *)bp->b_data + ino_to_fsbo(fs, cancelip->i_number);
dip = (struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, cancelip->i_number);
if (expungetype == BLK_NOCOPY)
dip->di_mode = 0;
dip->di_size = 0;
dip->di_blocks = 0;
dip->di_flags &= ~SF_SNAPSHOT;
bzero(&dip->di_db[0], (NDADDR + NIADDR) * sizeof(ufs_daddr_t));
bzero(&dip->di_db[0], (NDADDR + NIADDR) * sizeof(ufs1_daddr_t));
bdwrite(bp);
return (0);
}
@ -688,24 +741,25 @@ expunge(snapvp, cancelip, fs, acctfunc, expungetype)
* its indirect blocks in snapvp.
*/
static int
indiracct(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks, blksperindir, fs,
acctfunc, expungetype)
indiracct_ufs1(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks,
blksperindir, fs, acctfunc, expungetype)
struct vnode *snapvp;
struct vnode *cancelvp;
int level;
ufs_daddr_t blkno;
int lbn;
int rlbn;
int remblks;
int blksperindir;
ufs1_daddr_t blkno;
ufs_lbn_t lbn;
ufs_lbn_t rlbn;
ufs_lbn_t remblks;
ufs_lbn_t blksperindir;
struct fs *fs;
int (*acctfunc)(struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
struct fs *, ufs_daddr_t, int);
int (*acctfunc)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
struct fs *, ufs_lbn_t, int);
int expungetype;
{
int subblksperindir, error, last, num, i;
int error, num, i;
ufs_lbn_t subblksperindir;
struct indir indirs[NIADDR + 2];
ufs_daddr_t *bap;
ufs1_daddr_t last, *bap;
struct buf *bp;
if ((error = ufs_getlbns(cancelvp, rlbn, indirs, &num)) != 0)
@ -729,7 +783,7 @@ indiracct(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks, blksperindir, fs,
last = howmany(remblks, blksperindir);
if (last > NINDIR(fs))
last = NINDIR(fs);
MALLOC(bap, ufs_daddr_t *, fs->fs_bsize, M_DEVBUF, M_WAITOK);
MALLOC(bap, ufs1_daddr_t *, fs->fs_bsize, M_DEVBUF, M_WAITOK);
bcopy(bp->b_data, (caddr_t)bap, fs->fs_bsize);
bqrelse(bp);
error = (*acctfunc)(snapvp, &bap[0], &bap[last], fs, rlbn, expungetype);
@ -741,7 +795,7 @@ indiracct(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks, blksperindir, fs,
*/
subblksperindir = blksperindir / NINDIR(fs);
for (lbn++, level--, i = 0; i < last; i++) {
error = indiracct(snapvp, cancelvp, level, bap[i], lbn,
error = indiracct_ufs1(snapvp, cancelvp, level, bap[i], lbn,
rlbn, remblks, subblksperindir, fs, acctfunc, expungetype);
if (error)
goto out;
@ -758,33 +812,34 @@ indiracct(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks, blksperindir, fs,
* Do both snap accounting and map accounting.
*/
static int
fullacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
fullacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, exptype)
struct vnode *vp;
ufs_daddr_t *oldblkp, *lastblkp;
ufs1_daddr_t *oldblkp, *lastblkp;
struct fs *fs;
ufs_daddr_t lblkno;
int expungetype; /* BLK_SNAP or BLK_NOCOPY */
ufs_lbn_t lblkno;
int exptype; /* BLK_SNAP or BLK_NOCOPY */
{
int error;
if ((error = snapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)))
if ((error = snapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, exptype)))
return (error);
return (mapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype));
return (mapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, exptype));
}
/*
* Identify a set of blocks allocated in a snapshot inode.
*/
static int
snapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
snapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
struct vnode *vp;
ufs_daddr_t *oldblkp, *lastblkp;
ufs1_daddr_t *oldblkp, *lastblkp;
struct fs *fs;
ufs_daddr_t lblkno;
ufs_lbn_t lblkno;
int expungetype; /* BLK_SNAP or BLK_NOCOPY */
{
struct inode *ip = VTOI(vp);
ufs_daddr_t lbn, blkno, *blkp;
ufs1_daddr_t blkno, *blkp;
ufs_lbn_t lbn;
struct buf *ibp;
int error;
@ -794,14 +849,14 @@ snapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
continue;
lbn = fragstoblks(fs, blkno);
if (lbn < NDADDR) {
blkp = &ip->i_db[lbn];
blkp = &ip->i_din1->di_db[lbn];
ip->i_flag |= IN_CHANGE | IN_UPDATE;
} else {
error = UFS_BALLOC(vp, lblktosize(fs, (off_t)lbn),
fs->fs_bsize, KERNCRED, B_METAONLY, &ibp);
if (error)
return (error);
blkp = &((ufs_daddr_t *)(ibp->b_data))
blkp = &((ufs1_daddr_t *)(ibp->b_data))
[(lbn - NDADDR) % NINDIR(fs)];
}
/*
@ -828,14 +883,267 @@ snapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
* Account for a set of blocks allocated in a snapshot inode.
*/
static int
mapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
mapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
struct vnode *vp;
ufs_daddr_t *oldblkp, *lastblkp;
ufs1_daddr_t *oldblkp, *lastblkp;
struct fs *fs;
ufs_daddr_t lblkno;
ufs_lbn_t lblkno;
int expungetype;
{
ufs_daddr_t blkno;
ufs1_daddr_t blkno;
ino_t inum;
inum = VTOI(vp)->i_number;
for ( ; oldblkp < lastblkp; oldblkp++, lblkno++) {
blkno = *oldblkp;
if (blkno == 0 || blkno == BLK_NOCOPY)
continue;
if (blkno == BLK_SNAP)
blkno = blkstofrags(fs, lblkno);
ffs_blkfree(fs, vp, blkno, fs->fs_bsize, inum);
}
return (0);
}
/*
* Before expunging a snapshot inode, note all the
* blocks that it claims with BLK_SNAP so that fsck will
* be able to account for those blocks properly and so
* that this snapshot knows that it need not copy them
* if the other snapshot holding them is freed. This code
* is reproduced once each for UFS1 and UFS2.
*/
static int
expunge_ufs2(snapvp, cancelip, fs, acctfunc, expungetype)
struct vnode *snapvp;
struct inode *cancelip;
struct fs *fs;
int (*acctfunc)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
struct fs *, ufs_lbn_t, int);
int expungetype;
{
int i, error, indiroff;
ufs_lbn_t lbn, rlbn;
ufs2_daddr_t len, blkno, numblks, blksperindir;
struct ufs2_dinode *dip;
struct thread *td = curthread;
struct buf *bp;
numblks = howmany(cancelip->i_size, fs->fs_bsize);
if ((error = (*acctfunc)(snapvp, &cancelip->i_din2->di_db[0],
&cancelip->i_din2->di_ib[NIADDR], fs, 0, expungetype)))
return (error);
blksperindir = 1;
lbn = -NDADDR;
len = numblks - NDADDR;
rlbn = NDADDR;
for (i = 0; len > 0 && i < NIADDR; i++) {
error = indiracct_ufs2(snapvp, ITOV(cancelip), i,
cancelip->i_din2->di_ib[i], lbn, rlbn, len,
blksperindir, fs, acctfunc, expungetype);
if (error)
return (error);
blksperindir *= NINDIR(fs);
lbn -= blksperindir + 1;
len -= blksperindir;
rlbn += blksperindir;
}
/*
* Prepare to expunge the inode. If its inode block has not
* yet been copied, then allocate and fill the copy.
*/
lbn = fragstoblks(fs, ino_to_fsba(fs, cancelip->i_number));
blkno = 0;
if (lbn < NDADDR) {
blkno = cancelip->i_din2->di_db[lbn];
} else {
td->td_proc->p_flag |= P_COWINPROGRESS;
error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn),
fs->fs_bsize, KERNCRED, B_METAONLY, &bp);
td->td_proc->p_flag &= ~P_COWINPROGRESS;
if (error)
return (error);
indiroff = (lbn - NDADDR) % NINDIR(fs);
blkno = ((ufs2_daddr_t *)(bp->b_data))[indiroff];
bqrelse(bp);
}
error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn),
fs->fs_bsize, KERNCRED, 0, &bp);
if (error)
return (error);
if (blkno == 0 && (error = readblock(bp, lbn)))
return (error);
/*
* Set a snapshot inode to be a zero length file, regular files
* to be completely unallocated.
*/
dip = (struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, cancelip->i_number);
if (expungetype == BLK_NOCOPY)
dip->di_mode = 0;
dip->di_size = 0;
dip->di_blocks = 0;
dip->di_flags &= ~SF_SNAPSHOT;
bzero(&dip->di_db[0], (NDADDR + NIADDR) * sizeof(ufs2_daddr_t));
bdwrite(bp);
return (0);
}
/*
* Descend an indirect block chain for vnode cancelvp accounting for all
* its indirect blocks in snapvp.
*/
static int
indiracct_ufs2(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks,
blksperindir, fs, acctfunc, expungetype)
struct vnode *snapvp;
struct vnode *cancelvp;
int level;
ufs2_daddr_t blkno;
ufs_lbn_t lbn;
ufs_lbn_t rlbn;
ufs_lbn_t remblks;
ufs_lbn_t blksperindir;
struct fs *fs;
int (*acctfunc)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
struct fs *, ufs_lbn_t, int);
int expungetype;
{
int error, num, i;
ufs_lbn_t subblksperindir;
struct indir indirs[NIADDR + 2];
ufs2_daddr_t last, *bap;
struct buf *bp;
if ((error = ufs_getlbns(cancelvp, rlbn, indirs, &num)) != 0)
return (error);
if (lbn != indirs[num - 1 - level].in_lbn || blkno == 0 || num < 2)
panic("indiracct: botched params");
/*
* We have to expand bread here since it will deadlock looking
* up the block number for any blocks that are not in the cache.
*/
bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0);
bp->b_blkno = fsbtodb(fs, blkno);
if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0 &&
(error = readblock(bp, fragstoblks(fs, blkno)))) {
brelse(bp);
return (error);
}
/*
* Account for the block pointers in this indirect block.
*/
last = howmany(remblks, blksperindir);
if (last > NINDIR(fs))
last = NINDIR(fs);
MALLOC(bap, ufs2_daddr_t *, fs->fs_bsize, M_DEVBUF, M_WAITOK);
bcopy(bp->b_data, (caddr_t)bap, fs->fs_bsize);
bqrelse(bp);
error = (*acctfunc)(snapvp, &bap[0], &bap[last], fs, rlbn, expungetype);
if (error || level == 0)
goto out;
/*
* Account for the block pointers in each of the indirect blocks
* in the levels below us.
*/
subblksperindir = blksperindir / NINDIR(fs);
for (lbn++, level--, i = 0; i < last; i++) {
error = indiracct_ufs2(snapvp, cancelvp, level, bap[i], lbn,
rlbn, remblks, subblksperindir, fs, acctfunc, expungetype);
if (error)
goto out;
rlbn += blksperindir;
lbn -= blksperindir;
remblks -= blksperindir;
}
out:
FREE(bap, M_DEVBUF);
return (error);
}
/*
* Do both snap accounting and map accounting.
*/
static int
fullacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, exptype)
struct vnode *vp;
ufs2_daddr_t *oldblkp, *lastblkp;
struct fs *fs;
ufs_lbn_t lblkno;
int exptype; /* BLK_SNAP or BLK_NOCOPY */
{
int error;
if ((error = snapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, exptype)))
return (error);
return (mapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, exptype));
}
/*
* Identify a set of blocks allocated in a snapshot inode.
*/
static int
snapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
struct vnode *vp;
ufs2_daddr_t *oldblkp, *lastblkp;
struct fs *fs;
ufs_lbn_t lblkno;
int expungetype; /* BLK_SNAP or BLK_NOCOPY */
{
struct inode *ip = VTOI(vp);
ufs2_daddr_t blkno, *blkp;
ufs_lbn_t lbn;
struct buf *ibp;
int error;
for ( ; oldblkp < lastblkp; oldblkp++) {
blkno = *oldblkp;
if (blkno == 0 || blkno == BLK_NOCOPY || blkno == BLK_SNAP)
continue;
lbn = fragstoblks(fs, blkno);
if (lbn < NDADDR) {
blkp = &ip->i_din2->di_db[lbn];
ip->i_flag |= IN_CHANGE | IN_UPDATE;
} else {
error = UFS_BALLOC(vp, lblktosize(fs, (off_t)lbn),
fs->fs_bsize, KERNCRED, B_METAONLY, &ibp);
if (error)
return (error);
blkp = &((ufs2_daddr_t *)(ibp->b_data))
[(lbn - NDADDR) % NINDIR(fs)];
}
/*
* If we are expunging a snapshot vnode and we
* find a block marked BLK_NOCOPY, then it is
* one that has been allocated to this snapshot after
* we took our current snapshot and can be ignored.
*/
if (expungetype == BLK_SNAP && *blkp == BLK_NOCOPY) {
if (lbn >= NDADDR)
brelse(ibp);
} else {
if (*blkp != 0)
panic("snapacct: bad block");
*blkp = expungetype;
if (lbn >= NDADDR)
bdwrite(ibp);
}
}
return (0);
}
/*
* Account for a set of blocks allocated in a snapshot inode.
*/
static int
mapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
struct vnode *vp;
ufs2_daddr_t *oldblkp, *lastblkp;
struct fs *fs;
ufs_lbn_t lblkno;
int expungetype;
{
ufs2_daddr_t blkno;
ino_t inum;
inum = VTOI(vp)->i_number;
@ -901,8 +1209,8 @@ ffs_snapremove(vp)
struct vnode *devvp;
struct buf *ibp;
struct fs *fs;
ufs_daddr_t blkno, dblk;
int error, numblks, loc, last;
ufs2_daddr_t numblks, blkno, dblk;
int error, loc, last;
ip = VTOI(vp);
fs = ip->i_fs;
@ -927,14 +1235,14 @@ ffs_snapremove(vp)
* snapshots that want them (see ffs_snapblkfree below).
*/
for (blkno = 1; blkno < NDADDR; blkno++) {
dblk = ip->i_db[blkno];
dblk = DIP(ip, i_db[blkno]);
if (dblk == BLK_NOCOPY || dblk == BLK_SNAP)
ip->i_db[blkno] = 0;
DIP(ip, i_db[blkno]) = 0;
else if ((dblk == blkstofrags(fs, blkno) &&
ffs_snapblkfree(fs, ip->i_devvp, dblk, fs->fs_bsize,
ip->i_number))) {
ip->i_blocks -= btodb(fs->fs_bsize);
ip->i_db[blkno] = 0;
DIP(ip, i_blocks) -= btodb(fs->fs_bsize);
DIP(ip, i_db[blkno]) = 0;
}
}
numblks = howmany(ip->i_size, fs->fs_bsize);
@ -943,17 +1251,32 @@ ffs_snapremove(vp)
fs->fs_bsize, KERNCRED, B_METAONLY, &ibp);
if (error)
continue;
if ((last = fs->fs_size - blkno) > NINDIR(fs))
if (fs->fs_size - blkno > NINDIR(fs))
last = NINDIR(fs);
else
last = fs->fs_size - blkno;
for (loc = 0; loc < last; loc++) {
dblk = ((ufs_daddr_t *)(ibp->b_data))[loc];
if (ip->i_ump->um_fstype == UFS1) {
dblk = ((ufs1_daddr_t *)(ibp->b_data))[loc];
if (dblk == BLK_NOCOPY || dblk == BLK_SNAP)
((ufs1_daddr_t *)(ibp->b_data))[loc]= 0;
else if ((dblk == blkstofrags(fs, blkno) &&
ffs_snapblkfree(fs, ip->i_devvp, dblk,
fs->fs_bsize, ip->i_number))) {
ip->i_din1->di_blocks -=
btodb(fs->fs_bsize);
((ufs1_daddr_t *)(ibp->b_data))[loc]= 0;
}
continue;
}
dblk = ((ufs2_daddr_t *)(ibp->b_data))[loc];
if (dblk == BLK_NOCOPY || dblk == BLK_SNAP)
((ufs_daddr_t *)(ibp->b_data))[loc] = 0;
((ufs2_daddr_t *)(ibp->b_data))[loc] = 0;
else if ((dblk == blkstofrags(fs, blkno) &&
ffs_snapblkfree(fs, ip->i_devvp, dblk,
fs->fs_bsize, ip->i_number))) {
ip->i_blocks -= btodb(fs->fs_bsize);
((ufs_daddr_t *)(ibp->b_data))[loc] = 0;
ip->i_din2->di_blocks -= btodb(fs->fs_bsize);
((ufs2_daddr_t *)(ibp->b_data))[loc] = 0;
}
}
bawrite(ibp);
@ -962,6 +1285,7 @@ ffs_snapremove(vp)
* Clear snapshot flag and drop reference.
*/
ip->i_flags &= ~SF_SNAPSHOT;
DIP(ip, i_flags) = ip->i_flags;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
@ -987,7 +1311,7 @@ int
ffs_snapblkfree(fs, devvp, bno, size, inum)
struct fs *fs;
struct vnode *devvp;
ufs_daddr_t bno;
ufs2_daddr_t bno;
long size;
ino_t inum;
{
@ -995,7 +1319,8 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
struct thread *td = curthread;
struct inode *ip;
struct vnode *vp;
ufs_daddr_t lbn, blkno;
ufs_lbn_t lbn;
ufs2_daddr_t blkno;
int indiroff = 0, error = 0, claimedblk = 0;
struct snaphead *snaphead;
@ -1007,7 +1332,7 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
* Lookup block being written.
*/
if (lbn < NDADDR) {
blkno = ip->i_db[lbn];
blkno = DIP(ip, i_db[lbn]);
} else {
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
td->td_proc->p_flag |= P_COWINPROGRESS;
@ -1018,46 +1343,52 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
if (error)
break;
indiroff = (lbn - NDADDR) % NINDIR(fs);
blkno = ((ufs_daddr_t *)(ibp->b_data))[indiroff];
if (ip->i_ump->um_fstype == UFS1)
blkno=((ufs1_daddr_t *)(ibp->b_data))[indiroff];
else
blkno=((ufs2_daddr_t *)(ibp->b_data))[indiroff];
}
/*
* Check to see if block needs to be copied.
*/
switch (blkno) {
/*
* If the snapshot has already copied the block (default),
* or does not care about the block, it is not needed.
*/
default:
case BLK_NOCOPY:
if (lbn >= NDADDR)
bqrelse(ibp);
continue;
/*
* No previous snapshot claimed the block, so it will be
* freed and become a BLK_NOCOPY (don't care) for us.
*/
case BLK_SNAP:
if (blkno == 0) {
/*
* A block that we map is being freed. If it has not
* been claimed yet, we will claim or copy it (below).
*/
claimedblk = 1;
} else if (blkno == BLK_SNAP) {
/*
* No previous snapshot claimed the block,
* so it will be * freed and become a BLK_NOCOPY
* (don't care) for us.
*/
if (claimedblk)
panic("snapblkfree: inconsistent block type");
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (lbn < NDADDR) {
ip->i_db[lbn] = BLK_NOCOPY;
DIP(ip, i_db[lbn]) = BLK_NOCOPY;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
} else if (ip->i_ump->um_fstype == UFS1) {
((ufs1_daddr_t *)(ibp->b_data))[indiroff] =
BLK_NOCOPY;
bdwrite(ibp);
} else {
((ufs_daddr_t *)(ibp->b_data))[indiroff] =
((ufs2_daddr_t *)(ibp->b_data))[indiroff] =
BLK_NOCOPY;
bdwrite(ibp);
}
VOP_UNLOCK(vp, 0, td);
continue;
/*
* A block that we map is being freed. If it has not been
* claimed yet, we will claim or copy it (below).
*/
case 0:
claimedblk = 1;
break;
} else /* BLK_NOCOPY or default */ {
/*
* If the snapshot has already copied the block
* (default), or does not care about the block,
* it is not needed.
*/
if (lbn >= NDADDR)
bqrelse(ibp);
continue;
}
/*
* If this is a full size block, we will just grab it
@ -1069,18 +1400,21 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
if (size == fs->fs_bsize) {
#ifdef DEBUG
if (snapdebug)
printf("%s %d lbn %d from inum %d\n",
"Grabonremove: snapino", ip->i_number, lbn,
inum);
printf("%s %d lbn %lld from inum %d\n",
"Grabonremove: snapino", ip->i_number,
(intmax_t)lbn, inum);
#endif
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (lbn < NDADDR) {
ip->i_db[lbn] = bno;
DIP(ip, i_db[lbn]) = bno;
} else if (ip->i_ump->um_fstype == UFS1) {
((ufs1_daddr_t *)(ibp->b_data))[indiroff] = bno;
bdwrite(ibp);
} else {
((ufs_daddr_t *)(ibp->b_data))[indiroff] = bno;
((ufs2_daddr_t *)(ibp->b_data))[indiroff] = bno;
bdwrite(ibp);
}
ip->i_blocks += btodb(size);
DIP(ip, i_blocks) += btodb(size);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
VOP_UNLOCK(vp, 0, td);
return (1);
@ -1103,10 +1437,10 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
}
#ifdef DEBUG
if (snapdebug)
printf(
"Copyonremove: snapino %lu lbn %ld for inum %lu size %ld to blkno %lld\n",
(unsigned long)ip->i_number, (long)lbn,
(unsigned long)inum, size, (long long)cbp->b_blkno);
printf("%s%d lbn %lld %s %d size %ld to blkno %lld\n",
"Copyonremove: snapino ", ip->i_number,
(intmax_t)lbn, "for inum", inum, size,
(intmax_t)cbp->b_blkno);
#endif
/*
* If we have already read the old block contents, then
@ -1245,7 +1579,7 @@ ffs_copyonwrite(devvp, bp)
struct fs *fs;
struct inode *ip;
struct vnode *vp;
ufs_daddr_t lbn, blkno;
ufs2_daddr_t lbn, blkno;
int indiroff, error = 0;
fs = TAILQ_FIRST(&devvp->v_rdev->si_snapshots)->i_fs;
@ -1273,7 +1607,7 @@ ffs_copyonwrite(devvp, bp)
retry:
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (lbn < NDADDR) {
blkno = ip->i_db[lbn];
blkno = DIP(ip, i_db[lbn]);
} else {
td->td_proc->p_flag |= P_COWINPROGRESS;
error = UFS_BALLOC(vp, lblktosize(fs, (off_t)lbn),
@ -1287,7 +1621,10 @@ ffs_copyonwrite(devvp, bp)
goto retry;
}
indiroff = (lbn - NDADDR) % NINDIR(fs);
blkno = ((ufs_daddr_t *)(ibp->b_data))[indiroff];
if (ip->i_ump->um_fstype == UFS1)
blkno=((ufs1_daddr_t *)(ibp->b_data))[indiroff];
else
blkno=((ufs2_daddr_t *)(ibp->b_data))[indiroff];
bqrelse(ibp);
}
#ifdef DIAGNOSTIC
@ -1316,14 +1653,14 @@ ffs_copyonwrite(devvp, bp)
}
#ifdef DEBUG
if (snapdebug) {
printf("Copyonwrite: snapino %d lbn %d for ",
ip->i_number, lbn);
printf("Copyonwrite: snapino %d lbn %lld for ",
ip->i_number, (intmax_t)lbn);
if (bp->b_vp == devvp)
printf("fs metadata");
else
printf("inum %d", VTOI(bp->b_vp)->i_number);
printf(" lblkno %lld to blkno %lld\n",
(long long)bp->b_lblkno, (long long)cbp->b_blkno);
(intmax_t)bp->b_lblkno, (intmax_t)cbp->b_blkno);
}
#endif
/*
@ -1379,7 +1716,7 @@ ffs_copyonwrite(devvp, bp)
static int
readblock(bp, lbn)
struct buf *bp;
daddr_t lbn;
ufs2_daddr_t lbn;
{
struct uio auio;
struct iovec aiov;

View File

@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/stdint.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/malloc.h>
@ -163,7 +164,8 @@ static void handle_allocdirect_partdone(struct allocdirect *);
static void handle_allocindir_partdone(struct allocindir *);
static void initiate_write_filepage(struct pagedep *, struct buf *);
static void handle_written_mkdir(struct mkdir *, int);
static void initiate_write_inodeblock(struct inodedep *, struct buf *);
static void initiate_write_inodeblock_ufs1(struct inodedep *, struct buf *);
static void initiate_write_inodeblock_ufs2(struct inodedep *, struct buf *);
static void handle_workitem_freefile(struct freefile *);
static void handle_workitem_remove(struct dirrem *, struct vnode *);
static struct dirrem *newdirrem(struct buf *, struct inode *,
@ -171,7 +173,8 @@ static struct dirrem *newdirrem(struct buf *, struct inode *,
static void free_diradd(struct diradd *);
static void free_allocindir(struct allocindir *, struct inodedep *);
static void free_newdirblk(struct newdirblk *);
static int indir_trunc(struct freeblks *, ufs_daddr_t, int, ufs_lbn_t, long *);
static int indir_trunc(struct freeblks *, ufs2_daddr_t, int, ufs_lbn_t,
ufs2_daddr_t *);
static void deallocate_dependencies(struct buf *, struct inodedep *);
static void free_allocdirect(struct allocdirectlst *,
struct allocdirect *, int);
@ -181,14 +184,14 @@ static void handle_workitem_freeblocks(struct freeblks *, int);
static void merge_inode_lists(struct inodedep *);
static void setup_allocindir_phase2(struct buf *, struct inode *,
struct allocindir *);
static struct allocindir *newallocindir(struct inode *, int, ufs_daddr_t,
ufs_daddr_t);
static struct allocindir *newallocindir(struct inode *, int, ufs2_daddr_t,
ufs2_daddr_t);
static void handle_workitem_freefrag(struct freefrag *);
static struct freefrag *newfreefrag(struct inode *, ufs_daddr_t, long);
static struct freefrag *newfreefrag(struct inode *, ufs2_daddr_t, long);
static void allocdirect_merge(struct allocdirectlst *,
struct allocdirect *, struct allocdirect *);
static struct bmsafemap *bmsafemap_lookup(struct buf *);
static int newblk_lookup(struct fs *, ufs_daddr_t, int, struct newblk **);
static int newblk_lookup(struct fs *, ufs2_daddr_t, int, struct newblk **);
static int inodedep_lookup(struct fs *, ino_t, int, struct inodedep **);
static int pagedep_lookup(struct inode *, ufs_lbn_t, int, struct pagedep **);
static void pause_timer(void *);
@ -1036,7 +1039,7 @@ inodedep_lookup(fs, inum, flags, inodedeppp)
inodedep->id_ino = inum;
inodedep->id_state = ALLCOMPLETE;
inodedep->id_nlinkdelta = 0;
inodedep->id_savedino = NULL;
inodedep->id_savedino1 = NULL;
inodedep->id_savedsize = -1;
inodedep->id_buf = NULL;
LIST_INIT(&inodedep->id_pendinghd);
@ -1068,7 +1071,7 @@ static struct sema newblk_in_progress;
static int
newblk_lookup(fs, newblkno, flags, newblkpp)
struct fs *fs;
ufs_daddr_t newblkno;
ufs2_daddr_t newblkno;
int flags;
struct newblk **newblkpp;
{
@ -1139,7 +1142,7 @@ softdep_mount(devvp, mp, fs, cred)
struct fs *fs;
struct ucred *cred;
{
struct csum cstotal;
struct csum_total cstotal;
struct cg *cgp;
struct buf *bp;
int error, cyl;
@ -1246,7 +1249,7 @@ void
softdep_setup_blkmapdep(bp, fs, newblkno)
struct buf *bp; /* buffer for cylgroup block with block map */
struct fs *fs; /* filesystem doing allocation */
ufs_daddr_t newblkno; /* number of newly allocated block */
ufs2_daddr_t newblkno; /* number of newly allocated block */
{
struct newblk *newblk;
struct bmsafemap *bmsafemap;
@ -1332,8 +1335,8 @@ void
softdep_setup_allocdirect(ip, lbn, newblkno, oldblkno, newsize, oldsize, bp)
struct inode *ip; /* inode to which block is being added */
ufs_lbn_t lbn; /* block pointer within inode */
ufs_daddr_t newblkno; /* disk block number being added */
ufs_daddr_t oldblkno; /* previous block number, 0 unless frag */
ufs2_daddr_t newblkno; /* disk block number being added */
ufs2_daddr_t oldblkno; /* previous block number, 0 unless frag */
long newsize; /* size of new block */
long oldsize; /* size of new block */
struct buf *bp; /* bp for allocated block */
@ -1457,9 +1460,11 @@ allocdirect_merge(adphead, newadp, oldadp)
newadp->ad_oldsize != oldadp->ad_newsize ||
newadp->ad_lbn >= NDADDR) {
FREE_LOCK(&lk);
panic("allocdirect_merge: old %d != new %d || lbn %ld >= %d",
newadp->ad_oldblkno, oldadp->ad_newblkno, newadp->ad_lbn,
NDADDR);
panic("%s %lld != new %lld || old size %ld != new %ld",
"allocdirect_merge: old blkno",
(intmax_t)newadp->ad_oldblkno,
(intmax_t)oldadp->ad_newblkno,
newadp->ad_oldsize, oldadp->ad_newsize);
}
newadp->ad_oldblkno = oldadp->ad_oldblkno;
newadp->ad_oldsize = oldadp->ad_oldsize;
@ -1504,7 +1509,7 @@ allocdirect_merge(adphead, newadp, oldadp)
static struct freefrag *
newfreefrag(ip, blkno, size)
struct inode *ip;
ufs_daddr_t blkno;
ufs2_daddr_t blkno;
long size;
{
struct freefrag *freefrag;
@ -1521,7 +1526,6 @@ newfreefrag(ip, blkno, size)
freefrag->ff_state = 0;
freefrag->ff_inum = ip->i_number;
freefrag->ff_mnt = ITOV(ip)->v_mount;
freefrag->ff_devvp = ip->i_devvp;
freefrag->ff_blkno = blkno;
freefrag->ff_fragsize = size;
return (freefrag);
@ -1535,9 +1539,10 @@ static void
handle_workitem_freefrag(freefrag)
struct freefrag *freefrag;
{
struct ufsmount *ump = VFSTOUFS(freefrag->ff_mnt);
ffs_blkfree(VFSTOUFS(freefrag->ff_mnt)->um_fs, freefrag->ff_devvp,
freefrag->ff_blkno, freefrag->ff_fragsize, freefrag->ff_inum);
ffs_blkfree(ump->um_fs, ump->um_devvp, freefrag->ff_blkno,
freefrag->ff_fragsize, freefrag->ff_inum);
FREE(freefrag, M_FREEFRAG);
}
@ -1573,8 +1578,8 @@ static struct allocindir *
newallocindir(ip, ptrno, newblkno, oldblkno)
struct inode *ip; /* inode for file being extended */
int ptrno; /* offset of pointer in indirect block */
ufs_daddr_t newblkno; /* disk block number being added */
ufs_daddr_t oldblkno; /* previous block number, 0 if none */
ufs2_daddr_t newblkno; /* disk block number being added */
ufs2_daddr_t oldblkno; /* previous block number, 0 if none */
{
struct allocindir *aip;
@ -1599,8 +1604,8 @@ softdep_setup_allocindir_page(ip, lbn, bp, ptrno, newblkno, oldblkno, nbp)
ufs_lbn_t lbn; /* allocated block number within file */
struct buf *bp; /* buffer with indirect blk referencing page */
int ptrno; /* offset of pointer in indirect block */
ufs_daddr_t newblkno; /* disk block number being added */
ufs_daddr_t oldblkno; /* previous block number, 0 if none */
ufs2_daddr_t newblkno; /* disk block number being added */
ufs2_daddr_t oldblkno; /* previous block number, 0 if none */
struct buf *nbp; /* buffer holding allocated page */
{
struct allocindir *aip;
@ -1631,7 +1636,7 @@ softdep_setup_allocindir_meta(nbp, ip, bp, ptrno, newblkno)
struct inode *ip; /* inode for file being extended */
struct buf *bp; /* indirect block referencing allocated block */
int ptrno; /* offset of pointer in indirect block */
ufs_daddr_t newblkno; /* disk block number being added */
ufs2_daddr_t newblkno; /* disk block number being added */
{
struct allocindir *aip;
@ -1658,7 +1663,7 @@ setup_allocindir_phase2(bp, ip, aip)
struct allocindir *oldaip;
struct freefrag *freefrag;
struct newblk *newblk;
ufs_daddr_t blkno;
ufs2_daddr_t blkno;
if (bp->b_lblkno >= 0)
panic("setup_allocindir_phase2: not indir blk");
@ -1719,8 +1724,12 @@ setup_allocindir_phase2(bp, ip, aip)
free_allocindir(oldaip, NULL);
}
LIST_INSERT_HEAD(&indirdep->ir_deplisthd, aip, ai_next);
((ufs_daddr_t *)indirdep->ir_savebp->b_data)
[aip->ai_offset] = aip->ai_oldblkno;
if (ip->i_ump->um_fstype == UFS1)
((ufs1_daddr_t *)indirdep->ir_savebp->b_data)
[aip->ai_offset] = aip->ai_oldblkno;
else
((ufs2_daddr_t *)indirdep->ir_savebp->b_data)
[aip->ai_offset] = aip->ai_oldblkno;
FREE_LOCK(&lk);
if (freefrag != NULL)
handle_workitem_freefrag(freefrag);
@ -1736,6 +1745,8 @@ setup_allocindir_phase2(bp, ip, aip)
M_INDIRDEP, M_SOFTDEP_FLAGS);
newindirdep->ir_list.wk_type = D_INDIRDEP;
newindirdep->ir_state = ATTACHED;
if (ip->i_ump->um_fstype == UFS1)
newindirdep->ir_state |= UFS1FMT;
LIST_INIT(&newindirdep->ir_deplisthd);
LIST_INIT(&newindirdep->ir_donehd);
if (bp->b_blkno == bp->b_lblkno) {
@ -1803,17 +1814,18 @@ softdep_setup_freeblocks(ip, length)
freeblks->fb_mnt = ITOV(ip)->v_mount;
freeblks->fb_oldsize = ip->i_size;
freeblks->fb_newsize = length;
freeblks->fb_chkcnt = ip->i_blocks;
freeblks->fb_chkcnt = DIP(ip, i_blocks);
for (i = 0; i < NDADDR; i++) {
freeblks->fb_dblks[i] = ip->i_db[i];
ip->i_db[i] = 0;
freeblks->fb_dblks[i] = DIP(ip, i_db[i]);
DIP(ip, i_db[i]) = 0;
}
for (i = 0; i < NIADDR; i++) {
freeblks->fb_iblks[i] = ip->i_ib[i];
ip->i_ib[i] = 0;
freeblks->fb_iblks[i] = DIP(ip, i_ib[i]);
DIP(ip, i_ib[i]) = 0;
}
ip->i_blocks = 0;
DIP(ip, i_blocks) = 0;
ip->i_size = 0;
DIP(ip, i_size) = 0;
/*
* If the file was removed, then the space being freed was
* accounted for then (see softdep_filereleased()). If the
@ -1832,8 +1844,12 @@ softdep_setup_freeblocks(ip, length)
brelse(bp);
softdep_error("softdep_setup_freeblocks", error);
}
*((struct dinode *)bp->b_data + ino_to_fsbo(fs, ip->i_number)) =
ip->i_din;
if (ip->i_ump->um_fstype == UFS1)
*((struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1;
else
*((struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
/*
* Find and eliminate any inode dependencies.
*/
@ -2116,9 +2132,9 @@ free_newdirblk(newdirblk)
*/
void
softdep_freefile(pvp, ino, mode)
struct vnode *pvp;
ino_t ino;
int mode;
struct vnode *pvp;
ino_t ino;
int mode;
{
struct inode *ip = VTOI(pvp);
struct inodedep *inodedep;
@ -2188,9 +2204,9 @@ check_inode_unwritten(inodedep)
inodedep->id_buf = NULL;
if (inodedep->id_state & ONWORKLIST)
WORKLIST_REMOVE(&inodedep->id_list);
if (inodedep->id_savedino != NULL) {
FREE(inodedep->id_savedino, M_INODEDEP);
inodedep->id_savedino = NULL;
if (inodedep->id_savedino1 != NULL) {
FREE(inodedep->id_savedino1, M_INODEDEP);
inodedep->id_savedino1 = NULL;
}
if (free_inodedep(inodedep) == 0) {
FREE_LOCK(&lk);
@ -2214,7 +2230,7 @@ free_inodedep(inodedep)
LIST_FIRST(&inodedep->id_inowait) != NULL ||
TAILQ_FIRST(&inodedep->id_inoupdt) != NULL ||
TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL ||
inodedep->id_nlinkdelta != 0 || inodedep->id_savedino != NULL)
inodedep->id_nlinkdelta != 0 || inodedep->id_savedino1 != NULL)
return (0);
LIST_REMOVE(inodedep, id_hash);
WORKITEM_FREE(inodedep, D_INODEDEP);
@ -2237,10 +2253,9 @@ handle_workitem_freeblocks(freeblks, flags)
{
struct inode *ip;
struct vnode *vp;
ufs_daddr_t bn;
struct fs *fs;
int i, level, bsize;
long nblocks, blocksreleased = 0;
int i, nblocks, level, bsize;
ufs2_daddr_t bn, blocksreleased = 0;
int error, allerror = 0;
ufs_lbn_t baselbns[NIADDR], tmpval;
@ -2288,7 +2303,7 @@ handle_workitem_freeblocks(freeblks, flags)
VFS_VGET(freeblks->fb_mnt, freeblks->fb_previousinum,
(flags & LK_NOWAIT) | LK_EXCLUSIVE, &vp) == 0) {
ip = VTOI(vp);
ip->i_blocks += freeblks->fb_chkcnt - blocksreleased;
DIP(ip, i_blocks) += freeblks->fb_chkcnt - blocksreleased;
ip->i_flag |= IN_CHANGE;
vput(vp);
}
@ -2313,18 +2328,19 @@ handle_workitem_freeblocks(freeblks, flags)
static int
indir_trunc(freeblks, dbn, level, lbn, countp)
struct freeblks *freeblks;
ufs_daddr_t dbn;
ufs2_daddr_t dbn;
int level;
ufs_lbn_t lbn;
long *countp;
ufs2_daddr_t *countp;
{
struct buf *bp;
ufs_daddr_t *bap;
ufs_daddr_t nb;
struct fs *fs;
struct worklist *wk;
struct indirdep *indirdep;
int i, lbnadd, nblocks;
ufs1_daddr_t *bap1 = 0;
ufs2_daddr_t nb, *bap2 = 0;
ufs_lbn_t lbnadd;
int i, nblocks, ufs1fmt;
int error, allerror = 0;
fs = VFSTOUFS(freeblks->fb_mnt)->um_fs;
@ -2371,10 +2387,20 @@ indir_trunc(freeblks, dbn, level, lbn, countp)
/*
* Recursively free indirect blocks.
*/
bap = (ufs_daddr_t *)bp->b_data;
if (VFSTOUFS(freeblks->fb_mnt)->um_fstype == UFS1) {
ufs1fmt = 1;
bap1 = (ufs1_daddr_t *)bp->b_data;
} else {
ufs1fmt = 0;
bap2 = (ufs2_daddr_t *)bp->b_data;
}
nblocks = btodb(fs->fs_bsize);
for (i = NINDIR(fs) - 1; i >= 0; i--) {
if ((nb = bap[i]) == 0)
if (ufs1fmt)
nb = bap1[i];
else
nb = bap2[i];
if (nb == 0)
continue;
if (level != 0) {
if ((error = indir_trunc(freeblks, fsbtodb(fs, nb),
@ -2449,7 +2475,7 @@ softdep_setup_directory_add(bp, dp, diroffset, newinum, newdirbp, isnewblk)
struct buf *bp; /* buffer containing directory block */
struct inode *dp; /* inode for directory */
off_t diroffset; /* offset of new entry in directory */
long newinum; /* inode referenced by new directory entry */
ino_t newinum; /* inode referenced by new directory entry */
struct buf *newdirbp; /* non-NULL => contents of new mkdir */
int isnewblk; /* entry is in a newly allocated block */
{
@ -2868,7 +2894,7 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir)
struct buf *bp; /* buffer containing directory block */
struct inode *dp; /* inode for the directory being modified */
struct inode *ip; /* inode for directory entry being removed */
long newinum; /* new inode number for changed entry */
ino_t newinum; /* new inode number for changed entry */
int isrmdir; /* indicates if doing RMDIR */
{
int offset;
@ -3028,7 +3054,7 @@ softdep_releasefile(ip)
if ((inodedep_lookup(ip->i_fs, ip->i_number, 0, &inodedep)))
inodedep->id_state |= SPACECOUNTED;
FREE_LOCK(&lk);
ip->i_fs->fs_pendingblocks += ip->i_blocks;
ip->i_fs->fs_pendingblocks += DIP(ip, i_blocks);
ip->i_fs->fs_pendinginodes += 1;
ip->i_flag |= IN_SPACECOUNTED;
}
@ -3066,6 +3092,7 @@ handle_workitem_remove(dirrem, xp)
*/
if ((dirrem->dm_state & RMDIR) == 0) {
ip->i_nlink--;
DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
if (ip->i_nlink < ip->i_effnlink) {
FREE_LOCK(&lk);
@ -3086,6 +3113,7 @@ handle_workitem_remove(dirrem, xp)
* the parent decremented to account for the loss of "..".
*/
ip->i_nlink -= 2;
DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
if (ip->i_nlink < ip->i_effnlink) {
FREE_LOCK(&lk);
@ -3193,6 +3221,7 @@ softdep_disk_io_initiation(bp)
{
struct worklist *wk, *nextwk;
struct indirdep *indirdep;
struct inodedep *inodedep;
/*
* We only care about write operations. There should never
@ -3212,7 +3241,11 @@ softdep_disk_io_initiation(bp)
continue;
case D_INODEDEP:
initiate_write_inodeblock(WK_INODEDEP(wk), bp);
inodedep = WK_INODEDEP(wk);
if (inodedep->id_fs->fs_magic == FS_UFS1_MAGIC)
initiate_write_inodeblock_ufs1(inodedep, bp);
else
initiate_write_inodeblock_ufs2(inodedep, bp);
continue;
case D_INDIRDEP:
@ -3309,39 +3342,43 @@ initiate_write_filepage(pagedep, bp)
}
/*
* Version of initiate_write_inodeblock that handles UFS1 dinodes.
* Note that any bug fixes made to this routine must be done in the
* version found below.
*
* Called from within the procedure above to deal with unsatisfied
* allocation dependencies in an inodeblock. The buffer must be
* locked, thus, no I/O completion operations can occur while we
* are manipulating its associated dependencies.
*/
static void
initiate_write_inodeblock(inodedep, bp)
initiate_write_inodeblock_ufs1(inodedep, bp)
struct inodedep *inodedep;
struct buf *bp; /* The inode block */
{
struct allocdirect *adp, *lastadp;
struct dinode *dp;
struct ufs1_dinode *dp;
struct fs *fs;
ufs_lbn_t prevlbn = 0;
int i, deplist;
ufs_lbn_t i, prevlbn = 0;
int deplist;
if (inodedep->id_state & IOSTARTED)
panic("initiate_write_inodeblock: already started");
panic("initiate_write_inodeblock_ufs1: already started");
inodedep->id_state |= IOSTARTED;
fs = inodedep->id_fs;
dp = (struct dinode *)bp->b_data +
dp = (struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, inodedep->id_ino);
/*
* If the bitmap is not yet written, then the allocated
* inode cannot be written to disk.
*/
if ((inodedep->id_state & DEPCOMPLETE) == 0) {
if (inodedep->id_savedino != NULL)
panic("initiate_write_inodeblock: already doing I/O");
MALLOC(inodedep->id_savedino, struct dinode *,
sizeof(struct dinode), M_INODEDEP, M_SOFTDEP_FLAGS);
*inodedep->id_savedino = *dp;
bzero((caddr_t)dp, sizeof(struct dinode));
if (inodedep->id_savedino1 != NULL)
panic("initiate_write_inodeblock_ufs1: I/O underway");
MALLOC(inodedep->id_savedino1, struct ufs1_dinode *,
sizeof(struct ufs1_dinode), M_INODEDEP, M_SOFTDEP_FLAGS);
*inodedep->id_savedino1 = *dp;
bzero((caddr_t)dp, sizeof(struct ufs1_dinode));
return;
}
/*
@ -3365,16 +3402,172 @@ initiate_write_inodeblock(inodedep, bp)
if (adp->ad_lbn < NDADDR &&
dp->di_db[adp->ad_lbn] != adp->ad_newblkno) {
FREE_LOCK(&lk);
panic("%s: direct pointer #%ld mismatch %d != %d",
"softdep_write_inodeblock", adp->ad_lbn,
dp->di_db[adp->ad_lbn], adp->ad_newblkno);
panic("%s: direct pointer #%lld mismatch %d != %lld",
"softdep_write_inodeblock",
(intmax_t)adp->ad_lbn,
dp->di_db[adp->ad_lbn],
(intmax_t)adp->ad_newblkno);
}
if (adp->ad_lbn >= NDADDR &&
dp->di_ib[adp->ad_lbn - NDADDR] != adp->ad_newblkno) {
FREE_LOCK(&lk);
panic("%s: indirect pointer #%ld mismatch %d != %d",
"softdep_write_inodeblock", adp->ad_lbn - NDADDR,
dp->di_ib[adp->ad_lbn - NDADDR], adp->ad_newblkno);
panic("%s: indirect pointer #%lld mismatch %d != %lld",
"softdep_write_inodeblock",
(intmax_t)adp->ad_lbn - NDADDR,
dp->di_ib[adp->ad_lbn - NDADDR],
(intmax_t)adp->ad_newblkno);
}
deplist |= 1 << adp->ad_lbn;
if ((adp->ad_state & ATTACHED) == 0) {
FREE_LOCK(&lk);
panic("softdep_write_inodeblock: Unknown state 0x%x",
adp->ad_state);
}
#endif /* DIAGNOSTIC */
adp->ad_state &= ~ATTACHED;
adp->ad_state |= UNDONE;
}
/*
* The on-disk inode cannot claim to be any larger than the last
* fragment that has been written. Otherwise, the on-disk inode
* might have fragments that were not the last block in the file
* which would corrupt the filesystem.
*/
for (lastadp = NULL, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
lastadp = adp, adp = TAILQ_NEXT(adp, ad_next)) {
if (adp->ad_lbn >= NDADDR)
break;
dp->di_db[adp->ad_lbn] = adp->ad_oldblkno;
/* keep going until hitting a rollback to a frag */
if (adp->ad_oldsize == 0 || adp->ad_oldsize == fs->fs_bsize)
continue;
dp->di_size = fs->fs_bsize * adp->ad_lbn + adp->ad_oldsize;
for (i = adp->ad_lbn + 1; i < NDADDR; i++) {
#ifdef DIAGNOSTIC
if (dp->di_db[i] != 0 && (deplist & (1 << i)) == 0) {
FREE_LOCK(&lk);
panic("softdep_write_inodeblock: lost dep1");
}
#endif /* DIAGNOSTIC */
dp->di_db[i] = 0;
}
for (i = 0; i < NIADDR; i++) {
#ifdef DIAGNOSTIC
if (dp->di_ib[i] != 0 &&
(deplist & ((1 << NDADDR) << i)) == 0) {
FREE_LOCK(&lk);
panic("softdep_write_inodeblock: lost dep2");
}
#endif /* DIAGNOSTIC */
dp->di_ib[i] = 0;
}
FREE_LOCK(&lk);
return;
}
/*
* If we have zero'ed out the last allocated block of the file,
* roll back the size to the last currently allocated block.
* We know that this last allocated block is a full-sized as
* we already checked for fragments in the loop above.
*/
if (lastadp != NULL &&
dp->di_size <= (lastadp->ad_lbn + 1) * fs->fs_bsize) {
for (i = lastadp->ad_lbn; i >= 0; i--)
if (dp->di_db[i] != 0)
break;
dp->di_size = (i + 1) * fs->fs_bsize;
}
/*
* The only dependencies are for indirect blocks.
*
* The file size for indirect block additions is not guaranteed.
* Such a guarantee would be non-trivial to achieve. The conventional
* synchronous write implementation also does not make this guarantee.
* Fsck should catch and fix discrepancies. Arguably, the file size
* can be over-estimated without destroying integrity when the file
* moves into the indirect blocks (i.e., is large). If we want to
* postpone fsck, we are stuck with this argument.
*/
for (; adp; adp = TAILQ_NEXT(adp, ad_next))
dp->di_ib[adp->ad_lbn - NDADDR] = 0;
FREE_LOCK(&lk);
}
/*
* Version of initiate_write_inodeblock that handles UFS2 dinodes.
* Note that any bug fixes made to this routine must be done in the
* version found above.
*
* Called from within the procedure above to deal with unsatisfied
* allocation dependencies in an inodeblock. The buffer must be
* locked, thus, no I/O completion operations can occur while we
* are manipulating its associated dependencies.
*/
static void
initiate_write_inodeblock_ufs2(inodedep, bp)
struct inodedep *inodedep;
struct buf *bp; /* The inode block */
{
struct allocdirect *adp, *lastadp;
struct ufs2_dinode *dp;
struct fs *fs;
ufs_lbn_t i, prevlbn = 0;
int deplist;
if (inodedep->id_state & IOSTARTED)
panic("initiate_write_inodeblock_ufs2: already started");
inodedep->id_state |= IOSTARTED;
fs = inodedep->id_fs;
dp = (struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, inodedep->id_ino);
/*
* If the bitmap is not yet written, then the allocated
* inode cannot be written to disk.
*/
if ((inodedep->id_state & DEPCOMPLETE) == 0) {
if (inodedep->id_savedino2 != NULL)
panic("initiate_write_inodeblock_ufs2: I/O underway");
MALLOC(inodedep->id_savedino2, struct ufs2_dinode *,
sizeof(struct ufs2_dinode), M_INODEDEP, M_SOFTDEP_FLAGS);
*inodedep->id_savedino2 = *dp;
bzero((caddr_t)dp, sizeof(struct ufs2_dinode));
return;
}
/*
* If no dependencies, then there is nothing to roll back.
*/
inodedep->id_savedsize = dp->di_size;
if (TAILQ_FIRST(&inodedep->id_inoupdt) == NULL)
return;
/*
* Set the dependencies to busy.
*/
ACQUIRE_LOCK(&lk);
for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
adp = TAILQ_NEXT(adp, ad_next)) {
#ifdef DIAGNOSTIC
if (deplist != 0 && prevlbn >= adp->ad_lbn) {
FREE_LOCK(&lk);
panic("softdep_write_inodeblock: lbn order");
}
prevlbn = adp->ad_lbn;
if (adp->ad_lbn < NDADDR &&
dp->di_db[adp->ad_lbn] != adp->ad_newblkno) {
FREE_LOCK(&lk);
panic("%s: direct pointer #%lld mismatch %lld != %lld",
"softdep_write_inodeblock",
(intmax_t)adp->ad_lbn,
(intmax_t)dp->di_db[adp->ad_lbn],
(intmax_t)adp->ad_newblkno);
}
if (adp->ad_lbn >= NDADDR &&
dp->di_ib[adp->ad_lbn - NDADDR] != adp->ad_newblkno) {
FREE_LOCK(&lk);
panic("%s indirect pointer #%lld mismatch %lld != %lld",
"softdep_write_inodeblock:",
(intmax_t)adp->ad_lbn - NDADDR,
(intmax_t)dp->di_ib[adp->ad_lbn - NDADDR],
(intmax_t)adp->ad_newblkno);
}
deplist |= 1 << adp->ad_lbn;
if ((adp->ad_state & ATTACHED) == 0) {
@ -3683,8 +3876,12 @@ handle_allocindir_partdone(aip)
LIST_INSERT_HEAD(&indirdep->ir_donehd, aip, ai_next);
return;
}
((ufs_daddr_t *)indirdep->ir_savebp->b_data)[aip->ai_offset] =
aip->ai_newblkno;
if (indirdep->ir_state & UFS1FMT)
((ufs1_daddr_t *)indirdep->ir_savebp->b_data)[aip->ai_offset] =
aip->ai_newblkno;
else
((ufs2_daddr_t *)indirdep->ir_savebp->b_data)[aip->ai_offset] =
aip->ai_newblkno;
LIST_REMOVE(aip, ai_next);
if (aip->ai_freefrag != NULL)
add_to_worklist(&aip->ai_freefrag->ff_list);
@ -3704,8 +3901,9 @@ handle_written_inodeblock(inodedep, bp)
{
struct worklist *wk, *filefree;
struct allocdirect *adp, *nextadp;
struct dinode *dp;
int hadchanges;
struct ufs1_dinode *dp1 = NULL;
struct ufs2_dinode *dp2 = NULL;
int hadchanges, fstype;
if ((inodedep->id_state & IOSTARTED) == 0) {
lk.lkt_held = NOHOLDER;
@ -3713,8 +3911,15 @@ handle_written_inodeblock(inodedep, bp)
}
inodedep->id_state &= ~IOSTARTED;
inodedep->id_state |= COMPLETE;
dp = (struct dinode *)bp->b_data +
ino_to_fsbo(inodedep->id_fs, inodedep->id_ino);
if (inodedep->id_fs->fs_magic == FS_UFS1_MAGIC) {
fstype = UFS1;
dp1 = (struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(inodedep->id_fs, inodedep->id_ino);
} else {
fstype = UFS2;
dp2 = (struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(inodedep->id_fs, inodedep->id_ino);
}
/*
* If we had to rollback the inode allocation because of
* bitmaps being incomplete, then simply restore it.
@ -3722,10 +3927,13 @@ handle_written_inodeblock(inodedep, bp)
* all associated dependencies have been cleared and the
* corresponding updates written to disk.
*/
if (inodedep->id_savedino != NULL) {
*dp = *inodedep->id_savedino;
FREE(inodedep->id_savedino, M_INODEDEP);
inodedep->id_savedino = NULL;
if (inodedep->id_savedino1 != NULL) {
if (fstype == UFS1)
*dp1 = *inodedep->id_savedino1;
else
*dp2 = *inodedep->id_savedino2;
FREE(inodedep->id_savedino1, M_INODEDEP);
inodedep->id_savedino1 = NULL;
if ((bp->b_flags & B_DELWRI) == 0)
stat_inode_bitmap++;
bdirty(bp);
@ -3742,24 +3950,55 @@ handle_written_inodeblock(inodedep, bp)
lk.lkt_held = NOHOLDER;
panic("handle_written_inodeblock: new entry");
}
if (adp->ad_lbn < NDADDR) {
if (dp->di_db[adp->ad_lbn] != adp->ad_oldblkno) {
lk.lkt_held = NOHOLDER;
panic("%s: %s #%ld mismatch %d != %d",
"handle_written_inodeblock",
"direct pointer", adp->ad_lbn,
dp->di_db[adp->ad_lbn], adp->ad_oldblkno);
if (fstype == UFS1) {
if (adp->ad_lbn < NDADDR) {
if (dp1->di_db[adp->ad_lbn]!=adp->ad_oldblkno) {
lk.lkt_held = NOHOLDER;
panic("%s %s #%lld mismatch %d != %lld",
"handle_written_inodeblock:",
"direct pointer",
(intmax_t)adp->ad_lbn,
dp1->di_db[adp->ad_lbn],
(intmax_t)adp->ad_oldblkno);
}
dp1->di_db[adp->ad_lbn] = adp->ad_newblkno;
} else {
if (dp1->di_ib[adp->ad_lbn - NDADDR] != 0) {
lk.lkt_held = NOHOLDER;
panic("%s: %s #%lld allocated as %d",
"handle_written_inodeblock",
"indirect pointer",
(intmax_t)adp->ad_lbn - NDADDR,
dp1->di_ib[adp->ad_lbn - NDADDR]);
}
dp1->di_ib[adp->ad_lbn - NDADDR] =
adp->ad_newblkno;
}
dp->di_db[adp->ad_lbn] = adp->ad_newblkno;
} else {
if (dp->di_ib[adp->ad_lbn - NDADDR] != 0) {
lk.lkt_held = NOHOLDER;
panic("%s: %s #%ld allocated as %d",
"handle_written_inodeblock",
"indirect pointer", adp->ad_lbn - NDADDR,
dp->di_ib[adp->ad_lbn - NDADDR]);
if (adp->ad_lbn < NDADDR) {
if (dp2->di_db[adp->ad_lbn]!=adp->ad_oldblkno) {
lk.lkt_held = NOHOLDER;
panic("%s: %s #%lld %s %lld != %lld",
"handle_written_inodeblock",
"direct pointer",
(intmax_t)adp->ad_lbn, "mismatch",
(intmax_t)dp2->di_db[adp->ad_lbn],
(intmax_t)adp->ad_oldblkno);
}
dp2->di_db[adp->ad_lbn] = adp->ad_newblkno;
} else {
if (dp2->di_ib[adp->ad_lbn - NDADDR] != 0) {
lk.lkt_held = NOHOLDER;
panic("%s: %s #%lld allocated as %lld",
"handle_written_inodeblock",
"indirect pointer",
(intmax_t)adp->ad_lbn - NDADDR,
(intmax_t)
dp2->di_ib[adp->ad_lbn - NDADDR]);
}
dp2->di_ib[adp->ad_lbn - NDADDR] =
adp->ad_newblkno;
}
dp->di_ib[adp->ad_lbn - NDADDR] = adp->ad_newblkno;
}
adp->ad_state &= ~UNDONE;
adp->ad_state |= ATTACHED;
@ -3774,9 +4013,16 @@ handle_written_inodeblock(inodedep, bp)
lk.lkt_held = NOHOLDER;
panic("handle_written_inodeblock: bad size");
}
if (dp->di_size != inodedep->id_savedsize) {
dp->di_size = inodedep->id_savedsize;
hadchanges = 1;
if (fstype == UFS1) {
if (dp1->di_size != inodedep->id_savedsize) {
dp1->di_size = inodedep->id_savedsize;
hadchanges = 1;
}
} else {
if (dp2->di_size != inodedep->id_savedsize) {
dp2->di_size = inodedep->id_savedsize;
hadchanges = 1;
}
}
inodedep->id_savedsize = -1;
/*
@ -4859,7 +5105,8 @@ softdep_request_cleanup(fs, vp)
struct fs *fs;
struct vnode *vp;
{
long starttime, needed;
long starttime;
ufs2_daddr_t needed;
needed = fs->fs_cstotal.cs_nbfree + fs->fs_contigsumsize;
starttime = time_second + tickdelay;

View File

@ -96,7 +96,7 @@ void
softdep_setup_blkmapdep(bp, fs, newblkno)
struct buf *bp;
struct fs *fs;
ufs_daddr_t newblkno;
ufs2_daddr_t newblkno;
{
panic("softdep_setup_blkmapdep called");
@ -106,8 +106,8 @@ void
softdep_setup_allocdirect(ip, lbn, newblkno, oldblkno, newsize, oldsize, bp)
struct inode *ip;
ufs_lbn_t lbn;
ufs_daddr_t newblkno;
ufs_daddr_t oldblkno;
ufs2_daddr_t newblkno;
ufs2_daddr_t oldblkno;
long newsize;
long oldsize;
struct buf *bp;
@ -122,8 +122,8 @@ softdep_setup_allocindir_page(ip, lbn, bp, ptrno, newblkno, oldblkno, nbp)
ufs_lbn_t lbn;
struct buf *bp;
int ptrno;
ufs_daddr_t newblkno;
ufs_daddr_t oldblkno;
ufs2_daddr_t newblkno;
ufs2_daddr_t oldblkno;
struct buf *nbp;
{
@ -136,7 +136,7 @@ softdep_setup_allocindir_meta(nbp, ip, bp, ptrno, newblkno)
struct inode *ip;
struct buf *bp;
int ptrno;
ufs_daddr_t newblkno;
ufs2_daddr_t newblkno;
{
panic("softdep_setup_allocindir_meta called");

View File

@ -35,15 +35,18 @@
*/
#include <sys/param.h>
#include <ufs/ffs/fs.h>
#ifndef _KERNEL
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#else
#include "opt_ddb.h"
#include <sys/systm.h>
#include <sys/stdint.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/bio.h>
#include <sys/buf.h>
@ -51,7 +54,11 @@
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/extattr.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ffs/ffs_extern.h>
#include <ufs/ffs/fs.h>
#ifdef DDB
void ffs_checkoverlap(struct buf *, struct inode *);
@ -72,7 +79,7 @@ ffs_blkatoff(vp, offset, res, bpp)
struct inode *ip;
struct fs *fs;
struct buf *bp;
ufs_daddr_t lbn;
ufs_lbn_t lbn;
int bsize, error;
ip = VTOI(vp);
@ -91,7 +98,49 @@ ffs_blkatoff(vp, offset, res, bpp)
*bpp = bp;
return (0);
}
#endif
/*
* Load up the contents of an inode and copy the appropriate pieces
* to the incore copy.
*/
void
ffs_load_inode(bp, ip, mtype, fs, ino)
struct buf *bp;
struct inode *ip;
struct malloc_type *mtype;
struct fs *fs;
ino_t ino;
{
if (ip->i_ump->um_fstype == UFS1) {
if (mtype != NULL)
MALLOC(ip->i_din1, struct ufs1_dinode *,
sizeof(struct ufs1_dinode), mtype, M_WAITOK);
*ip->i_din1 =
*((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
ip->i_mode = ip->i_din1->di_mode;
ip->i_nlink = ip->i_din1->di_nlink;
ip->i_size = ip->i_din1->di_size;
ip->i_flags = ip->i_din1->di_flags;
ip->i_gen = ip->i_din1->di_gen;
ip->i_uid = ip->i_din1->di_uid;
ip->i_gid = ip->i_din1->di_gid;
} else {
if (mtype != NULL)
MALLOC(ip->i_din2, struct ufs2_dinode *,
sizeof(struct ufs2_dinode), mtype, M_WAITOK);
*ip->i_din2 =
*((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
ip->i_mode = ip->i_din2->di_mode;
ip->i_nlink = ip->i_din2->di_nlink;
ip->i_size = ip->i_din2->di_size;
ip->i_flags = ip->i_din2->di_flags;
ip->i_gen = ip->i_din2->di_gen;
ip->i_uid = ip->i_din2->di_uid;
ip->i_gid = ip->i_din2->di_gid;
}
}
#endif /* KERNEL */
/*
* Update the frsum fields to reflect addition or deletion
@ -135,7 +184,7 @@ ffs_checkoverlap(bp, ip)
struct inode *ip;
{
struct buf *ebp, *ep;
ufs_daddr_t start, last;
ufs2_daddr_t start, last;
struct vnode *vp;
ebp = &buf[nbuf];
@ -151,9 +200,9 @@ ffs_checkoverlap(bp, ip)
ep->b_blkno + btodb(ep->b_bcount) <= start)
continue;
vprint("Disk overlap", vp);
(void)printf("\tstart %lu, end %lu overlap start %lu, end %lu\n",
(u_long)start, (u_long)last, (u_long)ep->b_blkno,
(u_long)(ep->b_blkno + btodb(ep->b_bcount) - 1));
printf("\tstart %llu, end %llu overlap start %llu, end %llu\n",
(intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno,
(intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1));
panic("ffs_checkoverlap: Disk buffer overlap");
}
}
@ -168,7 +217,7 @@ int
ffs_isblock(fs, cp, h)
struct fs *fs;
unsigned char *cp;
ufs_daddr_t h;
ufs1_daddr_t h;
{
unsigned char mask;
@ -197,7 +246,7 @@ int
ffs_isfreeblock(fs, cp, h)
struct fs *fs;
unsigned char *cp;
ufs_daddr_t h;
ufs1_daddr_t h;
{
switch ((int)fs->fs_frag) {
@ -222,7 +271,7 @@ void
ffs_clrblock(fs, cp, h)
struct fs *fs;
u_char *cp;
ufs_daddr_t h;
ufs1_daddr_t h;
{
switch ((int)fs->fs_frag) {
@ -250,7 +299,7 @@ void
ffs_setblock(fs, cp, h)
struct fs *fs;
unsigned char *cp;
ufs_daddr_t h;
ufs1_daddr_t h;
{
switch ((int)fs->fs_frag) {

View File

@ -35,6 +35,7 @@
*/
#include <sys/param.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
/*

View File

@ -39,6 +39,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/stdint.h>
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/kernel.h>
@ -67,8 +68,10 @@
static MALLOC_DEFINE(M_FFSNODE, "FFS node", "FFS vnode private part");
static int ffs_sbupdate(struct ufsmount *, int);
int ffs_reload(struct mount *,struct ucred *,struct thread *);
static int ffs_oldfscompat(struct fs *);
int ffs_reload(struct mount *,struct ucred *,struct thread *);
static void ffs_oldfscompat_read(struct fs *, struct ufsmount *,
ufs2_daddr_t);
static void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
static int ffs_init(struct vfsconf *);
static struct vfsops ufs_vfsops = {
@ -139,8 +142,8 @@ ffs_mount(mp, path, data, ndp, td)
struct nameidata *ndp; /* mount point credentials*/
struct thread *td; /* process requesting mount*/
{
size_t size;
struct vnode *devvp;
size_t size;
struct vnode *devvp;
struct ufs_args args;
struct ufsmount *ump = 0;
struct fs *fs;
@ -201,8 +204,9 @@ ffs_mount(mp, path, data, ndp, td)
}
if (fs->fs_pendingblocks != 0 ||
fs->fs_pendinginodes != 0) {
printf("%s: update error: blocks %d files %d\n",
fs->fs_fsmnt, fs->fs_pendingblocks,
printf("%s: %s: blocks %lld files %d\n",
fs->fs_fsmnt, "update error",
(intmax_t)fs->fs_pendingblocks,
fs->fs_pendinginodes);
fs->fs_pendingblocks = 0;
fs->fs_pendinginodes = 0;
@ -384,9 +388,9 @@ ffs_reload(mp, cred, td)
struct buf *bp;
struct fs *fs, *newfs;
dev_t dev;
ufs2_daddr_t sblockloc;
int i, blks, size, error;
int32_t *lp;
u_int sectorsize;
if ((mp->mnt_flag & MNT_RDONLY) == 0)
return (EINVAL);
@ -416,20 +420,18 @@ ffs_reload(mp, cred, td)
/*
* Step 2: re-read superblock from disk.
*/
if (VOP_IOCTL(devvp, DIOCGSECTORSIZE, (caddr_t)&sectorsize,
FREAD, NOCRED, td) != 0)
size = DEV_BSIZE;
else
size = sectorsize;
if ((error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) != 0)
fs = VFSTOUFS(mp)->um_fs;
if ((error = bread(devvp, fsbtodb(fs, fs->fs_sblockloc), fs->fs_sbsize,
NOCRED, &bp)) != 0)
return (error);
newfs = (struct fs *)bp->b_data;
if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
newfs->fs_bsize < sizeof(struct fs)) {
if ((newfs->fs_magic != FS_UFS1_MAGIC &&
newfs->fs_magic != FS_UFS2_MAGIC) ||
newfs->fs_bsize > MAXBSIZE ||
newfs->fs_bsize < sizeof(struct fs)) {
brelse(bp);
return (EIO); /* XXX needs translation */
}
fs = VFSTOUFS(mp)->um_fs;
/*
* Copy pointer fields back into superblock before copying in XXX
* new superblock. These should really be in the ufsmount. XXX
@ -439,20 +441,15 @@ ffs_reload(mp, cred, td)
newfs->fs_maxcluster = fs->fs_maxcluster;
newfs->fs_contigdirs = fs->fs_contigdirs;
newfs->fs_active = fs->fs_active;
sblockloc = fs->fs_sblockloc;
bcopy(newfs, fs, (u_int)fs->fs_sbsize);
if (fs->fs_sbsize < SBSIZE)
bp->b_flags |= B_INVAL | B_NOCACHE;
brelse(bp);
mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
ffs_oldfscompat(fs);
/* An old fsck may have zeroed these fields, so recheck them. */
if (fs->fs_avgfilesize <= 0) /* XXX */
fs->fs_avgfilesize = AVFILESIZ; /* XXX */
if (fs->fs_avgfpdir <= 0) /* XXX */
fs->fs_avgfpdir = AFPDIR; /* XXX */
ffs_oldfscompat_read(fs, VFSTOUFS(mp), sblockloc);
if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
printf("%s: reload pending error: blocks %d files %d\n",
fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes);
printf("%s: reload pending error: blocks %lld files %d\n",
fs->fs_fsmnt, (intmax_t)fs->fs_pendingblocks,
fs->fs_pendinginodes);
fs->fs_pendingblocks = 0;
fs->fs_pendinginodes = 0;
}
@ -517,8 +514,7 @@ ffs_reload(mp, cred, td)
vput(vp);
return (error);
}
ip->i_din = *((struct dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number));
ffs_load_inode(bp, ip, NULL, fs, ip->i_number);
ip->i_effnlink = ip->i_nlink;
brelse(bp);
vput(vp);
@ -528,9 +524,10 @@ ffs_reload(mp, cred, td)
return (0);
}
#include <sys/sysctl.h>
int bigcgs = 0;
SYSCTL_INT(_debug, OID_AUTO, bigcgs, CTLFLAG_RW, &bigcgs, 0, "");
/*
* Possible superblock locations ordered from most to least likely.
*/
static int sblock_try[] = SBLOCKSEARCH;
/*
* Common code for mount and mountroot
@ -547,10 +544,10 @@ ffs_mountfs(devvp, mp, td, malloctype)
struct fs *fs;
dev_t dev;
void *space;
ufs2_daddr_t sblockloc;
int error, i, blks, size, ronly;
int32_t *lp;
struct ucred *cred;
u_int64_t maxfilesize; /* XXX */
size_t strsize;
int ncount;
u_int sectorsize;
@ -617,15 +614,32 @@ ffs_mountfs(devvp, mp, td, malloctype)
bp = NULL;
ump = NULL;
if ((error = bread(devvp, SBLOCK, SBSIZE, cred, &bp)) != 0)
goto out;
fs = (struct fs *)bp->b_data;
if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
fs->fs_bsize < sizeof(struct fs)) {
fs = NULL;
sblockloc = 0;
/*
* Try reading the superblock in each of its possible locations.
*/
for (i = 0; sblock_try[i] != -1; i++) {
if ((error = bread(devvp, sblock_try[i] / size, SBLOCKSIZE,
cred, &bp)) != 0)
goto out;
fs = (struct fs *)bp->b_data;
sblockloc = numfrags(fs, sblock_try[i]);
if ((fs->fs_magic == FS_UFS1_MAGIC ||
(fs->fs_magic == FS_UFS2_MAGIC &&
fs->fs_sblockloc == sblockloc)) &&
fs->fs_bsize <= MAXBSIZE &&
fs->fs_bsize >= sizeof(struct fs))
break;
brelse(bp);
bp = NULL;
}
if (sblock_try[i] == -1) {
error = EINVAL; /* XXX needs translation */
goto out;
}
fs->fs_fmod = 0;
fs->fs_flags &= ~FS_INDEXDIRS; /* no support for directory indicies */
fs->fs_flags &= ~FS_UNCLEAN;
if (fs->fs_clean == 0) {
fs->fs_flags |= FS_UNCLEAN;
@ -642,40 +656,45 @@ ffs_mountfs(devvp, mp, td, malloctype)
error = EPERM;
goto out;
}
if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
printf("%s: lost blocks %d files %d\n", fs->fs_fsmnt,
fs->fs_pendingblocks, fs->fs_pendinginodes);
if ((fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) &&
(mp->mnt_flag & MNT_FORCE)) {
printf("%s: lost blocks %lld files %d\n", fs->fs_fsmnt,
(intmax_t)fs->fs_pendingblocks,
fs->fs_pendinginodes);
fs->fs_pendingblocks = 0;
fs->fs_pendinginodes = 0;
}
}
if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
printf("%s: mount pending error: blocks %d files %d\n",
fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes);
printf("%s: mount pending error: blocks %lld files %d\n",
fs->fs_fsmnt, (intmax_t)fs->fs_pendingblocks,
fs->fs_pendinginodes);
fs->fs_pendingblocks = 0;
fs->fs_pendinginodes = 0;
}
/* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
error = EROFS; /* needs translation */
goto out;
}
ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK | M_ZERO);
ump->um_malloctype = malloctype;
ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
M_WAITOK);
if (fs->fs_magic == FS_UFS1_MAGIC) {
ump->um_fstype = UFS1;
ump->um_balloc = ffs_balloc_ufs1;
} else {
ump->um_fstype = UFS2;
ump->um_balloc = ffs_balloc_ufs2;
}
ump->um_blkatoff = ffs_blkatoff;
ump->um_truncate = ffs_truncate;
ump->um_update = ffs_update;
ump->um_valloc = ffs_valloc;
ump->um_vfree = ffs_vfree;
ump->um_balloc = ffs_balloc;
bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
if (fs->fs_sbsize < SBSIZE)
if (fs->fs_sbsize < SBLOCKSIZE)
bp->b_flags |= B_INVAL | B_NOCACHE;
brelse(bp);
bp = NULL;
fs = ump->um_fs;
ffs_oldfscompat_read(fs, ump, sblockloc);
fs->fs_ronly = ronly;
size = fs->fs_cssize;
blks = howmany(size, fs->fs_fsize);
@ -708,11 +727,6 @@ ffs_mountfs(devvp, mp, td, malloctype)
fs->fs_contigdirs = (u_int8_t *)space;
bzero(fs->fs_contigdirs, size);
fs->fs_active = NULL;
/* Compatibility for old filesystems XXX */
if (fs->fs_avgfilesize <= 0) /* XXX */
fs->fs_avgfilesize = AVFILESIZ; /* XXX */
if (fs->fs_avgfpdir <= 0) /* XXX */
fs->fs_avgfpdir = AFPDIR; /* XXX */
mp->mnt_data = (qaddr_t)ump;
mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0];
mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
@ -733,7 +747,6 @@ ffs_mountfs(devvp, mp, td, malloctype)
ufs_extattr_uepm_init(&ump->um_extattr);
#endif
devvp->v_rdev->si_mountpoint = mp;
ffs_oldfscompat(fs);
/*
* Set FS local "last mounted on" information (NULL pad)
@ -753,15 +766,6 @@ ffs_mountfs(devvp, mp, td, malloctype)
mp->mnt_time = fs->fs_time;
}
ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */
if (fs->fs_maxfilesize > maxfilesize) /* XXX */
fs->fs_maxfilesize = maxfilesize; /* XXX */
if (bigcgs) {
if (fs->fs_sparecon[0] <= 0)
fs->fs_sparecon[0] = fs->fs_cgsize;
fs->fs_cgsize = fs->fs_bsize;
}
if (ronly == 0) {
if ((fs->fs_flags & FS_DOSOFTDEP) &&
(error = softdep_mount(devvp, mp, fs, cred)) != 0) {
@ -808,36 +812,90 @@ ffs_mountfs(devvp, mp, td, malloctype)
return (error);
}
#include <sys/sysctl.h>
int bigcgs = 0;
SYSCTL_INT(_debug, OID_AUTO, bigcgs, CTLFLAG_RW, &bigcgs, 0, "");
/*
* Sanity checks for old filesystems.
* Sanity checks for loading old filesystem superblocks.
* See ffs_oldfscompat_write below for unwound actions.
*
* XXX - goes away some day.
* XXX - Parts get retired eventually.
* Unfortunately new bits get added.
*/
static int
ffs_oldfscompat(fs)
static void
ffs_oldfscompat_read(fs, ump, sblockloc)
struct fs *fs;
struct ufsmount *ump;
ufs2_daddr_t sblockloc;
{
off_t maxfilesize;
/*
* If not yet done, update UFS1 superblock with new wider fields.
*/
if (fs->fs_magic == FS_UFS1_MAGIC &&
fs->fs_sblockloc != sblockloc) {
fs->fs_maxbsize = fs->fs_bsize;
fs->fs_sblockloc = sblockloc;
fs->fs_time = fs->fs_old_time;
fs->fs_size = fs->fs_old_size;
fs->fs_dsize = fs->fs_old_dsize;
fs->fs_csaddr = fs->fs_old_csaddr;
fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir;
fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree;
fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree;
fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree;
}
if (fs->fs_magic == FS_UFS1_MAGIC &&
fs->fs_old_inodefmt < FS_44INODEFMT) {
fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
fs->fs_qbmask = ~fs->fs_bmask;
fs->fs_qfmask = ~fs->fs_fmask;
}
ump->um_savedmaxfilesize = fs->fs_maxfilesize;
maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1;
if (fs->fs_maxfilesize > maxfilesize)
fs->fs_maxfilesize = maxfilesize;
/* Compatibility for old filesystems */
if (fs->fs_avgfilesize <= 0)
fs->fs_avgfilesize = AVFILESIZ;
if (fs->fs_avgfpdir <= 0)
fs->fs_avgfpdir = AFPDIR;
if (bigcgs) {
fs->fs_save_cgsize = fs->fs_cgsize;
fs->fs_cgsize = fs->fs_bsize;
}
}
/*
* Unwinding superblock updates for old filesystems.
* See ffs_oldfscompat_read above for details.
*
* XXX - Parts get retired eventually.
* Unfortunately new bits get added.
*/
static void
ffs_oldfscompat_write(fs, ump)
struct fs *fs;
struct ufsmount *ump;
{
fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
fs->fs_nrpos = 8; /* XXX */
if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
#if 0
int i; /* XXX */
u_int64_t sizepb = fs->fs_bsize; /* XXX */
/* XXX */
fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
for (i = 0; i < NIADDR; i++) { /* XXX */
sizepb *= NINDIR(fs); /* XXX */
fs->fs_maxfilesize += sizepb; /* XXX */
} /* XXX */
#endif
fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
} /* XXX */
return (0);
/*
* Copy back UFS2 updated fields that UFS1 inspects.
*/
if (fs->fs_magic == FS_UFS1_MAGIC) {
fs->fs_old_time = fs->fs_time;
fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
}
fs->fs_maxfilesize = ump->um_savedmaxfilesize;
if (bigcgs) {
fs->fs_cgsize = fs->fs_save_cgsize;
fs->fs_save_cgsize = 0;
}
}
/*
@ -874,13 +932,10 @@ ffs_unmount(mp, mntflags, td)
return (error);
}
fs = ump->um_fs;
if (bigcgs) {
fs->fs_cgsize = fs->fs_sparecon[0];
fs->fs_sparecon[0] = 0;
}
if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
printf("%s: unmount pending error: blocks %d files %d\n",
fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes);
printf("%s: unmount pending error: blocks %lld files %d\n",
fs->fs_fsmnt, (intmax_t)fs->fs_pendingblocks,
fs->fs_pendinginodes);
fs->fs_pendingblocks = 0;
fs->fs_pendinginodes = 0;
}
@ -980,7 +1035,7 @@ ffs_statfs(mp, sbp, td)
ump = VFSTOUFS(mp);
fs = ump->um_fs;
if (fs->fs_magic != FS_MAGIC)
if (fs->fs_magic != FS_UFS1_MAGIC && fs->fs_magic != FS_UFS2_MAGIC)
panic("ffs_statfs");
sbp->f_bsize = fs->fs_fsize;
sbp->f_iosize = fs->fs_bsize;
@ -1173,6 +1228,7 @@ ffs_vget(mp, ino, flags, vpp)
lockinit(vp->v_vnlock, PINOD, "inode", VLKTIMEOUT, LK_CANRECURSE);
vp->v_data = ip;
ip->i_vnode = vp;
ip->i_ump = ump;
ip->i_fs = fs = ump->um_fs;
ip->i_dev = dev;
ip->i_number = ino;
@ -1222,7 +1278,7 @@ ffs_vget(mp, ino, flags, vpp)
*vpp = NULL;
return (error);
}
ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
ffs_load_inode(bp, ip, ump->um_malloctype, fs, ino);
if (DOINGSOFTDEP(vp))
softdep_load_inodeblock(ip);
else
@ -1250,16 +1306,19 @@ ffs_vget(mp, ino, flags, vpp)
*/
if (ip->i_gen == 0) {
ip->i_gen = random() / 2 + 1;
if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
ip->i_flag |= IN_MODIFIED;
DIP(ip, i_gen) = ip->i_gen;
}
}
/*
* Ensure that uid and gid are correct. This is a temporary
* fix until fsck has been changed to do the update.
*/
if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
ip->i_uid = ip->i_din.di_ouid; /* XXX */
ip->i_gid = ip->i_din.di_ogid; /* XXX */
if (fs->fs_magic == FS_UFS1_MAGIC && /* XXX */
fs->fs_old_inodefmt < FS_44INODEFMT) { /* XXX */
ip->i_uid = ip->i_din1->di_ouid; /* XXX */
ip->i_gid = ip->i_din1->di_ogid; /* XXX */
} /* XXX */
*vpp = vp;
@ -1333,7 +1392,7 @@ ffs_sbupdate(mp, waitfor)
struct ufsmount *mp;
int waitfor;
{
struct fs *dfs, *fs = mp->um_fs;
struct fs *fs = mp->um_fs;
struct buf *bp;
int blks;
void *space;
@ -1364,24 +1423,12 @@ ffs_sbupdate(mp, waitfor)
*/
if (allerror)
return (allerror);
bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_sblockloc),
(int)fs->fs_sbsize, 0, 0);
fs->fs_fmod = 0;
fs->fs_time = time_second;
bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
/* Restore compatibility to old filesystems. XXX */
dfs = (struct fs *)bp->b_data; /* XXX */
if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
dfs->fs_nrpos = -1; /* XXX */
if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
int32_t *lp, tmp; /* XXX */
/* XXX */
lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
tmp = lp[4]; /* XXX */
for (i = 4; i > 0; i--) /* XXX */
lp[i] = lp[i-1]; /* XXX */
lp[0] = tmp; /* XXX */
} /* XXX */
dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
ffs_oldfscompat_write((struct fs *)bp->b_data, mp);
if (waitfor != MNT_WAIT)
bawrite(bp);
else if ((error = bwrite(bp)) != 0)

View File

@ -126,7 +126,7 @@ ffs_fsync(ap)
struct buf *bp;
struct buf *nbp;
int s, error, wait, passes, skipmeta;
daddr_t lbn;
ufs_lbn_t lbn;
wait = (ap->a_waitfor == MNT_WAIT);
if (vn_isdisk(vp, NULL)) {

View File

@ -58,14 +58,30 @@
* The beginning of cylinder group cg in fs, is given by
* the ``cgbase(fs, cg)'' macro.
*
* The size and offset of the super-block in sector-size neutral bytes.
* Depending on the architecture and the media, the superblock may
* reside in any one of four places. For tiny media where every block
* counts, it is placed at the very front of the partition. Historically,
* UFS1 placed it 8K from the front to leave room for the disk label and
* a small bootstrap. For UFS2 it got moved to 64K from the front to leave
* room for the disk label and a bigger bootstrap, and for really piggy
* systems we check at 256K from the front if the first three fail. In
* all cases the size of the superblock will be SBLOCKSIZE. All values are
* given in byte-offset form, so they do not imply a sector size. The
* SBLOCKSEARCH specifies the order in which the locations should be searched.
*/
#define SBSIZE 8192
#define SBOFF ((off_t)(BBSIZE))
#define SBLOCK ((ufs_daddr_t)(SBOFF / DEV_BSIZE))
#define SBLOCK_FLOPPY 0
#define SBLOCK_UFS1 8192
#define SBLOCK_UFS2 65536
#define SBLOCK_PIGGY 262144
#define SBLOCKSIZE 8192
#define SBLOCKSEARCH \
{ SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 }
/* Max number of fragments per block, this is not tweakable */
/*
* Max number of fragments per block. This value is NOT tweakable.
*/
#define MAXFRAG 8
/*
* Addresses stored in inodes are capable of addressing fragments
* of `blocks'. File system blocks of at most size MAXBSIZE can
@ -176,8 +192,8 @@
* identify blocks that are in use by other snapshots (which are
* expunged from this snapshot).
*/
#define BLK_NOCOPY ((ufs_daddr_t)(1))
#define BLK_SNAP ((ufs_daddr_t)(2))
#define BLK_NOCOPY ((ufs2_daddr_t)(1))
#define BLK_SNAP ((ufs2_daddr_t)(2))
/*
* Sysctl values for the fast filesystem.
@ -193,12 +209,13 @@
/*
* Command structure passed in to the filesystem to adjust filesystem values.
*/
#define FFS_CMD_VERSION 0x05181979 /* version ID */
#define FFS_CMD_VERSION 0x19790518 /* version ID */
struct fsck_cmd {
int version; /* version of command structure */
int handle; /* reference to filesystem to be changed */
off_t value; /* inode or block number to be affected */
long size; /* amount or range to be adjusted */
int32_t version; /* version of command structure */
int32_t handle; /* reference to filesystem to be changed */
int64_t value; /* inode or block number to be affected */
int64_t size; /* amount or range to be adjusted */
int64_t spare; /* reserved for future use */
};
/*
@ -213,6 +230,14 @@ struct csum {
int32_t cs_nifree; /* number of free inodes */
int32_t cs_nffree; /* number of free frags */
};
struct csum_total {
int64_t cs_ndir; /* number of directories */
int64_t cs_nbfree; /* number of free blocks */
int64_t cs_nifree; /* number of free inodes */
int64_t cs_nffree; /* number of free frags */
int64_t cs_numclusters; /* number of free clusters */
int64_t cs_spare[3]; /* future expansion */
};
/*
* Super block for an FFS filesystem.
@ -220,23 +245,23 @@ struct csum {
struct fs {
int32_t fs_firstfield; /* historic filesystem linked list, */
int32_t fs_unused_1; /* used for incore super blocks */
ufs_daddr_t fs_sblkno; /* addr of super-block in filesys */
ufs_daddr_t fs_cblkno; /* offset of cyl-block in filesys */
ufs_daddr_t fs_iblkno; /* offset of inode-blocks in filesys */
ufs_daddr_t fs_dblkno; /* offset of first data after cg */
int32_t fs_cgoffset; /* cylinder group offset in cylinder */
int32_t fs_cgmask; /* used to calc mod fs_ntrak */
ufs_time_t fs_time; /* last time written */
int32_t fs_size; /* number of blocks in fs */
int32_t fs_dsize; /* number of data blocks in fs */
int32_t fs_sblkno; /* offset of super-block in filesys */
int32_t fs_cblkno; /* offset of cyl-block in filesys */
int32_t fs_iblkno; /* offset of inode-blocks in filesys */
int32_t fs_dblkno; /* offset of first data after cg */
int32_t fs_old_cgoffset; /* cylinder group offset in cylinder */
int32_t fs_old_cgmask; /* used to calc mod fs_ntrak */
int32_t fs_old_time; /* last time written */
int32_t fs_old_size; /* number of blocks in fs */
int32_t fs_old_dsize; /* number of data blocks in fs */
int32_t fs_ncg; /* number of cylinder groups */
int32_t fs_bsize; /* size of basic blocks in fs */
int32_t fs_fsize; /* size of frag blocks in fs */
int32_t fs_frag; /* number of frags in a block in fs */
/* these are configuration parameters */
int32_t fs_minfree; /* minimum percentage of free blocks */
int32_t fs_rotdelay; /* num of ms for optimal next block */
int32_t fs_rps; /* disk revolutions per second */
int32_t fs_old_rotdelay; /* num of ms for optimal next block */
int32_t fs_old_rps; /* disk revolutions per second */
/* these fields can be computed from the others */
int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */
int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */
@ -249,35 +274,30 @@ struct fs {
int32_t fs_fragshift; /* block to frag shift */
int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
int32_t fs_sbsize; /* actual size of super block */
int32_t fs_csmask; /* csum block offset (now unused) */
int32_t fs_csshift; /* csum block number (now unused) */
int32_t fs_spare1[2]; /* old fs_csmask */
/* old fs_csshift */
int32_t fs_nindir; /* value of NINDIR */
int32_t fs_inopb; /* value of INOPB */
int32_t fs_nspf; /* value of NSPF */
int32_t fs_old_nspf; /* value of NSPF */
/* yet another configuration parameter */
int32_t fs_optim; /* optimization preference, see below */
/* these fields are derived from the hardware */
int32_t fs_npsect; /* # sectors/track including spares */
int32_t fs_interleave; /* hardware sector interleave */
int32_t fs_trackskew; /* sector 0 skew, per track */
/* fs_id takes the space of the unused fs_headswitch and fs_trkseek fields */
int32_t fs_old_npsect; /* # sectors/track including spares */
int32_t fs_old_interleave; /* hardware sector interleave */
int32_t fs_old_trackskew; /* sector 0 skew, per track */
int32_t fs_id[2]; /* unique filesystem id */
/* sizes determined by number of cylinder groups and their sizes */
ufs_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */
int32_t fs_old_csaddr; /* blk addr of cyl grp summary area */
int32_t fs_cssize; /* size of cyl grp summary area */
int32_t fs_cgsize; /* cylinder group size */
/* these fields are derived from the hardware */
int32_t fs_ntrak; /* tracks per cylinder */
int32_t fs_nsect; /* sectors per track */
int32_t fs_spc; /* sectors per cylinder */
/* this comes from the disk driver partitioning */
int32_t fs_ncyl; /* cylinders in filesystem */
/* these fields can be computed from the others */
int32_t fs_cpg; /* cylinders per group */
int32_t fs_ipg; /* inodes per group */
int32_t fs_fpg; /* blocks per group * fs_frag */
int32_t fs_spare2; /* old fs_ntrak */
int32_t fs_old_nsect; /* sectors per track */
int32_t fs_old_spc; /* sectors per cylinder */
int32_t fs_old_ncyl; /* cylinders in filesystem */
int32_t fs_old_cpg; /* cylinders per group */
int32_t fs_ipg; /* inodes per group */
int32_t fs_fpg; /* blocks per group * fs_frag */
/* this data must be re-computed after crashes */
struct csum fs_cstotal; /* cylinder summary information */
struct csum fs_old_cstotal; /* cylinder summary information */
/* these fields are cleared at mount time */
int8_t fs_fmod; /* super block modified flag */
int8_t fs_clean; /* filesystem is clean flag */
@ -288,37 +308,44 @@ struct fs {
int32_t fs_cgrotor; /* last cg searched */
void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */
u_int8_t *fs_contigdirs; /* # of contiguously allocated dirs */
struct csum *fs_csp; /* cg summary info buffer for fs_cs */
struct csum *fs_csp; /* cg summary info buffer for fs_cs */
int32_t *fs_maxcluster; /* max cluster in each cyl group */
u_int *fs_active; /* used by snapshots to track fs */
int32_t fs_cpc; /* cyl per cycle in postbl */
int16_t fs_opostbl[16][8]; /* old rotation block list head */
int32_t fs_old_cpc; /* cyl per cycle in postbl */
int32_t fs_maxbsize; /* maximum blocking factor permitted */
int64_t fs_sparecon64[17]; /* old rotation block list head */
int64_t fs_sblockloc; /* location of standard superblock */
struct csum_total fs_cstotal; /* cylinder summary information */
ufs_time_t fs_time; /* last time written */
int64_t fs_size; /* number of blocks in fs */
int64_t fs_dsize; /* number of data blocks in fs */
ufs2_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */
int64_t fs_pendingblocks; /* blocks in process of being freed */
int32_t fs_pendinginodes; /* inodes in process of being freed */
int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */
int32_t fs_avgfilesize; /* expected average file size */
int32_t fs_avgfpdir; /* expected # of files per directory */
int32_t fs_sparecon[26]; /* reserved for future constants */
int32_t fs_pendingblocks; /* blocks in process of being freed */
int32_t fs_pendinginodes; /* inodes in process of being freed */
int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */
int32_t fs_sparecon32[27]; /* reserved for future constants */
int32_t fs_contigsumsize; /* size of cluster summary array */
int32_t fs_maxsymlinklen; /* max length of an internal symlink */
int32_t fs_inodefmt; /* format of on-disk inodes */
int32_t fs_old_inodefmt; /* format of on-disk inodes */
u_int64_t fs_maxfilesize; /* maximum representable file size */
int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */
int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */
int32_t fs_state; /* validate fs_clean field */
int32_t fs_postblformat; /* format of positional layout tables */
int32_t fs_nrpos; /* number of rotational positions */
int32_t fs_postbloff; /* (u_int16) rotation block list head */
int32_t fs_rotbloff; /* (u_int8) blocks for each rotation */
int32_t fs_old_postblformat; /* format of positional layout tables */
int32_t fs_old_nrpos; /* number of rotational positions */
int32_t fs_spare5[2]; /* old fs_postbloff */
/* old fs_rotbloff */
int32_t fs_magic; /* magic number */
u_int8_t fs_space[1]; /* list of blocks for each rotation */
/* actually longer */
};
/*
* Filesystem identification
*/
#define FS_MAGIC 0x011954 /* the fast filesystem magic number */
#define FS_UFS1_MAGIC 0x011954 /* UFS1 fast filesystem magic number */
#define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast filesystem magic number */
#define FS_OKAY 0x7c269d38 /* superblock checksum */
#define FS_42INODEFMT -1 /* 4.2BSD inode format */
#define FS_44INODEFMT 2 /* 4.4BSD inode format */
@ -332,6 +359,9 @@ struct fs {
/*
* Filesystem flags.
*
* The FS_UNCLEAN flag is set by the kernel when the filesystem was
* mounted with fs_clean set to zero. The FS_DOSOFTDEP flag indicates
* that the filesystem should be managed by the soft updates code.
* Note that the FS_NEEDSFSCK flag is set and cleared only by the
* fsck utility. It is set when background fsck finds an unexpected
* inconsistency which requires a traditional foreground fsck to be
@ -339,28 +369,16 @@ struct fs {
* disk error. A foreground fsck will clear the FS_NEEDSFSCK flag when
* it has successfully cleaned up the filesystem. The kernel uses this
* flag to enforce that inconsistent filesystems be mounted read-only.
* The FS_INDEXDIRS flag when set indicates that the kernel maintains
* on-disk auxiliary indexes (such as B-trees) for speeding directory
* accesses. Kernels that do not support auxiliary indicies clear the
* flag to indicate that the indicies need to be rebuilt (by fsck) before
* they can be used.
*/
#define FS_UNCLEAN 0x01 /* filesystem not clean at mount */
#define FS_DOSOFTDEP 0x02 /* filesystem using soft dependencies */
#define FS_NEEDSFSCK 0x04 /* filesystem needs sync fsck before mount */
/*
* Rotational layout table format types
*/
#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */
#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */
/*
* Macros for access to superblock array structures
*/
#define fs_postbl(fs, cylno) \
(((fs)->fs_postblformat == FS_42POSTBLFMT) \
? ((fs)->fs_opostbl[cylno]) \
: ((int16_t *)((u_int8_t *)(fs) + \
(fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos))
#define fs_rotbl(fs) \
(((fs)->fs_postblformat == FS_42POSTBLFMT) \
? ((fs)->fs_space) \
: ((u_int8_t *)((u_int8_t *)(fs) + (fs)->fs_rotbloff)))
#define FS_INDEXDIRS 0x08 /* kernel supports indexed directories */
/*
* Macros to access bits in the fs_active array.
@ -376,13 +394,18 @@ struct fs {
*/
#define CGSIZE(fs) \
/* base cg */ (sizeof(struct cg) + sizeof(int32_t) + \
/* blktot size */ (fs)->fs_cpg * sizeof(int32_t) + \
/* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(int16_t) + \
/* old btotoff */ (fs)->fs_old_cpg * sizeof(int32_t) + \
/* old boff */ (fs)->fs_old_cpg * sizeof(u_int16_t) + \
/* inode map */ howmany((fs)->fs_ipg, NBBY) + \
/* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY) +\
/* block map */ howmany((fs)->fs_fpg, NBBY) +\
/* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \
/* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \
/* cluster map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPB(fs), NBBY)))
/* cluster map */ howmany(fragstoblks(fs, (fs)->fs_fpg), NBBY)))
/*
* The minimal number of cylinder groups that should be created.
*/
#define MINCYLGRPS 4
/*
* Convert cylinder group to base address of its global summary info.
@ -396,25 +419,29 @@ struct fs {
struct cg {
int32_t cg_firstfield; /* historic cyl groups linked list */
int32_t cg_magic; /* magic number */
ufs_time_t cg_time; /* time last written */
int32_t cg_old_time; /* time last written */
int32_t cg_cgx; /* we are the cgx'th cylinder group */
int16_t cg_ncyl; /* number of cyl's this cg */
int16_t cg_niblk; /* number of inode blocks this cg */
int16_t cg_old_ncyl; /* number of cyl's this cg */
int16_t cg_old_niblk; /* number of inode blocks this cg */
int32_t cg_ndblk; /* number of data blocks this cg */
struct csum cg_cs; /* cylinder summary information */
int32_t cg_rotor; /* position of last used block */
int32_t cg_frotor; /* position of last used frag */
int32_t cg_irotor; /* position of last used inode */
int32_t cg_frsum[MAXFRAG]; /* counts of available frags */
int32_t cg_btotoff; /* (int32) block totals per cylinder */
int32_t cg_boff; /* (u_int16) free block positions */
int32_t cg_old_btotoff; /* (int32) block totals per cylinder */
int32_t cg_old_boff; /* (u_int16) free block positions */
int32_t cg_iusedoff; /* (u_int8) used inode map */
int32_t cg_freeoff; /* (u_int8) free block map */
int32_t cg_nextfreeoff; /* (u_int8) next available space */
int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */
int32_t cg_clusteroff; /* (u_int8) free cluster map */
int32_t cg_nclusterblks; /* number of clusters this cg */
int32_t cg_sparecon[13]; /* reserved for future use */
int32_t cg_niblk; /* number of inode blocks this cg */
int32_t cg_initediblk; /* last initialized inode */
int32_t cg_sparecon32[3]; /* reserved for future use */
ufs_time_t cg_time; /* time last written */
int64_t cg_sparecon64[3]; /* reserved for future use */
u_int8_t cg_space[1]; /* space for cylinder group maps */
/* actually longer */
};
@ -422,55 +449,16 @@ struct cg {
/*
* Macros for access to cylinder group array structures
*/
#define cg_blktot(cgp) \
(((cgp)->cg_magic != CG_MAGIC) \
? (((struct ocg *)(cgp))->cg_btot) \
: ((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_btotoff)))
#define cg_blks(fs, cgp, cylno) \
(((cgp)->cg_magic != CG_MAGIC) \
? (((struct ocg *)(cgp))->cg_b[cylno]) \
: ((int16_t *)((u_int8_t *)(cgp) + \
(cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos))
#define cg_chkmagic(cgp) ((cgp)->cg_magic == CG_MAGIC)
#define cg_inosused(cgp) \
(((cgp)->cg_magic != CG_MAGIC) \
? (((struct ocg *)(cgp))->cg_iused) \
: ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_iusedoff)))
((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_iusedoff))
#define cg_blksfree(cgp) \
(((cgp)->cg_magic != CG_MAGIC) \
? (((struct ocg *)(cgp))->cg_free) \
: ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_freeoff)))
#define cg_chkmagic(cgp) \
((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC)
((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_freeoff))
#define cg_clustersfree(cgp) \
((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_clusteroff))
#define cg_clustersum(cgp) \
((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_clustersumoff))
/*
* The following structure is defined
* for compatibility with old filesystems.
*/
struct ocg {
int32_t cg_firstfield; /* historic linked list of cyl groups */
int32_t cg_unused_1; /* used for incore cyl groups */
ufs_time_t cg_time; /* time last written */
int32_t cg_cgx; /* we are the cgx'th cylinder group */
int16_t cg_ncyl; /* number of cyl's this cg */
int16_t cg_niblk; /* number of inode blocks this cg */
int32_t cg_ndblk; /* number of data blocks this cg */
struct csum cg_cs; /* cylinder summary information */
int32_t cg_rotor; /* position of last used block */
int32_t cg_frotor; /* position of last used frag */
int32_t cg_irotor; /* position of last used inode */
int32_t cg_frsum[8]; /* counts of available frags */
int32_t cg_btot[32]; /* block totals per cylinder */
int16_t cg_b[32][8]; /* positions of free blocks */
u_int8_t cg_iused[256]; /* used inode map */
int32_t cg_magic; /* magic number */
u_int8_t cg_free[1]; /* free block map */
/* actually longer */
};
/*
* Turn filesystem block numbers into disk block addresses.
* This maps filesystem blocks to device size blocks.
@ -482,13 +470,14 @@ struct ocg {
* Cylinder group macros to locate things in cylinder groups.
* They calc filesystem addresses of cylinder group data structures.
*/
#define cgbase(fs, c) ((ufs_daddr_t)((fs)->fs_fpg * (c)))
#define cgbase(fs, c) ((ufs2_daddr_t)((fs)->fs_fpg * (c)))
#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */
#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */
#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */
#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */
#define cgstart(fs, c) \
(cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask)))
((fs)->fs_magic == FS_UFS2_MAGIC ? cgbase(fs, c) : \
(cgbase(fs, c) + (fs)->fs_old_cgoffset * ((c) & ~((fs)->fs_old_cgmask))))
/*
* Macros for handling inode numbers:
@ -498,7 +487,7 @@ struct ocg {
*/
#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg)
#define ino_to_fsba(fs, x) \
((ufs_daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \
((ufs2_daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \
(blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs))))))
#define ino_to_fsbo(fs, x) ((x) % INOPB(fs))
@ -515,12 +504,6 @@ struct ocg {
*/
#define blkmap(fs, map, loc) \
(((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag)))
#define cbtocylno(fs, bno) \
((bno) * NSPF(fs) / (fs)->fs_spc)
#define cbtorpos(fs, bno) \
(((bno) * NSPF(fs) % (fs)->fs_spc / (fs)->fs_nsect * (fs)->fs_trackskew + \
(bno) * NSPF(fs) % (fs)->fs_spc % (fs)->fs_nsect * (fs)->fs_interleave) % \
(fs)->fs_nsect * (fs)->fs_nrpos / (fs)->fs_npsect)
/*
* The following macros optimize certain frequently calculated
@ -531,6 +514,8 @@ struct ocg {
((loc) & (fs)->fs_qbmask)
#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \
((loc) & (fs)->fs_qfmask)
#define lfragtosize(fs, frag) /* calculates ((off_t)frag * fs->fs_fsize) */ \
((off_t)(frag) << (fs)->fs_fshift)
#define lblktosize(fs, blk) /* calculates ((off_t)blk * fs->fs_bsize) */ \
((off_t)(blk) << (fs)->fs_bshift)
/* Use this only when `blk' is known to be small, e.g., < NDADDR. */
@ -569,24 +554,12 @@ struct ocg {
(((lbn) >= NDADDR || (ip)->i_size >= smalllblktosize(fs, (lbn) + 1)) \
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (ip)->i_size))))
#define dblksize(fs, dip, lbn) \
(((lbn) >= NDADDR || \
(dip)->di_size >= (u_int64_t)smalllblktosize(fs, (lbn) + 1)) \
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (dip)->di_size))))
#define sblksize(fs, size, lbn) \
(((lbn) >= NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (size)))))
/*
* Number of disk sectors per block/fragment; assumes DEV_BSIZE byte
* sector size.
*/
#define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift)
#define NSPF(fs) ((fs)->fs_nspf)
/*
* Number of inodes in a secondary storage block/fragment.
*/

View File

@ -86,8 +86,11 @@
* says that the files space has been accounted to the pending free
* space count. The NEWBLOCK flag marks pagedep structures that have
* just been allocated, so must be claimed by the inode before all
* dependencies are complete. The ONWORKLIST flag shows whether the
* structure is currently linked onto a worklist.
* dependencies are complete. The INPROGRESS flag marks worklist
* structures that are still on the worklist, but are being considered
* for action by some process. The UFS1FMT flag indicates that the
* inode being processed is a ufs1 format. The ONWORKLIST flag shows
* whether the structure is currently linked onto a worklist.
*/
#define ATTACHED 0x0001
#define UNDONE 0x0002
@ -102,6 +105,7 @@
#define SPACECOUNTED 0x0400 /* inodedep only */
#define NEWBLOCK 0x0800 /* pagedep only */
#define INPROGRESS 0x1000 /* dirrem, freeblks, freefrag, freefile only */
#define UFS1FMT 0x2000 /* indirdep only */
#define ONWORKLIST 0x8000
#define ALLCOMPLETE (ATTACHED | COMPLETE | DEPCOMPLETE)
@ -177,7 +181,7 @@ TAILQ_HEAD(allocdirectlst, allocdirect);
* list, any removed operations are done, and the dependency structure
* is freed.
*/
#define DAHASHSZ 6
#define DAHASHSZ 5
#define DIRADDHASH(offset) (((offset) >> 2) % DAHASHSZ)
struct pagedep {
struct worklist pd_list; /* page buffer */
@ -245,7 +249,6 @@ struct inodedep {
struct fs *id_fs; /* associated filesystem */
ino_t id_ino; /* dependent inode */
nlink_t id_nlinkdelta; /* saved effective link count */
struct dinode *id_savedino; /* saved dinode contents */
LIST_ENTRY(inodedep) id_deps; /* bmsafemap's list of inodedep's */
struct buf *id_buf; /* related bmsafemap (if pending) */
off_t id_savedsize; /* file size saved during rollback */
@ -254,7 +257,13 @@ struct inodedep {
struct workhead id_inowait; /* operations waiting inode update */
struct allocdirectlst id_inoupdt; /* updates before inode written */
struct allocdirectlst id_newinoupdt; /* updates when inode written */
union {
struct ufs1_dinode *idu_savedino1; /* saved ufs1_dinode contents */
struct ufs2_dinode *idu_savedino2; /* saved ufs2_dinode contents */
} id_un;
};
#define id_savedino1 id_un.idu_savedino1
#define id_savedino2 id_un.idu_savedino2
/*
* A "newblk" structure is attached to a bmsafemap structure when a block
@ -267,8 +276,8 @@ struct inodedep {
struct newblk {
LIST_ENTRY(newblk) nb_hash; /* hashed lookup */
struct fs *nb_fs; /* associated filesystem */
ufs_daddr_t nb_newblkno; /* allocated block number */
int nb_state; /* state of bitmap dependency */
ufs2_daddr_t nb_newblkno; /* allocated block number */
LIST_ENTRY(newblk) nb_deps; /* bmsafemap's list of newblk's */
struct bmsafemap *nb_bmsafemap; /* associated bmsafemap */
};
@ -324,8 +333,8 @@ struct allocdirect {
# define ad_state ad_list.wk_state /* block pointer state */
TAILQ_ENTRY(allocdirect) ad_next; /* inodedep's list of allocdirect's */
ufs_lbn_t ad_lbn; /* block within file */
ufs_daddr_t ad_newblkno; /* new value of block pointer */
ufs_daddr_t ad_oldblkno; /* old value of block pointer */
ufs2_daddr_t ad_newblkno; /* new value of block pointer */
ufs2_daddr_t ad_oldblkno; /* old value of block pointer */
long ad_newsize; /* size of new block */
long ad_oldsize; /* size of old block */
LIST_ENTRY(allocdirect) ad_deps; /* bmsafemap's list of allocdirect's */
@ -379,8 +388,8 @@ struct allocindir {
# define ai_state ai_list.wk_state /* indirect block pointer state */
LIST_ENTRY(allocindir) ai_next; /* indirdep's list of allocindir's */
int ai_offset; /* pointer offset in indirect block */
ufs_daddr_t ai_newblkno; /* new block pointer value */
ufs_daddr_t ai_oldblkno; /* old block pointer value */
ufs2_daddr_t ai_newblkno; /* new block pointer value */
ufs2_daddr_t ai_oldblkno; /* old block pointer value */
struct freefrag *ai_freefrag; /* block to be freed when complete */
struct indirdep *ai_indirdep; /* address of associated indirdep */
LIST_ENTRY(allocindir) ai_deps; /* bmsafemap's list of allocindir's */
@ -400,9 +409,8 @@ struct allocindir {
struct freefrag {
struct worklist ff_list; /* id_inowait or delayed worklist */
# define ff_state ff_list.wk_state /* owning user; should be uid_t */
struct vnode *ff_devvp; /* filesystem device vnode */
struct mount *ff_mnt; /* associated mount point */
ufs_daddr_t ff_blkno; /* fragment physical block number */
ufs2_daddr_t ff_blkno; /* fragment physical block number */
long ff_fragsize; /* size of fragment being deleted */
ino_t ff_inum; /* owning inode number */
};
@ -416,14 +424,14 @@ struct freefrag {
struct freeblks {
struct worklist fb_list; /* id_inowait or delayed worklist */
ino_t fb_previousinum; /* inode of previous owner of blocks */
uid_t fb_uid; /* uid of previous owner of blocks */
struct vnode *fb_devvp; /* filesystem device vnode */
struct mount *fb_mnt; /* associated mount point */
off_t fb_oldsize; /* previous file size */
off_t fb_newsize; /* new file size */
int fb_chkcnt; /* used to check cnt of blks released */
uid_t fb_uid; /* uid of previous owner of blocks */
ufs_daddr_t fb_dblks[NDADDR]; /* direct blk ptrs to deallocate */
ufs_daddr_t fb_iblks[NIADDR]; /* indirect blk ptrs to deallocate */
ufs2_daddr_t fb_chkcnt; /* used to check cnt of blks released */
ufs2_daddr_t fb_dblks[NDADDR]; /* direct blk ptrs to deallocate */
ufs2_daddr_t fb_iblks[NIADDR]; /* indirect blk ptrs to deallocate */
};
/*

View File

@ -1,4 +1,13 @@
/*
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Marshall
* Kirk McKusick and Network Associates Laboratories, the Security
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
* research program
*
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
@ -15,18 +24,14 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* 3. The names of the authors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -40,7 +45,7 @@
*/
#ifndef _UFS_UFS_DINODE_H_
#define _UFS_UFS_DINODE_H_
#define _UFS_UFS_DINODE_H_
/*
* The root inode is the root of the filesystem. Inode 0 can't be used for
@ -59,51 +64,12 @@
#define WINO ((ino_t)1)
/*
* A dinode contains all the meta-data associated with a UFS file.
* This structure defines the on-disk format of a dinode. Since
* this structure describes an on-disk structure, all its fields
* are defined by types with precise widths.
* The size of physical and logical block numbers and time fields in UFS.
*/
/* typedef int32_t ufs_daddr_t; */
#define NDADDR 12 /* Direct addresses in inode. */
#define NIADDR 3 /* Indirect addresses in inode. */
struct dinode {
u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
int16_t di_nlink; /* 2: File link count. */
union {
u_int16_t oldids[2]; /* 4: Ffs: old user and group ids. */
} di_u;
u_int64_t di_size; /* 8: File byte count. */
int32_t di_atime; /* 16: Last access time. */
int32_t di_atimensec; /* 20: Last access time. */
int32_t di_mtime; /* 24: Last modified time. */
int32_t di_mtimensec; /* 28: Last modified time. */
int32_t di_ctime; /* 32: Last inode change time. */
int32_t di_ctimensec; /* 36: Last inode change time. */
ufs_daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */
ufs_daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */
u_int32_t di_flags; /* 100: Status flags (chflags). */
int32_t di_blocks; /* 104: Blocks actually held. */
int32_t di_gen; /* 108: Generation number. */
u_int32_t di_uid; /* 112: File owner. */
u_int32_t di_gid; /* 116: File group. */
int32_t di_spare[2]; /* 120: Reserved; currently unused */
};
/*
* The di_db fields may be overlaid with other information for
* file types that do not have associated disk storage. Block
* and character devices overlay the first data block with their
* dev_t value. Short symbolic links place their path in the
* di_db area.
*/
#define di_ogid di_u.oldids[1]
#define di_ouid di_u.oldids[0]
#define di_rdev di_db[0]
#define di_shortlink di_db
#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(ufs_daddr_t))
typedef int32_t ufs1_daddr_t;
typedef int64_t ufs2_daddr_t;
typedef int64_t ufs_lbn_t;
typedef int64_t ufs_time_t;
/* File permissions. */
#define IEXEC 0000100 /* Executable. */
@ -124,4 +90,81 @@ struct dinode {
#define IFSOCK 0140000 /* UNIX domain socket. */
#define IFWHT 0160000 /* Whiteout. */
#endif
/*
* A dinode contains all the meta-data associated with a UFS2 file.
* This structure defines the on-disk format of a dinode. Since
* this structure describes an on-disk structure, all its fields
* are defined by types with precise widths.
*/
#define NXADDR 2 /* External addresses in inode. */
#define NDADDR 12 /* Direct addresses in inode. */
#define NIADDR 3 /* Indirect addresses in inode. */
struct ufs2_dinode {
u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
int16_t di_nlink; /* 2: File link count. */
u_int32_t di_uid; /* 4: File owner. */
u_int32_t di_gid; /* 8: File group. */
u_int32_t di_blksize; /* 12: Inode blocksize. */
u_int64_t di_size; /* 16: File byte count. */
u_int64_t di_blocks; /* 24: Bytes actually held. */
ufs_time_t di_atime; /* 32: Last access time. */
ufs_time_t di_mtime; /* 40: Last modified time. */
ufs_time_t di_ctime; /* 48: Last inode change time. */
ufs_time_t di_createtime; /* 56: Last inode change time. */
int32_t di_mtimensec; /* 64: Last modified time. */
int32_t di_atimensec; /* 68: Last access time. */
int32_t di_ctimensec; /* 72: Last inode change time. */
int32_t di_creatensec; /* 76: Last inode change time. */
int32_t di_gen; /* 80: Generation number. */
u_int32_t di_kernflags; /* 84: Kernel flags. */
u_int32_t di_flags; /* 88: Status flags (chflags). */
int32_t di_extsize; /* 92: External attributes block. */
ufs2_daddr_t di_extb[NXADDR];/* 96: External attributes block. */
ufs2_daddr_t di_db[NDADDR]; /* 112: Direct disk blocks. */
ufs2_daddr_t di_ib[NIADDR]; /* 208: Indirect disk blocks. */
int64_t di_spare[3]; /* 232: Reserved; currently unused */
};
/*
* The di_db fields may be overlaid with other information for
* file types that do not have associated disk storage. Block
* and character devices overlay the first data block with their
* dev_t value. Short symbolic links place their path in the
* di_db area.
*/
#define di_rdev di_db[0]
/*
* A UFS1 dinode contains all the meta-data associated with a UFS1 file.
* This structure defines the on-disk format of a UFS1 dinode. Since
* this structure describes an on-disk structure, all its fields
* are defined by types with precise widths.
*/
struct ufs1_dinode {
u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
int16_t di_nlink; /* 2: File link count. */
union {
u_int16_t oldids[2]; /* 4: Ffs: old user and group ids. */
} di_u;
u_int64_t di_size; /* 8: File byte count. */
int32_t di_atime; /* 16: Last access time. */
int32_t di_atimensec; /* 20: Last access time. */
int32_t di_mtime; /* 24: Last modified time. */
int32_t di_mtimensec; /* 28: Last modified time. */
int32_t di_ctime; /* 32: Last inode change time. */
int32_t di_ctimensec; /* 36: Last inode change time. */
ufs1_daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */
ufs1_daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */
u_int32_t di_flags; /* 100: Status flags (chflags). */
int32_t di_blocks; /* 104: Blocks actually held. */
int32_t di_gen; /* 108: Generation number. */
u_int32_t di_uid; /* 112: File owner. */
u_int32_t di_gid; /* 116: File group. */
int32_t di_spare[2]; /* 120: Reserved; currently unused */
};
#define di_ogid di_u.oldids[1]
#define di_ouid di_u.oldids[0]
#endif /* _UFS_UFS_DINODE_H_ */

View File

@ -46,11 +46,6 @@
#include <sys/queue.h>
#include <ufs/ufs/dinode.h>
/*
* The size of a logical block number.
*/
typedef long ufs_lbn_t;
/*
* This must agree with the definition in <ufs/ufs/dir.h>.
*/
@ -69,6 +64,7 @@ struct inode {
LIST_ENTRY(inode) i_hash;/* Hash chain. */
TAILQ_ENTRY(inode) i_nextsnap; /* snapshot file list */
struct vnode *i_vnode;/* Vnode associated with this inode. */
struct ufsmount *i_ump;/* Ufsmount point associated with this inode. */
struct vnode *i_devvp;/* Vnode for block I/O. */
u_int32_t i_flag; /* flags, see below */
dev_t i_dev; /* Device associated with the inode. */
@ -91,31 +87,26 @@ struct inode {
struct dirhash *i_dirhash; /* Hashing for large directories */
/*
* The on-disk dinode itself.
* Copies from the on-disk dinode itself.
*/
struct dinode i_din; /* 128 bytes of the on-disk dinode. */
u_int16_t i_mode; /* IFMT, permissions; see below. */
int16_t i_nlink; /* File link count. */
u_int64_t i_size; /* File byte count. */
u_int32_t i_flags; /* Status flags (chflags). */
int64_t i_gen; /* Generation number. */
u_int32_t i_uid; /* File owner. */
u_int32_t i_gid; /* File group. */
/*
* The real copy of the on-disk inode.
*/
union {
struct ufs1_dinode *din1; /* UFS1 on-disk dinode. */
struct ufs2_dinode *din2; /* UFS2 on-disk dinode. */
} dinode_u;
};
#define i_atime i_din.di_atime
#define i_atimensec i_din.di_atimensec
#define i_blocks i_din.di_blocks
#define i_ctime i_din.di_ctime
#define i_ctimensec i_din.di_ctimensec
#define i_db i_din.di_db
#define i_flags i_din.di_flags
#define i_gen i_din.di_gen
#define i_gid i_din.di_gid
#define i_ib i_din.di_ib
#define i_mode i_din.di_mode
#define i_mtime i_din.di_mtime
#define i_mtimensec i_din.di_mtimensec
#define i_nlink i_din.di_nlink
#define i_rdev i_din.di_rdev
#define i_shortlink i_din.di_shortlink
#define i_size i_din.di_size
#define i_uid i_din.di_uid
/* These flags are kept in i_flag. */
/*
* These flags are kept in i_flag.
*/
#define IN_ACCESS 0x0001 /* Access time update request. */
#define IN_CHANGE 0x0002 /* Inode change time update request. */
#define IN_UPDATE 0x0004 /* Modification time update request. */
@ -125,13 +116,32 @@ struct inode {
#define IN_LAZYMOD 0x0040 /* Modified, but don't write yet. */
#define IN_SPACECOUNTED 0x0080 /* Blocks to be freed in free count. */
#define i_din1 dinode_u.din1
#define i_din2 dinode_u.din2
#ifdef _KERNEL
/*
* The DIP macro is used to access fields in the dinode that are
* not cached in the inode itself.
*/
#define DIP(ip, field) \
(((ip)->i_ump->um_fstype == UFS1) ? \
(ip)->i_din1->d##field : (ip)->i_din2->d##field)
#define MAXSYMLINKLEN(ip) \
((ip)->i_ump->um_fstype == UFS1) ? \
((NDADDR + NIADDR) * sizeof(ufs1_daddr_t)) : \
((NDADDR + NIADDR) * sizeof(ufs2_daddr_t))
#define SHORTLINK(ip) \
(((ip)->i_ump->um_fstype == UFS1) ? \
(caddr_t)(ip)->i_din1->di_db : (caddr_t)(ip)->i_din2->di_db)
/*
* Structure used to pass around logical block paths generated by
* ufs_getlbns and used by truncate and bmap code.
*/
struct indir {
ufs_daddr_t in_lbn; /* Logical block number. */
ufs2_daddr_t in_lbn; /* Logical block number. */
int in_off; /* Offset in buffer. */
int in_exists; /* Flag if the block exists. */
};

View File

@ -104,8 +104,8 @@ struct dqblk {
u_int32_t dqb_ihardlimit; /* maximum # allocated inodes + 1 */
u_int32_t dqb_isoftlimit; /* preferred inode limit */
u_int32_t dqb_curinodes; /* current # allocated inodes */
ufs_time_t dqb_btime; /* time limit for excessive disk use */
ufs_time_t dqb_itime; /* time limit for excessive files */
int32_t dqb_btime; /* time limit for excessive disk use */
int32_t dqb_itime; /* time limit for excessive files */
};
#ifdef _KERNEL
@ -178,8 +178,8 @@ struct thread;
struct ucred;
struct vnode;
int chkdq(struct inode *, long, struct ucred *, int);
int chkiq(struct inode *, long, struct ucred *, int);
int chkdq(struct inode *, int64_t, struct ucred *, int);
int chkiq(struct inode *, ino_t, struct ucred *, int);
void dqinit(void);
void dqrele(struct vnode *, struct dquot *);
int getinoquota(struct inode *);

View File

@ -191,6 +191,7 @@ ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip,
ip->i_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
ip->i_mode |= acl_posix1e_perms_to_mode(acl_user_obj,
acl_group_obj, acl_other);
DIP(ip, i_mode) = ip->i_mode;
} else {
/*
* Use the ACL_MASK entry.
@ -198,8 +199,10 @@ ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip,
ip->i_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
ip->i_mode |= acl_posix1e_perms_to_mode(acl_user_obj,
acl_mask, acl_other);
DIP(ip, i_mode) = ip->i_mode;
}
ip->i_mode |= preserve_mode;
DIP(ip, i_mode) = ip->i_mode;
}
/*

View File

@ -71,7 +71,7 @@ ufs_bmap(ap)
int *a_runb;
} */ *ap;
{
ufs_daddr_t blkno;
ufs2_daddr_t blkno;
int error;
/*
@ -106,8 +106,8 @@ ufs_bmap(ap)
int
ufs_bmaparray(vp, bn, bnp, runp, runb)
struct vnode *vp;
ufs_daddr_t bn;
ufs_daddr_t *bnp;
ufs2_daddr_t bn;
ufs2_daddr_t *bnp;
int *runp;
int *runb;
{
@ -117,8 +117,8 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
struct mount *mp;
struct vnode *devvp;
struct indir a[NIADDR+1], *ap;
ufs_daddr_t daddr;
long metalbn;
ufs2_daddr_t daddr;
ufs_lbn_t metalbn;
int error, num, maxrun = 0;
int *nump;
@ -146,7 +146,7 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
num = *nump;
if (num == 0) {
*bnp = blkptrtodb(ump, ip->i_db[bn]);
*bnp = blkptrtodb(ump, DIP(ip, i_db[bn]));
/*
* Since this is FFS independent code, we are out of
* scope for the definitions of BLK_NOCOPY and
@ -155,8 +155,8 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
* return a request for a zeroed out buffer if attempts
* are made to read a BLK_NOCOPY or BLK_SNAP block.
*/
if ((ip->i_flags & SF_SNAPSHOT) &&
ip->i_db[bn] > 0 && ip->i_db[bn] < ump->um_seqinc) {
if ((ip->i_flags & SF_SNAPSHOT) && DIP(ip, i_db[bn]) > 0 &&
DIP(ip, i_db[bn]) < ump->um_seqinc) {
*bnp = -1;
} else if (*bnp == 0) {
if (ip->i_flags & SF_SNAPSHOT)
@ -164,15 +164,16 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
else
*bnp = -1;
} else if (runp) {
daddr_t bnb = bn;
ufs2_daddr_t bnb = bn;
for (++bn; bn < NDADDR && *runp < maxrun &&
is_sequential(ump, ip->i_db[bn - 1], ip->i_db[bn]);
is_sequential(ump, DIP(ip, i_db[bn - 1]),
DIP(ip, i_db[bn]));
++bn, ++*runp);
bn = bnb;
if (runb && (bn > 0)) {
for (--bn; (bn >= 0) && (*runb < maxrun) &&
is_sequential(ump, ip->i_db[bn],
ip->i_db[bn+1]);
is_sequential(ump, DIP(ip, i_db[bn]),
DIP(ip, i_db[bn+1]));
--bn, ++*runb);
}
}
@ -181,7 +182,7 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
/* Get disk address out of indirect block array */
daddr = ip->i_ib[ap->in_off];
daddr = DIP(ip, i_ib[ap->in_off]);
for (bp = NULL, ++ap; --num; ++ap) {
/*
@ -221,21 +222,41 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
}
}
daddr = ((ufs_daddr_t *)bp->b_data)[ap->in_off];
if (ip->i_ump->um_fstype == UFS1) {
daddr = ((ufs1_daddr_t *)bp->b_data)[ap->in_off];
if (num == 1 && daddr && runp) {
for (bn = ap->in_off + 1;
bn < MNINDIR(ump) && *runp < maxrun &&
is_sequential(ump,
((ufs1_daddr_t *)bp->b_data)[bn - 1],
((ufs1_daddr_t *)bp->b_data)[bn]);
++bn, ++*runp);
bn = ap->in_off;
if (runb && bn) {
for (--bn; bn >= 0 && *runb < maxrun &&
is_sequential(ump,
((ufs1_daddr_t *)bp->b_data)[bn],
((ufs1_daddr_t *)bp->b_data)[bn+1]);
--bn, ++*runb);
}
}
continue;
}
daddr = ((ufs2_daddr_t *)bp->b_data)[ap->in_off];
if (num == 1 && daddr && runp) {
for (bn = ap->in_off + 1;
bn < MNINDIR(ump) && *runp < maxrun &&
is_sequential(ump,
((ufs_daddr_t *)bp->b_data)[bn - 1],
((ufs_daddr_t *)bp->b_data)[bn]);
((ufs2_daddr_t *)bp->b_data)[bn - 1],
((ufs2_daddr_t *)bp->b_data)[bn]);
++bn, ++*runp);
bn = ap->in_off;
if (runb && bn) {
for(--bn; bn >= 0 && *runb < maxrun &&
is_sequential(ump,
((ufs_daddr_t *)bp->b_data)[bn],
((ufs_daddr_t *)bp->b_data)[bn+1]);
--bn, ++*runb);
for (--bn; bn >= 0 && *runb < maxrun &&
is_sequential(ump,
((ufs2_daddr_t *)bp->b_data)[bn],
((ufs2_daddr_t *)bp->b_data)[bn + 1]);
--bn, ++*runb);
}
}
}
@ -275,22 +296,22 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
int
ufs_getlbns(vp, bn, ap, nump)
struct vnode *vp;
ufs_daddr_t bn;
ufs2_daddr_t bn;
struct indir *ap;
int *nump;
{
long blockcnt, metalbn, realbn;
ufs2_daddr_t blockcnt;
ufs_lbn_t metalbn, realbn;
struct ufsmount *ump;
int i, numlevels, off;
int64_t qblockcnt;
ump = VFSTOUFS(vp->v_mount);
if (nump)
*nump = 0;
numlevels = 0;
realbn = bn;
if ((long)bn < 0)
bn = -(long)bn;
if (bn < 0)
bn = -bn;
/* The first NDADDR blocks are direct blocks. */
if (bn < NDADDR)
@ -305,15 +326,9 @@ ufs_getlbns(vp, bn, ap, nump)
for (blockcnt = 1, i = NIADDR, bn -= NDADDR;; i--, bn -= blockcnt) {
if (i == 0)
return (EFBIG);
/*
* Use int64_t's here to avoid overflow for triple indirect
* blocks when longs have 32 bits and the block size is more
* than 4K.
*/
qblockcnt = (int64_t)blockcnt * MNINDIR(ump);
if (bn < qblockcnt)
blockcnt *= MNINDIR(ump);
if (bn < blockcnt)
break;
blockcnt = qblockcnt;
}
/* Calculate the address of the first meta-block. */
@ -337,6 +352,7 @@ ufs_getlbns(vp, bn, ap, nump)
if (metalbn == realbn)
break;
blockcnt /= MNINDIR(ump);
off = (bn / blockcnt) % MNINDIR(ump);
++numlevels;
@ -346,7 +362,6 @@ ufs_getlbns(vp, bn, ap, nump)
++ap;
metalbn -= -1 + off * blockcnt;
blockcnt /= MNINDIR(ump);
}
if (nump)
*nump = numlevels;

View File

@ -947,7 +947,7 @@ ufs_extattr_get(struct vnode *vp, int attrnamespace, const char *name,
* is to coerce this to undefined, and let it get cleaned
* up by the next write or extattrctl clean.
*/
printf("ufs_extattr_get (%s): inode number inconsistency (%d, %d)\n",
printf("ufs_extattr_get (%s): inode number inconsistency (%d, %lld)\n",
mp->mnt_stat.f_mntonname, ueh.ueh_i_gen, ip->i_gen);
error = ENOATTR;
goto vopunlock_exit;
@ -1226,7 +1226,7 @@ ufs_extattr_rm(struct vnode *vp, int attrnamespace, const char *name,
* coerce this to undefined, and let it get cleaned up by
* the next write or extattrctl clean.
*/
printf("ufs_extattr_rm (%s): inode number inconsistency (%d, %d)\n",
printf("ufs_extattr_rm (%s): inode number inconsistency (%d, %lld)\n",
mp->mnt_stat.f_mntonname, ueh.ueh_i_gen, ip->i_gen);
error = ENOATTR;
goto vopunlock_exit;

View File

@ -60,7 +60,8 @@ int ufs_vnoperatefifo(struct vop_generic_args *);
int ufs_vnoperatespec(struct vop_generic_args *);
int ufs_bmap(struct vop_bmap_args *);
int ufs_bmaparray(struct vnode *, ufs_daddr_t, ufs_daddr_t *, int *, int *);
int ufs_bmaparray(struct vnode *, ufs2_daddr_t, ufs2_daddr_t *, int *,
int *);
int ufs_fhtovp(struct mount *, struct ufid *, struct vnode **);
int ufs_checkpath(struct inode *, struct inode *, struct ucred *);
void ufs_dirbad(struct inode *, doff_t, char *);
@ -72,7 +73,7 @@ int ufs_direnter(struct vnode *, struct vnode *, struct direct *,
struct componentname *, struct buf *);
int ufs_dirremove(struct vnode *, struct inode *, int, int);
int ufs_dirrewrite(struct inode *, struct inode *, ino_t, int, int);
int ufs_getlbns(struct vnode *, ufs_daddr_t, struct indir *, int *);
int ufs_getlbns(struct vnode *, ufs2_daddr_t, struct indir *, int *);
int ufs_ihashget(dev_t, ino_t, int, struct vnode **);
void ufs_ihashinit(void);
int ufs_ihashins(struct inode *, int, struct vnode **);
@ -94,12 +95,12 @@ int ufs_vinit(struct mount *, vop_t **, vop_t **, struct vnode **);
* Soft update function prototypes.
*/
int softdep_setup_directory_add(struct buf *, struct inode *, off_t,
long, struct buf *, int);
ino_t, struct buf *, int);
void softdep_change_directoryentry_offset(struct inode *, caddr_t,
caddr_t, caddr_t, int);
void softdep_setup_remove(struct buf *,struct inode *, struct inode *, int);
void softdep_setup_directory_change(struct buf *, struct inode *,
struct inode *, long, int);
struct inode *, ino_t, int);
void softdep_change_linkcnt(struct inode *);
void softdep_releasefile(struct inode *);
int softdep_slowdown(struct vnode *);

View File

@ -73,7 +73,8 @@ ufs_inactive(ap)
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
struct thread *td = ap->a_td;
int mode, error = 0;
mode_t mode;
int error = 0;
if (prtactive && vp->v_usecount != 0)
vprint("ufs_inactive: pushing active", vp);
@ -101,9 +102,10 @@ ufs_inactive(ap)
* So, rather than creating a new entry point to do the
* same thing, we just use softdep_change_linkcnt().
*/
ip->i_rdev = 0;
DIP(ip, i_rdev) = 0;
mode = ip->i_mode;
ip->i_mode = 0;
DIP(ip, i_mode) = 0;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (DOINGSOFTDEP(vp))
softdep_change_linkcnt(ip);
@ -139,15 +141,15 @@ ufs_reclaim(ap)
struct thread *a_td;
} */ *ap;
{
struct inode *ip;
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
struct ufsmount *ump = ip->i_ump;
#ifdef QUOTA
int i;
#endif
if (prtactive && vp->v_usecount != 0)
vprint("ufs_reclaim: pushing active", vp);
ip = VTOI(vp);
if (ip->i_flag & IN_LAZYMOD) {
ip->i_flag |= IN_MODIFIED;
UFS_UPDATE(vp, 0);
@ -177,7 +179,11 @@ ufs_reclaim(ap)
if (ip->i_dirhash != NULL)
ufsdirhash_free(ip);
#endif
FREE(vp->v_data, VFSTOUFS(vp->v_mount)->um_malloctype);
if (ump->um_fstype == UFS1)
FREE(ip->i_din1, ump->um_malloctype);
else
FREE(ip->i_din2, ump->um_malloctype);
FREE(vp->v_data, ump->um_malloctype);
vp->v_data = 0;
return (0);
}

View File

@ -131,8 +131,8 @@ ufs_lookup(ap)
struct componentname *a_cnp;
} */ *ap;
{
struct vnode *vdp; /* vnode for directory being searched */
struct inode *dp; /* inode for directory being searched */
struct vnode *vdp; /* vnode for directory being searched */
struct inode *dp; /* inode for directory being searched */
struct buf *bp; /* a buffer of directory entries */
struct direct *ep; /* the current directory entry */
int entryoffsetinblock; /* offset of ep in bp's buffer */
@ -467,6 +467,7 @@ ufs_lookup(ap)
if (dp->i_offset + DIRSIZ(OFSFMT(vdp), ep) > dp->i_size) {
ufs_dirbad(dp, dp->i_offset, "i_size too small");
dp->i_size = dp->i_offset + DIRSIZ(OFSFMT(vdp), ep);
DIP(dp, i_size) = dp->i_size;
dp->i_flag |= IN_CHANGE | IN_UPDATE;
}
brelse(bp);
@ -644,8 +645,7 @@ ufs_dirbadentry(dp, ep, entryoffsetinblock)
struct direct *ep;
int entryoffsetinblock;
{
int i;
int namlen;
int i, namlen;
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (OFSFMT(dp))
@ -760,6 +760,7 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp)
return (error);
}
dp->i_size = dp->i_offset + DIRBLKSIZ;
DIP(dp, i_size) = dp->i_size;
dp->i_flag |= IN_CHANGE | IN_UPDATE;
vnode_pager_setsize(dvp, (u_long)dp->i_size);
dirp->d_reclen = DIRBLKSIZ;
@ -838,8 +839,10 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp)
*
* N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN.
*/
if (dp->i_offset + dp->i_count > dp->i_size)
if (dp->i_offset + dp->i_count > dp->i_size) {
dp->i_size = dp->i_offset + dp->i_count;
DIP(dp, i_size) = dp->i_size;
}
/*
* Get the block containing the space for the new directory entry.
*/
@ -1049,6 +1052,7 @@ ufs_dirremove(dvp, ip, flags, isrmdir)
if (ip) {
ip->i_effnlink--;
ip->i_nlink--;
DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
}
if (flags & DOWHITEOUT)
@ -1102,6 +1106,7 @@ ufs_dirrewrite(dp, oip, newinum, newtype, isrmdir)
bdwrite(bp);
} else {
oip->i_nlink--;
DIP(oip, i_nlink) = oip->i_nlink;
oip->i_flag |= IN_CHANGE;
if (DOINGASYNC(vdp)) {
bdwrite(bp);
@ -1138,7 +1143,7 @@ ufs_dirempty(ip, parentino, cred)
ino_t parentino;
struct ucred *cred;
{
off_t off;
doff_t off;
struct dirtemplate dbuf;
struct direct *dp = (struct direct *)&dbuf;
int error, count, namlen;
@ -1197,7 +1202,8 @@ ufs_checkpath(source, target, cred)
struct ucred *cred;
{
struct vnode *vp;
int error, rootino, namlen;
int error, namlen;
ino_t rootino;
struct dirtemplate dirbuf;
vp = ITOV(target);

View File

@ -54,6 +54,7 @@
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
static MALLOC_DEFINE(M_DQUOT, "UFS quota", "UFS quota entries");
@ -62,8 +63,8 @@ static MALLOC_DEFINE(M_DQUOT, "UFS quota", "UFS quota entries");
*/
static char *quotatypes[] = INITQFNAMES;
static int chkdqchg(struct inode *, long, struct ucred *, int);
static int chkiqchg(struct inode *, long, struct ucred *, int);
static int chkdqchg(struct inode *, ufs2_daddr_t, struct ucred *, int);
static int chkiqchg(struct inode *, ino_t, struct ucred *, int);
static int dqget(struct vnode *,
u_long, struct ufsmount *, int, struct dquot **);
static int dqsync(struct vnode *, struct dquot *);
@ -118,13 +119,13 @@ getinoquota(ip)
int
chkdq(ip, change, cred, flags)
struct inode *ip;
long change;
ufs2_daddr_t change;
struct ucred *cred;
int flags;
{
struct dquot *dq;
int i;
int ncurblocks, error;
ufs2_daddr_t ncurblocks;
int i, error;
#ifdef DIAGNOSTIC
if ((flags & CHOWN) == 0)
@ -184,12 +185,12 @@ chkdq(ip, change, cred, flags)
static int
chkdqchg(ip, change, cred, type)
struct inode *ip;
long change;
ufs2_daddr_t change;
struct ucred *cred;
int type;
{
struct dquot *dq = ip->i_dquot[type];
long ncurblocks = dq->dq_curblocks + change;
ufs2_daddr_t ncurblocks = dq->dq_curblocks + change;
/*
* If user would exceed their hard limit, disallow space allocation.
@ -239,13 +240,13 @@ chkdqchg(ip, change, cred, type)
int
chkiq(ip, change, cred, flags)
struct inode *ip;
long change;
ino_t change;
struct ucred *cred;
int flags;
{
struct dquot *dq;
int i;
int ncurinodes, error;
ino_t ncurinodes;
int i, error;
#ifdef DIAGNOSTIC
if ((flags & CHOWN) == 0)
@ -305,12 +306,12 @@ chkiq(ip, change, cred, flags)
static int
chkiqchg(ip, change, cred, type)
struct inode *ip;
long change;
ino_t change;
struct ucred *cred;
int type;
{
struct dquot *dq = ip->i_dquot[type];
long ncurinodes = dq->dq_curinodes + change;
ino_t ncurinodes = dq->dq_curinodes + change;
/*
* If user would exceed their hard limit, disallow inode allocation.

View File

@ -68,11 +68,11 @@ READ(ap)
struct uio *uio;
FS *fs;
struct buf *bp;
daddr_t lbn, nextlbn;
ufs_lbn_t lbn, nextlbn;
off_t bytesinfile;
long size, xfersize, blkoffset;
int error, orig_resid;
u_short mode;
mode_t mode;
int seqcount;
int ioflag;
vm_object_t object;
@ -394,7 +394,7 @@ WRITE(ap)
FS *fs;
struct buf *bp;
struct thread *td;
ufs_daddr_t lbn;
ufs_lbn_t lbn;
off_t osize;
int seqcount;
int blkoffset, error, extended, flags, ioflag, resid, size, xfersize;
@ -519,6 +519,7 @@ WRITE(ap)
if (uio->uio_offset + xfersize > ip->i_size) {
ip->i_size = uio->uio_offset + xfersize;
DIP(ip, i_size) = ip->i_size;
extended = 1;
}
@ -571,8 +572,10 @@ WRITE(ap)
* tampering.
*/
if (resid > uio->uio_resid && ap->a_cred &&
suser_cred(ap->a_cred, PRISON_ROOT))
suser_cred(ap->a_cred, PRISON_ROOT)) {
ip->i_mode &= ~(ISUID | ISGID);
DIP(ip, i_mode) = ip->i_mode;
}
if (resid > uio->uio_resid)
VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0));
if (error) {
@ -609,8 +612,7 @@ ffs_getpages(ap)
int bbackwards, bforwards;
int pbackwards, pforwards;
int firstpage;
int reqlblkno;
ufs_daddr_t reqblkno;
ufs2_daddr_t reqblkno, reqlblkno;
int poff;
int pcount;
int rtval;

View File

@ -162,17 +162,17 @@ ufs_itimes(vp)
if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
vfs_timestamp(&ts);
if (ip->i_flag & IN_ACCESS) {
ip->i_atime = ts.tv_sec;
ip->i_atimensec = ts.tv_nsec;
DIP(ip, i_atime) = ts.tv_sec;
DIP(ip, i_atimensec) = ts.tv_nsec;
}
if (ip->i_flag & IN_UPDATE) {
ip->i_mtime = ts.tv_sec;
ip->i_mtimensec = ts.tv_nsec;
DIP(ip, i_mtime) = ts.tv_sec;
DIP(ip, i_mtimensec) = ts.tv_nsec;
ip->i_modrev++;
}
if (ip->i_flag & IN_CHANGE) {
ip->i_ctime = ts.tv_sec;
ip->i_ctimensec = ts.tv_nsec;
DIP(ip, i_ctime) = ts.tv_sec;
DIP(ip, i_ctimensec) = ts.tv_nsec;
}
}
ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
@ -232,7 +232,7 @@ ufs_mknod(ap)
* Want to be able to use this to make badblock
* inodes, so don't truncate the dev number.
*/
ip->i_rdev = vap->va_rdev;
DIP(ip, i_rdev) = vap->va_rdev;
}
/*
* Remove inode, then reload it through VFS_VGET so it is
@ -419,18 +419,34 @@ ufs_getattr(ap)
vap->va_nlink = ip->i_effnlink;
vap->va_uid = ip->i_uid;
vap->va_gid = ip->i_gid;
vap->va_rdev = ip->i_rdev;
vap->va_size = ip->i_din.di_size;
vap->va_atime.tv_sec = ip->i_atime;
vap->va_atime.tv_nsec = ip->i_atimensec;
vap->va_mtime.tv_sec = ip->i_mtime;
vap->va_mtime.tv_nsec = ip->i_mtimensec;
vap->va_ctime.tv_sec = ip->i_ctime;
vap->va_ctime.tv_nsec = ip->i_ctimensec;
if (ip->i_ump->um_fstype == UFS1) {
vap->va_rdev = ip->i_din1->di_rdev;
vap->va_size = ip->i_din1->di_size;
vap->va_atime.tv_sec = ip->i_din1->di_atime;
vap->va_atime.tv_nsec = ip->i_din1->di_atimensec;
vap->va_mtime.tv_sec = ip->i_din1->di_mtime;
vap->va_mtime.tv_nsec = ip->i_din1->di_mtimensec;
vap->va_ctime.tv_sec = ip->i_din1->di_ctime;
vap->va_ctime.tv_nsec = ip->i_din1->di_ctimensec;
vap->va_createtime.tv_sec = 0;
vap->va_createtime.tv_nsec = 0;
vap->va_bytes = dbtob((u_quad_t)ip->i_din1->di_blocks);
} else {
vap->va_rdev = ip->i_din2->di_rdev;
vap->va_size = ip->i_din2->di_size;
vap->va_atime.tv_sec = ip->i_din2->di_atime;
vap->va_atime.tv_nsec = ip->i_din2->di_atimensec;
vap->va_mtime.tv_sec = ip->i_din2->di_mtime;
vap->va_mtime.tv_nsec = ip->i_din2->di_mtimensec;
vap->va_ctime.tv_sec = ip->i_din2->di_ctime;
vap->va_ctime.tv_nsec = ip->i_din2->di_ctimensec;
vap->va_createtime.tv_sec = ip->i_din2->di_createtime;
vap->va_createtime.tv_nsec = ip->i_din2->di_creatensec;
vap->va_bytes = dbtob((u_quad_t)ip->i_din2->di_blocks);
}
vap->va_flags = ip->i_flags;
vap->va_gen = ip->i_gen;
vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
vap->va_bytes = dbtob((u_quad_t)ip->i_blocks);
vap->va_type = IFTOVT(ip->i_mode);
vap->va_filerev = ip->i_modrev;
return (0);
@ -494,6 +510,7 @@ ufs_setattr(ap)
(ip->i_flags & SF_SNAPSHOT) != 0))
return (EPERM);
ip->i_flags = vap->va_flags;
DIP(ip, i_flags) = vap->va_flags;
} else {
if (ip->i_flags
& (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
@ -501,6 +518,7 @@ ufs_setattr(ap)
return (EPERM);
ip->i_flags &= SF_SETTABLE;
ip->i_flags |= (vap->va_flags & UF_SETTABLE);
DIP(ip, i_flags) = ip->i_flags;
}
ip->i_flag |= IN_CHANGE;
if (vap->va_flags & (IMMUTABLE | APPEND))
@ -563,12 +581,12 @@ ufs_setattr(ap)
ip->i_flag |= IN_CHANGE | IN_UPDATE;
ufs_itimes(vp);
if (vap->va_atime.tv_sec != VNOVAL) {
ip->i_atime = vap->va_atime.tv_sec;
ip->i_atimensec = vap->va_atime.tv_nsec;
DIP(ip, i_atime) = vap->va_atime.tv_sec;
DIP(ip, i_atimensec) = vap->va_atime.tv_nsec;
}
if (vap->va_mtime.tv_sec != VNOVAL) {
ip->i_mtime = vap->va_mtime.tv_sec;
ip->i_mtimensec = vap->va_mtime.tv_nsec;
DIP(ip, i_mtime) = vap->va_mtime.tv_sec;
DIP(ip, i_mtimensec) = vap->va_mtime.tv_nsec;
}
error = UFS_UPDATE(vp, 0);
if (error)
@ -620,6 +638,7 @@ ufs_chmod(vp, mode, cred, td)
}
ip->i_mode &= ~ALLPERMS;
ip->i_mode |= (mode & ALLPERMS);
DIP(ip, i_mode) = ip->i_mode;
ip->i_flag |= IN_CHANGE;
return (0);
}
@ -642,7 +661,7 @@ ufs_chown(vp, uid, gid, cred, td)
int error = 0;
#ifdef QUOTA
int i;
long change;
ufs2_daddr_t change;
#endif
if (uid == (uid_t)VNOVAL)
@ -677,7 +696,7 @@ ufs_chown(vp, uid, gid, cred, td)
dqrele(vp, ip->i_dquot[GRPQUOTA]);
ip->i_dquot[GRPQUOTA] = NODQUOT;
}
change = ip->i_blocks;
change = DIP(ip, i_blocks);
(void) chkdq(ip, -change, cred, CHOWN);
(void) chkiq(ip, -1, cred, CHOWN);
for (i = 0; i < MAXQUOTAS; i++) {
@ -686,7 +705,9 @@ ufs_chown(vp, uid, gid, cred, td)
}
#endif
ip->i_gid = gid;
DIP(ip, i_gid) = gid;
ip->i_uid = uid;
DIP(ip, i_uid) = uid;
#ifdef QUOTA
if ((error = getinoquota(ip)) == 0) {
if (ouid == uid) {
@ -709,7 +730,9 @@ ufs_chown(vp, uid, gid, cred, td)
}
}
ip->i_gid = ogid;
DIP(ip, i_gid) = ogid;
ip->i_uid = ouid;
DIP(ip, i_uid) = ouid;
if (getinoquota(ip) == 0) {
if (ouid == uid) {
dqrele(vp, ip->i_dquot[USRQUOTA]);
@ -729,8 +752,10 @@ ufs_chown(vp, uid, gid, cred, td)
panic("ufs_chown: lost quota");
#endif /* QUOTA */
ip->i_flag |= IN_CHANGE;
if (suser_cred(cred, PRISON_ROOT) && (ouid != uid || ogid != gid))
if (suser_cred(cred, PRISON_ROOT) && (ouid != uid || ogid != gid)) {
ip->i_mode &= ~(ISUID | ISGID);
DIP(ip, i_mode) = ip->i_mode;
}
return (0);
}
@ -803,6 +828,7 @@ ufs_link(ap)
}
ip->i_effnlink++;
ip->i_nlink++;
DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vp))
softdep_change_linkcnt(ip);
@ -815,6 +841,7 @@ ufs_link(ap)
if (error) {
ip->i_effnlink--;
ip->i_nlink--;
DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vp))
softdep_change_linkcnt(ip);
@ -1065,6 +1092,7 @@ ufs_rename(ap)
*/
ip->i_effnlink++;
ip->i_nlink++;
DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(fvp))
softdep_change_linkcnt(ip);
@ -1130,6 +1158,7 @@ ufs_rename(ap)
}
dp->i_effnlink++;
dp->i_nlink++;
DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tdvp))
softdep_change_linkcnt(dp);
@ -1144,6 +1173,7 @@ ufs_rename(ap)
if (doingdirectory && newparent) {
dp->i_effnlink--;
dp->i_nlink--;
DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tdvp))
softdep_change_linkcnt(dp);
@ -1222,9 +1252,11 @@ ufs_rename(ap)
*/
if (!newparent) {
dp->i_nlink--;
DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
}
xp->i_nlink--;
DIP(xp, i_nlink) = xp->i_nlink;
xp->i_flag |= IN_CHANGE;
ioflag = DOINGASYNC(tvp) ? 0 : IO_SYNC;
if ((error = UFS_TRUNCATE(tvp, (off_t)0, ioflag,
@ -1321,6 +1353,7 @@ ufs_rename(ap)
if (vn_lock(fvp, LK_EXCLUSIVE, td) == 0) {
ip->i_effnlink--;
ip->i_nlink--;
DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
ip->i_flag &= ~IN_RENAME;
if (DOINGSOFTDEP(fvp))
@ -1378,6 +1411,7 @@ ufs_mkdir(ap)
goto out;
ip = VTOI(tvp);
ip->i_gid = dp->i_gid;
DIP(ip, i_gid) = dp->i_gid;
#ifdef SUIDDIR
{
#ifdef QUOTA
@ -1396,6 +1430,7 @@ ufs_mkdir(ap)
(dp->i_mode & ISUID) && dp->i_uid) {
dmode |= ISUID;
ip->i_uid = dp->i_uid;
DIP(ip, i_uid) = dp->i_uid;
#ifdef QUOTA
if (dp->i_uid != cnp->cn_cred->cr_uid) {
/*
@ -1412,8 +1447,10 @@ ufs_mkdir(ap)
ucp = &ucred;
}
#endif
} else
} else {
ip->i_uid = cnp->cn_cred->cr_uid;
DIP(ip, i_uid) = ip->i_uid;
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ucp, 0))) {
@ -1425,6 +1462,7 @@ ufs_mkdir(ap)
}
#else /* !SUIDDIR */
ip->i_uid = cnp->cn_cred->cr_uid;
DIP(ip, i_uid) = ip->i_uid;
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, cnp->cn_cred, 0))) {
@ -1459,6 +1497,7 @@ ufs_mkdir(ap)
* not defined case.
*/
ip->i_mode = dmode;
DIP(ip, i_mode) = dmode;
*dacl = *acl;
ufs_sync_acl_from_inode(ip, acl);
break;
@ -1470,6 +1509,7 @@ ufs_mkdir(ap)
* Just use the mode as-is.
*/
ip->i_mode = dmode;
DIP(ip, i_mode) = dmode;
FREE(acl, M_ACL);
FREE(dacl, M_ACL);
dacl = acl = NULL;
@ -1482,14 +1522,18 @@ ufs_mkdir(ap)
}
#else /* !UFS_ACL */
ip->i_mode = dmode;
DIP(ip, i_mode) = dmode;
#endif /* !UFS_ACL */
tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
ip->i_effnlink = 2;
ip->i_nlink = 2;
DIP(ip, i_nlink) = 2;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
if (cnp->cn_flags & ISWHITEOUT)
if (cnp->cn_flags & ISWHITEOUT) {
ip->i_flags |= UF_OPAQUE;
DIP(ip, i_flags) = ip->i_flags;
}
/*
* Bump link count in parent directory to reflect work done below.
@ -1498,6 +1542,7 @@ ufs_mkdir(ap)
*/
dp->i_effnlink++;
dp->i_nlink++;
DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(dvp))
softdep_change_linkcnt(dp);
@ -1555,6 +1600,7 @@ ufs_mkdir(ap)
B_CLRBUF, &bp)) != 0)
goto bad;
ip->i_size = DIRBLKSIZ;
DIP(ip, i_size) = DIRBLKSIZ;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
vnode_pager_setsize(tvp, (u_long)ip->i_size);
bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate);
@ -1602,6 +1648,7 @@ ufs_mkdir(ap)
} else {
dp->i_effnlink--;
dp->i_nlink--;
DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(dvp))
softdep_change_linkcnt(dp);
@ -1611,6 +1658,7 @@ ufs_mkdir(ap)
*/
ip->i_effnlink = 0;
ip->i_nlink = 0;
DIP(ip, i_nlink) = 0;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
@ -1699,8 +1747,10 @@ ufs_rmdir(ap)
*/
if (!DOINGSOFTDEP(vp)) {
dp->i_nlink--;
DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
ip->i_nlink--;
DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
ioflag = DOINGASYNC(vp) ? 0 : IO_SYNC;
error = UFS_TRUNCATE(vp, (off_t)0, ioflag, cnp->cn_cred,
@ -1743,8 +1793,9 @@ ufs_symlink(ap)
len = strlen(ap->a_target);
if (len < vp->v_mount->mnt_maxsymlinklen) {
ip = VTOI(vp);
bcopy(ap->a_target, (char *)ip->i_shortlink, len);
bcopy(ap->a_target, SHORTLINK(ip), len);
ip->i_size = len;
DIP(ip, i_size) = len;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
} else
error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
@ -1884,12 +1935,12 @@ ufs_readlink(ap)
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
int isize;
doff_t isize;
isize = ip->i_size;
if ((isize < vp->v_mount->mnt_maxsymlinklen) ||
(ip->i_din.di_blocks == 0)) { /* XXX - for old fastlink support */
uiomove((char *)ip->i_shortlink, isize, ap->a_uio);
DIP(ip, i_blocks) == 0) { /* XXX - for old fastlink support */
uiomove(SHORTLINK(ip), isize, ap->a_uio);
return (0);
}
return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
@ -1912,7 +1963,7 @@ ufs_strategy(ap)
struct buf *bp = ap->a_bp;
struct vnode *vp = ap->a_vp;
struct inode *ip;
ufs_daddr_t blkno;
ufs2_daddr_t blkno;
int error;
ip = VTOI(vp);
@ -2206,7 +2257,7 @@ ufs_vinit(mntp, specops, fifoops, vpp)
case VCHR:
case VBLK:
vp->v_op = specops;
vp = addaliasu(vp, ip->i_rdev);
vp = addaliasu(vp, DIP(ip, i_rdev));
ip->i_vnode = vp;
break;
case VFIFO:
@ -2261,6 +2312,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
return (error);
ip = VTOI(tvp);
ip->i_gid = pdir->i_gid;
DIP(ip, i_gid) = pdir->i_gid;
#ifdef SUIDDIR
{
#ifdef QUOTA
@ -2278,6 +2330,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
(pdir->i_mode & ISUID) &&
(pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) {
ip->i_uid = pdir->i_uid;
DIP(ip, i_uid) = ip->i_uid;
mode &= ~07111;
#ifdef QUOTA
/*
@ -2293,8 +2346,10 @@ ufs_makeinode(mode, dvp, vpp, cnp)
ucred.cr_groups[0] = pdir->i_gid;
ucp = &ucred;
#endif
} else
} else {
ip->i_uid = cnp->cn_cred->cr_uid;
DIP(ip, i_uid) = ip->i_uid;
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
@ -2307,6 +2362,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
}
#else /* !SUIDDIR */
ip->i_uid = cnp->cn_cred->cr_uid;
DIP(ip, i_uid) = ip->i_uid;
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, cnp->cn_cred, 0))) {
@ -2339,6 +2395,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
* not defined case.
*/
ip->i_mode = mode;
DIP(ip, i_mode) = mode;
ufs_sync_acl_from_inode(ip, acl);
break;
}
@ -2348,6 +2405,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
* Just use the mode as-is.
*/
ip->i_mode = mode;
DIP(ip, i_mode) = mode;
FREE(acl, M_ACL);
acl = NULL;
break;
@ -2359,18 +2417,24 @@ ufs_makeinode(mode, dvp, vpp, cnp)
}
#else /* !UFS_ACL */
ip->i_mode = mode;
DIP(ip, i_mode) = mode;
#endif /* !UFS_ACL */
tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */
ip->i_effnlink = 1;
ip->i_nlink = 1;
DIP(ip, i_nlink) = 1;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
suser_cred(cnp->cn_cred, PRISON_ROOT))
suser_cred(cnp->cn_cred, PRISON_ROOT)) {
ip->i_mode &= ~ISGID;
DIP(ip, i_mode) = ip->i_mode;
}
if (cnp->cn_flags & ISWHITEOUT)
if (cnp->cn_flags & ISWHITEOUT) {
ip->i_flags |= UF_OPAQUE;
DIP(ip, i_flags) = ip->i_flags;
}
/*
* Make sure inode goes to disk before directory entry.
@ -2422,6 +2486,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
*/
ip->i_effnlink = 0;
ip->i_nlink = 0;
DIP(ip, i_nlink) = 0;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);

View File

@ -65,9 +65,8 @@ struct ufsmount {
struct mount *um_mountp; /* filesystem vfs structure */
dev_t um_dev; /* device mounted */
struct vnode *um_devvp; /* block device mounted vnode */
u_long um_fstype; /* type of filesystem */
struct fs *um_fs; /* pointer to superblock */
struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */
struct ucred *um_cred[MAXQUOTAS]; /* quota file access cred */
struct ufs_extattr_per_mount um_extattr; /* extended attrs */
@ -94,6 +93,12 @@ struct ufsmount {
#define UFS_VALLOC(aa, bb, cc, dd) VFSTOUFS((aa)->v_mount)->um_valloc(aa, bb, cc, dd)
#define UFS_VFREE(aa, bb, cc) VFSTOUFS((aa)->v_mount)->um_vfree(aa, bb, cc)
/*
* Filesystem types
*/
#define UFS1 1
#define UFS2 2
/*
* Flags describing the state of quotas.
*/

View File

@ -599,7 +599,11 @@ ufs_filestat(vp, fsp)
fsp->fileid = (long)inode.i_number;
fsp->mode = (mode_t)inode.i_mode;
fsp->size = (u_long)inode.i_size;
#if should_be_but_is_hard
fsp->rdev = inode.i_rdev;
#else
fsp->rdev = 0;
#endif
return 1;
}

View File

@ -39,9 +39,8 @@ static const char rcsid[] =
#include <sys/mount.h>
#include <sys/disklabel.h>
#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <err.h>
#include <fcntl.h>
@ -63,9 +62,9 @@ static long blocksize;
static char *header;
static int headerlen;
static struct dinode *get_inode(int, struct fs *, ino_t);
static int virtualblocks(struct fs *, struct dinode *);
static int isfree(struct dinode *);
static union dinode *get_inode(int, struct fs *, ino_t);
static int virtualblocks(struct fs *, union dinode *);
static int isfree(struct fs *, union dinode *);
static void inituser(void);
static void usrrehash(void);
static struct user *user(uid_t);
@ -96,51 +95,65 @@ static void quot(char *, char *);
#endif
#define INOCNT(fs) ((fs)->fs_ipg)
#define INOSZ(fs) (sizeof(struct dinode) * INOCNT(fs))
#define INOSZ(fs) \
(((fs)->fs_magic == FS_UFS1_MAGIC ? sizeof(struct ufs1_dinode) : \
sizeof(struct ufs2_dinode)) * INOCNT(fs))
static struct dinode *
union dinode {
struct ufs1_dinode dp1;
struct ufs2_dinode dp2;
};
#define DIP(fs, dp, field) \
(((fs)->fs_magic == FS_UFS1_MAGIC) ? \
(dp)->dp1.field : (dp)->dp2.field)
static union dinode *
get_inode(fd,super,ino)
int fd;
struct fs *super;
ino_t ino;
{
static struct dinode *ip;
static caddr_t ipbuf;
static ino_t last;
if (fd < 0) { /* flush cache */
if (ip) {
free(ip);
ip = 0;
if (ipbuf) {
free(ipbuf);
ipbuf = 0;
}
return 0;
}
if (!ip || ino < last || ino >= last + INOCNT(super)) {
if (!ip
&& !(ip = (struct dinode *)malloc(INOSZ(super))))
if (!ipbuf || ino < last || ino >= last + INOCNT(super)) {
if (!ipbuf
&& !(ipbuf = malloc(INOSZ(super))))
errx(1, "allocate inodes");
last = (ino / INOCNT(super)) * INOCNT(super);
if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0
|| read(fd,ip,INOSZ(super)) != (ssize_t)INOSZ(super))
|| read(fd, ipbuf, INOSZ(super)) != (ssize_t)INOSZ(super))
err(1, "read inodes");
}
return ip + ino % INOCNT(super);
if (super->fs_magic == FS_UFS1_MAGIC)
return ((union dinode *)
&((struct ufs1_dinode *)ipbuf)[ino % INOCNT(super)]);
return ((union dinode *)
&((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)]);
}
#ifdef COMPAT
#define actualblocks(super,ip) ((ip)->di_blocks/2)
#define actualblocks(fs, dp) (DIP(fs, dp, di_blocks) / 2)
#else
#define actualblocks(super,ip) ((ip)->di_blocks)
#define actualblocks(fs, dp) DIP(fs, dp, di_blocks)
#endif
static int virtualblocks(super,ip)
static int virtualblocks(super, dp)
struct fs *super;
struct dinode *ip;
union dinode *dp;
{
register off_t nblk, sz;
sz = ip->di_size;
sz = DIP(super, dp, di_size);
#ifdef COMPAT
if (lblkno(super,sz) >= NDADDR) {
nblk = blkroundup(super,sz);
@ -169,14 +182,15 @@ static int virtualblocks(super,ip)
}
static int
isfree(ip)
struct dinode *ip;
isfree(super, dp)
struct fs *super;
union dinode *dp;
{
#ifdef COMPAT
return (ip->di_mode&IFMT) == 0;
return (DIP(super, dp, di_mode) & IFMT) == 0;
#else /* COMPAT */
switch (ip->di_mode&IFMT) {
switch (DIP(super, dp, di_mode) & IFMT) {
case IFIFO:
case IFLNK: /* should check FASTSYMLINK? */
case IFDIR:
@ -341,13 +355,13 @@ initfsizes()
}
static void
dofsizes(fd,super,name)
dofsizes(fd, super, name)
int fd;
struct fs *super;
char *name;
{
ino_t inode, maxino;
struct dinode *ip;
union dinode *dp;
daddr_t sz, ksz;
struct fsizes *fp, **fsp;
register int i;
@ -359,16 +373,16 @@ dofsizes(fd,super,name)
#endif /* COMPAT */
for (inode = 0; inode < maxino; inode++) {
errno = 0;
if ((ip = get_inode(fd,super,inode))
if ((dp = get_inode(fd,super,inode))
#ifdef COMPAT
&& ((ip->di_mode&IFMT) == IFREG
|| (ip->di_mode&IFMT) == IFDIR)
&& ((DIP(super, dp, di_mode) & IFMT) == IFREG
|| (DIP(super, dp, di_mode) & IFMT) == IFDIR)
#else /* COMPAT */
&& !isfree(ip)
&& !isfree(super, dp)
#endif /* COMPAT */
) {
sz = estimate ? virtualblocks(super,ip) :
actualblocks(super,ip);
sz = estimate ? virtualblocks(super, dp) :
actualblocks(super, dp);
#ifdef COMPAT
if (sz >= FSZCNT) {
fsizes->fsz_count[FSZCNT-1]++;
@ -416,25 +430,25 @@ dofsizes(fd,super,name)
}
static void
douser(fd,super,name)
douser(fd, super, name)
int fd;
struct fs *super;
char *name;
{
ino_t inode, maxino;
struct user *usr, *usrs;
struct dinode *ip;
union dinode *dp;
register int n;
maxino = super->fs_ncg * super->fs_ipg - 1;
for (inode = 0; inode < maxino; inode++) {
errno = 0;
if ((ip = get_inode(fd,super,inode))
&& !isfree(ip))
uses(ip->di_uid,
estimate ? virtualblocks(super,ip) :
actualblocks(super,ip),
ip->di_atime);
if ((dp = get_inode(fd,super,inode))
&& !isfree(super, dp))
uses(DIP(super, dp, di_uid),
estimate ? virtualblocks(super, dp) :
actualblocks(super, dp),
DIP(super, dp, di_atime));
else if (errno) {
err(1, "%s", name);
}
@ -459,7 +473,7 @@ douser(fd,super,name)
}
static void
donames(fd,super,name)
donames(fd, super, name)
int fd;
struct fs *super;
char *name;
@ -467,7 +481,7 @@ donames(fd,super,name)
int c;
ino_t inode, inode1;
ino_t maxino;
struct dinode *ip;
union dinode *dp;
maxino = super->fs_ncg * super->fs_ipg - 1;
/* first skip the name of the filesystem */
@ -481,9 +495,9 @@ donames(fd,super,name)
return;
}
errno = 0;
if ((ip = get_inode(fd,super,inode))
&& !isfree(ip)) {
printf("%s\t",user(ip->di_uid)->name);
if ((dp = get_inode(fd,super,inode))
&& !isfree(super, dp)) {
printf("%s\t",user(DIP(super, dp, di_uid))->name);
/* now skip whitespace */
while ((c = getchar()) == ' ' || c == '\t');
/* and print out the remainder of the input line */
@ -516,25 +530,45 @@ usage()
exit(1);
}
static char superblock[SBSIZE];
/*
* Possible superblock locations ordered from most to least likely.
*/
static int sblock_try[] = SBLOCKSEARCH;
static char superblock[SBLOCKSIZE];
void
quot(name,mp)
char *name, *mp;
{
int fd;
int i, fd;
struct fs *fs;
get_inode(-1, NULL, 0); /* flush cache */
inituser();
initfsizes();
if ((fd = open(name,0)) < 0
|| lseek(fd,SBOFF,0) != SBOFF
|| read(fd,superblock,SBSIZE) != SBSIZE) {
if ((fd = open(name,0)) < 0) {
warn("%s", name);
close(fd);
return;
}
if (((struct fs *)superblock)->fs_magic != FS_MAGIC) {
for (i = 0; sblock_try[i] != -1; i++) {
if (lseek(fd, sblock_try[i], 0) != sblock_try[i]) {
close(fd);
return;
}
if (read(fd, superblock, SBLOCKSIZE) != SBLOCKSIZE) {
close(fd);
return;
}
fs = (struct fs *)superblock;
if ((fs->fs_magic == FS_UFS1_MAGIC ||
(fs->fs_magic == FS_UFS2_MAGIC &&
fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) &&
fs->fs_bsize <= MAXBSIZE &&
fs->fs_bsize >= sizeof(struct fs))
break;
}
if (sblock_try[i] == -1) {
warnx("%s: not a BSD filesystem",name);
close(fd);
return;
@ -543,7 +577,7 @@ quot(name,mp)
if (mp)
printf(" (%s)",mp);
putchar('\n');
(*func)(fd,(struct fs *)superblock,name);
(*func)(fd, fs, name);
close(fd);
}