示例#1
0
/* Does most of the work for link(). */
int
vfs_link(char *oldpath, char *newpath)
{
	struct vnode *oldfile;
	struct vnode *newdir;
	char newname[NAME_MAX+1];
	int result;

	result = vfs_lookup(oldpath, &oldfile);
	if (result) {
		return result;
	}
	result = vfs_lookparent(newpath, &newdir, newname, sizeof(newname));
	if (result) {
		VOP_DECREF(oldfile);
		return result;
	}

	if (oldfile->vn_fs==NULL || newdir->vn_fs==NULL ||
	    oldfile->vn_fs != newdir->vn_fs) {
		VOP_DECREF(newdir);
		VOP_DECREF(oldfile);
		return EXDEV;
	}

	result = VOP_LINK(newdir, newname, oldfile);

	VOP_DECREF(newdir);
	VOP_DECREF(oldfile);

	return result;
}
示例#2
0
文件: sfs_vnode.c 项目: mholden/os161
/*
 * Lookup gets a vnode for a pathname.
 */
static
int
sfs_lookup(struct vnode *v, char *path, struct vnode **ret)
{
	struct sfs_vnode *sv = v->vn_data;
	struct sfs_vnode *parent, *child;
        char name[SFS_NAMELEN];
        int i, err;

        if (sv->sv_i.sfi_type != SFS_TYPE_DIR) {
                return ENOTDIR;
        }

        parent = sv; 
        VOP_INCREF(&parent->sv_v);
        child = NULL; //just to be safe

        while(1){
                i = 0;  
                while(path[i] != '/' && path[i] != '\0' && i < SFS_NAMELEN) i++;
                if(i >= SFS_NAMELEN){
                        VOP_DECREF(&parent->sv_v);
                        return ENAMETOOLONG;
                }
                else if(path[i] == '/'){
                        path[i] = 0;
                        strcpy(name, path);
                        path = &path[i + 1];
         
                        err = sfs_lookonce(parent, name, &child, NULL);
                        if(err){
                                VOP_DECREF(&parent->sv_v);
                                return err;
                        }

                        VOP_DECREF(&parent->sv_v);
                        parent = child;
                        if(parent->sv_i.sfi_type != SFS_TYPE_DIR) return ENOTDIR;
                } else{ /* Hit NULL, so this is our last time through */
                        assert(path[i] == '\0');
                        
			err = sfs_lookonce(parent, path, &child, NULL);
                        if(err){
                                VOP_DECREF(&parent->sv_v);
                                return err;
                        }       
         
                        VOP_DECREF(&parent->sv_v);

			break;
                }
        }

	*ret = &child->sv_v;

	return 0;
}
示例#3
0
static
int
sfs_lookparent_internal(struct vnode *v, char *path, struct vnode **ret,
		  char *buf, size_t buflen)
{
	struct sfs_vnode *sv = v->vn_data;
	struct sfs_vnode *next;
	char *s;
	int result;

	VOP_INCREF(&sv->sv_absvn);

	while (1) {
		/* Don't need lock to check vnode type; it's constant */
		if (sv->sv_type != SFS_TYPE_DIR) {
			VOP_DECREF(&sv->sv_absvn);
			return ENOTDIR;
		}

		s = strchr(path, '/');
		if (!s) {
			/* Last component. */
			break;
		}
		*s = 0;
		s++;

		lock_acquire(sv->sv_lock);
		result = sfs_lookonce(sv, path, &next, NULL);
		lock_release(sv->sv_lock);

		if (result) {
			VOP_DECREF(&sv->sv_absvn);
			return result;
		}

		VOP_DECREF(&sv->sv_absvn);
		sv = next;
		path = s;
	}

	if (strlen(path)+1 > buflen) {
		VOP_DECREF(&sv->sv_absvn);
		return ENAMETOOLONG;
	}
	strcpy(buf, path);

	*ret = &sv->sv_absvn;

	return 0;
}
示例#4
0
/*
 * Set current directory as a vnode.
 * The passed vnode must in fact be a directory.
 */
int
vfs_setcurdir(struct vnode *dir)
{
	struct vnode *old;
	mode_t vtype;
	int result;

	result = VOP_GETTYPE(dir, &vtype);
	if (result) {
		return result;
	}
	if (vtype != S_IFDIR) {
		return ENOTDIR;
	}

	VOP_INCREF(dir);

	spinlock_acquire(&curproc->p_lock);
	old = curproc->p_cwd;
	curproc->p_cwd = dir;
	spinlock_release(&curproc->p_lock);

	if (old!=NULL) {
		VOP_DECREF(old);
	}

	return 0;
}
示例#5
0
文件: sfs_vnode.c 项目: mholden/os161
/*
 * Delete a file.
 */
static
int
sfs_remove(struct vnode *dir, const char *name)
{
	struct sfs_vnode *sv = dir->vn_data;
	struct sfs_vnode *victim;
	int slot;
	int result;

	/* Look for the file and fetch a vnode for it. */
	result = sfs_lookonce(sv, name, &victim, &slot);
	if (result) {
		return result;
	}

	/* Erase its directory entry. */
	result = sfs_dir_unlink(sv, slot);
	if (result==0) {
		/* If we succeeded, decrement the link count. */
		assert(victim->sv_i.sfi_linkcount > 0);
		victim->sv_i.sfi_linkcount--;
		victim->sv_dirty = 1;
	}

	/* Discard the reference that sfs_lookonce got us */
	VOP_DECREF(&victim->sv_v);

	return result;
}
示例#6
0
文件: file.c 项目: script3r/os161
/**
 * close the file given by the descriptor
 */
int
file_close_descriptor( struct proc *p, int fd ) {
	struct file 	*f = NULL;
	int 		err = 0;

	err = file_get( p, fd, &f );
	if( err )
		return err;
	
	//make sure there are programs using it
	KASSERT( f->f_refcount > 0 );

	//detach from the file descriptor table
	fd_detach( p->p_fd, fd );
	
	//decrease both refcounts
	f->f_refcount--;
	VOP_DECREF( f->f_vnode );

	//destroy if we are the only ones using it
	if( f->f_refcount == 0 ) {
		F_UNLOCK( f );
		file_destroy( f );
		return 0;
	}

	//unlock the file
	F_UNLOCK( f );
	return 0;
}
示例#7
0
/*
 * Helper function for rename. Make sure COMPARE is not a direct
 * ancestor of (or the same as) CHILD.
 *
 * Note: acquires locks as it goes up.
 */
static
int
check_parent(struct sfs_vnode *lookfor, struct sfs_vnode *failon,
	     struct sfs_vnode *child, int *found)
{
	struct sfs_vnode *up;
	int result;

	*found = 0;

	VOP_INCREF(&child->sv_absvn);
	while (1) {
		if (failon == child) {
			/* Bad */
			VOP_DECREF(&child->sv_absvn);
			return EINVAL;
		}

		if (lookfor == child) {
			*found = 1;
		}

		lock_acquire(child->sv_lock);
		result = sfs_lookonce(child, "..", &up, NULL);
		lock_release(child->sv_lock);

		if (result) {
			VOP_DECREF(&child->sv_absvn);
			return result;
		}
		if (child == up) {
			/* Hit root, done */
			VOP_DECREF(&up->sv_absvn);
			break;
		}
		VOP_DECREF(&child->sv_absvn);
		child = up;
	}

	VOP_DECREF(&child->sv_absvn);
	return 0;
}
示例#8
0
文件: sfs_vnode.c 项目: mholden/os161
/* Setup . and .. in root directory if this is the first mount */
int
sfs_setup_root(struct sfs_fs *sfs)
{
	struct fs *fs = &sfs->sfs_absfs;
	struct vnode *root_vv;
	struct sfs_vnode *root_sv;
	int result;

	root_vv = sfs_getroot(fs);
	root_sv = root_vv->vn_data;

	if(sfs_dir_nentries(root_sv) != 0){
		VOP_DECREF(root_vv);
		return 0;
	}

	result = sfs_dir_link(root_sv, ".", SFS_ROOT_LOCATION, NULL);
        if (result) {
                VOP_DECREF(root_vv);
                return result;
        }

        root_sv->sv_i.sfi_linkcount++;
        root_sv->sv_dirty = 1;

        result = sfs_dir_link(root_sv, "..", SFS_ROOT_LOCATION, NULL);
        if (result) {
                sfs_dir_unlink(root_sv, 0); /* Hope this doesn't fail?? */
                root_sv->sv_i.sfi_linkcount--;
                root_sv->sv_dirty = 1;
                VOP_DECREF(root_vv);
                return result;
        }

        root_sv->sv_i.sfi_linkcount++;
        root_sv->sv_dirty = 1;	

	/* Decrement reference that sfs_getroot incremented */
	VOP_DECREF(root_vv);

	return 0;
}
示例#9
0
/*
 * Cause the current thread to exit.
 *
 * We clean up the parts of the thread structure we don't actually
 * need to run right away. The rest has to wait until thread_destroy
 * gets called from exorcise().
 */
void
thread_exit(int exitcode)
{
	DEBUG(DB_THREADS,"Thread %s exiting with %d",
               curthread->t_name, exitcode);

	/* ASST1: Let the pid management system know this thread is done. */
	pid_setexited(curthread->t_pid, exitcode);

	if (curthread->t_stack != NULL) {
		/*
		 * Check the magic number we put on the bottom end of
		 * the stack in thread_fork. If these assertions go
		 * off, it most likely means you overflowed your stack
		 * at some point, which can cause all kinds of
		 * mysterious other things to happen.
		 */
		assert(curthread->t_stack[0] == (char)0xae);
		assert(curthread->t_stack[1] == (char)0x11);
		assert(curthread->t_stack[2] == (char)0xda);
		assert(curthread->t_stack[3] == (char)0x33);
	}

	splhigh();

	if (curthread->t_vmspace) {
		/*
		 * Do this carefully to avoid race condition with
		 * context switch code.
		 */
		struct addrspace *as = curthread->t_vmspace;
		curthread->t_vmspace = NULL;
		as_destroy(as);
	}

	if (curthread->t_cwd) {
		VOP_DECREF(curthread->t_cwd);
		curthread->t_cwd = NULL;
	}

	/* A3 SETUP */
	if (curthread->t_filetable) {
		filetable_destroy(curthread->t_filetable);
    /* set it back to NULL so it can be initialized again */
    curthread->t_filetable = NULL;
	}
	/* END A3 SETUP */

	assert(numthreads>0);
	numthreads--;
	mi_switch(S_ZOMB);

	panic("Thread came back from the dead!\n");
}
示例#10
0
/*
 * Create a file. If EXCL is set, insist that the filename not already
 * exist; otherwise, if it already exists, just open it.
 */
static
int
sfs_creat(struct vnode *v, const char *name, int excl, struct vnode **ret)
{
	struct sfs_fs *sfs = v->vn_fs->fs_data;
	struct sfs_vnode *sv = v->vn_data;
	struct sfs_vnode *newguy;
	u_int32_t ino;
	int result;

	/* Look up the name */
	result = sfs_dir_findname(sv, name, &ino, NULL, NULL);
	if (result!=0 && result!=ENOENT) {
		return result;
	}

	/* If it exists and we didn't want it to, fail */
	if (result==0 && excl) {
		return EEXIST;
	}

	if (result==0) {
		/* We got a file; load its vnode and return */
		result = sfs_loadvnode(sfs, ino, SFS_TYPE_INVAL, &newguy);
		if (result) {
			return result;
		}
		*ret = &newguy->sv_v;
		return 0;
	}

	/* Didn't exist - create it */
	result = sfs_makeobj(sfs, SFS_TYPE_FILE, &newguy);
	if (result) {
		return result;
	}

	/* Link it into the directory */
	result = sfs_dir_link(sv, name, newguy->sv_ino, NULL);
	if (result) {
		VOP_DECREF(&newguy->sv_v);
		return result;
	}

	/* Update the linkcount of the new file */
	newguy->sv_i.sfi_linkcount++;

	/* and consequently mark it dirty. */
	newguy->sv_dirty = 1;

	*ret = &newguy->sv_v;
	
	return 0;
}
示例#11
0
文件: thread.c 项目: jessZhAnG/OS
/*
 * Cause the current thread to exit.
 *
 * We clean up the parts of the thread structure we don't actually
 * need to run right away. The rest has to wait until thread_destroy
 * gets called from exorcise().
 */
void
thread_exit(void)
{
	if (curthread->t_stack != NULL) {
		/*
		 * Check the magic number we put on the bottom end of
		 * the stack in thread_fork. If these assertions go
		 * off, it most likely means you overflowed your stack
		 * at some point, which can cause all kinds of
		 * mysterious other things to happen.
		 */
		assert(curthread->t_stack[0] == (char)0xae);
		assert(curthread->t_stack[1] == (char)0x11);
		assert(curthread->t_stack[2] == (char)0xda);
		assert(curthread->t_stack[3] == (char)0x33);
	}
        #if OPT_A2
        vfs_close(curthread->ft[0]->file);
        vfs_close(curthread->ft[1]->file);
        vfs_close(curthread->ft[2]->file);
        #endif
	splhigh();

	if (curthread->t_vmspace) {
		/*
		 * Do this carefully to avoid race condition with
		 * context switch code.
		 */
		struct addrspace *as = curthread->t_vmspace;
		curthread->t_vmspace = NULL;
		as_destroy(as);
	}

	if (curthread->t_cwd) {
		VOP_DECREF(curthread->t_cwd);
		curthread->t_cwd = NULL;
	}

	assert(numthreads>0);

	numthreads--;
       /* #if OPT_A2
        struct process* current = p_table[curthread->pid];
        if (current->ppid != -1){
           struct process* parent = p_table[current->ppid];
           if (parent->waiting) cv_broadcast(parent->exit,parent->exitlock);
        }         
        #endif
        */
	mi_switch(S_ZOMB);

	panic("Thread came back from the dead!\n");
}
示例#12
0
文件: proc.c 项目: BWK/os161
/*
 * Destroy a proc structure.
 *
 * Note: nothing currently calls this. Your wait/exit code will
 * probably want to do so.
 */
void
proc_destroy(struct proc *proc)
{
	/*
	 * You probably want to destroy and null out much of the
	 * process (particularly the address space) at exit time if
	 * your wait/exit design calls for the process structure to
	 * hang around beyond process exit. Some wait/exit designs
	 * do, some don't.
	 */

	KASSERT(proc != NULL);
	KASSERT(proc != kproc);

	/*
	 * We don't take p_lock in here because we must have the only
	 * reference to this structure. (Otherwise it would be
	 * incorrect to destroy it.)
	 */

	/* VFS fields */
	if (proc->p_cwd) {
		VOP_DECREF(proc->p_cwd);
		proc->p_cwd = NULL;
	}

	/* VM fields */
	if (proc->p_addrspace) {
		/*
		 * In case p is the currently running process (which
		 * it might be in some circumstances, or if this code
		 * gets moved into exit as suggested above), clear
		 * p_addrspace before calling as_destroy. Otherwise if
		 * as_destroy sleeps (which is quite possible) when we
		 * come back we'll be calling as_activate on a
		 * half-destroyed address space. This tends to be
		 * messily fatal.
		 */
		struct addrspace *as;

		as_deactivate();
		as = curproc_setas(NULL);
		as_destroy(as);
	}

	threadarray_cleanup(&proc->p_threads);
	spinlock_cleanup(&proc->p_lock);

	kfree(proc->p_name);
	kfree(proc);
}
示例#13
0
/*
 * Set current directory, as a pathname. Use vfs_lookup to translate
 * it to a vnode.
 */
int
vfs_chdir(char *path)
{
	struct vnode *vn;
	int result;

	result = vfs_lookup(path, &vn);
	if (result) {
		return result;
	}
	result = vfs_setcurdir(vn);
	VOP_DECREF(vn);
	return result;
}
示例#14
0
/*
 * Set current directory to "none".
 */
int
vfs_clearcurdir(void)
{
	struct vnode *old;

	spinlock_acquire(&curproc->p_lock);
	old = curproc->p_cwd;
	curproc->p_cwd = NULL;
	spinlock_release(&curproc->p_lock);

	if (old!=NULL) {
		VOP_DECREF(old);
	}

	return 0;
}
示例#15
0
/*
 * Does most of the work for symlink().
 *
 * Note, however, if you're implementing symlinks, that various
 * other parts of the VFS layer are missing crucial elements of
 * support for symlinks.
 */
int
vfs_symlink(const char *contents, char *path)
{
	struct vnode *newdir;
	char newname[NAME_MAX+1];
	int result;

	result = vfs_lookparent(path, &newdir, newname, sizeof(newname));
	if (result) {
		return result;
	}

	result = VOP_SYMLINK(newdir, newname, contents);
	VOP_DECREF(newdir);

	return result;
}
示例#16
0
/*
 * Does most of the work for readlink().
 *
 * Note, however, if you're implementing symlinks, that various
 * other parts of the VFS layer are missing crucial elements of
 * support for symlinks.
 */
int
vfs_readlink(char *path, struct uio *uio)
{
	struct vnode *vn;
	int result;

	result = vfs_lookup(path, &vn);
	if (result) {
		return result;
	}

	result = VOP_READLINK(vn, uio);

	VOP_DECREF(vn);

	return result;
}
示例#17
0
/* Does most of the work for remove(). */
int
vfs_remove(char *path)
{
	struct vnode *dir;
	char name[NAME_MAX+1];
	int result;
	
	result = vfs_lookparent(path, &dir, name, sizeof(name));
	if (result) {
		return result;
	}

	result = VOP_REMOVE(dir, name);
	VOP_DECREF(dir);

	return result;
}
/*
 * Cause the current thread to exit.
 *
 * We clean up the parts of the thread structure we don't actually
 * need to run right away. The rest has to wait until thread_destroy
 * gets called from exorcise().
 */
void
thread_exit(void)
{
	if (curthread->t_stack != NULL) {
		/*
		 * Check the magic number we put on the bottom end of
		 * the stack in thread_fork. If these assertions go
		 * off, it most likely means you overflowed your stack
		 * at some point, which can cause all kinds of
		 * mysterious other things to happen.
		 */
		assert(curthread->t_stack[0] == (char)0xae);
		assert(curthread->t_stack[1] == (char)0x11);
		assert(curthread->t_stack[2] == (char)0xda);
		assert(curthread->t_stack[3] == (char)0x33);
	}

	splhigh();

	if (curthread->t_vmspace) {
		/*
		 * Do this carefully to avoid race condition with
		 * context switch code.
		 */
		struct addrspace *as = curthread->t_vmspace;
		curthread->t_vmspace = NULL;
		as_destroy(as);
	}

	if (curthread->t_cwd) {
		VOP_DECREF(curthread->t_cwd);
		curthread->t_cwd = NULL;
	}

	if(curthread->ft) {
		delete_process_filetable(curthread->ft);
		curthread->ft = NULL;
	}

	assert(numthreads>0);
	numthreads--;
	mi_switch(S_ZOMB);

	panic("Thread came back from the dead!\n");
}
示例#19
0
/*
 * Does most of the work for rmdir.
 */
int
vfs_rmdir(char *path)
{
	struct vnode *parent;
	char name[NAME_MAX+1];
	int result;

	result = vfs_lookparent(path, &parent, name, sizeof(name));
	if (result) {
		return result;
	}

	result = VOP_RMDIR(parent, name);

	VOP_DECREF(parent);

	return result;
}
示例#20
0
/* Does most of the work for close(). */
void
vfs_close(struct vnode *vn)
{
	/*
	 * VOP_DECOPEN and VOP_DECREF don't return errors.
	 *
	 * We assume that the file system makes every reasonable
	 * effort to not fail. If it does fail - such as on a hard I/O
	 * error or something - vnode.c prints a warning. The reason
	 * we don't report errors up to or above this level is that
	 *    (1) most application software does not check for close
	 *        failing, and more importantly
	 *    (2) we're often called from places like process exit
	 *        where reporting the error is impossible and
	 *        meaningful recovery is entirely impractical.
	 */

	VOP_DECOPEN(vn);
	VOP_DECREF(vn);
}
示例#21
0
/*
 * Routine for "mounting" an emufs - we're not really mounted in the
 * sense that the VFS understands that term, because we're not
 * connected to a block device.
 *
 * Basically, we just add ourselves to the name list in the VFS layer.
 */
static
int
emufs_addtovfs(struct emu_softc *sc, const char *devname)
{
    struct emufs_fs *ef;
    int result;

    ef = kmalloc(sizeof(struct emufs_fs));
    if (ef==NULL) {
        return ENOMEM;
    }

    ef->ef_fs.fs_sync = emufs_sync;
    ef->ef_fs.fs_getvolname = emufs_getvolname;
    ef->ef_fs.fs_getroot = emufs_getroot;
    ef->ef_fs.fs_unmount = emufs_unmount;
    ef->ef_fs.fs_data = ef;

    ef->ef_emu = sc;
    ef->ef_root = NULL;
    ef->ef_vnodes = vnodearray_create();
    if (ef->ef_vnodes == NULL) {
        kfree(ef);
        return ENOMEM;
    }

    result = emufs_loadvnode(ef, EMU_ROOTHANDLE, 1, &ef->ef_root);
    if (result) {
        kfree(ef);
        return result;
    }

    KASSERT(ef->ef_root!=NULL);

    result = vfs_addfs(devname, &ef->ef_fs);
    if (result) {
        VOP_DECREF(&ef->ef_root->ev_v);
        kfree(ef);
    }
    return result;
}
示例#22
0
/*
 * Get current directory, as a pathname.
 * Use VOP_NAMEFILE to get the pathname and FSOP_GETVOLNAME to get the
 * volume name.
 */
int
vfs_getcwd(struct uio *uio)
{
	struct vnode *cwd;
	int result;
	const char *name;
	char colon=':';

	KASSERT(uio->uio_rw==UIO_READ);

	result = vfs_getcurdir(&cwd);
	if (result) {
		return result;
	}

	/* The current dir must be a directory, and thus it is not a device. */
	KASSERT(cwd->vn_fs != NULL);

	name = FSOP_GETVOLNAME(cwd->vn_fs);
	if (name==NULL) {
		name = vfs_getdevname(cwd->vn_fs);
	}
	KASSERT(name != NULL);

	result = uiomove((char *)name, strlen(name), uio);
	if (result) {
		goto out;
	}
	result = uiomove(&colon, 1, uio);
	if (result) {
		goto out;
	}

	result = VOP_NAMEFILE(cwd, uio);

 out:

	VOP_DECREF(cwd);
	return result;
}
示例#23
0
/*
 * Lookup gets a vnode for a pathname.
 *
 * Locking: gets the vnode lock while calling sfs_lookonce. Doesn't
 *   lock the new vnode, but does hand back a reference to it (so it
 *   won't evaporate).
 *
 * Requires up to 3 buffers.
 */
static
int
sfs_lookup(struct vnode *v, char *path, struct vnode **ret)
{
	struct sfs_vnode *sv = v->vn_data;
	struct vnode *dirv;
	struct sfs_vnode *dir;
	struct sfs_vnode *final;
	int result;
	char name[SFS_NAMELEN];

	reserve_buffers(SFS_BLOCKSIZE);

	result = sfs_lookparent_internal(&sv->sv_absvn, path, &dirv, name, sizeof(name));
	if (result) {
		unreserve_buffers(SFS_BLOCKSIZE);
		return result;
	}

	dir = dirv->vn_data;
	lock_acquire(dir->sv_lock);

	result = sfs_lookonce(dir, name, &final, NULL);

	lock_release(dir->sv_lock);
	VOP_DECREF(dirv);

	if (result) {
		unreserve_buffers(SFS_BLOCKSIZE);
		return result;
	}

	*ret = &final->sv_absvn;

	unreserve_buffers(SFS_BLOCKSIZE);
	return 0;
}
示例#24
0
文件: sfs_vnode.c 项目: mholden/os161
static
int
sfs_rmdir(struct vnode *vv, const char *name){
	struct sfs_vnode *sv = vv->vn_data;
        struct sfs_vnode *victim;
	struct sfs_dir tsd;
        int slot, slot2, nentries;
        int result;

        /* Look for the directory and fetch a vnode for it. */
        result = sfs_lookonce(sv, name, &victim, &slot);
        if (result) {
                return result;
        }

	/* Make sure it's a directory and that only . and .. are left */
	if(victim->sv_i.sfi_type != SFS_TYPE_DIR){
		VOP_DECREF(&victim->sv_v);
		return ENOTDIR;
	}

	nentries = sfs_dir_nentries(victim);
	if(nentries != 2){
		slot2 = 2; 
		while(slot2 < nentries){
			/* Ensure all other entries are blank */
			result = sfs_readdir(victim, &tsd, slot2);
                	if(result){
				VOP_DECREF(&victim->sv_v);
				return result;
			}

                	if(tsd.sfd_ino != SFS_NOINO){
				VOP_DECREF(&victim->sv_v);
                                return ENOTEMPTY;
			}
                	slot2++;
		}	
	}

	/* Get rid of . and .. (should always be in slot 0 and 1) */
	result = sfs_dir_unlink(victim, 0);
	if(result){
		VOP_DECREF(&victim->sv_v);
		return result;
	}
	assert(victim->sv_i.sfi_linkcount > 0);
        victim->sv_i.sfi_linkcount--;
        victim->sv_dirty = 1;

	result = sfs_dir_unlink(victim, 1);
        if(result){
                VOP_DECREF(&victim->sv_v);
                return result;
        }       
	assert(sv->sv_i.sfi_linkcount > 0);
        sv->sv_i.sfi_linkcount--;
        sv->sv_dirty = 1;

        /* Erase its directory entry. */
        result = sfs_dir_unlink(sv, slot);
        if (result==0) {
                /* If we succeeded, decrement the link count. */
                assert(victim->sv_i.sfi_linkcount > 0);
                victim->sv_i.sfi_linkcount--;
                victim->sv_dirty = 1;
        }

        /* Discard the reference that sfs_lookonce got us */
        VOP_DECREF(&victim->sv_v);

	return result;
}
示例#25
0
文件: sfs_vnode.c 项目: mholden/os161
static
int
sfs_mkdir(struct vnode *vv, const char *name){
	struct sfs_fs *sfs = vv->vn_fs->fs_data;
        struct sfs_vnode *sv = vv->vn_data;
        struct sfs_vnode *newguy;
        u_int32_t ino;
        int result, result2, slot1, slot2;

        /* Look up the name */
        result = sfs_dir_findname(sv, name, &ino, NULL, NULL);
        if (result!=0 && result!=ENOENT) {
                return result;
        }

        if (result==0) {
                /* Directory or file of same name already exists */
                return EINVAL;
        }

        /* Didn't exist - create it */
        result = sfs_makeobj(sfs, SFS_TYPE_DIR, &newguy);
        if (result) {
                return result;
        }

        /* Link it into the directory */
        result = sfs_dir_link(sv, name, newguy->sv_ino, &slot1);
        if (result) {
                VOP_DECREF(&newguy->sv_v);
                return result;
        }

        /* Increment linkcount of the new directory and mark it dirty */
        newguy->sv_i.sfi_linkcount++;
        newguy->sv_dirty = 1;

	/* Link . and .. into our directory */
	result = sfs_dir_link(newguy, ".", newguy->sv_ino, &slot2);
        if (result) {
		result2 = sfs_dir_unlink(sv, slot1);
                if(result2){
			VOP_DECREF(&newguy->sv_v);
			return result2;
		}
		newguy->sv_i.sfi_linkcount--;
        	newguy->sv_dirty = 1;
		VOP_DECREF(&newguy->sv_v);
                return result;
        }

	newguy->sv_i.sfi_linkcount++;
        newguy->sv_dirty = 1;

	result = sfs_dir_link(newguy, "..", sv->sv_ino, NULL);
        if (result) {
		result2 = sfs_dir_unlink(newguy, slot2);
		if(result2){
			VOP_DECREF(&newguy->sv_v);
			return result2;
		}
                newguy->sv_i.sfi_linkcount--; 
                newguy->sv_dirty = 1;
                result2 = sfs_dir_unlink(sv, slot1);
		if(result2){
                        VOP_DECREF(&newguy->sv_v);
                        return result2;
                }
                newguy->sv_i.sfi_linkcount--;
                newguy->sv_dirty = 1;
		VOP_DECREF(&newguy->sv_v);
                return result;
        }

        sv->sv_i.sfi_linkcount++;
        sv->sv_dirty = 1;

	VOP_DECREF(&newguy->sv_v);

	return 0;
}
示例#26
0
文件: sfs_vnode.c 项目: mholden/os161
/*
 * Rename a file.
 */
static
int
sfs_rename(struct vnode *d1, const char *n1, 
	   struct vnode *d2, const char *n2)
{
	struct sfs_vnode *sv1 = d1->vn_data;
	struct sfs_vnode *sv2 = d2->vn_data;
	struct sfs_vnode *g1;
	int slot1, slot2;
	int result, result2;

	/* Look up the old name of the file and get its inode and slot number*/
	result = sfs_lookonce(sv1, n1, &g1, &slot1);
	if (result) {
		return result;
	}

	/*
	 * Link it to the 'new' directory under the new name.
	 *
	 * We could theoretically just overwrite the original
	 * directory entry, except that we need to check to make sure
	 * the new name doesn't already exist; might as well use the
	 * existing link routine.
	 */
	result = sfs_dir_link(sv2, n2, g1->sv_ino, &slot2);
	if (result) {
		goto puke;
	}
	
	/* Increment the link count, and mark inode dirty */
	g1->sv_i.sfi_linkcount++;
	g1->sv_dirty = 1;

	/* Unlink the old slot */
	result = sfs_dir_unlink(sv1, slot1);
	if (result) {
		goto puke_harder;
	}

	/*
	 * Decrement the link count again, and mark the inode dirty again,
	 * in case it's been synced behind our back.
	 */
	assert(g1->sv_i.sfi_linkcount>0);
	g1->sv_i.sfi_linkcount--;
	g1->sv_dirty = 1;

	/* Let go of the reference to g1 */
	VOP_DECREF(&g1->sv_v);

	return 0;

 puke_harder:
	/*
	 * Error recovery: try to undo what we already did
	 */
	result2 = sfs_dir_unlink(sv2, slot2);
	if (result2) {
		kprintf("sfs: rename: %s\n", strerror(result));
		kprintf("sfs: rename: while cleaning up: %s\n", 
			strerror(result2));
		panic("sfs: rename: Cannot recover\n");
	}
	g1->sv_i.sfi_linkcount--;
 puke:
	/* Let go of the reference to g1 */
	VOP_DECREF(&g1->sv_v);
	return result;
}
示例#27
0
文件: sfs_vnode.c 项目: mholden/os161
/*
 * Get the full pathname for a file. This only needs to work on directories.
 * Since we don't support subdirectories, assume it's the root directory
 * and hand back the empty string. (The VFS layer takes care of the
 * device name, leading slash, etc.)
 */
static
int
sfs_namefile(struct vnode *vv, struct uio *uio)
{
	/* 
	 * 1. All you really have is inode number of directory passed in.
	 * 2. Get inode number of parent by reading directory slot 0 (..)
	 * 3. loadvnode of parent
	 * 4. Get our name by reading through parent directory for our inode
	 *    number
	 * 5. Add this name to string
	 * 6. Repeat 2 through 5 until we hit root
	 * 7. uiomove
	 *	Deal with reference counters as you need to, as loadvnode
	 *	increments refcount on vnode that we load. 
	 */
	
	struct sfs_vnode *sv = vv->vn_data;
	struct sfs_vnode *child_dir, *parent_dir;
	struct sfs_dir tsd;
	int err, nentries, slot;
	char to_add[SFS_NAMELEN + 1], pathname[(SFS_NAMELEN + 1) * SFS_DIR_DEPTH];
	
	/* If we're root, do nothing */
	if(sv->sv_ino == SFS_ROOT_LOCATION) return 0;

	child_dir = sv;
	VOP_INCREF(&child_dir->sv_v);

	while(1){
		err = sfs_readdir(child_dir, &tsd, 1);
        	if(err) return err;	

		assert(!strcmp(tsd.sfd_name, ".."));

		err = sfs_loadvnode(child_dir->sv_v.vn_fs->fs_data, tsd.sfd_ino, SFS_TYPE_INVAL, &parent_dir);
		if(err) return err;

		nentries = sfs_dir_nentries(parent_dir);
		slot = 2;
		while (slot < nentries){
			err = sfs_readdir(parent_dir, &tsd, slot);
        		if(err) return err;

			if(tsd.sfd_ino == child_dir->sv_ino) break;
                	slot++;
        	}

		/* 
	 	 * Doesn't make sense if we don't find our directory listed in our
	 	 * parent directory..
	 	 */
        	assert(slot < nentries);

		strcpy(to_add, tsd.sfd_name);
		strcat(to_add, "/");
		strcat(to_add, pathname);
		strcpy(pathname, to_add);
	
		VOP_DECREF(&child_dir->sv_v);
		if(parent_dir->sv_ino == SFS_ROOT_LOCATION){
			VOP_DECREF(&parent_dir->sv_v);
                        break;
		} else child_dir = parent_dir;
	}

	err = uiomove(pathname, strlen(pathname) + 1, uio);
	if(err) return err;

	return 0;
}
示例#28
0
/*
 * Create a new thread based on an existing one.
 * The new thread has name NAME, and starts executing in function FUNC.
 * DATA1 and DATA2 are passed to FUNC.
 */
int
thread_fork(const char *name, 
	    void *data1, unsigned long data2,
	    void (*func)(void *, unsigned long),
	    pid_t *ret)
{
	struct thread *newguy;
	int s, result;

	/* Allocate a thread */
	newguy = thread_create(name);
	if (newguy==NULL) {
		return ENOMEM;
	}

	/* ASST1: Allocate a pid */
	result = pid_alloc(&newguy->t_pid);
	if (result != 0) {
	  kfree(newguy->t_name);
	  kfree(newguy);
	  return result;
	}

	/* Allocate a stack */
	newguy->t_stack = kmalloc(STACK_SIZE);
	if (newguy->t_stack==NULL) {
		pid_unalloc(newguy->t_pid); /* ASST1: cleanup pid on fail */
		kfree(newguy->t_name);
		kfree(newguy);
		return ENOMEM;
	}

	/* stick a magic number on the bottom end of the stack */
	newguy->t_stack[0] = 0xae;
	newguy->t_stack[1] = 0x11;
	newguy->t_stack[2] = 0xda;
	newguy->t_stack[3] = 0x33;

	/* Inherit the current directory */
	if (curthread->t_cwd != NULL) {
		VOP_INCREF(curthread->t_cwd);
		newguy->t_cwd = curthread->t_cwd;
	}

	/* ASST1: copy address space if there is one */
	if (curthread->t_vmspace != NULL) {
		result = as_copy(curthread->t_vmspace, &newguy->t_vmspace);
		if (result) {
			pid_unalloc(newguy->t_pid); 
			kfree(newguy->t_name);
			kfree(newguy->t_stack);
			kfree(newguy);			
			return ENOMEM;
		}
	}


	/* Set up the pcb (this arranges for func to be called) */
	md_initpcb(&newguy->t_pcb, newguy->t_stack, data1, data2, func);

	/* Interrupts off for atomicity */
	s = splhigh();

	/*
	 * Make sure our data structures have enough space, so we won't
	 * run out later at an inconvenient time.
	 */
	result = array_preallocate(sleepers, numthreads+1);
	if (result) {
		goto fail;
	}
	result = array_preallocate(zombies, numthreads+1);
	if (result) {
		goto fail;
	}

	/* Do the same for the scheduler. */
	result = scheduler_preallocate(numthreads+1);
	if (result) {
		goto fail;
	}

	/* Make the new thread runnable */
	result = make_runnable(newguy);
	if (result != 0) {
		goto fail;
	}

	/*
	 * Increment the thread counter. This must be done atomically
	 * with the preallocate calls; otherwise the count can be
	 * temporarily too low, which would obviate its reason for
	 * existence.
	 */
	numthreads++;

	/* Done with stuff that needs to be atomic */
	splx(s);

	/*
	 * Return new thread structure if it's wanted.  Note that
	 * using the thread structure from the parent thread should be
	 * done only with caution, because in general the child thread
	 * might exit at any time.
	 */
	if (ret != NULL) {
		*ret = newguy->t_pid; /* ASST1 return pid, not thread struct */
	} else {
		/* Not returning the pid... better detach the new thread */
		result = thread_detach(newguy->t_pid);
		assert(result == 0); /* can't fail. */
	}

	return 0;

 fail:
	splx(s);

	/* ASST1: cleanup pid and vmspace on fail */
	pid_unalloc(newguy->t_pid); 

	if (newguy->t_vmspace) {
		as_destroy(newguy->t_vmspace);
	}

	if (newguy->t_cwd != NULL) {
		VOP_DECREF(newguy->t_cwd);
	}
	kfree(newguy->t_stack);
	kfree(newguy->t_name);
	kfree(newguy);

	return result;
}
示例#29
0
/*
 * Delete a file.
 *
 * Locking: locks the directory, then the file. Unlocks both.
 *   This follows the hierarchical locking order imposed by the directory tree.
 *
 * Requires up to 4 buffers.
 */
static
int
sfs_remove(struct vnode *dir, const char *name)
{
	struct sfs_vnode *sv = dir->vn_data;
	struct sfs_vnode *victim;
	struct sfs_dinode *victim_inodeptr;
	struct sfs_dinode *dir_inodeptr;
	int slot;
	int result;

	/* need to check this to avoid deadlock even in error condition */
	if (!strcmp(name, ".") || !strcmp(name, "..")) {
		return EISDIR;
	}

	lock_acquire(sv->sv_lock);
	reserve_buffers(SFS_BLOCKSIZE);

	result = sfs_dinode_load(sv);
	if (result) {
		goto out_buffers;
	}
	dir_inodeptr = sfs_dinode_map(sv);

	if (dir_inodeptr->sfi_linkcount == 0) {
		result = ENOENT;
		goto out_loadsv;
	}

	/* Look for the file and fetch a vnode for it. */
	result = sfs_lookonce(sv, name, &victim, &slot);
	if (result) {
		goto out_loadsv;
	}

	lock_acquire(victim->sv_lock);
	result = sfs_dinode_load(victim);
	if (result) {
		lock_release(victim->sv_lock);
		VOP_DECREF(&victim->sv_absvn);
		goto out_loadsv;
	}
	victim_inodeptr = sfs_dinode_map(victim);
	KASSERT(victim_inodeptr->sfi_linkcount > 0);

	/* Not allowed on directories */
	if (victim_inodeptr->sfi_type == SFS_TYPE_DIR) {
		result = EISDIR;
		goto out_reference;
	}

	/* Erase its directory entry. */
	result = sfs_dir_unlink(sv, slot);
	if (result) {
		goto out_reference;
	}

	/* Decrement the link count. */
	KASSERT(victim_inodeptr->sfi_linkcount > 0);
	victim_inodeptr->sfi_linkcount--;
	sfs_dinode_mark_dirty(victim);

out_reference:
	/* Discard the reference that sfs_lookonce got us */
	sfs_dinode_unload(victim);
	lock_release(victim->sv_lock);
	VOP_DECREF(&victim->sv_absvn);

out_loadsv:
	sfs_dinode_unload(sv);

out_buffers:
	lock_release(sv->sv_lock);
	unreserve_buffers(SFS_BLOCKSIZE);
	return result;
}
示例#30
0
文件: thread.c 项目: MattMarji/os161
/*
 * Create a new thread based on an existing one.
 * The new threaD has name NAME, and starts executing in function FUNC.
 * DATA1 and DATA2 are passed to FUNC.
 */
int
thread_fork(const char *name, 
	    void *data1, unsigned long data2,
	    void (*func)(void *, unsigned long),
	    struct thread **ret)
{
	
	struct thread *newguy;
	int s, result;

	/* Allocate a thread */
	newguy = thread_create(name);
	if (newguy==NULL) {
		return ENOMEM;
	}

	/* Allocate a stack */
	newguy->t_stack = kmalloc(STACK_SIZE);
	if (newguy->t_stack==NULL) {
		kfree(newguy->t_name);
		kfree(newguy);
		return ENOMEM;
	}

	/* stick a magic number on the bottom end of the stack */
	newguy->t_stack[0] = 0xae;
	newguy->t_stack[1] = 0x11;
	newguy->t_stack[2] = 0xda;
	newguy->t_stack[3] = 0x33;

	/* Inherit the current directory */
	if (curthread->t_cwd != NULL) {
		VOP_INCREF(curthread->t_cwd);
		newguy->t_cwd = curthread->t_cwd;
	}
	
	/* Set up the pcb (this arranges for func to be called) */
	md_initpcb(&newguy->t_pcb, newguy->t_stack, data1, data2, func);

	/* Interrupts off for atomicity */
	s = splhigh();
	
	/*
	 * Make sure our data structures have enough space, so we won't
	 * run out later at an inconvenient time.
	 */
	result = array_preallocate(sleepers, numthreads+1);
	if (result) {
		goto fail;
	}
	result = array_preallocate(zombies, numthreads+1);
	if (result) {
		goto fail;
	}

	/* Do the same for the scheduler. */
	result = scheduler_preallocate(numthreads+1);
	if (result) {
		goto fail;
	}

	/* Make the new thread runnable */
	result = make_runnable(newguy);
	if (result != 0) {
		goto fail;
	}

	/*
	 * Increment the thread counter. This must be done atomically
	 * with the preallocate calls; otherwise the count can be
	 * temporarily too low, which would obviate its reason for
	 * existence.
	 */
	numthreads++;

	//The child's Parent PID (curthread->pid) is stored in its PPID
	newguy->parent_pid = curthread->pid;


	struct pid_node *temp;
	struct pid_node *temp2;	
	
	temp = find_node(curthread->pid); //return the pid_node of the parent.
		
	temp2 = find_node(newguy->pid); //return the pid_node of the forked child.

	if (temp->next_children == NULL) //this means that the parent has no children.
	{
		temp->next_children = temp2;
	}	
	else{ //HAS CHILDREN.
		temp = temp->next_children;
		while (temp->next_siblings != NULL){
			temp = temp->next_siblings;
		}
		temp->next_siblings = temp2;		
	
	}	
	

	/* Done with stuff that needs to be atomic */
	splx(s);

	/*
	 * Return new thread structure if it's wanted.  Note that
	 * using the thread structure from the parent thread should be
	 * done only with caution, because in general the child thread
	 * might exit at any time.
	 */
	 
	
	
	if (ret != NULL) {
		*ret = newguy;
	}

	return 0;
	

 fail:
	splx(s);
	if (newguy->t_cwd != NULL) {
		VOP_DECREF(newguy->t_cwd);
	}
	kfree(newguy->t_stack);
	kfree(newguy->t_name);
	kfree(newguy);

	return result;
}