Fork me on GitHub

root/fs/minix/v1_inode.c

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

DEFINITIONS

This source file includes following definitions.
  1. free_zone
  2. v1_minix_read_inode
  3. v1_minix_write_inode
  4. v1_minix_ialloc
  5. v1_minix_ifree
  6. v1_minix_bmap
  7. v1_minix_truncate

   1 /*
   2  * fiwix/fs/minix/v1_inode.c
   3  *
   4  * Copyright 2018, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/kernel.h>
   9 #include <fiwix/fs.h>
  10 #include <fiwix/filesystems.h>
  11 #include <fiwix/fs_minix.h>
  12 #include <fiwix/fs_pipe.h>
  13 #include <fiwix/statfs.h>
  14 #include <fiwix/sleep.h>
  15 #include <fiwix/stat.h>
  16 #include <fiwix/sched.h>
  17 #include <fiwix/buffer.h>
  18 #include <fiwix/process.h>
  19 #include <fiwix/errno.h>
  20 #include <fiwix/stdio.h>
  21 #include <fiwix/string.h>
  22 
  23 #define BLOCKS_PER_IND_BLOCK(sb)        (sb->s_blocksize / sizeof(__u16))
  24 #define MINIX_INODES_PER_BLOCK(sb)      (sb->s_blocksize / sizeof(struct minix_inode))
  25 
  26 #define MINIX_NDIR_BLOCKS               7
  27 #define MINIX_IND_BLOCK                 MINIX_NDIR_BLOCKS
  28 #define MINIX_DIND_BLOCK                (MINIX_NDIR_BLOCKS + 1)
  29 
  30 static void free_zone(struct inode *i, int block, int offset)
  31 {
  32         int n;
  33         struct buffer *buf;
  34         __u16 *zone;
  35 
  36         if(!(buf = bread(i->dev, block, i->sb->s_blocksize))) {
  37                 printk("WARNING: %s(): error reading block %d.\n", __FUNCTION__, block);
  38                 return;
  39         }
  40         zone = (__u16 *)buf->data;
  41         for(n = offset; n < BLOCKS_PER_IND_BLOCK(i->sb); n++) {
  42                 if(zone[n]) {
  43                         minix_bfree(i->sb, zone[n]);
  44                         zone[n] = 0;
  45                 }
  46         }
  47         bwrite(buf);
  48 }
  49 
  50 int v1_minix_read_inode(struct inode *i)
  51 {
  52         __ino_t block;
  53         short int offset;
  54         struct minix_inode *ii;
  55         struct buffer *buf;
  56         int errno;
  57 
  58         block = 1 + SUPERBLOCK + i->sb->u.minix.sb.s_imap_blocks + i->sb->u.minix.sb.s_zmap_blocks + (i->inode - 1) / MINIX_INODES_PER_BLOCK(i->sb);
  59 
  60         if(!(buf = bread(i->dev, block, i->sb->s_blocksize))) {
  61                 return -EIO;
  62         }
  63         offset = (i->inode - 1) % MINIX_INODES_PER_BLOCK(i->sb);
  64         ii = ((struct minix_inode *)buf->data) + offset;
  65 
  66         i->i_mode = ii->i_mode;
  67         i->i_uid = ii->i_uid;
  68         i->i_size = ii->i_size;
  69         i->i_atime = ii->i_time;
  70         i->i_ctime = ii->i_time;
  71         i->i_mtime = ii->i_time;
  72         i->i_gid = ii->i_gid;
  73         i->i_nlink = ii->i_nlinks;
  74         memcpy_b(i->u.minix.u.i1_zone, ii->i_zone, sizeof(ii->i_zone));
  75         i->count = 1;
  76 
  77         errno = 0;
  78         switch(i->i_mode & S_IFMT) {
  79                 case S_IFCHR:
  80                         i->fsop = &def_chr_fsop;
  81                         i->rdev = ii->i_zone[0];
  82                         break;
  83                 case S_IFBLK:
  84                         i->fsop = &def_blk_fsop;
  85                         i->rdev = ii->i_zone[0];
  86                         break;
  87                 case S_IFIFO:
  88                         i->fsop = &pipefs_fsop;
  89                         /* it's a union so we need to clear pipefs_i */
  90                         memset_b(&i->u.pipefs, NULL, sizeof(struct pipefs_inode));
  91                         break;
  92                 case S_IFDIR:
  93                         i->fsop = &minix_dir_fsop;
  94                         break;
  95                 case S_IFREG:
  96                         i->fsop = &minix_file_fsop;
  97                         break;
  98                 case S_IFLNK:
  99                         i->fsop = &minix_symlink_fsop;
 100                         break;
 101                 case S_IFSOCK:
 102                         i->fsop = NULL;
 103                         break;
 104                 default:
 105                         printk("WARNING: %s(): invalid inode (%d) mode %o.\n", __FUNCTION__, i->inode, i->i_mode);
 106                         errno = -ENOENT;
 107                         break;
 108         }
 109 
 110         brelse(buf);
 111         return errno;
 112 }
 113 
 114 int v1_minix_write_inode(struct inode *i)
 115 {
 116         __ino_t block;
 117         short int offset;
 118         struct minix_inode *ii;
 119         struct buffer *buf;
 120 
 121         block = 1 + SUPERBLOCK + i->sb->u.minix.sb.s_imap_blocks + i->sb->u.minix.sb.s_zmap_blocks + (i->inode - 1) / MINIX_INODES_PER_BLOCK(i->sb);
 122 
 123         if(!(buf = bread(i->dev, block, i->sb->s_blocksize))) {
 124                 return -EIO;
 125         }
 126         offset = (i->inode - 1) % MINIX_INODES_PER_BLOCK(i->sb);
 127         ii = ((struct minix_inode *)buf->data) + offset;
 128 
 129         ii->i_mode = i->i_mode;
 130         ii->i_uid = i->i_uid;
 131         ii->i_size = i->i_size;
 132         ii->i_time = i->i_mtime;
 133         ii->i_gid = i->i_gid;
 134         ii->i_nlinks = i->i_nlink;
 135         if(S_ISCHR(i->i_mode) || S_ISBLK(i->i_mode)) {
 136                 ii->i_zone[0] = i->rdev;
 137         } else {
 138                 memcpy_b(ii->i_zone, i->u.minix.u.i1_zone, sizeof(i->u.minix.u.i1_zone));
 139         }
 140         i->dirty = 0;
 141         bwrite(buf);
 142         return 0;
 143 }
 144 
 145 int v1_minix_ialloc(struct inode *i, int mode)
 146 {
 147         __blk_t offset;
 148         int inode, errno;
 149         struct superblock *sb;
 150 
 151         sb = i->sb;
 152         superblock_lock(sb);
 153 
 154         offset = 1 + SUPERBLOCK;
 155 
 156         if(!(inode = minix_find_first_zero(sb, offset, sb->u.minix.sb.s_ninodes, offset + sb->u.minix.sb.s_imap_blocks))) {
 157                 superblock_unlock(sb);
 158                 return -ENOSPC;
 159         }
 160 
 161         errno = minix_change_bit(SET_BIT, sb, offset, inode);
 162 
 163         if(errno) {
 164                 if(errno < 0) {
 165                         printk("WARNING: %s(): unable to set inode %d.\n", __FUNCTION__, inode);
 166                         superblock_unlock(sb);
 167                         return errno;
 168                 } else {
 169                         printk("WARNING: %s(): inode %d is already marked as used!\n", __FUNCTION__, inode);
 170                 }
 171         }
 172 
 173         i->inode = inode;
 174         i->i_atime = CURRENT_TIME;
 175         i->i_mtime = CURRENT_TIME;
 176         i->i_ctime = CURRENT_TIME;
 177         superblock_unlock(sb);
 178         return 0;
 179 }
 180 
 181 void v1_minix_ifree(struct inode *i)
 182 {
 183         int errno;
 184         struct superblock *sb;
 185 
 186         minix_truncate(i, 0);
 187 
 188         sb = i->sb;
 189         superblock_lock(sb);
 190 
 191         errno = minix_change_bit(CLEAR_BIT, i->sb, 1 + SUPERBLOCK, i->inode);
 192 
 193         if(errno) {
 194                 if(errno < 0) {
 195                         printk("WARNING: %s(): unable to clear inode %d.\n", __FUNCTION__, i->inode);
 196                 } else {
 197                         printk("WARNING: %s(): inode %d is already marked as free!\n", __FUNCTION__, i->inode);
 198                 }
 199         }
 200 
 201         i->i_size = 0;
 202         i->i_mtime = CURRENT_TIME;
 203         i->i_ctime = CURRENT_TIME;
 204         i->dirty = 1;
 205         superblock_unlock(sb);
 206 }
 207 
 208 int v1_minix_bmap(struct inode *i, __off_t offset, int mode)
 209 {
 210         unsigned char level;
 211         __u16 *indblock, *dindblock;
 212         __blk_t block, iblock, dblock, newblock;
 213         int blksize;
 214         struct buffer *buf, *buf2, *buf3;
 215 
 216         blksize = i->sb->s_blocksize;
 217         block = offset / blksize;
 218         level = 0;
 219 
 220         if(block < MINIX_NDIR_BLOCKS) {
 221                 level = MINIX_NDIR_BLOCKS - 1;
 222         } else {
 223                 if(block < (BLOCKS_PER_IND_BLOCK(i->sb) + MINIX_NDIR_BLOCKS)) {
 224                         level = MINIX_IND_BLOCK;
 225                 } else {
 226                         level = MINIX_DIND_BLOCK;
 227                 }
 228                 block -= MINIX_NDIR_BLOCKS;
 229         }
 230 
 231         if(level < MINIX_NDIR_BLOCKS) {
 232                 if(!i->u.minix.u.i1_zone[block] && mode == FOR_WRITING) {
 233                         if((newblock = minix_balloc(i->sb)) < 0) {
 234                                 return -ENOSPC;
 235                         }
 236                         /* initialize the new block */
 237                         if(!(buf = bread(i->dev, newblock, blksize))) {
 238                                 minix_bfree(i->sb, newblock);
 239                                 return -EIO;
 240                         }
 241                         memset_b(buf->data, 0, blksize);
 242                         bwrite(buf);
 243                         i->u.minix.u.i1_zone[block] = newblock;
 244                 }
 245                 return i->u.minix.u.i1_zone[block];
 246         }
 247 
 248         if(!i->u.minix.u.i1_zone[level]) {
 249                 if(mode == FOR_WRITING) {
 250                         if((newblock = minix_balloc(i->sb)) < 0) {
 251                                 return -ENOSPC;
 252                         }
 253                         /* initialize the new block */
 254                         if(!(buf = bread(i->dev, newblock, blksize))) {
 255                                 minix_bfree(i->sb, newblock);
 256                                 return -EIO;
 257                         }
 258                         memset_b(buf->data, 0, blksize);
 259                         bwrite(buf);
 260                         i->u.minix.u.i1_zone[level] = newblock;
 261                 } else {
 262                         return 0;
 263                 }
 264         }
 265         if(!(buf = bread(i->dev, i->u.minix.u.i1_zone[level], blksize))) {
 266                 return -EIO;
 267         }
 268         indblock = (__u16 *)buf->data;
 269         dblock = block - BLOCKS_PER_IND_BLOCK(i->sb);
 270 
 271         if(level == MINIX_DIND_BLOCK) {
 272                 block = dblock / BLOCKS_PER_IND_BLOCK(i->sb);
 273         }
 274 
 275         if(!indblock[block]) {
 276                 if(mode == FOR_WRITING) {
 277                         if((newblock = minix_balloc(i->sb)) < 0) {
 278                                 brelse(buf);
 279                                 return -ENOSPC;
 280                         }
 281                         /* initialize the new block */
 282                         if(!(buf2 = bread(i->dev, newblock, blksize))) {
 283                                 minix_bfree(i->sb, newblock);
 284                                 brelse(buf);
 285                                 return -EIO;
 286                         }
 287                         memset_b(buf2->data, 0, blksize);
 288                         bwrite(buf2);
 289                         indblock[block] = newblock;
 290                         if(level == MINIX_IND_BLOCK) {
 291                                 bwrite(buf);
 292                                 return newblock;
 293                         }
 294                         buf->flags |= (BUFFER_DIRTY | BUFFER_VALID);
 295                 } else {
 296                         brelse(buf);
 297                         return 0;
 298                 }
 299         }
 300         if(level == MINIX_IND_BLOCK) {
 301                 newblock = indblock[block];
 302                 brelse(buf);
 303                 return newblock;
 304         }
 305 
 306         iblock = block;
 307         if(!(buf2 = bread(i->dev, indblock[iblock], blksize))) {
 308                 printk("%s(): returning -EIO\n", __FUNCTION__);
 309                 brelse(buf);
 310                 return -EIO;
 311         }
 312         dindblock = (__u16 *)buf2->data;
 313         block = dindblock[dblock - (iblock * BLOCKS_PER_IND_BLOCK(i->sb))];
 314         if(!block && mode == FOR_WRITING) {
 315                 if((newblock = minix_balloc(i->sb)) < 0) {
 316                         brelse(buf);
 317                         brelse(buf2);
 318                         return -ENOSPC;
 319                 }
 320                 /* initialize the new block */
 321                 if(!(buf3 = bread(i->dev, newblock, blksize))) {
 322                         minix_bfree(i->sb, newblock);
 323                         brelse(buf);
 324                         brelse(buf2);
 325                         return -EIO;
 326                 }
 327                 memset_b(buf3->data, 0, blksize);
 328                 bwrite(buf3);
 329                 dindblock[dblock - (iblock * BLOCKS_PER_IND_BLOCK(i->sb))] = newblock;
 330                 buf2->flags |= (BUFFER_DIRTY | BUFFER_VALID);
 331                 block = newblock;
 332         }
 333         brelse(buf);
 334         brelse(buf2);
 335         return block;
 336 }
 337 
 338 int v1_minix_truncate(struct inode *i, __off_t length)
 339 {
 340         int n;
 341         __blk_t block, dblock;
 342         __u16 *zone;
 343         struct buffer *buf;
 344 
 345         block = length / i->sb->s_blocksize;
 346 
 347         if(!S_ISDIR(i->i_mode) && !S_ISREG(i->i_mode) && !S_ISLNK(i->i_mode)) {
 348                 return -EINVAL;
 349         }
 350 
 351         if(block < MINIX_NDIR_BLOCKS) {
 352                 for(n = block; n < MINIX_NDIR_BLOCKS; n++) {
 353                         if(i->u.minix.u.i1_zone[n]) {
 354                                 minix_bfree(i->sb, i->u.minix.u.i1_zone[n]);
 355                                 i->u.minix.u.i1_zone[n] = 0;
 356                         }
 357                 }
 358                 block = 0;
 359         }
 360 
 361         if(!block || block < (BLOCKS_PER_IND_BLOCK(i->sb) + MINIX_NDIR_BLOCKS)) {
 362                 if(block) {
 363                         block -= MINIX_NDIR_BLOCKS;
 364                 }
 365                 if(i->u.minix.u.i1_zone[MINIX_IND_BLOCK]) {
 366                         free_zone(i, i->u.minix.u.i1_zone[MINIX_IND_BLOCK], block);
 367                         if(!block) {
 368                                 minix_bfree(i->sb, i->u.minix.u.i1_zone[MINIX_IND_BLOCK]);
 369                                 i->u.minix.u.i1_zone[MINIX_IND_BLOCK] = 0;
 370                         }
 371                 }
 372                 block = 0;
 373         }
 374 
 375         if(block) {
 376                 block -= MINIX_NDIR_BLOCKS;
 377                 block -= BLOCKS_PER_IND_BLOCK(i->sb);
 378         }
 379         if(i->u.minix.u.i1_zone[MINIX_DIND_BLOCK]) {
 380                 if(!(buf = bread(i->dev, i->u.minix.u.i1_zone[MINIX_DIND_BLOCK], i->sb->s_blocksize))) {
 381                         printk("%s(): error reading block %d.\n", __FUNCTION__, i->u.minix.u.i1_zone[MINIX_DIND_BLOCK]);
 382                 }
 383                 zone = (__u16 *)buf->data;
 384                 dblock = block % BLOCKS_PER_IND_BLOCK(i->sb);
 385                 for(n = block / BLOCKS_PER_IND_BLOCK(i->sb); n < BLOCKS_PER_IND_BLOCK(i->sb); n++) {
 386                         if(zone[n]) {
 387                                 free_zone(i, zone[n], dblock);
 388                                 if(!dblock) {
 389                                         minix_bfree(i->sb, zone[n]);
 390                                 }
 391                         }
 392                         dblock = 0;
 393                 }
 394                 bwrite(buf);
 395                 if(!block) {
 396                         minix_bfree(i->sb, i->u.minix.u.i1_zone[MINIX_DIND_BLOCK]);
 397                         i->u.minix.u.i1_zone[MINIX_DIND_BLOCK] = 0;
 398                 }
 399         }
 400 
 401         i->i_mtime = CURRENT_TIME;
 402         i->i_ctime = CURRENT_TIME;
 403         i->i_size = length;
 404         i->dirty = 1;
 405 
 406         return 0;
 407 }

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