コード例 #1
0
ファイル: sfs_vnode.c プロジェクト: mholden/os161
/*
 * Called when the vnode refcount (in-memory usage count) hits zero.
 *
 * This function should try to avoid returning errors other than EBUSY.
 */
static
int
sfs_reclaim(struct vnode *v)
{
	struct sfs_vnode *sv = v->vn_data;
	struct sfs_fs *sfs = v->vn_fs->fs_data;
	int ix, i, num, result;

	lock_acquire(sfs->sfs_vnodes_lock);

	/*
	 * Make sure someone else hasn't picked up the vnode since the
	 * decision was made to reclaim it. (You must also synchronize
	 * this with sfs_loadvnode.)
	 */
	lock_acquire(v->vn_countlock);
	if (v->vn_refcount != 1) {

		/* consume the reference VOP_DECREF gave us */
		assert(v->vn_refcount>1);
		v->vn_refcount--;

		lock_release(v->vn_countlock);
		lock_release(sfs->sfs_vnodes_lock);

		return EBUSY;
	}
	lock_release(v->vn_countlock);
	

	/* If there are no on-disk references to the file either, erase it. */
	if (sv->sv_i.sfi_linkcount==0 && sv->sv_i.sfi_type==SFS_TYPE_FILE) {
		/* 
		 * VOP_TRUNCATE doesn't work on directories, which is why I added
		 * the second requirement to the above if statement.
		 */
		result = VOP_TRUNCATE(&sv->sv_v, 0);
		if (result) {
			lock_release(sfs->sfs_vnodes_lock);
			return result;
		}
	}

	/* Sync the inode to disk */
	result = sfs_sync_inode(sv);
	if (result) {
		lock_release(sfs->sfs_vnodes_lock);
		return result;
	}

	/* If there are no on-disk references, discard the inode */
	if (sv->sv_i.sfi_linkcount==0) {
		sfs_bfree(sfs, sv->sv_ino);
	}

	/* Remove the vnode structure from the table in the struct sfs_fs. */
	ix = -1;
	num = array_getnum(sfs->sfs_vnodes);
	for (i=0; i<num; i++) {
		struct sfs_vnode *sv2 = array_getguy(sfs->sfs_vnodes, i);
		if (sv2==sv) {
			ix = i;
			break;
		}
	}
	if (ix<0) {
		panic("sfs: reclaim vnode %u not in vnode pool\n",
		      sv->sv_ino);
	}
	array_remove(sfs->sfs_vnodes, ix);

	VOP_KILL(&sv->sv_v);

	/* Release the storage for the vnode structure itself. */
	kfree(sv);

	lock_release(sfs->sfs_vnodes_lock);

	/* Done */
	return 0;
}
コード例 #2
0
ファイル: open.c プロジェクト: akat1/impala
errno_t
sc_open(thread_t *p, syscall_result_t *r, sc_open_args *arg)
{
    int fd;
    int flags = arg->flags;
    int error = 0;
    vnode_t *node;
    proc_t *proc = p->thr_proc;
    char fname[PATH_MAX+1];
    if((error = copyinstr(fname, arg->fname, PATH_MAX)))
        return error;
    KASSERT(proc->p_rootdir!=NULL);
    error = vfs_lookup(proc->p_curdir, &node, fname, p, LKP_NORMAL);
    if(error) {
        if(!(flags & O_CREAT))
            return error;
        vnode_t *parent;
        error = vfs_lookup_parent(proc->p_curdir, &parent, fname, p);
        if(error)
            return error;
        if((error = VOP_ACCESS(parent, W_OK, proc->p_cred))) {
            vrele(parent);
            return error;
        }
        vattr_t attr;
        attr.va_mode = arg->mode & ~(proc->p_umask) & 0777;
        attr.va_type = VNODE_TYPE_REG;
        attr.va_uid = proc->p_cred->p_uid;
        attr.va_gid = proc->p_cred->p_gid;
        attr.va_size = 0;
        attr.va_dev = NULL;
        error = VOP_CREATE(parent, &node, _get_last_cmpt(fname), &attr);
        VOP_UNLOCK(parent);
        if(error)
            return error;
        VOP_LOCK(node);
    } else {
        //plik istnieje
        if((flags & O_CREAT) && (flags & O_EXCL)) {
            vrele(node);
            return -EEXIST;
        }
        if((node->v_type == VNODE_TYPE_DIR) && (flags & (O_RDWR | O_WRONLY))) {
            vrele(node);
            return -EISDIR;
        }
    }
    int wmode = (flags & O_RDWR) ? (W_OK | R_OK) :
                (flags & O_RDONLY) ? (R_OK) : (W_OK);
    if((error = VOP_ACCESS(node, wmode, proc->p_cred))) {
        vrele(node);
        return error;
    }
    if((error = VOP_OPEN(node, flags, arg->mode))) {
        vrele(node);
        return error;
    }
    if(ISSET(flags, O_RDWR | O_WRONLY) && ISSET(flags, O_TRUNC)
       && node->v_type == VNODE_TYPE_REG)
        VOP_TRUNCATE(node, 0);

    if((error = f_alloc(proc, node, flags, &fd))) {
        vrele(node); // <- powinno to tutaj być, dopisałem bo nie było.
        return error;
    }
    VOP_UNLOCK(node);
    r->result = fd;
    return 0;
}
コード例 #3
0
ファイル: sfs_vnops.c プロジェクト: guzhuo0624/workonc-
/*
 * Called when the vnode refcount (in-memory usage count) hits zero.
 *
 * This function should try to avoid returning errors other than EBUSY.
 */
static
int
sfs_reclaim(struct vnode *v)
{
	struct sfs_vnode *sv = v->vn_data;
	struct sfs_fs *sfs = v->vn_fs->fs_data;
	unsigned ix, i, num;
	int result;

	vfs_biglock_acquire();

	/*
	 * Make sure someone else hasn't picked up the vnode since the
	 * decision was made to reclaim it. (You must also synchronize
	 * this with sfs_loadvnode.)
	 */
	if (v->vn_refcount != 1) {

		/* consume the reference VOP_DECREF gave us */
		KASSERT(v->vn_refcount>1);
		v->vn_refcount--;

		vfs_biglock_release();
		return EBUSY;
	}

	/* If there are no on-disk references to the file either, erase it. */
	if (sv->sv_i.sfi_linkcount==0) {
		result = VOP_TRUNCATE(&sv->sv_v, 0);
		if (result) {
			vfs_biglock_release();
			return result;
		}
	}

	/* Sync the inode to disk */
	result = sfs_sync_inode(sv);
	if (result) {
		vfs_biglock_release();
		return result;
	}

	/* If there are no on-disk references, discard the inode */
	if (sv->sv_i.sfi_linkcount==0) {
		sfs_bfree(sfs, sv->sv_ino);
	}

	/* Remove the vnode structure from the table in the struct sfs_fs. */
	num = vnodearray_num(sfs->sfs_vnodes);
	ix = num;
	for (i=0; i<num; i++) {
		struct vnode *v2 = vnodearray_get(sfs->sfs_vnodes, i);
		struct sfs_vnode *sv2 = v2->vn_data;
		if (sv2 == sv) {
			ix = i;
			break;
		}
	}
	if (ix == num) {
		panic("sfs: reclaim vnode %u not in vnode pool\n",
		      sv->sv_ino);
	}
	vnodearray_remove(sfs->sfs_vnodes, ix);

	VOP_CLEANUP(&sv->sv_v);

	vfs_biglock_release();

	/* Release the storage for the vnode structure itself. */
	kfree(sv);

	/* Done */
	return 0;
}
コード例 #4
0
ファイル: vfspath.c プロジェクト: Mr-Grieves/os161
/* Does most of the work for open(). */
int
vfs_open(char *path, int openflags, struct vnode **ret)
{
	int how;
	int result;
	int canwrite;
	struct vnode *vn = NULL;

	how = openflags & O_ACCMODE;

	switch (how) {
	    case O_RDONLY:
		canwrite=0;
		break;
	    case O_WRONLY:
	    case O_RDWR:
		canwrite=1;
		break;
	    default:
		return EINVAL;
	}

	if (openflags & O_CREAT) {
		char name[NAME_MAX+1];
		struct vnode *dir;
		int excl = (openflags & O_EXCL)!=0;
		
		result = vfs_lookparent(path, &dir, name, sizeof(name));
		if (result) {
			return result;
		}

		result = VOP_CREAT(dir, name, excl, &vn);

		VOP_DECREF(dir);
	}
	else {
		result = vfs_lookup(path, &vn);
	}

	if (result) {
		return result;
	}

	assert(vn != NULL);

	result = VOP_OPEN(vn, openflags);
	if (result) {
		VOP_DECREF(vn);
		return result;
	}

	VOP_INCOPEN(vn);
	
	if (openflags & O_TRUNC) {
		if (canwrite==0) {
			result = EINVAL;
		}
		else {
			result = VOP_TRUNCATE(vn, 0);
		}
		if (result) {
			VOP_DECOPEN(vn);
			VOP_DECREF(vn);
			return result;
		}
	}

	*ret = vn;

	return 0;
}