Home | History | Annotate | Line # | Download | only in chfs
chfs_build.c revision 1.6
      1  1.6  andvar /*	$NetBSD: chfs_build.c,v 1.6 2021/07/19 21:04:39 andvar 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  * All rights reserved.
      7  1.1   ahoka  *
      8  1.1   ahoka  * This code is derived from software contributed to The NetBSD Foundation
      9  1.1   ahoka  * by the Department of Software Engineering, University of Szeged, Hungary
     10  1.1   ahoka  *
     11  1.1   ahoka  * Redistribution and use in source and binary forms, with or without
     12  1.1   ahoka  * modification, are permitted provided that the following conditions
     13  1.1   ahoka  * are met:
     14  1.1   ahoka  * 1. Redistributions of source code must retain the above copyright
     15  1.1   ahoka  *    notice, this list of conditions and the following disclaimer.
     16  1.1   ahoka  * 2. Redistributions in binary form must reproduce the above copyright
     17  1.1   ahoka  *    notice, this list of conditions and the following disclaimer in the
     18  1.1   ahoka  *    documentation and/or other materials provided with the distribution.
     19  1.1   ahoka  *
     20  1.1   ahoka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  1.1   ahoka  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  1.1   ahoka  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  1.1   ahoka  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  1.1   ahoka  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     25  1.1   ahoka  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     26  1.1   ahoka  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     27  1.1   ahoka  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     28  1.1   ahoka  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     29  1.1   ahoka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     30  1.1   ahoka  * SUCH DAMAGE.
     31  1.1   ahoka  */
     32  1.1   ahoka 
     33  1.1   ahoka #include "chfs.h"
     34  1.1   ahoka 
     35  1.1   ahoka 
     36  1.5   ttoth /*
     37  1.5   ttoth  * chfs_calc_trigger_levels - setup filesystem parameters
     38  1.5   ttoth  * Setups filesystem parameters (reserved blocks and GC trigger level)
     39  1.5   ttoth  * for a specific flash.
     40  1.5   ttoth  */
     41  1.1   ahoka void
     42  1.1   ahoka chfs_calc_trigger_levels(struct chfs_mount *chmp)
     43  1.1   ahoka {
     44  1.1   ahoka 	uint32_t size;
     45  1.1   ahoka 
     46  1.1   ahoka 	chmp->chm_resv_blocks_deletion = 2;
     47  1.1   ahoka 
     48  1.5   ttoth 	size = chmp->chm_ebh->flash_size / 50;  /* 2% of flash size */
     49  1.1   ahoka 	size += chmp->chm_ebh->peb_nr * 100;
     50  1.1   ahoka 	size += chmp->chm_ebh->eb_size - 1;
     51  1.1   ahoka 
     52  1.1   ahoka 	chmp->chm_resv_blocks_write =
     53  1.1   ahoka 	    chmp->chm_resv_blocks_deletion + (size / chmp->chm_ebh->eb_size);
     54  1.1   ahoka 	chmp->chm_resv_blocks_gctrigger = chmp->chm_resv_blocks_write + 1;
     55  1.1   ahoka 	chmp->chm_resv_blocks_gcmerge = chmp->chm_resv_blocks_deletion + 1;
     56  1.1   ahoka 	chmp->chm_vdirty_blocks_gctrigger = chmp->chm_resv_blocks_gctrigger * 10;
     57  1.1   ahoka 
     58  1.1   ahoka 	chmp->chm_nospc_dirty =
     59  1.1   ahoka 	    chmp->chm_ebh->eb_size + (chmp->chm_ebh->flash_size / 100);
     60  1.1   ahoka }
     61  1.1   ahoka 
     62  1.1   ahoka 
     63  1.5   ttoth /*
     64  1.1   ahoka  * chfs_build_set_vnodecache_nlink - set pvno and nlink in vnodecaches
     65  1.5   ttoth  * Travels vc's directory entries and sets the pvno and nlink
     66  1.1   ahoka  * attribute of the vnode where the dirent's vno points.
     67  1.1   ahoka  */
     68  1.1   ahoka void
     69  1.1   ahoka chfs_build_set_vnodecache_nlink(struct chfs_mount *chmp,
     70  1.1   ahoka     struct chfs_vnode_cache *vc)
     71  1.1   ahoka {
     72  1.4   ttoth 	struct chfs_dirent *fd, *tmpfd;
     73  1.1   ahoka 
     74  1.4   ttoth 	TAILQ_FOREACH_SAFE(fd, &vc->scan_dirents, fds, tmpfd) {
     75  1.1   ahoka 		struct chfs_vnode_cache *child_vc;
     76  1.1   ahoka 
     77  1.1   ahoka 		if (!fd->vno)
     78  1.1   ahoka 			continue;
     79  1.1   ahoka 
     80  1.1   ahoka 		mutex_enter(&chmp->chm_lock_vnocache);
     81  1.1   ahoka 		child_vc = chfs_vnode_cache_get(chmp, fd->vno);
     82  1.1   ahoka 		mutex_exit(&chmp->chm_lock_vnocache);
     83  1.1   ahoka 		if (!child_vc) {
     84  1.1   ahoka 			chfs_mark_node_obsolete(chmp, fd->nref);
     85  1.4   ttoth 			TAILQ_REMOVE(&vc->scan_dirents, fd, fds);
     86  1.1   ahoka 			continue;
     87  1.1   ahoka 		}
     88  1.3   ttoth 		if (fd->type == CHT_DIR) {
     89  1.1   ahoka 			if (child_vc->nlink < 1)
     90  1.1   ahoka 				child_vc->nlink = 1;
     91  1.1   ahoka 
     92  1.1   ahoka 			if (child_vc->pvno) {
     93  1.1   ahoka 				chfs_err("found a hard link: child dir: %s"
     94  1.1   ahoka 				    ", (vno: %llu) of dir vno: %llu\n",
     95  1.2     agc 				    fd->name, (unsigned long long)fd->vno,
     96  1.2     agc 				    (unsigned long long)vc->vno);
     97  1.1   ahoka 			} else {
     98  1.1   ahoka 				child_vc->pvno = vc->vno;
     99  1.1   ahoka 			}
    100  1.1   ahoka 		}
    101  1.1   ahoka 		child_vc->nlink++;
    102  1.1   ahoka 		vc->nlink++;
    103  1.1   ahoka 	}
    104  1.1   ahoka }
    105  1.1   ahoka 
    106  1.5   ttoth /*
    107  1.1   ahoka  * chfs_build_remove_unlinked vnode
    108  1.1   ahoka  */
    109  1.1   ahoka void
    110  1.1   ahoka chfs_build_remove_unlinked_vnode(struct chfs_mount *chmp,
    111  1.1   ahoka     struct chfs_vnode_cache *vc,
    112  1.1   ahoka     struct chfs_dirent_list *unlinked)
    113  1.1   ahoka {
    114  1.1   ahoka 	struct chfs_node_ref *nref;
    115  1.1   ahoka 	struct chfs_dirent *fd, *tmpfd;
    116  1.1   ahoka 
    117  1.1   ahoka 	dbg("START\n");
    118  1.2     agc 	dbg("vno: %llu\n", (unsigned long long)vc->vno);
    119  1.1   ahoka 
    120  1.4   ttoth 	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
    121  1.1   ahoka 	nref = vc->dnode;
    122  1.5   ttoth 	/* The vnode cache is at the end of the data node's chain */
    123  1.1   ahoka 	while (nref != (struct chfs_node_ref *)vc) {
    124  1.1   ahoka 		struct chfs_node_ref *next = nref->nref_next;
    125  1.1   ahoka 		dbg("mark dnode\n");
    126  1.1   ahoka 		chfs_mark_node_obsolete(chmp, nref);
    127  1.1   ahoka 		nref = next;
    128  1.1   ahoka 	}
    129  1.4   ttoth 	vc->dnode = (struct chfs_node_ref *)vc;
    130  1.1   ahoka 	nref = vc->dirents;
    131  1.5   ttoth 	/* The vnode cache is at the end of the dirent node's chain */
    132  1.1   ahoka 	while (nref != (struct chfs_node_ref *)vc) {
    133  1.1   ahoka 		struct chfs_node_ref *next = nref->nref_next;
    134  1.1   ahoka 		dbg("mark dirent\n");
    135  1.1   ahoka 		chfs_mark_node_obsolete(chmp, nref);
    136  1.1   ahoka 		nref = next;
    137  1.1   ahoka 	}
    138  1.4   ttoth 	vc->dirents = (struct chfs_node_ref *)vc;
    139  1.1   ahoka 	if (!TAILQ_EMPTY(&vc->scan_dirents)) {
    140  1.1   ahoka 		TAILQ_FOREACH_SAFE(fd, &vc->scan_dirents, fds, tmpfd) {
    141  1.1   ahoka 			struct chfs_vnode_cache *child_vc;
    142  1.1   ahoka 			dbg("dirent dump:\n");
    143  1.2     agc 			dbg(" ->vno:     %llu\n", (unsigned long long)fd->vno);
    144  1.2     agc 			dbg(" ->version: %llu\n", (unsigned long long)fd->version);
    145  1.1   ahoka 			dbg(" ->nhash:   0x%x\n", fd->nhash);
    146  1.1   ahoka 			dbg(" ->nsize:   %d\n", fd->nsize);
    147  1.1   ahoka 			dbg(" ->name:    %s\n", fd->name);
    148  1.1   ahoka 			dbg(" ->type:    %d\n", fd->type);
    149  1.1   ahoka 			TAILQ_REMOVE(&vc->scan_dirents, fd, fds);
    150  1.1   ahoka 
    151  1.1   ahoka 			if (!fd->vno) {
    152  1.1   ahoka 				chfs_free_dirent(fd);
    153  1.1   ahoka 				continue;
    154  1.1   ahoka 			}
    155  1.1   ahoka 			mutex_enter(&chmp->chm_lock_vnocache);
    156  1.1   ahoka 			child_vc = chfs_vnode_cache_get(chmp, fd->vno);
    157  1.1   ahoka 			mutex_exit(&chmp->chm_lock_vnocache);
    158  1.1   ahoka 			if (!child_vc) {
    159  1.1   ahoka 				chfs_free_dirent(fd);
    160  1.1   ahoka 				continue;
    161  1.1   ahoka 			}
    162  1.5   ttoth 			/*
    163  1.1   ahoka 			 * Decrease nlink in child. If it is 0, add to unlinked
    164  1.1   ahoka 			 * dirents or just free it otherwise.
    165  1.1   ahoka 			 */
    166  1.1   ahoka 			child_vc->nlink--;
    167  1.1   ahoka 
    168  1.1   ahoka 			if (!child_vc->nlink) {
    169  1.1   ahoka 				// XXX HEAD or TAIL?
    170  1.1   ahoka 				// original code did HEAD, but we could add
    171  1.1   ahoka 				// it to the TAIL easily with TAILQ.
    172  1.1   ahoka 				TAILQ_INSERT_TAIL(unlinked, fd, fds);
    173  1.1   ahoka 			} else {
    174  1.1   ahoka 				chfs_free_dirent(fd);
    175  1.1   ahoka 			}
    176  1.1   ahoka 		}
    177  1.1   ahoka 	} else {
    178  1.1   ahoka 		dbg("there are no scan dirents\n");
    179  1.1   ahoka 	}
    180  1.1   ahoka 
    181  1.1   ahoka 	nref = vc->v;
    182  1.1   ahoka 	while ((struct chfs_vnode_cache *)nref != vc) {
    183  1.4   ttoth 		chfs_mark_node_obsolete(chmp, nref);
    184  1.1   ahoka 		nref = nref->nref_next;
    185  1.1   ahoka 	}
    186  1.4   ttoth 	vc->v = (struct chfs_node_ref *)vc;
    187  1.1   ahoka 
    188  1.1   ahoka 	mutex_enter(&chmp->chm_lock_vnocache);
    189  1.1   ahoka 	if (vc->vno != CHFS_ROOTINO)
    190  1.4   ttoth 		vc->state = VNO_STATE_UNCHECKED;
    191  1.1   ahoka 	mutex_exit(&chmp->chm_lock_vnocache);
    192  1.1   ahoka 	dbg("END\n");
    193  1.1   ahoka }
    194  1.1   ahoka 
    195  1.5   ttoth /*
    196  1.1   ahoka  * chfs_build_filesystem - build in-memory representation of filesystem
    197  1.1   ahoka  *
    198  1.1   ahoka  * Step 1:
    199  1.5   ttoth  * Scans through the eraseblocks mapped in EBH.
    200  1.1   ahoka  * During scan builds up the map of vnodes and directory entries and puts them
    201  1.1   ahoka  * into the vnode_cache.
    202  1.1   ahoka  * Step 2:
    203  1.1   ahoka  * Scans the directory tree and set the nlink in the vnode caches.
    204  1.1   ahoka  * Step 3:
    205  1.1   ahoka  * Scans vnode caches with nlink = 0
    206  1.1   ahoka  */
    207  1.1   ahoka int
    208  1.1   ahoka chfs_build_filesystem(struct chfs_mount *chmp)
    209  1.1   ahoka {
    210  1.1   ahoka 	int i,err = 0;
    211  1.1   ahoka 	struct chfs_vnode_cache *vc;
    212  1.1   ahoka 	struct chfs_dirent *fd, *tmpfd;
    213  1.1   ahoka 	struct chfs_node_ref **nref;
    214  1.1   ahoka 	struct chfs_dirent_list unlinked;
    215  1.1   ahoka 	struct chfs_vnode_cache *notregvc;
    216  1.1   ahoka 
    217  1.1   ahoka 	TAILQ_INIT(&unlinked);
    218  1.1   ahoka 
    219  1.1   ahoka 	mutex_enter(&chmp->chm_lock_mountfields);
    220  1.1   ahoka 
    221  1.5   ttoth 	/* Step 1 */
    222  1.1   ahoka 	chmp->chm_flags |= CHFS_MP_FLAG_SCANNING;
    223  1.1   ahoka 	for (i = 0; i < chmp->chm_ebh->peb_nr; i++) {
    224  1.1   ahoka 		chmp->chm_blocks[i].lnr = i;
    225  1.1   ahoka 		chmp->chm_blocks[i].free_size = chmp->chm_ebh->eb_size;
    226  1.5   ttoth 		/* If the LEB is add to free list skip it. */
    227  1.1   ahoka 		if (chmp->chm_ebh->lmap[i] < 0) {
    228  1.1   ahoka 			TAILQ_INSERT_TAIL(&chmp->chm_free_queue,
    229  1.1   ahoka 			    &chmp->chm_blocks[i], queue);
    230  1.1   ahoka 			chmp->chm_nr_free_blocks++;
    231  1.1   ahoka 			continue;
    232  1.1   ahoka 		}
    233  1.1   ahoka 
    234  1.1   ahoka 		err = chfs_scan_eraseblock(chmp, &chmp->chm_blocks[i]);
    235  1.1   ahoka 		switch (err) {
    236  1.1   ahoka 		case CHFS_BLK_STATE_FREE:
    237  1.1   ahoka 			chmp->chm_nr_free_blocks++;
    238  1.1   ahoka 			TAILQ_INSERT_TAIL(&chmp->chm_free_queue,
    239  1.1   ahoka 			    &chmp->chm_blocks[i], queue);
    240  1.1   ahoka 			break;
    241  1.1   ahoka 		case CHFS_BLK_STATE_CLEAN:
    242  1.1   ahoka 			TAILQ_INSERT_TAIL(&chmp->chm_clean_queue,
    243  1.1   ahoka 			    &chmp->chm_blocks[i], queue);
    244  1.1   ahoka 			break;
    245  1.1   ahoka 		case CHFS_BLK_STATE_PARTDIRTY:
    246  1.1   ahoka 			if (chmp->chm_blocks[i].free_size > chmp->chm_wbuf_pagesize &&
    247  1.1   ahoka 			    (!chmp->chm_nextblock ||
    248  1.1   ahoka 				chmp->chm_blocks[i].free_size >
    249  1.1   ahoka 				chmp->chm_nextblock->free_size)) {
    250  1.1   ahoka 				/* convert the old nextblock's free size to
    251  1.1   ahoka 				 * dirty and put it on a list */
    252  1.1   ahoka 				if (chmp->chm_nextblock) {
    253  1.1   ahoka 					err = chfs_close_eraseblock(chmp,
    254  1.1   ahoka 					    chmp->chm_nextblock);
    255  1.6  andvar 					if (err) {
    256  1.6  andvar 						mutex_exit(&chmp->chm_lock_mountfields);
    257  1.1   ahoka 						return err;
    258  1.6  andvar 					}
    259  1.1   ahoka 				}
    260  1.1   ahoka 				chmp->chm_nextblock = &chmp->chm_blocks[i];
    261  1.1   ahoka 			} else {
    262  1.1   ahoka 				/* convert the scanned block's free size to
    263  1.1   ahoka 				 * dirty and put it on a list */
    264  1.1   ahoka 				err = chfs_close_eraseblock(chmp,
    265  1.1   ahoka 				    &chmp->chm_blocks[i]);
    266  1.6  andvar 				if (err) {
    267  1.6  andvar 					mutex_exit(&chmp->chm_lock_mountfields);
    268  1.1   ahoka 					return err;
    269  1.6  andvar 				}
    270  1.1   ahoka 			}
    271  1.1   ahoka 			break;
    272  1.1   ahoka 		case CHFS_BLK_STATE_ALLDIRTY:
    273  1.1   ahoka 			/*
    274  1.1   ahoka 			 * The block has a valid EBH header, but it doesn't
    275  1.1   ahoka 			 * contain any valid data.
    276  1.1   ahoka 			 */
    277  1.1   ahoka 			TAILQ_INSERT_TAIL(&chmp->chm_erase_pending_queue,
    278  1.1   ahoka 			    &chmp->chm_blocks[i], queue);
    279  1.1   ahoka 			chmp->chm_nr_erasable_blocks++;
    280  1.1   ahoka 			break;
    281  1.1   ahoka 		default:
    282  1.1   ahoka 			/* It was an error, unknown  state */
    283  1.1   ahoka 			break;
    284  1.1   ahoka 		}
    285  1.1   ahoka 
    286  1.1   ahoka 	}
    287  1.1   ahoka 	chmp->chm_flags &= ~CHFS_MP_FLAG_SCANNING;
    288  1.1   ahoka 
    289  1.1   ahoka 
    290  1.1   ahoka 	//TODO need bad block check (and bad block handling in EBH too!!)
    291  1.1   ahoka 	/* Now EBH only checks block is bad  during its scan operation.
    292  1.1   ahoka 	 * Need check at erase + write + read...
    293  1.1   ahoka 	 */
    294  1.1   ahoka 
    295  1.5   ttoth 	/* Step 2 */
    296  1.1   ahoka 	chmp->chm_flags |= CHFS_MP_FLAG_BUILDING;
    297  1.1   ahoka 	for (i = 0; i < VNODECACHE_SIZE; i++) {
    298  1.1   ahoka 		vc = chmp->chm_vnocache_hash[i];
    299  1.1   ahoka 		while (vc) {
    300  1.2     agc 			dbg("vc->vno: %llu\n", (unsigned long long)vc->vno);
    301  1.1   ahoka 			if (!TAILQ_EMPTY(&vc->scan_dirents))
    302  1.1   ahoka 				chfs_build_set_vnodecache_nlink(chmp, vc);
    303  1.1   ahoka 			vc = vc->next;
    304  1.1   ahoka 		}
    305  1.1   ahoka 	}
    306  1.1   ahoka 
    307  1.5   ttoth 	/* Step 3 */
    308  1.1   ahoka 	for (i =  0; i < VNODECACHE_SIZE; i++) {
    309  1.1   ahoka 		vc = chmp->chm_vnocache_hash[i];
    310  1.1   ahoka 		while (vc) {
    311  1.1   ahoka 			if (vc->nlink) {
    312  1.1   ahoka 				vc = vc->next;
    313  1.1   ahoka 				continue;
    314  1.1   ahoka 			}
    315  1.1   ahoka 
    316  1.1   ahoka 			chfs_build_remove_unlinked_vnode(chmp,
    317  1.1   ahoka 			    vc, &unlinked);
    318  1.1   ahoka 			vc = vc->next;
    319  1.1   ahoka 		}
    320  1.1   ahoka 	}
    321  1.1   ahoka 	/* Remove the newly unlinked vnodes. They are on the unlinked list */
    322  1.1   ahoka 	TAILQ_FOREACH_SAFE(fd, &unlinked, fds, tmpfd) {
    323  1.1   ahoka 		TAILQ_REMOVE(&unlinked, fd, fds);
    324  1.1   ahoka 		mutex_enter(&chmp->chm_lock_vnocache);
    325  1.1   ahoka 		vc = chfs_vnode_cache_get(chmp, fd->vno);
    326  1.1   ahoka 		mutex_exit(&chmp->chm_lock_vnocache);
    327  1.1   ahoka 		if (vc) {
    328  1.1   ahoka 			chfs_build_remove_unlinked_vnode(chmp,
    329  1.1   ahoka 			    vc, &unlinked);
    330  1.1   ahoka 		}
    331  1.1   ahoka 		chfs_free_dirent(fd);
    332  1.1   ahoka 	}
    333  1.1   ahoka 
    334  1.1   ahoka 	chmp->chm_flags &= ~CHFS_MP_FLAG_BUILDING;
    335  1.1   ahoka 
    336  1.1   ahoka 	/* Free all dirents */
    337  1.1   ahoka 	for (i =  0; i < VNODECACHE_SIZE; i++) {
    338  1.1   ahoka 		vc = chmp->chm_vnocache_hash[i];
    339  1.1   ahoka 		while (vc) {
    340  1.1   ahoka 			TAILQ_FOREACH_SAFE(fd, &vc->scan_dirents, fds, tmpfd) {
    341  1.1   ahoka 				TAILQ_REMOVE(&vc->scan_dirents, fd, fds);
    342  1.1   ahoka 				if (fd->vno == 0) {
    343  1.1   ahoka 					nref = &fd->nref;
    344  1.1   ahoka 					*nref = fd->nref->nref_next;
    345  1.3   ttoth 				} else if (fd->type == CHT_DIR) {
    346  1.5   ttoth 					/* set state every non-VREG file's vc */
    347  1.1   ahoka 					mutex_enter(&chmp->chm_lock_vnocache);
    348  1.4   ttoth 					notregvc = chfs_vnode_cache_get(chmp, fd->vno);
    349  1.4   ttoth 					notregvc->state = VNO_STATE_PRESENT;
    350  1.1   ahoka 					mutex_exit(&chmp->chm_lock_vnocache);
    351  1.1   ahoka 				}
    352  1.1   ahoka 				chfs_free_dirent(fd);
    353  1.1   ahoka 			}
    354  1.1   ahoka 			KASSERT(TAILQ_EMPTY(&vc->scan_dirents));
    355  1.1   ahoka 			vc = vc->next;
    356  1.1   ahoka 		}
    357  1.1   ahoka 	}
    358  1.1   ahoka 
    359  1.5   ttoth 	/* Set up chmp->chm_wbuf_ofs for the first write */
    360  1.1   ahoka 	if (chmp->chm_nextblock) {
    361  1.1   ahoka 		dbg("free_size: %d\n", chmp->chm_nextblock->free_size);
    362  1.1   ahoka 		chmp->chm_wbuf_ofs = chmp->chm_ebh->eb_size -
    363  1.1   ahoka 		    chmp->chm_nextblock->free_size;
    364  1.1   ahoka 	} else {
    365  1.1   ahoka 		chmp->chm_wbuf_ofs = 0xffffffff;
    366  1.1   ahoka 	}
    367  1.1   ahoka 	mutex_exit(&chmp->chm_lock_mountfields);
    368  1.1   ahoka 
    369  1.1   ahoka 	return 0;
    370  1.1   ahoka }
    371  1.1   ahoka 
    372