Example #1
0
static int
nandfs_process_bdesc(struct nandfs_device *nffsdev, struct nandfs_bdesc *bd,
    uint64_t nmembs)
{
	struct nandfs_node *dat_node;
	struct buf *bp;
	uint64_t i;
	int error;

	dat_node = nffsdev->nd_dat_node;

	VOP_LOCK(NTOV(dat_node), LK_EXCLUSIVE);

	for (i = 0; i < nmembs; i++) {
		if (!bd[i].bd_alive)
			continue;
		DPRINTF(CLEAN, ("%s: idx %jx offset %jx\n",
		    __func__, i, bd[i].bd_offset));
		if (bd[i].bd_level) {
			error = nandfs_bread_meta(dat_node, bd[i].bd_offset,
			    NULL, 0, &bp);
			if (error) {
				nandfs_error("%s: cannot read dat node "
				    "level:%d\n", __func__, bd[i].bd_level);
				brelse(bp);
				VOP_UNLOCK(NTOV(dat_node), 0);
				return (error);
			}
			nandfs_dirty_buf_meta(bp, 1);
			nandfs_bmap_dirty_blocks(VTON(bp->b_vp), bp, 1);
		} else {
			error = nandfs_bread(dat_node, bd[i].bd_offset, NULL,
			    0, &bp);
			if (error) {
				nandfs_error("%s: cannot read dat node\n",
				    __func__);
				brelse(bp);
				VOP_UNLOCK(NTOV(dat_node), 0);
				return (error);
			}
			nandfs_dirty_buf(bp, 1);
		}
		DPRINTF(CLEAN, ("%s: bp: %p\n", __func__, bp));
	}

	VOP_UNLOCK(NTOV(dat_node), 0);

	return (0);
}
Example #2
0
File: udf.c Project: coyizumi/cs111
int
udf_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
{
	struct udf_node node;
	struct udf_mnt mnt;
	int error;

	assert(kd);
	assert(vn);
	error = kvm_read_all(kd, (unsigned long)VTON(vp), &node, sizeof(node));
	if (error != 0) {
		warnx("can't read udf fnode at %p", (void *)VTON(vp));
		return (1);
	}
        error = kvm_read_all(kd, (unsigned long)node.udfmp, &mnt, sizeof(mnt));
        if (error != 0) {
                warnx("can't read udf_mnt at %p for vnode %p",
                    (void *)node.udfmp, vp);
                return (1);
        }
	vn->vn_fileid = node.hash_id;
	vn->vn_fsid = dev2udev(kd, mnt.im_dev);
	return (0);
}
Example #3
0
int
nandfs_update_dirent(struct vnode *dvp, struct nandfs_node *fnode,
    struct nandfs_node *tnode)
{
	struct nandfs_node *dir_node;
	struct nandfs_dir_entry *dirent;
	struct buf *bp;
	uint64_t file_size, blocknr;
	uint32_t blocksize, off;
	uint8_t *pos;
	int error;

	dir_node = VTON(dvp);
	file_size = dir_node->nn_inode.i_size;
	if (!file_size)
		return (0);

	DPRINTF(LOOKUP,
	    ("chg direntry dvp %p ino %#jx  to in %#jx at off %#jx\n",
	    dvp, (uintmax_t)tnode->nn_ino, (uintmax_t)fnode->nn_ino,
	    (uintmax_t)tnode->nn_diroff));

	blocksize = dir_node->nn_nandfsdev->nd_blocksize;
	blocknr = tnode->nn_diroff / blocksize;
	off = tnode->nn_diroff % blocksize;
	error = nandfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
	if (error) {
		brelse(bp);
		return (error);
	}

	pos = bp->b_data;
	dirent = (struct nandfs_dir_entry *) (pos + off);
	KASSERT((dirent->inode == tnode->nn_ino),
	    ("direntry mismatch"));

	dirent->inode = fnode->nn_ino;
	error = nandfs_dirty_buf(bp, 0);
	if (error)
		return (error);

	return (0);
}
Example #4
0
int
nandfs_update_parent_dir(struct vnode *dvp, uint64_t newparent)
{
	struct nandfs_dir_entry *dirent;
	struct nandfs_node *dir_node;
	struct buf *bp;
	int error;

	dir_node = VTON(dvp);
	error = nandfs_bread(dir_node, 0, NOCRED, 0, &bp);
	if (error) {
		brelse(bp);
		return (error);
	}
	dirent = (struct nandfs_dir_entry *)bp->b_data;
	dirent->inode = newparent;
	error = nandfs_dirty_buf(bp, 0);
	if (error)
		return (error);

	return (0);
}
Example #5
0
static int
udf_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp)
{
	struct ifid *ifhp;
	struct vnode *nvp;
	struct udf_node *np;
	off_t fsize;
	int error;

	ifhp = (struct ifid *)fhp;

	if ((error = VFS_VGET(mp, ifhp->ifid_ino, LK_EXCLUSIVE, &nvp)) != 0) {
		*vpp = NULLVP;
		return (error);
	}

	np = VTON(nvp);
	fsize = le64toh(np->fentry->inf_len);

	*vpp = nvp;
	vnode_create_vobject(*vpp, fsize, curthread);
	return (0);
}
Example #6
0
int
nandfs_add_dirent(struct vnode *dvp, uint64_t ino, char *nameptr, long namelen,
    uint8_t type)
{
	struct nandfs_node *dir_node = VTON(dvp);
	struct nandfs_dir_entry *dirent, *pdirent;
	uint32_t blocksize = dir_node->nn_nandfsdev->nd_blocksize;
	uint64_t filesize = dir_node->nn_inode.i_size;
	uint64_t inode_blks = dir_node->nn_inode.i_blocks;
	uint32_t off, rest;
	uint8_t *pos;
	struct buf *bp;
	int error;

	pdirent = NULL;
	bp = NULL;
	if (inode_blks) {
		error = nandfs_bread(dir_node, inode_blks - 1, NOCRED, 0, &bp);
		if (error) {
			brelse(bp);
			return (error);
		}

		pos = bp->b_data;
		off = 0;
		while (off < blocksize) {
			pdirent = (struct nandfs_dir_entry *) (pos + off);
			if (!pdirent->rec_len) {
				pdirent = NULL;
				break;
			}
			off += pdirent->rec_len;
		}

		if (pdirent)
			rest = pdirent->rec_len -
			    NANDFS_DIR_REC_LEN(pdirent->name_len);
		else
			rest = blocksize;

		if (rest < NANDFS_DIR_REC_LEN(namelen)) {
			/* Do not update pdirent as new block is created */
			pdirent = NULL;
			brelse(bp);
			/* Set to NULL to create new */
			bp = NULL;
			filesize += rest;
		}
	}

	/* If no bp found create new */
	if (!bp) {
		error = nandfs_bcreate(dir_node, inode_blks, NOCRED, 0, &bp);
		if (error)
			return (error);
		off = 0;
		pos = bp->b_data;
	}

	/* Modify pdirent if exists */
	if (pdirent) {
		DPRINTF(LOOKUP, ("modify pdirent %p\n", pdirent));
		/* modify last de */
		off -= pdirent->rec_len;
		pdirent->rec_len =
		    NANDFS_DIR_REC_LEN(pdirent->name_len);
		off += pdirent->rec_len;
	}

	/* Create new dirent */
	dirent = (struct nandfs_dir_entry *) (pos + off);
	dirent->rec_len = blocksize - off;
	dirent->inode = ino;
	dirent->name_len = namelen;
	memset(dirent->name, 0, NANDFS_DIR_NAME_LEN(namelen));
	memcpy(dirent->name, nameptr, namelen);
	dirent->file_type = type;

	filesize += NANDFS_DIR_REC_LEN(dirent->name_len);

	DPRINTF(LOOKUP, ("create dir_entry '%.*s' at %p with size %x "
	    "new filesize: %jx\n",
	    (int)namelen, dirent->name, dirent, dirent->rec_len,
	    (uintmax_t)filesize));

	error = nandfs_dirty_buf(bp, 0);
	if (error)
		return (error);

	dir_node->nn_inode.i_size = filesize;
	dir_node->nn_flags |= IN_CHANGE | IN_UPDATE;
	vnode_pager_setsize(dvp, filesize);

	return (0);
}
Example #7
0
int
nandfs_remove_dirent(struct vnode *dvp, struct nandfs_node *node,
    struct componentname *cnp)
{
	struct nandfs_node *dir_node;
	struct nandfs_dir_entry *dirent, *pdirent;
	struct buf *bp;
	uint64_t filesize, blocknr, ino, offset;
	uint32_t blocksize, limit, off;
	uint16_t newsize;
	uint8_t *pos;
	int error, found;

	dir_node = VTON(dvp);
	filesize = dir_node->nn_inode.i_size;
	if (!filesize)
		return (0);

	if (node) {
		offset = node->nn_diroff;
		ino = node->nn_ino;
	} else {
		offset = dir_node->nn_diroff;
		ino = NANDFS_WHT_INO;
	}

	dirent = pdirent = NULL;
	blocksize = dir_node->nn_nandfsdev->nd_blocksize;
	blocknr = offset / blocksize;

	DPRINTF(LOOKUP, ("rm direntry dvp %p node %p ino %#jx at off %#jx\n",
	    dvp, node, (uintmax_t)ino, (uintmax_t)offset));

	error = nandfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
	if (error) {
		brelse(bp);
		return (error);
	}

	pos = bp->b_data;
	off = 0;
	found = 0;
	limit = offset % blocksize;
	pdirent = (struct nandfs_dir_entry *) bp->b_data;
	while (off <= limit) {
		dirent = (struct nandfs_dir_entry *) (pos + off);

		if ((off == limit) &&
		    (dirent->inode == ino)) {
			found = 1;
			break;
		}
		if (dirent->inode != 0)
			pdirent = dirent;
		off += dirent->rec_len;
	}

	if (!found) {
		nandfs_error("cannot find entry to remove");
		brelse(bp);
		return (error);
	}
	DPRINTF(LOOKUP,
	    ("rm dirent ino %#jx at %#x with size %#x\n",
	    (uintmax_t)dirent->inode, off, dirent->rec_len));

	newsize = (uintptr_t)dirent - (uintptr_t)pdirent;
	newsize += dirent->rec_len;
	pdirent->rec_len = newsize;
	dirent->inode = 0;
	error = nandfs_dirty_buf(bp, 0);
	if (error)
		return (error);

	dir_node->nn_flags |= IN_CHANGE | IN_UPDATE;
	/* If last one modify filesize */
	if ((offset + NANDFS_DIR_REC_LEN(dirent->name_len)) == filesize) {
		filesize = blocknr * blocksize +
		    ((uintptr_t)pdirent - (uintptr_t)pos) +
		    NANDFS_DIR_REC_LEN(pdirent->name_len);
		dir_node->nn_inode.i_size = filesize;
	}

	return (0);
}