[BACK]Return to ramfs_vnops.c CVS log [TXT][DIR] Up to [local] / prex-old / usr / server / fs / ramfs

Annotation of prex-old/usr/server/fs/ramfs/ramfs_vnops.c, Revision 1.1.1.1.2.1

1.1       nbrk        1: /*
                      2:  * Copyright (c) 2006-2007, Kohsuke Ohtani
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. Neither the name of the author nor the names of any co-contributors
                     14:  *    may be used to endorse or promote products derived from this software
                     15:  *    without specific prior written permission.
                     16:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     27:  * SUCH DAMAGE.
                     28:  */
                     29:
1.1.1.1.2.1! nbrk       30: /*
        !            31:  * rmafs_vnops.c - vnode operations for RAM file system.
        !            32:  */
        !            33:
1.1       nbrk       34: #include <prex/prex.h>
                     35:
                     36: #include <sys/stat.h>
                     37: #include <sys/vnode.h>
                     38: #include <sys/file.h>
                     39: #include <sys/mount.h>
                     40: #include <sys/dirent.h>
                     41: #include <sys/param.h>
                     42:
                     43: #include <errno.h>
                     44: #include <string.h>
                     45: #include <stdlib.h>
                     46: #include <fcntl.h>
                     47:
                     48: #include "ramfs.h"
                     49:
                     50: #define ramfs_open     ((vnop_open_t)vop_nullop)
                     51: #define ramfs_close    ((vnop_close_t)vop_nullop)
1.1.1.1.2.1! nbrk       52: static int ramfs_read  (vnode_t, file_t, void *, size_t, size_t *);
        !            53: static int ramfs_write (vnode_t, file_t, void *, size_t, size_t *);
1.1       nbrk       54: #define ramfs_seek     ((vnop_seek_t)vop_nullop)
                     55: #define ramfs_ioctl    ((vnop_ioctl_t)vop_einval)
                     56: #define ramfs_fsync    ((vnop_fsync_t)vop_nullop)
                     57: static int ramfs_readdir(vnode_t, file_t, struct dirent *);
1.1.1.1.2.1! nbrk       58: static int ramfs_lookup        (vnode_t, char *, vnode_t);
        !            59: static int ramfs_create        (vnode_t, char *, mode_t);
        !            60: static int ramfs_remove        (vnode_t, vnode_t, char *);
        !            61: static int ramfs_rename        (vnode_t, vnode_t, char *, vnode_t, vnode_t, char *);
        !            62: static int ramfs_mkdir (vnode_t, char *, mode_t);
        !            63: static int ramfs_rmdir (vnode_t, vnode_t, char *);
1.1       nbrk       64: #define ramfs_getattr  ((vnop_getattr_t)vop_nullop)
                     65: #define ramfs_setattr  ((vnop_setattr_t)vop_nullop)
                     66: #define ramfs_inactive ((vnop_inactive_t)vop_nullop)
                     67: static int ramfs_truncate(vnode_t);
                     68:
                     69:
                     70: #if CONFIG_FS_THREADS > 1
                     71: static mutex_t ramfs_lock = MUTEX_INITIALIZER;
                     72: #endif
                     73:
                     74: /*
                     75:  * vnode operations
                     76:  */
                     77: struct vnops ramfs_vnops = {
                     78:        ramfs_open,             /* open */
                     79:        ramfs_close,            /* close */
                     80:        ramfs_read,             /* read */
                     81:        ramfs_write,            /* write */
                     82:        ramfs_seek,             /* seek */
                     83:        ramfs_ioctl,            /* ioctl */
                     84:        ramfs_fsync,            /* fsync */
                     85:        ramfs_readdir,          /* readdir */
                     86:        ramfs_lookup,           /* lookup */
                     87:        ramfs_create,           /* create */
                     88:        ramfs_remove,           /* remove */
                     89:        ramfs_rename,           /* remame */
                     90:        ramfs_mkdir,            /* mkdir */
                     91:        ramfs_rmdir,            /* rmdir */
                     92:        ramfs_getattr,          /* getattr */
                     93:        ramfs_setattr,          /* setattr */
                     94:        ramfs_inactive,         /* inactive */
                     95:        ramfs_truncate,         /* truncate */
                     96: };
                     97:
                     98: struct ramfs_node *
                     99: ramfs_allocate_node(char *name, int type)
                    100: {
1.1.1.1.2.1! nbrk      101:        struct ramfs_node *np;
1.1       nbrk      102:
1.1.1.1.2.1! nbrk      103:        np = malloc(sizeof(struct ramfs_node));
        !           104:        if (np == NULL)
1.1       nbrk      105:                return NULL;
1.1.1.1.2.1! nbrk      106:        memset(np, 0, sizeof(struct ramfs_node));
1.1       nbrk      107:
1.1.1.1.2.1! nbrk      108:        np->rn_namelen = strlen(name);
        !           109:        np->rn_name = malloc(np->rn_namelen + 1);
        !           110:        if (np->rn_name == NULL) {
        !           111:                free(np);
1.1       nbrk      112:                return NULL;
                    113:        }
1.1.1.1.2.1! nbrk      114:        strcpy(np->rn_name, name);
        !           115:        np->rn_type = type;
        !           116:        return np;
1.1       nbrk      117: }
                    118:
                    119: void
1.1.1.1.2.1! nbrk      120: ramfs_free_node(struct ramfs_node *np)
1.1       nbrk      121: {
                    122:
1.1.1.1.2.1! nbrk      123:        free(np->rn_name);
        !           124:        free(np);
1.1       nbrk      125: }
                    126:
                    127: static struct ramfs_node *
1.1.1.1.2.1! nbrk      128: ramfs_add_node(struct ramfs_node *dnp, char *name, int type)
1.1       nbrk      129: {
1.1.1.1.2.1! nbrk      130:        struct ramfs_node *np, *prev;
1.1       nbrk      131:
1.1.1.1.2.1! nbrk      132:        np = ramfs_allocate_node(name, type);
        !           133:        if (np == NULL)
1.1       nbrk      134:                return NULL;
                    135:
                    136:        mutex_lock(&ramfs_lock);
                    137:
                    138:        /* Link to the directory list */
1.1.1.1.2.1! nbrk      139:        if (dnp->rn_child == NULL) {
        !           140:                dnp->rn_child = np;
1.1       nbrk      141:        } else {
1.1.1.1.2.1! nbrk      142:                prev = dnp->rn_child;
        !           143:                while (prev->rn_next != NULL)
        !           144:                        prev = prev->rn_next;
        !           145:                prev->rn_next = np;
1.1       nbrk      146:        }
                    147:        mutex_unlock(&ramfs_lock);
1.1.1.1.2.1! nbrk      148:        return np;
1.1       nbrk      149: }
                    150:
                    151: static int
1.1.1.1.2.1! nbrk      152: ramfs_remove_node(struct ramfs_node *dnp, struct ramfs_node *np)
1.1       nbrk      153: {
                    154:        struct ramfs_node *prev;
                    155:
1.1.1.1.2.1! nbrk      156:        if (dnp->rn_child == NULL)
1.1       nbrk      157:                return EBUSY;
                    158:
                    159:        mutex_lock(&ramfs_lock);
                    160:
                    161:        /* Unlink from the directory list */
1.1.1.1.2.1! nbrk      162:        if (dnp->rn_child == np) {
        !           163:                dnp->rn_child = np->rn_next;
1.1       nbrk      164:        } else {
1.1.1.1.2.1! nbrk      165:                for (prev = dnp->rn_child; prev->rn_next != np;
        !           166:                     prev = prev->rn_next) {
        !           167:                        if (prev->rn_next == NULL) {
1.1       nbrk      168:                                mutex_unlock(&ramfs_lock);
                    169:                                return ENOENT;
                    170:                        }
                    171:                }
1.1.1.1.2.1! nbrk      172:                prev->rn_next = np->rn_next;
1.1       nbrk      173:        }
1.1.1.1.2.1! nbrk      174:        ramfs_free_node(np);
1.1       nbrk      175:
                    176:        mutex_unlock(&ramfs_lock);
                    177:        return 0;
                    178: }
                    179:
                    180: static int
1.1.1.1.2.1! nbrk      181: ramfs_rename_node(struct ramfs_node *np, char *name)
1.1       nbrk      182: {
                    183:        size_t len;
                    184:        char *tmp;
                    185:
                    186:        len = strlen(name);
1.1.1.1.2.1! nbrk      187:        if (len <= np->rn_namelen) {
1.1       nbrk      188:                /* Reuse current name buffer */
1.1.1.1.2.1! nbrk      189:                strcpy(np->rn_name, name);
1.1       nbrk      190:        } else {
                    191:                /* Expand name buffer */
                    192:                tmp = malloc(len + 1);
                    193:                if (tmp == NULL)
                    194:                        return ENOMEM;
                    195:                strcpy(tmp, name);
1.1.1.1.2.1! nbrk      196:                free(np->rn_name);
        !           197:                np->rn_name = tmp;
1.1       nbrk      198:        }
1.1.1.1.2.1! nbrk      199:        np->rn_namelen = len;
1.1       nbrk      200:        return 0;
                    201: }
                    202:
                    203: static int
                    204: ramfs_lookup(vnode_t dvp, char *name, vnode_t vp)
                    205: {
1.1.1.1.2.1! nbrk      206:        struct ramfs_node *np, *dnp;
1.1       nbrk      207:        size_t len;
1.1.1.1.2.1! nbrk      208:        int found;
1.1       nbrk      209:
                    210:        if (*name == '\0')
                    211:                return ENOENT;
                    212:
                    213:        mutex_lock(&ramfs_lock);
                    214:
                    215:        len = strlen(name);
1.1.1.1.2.1! nbrk      216:        dnp = dvp->v_data;
        !           217:        found = 0;
        !           218:        for (np = dnp->rn_child; np != NULL; np = np->rn_next) {
        !           219:                if (np->rn_namelen == len &&
        !           220:                    memcmp(name, np->rn_name, len) == 0) {
        !           221:                        found = 1;
1.1       nbrk      222:                        break;
1.1.1.1.2.1! nbrk      223:                }
1.1       nbrk      224:        }
1.1.1.1.2.1! nbrk      225:        if (found == 0) {
1.1       nbrk      226:                mutex_unlock(&ramfs_lock);
                    227:                return ENOENT;
                    228:        }
1.1.1.1.2.1! nbrk      229:        vp->v_data = np;
1.1       nbrk      230:        vp->v_mode = ALLPERMS;
1.1.1.1.2.1! nbrk      231:        vp->v_type = np->rn_type;
        !           232:        vp->v_size = np->rn_size;
1.1       nbrk      233:
                    234:        mutex_unlock(&ramfs_lock);
                    235:        return 0;
                    236: }
                    237:
                    238: static int
                    239: ramfs_mkdir(vnode_t dvp, char *name, mode_t mode)
                    240: {
1.1.1.1.2.1! nbrk      241:        struct ramfs_node *np;
1.1       nbrk      242:
1.1.1.1.2.1! nbrk      243:        DPRINTF(("mkdir %s\n", name));
1.1       nbrk      244:        if (!S_ISDIR(mode))
                    245:                return EINVAL;
                    246:
1.1.1.1.2.1! nbrk      247:        np = ramfs_add_node(dvp->v_data, name, VDIR);
        !           248:        if (np == NULL)
1.1       nbrk      249:                return ENOMEM;
1.1.1.1.2.1! nbrk      250:        np->rn_size = 0;
1.1       nbrk      251:        return 0;
                    252: }
                    253:
                    254: /* Remove a directory */
                    255: static int
                    256: ramfs_rmdir(vnode_t dvp, vnode_t vp, char *name)
                    257: {
                    258:
                    259:        return ramfs_remove_node(dvp->v_data, vp->v_data);
                    260: }
                    261:
                    262: /* Remove a file */
                    263: static int
                    264: ramfs_remove(vnode_t dvp, vnode_t vp, char *name)
                    265: {
1.1.1.1.2.1! nbrk      266:        struct ramfs_node *np;
1.1       nbrk      267:        int err;
                    268:
1.1.1.1.2.1! nbrk      269:        DPRINTF(("remove %s in %s\n", name, dvp->v_path));
1.1       nbrk      270:        err = ramfs_remove_node(dvp->v_data, vp->v_data);
                    271:        if (err)
                    272:                return err;
                    273:
1.1.1.1.2.1! nbrk      274:        np = vp->v_data;
        !           275:        if (np->rn_buf != NULL)
        !           276:                vm_free(task_self(), np->rn_buf);
1.1       nbrk      277:        return 0;
                    278: }
                    279:
                    280: /* Truncate file */
                    281: static int
                    282: ramfs_truncate(vnode_t vp)
                    283: {
1.1.1.1.2.1! nbrk      284:        struct ramfs_node *np;
1.1       nbrk      285:
1.1.1.1.2.1! nbrk      286:        DPRINTF(("truncate %s\n", vp->v_path));
        !           287:        np = vp->v_data;
        !           288:        if (np->rn_buf != NULL) {
        !           289:                vm_free(task_self(), np->rn_buf);
        !           290:                np->rn_buf = NULL;
        !           291:                np->rn_bufsize = 0;
1.1       nbrk      292:        }
                    293:        vp->v_size = 0;
                    294:        return 0;
                    295: }
                    296:
                    297: /*
                    298:  * Create empty file.
                    299:  */
                    300: static int
                    301: ramfs_create(vnode_t dvp, char *name, mode_t mode)
                    302: {
1.1.1.1.2.1! nbrk      303:        struct ramfs_node *np;
1.1       nbrk      304:
1.1.1.1.2.1! nbrk      305:        DPRINTF(("create %s in %s\n", name, dvp->v_path));
1.1       nbrk      306:        if (!S_ISREG(mode))
                    307:                return EINVAL;
                    308:
1.1.1.1.2.1! nbrk      309:        np = ramfs_add_node(dvp->v_data, name, VREG);
        !           310:        if (np == NULL)
1.1       nbrk      311:                return ENOMEM;
                    312:        return 0;
                    313: }
                    314:
                    315: static int
                    316: ramfs_read(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
                    317: {
1.1.1.1.2.1! nbrk      318:        struct ramfs_node *np;
1.1       nbrk      319:        off_t off;
                    320:
                    321:        *result = 0;
                    322:        if (vp->v_type == VDIR)
                    323:                return EISDIR;
                    324:        if (vp->v_type != VREG)
                    325:                return EINVAL;
                    326:
                    327:        off = fp->f_offset;
                    328:        if (off >= (off_t)vp->v_size)
                    329:                return 0;
                    330:
                    331:        if (vp->v_size - off < size)
                    332:                size = vp->v_size - off;
                    333:
1.1.1.1.2.1! nbrk      334:        np = vp->v_data;
        !           335:        memcpy(buf, np->rn_buf + off, size);
1.1       nbrk      336:
                    337:        fp->f_offset += size;
                    338:        *result = size;
                    339:        return 0;
                    340: }
                    341:
                    342: static int
                    343: ramfs_write(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
                    344: {
1.1.1.1.2.1! nbrk      345:        struct ramfs_node *np;
1.1       nbrk      346:        off_t file_pos, end_pos;
                    347:        void *new_buf;
                    348:        size_t new_size;
                    349:        task_t task;
                    350:
                    351:        *result = 0;
                    352:        if (vp->v_type == VDIR)
                    353:                return EISDIR;
                    354:        if (vp->v_type != VREG)
                    355:                return EINVAL;
                    356:
1.1.1.1.2.1! nbrk      357:        np = vp->v_data;
1.1       nbrk      358:        /* Check if the file position exceeds the end of file. */
                    359:        end_pos = vp->v_size;
                    360:        file_pos = (fp->f_flags & O_APPEND) ? end_pos : fp->f_offset;
                    361:        if (file_pos + size > (size_t)end_pos) {
                    362:                /* Expand the file size before writing to it */
                    363:                end_pos = file_pos + size;
1.1.1.1.2.1! nbrk      364:                if (end_pos > (off_t)np->rn_bufsize) {
1.1       nbrk      365:                        task = task_self();
                    366:                        /*
                    367:                         * We allocate the data buffer in page boundary.
                    368:                         * So that we can reduce the memory allocation unless
                    369:                         * the file size exceeds next page boundary.
                    370:                         * This will prevent the memory fragmentation by
                    371:                         * many malloc/free calls.
                    372:                         */
                    373:                        new_size = PAGE_ALIGN(end_pos);
                    374:                        if (vm_allocate(task, &new_buf, new_size, 1))
                    375:                                return EIO;
1.1.1.1.2.1! nbrk      376:                        if (np->rn_size != 0) {
        !           377:                                memcpy(new_buf, np->rn_buf, vp->v_size);
        !           378:                                vm_free(task, np->rn_buf);
1.1       nbrk      379:                        }
1.1.1.1.2.1! nbrk      380:                        np->rn_buf = new_buf;
        !           381:                        np->rn_bufsize = new_size;
1.1       nbrk      382:                }
1.1.1.1.2.1! nbrk      383:                np->rn_size = end_pos;
1.1       nbrk      384:                vp->v_size = end_pos;
                    385:        }
1.1.1.1.2.1! nbrk      386:        memcpy(np->rn_buf + file_pos, buf, size);
1.1       nbrk      387:        fp->f_offset += size;
                    388:        *result = size;
                    389:        return 0;
                    390: }
                    391:
                    392: static int
                    393: ramfs_rename(vnode_t dvp1, vnode_t vp1, char *name1,
                    394:             vnode_t dvp2, vnode_t vp2, char *name2)
                    395: {
1.1.1.1.2.1! nbrk      396:        struct ramfs_node *np, *old_np;
1.1       nbrk      397:        int err;
                    398:
                    399:        if (vp2) {
                    400:                /* Remove destination file, first */
                    401:                err = ramfs_remove_node(dvp2->v_data, vp2->v_data);
                    402:                if (err)
                    403:                        return err;
                    404:        }
                    405:        /* Same directory ? */
                    406:        if (dvp1 == dvp2) {
                    407:                /* Change the name of existing file */
                    408:                err = ramfs_rename_node(vp1->v_data, name2);
                    409:                if (err)
                    410:                        return err;
                    411:        } else {
                    412:                /* Create new file or directory */
1.1.1.1.2.1! nbrk      413:                old_np = vp1->v_data;
        !           414:                np = ramfs_add_node(dvp2->v_data, name2, VREG);
        !           415:                if (np == NULL)
1.1       nbrk      416:                        return ENOMEM;
                    417:
                    418:                if (vp1->v_type == VREG) {
                    419:                        /* Copy file data */
1.1.1.1.2.1! nbrk      420:                        np->rn_buf = old_np->rn_buf;
        !           421:                        np->rn_size = old_np->rn_size;
        !           422:                        np->rn_bufsize = old_np->rn_bufsize;
1.1       nbrk      423:                }
                    424:                /* Remove source file */
                    425:                ramfs_remove_node(dvp1->v_data, vp1->v_data);
                    426:        }
                    427:        return 0;
                    428: }
                    429:
                    430: /*
                    431:  * @vp: vnode of the directory.
                    432:  */
                    433: static int
                    434: ramfs_readdir(vnode_t vp, file_t fp, struct dirent *dir)
                    435: {
1.1.1.1.2.1! nbrk      436:        struct ramfs_node *np, *dnp;
1.1       nbrk      437:        int i;
                    438:
                    439:        mutex_lock(&ramfs_lock);
                    440:
                    441:        if (fp->f_offset == 0) {
                    442:                dir->d_type = DT_DIR;
                    443:                strcpy((char *)&dir->d_name, ".");
                    444:        } else if (fp->f_offset == 1) {
                    445:                dir->d_type = DT_DIR;
                    446:                strcpy((char *)&dir->d_name, "..");
                    447:        } else {
1.1.1.1.2.1! nbrk      448:                dnp = vp->v_data;
        !           449:                np = dnp->rn_child;
        !           450:                if (np == NULL) {
1.1       nbrk      451:                        mutex_unlock(&ramfs_lock);
                    452:                        return ENOENT;
                    453:                }
                    454:
                    455:                for (i = 0; i != (fp->f_offset - 2); i++) {
1.1.1.1.2.1! nbrk      456:                        np = np->rn_next;
        !           457:                        if (np == NULL) {
1.1       nbrk      458:                                mutex_unlock(&ramfs_lock);
                    459:                                return ENOENT;
                    460:                        }
                    461:                }
1.1.1.1.2.1! nbrk      462:                if (np->rn_type == VDIR)
1.1       nbrk      463:                        dir->d_type = DT_DIR;
                    464:                else
                    465:                        dir->d_type = DT_REG;
1.1.1.1.2.1! nbrk      466:                strcpy((char *)&dir->d_name, np->rn_name);
1.1       nbrk      467:        }
                    468:        dir->d_fileno = fp->f_offset;
                    469:        dir->d_namlen = strlen(dir->d_name);
                    470:
                    471:        fp->f_offset++;
                    472:
                    473:        mutex_unlock(&ramfs_lock);
                    474:        return 0;
                    475: }
                    476:
                    477: int
                    478: ramfs_init(void)
                    479: {
                    480:        return 0;
                    481: }

CVSweb