Exemple #1
0
// Open inode number 'inum'.
// A pointer to the inode is stored in '*ino_store'.
// The inode is locked exclusively, and its 'i_opencount' is incremented.
// On the first read from disk, the memory-only fields are initialized
// to sensible values.
// Every inode_open() must be balanced by an inode_close().
// Returns 0 on success, < 0 on failure.
//
static int
inode_open(int inum, struct Inode **ino_store)
{
	int r;
	struct Inode *ino;

	// Always make sure our pagefault handler is installed.
	add_pgfault_handler(bcache_pgfault_handler);

	ino = get_inode(inum);
	r = bcache_ipc(ino, BCREQ_MAP_WLOCK);
	if (r < 0) {
		*ino_store = 0;
		return r;
	}

	// Initialize memory-only fields when an inode is first read from disk.
	if (r == 0) {		// i.e., the block has not been INITIALIZEd
		ino->i_inum = inum;
		ino->i_opencount = 0;
		bcache_ipc(ino, BCREQ_INITIALIZE);
	}

	// Account for our reservation and return.
	++ino->i_opencount;
	*ino_store = ino;
	return 0;
}
void
umain(int argc, char **argv)
{
	add_pgfault_handler(handler);
	cprintf("%s\n", (char*)0xDeadBeef);
	cprintf("%s\n", (char*)0xCafeBffe);
}
Exemple #3
0
// Checks file system structures.
// Checks all file system invariants hold and prints out any errors it finds.
// Does no locking, so if run in parallel with other environments, it can
// get confused and report transient "errors."
// Returns 0 if the file system is OK, -E_INVAL if any errors were found.
//
int
fsck(void)
{
	blocknum_t min_nblocks;
	int i, j, k;
	int errors = 0;

	add_pgfault_handler(bcache_pgfault_handler);

	// superblock checks
	if (super->s_magic != FS_MAGIC)
		panic("fsck: file system magic number %08x should be %08x", super->s_magic, FS_MAGIC);
	if (super->s_nblocks < 4)
		panic("fsck: file system must have at least 4 blocks");
	if (super->s_ninodes < 1)
		panic("fsck: file system must have at least 1 inode");
	min_nblocks = 2 /* boot sector, superblock */
		+ ROUNDUP(super->s_nblocks, BLKSIZE) / BLKSIZE /* freemap */
		+ (super->s_ninodes - 1); /* inodes */
	if (super->s_nblocks < min_nblocks)
		panic("fsck: file system with %d inodes has %d blocks, needs at least %d", super->s_ninodes, super->s_nblocks, min_nblocks);

	// basic freemap checks: initial blocks not free, free blocks marked
	// with 1 (later checks will overwrite freemap)
	for (i = 0; i < super->s_nblocks; ++i)
		if (i < min_nblocks && freemap[i] != 0) {
			cprintf("fsck: freemap[%d]: should be 0 (allocated), is %d\n", i, freemap[i]);
			++errors;
		} else if (freemap[i] != 0 && freemap[i] != 1) {
			cprintf("fsck: freemap[%d]: should be 0 or 1, is %d\n", i, freemap[i]);
			++errors;
			freemap[i] = (freemap[i] > 0 ? 1 : 0);
		}

	// inode checks: inode 1 is referenced, unreferenced inodes
	// have no data pointers, ftype makes sense, no data pointer overlap
	for (i = 1; i < super->s_ninodes; ++i) {
		struct Inode *ino = get_inode(i);
		off_t true_size;
		// check for open-but-unreferenced inode; be careful of
		// uninitialized inodes (use bcache_ipc to check)
		bool active = ino->i_refcount != 0;
		if (!active && ino->i_opencount != 0
		    && bcache_ipc(ino, BCREQ_MAP) != 0)
			active = true;
		if (active && ino->i_ftype != FTYPE_REG && ino->i_ftype != FTYPE_DIR) {
			cprintf("fsck: inode[%d]: odd i_ftype %d\n", i, ino->i_ftype);
			++errors;
		}
		if (i == 1 && ino->i_refcount == 0) {
			cprintf("fsck: inode[1]: root inode should be referenced\n");
			++errors;
		} else if (i == 1 && ino->i_ftype != FTYPE_DIR) {
			cprintf("fsck: inode[1]: root inode should be directory\n");
			++errors;
		}
		if (active && ino->i_size > MAXFILESIZE) {
			cprintf("fsck: inode[%d]: size %d too large\n", i, ino->i_size);
			++errors;
		}
		if (active && ino->i_inum != i) {
			cprintf("fsck: inode[%d]: wrong inumber %d\n", i, ino->i_inum);
			++errors;
		}
		true_size = active ? ino->i_size : 0;
		for (j = 0; j < NDIRECT; ++j) {
			blocknum_t b = ino->i_direct[j];
			if (j * BLKSIZE < true_size && !b) {
				cprintf("fsck: inode[%d]: direct block %d is null, though file size is %d\n", i, j, true_size);
				++errors;
			} else if (j * BLKSIZE >= true_size && b && active) {
				cprintf("fsck: inode[%d]: direct block %d exists, though file size is %d\n", i, j, true_size);
				++errors;
			}
			if (b && active) {
				if (b < min_nblocks) {
					cprintf("fsck: inode[%d]: direct block %d == %d is in special block range\n", i, j, b);
					++errors;
				} else if (freemap[b] == 1) {
					cprintf("fsck: inode[%d]: direct block %d == %d is marked as free\n", i, j, b);
					++errors;
				} else if (freemap[b] == -1) {
					cprintf("fsck: inode[%d]: direct block %d == %d used more than once\n", i, j, b);
					++errors;
				} else
					freemap[b] = -1;
			}
		}
		ino->i_fsck_refcount = (i == 1 ? 1 : 0);
		ino->i_fsck_checked = 0;
	}

	// directory checks
	while (1) {
		struct Inode *ino;
		for (i = 1; i < super->s_ninodes; ++i) {
			ino = get_inode(i);
			if (ino->i_fsck_refcount > 0
			    && !ino->i_fsck_checked
			    && ino->i_ftype == FTYPE_DIR)
				goto check_directory_inode;
		}
		break;

	check_directory_inode:
		ino->i_fsck_checked = 1;
		if (ino->i_size % sizeof(struct Direntry) != 0) {
			cprintf("inode[%d]: directory size %d not multiple of %d\n", i, ino->i_size, sizeof(struct Direntry));
			++errors;
		}
		for (j = 0; (off_t) (j + sizeof(struct Direntry)) <= ino->i_size; j += sizeof(struct Direntry)) {
			struct Direntry *de = (struct Direntry *) inode_data(ino, j);
			char name[MAXNAMELEN];
			int namelen;

			if (de->de_inum == 0)
				continue;

			if (de->de_namelen <= 0 || de->de_namelen >= MAXNAMELEN) {
				cprintf("inode[%d] de@%d: bad filename length %d\n", i, j, de->de_namelen);
				++errors;
			} else if (de->de_name[de->de_namelen] != 0) {
				cprintf("inode[%d] de@%d: filename is not null terminated\n", i, j);
				++errors;
			}
			memcpy(name, de->de_name, MAXNAMELEN);
			namelen = MAX(MIN(de->de_namelen, MAXNAMELEN - 1), 0);
			name[namelen] = 0;

			if (de->de_inum >= super->s_ninodes) {
				cprintf("inode[%d] de@%d (%s): inode %d out of range\n", i, j, name, de->de_inum);
				++errors;
			} else {
				struct Inode *refed = get_inode(de->de_inum);
				++refed->i_fsck_refcount;
				if (refed->i_refcount == 0) {
					cprintf("inode[%d] de@%d (%s): refers to free inode %d\n", i, j, name, de->de_inum);
					++errors;
				}
			}
			for (k = 0; k < j && de->de_namelen < MAXNAMELEN; k += sizeof(struct Direntry)) {
				struct Direntry *xde = (struct Direntry *) inode_data(ino, k);
				if (xde->de_inum != 0
				    && xde->de_namelen == namelen
				    && memcmp(xde->de_name, name, namelen) == 0) {
					cprintf("inode[%d] de@%d (%s): same filename as de@%d\n", i, j, name, k);
					++errors;
				}
			}
		}
	}

	// refcount consistency
	for (i = 1; i < super->s_ninodes; ++i) {
		struct Inode *ino = get_inode(i);
		if (ino->i_refcount != ino->i_fsck_refcount) {
			cprintf("fsck: inode[%d]: refcount %d should be %d\n", i, ino->i_refcount, ino->i_fsck_refcount);
			++errors;
		}
	}

	// clean up freemap
	for (i = 0; i < super->s_nblocks; ++i)
		if (freemap[i] == -1)
			freemap[i] = 0;
		else if (freemap[i] == 0 && i >= min_nblocks) {
			cprintf("fsck: freemap[%d]: unreferenced block is not free\n", i);
			++errors;
		}

	return errors ? -E_INVAL : 0;
}