tools/llvm: Do not build with symbols
[minix3.git] / sys / ufs / chfs / chfs_vnode.c
blob23a27a3f38f328338c2db3552e289f1f3a383b38
1 /* $NetBSD: chfs_vnode.c,v 1.8 2012/10/19 12:44:39 ttoth Exp $ */
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.
10 * This code is derived from software contributed to The NetBSD Foundation
11 * by the Department of Software Engineering, University of Szeged, Hungary
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.
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.
35 #include "chfs.h"
36 #include "chfs_inode.h"
37 #include <sys/malloc.h>
38 #include <sys/kauth.h>
39 #include <sys/namei.h>
40 #include <sys/uio.h>
41 #include <sys/buf.h>
43 #include <miscfs/genfs/genfs.h>
45 /* chfs_vnode_lookup - lookup for a vnode */
46 struct vnode *
47 chfs_vnode_lookup(struct chfs_mount *chmp, ino_t vno)
49 struct vnode *vp;
50 struct chfs_inode *ip;
52 TAILQ_FOREACH(vp, &chmp->chm_fsmp->mnt_vnodelist, v_mntvnodes) {
53 ip = VTOI(vp);
54 if (ip && ip->ino == vno)
55 return vp;
57 return NULL;
60 /* chfs_readvnode - reads a vnode from the flash and setups its inode */
61 int
62 chfs_readvnode(struct mount *mp, ino_t ino, struct vnode **vpp)
64 struct ufsmount* ump = VFSTOUFS(mp);
65 struct chfs_mount *chmp = ump->um_chfs;
66 struct chfs_vnode_cache *chvc;
67 struct chfs_flash_vnode *chfvn;
68 struct chfs_inode *ip;
69 int err;
70 char* buf;
71 size_t retlen, len;
72 struct vnode* vp = NULL;
73 dbg("readvnode | ino: %llu\n", (unsigned long long)ino);
75 len = sizeof(struct chfs_flash_vnode);
77 KASSERT(vpp != NULL);
79 if (vpp != NULL) {
80 vp = *vpp;
83 ip = VTOI(vp);
84 chvc = ip->chvc;
86 /* root node is in-memory only */
87 if (chvc && ino != CHFS_ROOTINO) {
88 dbg("offset: %" PRIu32 ", lnr: %d\n",
89 CHFS_GET_OFS(chvc->v->nref_offset), chvc->v->nref_lnr);
91 KASSERT((void *)chvc != (void *)chvc->v);
93 /* reading */
94 buf = kmem_alloc(len, KM_SLEEP);
95 err = chfs_read_leb(chmp, chvc->v->nref_lnr, buf,
96 CHFS_GET_OFS(chvc->v->nref_offset), len, &retlen);
97 if (err)
98 return err;
99 if (retlen != len) {
100 chfs_err("Error reading vnode: read: %zu insted of: %zu\n",
101 len, retlen);
102 return EIO;
104 chfvn = (struct chfs_flash_vnode*)buf;
106 /* setup inode fields */
107 chfs_set_vnode_size(vp, chfvn->dn_size);
108 ip->mode = chfvn->mode;
109 ip->ch_type = IFTOCHT(ip->mode);
110 vp->v_type = CHTTOVT(ip->ch_type);
111 ip->version = chfvn->version;
112 ip->uid = chfvn->uid;
113 ip->gid = chfvn->gid;
114 ip->atime = chfvn->atime;
115 ip->mtime = chfvn->mtime;
116 ip->ctime = chfvn->ctime;
118 kmem_free(buf, len);
122 *vpp = vp;
123 return 0;
127 * chfs_readddirent -
128 * reads a directory entry from flash and adds it to its inode
131 chfs_readdirent(struct mount *mp, struct chfs_node_ref *chnr, struct chfs_inode *pdir)
133 struct ufsmount *ump = VFSTOUFS(mp);
134 struct chfs_mount *chmp = ump->um_chfs;
135 struct chfs_flash_dirent_node chfdn;
136 struct chfs_dirent *fd;
137 size_t len = sizeof(struct chfs_flash_dirent_node);
138 size_t retlen;
139 int err = 0;
141 /* read flash_dirent_node */
142 err = chfs_read_leb(chmp, chnr->nref_lnr, (char *)&chfdn,
143 CHFS_GET_OFS(chnr->nref_offset), len, &retlen);
144 if (err) {
145 return err;
147 if (retlen != len) {
148 chfs_err("Error reading vnode: read: %zu insted of: %zu\n",
149 retlen, len);
150 return EIO;
153 /* set fields of dirent */
154 fd = chfs_alloc_dirent(chfdn.nsize + 1);
155 fd->version = chfdn.version;
156 fd->vno = chfdn.vno;
157 fd->type = chfdn.dtype;
158 fd->nsize = chfdn.nsize;
160 /* read the name of the dirent */
161 err = chfs_read_leb(chmp, chnr->nref_lnr, fd->name,
162 CHFS_GET_OFS(chnr->nref_offset) + len, chfdn.nsize, &retlen);
163 if (err) {
164 return err;
167 if (retlen != chfdn.nsize) {
168 chfs_err("Error reading vnode: read: %zu insted of: %zu\n",
169 len, retlen);
170 return EIO;
173 fd->name[fd->nsize] = 0;
174 fd->nref = chnr;
176 /* add to inode */
177 chfs_add_fd_to_inode(chmp, pdir, fd);
178 return 0;
181 /* chfs_makeinode - makes a new file and initializes its structures */
183 chfs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp,
184 struct componentname *cnp, enum vtype type)
186 struct chfs_inode *ip, *pdir;
187 struct vnode *vp;
188 struct ufsmount* ump = VFSTOUFS(dvp->v_mount);
189 struct chfs_mount* chmp = ump->um_chfs;
190 struct chfs_vnode_cache* chvc;
191 int error;
192 ino_t vno;
193 struct chfs_dirent *nfd;
195 dbg("makeinode\n");
196 pdir = VTOI(dvp);
198 *vpp = NULL;
200 /* number of vnode will be the new maximum */
201 vno = ++(chmp->chm_max_vno);
203 error = VFS_VGET(dvp->v_mount, vno, &vp);
204 if (error)
205 return (error);
207 /* setup vnode cache */
208 mutex_enter(&chmp->chm_lock_vnocache);
209 chvc = chfs_vnode_cache_get(chmp, vno);
211 chvc->pvno = pdir->ino;
212 chvc->vno_version = kmem_alloc(sizeof(uint64_t), KM_SLEEP);
213 *(chvc->vno_version) = 1;
214 if (type != VDIR)
215 chvc->nlink = 1;
216 else
217 chvc->nlink = 2;
218 chvc->state = VNO_STATE_CHECKEDABSENT;
219 mutex_exit(&chmp->chm_lock_vnocache);
221 /* setup inode */
222 ip = VTOI(vp);
223 ip->ino = vno;
225 if (type == VDIR)
226 chfs_set_vnode_size(vp, 512);
227 else
228 chfs_set_vnode_size(vp, 0);
230 ip->uid = kauth_cred_geteuid(cnp->cn_cred);
231 ip->gid = kauth_cred_getegid(cnp->cn_cred);
232 ip->version = 1;
233 ip->iflag |= (IN_ACCESS | IN_CHANGE | IN_UPDATE);
235 ip->chvc = chvc;
236 ip->target = NULL;
238 ip->mode = mode;
239 vp->v_type = type; /* Rest init'd in getnewvnode(). */
240 ip->ch_type = VTTOCHT(vp->v_type);
242 /* authorize setting SGID if needed */
243 if (ip->mode & ISGID) {
244 error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY,
245 vp, NULL, genfs_can_chmod(vp->v_type, cnp->cn_cred, ip->uid,
246 ip->gid, mode));
247 if (error)
248 ip->mode &= ~ISGID;
251 /* write vnode information to the flash */
252 chfs_update(vp, NULL, NULL, UPDATE_WAIT);
254 mutex_enter(&chmp->chm_lock_mountfields);
256 error = chfs_write_flash_vnode(chmp, ip, ALLOC_NORMAL);
257 if (error) {
258 mutex_exit(&chmp->chm_lock_mountfields);
259 vput(vp);
260 vput(dvp);
261 return error;
264 /* update parent's vnode information and write it to the flash */
265 pdir->iflag |= (IN_ACCESS | IN_CHANGE | IN_MODIFY | IN_UPDATE);
266 chfs_update(dvp, NULL, NULL, UPDATE_WAIT);
268 error = chfs_write_flash_vnode(chmp, pdir, ALLOC_NORMAL);
269 if (error) {
270 mutex_exit(&chmp->chm_lock_mountfields);
271 vput(vp);
272 vput(dvp);
273 return error;
275 vput(dvp);
277 /* setup directory entry */
278 nfd = chfs_alloc_dirent(cnp->cn_namelen + 1);
279 nfd->vno = ip->ino;
280 nfd->version = (++pdir->chvc->highest_version);
281 nfd->type = ip->ch_type;
282 nfd->nsize = cnp->cn_namelen;
283 memcpy(&(nfd->name), cnp->cn_nameptr, cnp->cn_namelen);
284 nfd->name[nfd->nsize] = 0;
285 nfd->nhash = hash32_buf(nfd->name, cnp->cn_namelen, HASH32_BUF_INIT);
287 /* write out */
288 error = chfs_write_flash_dirent(chmp, pdir, ip, nfd, ip->ino, ALLOC_NORMAL);
289 if (error) {
290 mutex_exit(&chmp->chm_lock_mountfields);
291 vput(vp);
292 return error;
295 //TODO set parent's dir times
297 /* add dirent to parent */
298 chfs_add_fd_to_inode(chmp, pdir, nfd);
300 pdir->chvc->nlink++;
302 mutex_exit(&chmp->chm_lock_mountfields);
304 *vpp = vp;
305 return (0);
308 /* chfs_set_vnode_size - updates size of vnode and also inode */
309 void
310 chfs_set_vnode_size(struct vnode *vp, size_t size)
312 struct chfs_inode *ip;
314 KASSERT(vp != NULL);
316 ip = VTOI(vp);
317 KASSERT(ip != NULL);
319 ip->size = size;
320 vp->v_size = vp->v_writesize = size;
321 return;
325 * chfs_change_size_free - updates free size
326 * "change" parameter is positive if we have to increase the size
327 * and negative if we have to decrease it
329 void
330 chfs_change_size_free(struct chfs_mount *chmp,
331 struct chfs_eraseblock *cheb, int change)
333 KASSERT(mutex_owned(&chmp->chm_lock_sizes));
334 KASSERT((int)(chmp->chm_free_size + change) >= 0);
335 KASSERT((int)(cheb->free_size + change) >= 0);
336 KASSERT((int)(cheb->free_size + change) <= chmp->chm_ebh->eb_size);
337 chmp->chm_free_size += change;
338 cheb->free_size += change;
339 return;
343 * chfs_change_size_dirty - updates dirty size
344 * "change" parameter is positive if we have to increase the size
345 * and negative if we have to decrease it
347 void
348 chfs_change_size_dirty(struct chfs_mount *chmp,
349 struct chfs_eraseblock *cheb, int change)
351 KASSERT(mutex_owned(&chmp->chm_lock_sizes));
352 KASSERT((int)(chmp->chm_dirty_size + change) >= 0);
353 KASSERT((int)(cheb->dirty_size + change) >= 0);
354 KASSERT((int)(cheb->dirty_size + change) <= chmp->chm_ebh->eb_size);
355 chmp->chm_dirty_size += change;
356 cheb->dirty_size += change;
357 return;
361 * chfs_change_size_unchecked - updates unchecked size
362 * "change" parameter is positive if we have to increase the size
363 * and negative if we have to decrease it
365 void
366 chfs_change_size_unchecked(struct chfs_mount *chmp,
367 struct chfs_eraseblock *cheb, int change)
369 KASSERT(mutex_owned(&chmp->chm_lock_sizes));
370 KASSERT((int)(chmp->chm_unchecked_size + change) >= 0);
371 KASSERT((int)(cheb->unchecked_size + change) >= 0);
372 KASSERT((int)(cheb->unchecked_size + change) <= chmp->chm_ebh->eb_size);
373 chmp->chm_unchecked_size += change;
374 cheb->unchecked_size += change;
375 return;
379 * chfs_change_size_used - updates used size
380 * "change" parameter is positive if we have to increase the size
381 * and negative if we have to decrease it
383 void
384 chfs_change_size_used(struct chfs_mount *chmp,
385 struct chfs_eraseblock *cheb, int change)
387 KASSERT(mutex_owned(&chmp->chm_lock_sizes));
388 KASSERT((int)(chmp->chm_used_size + change) >= 0);
389 KASSERT((int)(cheb->used_size + change) >= 0);
390 KASSERT((int)(cheb->used_size + change) <= chmp->chm_ebh->eb_size);
391 chmp->chm_used_size += change;
392 cheb->used_size += change;
393 return;
397 * chfs_change_size_wasted - updates wasted size
398 * "change" parameter is positive if we have to increase the size
399 * and negative if we have to decrease it
401 void
402 chfs_change_size_wasted(struct chfs_mount *chmp,
403 struct chfs_eraseblock *cheb, int change)
405 KASSERT(mutex_owned(&chmp->chm_lock_sizes));
406 KASSERT((int)(chmp->chm_wasted_size + change) >= 0);
407 KASSERT((int)(cheb->wasted_size + change) >= 0);
408 KASSERT((int)(cheb->wasted_size + change) <= chmp->chm_ebh->eb_size);
409 chmp->chm_wasted_size += change;
410 cheb->wasted_size += change;
411 return;