The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/sysvbfs/bfs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: bfs.c,v 1.6 2006/08/26 14:04:55 tsutsui Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 2004 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by UCHIYAMA Yasushi.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 
   41 __KERNEL_RCSID(0, "$NetBSD: bfs.c,v 1.6 2006/08/26 14:04:55 tsutsui Exp $");
   42 #define BFS_DEBUG
   43 
   44 #include <sys/param.h>
   45 #include <sys/kernel.h>
   46 #include <sys/types.h>
   47 #include <sys/systm.h>
   48 #include <sys/errno.h>
   49 #include <sys/malloc.h>
   50 #include <sys/time.h>
   51 
   52 #ifdef _KERNEL
   53 MALLOC_DEFINE(M_BFS, "sysvbfs core", "sysvbfs internal structures");
   54 #define __MALLOC(s, t, f)       malloc(s, t, f)
   55 #define __FREE(a, s, t)         free(a, t)
   56 #elif defined _STANDALONE
   57 #include <lib/libsa/stand.h>
   58 #include <lib/libkern/libkern.h>
   59 #define __MALLOC(s, t, f)       alloc(s)
   60 #define __FREE(a, s, t)         dealloc(a, s)
   61 #else
   62 #include "local.h"
   63 #define __MALLOC(s, t, f)       malloc(s)
   64 #define __FREE(a, s, t)         free(a)
   65 #endif
   66 #include <fs/sysvbfs/bfs.h>
   67 
   68 #ifdef BFS_DEBUG
   69 #define DPRINTF(on, fmt, args...)       if (on) printf(fmt, ##args)
   70 #else
   71 #define DPRINTF(arg...)         ((void)0)
   72 #endif
   73 
   74 #define ROUND_SECTOR(x)         (((x) + 511) & ~511)
   75 #define TRUNC_SECTOR(x)         ((x) & ~511)
   76 
   77 #define STATIC
   78 
   79 STATIC int bfs_init_superblock(struct bfs *, int, size_t *);
   80 STATIC int bfs_init_inode(struct bfs *, uint8_t *, size_t *);
   81 STATIC int bfs_init_dirent(struct bfs *, uint8_t *);
   82 
   83 /* super block ops. */
   84 STATIC boolean_t bfs_superblock_valid(const struct bfs_super_block *);
   85 STATIC boolean_t bfs_writeback_dirent(const struct bfs *, struct bfs_dirent *,
   86     boolean_t);
   87 STATIC boolean_t bfs_writeback_inode(const struct bfs *, struct bfs_inode *);
   88 
   89 int
   90 bfs_init2(struct bfs **bfsp, int bfs_sector, struct sector_io_ops *io,
   91     boolean_t debug)
   92 {
   93         struct bfs *bfs;
   94         size_t memsize;
   95         uint8_t *p;
   96         int err;
   97 
   98         /* 1. */
   99         DPRINTF(debug, "bfs sector = %d\n", bfs_sector);
  100         if ((bfs = (void *)__MALLOC(sizeof(struct bfs), M_BFS, M_NOWAIT)) == 0)
  101                 return ENOMEM;
  102         memset(bfs, 0, sizeof *bfs);
  103         bfs->io = io;
  104         bfs->debug = debug;
  105 
  106         /* 2. */
  107         if ((err = bfs_init_superblock(bfs, bfs_sector, &memsize)) != 0) {
  108                 bfs_fini(bfs);
  109                 return err;
  110         }
  111         DPRINTF(debug, "bfs super block + inode area = %zd\n", memsize);
  112         bfs->super_block_size = memsize;
  113         if ((p = (void *)__MALLOC(memsize, M_BFS, M_NOWAIT)) == 0) {
  114                 bfs_fini(bfs);
  115                 return ENOMEM;
  116         }
  117         /* 3. */
  118         if ((err = bfs_init_inode(bfs, p, &memsize)) != 0) {
  119                 bfs_fini(bfs);
  120                 return err;
  121         }
  122         DPRINTF(debug, "bfs dirent area = %zd\n", memsize);
  123         bfs->dirent_size = memsize;
  124         if ((p = (void *)__MALLOC(memsize, M_BFS, M_NOWAIT)) == 0) {
  125                 bfs_fini(bfs);
  126                 return ENOMEM;
  127         }
  128         /* 4. */
  129         if ((err = bfs_init_dirent(bfs, p)) != 0) {
  130                 bfs_fini(bfs);
  131                 return err;
  132         }
  133 
  134 #ifdef BFS_DEBUG
  135         bfs_dump(bfs);
  136 #endif
  137         *bfsp = bfs;
  138 
  139         return 0;
  140 }
  141 
  142 void
  143 bfs_fini(struct bfs *bfs)
  144 {
  145 
  146         if (bfs == 0)
  147                 return;
  148         if (bfs->super_block)
  149                 __FREE(bfs->super_block, bfs->super_block_size, M_BFS);
  150         if (bfs->dirent)
  151                 __FREE(bfs->dirent, bfs->dirent_size, M_BFS);
  152         __FREE(bfs, sizeof(struct bfs), M_BFS);
  153 }
  154 
  155 STATIC int
  156 bfs_init_superblock(struct bfs *bfs, int bfs_sector, size_t *required_memory)
  157 {
  158         struct bfs_super_block super;
  159 
  160         bfs->start_sector = bfs_sector;
  161 
  162         /* Read super block */
  163         if (!bfs->io->read(bfs->io, (uint8_t *)&super, bfs_sector))
  164                 return EIO;
  165 
  166         if (!bfs_superblock_valid(&super))
  167                 return EINVAL;
  168 
  169         /* i-node table size */
  170         bfs->data_start = super.header.data_start_byte;
  171         bfs->data_end = super.header.data_end_byte;
  172 
  173         bfs->max_inode = (bfs->data_start - sizeof(struct bfs_super_block)) /
  174             sizeof(struct bfs_inode);
  175 
  176         *required_memory = ROUND_SECTOR(bfs->data_start);
  177 
  178         return 0;
  179 }
  180 
  181 STATIC int
  182 bfs_init_inode(struct bfs *bfs, uint8_t *p, size_t *required_memory)
  183 {
  184         struct bfs_inode *inode, *root_inode;
  185         int i;
  186 
  187         if (!bfs->io->read_n(bfs->io, p, bfs->start_sector,
  188             bfs->data_start >> DEV_BSHIFT))
  189                 return EIO;
  190 
  191         bfs->super_block = (struct bfs_super_block *)p;
  192         bfs->inode = (struct bfs_inode *)(p + sizeof(struct bfs_super_block));
  193         p += bfs->data_start;
  194 
  195         bfs->n_inode = 0;
  196         inode = bfs->inode;
  197         root_inode = 0;
  198         for (i = 0; i < bfs->max_inode; i++, inode++) {
  199                 if (inode->number != 0) {
  200                         bfs->n_inode++;
  201                         if (inode->number == BFS_ROOT_INODE)
  202                                 root_inode = inode;
  203                 }
  204         }
  205         DPRINTF(bfs->debug, "inode: %d/%d\n", bfs->n_inode, bfs->max_inode);
  206 
  207         if (root_inode == 0) {
  208                 DPRINTF(bfs->debug, "no root directory.\n");
  209                 return ENOTDIR;
  210         }
  211         /* dirent table size */
  212         DPRINTF(bfs->debug, "root inode: %d-%d\n", root_inode->start_sector,
  213             root_inode->end_sector);
  214         bfs->root_inode = root_inode;
  215 
  216         *required_memory = (root_inode->end_sector -
  217             root_inode->start_sector + 1) << DEV_BSHIFT;
  218 
  219         return 0;
  220 }
  221 
  222 STATIC int
  223 bfs_init_dirent(struct bfs *bfs, uint8_t *p)
  224 {
  225         struct bfs_dirent *file;
  226         struct bfs_inode *inode = bfs->root_inode;
  227         int i, n;
  228 
  229         n = inode->end_sector - inode->start_sector + 1;
  230 
  231         if (!bfs->io->read_n(bfs->io, p,
  232             bfs->start_sector + inode->start_sector, n))
  233                 return EIO;
  234 
  235         bfs->dirent = (struct bfs_dirent *)p;
  236         bfs->max_dirent = (n << DEV_BSHIFT) / sizeof(struct bfs_dirent);
  237 
  238         file = bfs->dirent;
  239         bfs->n_dirent = 0;
  240         for (i = 0; i < bfs->max_dirent; i++, file++)
  241                 if (file->inode != 0)
  242                         bfs->n_dirent++;
  243 
  244         DPRINTF(bfs->debug, "dirent: %d/%d\n", bfs->n_dirent, bfs->max_dirent);
  245 
  246         return 0;
  247 }
  248 
  249 int
  250 bfs_file_read(const struct bfs *bfs, const char *fname, void *buf, size_t bufsz,
  251     size_t *read_size)
  252 {
  253         int start, end, n;
  254         size_t sz;
  255         uint8_t tmpbuf[DEV_BSIZE];
  256         uint8_t *p;
  257 
  258         if (!bfs_file_lookup(bfs, fname, &start, &end, &sz))
  259                 return ENOENT;
  260 
  261         if (sz > bufsz)
  262                 return ENOMEM;
  263 
  264         p = buf;
  265         n = end - start;
  266         bfs->io->read_n(bfs->io, p, start, n);
  267         /* last sector */
  268         n *= DEV_BSIZE;
  269         bfs->io->read(bfs->io, tmpbuf, end);
  270         memcpy(p + n, tmpbuf, sz - n);
  271 
  272         if (read_size)
  273                 *read_size = sz;
  274 
  275         return 0;
  276 }
  277 
  278 int
  279 bfs_file_write(struct bfs *bfs, const char *fname, void *buf,
  280     size_t bufsz)
  281 {
  282         struct bfs_fileattr attr;
  283         struct bfs_dirent *dirent;
  284         char name[BFS_FILENAME_MAXLEN];
  285         int err;
  286 
  287         strncpy(name, fname, BFS_FILENAME_MAXLEN);
  288 
  289         if (bfs_dirent_lookup_by_name(bfs, name, &dirent)) {
  290                 struct bfs_inode *inode;
  291                 if (!bfs_inode_lookup(bfs, dirent->inode, &inode)) {
  292                         DPRINTF(bfs->debug, "%s: dirent found, but inode "
  293                             "not found. inconsistent filesystem.\n",
  294                             __FUNCTION__);
  295                         return ENOENT;
  296                 }
  297                 attr = inode->attr;     /* copy old attribute */
  298                 bfs_file_delete(bfs, name);
  299                 if ((err = bfs_file_create(bfs, name, buf, bufsz, &attr)) != 0)
  300                         return err;
  301         } else {
  302                 memset(&attr, 0xff, sizeof attr);       /* Set VNOVAL all */
  303 #ifdef _KERNEL
  304                 attr.atime = time_second;
  305                 attr.ctime = time_second;
  306                 attr.mtime = time_second;
  307 #endif
  308                 if ((err = bfs_file_create(bfs, name, buf, bufsz, &attr)) != 0)
  309                         return err;
  310         }
  311 
  312         return 0;
  313 }
  314 
  315 int
  316 bfs_file_delete(struct bfs *bfs, const char *fname)
  317 {
  318         struct bfs_inode *inode;
  319         struct bfs_dirent *dirent;
  320 
  321         if (!bfs_dirent_lookup_by_name(bfs, fname, &dirent))
  322                 return ENOENT;
  323 
  324         if (!bfs_inode_lookup(bfs, dirent->inode, &inode))
  325                 return ENOENT;
  326 
  327         memset(dirent, 0, sizeof *dirent);
  328         memset(inode, 0, sizeof *inode);
  329         bfs->n_inode--;
  330         bfs->n_dirent--;
  331 
  332         bfs_writeback_dirent(bfs, dirent, FALSE);
  333         bfs_writeback_inode(bfs, inode);
  334         DPRINTF(bfs->debug, "%s: \"%s\" deleted.\n", __FUNCTION__, fname);
  335 
  336         return 0;
  337 }
  338 
  339 int
  340 bfs_file_rename(struct bfs *bfs, const char *from_name, const char *to_name)
  341 {
  342         struct bfs_dirent *dirent;
  343         int err = 0;
  344 
  345         if (strlen(to_name) > BFS_FILENAME_MAXLEN) {
  346                 err =  ENAMETOOLONG;
  347                 goto out;
  348         }
  349         if (!bfs_dirent_lookup_by_name(bfs, from_name, &dirent)) {
  350                 err = ENOENT;
  351                 goto out;
  352         }
  353 
  354         bfs_file_delete(bfs, to_name);
  355         strncpy(dirent->name, to_name, BFS_FILENAME_MAXLEN);
  356         bfs_writeback_dirent(bfs, dirent, FALSE);
  357 
  358  out:
  359         DPRINTF(bfs->debug, "%s: \"%s\" -> \"%s\" error=%d.\n", __FUNCTION__,
  360             from_name, to_name, err);
  361 
  362         return err;
  363 }
  364 
  365 int
  366 bfs_file_create(struct bfs *bfs, const char *fname, void *buf, size_t bufsz,
  367     const struct bfs_fileattr *attr)
  368 {
  369         struct bfs_inode *inode;
  370         struct bfs_dirent *file;
  371         int i, j, n, start;
  372         uint8_t *p, tmpbuf[DEV_BSIZE];
  373         int err;
  374 
  375         /* Find free i-node and data block */
  376         if ((err = bfs_inode_alloc(bfs, &inode, &j, &start)) != 0)
  377                 return err;
  378 
  379         /* File size (unit block) */
  380         n = (ROUND_SECTOR(bufsz) >> DEV_BSHIFT) - 1;
  381         if (n < 0)      /* bufsz == 0 */
  382                 n = 0;
  383 
  384         if ((start + n) * DEV_BSIZE >= bfs->data_end) {
  385                 DPRINTF(bfs->debug, "disk full.\n");
  386                 return ENOSPC;
  387         }
  388 
  389         /* Find free dirent */
  390         for (file = bfs->dirent, i = 0; i < bfs->max_dirent; i++, file++)
  391                 if (file->inode == 0)
  392                         break;
  393         if (i == bfs->max_dirent) {
  394                 DPRINTF(bfs->debug, "dirent full.\n");
  395                 return ENOSPC;
  396         }
  397 
  398         /* i-node */
  399         memset(inode, 0, sizeof *inode);
  400         inode->number = j;
  401         inode->start_sector = start;
  402         inode->end_sector = start + n;
  403         inode->eof_offset_byte = start * DEV_BSIZE + bufsz - 1;
  404         /* i-node attribute */
  405         inode->attr.type = 1;
  406         inode->attr.mode = 0;
  407         inode->attr.nlink = 1;
  408         bfs_inode_set_attr(bfs, inode, attr);
  409 
  410         /* Dirent */
  411         memset(file, 0, sizeof *file);
  412         file->inode = inode->number;
  413         strncpy(file->name, fname, BFS_FILENAME_MAXLEN);
  414 
  415         DPRINTF(bfs->debug, "%s: start %d end %d\n", __FUNCTION__,
  416             inode->start_sector, inode->end_sector);
  417 
  418         if (buf != 0) {
  419                 p = (uint8_t *)buf;
  420                 /* Data block */
  421                 n = 0;
  422                 for (i = inode->start_sector; i < inode->end_sector; i++) {
  423                         if (!bfs->io->write(bfs->io, p, bfs->start_sector + i))
  424                                 return EIO;
  425                         p += DEV_BSIZE;
  426                         n += DEV_BSIZE;
  427                 }
  428                 /* last sector */
  429                 memset(tmpbuf, 0, DEV_BSIZE);
  430                 memcpy(tmpbuf, p, bufsz - n);
  431                 if (!bfs->io->write(bfs->io, tmpbuf, bfs->start_sector + i))
  432                         return EIO;
  433         }
  434         /* Update */
  435         bfs->n_inode++;
  436         bfs->n_dirent++;
  437         bfs_writeback_dirent(bfs, file, TRUE);
  438         bfs_writeback_inode(bfs, inode);
  439 
  440         return 0;
  441 }
  442 
  443 STATIC boolean_t
  444 bfs_writeback_dirent(const struct bfs *bfs, struct bfs_dirent *dir,
  445     boolean_t create)
  446 {
  447         struct bfs_dirent *dir_base = bfs->dirent;
  448         struct bfs_inode *root_inode = bfs->root_inode;
  449         uintptr_t eof;
  450         int i;
  451 
  452         i = ((dir - dir_base) * sizeof *dir) >> DEV_BSHIFT;
  453 
  454         eof = (uintptr_t)(dir + 1) - 1;
  455         eof = eof - (uintptr_t)dir_base +
  456             (root_inode->start_sector << DEV_BSHIFT);
  457 
  458         /* update root directory inode */
  459 #if 0
  460         printf("eof new=%d old=%d\n", eof, root_inode->eof_offset_byte);
  461 #endif
  462         if (create) {
  463                 if (eof > root_inode->eof_offset_byte) {
  464                         root_inode->eof_offset_byte = eof;
  465                 }
  466         } else {
  467                 /* delete the last entry */
  468                 if (eof == root_inode->eof_offset_byte) {
  469                         root_inode->eof_offset_byte = eof - sizeof *dir;
  470                 }
  471         }
  472         bfs_writeback_inode(bfs, root_inode);
  473 
  474         /* update dirent */
  475         return bfs->io->write(bfs->io, (uint8_t *)dir_base + (i << DEV_BSHIFT),
  476             bfs->start_sector + bfs->root_inode->start_sector + i);
  477 }
  478 
  479 STATIC boolean_t
  480 bfs_writeback_inode(const struct bfs *bfs, struct bfs_inode *inode)
  481 {
  482         struct bfs_inode *inode_base = bfs->inode;
  483         int i;
  484 
  485         i = ((inode - inode_base) * sizeof *inode) >> DEV_BSHIFT;
  486 
  487         return bfs->io->write(bfs->io,
  488             (uint8_t *)inode_base + (i << DEV_BSHIFT),
  489             bfs->start_sector + 1/*super block*/ + i);
  490 }
  491 
  492 boolean_t
  493 bfs_file_lookup(const struct bfs *bfs, const char *fname, int *start, int *end,
  494     size_t *size)
  495 {
  496         struct bfs_inode *inode;
  497         struct bfs_dirent *dirent;
  498 
  499         if (!bfs_dirent_lookup_by_name(bfs, fname, &dirent))
  500                 return FALSE;
  501         if (!bfs_inode_lookup(bfs, dirent->inode, &inode))
  502                 return FALSE;
  503 
  504         if (start)
  505                 *start = inode->start_sector + bfs->start_sector;
  506         if (end)
  507                 *end = inode->end_sector + bfs->start_sector;
  508         if (size)
  509                 *size = bfs_file_size(inode);
  510 
  511         DPRINTF(bfs->debug, "%s: %d + %d -> %d (%zd)\n",
  512             fname, bfs->start_sector, inode->start_sector,
  513             inode->end_sector, *size);
  514 
  515         return TRUE;
  516 }
  517 
  518 boolean_t
  519 bfs_dirent_lookup_by_inode(const struct bfs *bfs, int inode,
  520     struct bfs_dirent **dirent)
  521 {
  522         struct bfs_dirent *file;
  523         int i;
  524 
  525         for (file = bfs->dirent, i = 0; i < bfs->max_dirent; i++, file++)
  526                 if (file->inode == inode)
  527                         break;
  528 
  529         if (i == bfs->max_dirent)
  530                 return FALSE;
  531 
  532         *dirent = file;
  533 
  534         return TRUE;
  535 }
  536 
  537 boolean_t
  538 bfs_dirent_lookup_by_name(const struct bfs *bfs, const char *fname,
  539     struct bfs_dirent **dirent)
  540 {
  541         struct bfs_dirent *file;
  542         int i;
  543 
  544         for (file = bfs->dirent, i = 0; i < bfs->max_dirent; i++, file++)
  545                 if ((file->inode != 0) &&
  546                     (strncmp(file->name, fname, BFS_FILENAME_MAXLEN) ==0))
  547                         break;
  548 
  549         if (i == bfs->max_dirent)
  550                 return FALSE;
  551 
  552         *dirent = file;
  553 
  554         return TRUE;
  555 }
  556 
  557 boolean_t
  558 bfs_inode_lookup(const struct bfs *bfs, ino_t n, struct bfs_inode **iinode)
  559 {
  560         struct bfs_inode *inode;
  561         int i;
  562 
  563         for (inode = bfs->inode, i = 0; i < bfs->max_inode; i++, inode++)
  564                 if (inode->number == n)
  565                         break;
  566 
  567         if (i == bfs->max_inode)
  568                 return FALSE;
  569 
  570         *iinode = inode;
  571 
  572         return TRUE;
  573 }
  574 
  575 size_t
  576 bfs_file_size(const struct bfs_inode *inode)
  577 {
  578 
  579         return inode->eof_offset_byte - inode->start_sector * DEV_BSIZE + 1;
  580 }
  581 
  582 STATIC int
  583 bfs_inode_alloc(const struct bfs *bfs, struct bfs_inode **free_inode,
  584     int *free_inode_number, int *free_block)
  585 {
  586         struct bfs_inode *jnode, *inode;
  587         int i, j, start;
  588 
  589         j = start = 0;
  590         inode = bfs->inode;
  591         jnode = 0;
  592 
  593         for (i = BFS_ROOT_INODE; i < bfs->max_inode; i++, inode++) {
  594                 /* Steal i-node # */
  595                 if (j == 0)
  596                         j = i;
  597 
  598                 /* Get free i-node */
  599                 if (jnode == 0 && (inode->number == 0))
  600                         jnode = inode;
  601 
  602                 /* Get free i-node # and data block */
  603                 if (inode->number != 0) {
  604                         if (inode->end_sector > start)
  605                                 start = inode->end_sector;
  606                         if (inode->number == j)
  607                                 j = 0;  /* conflict */
  608                 }
  609         }
  610         start++;
  611 
  612         if (jnode ==  0) {
  613                 DPRINTF(bfs->debug, "i-node full.\n");
  614                 return ENOSPC;
  615         }
  616 
  617         if (start * DEV_BSIZE >= bfs->data_end) {
  618                 DPRINTF(bfs->debug, "data block full.\n");
  619                 /* compaction here ? */
  620                 return ENOSPC;
  621         }
  622         if (free_inode)
  623                 *free_inode = jnode;
  624         if (free_inode_number)
  625                 *free_inode_number = j;
  626         if (free_block)
  627                 *free_block = start;
  628 
  629         return 0;
  630 }
  631 
  632 void
  633 bfs_inode_set_attr(const struct bfs *bfs, struct bfs_inode *inode,
  634     const struct bfs_fileattr *from)
  635 {
  636         struct bfs_fileattr *to = &inode->attr;
  637 
  638         if (from != NULL) {
  639                 if (from->uid != (uid_t)-1)
  640                         to->uid = from->uid;
  641                 if (from->gid != (uid_t)-1)
  642                         to->gid = from->gid;
  643                 if (from->mode != (mode_t)-1)
  644                         to->mode = from->mode;
  645                 if (from->atime != -1)
  646                         to->atime = from->atime;
  647                 if (from->ctime != -1)
  648                         to->ctime = from->ctime;
  649                 if (from->mtime != -1)
  650                         to->mtime = from->mtime;
  651         }
  652         bfs_writeback_inode(bfs, inode);
  653 }
  654 
  655 STATIC boolean_t
  656 bfs_superblock_valid(const struct bfs_super_block *super)
  657 {
  658 
  659         return super->header.magic == BFS_MAGIC;
  660 }
  661 
  662 boolean_t
  663 bfs_dump(const struct bfs *bfs)
  664 {
  665         const struct bfs_super_block_header *h;
  666         const struct bfs_compaction *compaction;
  667         const struct bfs_inode *inode;
  668         struct bfs_dirent *file;
  669         int i, j, s, e;
  670         size_t bytes;
  671 
  672         if (!bfs_superblock_valid(bfs->super_block)) {
  673                 DPRINTF(bfs->debug, "invalid bfs super block.\n");
  674                 return FALSE;
  675         }
  676         h = &bfs->super_block->header;
  677         compaction = &bfs->super_block->compaction;
  678 
  679         DPRINTF(bfs->debug, "super block %zdbyte, inode %zdbyte, dirent %zdbyte\n",
  680             sizeof *bfs->super_block, sizeof *inode, sizeof *file);
  681 
  682         DPRINTF(bfs->debug, "magic=%x\n", h->magic);
  683         DPRINTF(bfs->debug, "data_start_byte=0x%x\n", h->data_start_byte);
  684         DPRINTF(bfs->debug, "data_end_byte=0x%x\n", h->data_end_byte);
  685         DPRINTF(bfs->debug, "from=%#x\n", compaction->from);
  686         DPRINTF(bfs->debug, "to=%#x\n", compaction->to);
  687         DPRINTF(bfs->debug, "from_backup=%#x\n", compaction->from_backup);
  688         DPRINTF(bfs->debug, "to_backup=%#x\n", compaction->to_backup);
  689         DPRINTF(bfs->debug, "fsname=%s\n", bfs->super_block->fsname);
  690         DPRINTF(bfs->debug, "volume=%s\n", bfs->super_block->volume);
  691 
  692         /* inode list */
  693         DPRINTF(bfs->debug, "[inode index list]\n");
  694         for (inode = bfs->inode, i = j = 0; i < bfs->max_inode; inode++, i++) {
  695                 if (inode->number != 0) {
  696                         const struct bfs_fileattr *attr = &inode->attr;
  697                         DPRINTF(bfs->debug, "%3d  %8d %8d %8d (%d) ",
  698                             inode->number,
  699                             inode->eof_offset_byte -
  700                             (inode->start_sector * DEV_BSIZE) + 1,/* file size*/
  701                             inode->start_sector,
  702                             inode->end_sector, i);
  703 
  704                         DPRINTF(bfs->debug, "%d %d %d %d %d %08x %08x %08x\n",
  705                             attr->type, attr->mode, attr->uid, attr->gid,
  706                             attr->nlink, attr->atime, attr->mtime, attr->ctime);
  707                         j++;
  708                 }
  709         }
  710         if (j != bfs->n_inode) {
  711                 DPRINTF(bfs->debug, "inconsistent cached data. (i-node)\n");
  712                 return FALSE;
  713         }
  714         DPRINTF(bfs->debug, "total %d i-node.\n", j);
  715 
  716         /* file list */
  717         DPRINTF(bfs->debug, "[dirent index list]\n");
  718         DPRINTF(bfs->debug, "%d file entries.\n", bfs->max_dirent);
  719         file = bfs->dirent;
  720         for (i = j = 0; i < bfs->max_dirent; i++, file++) {
  721                 if (file->inode != 0) {
  722                         if (bfs_file_lookup(bfs, file->name, &s, &e, &bytes))
  723                                 DPRINTF(bfs->debug, "%3d %14s %8d %8d %8zd\n",
  724                                     file->inode, file->name, s, e, bytes);
  725                         j++;
  726                 }
  727         }
  728         if (j != bfs->n_dirent) {
  729                 DPRINTF(bfs->debug, "inconsistent cached data. (dirent)\n");
  730                 return FALSE;
  731         }
  732         DPRINTF(bfs->debug, "%d files.\n", j);
  733 
  734         return TRUE;
  735 }

Cache object: 0fcf6df014d05606f834d3dc975bcb13


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.