Example #1
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;
}
Example #2
0
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;
}
Example #3
0
static
int
sfs_mkdir(struct vnode *v, const char *name, mode_t mode)
{
	struct sfs_fs *sfs = v->vn_fs->fs_data;
	struct sfs_vnode *sv = v->vn_data;
	int result;
	uint32_t ino;
	struct sfs_dinode *dir_inodeptr;
	struct sfs_dinode *new_inodeptr;
	struct sfs_vnode *newguy;

	(void)mode;

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

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

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

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

	/* If it exists, fail */
	if (result==0) {
		result = EEXIST;
		goto die_simple;
	}

	/*
	 * If we're trying to create . or .. and we get this far
	 * (meaning the entry in question is missing), the fs is
	 * corrupted. Let's not make it worse. Best at this point to
	 * bail out and run fsck.
	 */
	if (!strcmp(name, ".") || !strcmp(name, "..")) {
		panic("sfs: %s: No %s entry in dir %u; please fsck\n",
		      sfs->sfs_sb.sb_volname, name, sv->sv_ino);
	}

	result = sfs_makeobj(sfs, SFS_TYPE_DIR, &newguy);
	if (result) {
		goto die_simple;
	}
	new_inodeptr = sfs_dinode_map(newguy);

	result = sfs_dir_link(newguy, ".", newguy->sv_ino, NULL);
	if (result) {
		goto die_uncreate;
	}

	result = sfs_dir_link(newguy, "..", sv->sv_ino, NULL);
	if (result) {
		goto die_uncreate;
	}

	result = sfs_dir_link(sv, name, newguy->sv_ino, NULL);
	if (result) {
		goto die_uncreate;
	}

        /*
         * Increment link counts (Note: not until after the names are
         * added - that way if one fails, the link count will be zero,
         * and reclaim will dispose of the new directory.
         *
         * Note also that the name in the parent directory gets added
         * last, so there's no case in which we have to go back and
         * remove it.
         */

	new_inodeptr->sfi_linkcount += 2;
	dir_inodeptr->sfi_linkcount++;
	sfs_dinode_mark_dirty(newguy);
	sfs_dinode_mark_dirty(sv);

	sfs_dinode_unload(newguy);
	sfs_dinode_unload(sv);
	lock_release(newguy->sv_lock);
	lock_release(sv->sv_lock);
	VOP_DECREF(&newguy->sv_absvn);

	unreserve_buffers(SFS_BLOCKSIZE);

	KASSERT(result==0);
	return result;

die_uncreate:
	sfs_dinode_unload(newguy);
	lock_release(newguy->sv_lock);
	VOP_DECREF(&newguy->sv_absvn);

die_simple:
	sfs_dinode_unload(sv);

die_early:
	unreserve_buffers(SFS_BLOCKSIZE);
	lock_release(sv->sv_lock);
	return result;
}
Example #4
0
/*
 * Create a file. If EXCL is set, insist that the filename not already
 * exist; otherwise, if it already exists, just open it.
 *
 * Locking: Gets/releases the vnode lock for v. Does not lock the new vnode,
 * as nobody else can get to it except by searching the directory it's in,
 * which is locked.
 *
 * Requires up to 4 buffers as VOP_DECREF invocations may take 3.
 */
static
int
sfs_creat(struct vnode *v, const char *name, bool excl, mode_t mode,
	  struct vnode **ret)
{
	struct sfs_fs *sfs = v->vn_fs->fs_data;
	struct sfs_vnode *sv = v->vn_data;
	struct sfs_vnode *newguy;
	struct sfs_dinode *sv_dino;
	struct sfs_dinode *new_dino;
	uint32_t ino;
	int result;

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

	result = sfs_dinode_load(sv);
	if (result) {
		unreserve_buffers(SFS_BLOCKSIZE);
		lock_release(sv->sv_lock);
		return result;
	}
	sv_dino = sfs_dinode_map(sv);

	if (sv_dino->sfi_linkcount == 0) {
		sfs_dinode_unload(sv);
		unreserve_buffers(SFS_BLOCKSIZE);
		lock_release(sv->sv_lock);
		return ENOENT;
	}

	sfs_dinode_unload(sv);

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

	/* If it exists and we didn't want it to, fail */
	if (result==0 && excl) {
		unreserve_buffers(SFS_BLOCKSIZE);
		lock_release(sv->sv_lock);
		return EEXIST;
	}

	if (result==0) {
		/* We got something; load its vnode and return */
		result = sfs_loadvnode(sfs, ino, SFS_TYPE_INVAL, &newguy);
		if (result) {
			unreserve_buffers(SFS_BLOCKSIZE);
			lock_release(sv->sv_lock);
			return result;
		}

		*ret = &newguy->sv_absvn;
		unreserve_buffers(SFS_BLOCKSIZE);
		lock_release(sv->sv_lock);
		return 0;
	}

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

	/* sfs_makeobj loads the inode for us */
	new_dino = sfs_dinode_map(newguy);

	/* We don't currently support file permissions; ignore MODE */
	(void)mode;

	/* Link it into the directory */
	result = sfs_dir_link(sv, name, newguy->sv_ino, NULL);
	if (result) {
		sfs_dinode_unload(newguy);
		lock_release(newguy->sv_lock);
		VOP_DECREF(&newguy->sv_absvn);
		lock_release(sv->sv_lock);
		unreserve_buffers(SFS_BLOCKSIZE);
		return result;
	}

	/* Update the linkcount of the new file */
	new_dino->sfi_linkcount++;

	/* and consequently mark it dirty. */
	sfs_dinode_mark_dirty(newguy);

	*ret = &newguy->sv_absvn;

	sfs_dinode_unload(newguy);
	unreserve_buffers(SFS_BLOCKSIZE);
	lock_release(newguy->sv_lock);
	lock_release(sv->sv_lock);
	return 0;
}
Example #5
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, bool excl, mode_t mode,
	  struct vnode **ret)
{
	struct sfs_fs *sfs = v->vn_fs->fs_data;
	struct sfs_vnode *sv = v->vn_data;
	struct sfs_vnode *newguy;
	uint32_t ino;
	int result;

	vfs_biglock_acquire();

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

	/* If it exists and we didn't want it to, fail */
	if (result==0 && excl) {
		vfs_biglock_release();
		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) {
			vfs_biglock_release();
			return result;
		}
		*ret = &newguy->sv_v;
		vfs_biglock_release();
		return 0;
	}

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

	/* We don't currently support file permissions; ignore MODE */
	(void)mode;

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

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

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

	*ret = &newguy->sv_v;
	
	vfs_biglock_release();
	return 0;
}