Home | History | Annotate | Line # | Download | only in chfs
chfs_write.c revision 1.3
      1  1.3  ttoth /*	$NetBSD: chfs_write.c,v 1.3 2012/04/12 15:31:01 ttoth Exp $	*/
      2  1.1  ahoka 
      3  1.1  ahoka /*-
      4  1.1  ahoka  * Copyright (c) 2010 Department of Software Engineering,
      5  1.1  ahoka  *		      University of Szeged, Hungary
      6  1.1  ahoka  * Copyright (C) 2010 David Tengeri <dtengeri (at) inf.u-szeged.hu>
      7  1.1  ahoka  * Copyright (C) 2010 Tamas Toth <ttoth (at) inf.u-szeged.hu>
      8  1.1  ahoka  * Copyright (C) 2010 Adam Hoka <ahoka (at) NetBSD.org>
      9  1.1  ahoka  * All rights reserved.
     10  1.1  ahoka  *
     11  1.1  ahoka  * This code is derived from software contributed to The NetBSD Foundation
     12  1.1  ahoka  * by the Department of Software Engineering, University of Szeged, Hungary
     13  1.1  ahoka  *
     14  1.1  ahoka  * Redistribution and use in source and binary forms, with or without
     15  1.1  ahoka  * modification, are permitted provided that the following conditions
     16  1.1  ahoka  * are met:
     17  1.1  ahoka  * 1. Redistributions of source code must retain the above copyright
     18  1.1  ahoka  *    notice, this list of conditions and the following disclaimer.
     19  1.1  ahoka  * 2. Redistributions in binary form must reproduce the above copyright
     20  1.1  ahoka  *    notice, this list of conditions and the following disclaimer in the
     21  1.1  ahoka  *    documentation and/or other materials provided with the distribution.
     22  1.1  ahoka  *
     23  1.1  ahoka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     24  1.1  ahoka  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25  1.1  ahoka  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26  1.1  ahoka  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     27  1.1  ahoka  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     28  1.1  ahoka  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     29  1.1  ahoka  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     30  1.1  ahoka  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     31  1.1  ahoka  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  1.1  ahoka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  1.1  ahoka  * SUCH DAMAGE.
     34  1.1  ahoka  */
     35  1.1  ahoka 
     36  1.1  ahoka /*
     37  1.1  ahoka  * chfs_write.c
     38  1.1  ahoka  *
     39  1.1  ahoka  *  Created on: 2010.02.17.
     40  1.1  ahoka  *      Author: dtengeri
     41  1.1  ahoka  */
     42  1.1  ahoka 
     43  1.1  ahoka #include <sys/param.h>
     44  1.1  ahoka #include <sys/buf.h>
     45  1.1  ahoka 
     46  1.1  ahoka #include "chfs.h"
     47  1.1  ahoka 
     48  1.1  ahoka int
     49  1.1  ahoka chfs_write_flash_vnode(struct chfs_mount *chmp,
     50  1.1  ahoka     struct chfs_inode *ip, int prio)
     51  1.1  ahoka {
     52  1.1  ahoka 	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
     53  1.1  ahoka 
     54  1.1  ahoka 	struct chfs_flash_vnode *fvnode;
     55  1.1  ahoka 	struct chfs_vnode_cache* chvc;
     56  1.1  ahoka 	struct chfs_node_ref *nref;
     57  1.1  ahoka 	struct iovec vec;
     58  1.1  ahoka 	size_t size, retlen;
     59  1.1  ahoka 	int err = 0, retries = 0;
     60  1.1  ahoka 
     61  1.1  ahoka 	if (ip->ino == CHFS_ROOTINO)
     62  1.1  ahoka 		return 0;
     63  1.1  ahoka 
     64  1.1  ahoka 	fvnode = chfs_alloc_flash_vnode();
     65  1.1  ahoka 	if (!fvnode)
     66  1.1  ahoka 		return ENOMEM;
     67  1.1  ahoka 
     68  1.1  ahoka 	chvc = ip->chvc;
     69  1.1  ahoka 
     70  1.1  ahoka 	/* setting up flash_vnode members */
     71  1.1  ahoka 	size = sizeof(*fvnode);
     72  1.1  ahoka 	//dbg("size: %zu | PADDED: %zu\n", size, CHFS_PAD(size));
     73  1.1  ahoka 	fvnode->magic = htole16(CHFS_FS_MAGIC_BITMASK);
     74  1.1  ahoka 	fvnode->type = htole16(CHFS_NODETYPE_VNODE);
     75  1.1  ahoka 	fvnode->length = htole32(CHFS_PAD(size));
     76  1.1  ahoka 	fvnode->hdr_crc = htole32(crc32(0, (uint8_t *)fvnode,
     77  1.1  ahoka 		CHFS_NODE_HDR_SIZE - 4));
     78  1.1  ahoka 	fvnode->vno = htole64(ip->ino);
     79  1.1  ahoka 	fvnode->version = htole64(++ip->chvc->highest_version);
     80  1.1  ahoka 	fvnode->mode = htole32(ip->mode);
     81  1.1  ahoka 	fvnode->dn_size = htole32(ip->size);
     82  1.1  ahoka 	fvnode->atime = htole32(ip->atime);
     83  1.1  ahoka 	fvnode->ctime = htole32(ip->ctime);
     84  1.1  ahoka 	fvnode->mtime = htole32(ip->mtime);
     85  1.1  ahoka 	fvnode->gid = htole32(ip->gid);
     86  1.1  ahoka 	fvnode->uid = htole32(ip->uid);
     87  1.1  ahoka 	fvnode->node_crc = htole32(crc32(0, (uint8_t *)fvnode, size - 4));
     88  1.1  ahoka 
     89  1.1  ahoka 	/* write out flash_vnode */
     90  1.1  ahoka retry:
     91  1.1  ahoka 	if (prio == ALLOC_GC) {
     92  1.1  ahoka 		/* the GC calls this function */
     93  1.1  ahoka 		err = chfs_reserve_space_gc(chmp, CHFS_PAD(size));
     94  1.1  ahoka 		if (err)
     95  1.1  ahoka 			goto out;
     96  1.1  ahoka 	} else {
     97  1.1  ahoka 		chfs_gc_trigger(chmp);
     98  1.1  ahoka 		if (prio == ALLOC_NORMAL)
     99  1.1  ahoka 			err = chfs_reserve_space_normal(chmp,
    100  1.1  ahoka 			    CHFS_PAD(size), ALLOC_NORMAL);
    101  1.1  ahoka 		else
    102  1.1  ahoka 			err = chfs_reserve_space_normal(chmp,
    103  1.1  ahoka 			    CHFS_PAD(size), ALLOC_DELETION);
    104  1.1  ahoka 		if (err)
    105  1.1  ahoka 			goto out;
    106  1.1  ahoka 	}
    107  1.1  ahoka 
    108  1.1  ahoka 	nref = chfs_alloc_node_ref(chmp->chm_nextblock);
    109  1.1  ahoka 	if (!nref) {
    110  1.1  ahoka 		err = ENOMEM;
    111  1.1  ahoka 		goto out;
    112  1.1  ahoka 	}
    113  1.1  ahoka 
    114  1.1  ahoka 	mutex_enter(&chmp->chm_lock_sizes);
    115  1.1  ahoka 
    116  1.1  ahoka 	nref->nref_offset = chmp->chm_ebh->eb_size - chmp->chm_nextblock->free_size;
    117  1.1  ahoka 	chfs_change_size_free(chmp, chmp->chm_nextblock, -CHFS_PAD(size));
    118  1.1  ahoka 	vec.iov_base = fvnode;
    119  1.1  ahoka 	vec.iov_len = CHFS_PAD(size);
    120  1.1  ahoka 	err = chfs_write_wbuf(chmp, &vec, 1, nref->nref_offset, &retlen);
    121  1.1  ahoka 	if (err || retlen != CHFS_PAD(size)) {
    122  1.1  ahoka 		chfs_err("error while writing out flash vnode to the media\n");
    123  1.1  ahoka 		chfs_err("err: %d | size: %zu | retlen : %zu\n",
    124  1.1  ahoka 		    err, CHFS_PAD(size), retlen);
    125  1.1  ahoka 		chfs_change_size_dirty(chmp,
    126  1.1  ahoka 		    chmp->chm_nextblock, CHFS_PAD(size));
    127  1.1  ahoka 		if (retries) {
    128  1.1  ahoka 			err = EIO;
    129  1.1  ahoka 			mutex_exit(&chmp->chm_lock_sizes);
    130  1.1  ahoka 			goto out;
    131  1.1  ahoka 		}
    132  1.1  ahoka 
    133  1.1  ahoka 		retries++;
    134  1.1  ahoka 		mutex_exit(&chmp->chm_lock_sizes);
    135  1.1  ahoka 		goto retry;
    136  1.1  ahoka 	}
    137  1.1  ahoka 	//Everything went well
    138  1.1  ahoka 	chfs_change_size_used(chmp,
    139  1.1  ahoka 	    &chmp->chm_blocks[nref->nref_lnr], CHFS_PAD(size));
    140  1.1  ahoka 	mutex_exit(&chmp->chm_lock_sizes);
    141  1.1  ahoka 
    142  1.1  ahoka 	chfs_add_vnode_ref_to_vc(chmp, chvc, nref);
    143  1.1  ahoka 	KASSERT(chmp->chm_blocks[nref->nref_lnr].used_size <= chmp->chm_ebh->eb_size);
    144  1.1  ahoka out:
    145  1.1  ahoka 	chfs_free_flash_vnode(fvnode);
    146  1.1  ahoka 	return err;
    147  1.1  ahoka }
    148  1.1  ahoka 
    149  1.1  ahoka int
    150  1.1  ahoka chfs_write_flash_dirent(struct chfs_mount *chmp, struct chfs_inode *pdir,
    151  1.1  ahoka     struct chfs_inode *ip, struct chfs_dirent *fd,
    152  1.1  ahoka     ino_t ino, int prio)
    153  1.1  ahoka {
    154  1.1  ahoka 	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
    155  1.1  ahoka 
    156  1.1  ahoka 	struct chfs_flash_dirent_node *fdirent;
    157  1.1  ahoka 	struct chfs_node_ref *nref;
    158  1.1  ahoka 	struct iovec vec[2];
    159  1.1  ahoka 	size_t size, retlen;
    160  1.1  ahoka 	int err = 0, retries = 0;
    161  1.1  ahoka 	uint8_t *name;
    162  1.1  ahoka 	size_t namelen;
    163  1.1  ahoka 
    164  1.1  ahoka 	KASSERT(fd->vno != CHFS_ROOTINO);
    165  1.1  ahoka 
    166  1.1  ahoka 	fdirent = chfs_alloc_flash_dirent();
    167  1.1  ahoka 	if (!fdirent)
    168  1.1  ahoka 		return ENOMEM;
    169  1.1  ahoka 
    170  1.1  ahoka 	size = sizeof(*fdirent) + fd->nsize;
    171  1.1  ahoka 	namelen = CHFS_PAD(size) - sizeof(*fdirent);
    172  1.1  ahoka 
    173  1.1  ahoka 	name = kmem_zalloc(namelen, KM_SLEEP);
    174  1.1  ahoka 	memcpy(name, fd->name, fd->nsize);
    175  1.1  ahoka 	//dbg("namelen: %zu | nsize: %hhu\n", namelen, fd->nsize);
    176  1.1  ahoka 
    177  1.1  ahoka 
    178  1.1  ahoka 	//dbg("size: %zu | PADDED: %zu\n", size, CHFS_PAD(size));
    179  1.1  ahoka 	fdirent->magic = htole16(CHFS_FS_MAGIC_BITMASK);
    180  1.1  ahoka 	fdirent->type = htole16(CHFS_NODETYPE_DIRENT);
    181  1.1  ahoka 	fdirent->length = htole32(CHFS_PAD(size));
    182  1.1  ahoka 	fdirent->hdr_crc = htole32(crc32(0, (uint8_t *)fdirent,
    183  1.1  ahoka 		CHFS_NODE_HDR_SIZE - 4));
    184  1.1  ahoka 	fdirent->vno = htole64(ino);
    185  1.1  ahoka 	fdirent->pvno = htole64(pdir->ino);
    186  1.1  ahoka 	fdirent->version = htole64(++pdir->chvc->highest_version);
    187  1.1  ahoka 	fdirent->mctime = ip?ip->ctime:0;
    188  1.1  ahoka 	fdirent->nsize = fd->nsize;
    189  1.1  ahoka 	fdirent->dtype = fd->type;
    190  1.1  ahoka 	fdirent->name_crc = crc32(0, (uint8_t *)&(fd->name), fd->nsize);
    191  1.1  ahoka 	fdirent->node_crc = crc32(0, (uint8_t *)fdirent, sizeof(*fdirent) - 4);
    192  1.1  ahoka 
    193  1.1  ahoka 	vec[0].iov_base = fdirent;
    194  1.1  ahoka 	vec[0].iov_len  = sizeof(*fdirent);
    195  1.1  ahoka 	vec[1].iov_base = name;
    196  1.1  ahoka 	vec[1].iov_len  = namelen;
    197  1.1  ahoka 
    198  1.1  ahoka retry:
    199  1.1  ahoka 	if (prio == ALLOC_GC) {
    200  1.1  ahoka 		/* the GC calls this function */
    201  1.1  ahoka 		err = chfs_reserve_space_gc(chmp, CHFS_PAD(size));
    202  1.1  ahoka 		if (err)
    203  1.1  ahoka 			goto out;
    204  1.1  ahoka 	} else {
    205  1.1  ahoka 		chfs_gc_trigger(chmp);
    206  1.1  ahoka 		if (prio == ALLOC_NORMAL)
    207  1.1  ahoka 			err = chfs_reserve_space_normal(chmp,
    208  1.1  ahoka 			    CHFS_PAD(size), ALLOC_NORMAL);
    209  1.1  ahoka 		else
    210  1.1  ahoka 			err = chfs_reserve_space_normal(chmp,
    211  1.1  ahoka 			    CHFS_PAD(size), ALLOC_DELETION);
    212  1.1  ahoka 		if (err)
    213  1.1  ahoka 			goto out;
    214  1.1  ahoka 	}
    215  1.1  ahoka 
    216  1.1  ahoka 	nref = chfs_alloc_node_ref(chmp->chm_nextblock);
    217  1.1  ahoka 	if (!nref) {
    218  1.1  ahoka 		err = ENOMEM;
    219  1.1  ahoka 		goto out;
    220  1.1  ahoka 	}
    221  1.1  ahoka 
    222  1.1  ahoka 	mutex_enter(&chmp->chm_lock_sizes);
    223  1.1  ahoka 
    224  1.1  ahoka 	nref->nref_offset = chmp->chm_ebh->eb_size - chmp->chm_nextblock->free_size;
    225  1.1  ahoka 	chfs_change_size_free(chmp, chmp->chm_nextblock, -CHFS_PAD(size));
    226  1.1  ahoka 
    227  1.1  ahoka 	err = chfs_write_wbuf(chmp, vec, 2, nref->nref_offset, &retlen);
    228  1.1  ahoka 	if (err || retlen != CHFS_PAD(size)) {
    229  1.1  ahoka 		chfs_err("error while writing out flash dirent node to the media\n");
    230  1.1  ahoka 		chfs_err("err: %d | size: %zu | retlen : %zu\n",
    231  1.1  ahoka 		    err, CHFS_PAD(size), retlen);
    232  1.1  ahoka 		chfs_change_size_dirty(chmp,
    233  1.1  ahoka 		    chmp->chm_nextblock, CHFS_PAD(size));
    234  1.1  ahoka 		if (retries) {
    235  1.1  ahoka 			err = EIO;
    236  1.1  ahoka 			mutex_exit(&chmp->chm_lock_sizes);
    237  1.1  ahoka 			goto out;
    238  1.1  ahoka 		}
    239  1.1  ahoka 
    240  1.1  ahoka 		retries++;
    241  1.1  ahoka 		mutex_exit(&chmp->chm_lock_sizes);
    242  1.1  ahoka 		goto retry;
    243  1.1  ahoka 	}
    244  1.1  ahoka 
    245  1.1  ahoka 
    246  1.1  ahoka 	// Everything went well
    247  1.1  ahoka 	chfs_change_size_used(chmp,
    248  1.1  ahoka 	    &chmp->chm_blocks[nref->nref_lnr], CHFS_PAD(size));
    249  1.1  ahoka 	mutex_exit(&chmp->chm_lock_sizes);
    250  1.1  ahoka 	KASSERT(chmp->chm_blocks[nref->nref_lnr].used_size <= chmp->chm_ebh->eb_size);
    251  1.1  ahoka 	fd->nref = nref;
    252  1.1  ahoka 	if (prio != ALLOC_DELETION) {
    253  1.1  ahoka 		chfs_add_node_to_list(chmp,
    254  1.1  ahoka 			pdir->chvc, nref, &pdir->chvc->dirents);
    255  1.1  ahoka 	}
    256  1.1  ahoka out:
    257  1.1  ahoka 	chfs_free_flash_dirent(fdirent);
    258  1.1  ahoka 	return err;
    259  1.1  ahoka }
    260  1.1  ahoka 
    261  1.1  ahoka /**
    262  1.1  ahoka  * chfs_write_flash_dnode - write out a data node to flash
    263  1.1  ahoka  * @chmp: chfs mount structure
    264  1.1  ahoka  * @vp: vnode where the data belongs to
    265  1.1  ahoka  * @bp: buffer contains data
    266  1.1  ahoka  */
    267  1.1  ahoka int
    268  1.1  ahoka chfs_write_flash_dnode(struct chfs_mount *chmp, struct vnode *vp,
    269  1.1  ahoka     struct buf *bp, struct chfs_full_dnode *fd)
    270  1.1  ahoka {
    271  1.1  ahoka 	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
    272  1.1  ahoka 
    273  1.1  ahoka 	int err = 0, retries = 0;
    274  1.1  ahoka 	size_t size, retlen;
    275  1.1  ahoka 	off_t ofs;
    276  1.1  ahoka 	struct chfs_flash_data_node *dnode;
    277  1.1  ahoka 	struct chfs_node_ref *nref;
    278  1.1  ahoka 	struct chfs_inode *ip = VTOI(vp);
    279  1.1  ahoka 	struct iovec vec[2];
    280  1.1  ahoka 	uint32_t len;
    281  1.1  ahoka 	void *tmpbuf = NULL;
    282  1.1  ahoka 
    283  1.1  ahoka 	KASSERT(ip->ino != CHFS_ROOTINO);
    284  1.1  ahoka 
    285  1.1  ahoka 	dnode = chfs_alloc_flash_dnode();
    286  1.1  ahoka 	if (!dnode)
    287  1.1  ahoka 		return ENOMEM;
    288  1.1  ahoka 
    289  1.1  ahoka 	/* initialize flash data node */
    290  1.1  ahoka 	ofs = bp->b_blkno * PAGE_SIZE;
    291  1.1  ahoka 	//dbg("vp->v_size: %ju, bp->b_blkno: %ju, bp-b_data: %p,"
    292  1.1  ahoka 	//    " bp->b_resid: %ju\n",
    293  1.1  ahoka 	//    (uintmax_t )vp->v_size, (uintmax_t )bp->b_blkno,
    294  1.1  ahoka 	//    bp->b_data, (uintmax_t )bp->b_resid);
    295  1.1  ahoka 	//dbg("[XXX]vp->v_size - ofs: %llu\n", (vp->v_size - ofs));
    296  1.1  ahoka 	len = MIN((vp->v_size - ofs), bp->b_resid);
    297  1.1  ahoka 	size = sizeof(*dnode) + len;
    298  1.1  ahoka 
    299  1.1  ahoka 	dnode->magic = htole16(CHFS_FS_MAGIC_BITMASK);
    300  1.1  ahoka 	dnode->type = htole16(CHFS_NODETYPE_DATA);
    301  1.1  ahoka 	dnode->length = htole32(CHFS_PAD(size));
    302  1.1  ahoka 	dnode->hdr_crc = htole32(crc32(0, (uint8_t *)dnode,
    303  1.1  ahoka 		CHFS_NODE_HDR_SIZE - 4));
    304  1.1  ahoka 	dnode->vno = htole64(ip->ino);
    305  1.1  ahoka 	dnode->version = htole64(++ip->chvc->highest_version);
    306  1.1  ahoka 	dnode->offset = htole64(ofs);
    307  1.1  ahoka 	dnode->data_length = htole32(len);
    308  1.1  ahoka 	dnode->data_crc = htole32(crc32(0, (uint8_t *)bp->b_data, len));
    309  1.1  ahoka 	dnode->node_crc = htole32(crc32(0, (uint8_t *)dnode,
    310  1.1  ahoka 		sizeof(*dnode) - 4));
    311  1.1  ahoka 
    312  1.2    agc 	dbg("dnode @%llu %ub v%llu\n", (unsigned long long)dnode->offset,
    313  1.2    agc 		dnode->data_length, (unsigned long long)dnode->version);
    314  1.1  ahoka 
    315  1.1  ahoka 	if (CHFS_PAD(size) - sizeof(*dnode)) {
    316  1.1  ahoka 		tmpbuf = kmem_zalloc(CHFS_PAD(size)
    317  1.1  ahoka 		    - sizeof(*dnode), KM_SLEEP);
    318  1.1  ahoka 		memcpy(tmpbuf, bp->b_data, len);
    319  1.1  ahoka 	}
    320  1.1  ahoka 
    321  1.1  ahoka 	/* creating iovecs for wbuf */
    322  1.1  ahoka 	vec[0].iov_base = dnode;
    323  1.1  ahoka 	vec[0].iov_len = sizeof(*dnode);
    324  1.1  ahoka 	vec[1].iov_base = tmpbuf;
    325  1.1  ahoka 	vec[1].iov_len = CHFS_PAD(size) - sizeof(*dnode);
    326  1.1  ahoka 
    327  1.1  ahoka 	fd->frags = 0;
    328  1.1  ahoka 	fd->ofs = ofs;
    329  1.1  ahoka 	fd->size = len;
    330  1.1  ahoka 
    331  1.1  ahoka retry:
    332  1.1  ahoka 
    333  1.1  ahoka 	/* Reserve space for data node. This will set up the next eraseblock
    334  1.1  ahoka 	 * where to we will write.
    335  1.1  ahoka 	 */
    336  1.1  ahoka 
    337  1.1  ahoka 	chfs_gc_trigger(chmp);
    338  1.1  ahoka 	err = chfs_reserve_space_normal(chmp,
    339  1.1  ahoka 	    CHFS_PAD(size), ALLOC_NORMAL);
    340  1.1  ahoka 	if (err)
    341  1.1  ahoka 		goto out;
    342  1.1  ahoka 
    343  1.1  ahoka 	nref = chfs_alloc_node_ref(chmp->chm_nextblock);
    344  1.1  ahoka 	if (!nref) {
    345  1.1  ahoka 		err = ENOMEM;
    346  1.1  ahoka 		goto out;
    347  1.1  ahoka 	}
    348  1.1  ahoka 
    349  1.1  ahoka 	nref->nref_offset =
    350  1.1  ahoka 	    chmp->chm_ebh->eb_size - chmp->chm_nextblock->free_size;
    351  1.1  ahoka 
    352  1.1  ahoka 	KASSERT(nref->nref_offset < chmp->chm_ebh->eb_size);
    353  1.1  ahoka 
    354  1.1  ahoka 	mutex_enter(&chmp->chm_lock_sizes);
    355  1.1  ahoka 
    356  1.1  ahoka 	chfs_change_size_free(chmp,
    357  1.1  ahoka 	    chmp->chm_nextblock, -CHFS_PAD(size));
    358  1.1  ahoka 
    359  1.1  ahoka 	//dbg("vno: %llu nref lnr: %u offset: %u\n",
    360  1.1  ahoka 	//    dnode->vno, nref->nref_lnr, nref->nref_offset);
    361  1.1  ahoka 
    362  1.1  ahoka 	err = chfs_write_wbuf(chmp, vec, 2, nref->nref_offset, &retlen);
    363  1.1  ahoka 	if (err || retlen != CHFS_PAD(size)) {
    364  1.1  ahoka 		chfs_err("error while writing out flash data node to the media\n");
    365  1.1  ahoka 		chfs_err("err: %d | size: %zu | retlen : %zu\n",
    366  1.1  ahoka 		    err, size, retlen);
    367  1.1  ahoka 		chfs_change_size_dirty(chmp,
    368  1.1  ahoka 		    chmp->chm_nextblock, CHFS_PAD(size));
    369  1.1  ahoka 		if (retries) {
    370  1.1  ahoka 			err = EIO;
    371  1.1  ahoka 			mutex_exit(&chmp->chm_lock_sizes);
    372  1.1  ahoka 			goto out;
    373  1.1  ahoka 		}
    374  1.1  ahoka 
    375  1.1  ahoka 		retries++;
    376  1.1  ahoka 		mutex_exit(&chmp->chm_lock_sizes);
    377  1.1  ahoka 		goto retry;
    378  1.1  ahoka 	}
    379  1.1  ahoka 	/* Everything went well */
    380  1.1  ahoka 	ip->write_size += fd->size;
    381  1.1  ahoka 	chfs_change_size_used(chmp,
    382  1.1  ahoka 	    &chmp->chm_blocks[nref->nref_lnr], CHFS_PAD(size));
    383  1.1  ahoka 	mutex_exit(&chmp->chm_lock_sizes);
    384  1.1  ahoka 
    385  1.1  ahoka 	KASSERT(chmp->chm_blocks[nref->nref_lnr].used_size <= chmp->chm_ebh->eb_size);
    386  1.1  ahoka 	fd->nref = nref;
    387  1.1  ahoka 	chfs_add_node_to_list(chmp, ip->chvc, nref, &ip->chvc->dnode);
    388  1.1  ahoka out:
    389  1.1  ahoka 	chfs_free_flash_dnode(dnode);
    390  1.1  ahoka 	if (CHFS_PAD(size) - sizeof(*dnode)) {
    391  1.1  ahoka 		kmem_free(tmpbuf, CHFS_PAD(size) - sizeof(*dnode));
    392  1.1  ahoka 	}
    393  1.1  ahoka 
    394  1.1  ahoka 	return err;
    395  1.1  ahoka }
    396  1.1  ahoka 
    397  1.1  ahoka /**
    398  1.1  ahoka  * chfs_do_link - makes a copy from a node
    399  1.1  ahoka  * @old: old node
    400  1.1  ahoka  * @oldfd: dirent of old node
    401  1.1  ahoka  * @parent: parent of new node
    402  1.1  ahoka  * @name: name of new node
    403  1.1  ahoka  * @namelen: length of name
    404  1.1  ahoka  * This function writes the dirent of the new node to the media.
    405  1.1  ahoka  */
    406  1.1  ahoka int
    407  1.3  ttoth chfs_do_link(struct chfs_inode *ip, struct chfs_inode *parent, const char *name, int namelen, enum chtype type)
    408  1.1  ahoka {
    409  1.1  ahoka 	int error = 0;
    410  1.1  ahoka 	struct vnode *vp = ITOV(ip);
    411  1.1  ahoka 	struct ufsmount *ump = VFSTOUFS(vp->v_mount);
    412  1.1  ahoka 	struct chfs_mount *chmp = ump->um_chfs;
    413  1.1  ahoka 	struct chfs_dirent *newfd = NULL;
    414  1.1  ahoka //	struct chfs_dirent *fd = NULL;
    415  1.1  ahoka 
    416  1.1  ahoka 	//dbg("link vno: %llu\n", ip->ino);
    417  1.1  ahoka 
    418  1.1  ahoka 	newfd = chfs_alloc_dirent(namelen + 1);
    419  1.1  ahoka 
    420  1.1  ahoka 	newfd->vno = ip->ino;
    421  1.1  ahoka 	newfd->type = type;
    422  1.1  ahoka 	newfd->nsize = namelen;
    423  1.1  ahoka 	memcpy(newfd->name, name, namelen);
    424  1.1  ahoka 	newfd->name[newfd->nsize] = 0;
    425  1.1  ahoka //	newfd->next = NULL;
    426  1.1  ahoka 
    427  1.1  ahoka 	ip->chvc->nlink++;
    428  1.1  ahoka 	parent->chvc->nlink++;
    429  1.1  ahoka 	ip->iflag |= IN_CHANGE;
    430  1.1  ahoka 	chfs_update(vp, NULL, NULL, UPDATE_WAIT);
    431  1.1  ahoka 
    432  1.1  ahoka 	mutex_enter(&chmp->chm_lock_mountfields);
    433  1.1  ahoka 
    434  1.1  ahoka 	error = chfs_write_flash_vnode(chmp, ip, ALLOC_NORMAL);
    435  1.1  ahoka 	if (error)
    436  1.1  ahoka 		return error;
    437  1.1  ahoka 
    438  1.1  ahoka 	error = chfs_write_flash_dirent(chmp,
    439  1.1  ahoka 	    parent, ip, newfd, ip->ino, ALLOC_NORMAL);
    440  1.1  ahoka 	/* TODO: what should we do if error isn't zero? */
    441  1.1  ahoka 
    442  1.1  ahoka 	mutex_exit(&chmp->chm_lock_mountfields);
    443  1.1  ahoka 
    444  1.1  ahoka 	/* add fd to the fd list */
    445  1.1  ahoka 	TAILQ_INSERT_TAIL(&parent->dents, newfd, fds);
    446  1.1  ahoka #if 0
    447  1.1  ahoka 	fd = parent->dents;
    448  1.1  ahoka 	if (!fd) {
    449  1.1  ahoka 		parent->dents = newfd;
    450  1.1  ahoka 	} else {
    451  1.1  ahoka 		while (fd->next)
    452  1.1  ahoka 			fd = fd->next;
    453  1.1  ahoka 		fd->next = newfd;
    454  1.1  ahoka 	}
    455  1.1  ahoka #endif
    456  1.1  ahoka 
    457  1.1  ahoka 	return error;
    458  1.1  ahoka }
    459  1.1  ahoka 
    460  1.1  ahoka 
    461  1.1  ahoka /**
    462  1.1  ahoka  * chfs_do_unlink - delete a node
    463  1.1  ahoka  * @ip: node what we'd like to delete
    464  1.1  ahoka  * @parent: parent of the node
    465  1.1  ahoka  * @name: name of the node
    466  1.1  ahoka  * @namelen: length of name
    467  1.1  ahoka  * This function set the nlink and vno of the node zero and write its dirent to the media.
    468  1.1  ahoka  */
    469  1.1  ahoka int
    470  1.1  ahoka chfs_do_unlink(struct chfs_inode *ip,
    471  1.1  ahoka     struct chfs_inode *parent, const char *name, int namelen)
    472  1.1  ahoka {
    473  1.1  ahoka 	struct chfs_dirent *fd, *tmpfd;
    474  1.1  ahoka 	int error = 0;
    475  1.1  ahoka 	struct vnode *vp = ITOV(ip);
    476  1.1  ahoka 	struct ufsmount *ump = VFSTOUFS(vp->v_mount);
    477  1.1  ahoka 	struct chfs_mount *chmp = ump->um_chfs;
    478  1.1  ahoka 	struct chfs_node_ref *nref;
    479  1.1  ahoka 
    480  1.1  ahoka 	//dbg("unlink vno: %llu\n", ip->ino);
    481  1.1  ahoka 
    482  1.1  ahoka 	vflushbuf(vp, 0);
    483  1.1  ahoka 
    484  1.1  ahoka 	mutex_enter(&chmp->chm_lock_mountfields);
    485  1.1  ahoka 
    486  1.1  ahoka 	/* remove the full direntry from the parent dents list */
    487  1.1  ahoka 	TAILQ_FOREACH_SAFE(fd, &parent->dents, fds, tmpfd) {
    488  1.1  ahoka 		if (fd->vno == ip->ino &&
    489  1.1  ahoka 		    fd->nsize == namelen &&
    490  1.1  ahoka 		    !memcmp(fd->name, name, fd->nsize)) {
    491  1.3  ttoth 			if (fd->type == CHT_DIR && ip->chvc->nlink == 2)
    492  1.1  ahoka 				ip->chvc->nlink = 0;
    493  1.1  ahoka 			else
    494  1.1  ahoka 				ip->chvc->nlink--;
    495  1.1  ahoka 
    496  1.3  ttoth 			fd->type = CHT_BLANK;
    497  1.1  ahoka 
    498  1.1  ahoka 			TAILQ_REMOVE(&parent->dents, fd, fds);
    499  1.1  ahoka 
    500  1.1  ahoka 			/* remove nref from dirents list */
    501  1.1  ahoka 			nref = parent->chvc->dirents;
    502  1.1  ahoka 			if (nref == fd->nref) {
    503  1.1  ahoka 				nref->nref_next = fd->nref->nref_next;
    504  1.1  ahoka 			} else {
    505  1.1  ahoka 				while (nref->nref_next && nref->nref_next != fd->nref)
    506  1.1  ahoka 					nref = nref->nref_next;
    507  1.1  ahoka 				if (nref->nref_next)
    508  1.1  ahoka 					nref->nref_next = fd->nref->nref_next;
    509  1.1  ahoka 			}
    510  1.1  ahoka 
    511  1.1  ahoka 			//dbg("FD->NREF vno: %llu, lnr: %u, ofs: %u\n",
    512  1.1  ahoka 			//    fd->vno, fd->nref->nref_lnr, fd->nref->nref_offset);
    513  1.1  ahoka 			chfs_mark_node_obsolete(chmp, fd->nref);
    514  1.1  ahoka 
    515  1.1  ahoka 			error = chfs_write_flash_dirent(chmp,
    516  1.1  ahoka 			    parent, ip, fd, 0, ALLOC_DELETION);
    517  1.1  ahoka 
    518  1.1  ahoka 			//dbg("FD->NREF vno: %llu, lnr: %u, ofs: %u\n",
    519  1.1  ahoka 			//    fd->vno, fd->nref->nref_lnr, fd->nref->nref_offset);
    520  1.1  ahoka 			chfs_mark_node_obsolete(chmp, fd->nref);
    521  1.1  ahoka 
    522  1.1  ahoka 			nref = ip->chvc->dnode;
    523  1.1  ahoka 			while (nref != (struct chfs_node_ref *)ip->chvc) {
    524  1.1  ahoka 				//dbg("DATA NREF\n");
    525  1.1  ahoka 				chfs_mark_node_obsolete(chmp, nref);
    526  1.1  ahoka 				nref = nref->nref_next;
    527  1.1  ahoka 			}
    528  1.1  ahoka 			ip->chvc->dnode = (struct chfs_node_ref *)ip->chvc;
    529  1.1  ahoka 
    530  1.1  ahoka 			nref = ip->chvc->v;
    531  1.1  ahoka 			while (nref != (struct chfs_node_ref *)ip->chvc) {
    532  1.1  ahoka 				//dbg("V NREF\n");
    533  1.1  ahoka 				chfs_mark_node_obsolete(chmp, nref);
    534  1.1  ahoka 				nref = nref->nref_next;
    535  1.1  ahoka 			}
    536  1.1  ahoka 			ip->chvc->v = ip->chvc->v->nref_next;
    537  1.1  ahoka 
    538  1.1  ahoka 			parent->chvc->nlink--;
    539  1.1  ahoka 			//TODO: if error
    540  1.1  ahoka 		}
    541  1.1  ahoka 	}
    542  1.1  ahoka 	mutex_exit(&chmp->chm_lock_mountfields);
    543  1.1  ahoka 
    544  1.1  ahoka 	return error;
    545  1.1  ahoka }
    546