Esempio n. 1
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);
}
Esempio n. 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;
	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 );
}