Fork me on GitHub

root/fs/ext2/super.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_superblock
  2. ext2_statfs
  3. ext2_read_superblock
  4. ext2_remount_fs
  5. ext2_write_superblock
  6. ext2_release_superblock
  7. ext2_init

   1 /*
   2  * fiwix/fs/ext2/super.c
   3  *
   4  * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/kernel.h>
   9 #include <fiwix/types.h>
  10 #include <fiwix/errno.h>
  11 #include <fiwix/fs.h>
  12 #include <fiwix/filesystems.h>
  13 #include <fiwix/fs_ext2.h>
  14 #include <fiwix/buffer.h>
  15 #include <fiwix/sched.h>
  16 #include <fiwix/stdio.h>
  17 #include <fiwix/string.h>
  18 
  19 struct fs_operations ext2_fsop = {
  20         FSOP_REQUIRES_DEV,
  21         NULL,
  22 
  23         NULL,                   /* open */
  24         NULL,                   /* close */
  25         NULL,                   /* read */
  26         NULL,                   /* write */
  27         NULL,                   /* ioctl */
  28         NULL,                   /* lseek */
  29         NULL,                   /* readdir */
  30         NULL,                   /* mmap */
  31         NULL,                   /* select */
  32 
  33         NULL,                   /* readlink */
  34         NULL,                   /* followlink */
  35         NULL,                   /* bmap */
  36         NULL,                   /* lookup */
  37         NULL,                   /* rmdir */
  38         NULL,                   /* link */
  39         NULL,                   /* unlink */
  40         NULL,                   /* symlink */
  41         NULL,                   /* mkdir */
  42         NULL,                   /* mknod */
  43         NULL,                   /* truncate */
  44         NULL,                   /* create */
  45         NULL,                   /* rename */
  46 
  47         NULL,                   /* read_block */
  48         NULL,                   /* write_block */
  49 
  50         ext2_read_inode,
  51         ext2_write_inode,
  52         ext2_ialloc,
  53         ext2_ifree,
  54         ext2_statfs,
  55         ext2_read_superblock,
  56         ext2_remount_fs,
  57         ext2_write_superblock,
  58         ext2_release_superblock
  59 };
  60 
  61 static void check_superblock(struct ext2_super_block *sb)
  62 {
  63         if(!(sb->s_state & EXT2_VALID_FS)) {
  64                 printk("WARNING: filesystem unchecked, fsck recommended.\n");
  65         } else if((sb->s_state & EXT2_ERROR_FS)) {
  66                 printk("WARNING: filesystem contains errors, fsck recommended.\n");
  67         } else if(sb->s_max_mnt_count >= 0 && sb->s_mnt_count >= (unsigned short int)sb->s_max_mnt_count) {
  68                 printk("WARNING: maximal mount count reached, fsck recommended.\n");
  69         } else if(sb->s_checkinterval && (sb->s_lastcheck + sb->s_checkinterval <= CURRENT_TIME)) {
  70                 printk("WARNING: checktime reached, fsck recommended.\n");
  71         }
  72 }
  73 
  74 void ext2_statfs(struct superblock *sb, struct statfs *statfsbuf)
  75 {
  76         statfsbuf->f_type = EXT2_SUPER_MAGIC;
  77         statfsbuf->f_bsize = sb->s_blocksize;
  78         statfsbuf->f_blocks = sb->u.ext2.sb.s_blocks_count;
  79         statfsbuf->f_bfree = sb->u.ext2.sb.s_free_blocks_count;
  80         if(statfsbuf->f_bfree >= sb->u.ext2.sb.s_r_blocks_count) {
  81                 statfsbuf->f_bavail = statfsbuf->f_bfree - sb->u.ext2.sb.s_r_blocks_count;
  82         } else {
  83                 statfsbuf->f_bavail = 0;
  84         }
  85         statfsbuf->f_files = sb->u.ext2.sb.s_inodes_count;
  86         statfsbuf->f_ffree = sb->u.ext2.sb.s_free_inodes_count;
  87         /* statfsbuf->f_fsid = ? */
  88         statfsbuf->f_namelen = EXT2_NAME_LEN;
  89 }
  90 
  91 int ext2_read_superblock(__dev_t dev, struct superblock *sb)
  92 {
  93         struct buffer *buf;
  94         struct ext2_super_block *ext2sb;
  95 
  96         superblock_lock(sb);
  97         if(!(buf = bread(dev, SUPERBLOCK, BLKSIZE_1K))) {
  98                 printk("WARNING: %s(): I/O error on device %d,%d.\n", __FUNCTION__, MAJOR(dev), MINOR(dev));
  99                 superblock_unlock(sb);
 100                 return -EIO;
 101         }
 102 
 103         ext2sb = (struct ext2_super_block *)buf->data;
 104         if(ext2sb->s_magic != EXT2_SUPER_MAGIC) {
 105                 printk("WARNING: %s(): invalid filesystem type or bad superblock on device %d,%d.\n", __FUNCTION__, MAJOR(dev), MINOR(dev));
 106                 superblock_unlock(sb);
 107                 brelse(buf);
 108                 return -EINVAL;
 109         }
 110 
 111         if(ext2sb->s_minor_rev_level || ext2sb->s_rev_level) {
 112                 printk("WARNING: %s(): unsupported ext2 filesystem revision.\n", __FUNCTION__);
 113                 printk("Only revision 0 (original without features) is supported.\n");
 114                 superblock_unlock(sb);
 115                 brelse(buf);
 116                 return -EINVAL;
 117         }
 118 
 119         sb->dev = dev;
 120         sb->fsop = &ext2_fsop;
 121         sb->s_blocksize = EXT2_MIN_BLOCK_SIZE << ext2sb->s_log_block_size;
 122         memcpy_b(&sb->u.ext2.sb, ext2sb, sizeof(struct ext2_super_block));
 123         EXT2_DESC_PER_BLOCK(sb) = sb->s_blocksize / sizeof(struct ext2_group_desc);
 124         sb->u.ext2.block_groups = 1 + (ext2sb->s_blocks_count - 1) / ext2sb->s_blocks_per_group;
 125 
 126         if(!(sb->root = iget(sb, EXT2_ROOT_INO))) {
 127                 printk("WARNING: %s(): unable to get root inode.\n", __FUNCTION__);
 128                 superblock_unlock(sb);
 129                 brelse(buf);
 130                 return -EINVAL;
 131         }
 132 
 133         check_superblock(ext2sb);
 134         if(!(sb->flags & MS_RDONLY)) {
 135                 sb->u.ext2.sb.s_state &= ~EXT2_VALID_FS;
 136                 sb->u.ext2.sb.s_mnt_count++;
 137                 sb->u.ext2.sb.s_mtime = CURRENT_TIME;
 138                 memcpy_b(buf->data, &sb->u.ext2.sb, sizeof(struct ext2_super_block));
 139                 bwrite(buf);
 140         } else {
 141                 brelse(buf);
 142         }
 143         superblock_unlock(sb);
 144         return 0;
 145 }
 146 
 147 int ext2_remount_fs(struct superblock *sb, int flags)
 148 {
 149         struct buffer *buf;
 150         struct ext2_super_block *ext2sb;
 151 
 152         if((flags & MS_RDONLY) == (sb->flags & MS_RDONLY)) {
 153                 return 0;
 154         }
 155 
 156         superblock_lock(sb);
 157         if(!(buf = bread(sb->dev, SUPERBLOCK, BLKSIZE_1K))) {
 158                 superblock_unlock(sb);
 159                 return -EIO;
 160         }
 161         ext2sb = (struct ext2_super_block *)buf->data;
 162 
 163         if(flags & MS_RDONLY) {
 164                 /* switching from RW to RO */
 165                 sb->u.ext2.sb.s_state |= EXT2_VALID_FS;
 166                 ext2sb->s_state |= EXT2_VALID_FS;
 167         } else {
 168                 /* switching from RO to RW */
 169                 check_superblock(ext2sb);
 170                 memcpy_b(&sb->u.ext2.sb, ext2sb, sizeof(struct ext2_super_block));
 171                 sb->u.ext2.sb.s_state &= ~EXT2_VALID_FS;
 172                 sb->u.ext2.sb.s_mnt_count++;
 173                 sb->u.ext2.sb.s_mtime = CURRENT_TIME;
 174                 ext2sb->s_state &= ~EXT2_VALID_FS;
 175         }
 176 
 177         sb->dirty = 1;
 178         superblock_unlock(sb);
 179         bwrite(buf);
 180         return 0;
 181 }
 182 
 183 int ext2_write_superblock(struct superblock *sb)
 184 {
 185         struct buffer *buf;
 186 
 187         superblock_lock(sb);
 188         if(!(buf = bread(sb->dev, SUPERBLOCK, BLKSIZE_1K))) {
 189                 superblock_unlock(sb);
 190                 return -EIO;
 191         }
 192 
 193         memcpy_b(buf->data, &sb->u.ext2.sb, sizeof(struct ext2_super_block));
 194         sb->dirty = 0;
 195         superblock_unlock(sb);
 196         bwrite(buf);
 197         return 0;
 198 }
 199 
 200 void ext2_release_superblock(struct superblock *sb)
 201 {
 202         if(sb->flags & MS_RDONLY) {
 203                 return;
 204         }
 205 
 206         superblock_lock(sb);
 207 
 208         sb->u.ext2.sb.s_state |= EXT2_VALID_FS;
 209         sb->dirty = 1;
 210 
 211         superblock_unlock(sb);
 212 }
 213 
 214 int ext2_init(void)
 215 {
 216         return register_filesystem("ext2", &ext2_fsop);
 217 }

/* [previous][next][first][last][top][bottom][index][help] */