Annotation of src/sys/ufs/chfs/chfs_vnode.c, Revision 1.17.2.1
1.17.2.1! ad 1: /* $NetBSD: chfs_vnode.c,v 1.18 2020/01/17 20:08:10 ad Exp $ */
1.1 ahoka 2:
3: /*-
4: * Copyright (c) 2010 Department of Software Engineering,
5: * University of Szeged, Hungary
6: * Copyright (C) 2010 Tamas Toth <ttoth@inf.u-szeged.hu>
7: * Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org>
8: * All rights reserved.
9: *
10: * This code is derived from software contributed to The NetBSD Foundation
11: * by the Department of Software Engineering, University of Szeged, Hungary
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: */
34:
35: #include "chfs.h"
36: #include "chfs_inode.h"
37: #include <sys/kauth.h>
38: #include <sys/namei.h>
39: #include <sys/uio.h>
40: #include <sys/buf.h>
41:
1.3 elad 42: #include <miscfs/genfs/genfs.h>
43:
1.8 ttoth 44: /* chfs_vnode_lookup - lookup for a vnode */
1.13 hannken 45: static bool
46: chfs_vnode_lookup_selector(void *ctx, struct vnode *vp)
47: {
48: ino_t *ino = ctx;
49:
1.15 riastrad 50: KASSERT(mutex_owned(vp->v_interlock));
51:
1.13 hannken 52: return (VTOI(vp) != NULL && VTOI(vp)->ino == *ino);
53: }
1.1 ahoka 54: struct vnode *
55: chfs_vnode_lookup(struct chfs_mount *chmp, ino_t vno)
56: {
1.13 hannken 57: struct vnode_iterator *marker;
1.1 ahoka 58: struct vnode *vp;
59:
1.13 hannken 60: vfs_vnode_iterator_init(chmp->chm_fsmp, &marker);
61: vp = vfs_vnode_iterator_next(marker, chfs_vnode_lookup_selector, &vno);
62: vfs_vnode_iterator_destroy(marker);
63:
64: return vp;
1.1 ahoka 65: }
66:
1.8 ttoth 67: /* chfs_readvnode - reads a vnode from the flash and setups its inode */
1.1 ahoka 68: int
1.8 ttoth 69: chfs_readvnode(struct mount *mp, ino_t ino, struct vnode **vpp)
1.1 ahoka 70: {
71: struct ufsmount* ump = VFSTOUFS(mp);
72: struct chfs_mount *chmp = ump->um_chfs;
73: struct chfs_vnode_cache *chvc;
74: struct chfs_flash_vnode *chfvn;
75: struct chfs_inode *ip;
76: int err;
77: char* buf;
78: size_t retlen, len;
79: struct vnode* vp = NULL;
1.2 agc 80: dbg("readvnode | ino: %llu\n", (unsigned long long)ino);
1.1 ahoka 81:
82: len = sizeof(struct chfs_flash_vnode);
83:
84: KASSERT(vpp != NULL);
85:
86: if (vpp != NULL) {
87: vp = *vpp;
88: }
89:
90: ip = VTOI(vp);
91: chvc = ip->chvc;
92:
1.8 ttoth 93: /* root node is in-memory only */
1.1 ahoka 94: if (chvc && ino != CHFS_ROOTINO) {
1.7 ttoth 95: dbg("offset: %" PRIu32 ", lnr: %d\n",
1.1 ahoka 96: CHFS_GET_OFS(chvc->v->nref_offset), chvc->v->nref_lnr);
97:
98: KASSERT((void *)chvc != (void *)chvc->v);
99:
1.8 ttoth 100: /* reading */
1.1 ahoka 101: buf = kmem_alloc(len, KM_SLEEP);
102: err = chfs_read_leb(chmp, chvc->v->nref_lnr, buf,
103: CHFS_GET_OFS(chvc->v->nref_offset), len, &retlen);
1.11 he 104: if (err) {
105: kmem_free(buf, len);
1.1 ahoka 106: return err;
1.11 he 107: }
1.1 ahoka 108: if (retlen != len) {
109: chfs_err("Error reading vnode: read: %zu insted of: %zu\n",
110: len, retlen);
1.11 he 111: kmem_free(buf, len);
1.1 ahoka 112: return EIO;
113: }
114: chfvn = (struct chfs_flash_vnode*)buf;
1.8 ttoth 115:
116: /* setup inode fields */
1.1 ahoka 117: chfs_set_vnode_size(vp, chfvn->dn_size);
118: ip->mode = chfvn->mode;
1.4 ttoth 119: ip->ch_type = IFTOCHT(ip->mode);
120: vp->v_type = CHTTOVT(ip->ch_type);
1.1 ahoka 121: ip->version = chfvn->version;
122: ip->uid = chfvn->uid;
123: ip->gid = chfvn->gid;
124: ip->atime = chfvn->atime;
125: ip->mtime = chfvn->mtime;
126: ip->ctime = chfvn->ctime;
1.8 ttoth 127:
1.1 ahoka 128: kmem_free(buf, len);
129: }
130:
131:
132: *vpp = vp;
133: return 0;
134: }
135:
1.8 ttoth 136: /*
137: * chfs_readddirent -
138: * reads a directory entry from flash and adds it to its inode
139: */
1.1 ahoka 140: int
141: chfs_readdirent(struct mount *mp, struct chfs_node_ref *chnr, struct chfs_inode *pdir)
142: {
143: struct ufsmount *ump = VFSTOUFS(mp);
144: struct chfs_mount *chmp = ump->um_chfs;
145: struct chfs_flash_dirent_node chfdn;
1.8 ttoth 146: struct chfs_dirent *fd;
1.1 ahoka 147: size_t len = sizeof(struct chfs_flash_dirent_node);
148: size_t retlen;
149: int err = 0;
150:
1.8 ttoth 151: /* read flash_dirent_node */
1.1 ahoka 152: err = chfs_read_leb(chmp, chnr->nref_lnr, (char *)&chfdn,
153: CHFS_GET_OFS(chnr->nref_offset), len, &retlen);
154: if (err) {
155: return err;
156: }
157: if (retlen != len) {
158: chfs_err("Error reading vnode: read: %zu insted of: %zu\n",
159: retlen, len);
160: return EIO;
161: }
162:
1.8 ttoth 163: /* set fields of dirent */
1.1 ahoka 164: fd = chfs_alloc_dirent(chfdn.nsize + 1);
165: fd->version = chfdn.version;
166: fd->vno = chfdn.vno;
167: fd->type = chfdn.dtype;
168: fd->nsize = chfdn.nsize;
169:
1.8 ttoth 170: /* read the name of the dirent */
1.1 ahoka 171: err = chfs_read_leb(chmp, chnr->nref_lnr, fd->name,
172: CHFS_GET_OFS(chnr->nref_offset) + len, chfdn.nsize, &retlen);
173: if (err) {
174: return err;
175: }
176:
177: if (retlen != chfdn.nsize) {
178: chfs_err("Error reading vnode: read: %zu insted of: %zu\n",
179: len, retlen);
180: return EIO;
181: }
182:
183: fd->name[fd->nsize] = 0;
184: fd->nref = chnr;
185:
1.8 ttoth 186: /* add to inode */
1.1 ahoka 187: chfs_add_fd_to_inode(chmp, pdir, fd);
188: return 0;
189: }
190:
1.8 ttoth 191: /* chfs_makeinode - makes a new file and initializes its structures */
1.1 ahoka 192: int
193: chfs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp,
1.4 ttoth 194: struct componentname *cnp, enum vtype type)
1.1 ahoka 195: {
196: struct chfs_inode *ip, *pdir;
197: struct vnode *vp;
198: struct ufsmount* ump = VFSTOUFS(dvp->v_mount);
199: struct chfs_mount* chmp = ump->um_chfs;
200: struct chfs_vnode_cache* chvc;
1.3 elad 201: int error;
1.1 ahoka 202: ino_t vno;
1.8 ttoth 203: struct chfs_dirent *nfd;
1.1 ahoka 204:
205: dbg("makeinode\n");
206: pdir = VTOI(dvp);
207:
208: *vpp = NULL;
209:
1.8 ttoth 210: /* number of vnode will be the new maximum */
1.1 ahoka 211: vno = ++(chmp->chm_max_vno);
212:
1.17.2.1! ad 213: error = VFS_VGET(dvp->v_mount, vno, LK_EXCLUSIVE, &vp);
1.1 ahoka 214: if (error)
215: return (error);
216:
1.8 ttoth 217: /* setup vnode cache */
1.1 ahoka 218: mutex_enter(&chmp->chm_lock_vnocache);
219: chvc = chfs_vnode_cache_get(chmp, vno);
220:
221: chvc->pvno = pdir->ino;
222: chvc->vno_version = kmem_alloc(sizeof(uint64_t), KM_SLEEP);
223: *(chvc->vno_version) = 1;
224: if (type != VDIR)
225: chvc->nlink = 1;
226: else
227: chvc->nlink = 2;
228: chvc->state = VNO_STATE_CHECKEDABSENT;
1.6 ttoth 229: mutex_exit(&chmp->chm_lock_vnocache);
1.1 ahoka 230:
1.8 ttoth 231: /* setup inode */
1.1 ahoka 232: ip = VTOI(vp);
233: ip->ino = vno;
234:
235: if (type == VDIR)
236: chfs_set_vnode_size(vp, 512);
237: else
238: chfs_set_vnode_size(vp, 0);
239:
240: ip->uid = kauth_cred_geteuid(cnp->cn_cred);
241: ip->gid = kauth_cred_getegid(cnp->cn_cred);
242: ip->version = 1;
243: ip->iflag |= (IN_ACCESS | IN_CHANGE | IN_UPDATE);
244:
245: ip->chvc = chvc;
246: ip->target = NULL;
247:
248: ip->mode = mode;
1.14 hannken 249: vp->v_type = type; /* Rest init'd in chfs_loadvnode(). */
1.4 ttoth 250: ip->ch_type = VTTOCHT(vp->v_type);
1.3 elad 251:
1.8 ttoth 252: /* authorize setting SGID if needed */
1.3 elad 253: if (ip->mode & ISGID) {
254: error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY,
255: vp, NULL, genfs_can_chmod(vp->v_type, cnp->cn_cred, ip->uid,
256: ip->gid, mode));
257: if (error)
258: ip->mode &= ~ISGID;
259: }
1.1 ahoka 260:
1.8 ttoth 261: /* write vnode information to the flash */
1.1 ahoka 262: chfs_update(vp, NULL, NULL, UPDATE_WAIT);
263:
264: mutex_enter(&chmp->chm_lock_mountfields);
265:
266: error = chfs_write_flash_vnode(chmp, ip, ALLOC_NORMAL);
267: if (error) {
268: mutex_exit(&chmp->chm_lock_mountfields);
269: vput(vp);
270: return error;
271: }
1.8 ttoth 272:
273: /* update parent's vnode information and write it to the flash */
1.1 ahoka 274: pdir->iflag |= (IN_ACCESS | IN_CHANGE | IN_MODIFY | IN_UPDATE);
275: chfs_update(dvp, NULL, NULL, UPDATE_WAIT);
276:
277: error = chfs_write_flash_vnode(chmp, pdir, ALLOC_NORMAL);
278: if (error) {
279: mutex_exit(&chmp->chm_lock_mountfields);
280: vput(vp);
281: return error;
282: }
283:
1.8 ttoth 284: /* setup directory entry */
1.1 ahoka 285: nfd = chfs_alloc_dirent(cnp->cn_namelen + 1);
286: nfd->vno = ip->ino;
287: nfd->version = (++pdir->chvc->highest_version);
1.4 ttoth 288: nfd->type = ip->ch_type;
1.1 ahoka 289: nfd->nsize = cnp->cn_namelen;
290: memcpy(&(nfd->name), cnp->cn_nameptr, cnp->cn_namelen);
291: nfd->name[nfd->nsize] = 0;
292: nfd->nhash = hash32_buf(nfd->name, cnp->cn_namelen, HASH32_BUF_INIT);
293:
1.8 ttoth 294: /* write out */
1.1 ahoka 295: error = chfs_write_flash_dirent(chmp, pdir, ip, nfd, ip->ino, ALLOC_NORMAL);
296: if (error) {
297: mutex_exit(&chmp->chm_lock_mountfields);
298: vput(vp);
299: return error;
300: }
301:
302: //TODO set parent's dir times
303:
1.8 ttoth 304: /* add dirent to parent */
1.1 ahoka 305: chfs_add_fd_to_inode(chmp, pdir, nfd);
1.8 ttoth 306:
1.1 ahoka 307: pdir->chvc->nlink++;
308:
309: mutex_exit(&chmp->chm_lock_mountfields);
310:
1.10 hannken 311: VOP_UNLOCK(vp);
1.1 ahoka 312: *vpp = vp;
1.17 christos 313: cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
1.1 ahoka 314: return (0);
315: }
316:
1.8 ttoth 317: /* chfs_set_vnode_size - updates size of vnode and also inode */
1.1 ahoka 318: void
319: chfs_set_vnode_size(struct vnode *vp, size_t size)
320: {
321: struct chfs_inode *ip;
322:
323: KASSERT(vp != NULL);
324:
325: ip = VTOI(vp);
326: KASSERT(ip != NULL);
327:
328: ip->size = size;
329: vp->v_size = vp->v_writesize = size;
330: return;
331: }
332:
1.8 ttoth 333: /*
334: * chfs_change_size_free - updates free size
335: * "change" parameter is positive if we have to increase the size
336: * and negative if we have to decrease it
337: */
1.1 ahoka 338: void
339: chfs_change_size_free(struct chfs_mount *chmp,
340: struct chfs_eraseblock *cheb, int change)
341: {
342: KASSERT(mutex_owned(&chmp->chm_lock_sizes));
343: KASSERT((int)(chmp->chm_free_size + change) >= 0);
344: KASSERT((int)(cheb->free_size + change) >= 0);
345: KASSERT((int)(cheb->free_size + change) <= chmp->chm_ebh->eb_size);
346: chmp->chm_free_size += change;
347: cheb->free_size += change;
348: return;
349: }
350:
1.8 ttoth 351: /*
352: * chfs_change_size_dirty - updates dirty size
353: * "change" parameter is positive if we have to increase the size
354: * and negative if we have to decrease it
355: */
1.1 ahoka 356: void
357: chfs_change_size_dirty(struct chfs_mount *chmp,
358: struct chfs_eraseblock *cheb, int change)
359: {
360: KASSERT(mutex_owned(&chmp->chm_lock_sizes));
361: KASSERT((int)(chmp->chm_dirty_size + change) >= 0);
362: KASSERT((int)(cheb->dirty_size + change) >= 0);
363: KASSERT((int)(cheb->dirty_size + change) <= chmp->chm_ebh->eb_size);
364: chmp->chm_dirty_size += change;
365: cheb->dirty_size += change;
366: return;
367: }
368:
1.8 ttoth 369: /*
370: * chfs_change_size_unchecked - updates unchecked size
371: * "change" parameter is positive if we have to increase the size
372: * and negative if we have to decrease it
373: */
1.1 ahoka 374: void
375: chfs_change_size_unchecked(struct chfs_mount *chmp,
376: struct chfs_eraseblock *cheb, int change)
377: {
378: KASSERT(mutex_owned(&chmp->chm_lock_sizes));
379: KASSERT((int)(chmp->chm_unchecked_size + change) >= 0);
380: KASSERT((int)(cheb->unchecked_size + change) >= 0);
381: KASSERT((int)(cheb->unchecked_size + change) <= chmp->chm_ebh->eb_size);
382: chmp->chm_unchecked_size += change;
383: cheb->unchecked_size += change;
384: return;
385: }
386:
1.8 ttoth 387: /*
388: * chfs_change_size_used - updates used size
389: * "change" parameter is positive if we have to increase the size
390: * and negative if we have to decrease it
391: */
1.1 ahoka 392: void
393: chfs_change_size_used(struct chfs_mount *chmp,
394: struct chfs_eraseblock *cheb, int change)
395: {
396: KASSERT(mutex_owned(&chmp->chm_lock_sizes));
397: KASSERT((int)(chmp->chm_used_size + change) >= 0);
398: KASSERT((int)(cheb->used_size + change) >= 0);
399: KASSERT((int)(cheb->used_size + change) <= chmp->chm_ebh->eb_size);
400: chmp->chm_used_size += change;
401: cheb->used_size += change;
402: return;
403: }
404:
1.8 ttoth 405: /*
406: * chfs_change_size_wasted - updates wasted size
407: * "change" parameter is positive if we have to increase the size
408: * and negative if we have to decrease it
409: */
1.1 ahoka 410: void
411: chfs_change_size_wasted(struct chfs_mount *chmp,
412: struct chfs_eraseblock *cheb, int change)
413: {
414: KASSERT(mutex_owned(&chmp->chm_lock_sizes));
415: KASSERT((int)(chmp->chm_wasted_size + change) >= 0);
416: KASSERT((int)(cheb->wasted_size + change) >= 0);
417: KASSERT((int)(cheb->wasted_size + change) <= chmp->chm_ebh->eb_size);
418: chmp->chm_wasted_size += change;
419: cheb->wasted_size += change;
420: return;
421: }
422:
CVSweb <webmaster@jp.NetBSD.org>