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/efs/super.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 /*
    2  * super.c
    3  *
    4  * Copyright (c) 1999 Al Smith
    5  *
    6  * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
    7  */
    8 
    9 #include <linux/init.h>
   10 #include <linux/module.h>
   11 #include <linux/locks.h>
   12 #include <linux/efs_fs.h>
   13 #include <linux/efs_vh.h>
   14 #include <linux/efs_fs_sb.h>
   15 
   16 static DECLARE_FSTYPE_DEV(efs_fs_type, "efs", efs_read_super);
   17 
   18 static struct super_operations efs_superblock_operations = {
   19         read_inode:     efs_read_inode,
   20         statfs:         efs_statfs,
   21 };
   22 
   23 static int __init init_efs_fs(void) {
   24         printk("EFS: "EFS_VERSION" - http://aeschi.ch.eu.org/efs/\n");
   25         return register_filesystem(&efs_fs_type);
   26 }
   27 
   28 static void __exit exit_efs_fs(void) {
   29         unregister_filesystem(&efs_fs_type);
   30 }
   31 
   32 EXPORT_NO_SYMBOLS;
   33 
   34 module_init(init_efs_fs)
   35 module_exit(exit_efs_fs)
   36 
   37 static efs_block_t efs_validate_vh(struct volume_header *vh) {
   38         int             i;
   39         unsigned int    cs, csum, *ui;
   40         efs_block_t     sblock = 0; /* shuts up gcc */
   41         struct pt_types *pt_entry;
   42         int             pt_type, slice = -1;
   43 
   44         if (be32_to_cpu(vh->vh_magic) != VHMAGIC) {
   45                 /*
   46                  * assume that we're dealing with a partition and allow
   47                  * read_super() to try and detect a valid superblock
   48                  * on the next block.
   49                  */
   50                 return 0;
   51         }
   52 
   53         ui = ((unsigned int *) (vh + 1)) - 1;
   54         for(csum = 0; ui >= ((unsigned int *) vh);) {
   55                 cs = *ui--;
   56                 csum += be32_to_cpu(cs);
   57         }
   58         if (csum) {
   59                 printk(KERN_INFO "EFS: SGI disklabel: checksum bad, label corrupted\n");
   60                 return 0;
   61         }
   62 
   63 #ifdef DEBUG
   64         printk(KERN_DEBUG "EFS: bf: \"%16s\"\n", vh->vh_bootfile);
   65 
   66         for(i = 0; i < NVDIR; i++) {
   67                 int     j;
   68                 char    name[VDNAMESIZE+1];
   69 
   70                 for(j = 0; j < VDNAMESIZE; j++) {
   71                         name[j] = vh->vh_vd[i].vd_name[j];
   72                 }
   73                 name[j] = (char) 0;
   74 
   75                 if (name[0]) {
   76                         printk(KERN_DEBUG "EFS: vh: %8s block: 0x%08x size: 0x%08x\n",
   77                                 name,
   78                                 (int) be32_to_cpu(vh->vh_vd[i].vd_lbn),
   79                                 (int) be32_to_cpu(vh->vh_vd[i].vd_nbytes));
   80                 }
   81         }
   82 #endif
   83 
   84         for(i = 0; i < NPARTAB; i++) {
   85                 pt_type = (int) be32_to_cpu(vh->vh_pt[i].pt_type);
   86                 for(pt_entry = sgi_pt_types; pt_entry->pt_name; pt_entry++) {
   87                         if (pt_type == pt_entry->pt_type) break;
   88                 }
   89 #ifdef DEBUG
   90                 if (be32_to_cpu(vh->vh_pt[i].pt_nblks)) {
   91                         printk(KERN_DEBUG "EFS: pt %2d: start: %08d size: %08d type: 0x%02x (%s)\n",
   92                                 i,
   93                                 (int) be32_to_cpu(vh->vh_pt[i].pt_firstlbn),
   94                                 (int) be32_to_cpu(vh->vh_pt[i].pt_nblks),
   95                                 pt_type,
   96                                 (pt_entry->pt_name) ? pt_entry->pt_name : "unknown");
   97                 }
   98 #endif
   99                 if (IS_EFS(pt_type)) {
  100                         sblock = be32_to_cpu(vh->vh_pt[i].pt_firstlbn);
  101                         slice = i;
  102                 }
  103         }
  104 
  105         if (slice == -1) {
  106                 printk(KERN_NOTICE "EFS: partition table contained no EFS partitions\n");
  107 #ifdef DEBUG
  108         } else {
  109                 printk(KERN_INFO "EFS: using slice %d (type %s, offset 0x%x)\n",
  110                         slice,
  111                         (pt_entry->pt_name) ? pt_entry->pt_name : "unknown",
  112                         sblock);
  113 #endif
  114         }
  115         return(sblock);
  116 }
  117 
  118 static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) {
  119 
  120         if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic))) return -1;
  121 
  122         sb->fs_magic     = be32_to_cpu(super->fs_magic);
  123         sb->total_blocks = be32_to_cpu(super->fs_size);
  124         sb->first_block  = be32_to_cpu(super->fs_firstcg);
  125         sb->group_size   = be32_to_cpu(super->fs_cgfsize);
  126         sb->data_free    = be32_to_cpu(super->fs_tfree);
  127         sb->inode_free   = be32_to_cpu(super->fs_tinode);
  128         sb->inode_blocks = be16_to_cpu(super->fs_cgisize);
  129         sb->total_groups = be16_to_cpu(super->fs_ncg);
  130     
  131         return 0;    
  132 }
  133 
  134 struct super_block *efs_read_super(struct super_block *s, void *d, int silent) {
  135         kdev_t dev = s->s_dev;
  136         struct efs_sb_info *sb;
  137         struct buffer_head *bh;
  138 
  139         sb = SUPER_INFO(s);
  140  
  141         s->s_magic              = EFS_SUPER_MAGIC;
  142         s->s_blocksize          = EFS_BLOCKSIZE;
  143         s->s_blocksize_bits     = EFS_BLOCKSIZE_BITS;
  144         
  145         if( set_blocksize(dev, EFS_BLOCKSIZE) < 0)
  146         {
  147                 printk(KERN_ERR "EFS: device does not support %d byte blocks\n",
  148                         EFS_BLOCKSIZE);
  149                 goto out_no_fs_ul;
  150         }
  151   
  152         /* read the vh (volume header) block */
  153         bh = sb_bread(s, 0);
  154 
  155         if (!bh) {
  156                 printk(KERN_ERR "EFS: cannot read volume header\n");
  157                 goto out_no_fs_ul;
  158         }
  159 
  160         /*
  161          * if this returns zero then we didn't find any partition table.
  162          * this isn't (yet) an error - just assume for the moment that
  163          * the device is valid and go on to search for a superblock.
  164          */
  165         sb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data);
  166         brelse(bh);
  167 
  168         if (sb->fs_start == -1) {
  169                 goto out_no_fs_ul;
  170         }
  171 
  172         bh = sb_bread(s, sb->fs_start + EFS_SUPER);
  173         if (!bh) {
  174                 printk(KERN_ERR "EFS: cannot read superblock\n");
  175                 goto out_no_fs_ul;
  176         }
  177                 
  178         if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) {
  179 #ifdef DEBUG
  180                 printk(KERN_WARNING "EFS: invalid superblock at block %u\n", sb->fs_start + EFS_SUPER);
  181 #endif
  182                 brelse(bh);
  183                 goto out_no_fs_ul;
  184         }
  185         brelse(bh);
  186 
  187         if (!(s->s_flags & MS_RDONLY)) {
  188 #ifdef DEBUG
  189                 printk(KERN_INFO "EFS: forcing read-only mode\n");
  190 #endif
  191                 s->s_flags |= MS_RDONLY;
  192         }
  193         s->s_op   = &efs_superblock_operations;
  194         s->s_root = d_alloc_root(iget(s, EFS_ROOTINODE));
  195  
  196         if (!(s->s_root)) {
  197                 printk(KERN_ERR "EFS: get root inode failed\n");
  198                 goto out_no_fs;
  199         }
  200 
  201         return(s);
  202 
  203 out_no_fs_ul:
  204 out_no_fs:
  205         return(NULL);
  206 }
  207 
  208 int efs_statfs(struct super_block *s, struct statfs *buf) {
  209         struct efs_sb_info *sb = SUPER_INFO(s);
  210 
  211         buf->f_type    = EFS_SUPER_MAGIC;       /* efs magic number */
  212         buf->f_bsize   = EFS_BLOCKSIZE;         /* blocksize */
  213         buf->f_blocks  = sb->total_groups *     /* total data blocks */
  214                         (sb->group_size - sb->inode_blocks);
  215         buf->f_bfree   = sb->data_free;         /* free data blocks */
  216         buf->f_bavail  = sb->data_free;         /* free blocks for non-root */
  217         buf->f_files   = sb->total_groups *     /* total inodes */
  218                         sb->inode_blocks *
  219                         (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
  220         buf->f_ffree   = sb->inode_free;        /* free inodes */
  221         buf->f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */
  222         buf->f_fsid.val[1] =  sb->fs_magic        & 0xffff; /* fs ID */
  223         buf->f_namelen = EFS_MAXNAMELEN;        /* max filename length */
  224 
  225         return 0;
  226 }
  227 

Cache object: 734ea679b5f3684771097bbdc680459f


[ 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.