Пример #1
0
/*
 * Clear the flag bits so the journal can be removed.
 */
static void
journal_clear(void)
{
	struct ufs1_dinode *dp1;
	struct ufs2_dinode *dp2;
	ino_t ino;
	int mode;
	void *ip;

	ino = journal_findfile();
	if (ino == (ino_t)-1 || ino == 0) {
		warnx("Journal file does not exist");
		return;
	}
	printf("Clearing journal flags from inode %ju\n", (uintmax_t)ino);
	if (getino(&disk, &ip, ino, &mode) != 0) {
		warn("Failed to get journal inode");
		return;
	}
	dp2 = ip;
	dp1 = ip;
	if (sblock.fs_magic == FS_UFS1_MAGIC)
		dp1->di_flags = 0;
	else
		dp2->di_flags = 0;
	if (putino(&disk) < 0) {
		warn("Failed to write journal inode");
		return;
	}
}
Пример #2
0
static int
journal_alloc(int64_t size)
{
	struct ufs1_dinode *dp1;
	struct ufs2_dinode *dp2;
	ufs2_daddr_t blk;
	void *ip;
	struct cg *cgp;
	int resid;
	ino_t ino;
	int blks;
	int mode;
	time_t utime;
	int i;

	cgp = &disk.d_cg;
	ino = 0;

	/*
	 * If the journal file exists we can't allocate it.
	 */
	ino = journal_findfile();
	if (ino == (ino_t)-1)
		return (-1);
	if (ino > 0) {
		warnx("Journal file %s already exists, please remove.",
		    SUJ_FILE);
		return (-1);
	}
	/*
	 * If the user didn't supply a size pick one based on the filesystem
	 * size constrained with hardcoded MIN and MAX values.  We opt for
	 * 1/1024th of the filesystem up to MAX but not exceeding one CG and
	 * not less than the MIN.
	 */
	if (size == 0) {
		size = (sblock.fs_size * sblock.fs_bsize) / 1024;
		size = MIN(SUJ_MAX, size);
		if (size / sblock.fs_fsize > sblock.fs_fpg)
			size = sblock.fs_fpg * sblock.fs_fsize;
		size = MAX(SUJ_MIN, size);
		/* fsck does not support fragments in journal files. */
		size = roundup(size, sblock.fs_bsize);
	}
	resid = blocks = size / sblock.fs_bsize;
	if (sblock.fs_cstotal.cs_nbfree < blocks) {
		warn("Insufficient free space for %jd byte journal", size);
		return (-1);
	}
	/*
	 * Find a cg with enough blocks to satisfy the journal
	 * size.  Presently the journal does not span cgs.
	 */
	while (cgread(&disk) == 1) {
		if (cgp->cg_cs.cs_nifree == 0)
			continue;
		ino = cgialloc(&disk);
		if (ino <= 0)
			break;
		printf("Using inode %ju in cg %d for %jd byte journal\n",
		    (uintmax_t)ino, cgp->cg_cgx, size);
		if (getino(&disk, &ip, ino, &mode) != 0) {
			warn("Failed to get allocated inode");
			sbdirty();
			goto out;
		}
		/*
		 * We leave fields unrelated to the number of allocated
		 * blocks and size uninitialized.  This causes legacy
		 * fsck implementations to clear the inode.
		 */
		dp2 = ip;
		dp1 = ip;
		time(&utime);
		if (sblock.fs_magic == FS_UFS1_MAGIC) {
			bzero(dp1, sizeof(*dp1));
			dp1->di_size = size;
			dp1->di_mode = IFREG | IREAD;
			dp1->di_nlink = 1;
			dp1->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP;
			dp1->di_atime = utime;
			dp1->di_mtime = utime;
			dp1->di_ctime = utime;
		} else {
			bzero(dp2, sizeof(*dp2));
			dp2->di_size = size;
			dp2->di_mode = IFREG | IREAD;
			dp2->di_nlink = 1;
			dp2->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP;
			dp2->di_atime = utime;
			dp2->di_mtime = utime;
			dp2->di_ctime = utime;
			dp2->di_birthtime = utime;
		}
		for (i = 0; i < NDADDR && resid; i++, resid--) {
			blk = journal_balloc();
			if (blk <= 0)
				goto out;
			if (sblock.fs_magic == FS_UFS1_MAGIC) {
				dp1->di_db[i] = blk;
				dp1->di_blocks++;
			} else {
				dp2->di_db[i] = blk;
				dp2->di_blocks++;
			}
		}
		for (i = 0; i < NIADDR && resid; i++) {
			blk = journal_balloc();
			if (blk <= 0)
				goto out;
			blks = indir_fill(blk, i, &resid) + 1;
			if (blks <= 0) {
				sbdirty();
				goto out;
			}
			if (sblock.fs_magic == FS_UFS1_MAGIC) {
				dp1->di_ib[i] = blk;
				dp1->di_blocks += blks;
			} else {
				dp2->di_ib[i] = blk;
				dp2->di_blocks += blks;
			}
		}
		if (sblock.fs_magic == FS_UFS1_MAGIC)
			dp1->di_blocks *= sblock.fs_bsize / disk.d_bsize;
		else
			dp2->di_blocks *= sblock.fs_bsize / disk.d_bsize;
		if (putino(&disk) < 0) {
			warn("Failed to write inode");
			sbdirty();
			return (-1);
		}
		if (cgwrite(&disk) < 0) {
			warn("Failed to write updated cg");
			sbdirty();
			return (-1);
		}
		if (journal_insertfile(ino) < 0) {
			sbdirty();
			return (-1);
		}
		sblock.fs_sujfree = 0;
		return (0);
	}
	warnx("Insufficient free space for the journal.");
out:
	return (-1);
}
Пример #3
0
static int journal_alloc( int64_t size ) {
	struct ufs1_dinode *dp1;
	struct ufs2_dinode *dp2;
	ufs2_daddr_t blk;
	void *ip;
	struct cg *cgp;
	int resid;
	ino_t ino;
	int blks;
	int mode;
	time_t utime;
	int i;
	cgp = &disk.d_cg;
	ino = 0;
	ino = journal_findfile();
	if ( ino == ( ino_t ) - 1 ) return ( -1 );
	if ( ino > 0 ) {
		warnx( "Journal file %s already exists, please remove.", SUJ_FILE );
		return ( -1 );
	}
	if ( size == 0 ) {
		size = ( sblock.fs_size * sblock.fs_bsize ) / 1024;
		size = MIN( SUJ_MAX, size );
		if ( size / sblock.fs_fsize > sblock.fs_fpg ) size = sblock.fs_fpg * sblock.fs_fsize;
		size = MAX( SUJ_MIN, size );
		size = roundup( size, sblock.fs_bsize );
	}
	resid = blocks = size / sblock.fs_bsize;
	if ( sblock.fs_cstotal.cs_nbfree < blocks ) {
		warn( "Insufficient free space for %jd byte journal", size );
		return ( -1 );
	}
	while ( cgread( &disk ) == 1 ) {
		if ( cgp->cg_cs.cs_nifree == 0 ) continue;
		ino = cgialloc( &disk );
		if ( ino <= 0 ) break;
		printf( "Using inode %ju in cg %d for %jd byte journal\n", (uintmax_t) ino, cgp->cg_cgx, size );
		if ( getino( &disk, &ip, ino, &mode ) != 0 ) {
			warn( "Failed to get allocated inode" );
			sbdirty();
			goto out;
		}
		dp2 = ip;
		dp1 = ip;
		time( &utime );
		if ( sblock.fs_magic == FS_UFS1_MAGIC ) {
			bzero( dp1, sizeof( *dp1 ) );
			dp1->di_size = size;
			dp1->di_mode = IFREG | IREAD;
			dp1->di_nlink = 1;
			dp1->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP;
			dp1->di_atime = utime;
			dp1->di_mtime = utime;
			dp1->di_ctime = utime;
		} else {
			bzero( dp2, sizeof( *dp2 ) );
			dp2->di_size = size;
			dp2->di_mode = IFREG | IREAD;
			dp2->di_nlink = 1;
			dp2->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP;
			dp2->di_atime = utime;
			dp2->di_mtime = utime;
			dp2->di_ctime = utime;
			dp2->di_birthtime = utime;
		}
		for ( i = 0; i < NDADDR && resid; i++, resid-- ) {
			blk = journal_balloc();
			if ( blk <= 0 ) goto out;
			if ( sblock.fs_magic == FS_UFS1_MAGIC ) {
				dp1->di_db[i] = blk;
				dp1->di_blocks++;
			} else {
				dp2->di_db[i] = blk;
				dp2->di_blocks++;
			}
		}
		for ( i = 0; i < NIADDR && resid; i++ ) {
			blk = journal_balloc();
			if ( blk <= 0 ) goto out;
			blks = indir_fill( blk, i, &resid ) + 1;
			if ( blks <= 0 ) {
				sbdirty();
				goto out;
			}
			if ( sblock.fs_magic == FS_UFS1_MAGIC ) {
				dp1->di_ib[i] = blk;
				dp1->di_blocks += blks;
			} else {
				dp2->di_ib[i] = blk;
				dp2->di_blocks += blks;
			}
		}
		if ( sblock.fs_magic == FS_UFS1_MAGIC ) dp1->di_blocks *= sblock.fs_bsize / disk.d_bsize;
		else dp2->di_blocks *= sblock.fs_bsize / disk.d_bsize;
		if ( putino( &disk ) < 0 ) {
			warn( "Failed to write inode" );
			sbdirty();
			return ( -1 );
		}
		if ( cgwrite( &disk ) < 0 ) {
			warn( "Failed to write updated cg" );
			sbdirty();
			return ( -1 );
		}
		if ( journal_insertfile( ino ) < 0 ) {
			sbdirty();
			return ( -1 );
		}
		sblock.fs_sujfree = 0;
		return ( 0 );
	}
	warnx( "Insufficient free space for the journal." );
	out: return ( -1 );
}
Пример #4
0
/*
 * Insert the journal file into the ROOTINO directory.  We always extend the
 * last frag
 */
static int
journal_insertfile(ino_t ino)
{
	struct ufs1_dinode *dp1;
	struct ufs2_dinode *dp2;
	void *ip;
	ufs2_daddr_t nblk;
	ufs2_daddr_t blk;
	ufs_lbn_t lbn;
	int size;
	int mode;
	int off;

	if (getino(&disk, &ip, ROOTINO, &mode) != 0) {
		warn("Failed to get root inode");
		sbdirty();
		return (-1);
	}
	dp2 = ip;
	dp1 = ip;
	blk = 0;
	size = 0;
	nblk = journal_balloc();
	if (nblk <= 0)
		return (-1);
	/*
	 * For simplicity sake we aways extend the ROOTINO into a new
	 * directory block rather than searching for space and inserting
	 * into an existing block.  However, if the rootino has frags
	 * have to free them and extend the block.
	 */
	if (sblock.fs_magic == FS_UFS1_MAGIC) {
		lbn = lblkno(&sblock, dp1->di_size);
		off = blkoff(&sblock, dp1->di_size);
		blk = dp1->di_db[lbn];
		size = sblksize(&sblock, (off_t)dp1->di_size, lbn);
	} else {
		lbn = lblkno(&sblock, dp2->di_size);
		off = blkoff(&sblock, dp2->di_size);
		blk = dp2->di_db[lbn];
		size = sblksize(&sblock, (off_t)dp2->di_size, lbn);
	}
	if (off != 0) {
		if (dir_extend(blk, nblk, off, ino) == -1)
			return (-1);
	} else {
		blk = 0;
		if (dir_insert(nblk, 0, ino) == -1)
			return (-1);
	}
	if (sblock.fs_magic == FS_UFS1_MAGIC) {
		dp1->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE;
		dp1->di_db[lbn] = nblk;
		dp1->di_size = lblktosize(&sblock, lbn+1);
	} else {
		dp2->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE;
		dp2->di_db[lbn] = nblk;
		dp2->di_size = lblktosize(&sblock, lbn+1);
	}
	if (putino(&disk) < 0) {
		warn("Failed to write root inode");
		return (-1);
	}
	if (cgwrite(&disk) < 0) {
		warn("Failed to write updated cg");
		sbdirty();
		return (-1);
	}
	if (blk) {
		if (cgbfree(&disk, blk, size) < 0) {
			warn("Failed to write cg");
			return (-1);
		}
	}

	return (0);
}
Пример #5
0
static int journal_insertfile( ino_t ino ) {
	struct ufs1_dinode *dp1;
	struct ufs2_dinode *dp2;
	void *ip;
	ufs2_daddr_t nblk;
	ufs2_daddr_t blk;
	ufs_lbn_t lbn;
	int size;
	int mode;
	int off;
	if ( getino( &disk, &ip, ROOTINO, &mode ) != 0 ) {
		warn( "Failed to get root inode" );
		sbdirty();
		return ( -1 );
	}
	dp2 = ip;
	dp1 = ip;
	blk = 0;
	size = 0;
	nblk = journal_balloc();
	if ( nblk <= 0 ) return ( -1 );
	if ( sblock.fs_magic == FS_UFS1_MAGIC ) {
		lbn = lblkno( &sblock, dp1->di_size );
		off = blkoff( &sblock, dp1->di_size );
		blk = dp1->di_db[lbn];
		size = sblksize( &sblock, (off_t) dp1->di_size, lbn );
	} else {
		lbn = lblkno( &sblock, dp2->di_size );
		off = blkoff( &sblock, dp2->di_size );
		blk = dp2->di_db[lbn];
		size = sblksize( &sblock, (off_t) dp2->di_size, lbn );
	}
	if ( off != 0 ) {
		if ( dir_extend( blk, nblk, off, ino ) == -1 ) return ( -1 );
	} else {
		blk = 0;
		if ( dir_insert( nblk, 0, ino ) == -1 ) return ( -1 );
	}
	if ( sblock.fs_magic == FS_UFS1_MAGIC ) {
		dp1->di_blocks += ( sblock.fs_bsize - size ) / DEV_BSIZE;
		dp1->di_db[lbn] = nblk;
		dp1->di_size = lblktosize( &sblock, lbn + 1 );
	} else {
		dp2->di_blocks += ( sblock.fs_bsize - size ) / DEV_BSIZE;
		dp2->di_db[lbn] = nblk;
		dp2->di_size = lblktosize( &sblock, lbn + 1 );
	}
	if ( putino( &disk ) < 0 ) {
		warn( "Failed to write root inode" );
		return ( -1 );
	}
	if ( cgwrite( &disk ) < 0 ) {
		warn( "Failed to write updated cg" );
		sbdirty();
		return ( -1 );
	}
	if ( blk ) {
		if ( cgbfree( &disk, blk, size ) < 0 ) {
			warn( "Failed to write cg" );
			return ( -1 );
		}
	}
	return ( 0 );
}