Esempio n. 1
0
void
fs_test(void)
{
	struct File *f;
	int r;
	char *blk;
	uint32_t *bits;

	// back up bitmap
	if ((r = sys_page_alloc(0, (void*) PGSIZE, PTE_P|PTE_U|PTE_W)) < 0)
		panic("sys_page_alloc: %e", r);
	bits = (uint32_t*) PGSIZE;
	memmove(bits, bitmap, PGSIZE);
	// allocate block
	if ((r = alloc_block()) < 0)
		panic("alloc_block: %e", r);
	// check that block was free
	assert(bits[r/32] & (1 << (r%32)));
	// and is not free any more
	assert(!(bitmap[r/32] & (1 << (r%32))));
	cprintf("alloc_block is good\n");

	if ((r = file_open("/not-found", &f)) < 0 && r != -E_NOT_FOUND)
		panic("file_open /not-found: %e", r);
	else if (r == 0)
		panic("file_open /not-found succeeded!");
	if ((r = file_open("/newmotd", &f)) < 0)
		panic("file_open /newmotd: %e", r);
	cprintf("file_open is good\n");

	if ((r = file_get_block(f, 0, &blk)) < 0)
		panic("file_get_block: %e", r);
	if (strcmp(blk, msg) != 0)
		panic("file_get_block returned wrong data");
	cprintf("file_get_block is good\n");

	*(volatile char*)blk = *(volatile char*)blk;
	assert((vpt[PPN(blk)] & PTE_D));
	file_flush(f);
	assert(!(vpt[PPN(blk)] & PTE_D));
	cprintf("file_flush is good\n");

	if ((r = file_set_size(f, 0)) < 0)
		panic("file_set_size: %e", r);
	assert(f->f_direct[0] == 0);
	assert(!(vpt[PPN(f)] & PTE_D));
	cprintf("file_truncate is good\n");

	if ((r = file_set_size(f, strlen(msg))) < 0)
		panic("file_set_size 2: %e", r);
	assert(!(vpt[PPN(f)] & PTE_D));
	if ((r = file_get_block(f, 0, &blk)) < 0)
		panic("file_get_block 2: %e", r);
	strcpy(blk, msg);
	assert((vpt[PPN(blk)] & PTE_D));
	file_flush(f);
	assert(!(vpt[PPN(blk)] & PTE_D));
	assert(!(vpt[PPN(f)] & PTE_D));
	cprintf("file rewrite is good\n");
}
Esempio n. 2
0
void
serve_set_size(u_int envid, struct Fsreq_set_size *rq)
{
	if (debug) {
		writef("serve_set_size %08x %08x %08x\n", envid, rq->req_fileid, rq->req_size);
	}

	struct Open *pOpen;

	int r;

	// Your code here
	if ((r = open_lookup(envid, rq->req_fileid, &pOpen)) < 0) {
		ipc_send(envid, r, 0, 0);
		return;
	}

	if ((r = file_set_size(pOpen->o_file, rq->req_size)) < 0) {
		ipc_send(envid, r, 0, 0);
		return;
	}

	ipc_send(envid, 0, 0, 0);//PTE_V);
	return;
	//	user_panic("serve_set_size not implemented");
}
Esempio n. 3
0
File: serv.c Progetto: ichaos/jos
void
serve_set_size(envid_t envid, struct Fsreq_set_size *rq)
{
	struct OpenFile *o;
	int r;

	if (debug)
		cprintf("serve_set_size %08x %08x %08x\n", envid,
                        rq->req_fileid, rq->req_size);

	// The file system server maintains three structures
	// for each open file.
	//
	// 1. The on-disk 'struct File' is mapped into the part of memory
	//    that maps the disk.  This memory is kept private to the
	//    file server.
	// 2. Each open file has a 'struct Fd' as well,
	//    which sort of corresponds to a Unix file descriptor.
	//    This 'struct Fd' is kept on *its own page* in memory,
	//    and it is shared with any environments that
	//    have the file open.
	//    Part of the 'struct Fd' is a *copy* of the on-disk
	//    'struct File' (struct Fd::fd_file.file), except that the
	//    block pointers are effectively garbage.
	//    This lets environments find out a file's size by examining
	//    struct Fd::fd_file.file.f_size, for example.
	//    *The server must make sure to keep two copies of the
	//    'struct File' in sync!*
	// 3. 'struct OpenFile' links these other two structures,
	//    and is kept private to the file server.
	//    The server maintains an array of all open files, indexed
	//    by "file ID".
	//    (There can be at most MAXFILE files open concurrently.)
	//    The client uses file IDs to communicate with the server.
	//    File IDs are a lot like environment IDs in the kernel.
	//    Use openfile_lookup to translate file IDs to struct OpenFile.

	// Every file system IPC call has the same general structure.
	// Here's how it goes.

	// First, use openfile_lookup to find the relevant open file.
	// On failure, return the error code to the client with ipc_send.
	if ((r = openfile_lookup(envid, rq->req_fileid, &o)) < 0)
		goto out;

	// Second, call the relevant file system function (from fs/fs.c).
	// On failure, return the error code to the client.
	if ((r = file_set_size(o->o_file, rq->req_size)) < 0)
		goto out;

	// Third, update the 'struct Fd' copy of the 'struct File'
	// as appropriate.
	o->o_fd->fd_file.file.f_size = rq->req_size;

	// Finally, return to the client!
	// (We just return r since we know it's 0 at this point.)
out:
	ipc_send(envid, r, 0, 0);
}
Esempio n. 4
0
void
serve_set_size(u_int envid, struct Fsreq_set_size *rq)
{
    struct Open *o;
    int r = 0;
	if (debug) printf("serve_set_size %08x %08x %08x\n", envid, rq->req_fileid, rq->req_size);
    if((r = open_lookup(envid, rq->req_fileid, &o)) < 0)
        goto out_set_size;
    r = file_set_size(&o->o_ff->f_file, rq->req_size);
    if(r == 0)
        o->o_file->f_size = rq->req_size;
out_set_size:
    ipc_send(envid, r, 0, 0);
	// Your code here
	// panic("serve_set_size not implemented");
}
Esempio n. 5
0
// Set the size of req->req_fileid to req->req_size bytes, truncating
// or extending the file as necessary.
int
serve_set_size(envid_t envid, struct Fsreq_set_size *req)
{
	struct OpenFile *o;
	int r;

	if (debug)
		cprintf("serve_set_size %08x %08x %08x\n", envid, req->req_fileid, req->req_size);

	// Every file system IPC call has the same general structure.
	// Here's how it goes.

	// First, use openfile_lookup to find the relevant open file.
	// On failure, return the error code to the client with ipc_send.
	if ((r = openfile_lookup(envid, req->req_fileid, &o)) < 0)
		return r;

	// Second, call the relevant file system function (from fs/fs.c).
	// On failure, return the error code to the client.
	return file_set_size(o->o_file, req->req_size);
}
Esempio n. 6
0
// Write count bytes from buf into f, starting at seek position
// offset.  This is meant to mimic the standard pwrite function.
// Extends the file if necessary.
// Returns the number of bytes written, < 0 on error.
int
file_write(struct File *f, const void *buf, size_t count, off_t offset)
{
	int r, bn;
	off_t pos;
	char *blk;

	// Extend file if necessary
	if (offset + count > f->f_size)
		if ((r = file_set_size(f, offset + count)) < 0)
			return r;

	for (pos = offset; pos < offset + count; ) {
		if ((r = file_get_block(f, pos / BLKSIZE, &blk)) < 0)
			return r;
		bn = MIN(BLKSIZE - pos % BLKSIZE, offset + count - pos);
		memmove(blk + pos % BLKSIZE, buf, bn);
		pos += bn;
		buf += bn;
	}

	return count;
}
Esempio n. 7
0
// Open req->req_path in mode req->req_omode, storing the Fd page and
// permissions to return to the calling environment in *pg_store and
// *perm_store respectively.
int
serve_open(envid_t envid, struct Fsreq_open *req,
	   void **pg_store, int *perm_store)
{
	char path[MAXPATHLEN];
	struct File *f;
	int fileid;
	int r;
	struct OpenFile *o;

	if (debug)
		cprintf("serve_open %08x %s 0x%x\n", envid, req->req_path, req->req_omode);

	// Copy in the path, making sure it's null-terminated
	memmove(path, req->req_path, MAXPATHLEN);
	path[MAXPATHLEN-1] = 0;

	// Find an open file ID
	if ((r = openfile_alloc(&o)) < 0) {
		if (debug)
			cprintf("openfile_alloc failed: %e", r);
		return r;
	}
	fileid = r;

	// Open the file
	if (req->req_omode & O_CREAT) {
		if ((r = file_create(path, &f)) < 0) {
			if (!(req->req_omode & O_EXCL) && r == -E_FILE_EXISTS)
				goto try_open;
			if (debug)
				cprintf("file_create failed: %e", r);
			return r;
		}
	} else {
try_open:
		if ((r = file_open(path, &f)) < 0) {
			if (debug)
				cprintf("file_open failed: %e", r);
			return r;
		}
	}

	// Truncate
	if (req->req_omode & O_TRUNC) {
		if ((r = file_set_size(f, 0)) < 0) {
			if (debug)
				cprintf("file_set_size failed: %e", r);
			return r;
		}
	}

	// Save the file pointer
	o->o_file = f;

	// Fill out the Fd structure
	o->o_fd->fd_file.id = o->o_fileid;
	o->o_fd->fd_omode = req->req_omode & O_ACCMODE;
	o->o_fd->fd_dev_id = devfile.dev_id;
	o->o_mode = req->req_omode;

	if (debug)
		cprintf("sending success, page %08x\n", (uintptr_t) o->o_fd);

	// Share the FD page with the caller
	*pg_store = o->o_fd;
	*perm_store = PTE_P|PTE_U|PTE_W;
	return 0;
}