Fork me on GitHub

root/fs/minix/v2_inode.c

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

DEFINITIONS

This source file includes following definitions.
  1. free_zone
  2. v2_minix_read_inode
  3. v2_minix_write_inode
  4. v2_minix_ialloc
  5. v2_minix_ifree
  6. v2_minix_bmap
  7. v2_minix_truncate

   1 /*
   2  * fiwix/fs/minix/v2_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(__u32))
  24 #define MINIX2_INODES_PER_BLOCK(sb)     (sb->s_blocksize / sizeof(struct minix2_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 #define MINIX_TIND_BLOCK                (MINIX_NDIR_BLOCKS + 2)
  30 
  31 static void free_zone(struct inode *i, int block, int offset)
  32 {
  33         int n;
  34         struct buffer *buf;
  35         __u32 *zone;
  36 
  37         if(!(buf = bread(i->dev, block, i->sb->s_blocksize))) {
  38                 printk("WARNING: %s(): error reading block %d.\n", __FUNCTION__, block);
  39                 return;
  40         }
  41         zone = (__u32 *)buf->data;
  42         for(n = offset; n < BLOCKS_PER_IND_BLOCK(i->sb); n++) {
  43                 if(zone[n]) {
  44                         minix_bfree(i->sb, zone[n]);
  45                         zone[n] = 0;
  46                 }
  47         }
  48         bwrite(buf);
  49 }
  50 
  51 int v2_minix_read_inode(struct inode *i)
  52 {
  53         __ino_t block;
  54         short int offset;
  55         struct minix2_inode *ii;
  56         struct buffer *buf;
  57         int errno;
  58 
  59         block = 1 + SUPERBLOCK + i->sb->u.minix.sb.s_imap_blocks + i->sb->u.minix.sb.s_zmap_blocks + (i->inode - 1) / MINIX2_INODES_PER_BLOCK(i->sb);
  60 
  61         if(!(buf = bread(i->dev, block, i->sb->s_blocksize))) {
  62                 return -EIO;
  63         }
  64         offset = (i->inode - 1) % MINIX2_INODES_PER_BLOCK(i->sb);
  65         ii = ((struct minix2_inode *)buf->data) + offset;
  66 
  67         i->i_mode = ii->i_mode;
  68         i->i_nlink = ii->i_nlink;
  69         i->i_uid = ii->i_uid;
  70         i->i_gid = ii->i_gid;
  71         i->i_size = ii->i_size;
  72         i->i_atime = ii->i_atime;
  73         i->i_mtime = ii->i_mtime;
  74         i->i_ctime = ii->i_ctime;
  75         memcpy_b(i->u.minix.u.i2_zone, ii->i_zone, sizeof(ii->i_zone));
  76         i->count = 1;
  77 
  78         errno = 0;
  79         switch(i->i_mode & S_IFMT) {
  80                 case S_IFCHR:
  81                         i->fsop = &def_chr_fsop;
  82                         i->rdev = ii->i_zone[0];
  83                         break;
  84                 case S_IFBLK:
  85                         i->fsop = &def_blk_fsop;
  86                         i->rdev = ii->i_zone[0];
  87                         break;
  88                 case S_IFIFO:
  89                         i->fsop = &pipefs_fsop;
  90                         /* it's a union so we need to clear pipefs_i */
  91                         memset_b(&i->u.pipefs, NULL, sizeof(struct pipefs_inode));
  92                         break;
  93                 case S_IFDIR:
  94                         i->fsop = &minix_dir_fsop;
  95                         break;
  96                 case S_IFREG:
  97                         i->fsop = &minix_file_fsop;
  98                         break;
  99                 case S_IFLNK:
 100                         i->fsop = &minix_symlink_fsop;
 101                         break;
 102                 case S_IFSOCK:
 103                         i->fsop = NULL;
 104                         break;
 105                 default:
 106                         printk("WARNING: %s(): invalid inode (%d) mode %o.\n", __FUNCTION__, i->inode, i->i_mode);
 107                         errno = -ENOENT;
 108                         break;
 109         }
 110 
 111         brelse(buf);
 112         return errno;
 113 }
 114 
 115 int v2_minix_write_inode(struct inode *i)
 116 {
 117         __ino_t block;
 118         short int offset;
 119         struct minix2_inode *ii;
 120         struct buffer *buf;
 121 
 122         block = 1 + SUPERBLOCK + i->sb->u.minix.sb.s_imap_blocks + i->sb->u.minix.sb.s_zmap_blocks + (i->inode - 1) / MINIX2_INODES_PER_BLOCK(i->sb);
 123 
 124         if(!(buf = bread(i->dev, block, i->sb->s_blocksize))) {
 125                 return -EIO;
 126         }
 127         offset = (i->inode - 1) % MINIX2_INODES_PER_BLOCK(i->sb);
 128         ii = ((struct minix2_inode *)buf->data) + offset;
 129 
 130         ii->i_mode = i->i_mode;
 131         ii->i_nlink = i->i_nlink;
 132         ii->i_uid = i->i_uid;
 133         ii->i_gid = i->i_gid;
 134         ii->i_size = i->i_size;
 135         ii->i_atime = i->i_atime;
 136         ii->i_mtime = i->i_mtime;
 137         ii->i_ctime = i->i_ctime;
 138         if(S_ISCHR(i->i_mode) || S_ISBLK(i->i_mode)) {
 139                 ii->i_zone[0] = i->rdev;
 140         } else {
 141                 memcpy_b(ii->i_zone, i->u.minix.u.i2_zone, sizeof(i->u.minix.u.i2_zone));
 142         }
 143         i->dirty = 0;
 144         bwrite(buf);
 145         return 0;
 146 }
 147 
 148 int v2_minix_ialloc(struct inode *i, int mode)
 149 {
 150         __blk_t offset;
 151         int inode, errno;
 152         struct superblock *sb;
 153 
 154         sb = i->sb;
 155         superblock_lock(sb);
 156 
 157         offset = 1 + SUPERBLOCK;
 158 
 159         if(!(inode = minix_find_first_zero(sb, offset, sb->u.minix.sb.s_ninodes, offset + sb->u.minix.sb.s_imap_blocks))) {
 160                 superblock_unlock(sb);
 161                 return -ENOSPC;
 162         }
 163 
 164         errno = minix_change_bit(SET_BIT, sb, offset, inode);
 165 
 166         if(errno) {
 167                 if(errno < 0) {
 168                         printk("WARNING: %s(): unable to set inode %d.\n", __FUNCTION__, inode);
 169                         superblock_unlock(sb);
 170                         return errno;
 171                 } else {
 172                         printk("WARNING: %s(): inode %d is already marked as used!\n", __FUNCTION__, inode);
 173                 }
 174         }
 175 
 176         i->inode = inode;
 177         i->i_atime = CURRENT_TIME;
 178         i->i_mtime = CURRENT_TIME;
 179         i->i_ctime = CURRENT_TIME;
 180         superblock_unlock(sb);
 181         return 0;
 182 }
 183 
 184 void v2_minix_ifree(struct inode *i)
 185 {
 186         int errno;
 187         struct superblock *sb;
 188 
 189         minix_truncate(i, 0);
 190 
 191         sb = i->sb;
 192         superblock_lock(sb);
 193 
 194         errno = minix_change_bit(CLEAR_BIT, i->sb, 1 + SUPERBLOCK, i->inode);
 195 
 196         if(errno) {
 197                 if(errno < 0) {
 198                         printk("WARNING: %s(): unable to clear inode %d.\n", __FUNCTION__, i->inode);
 199                 } else {
 200                         printk("WARNING: %s(): inode %d is already marked as free!\n", __FUNCTION__, i->inode);
 201                 }
 202         }
 203 
 204         i->i_size = 0;
 205         i->i_mtime = CURRENT_TIME;
 206         i->i_ctime = CURRENT_TIME;
 207         i->dirty = 1;
 208         superblock_unlock(sb);
 209 }
 210 
 211 int v2_minix_bmap(struct inode *i, __off_t offset, int mode)
 212 {
 213         unsigned char level;
 214         __u32 *indblock, *dindblock, *tindblock;
 215         __blk_t block, iblock, dblock, tblock, newblock;
 216         int blksize;
 217         struct buffer *buf, *buf2, *buf3, *buf4;
 218 
 219         blksize = i->sb->s_blocksize;
 220         block = offset / blksize;
 221         level = 0;
 222         buf3 = NULL;    /* makes GCC happy */
 223 
 224         if(block < MINIX_NDIR_BLOCKS) {
 225                 level = MINIX_NDIR_BLOCKS - 1;
 226         } else {
 227                 if(block < (BLOCKS_PER_IND_BLOCK(i->sb) + MINIX_NDIR_BLOCKS)) {
 228                         level = MINIX_IND_BLOCK;
 229                 } else if(block < ((BLOCKS_PER_IND_BLOCK(i->sb) * BLOCKS_PER_IND_BLOCK(i->sb)) + BLOCKS_PER_IND_BLOCK(i->sb) + MINIX_NDIR_BLOCKS)) {
 230                         level = MINIX_DIND_BLOCK;
 231                 } else {
 232                         level = MINIX_TIND_BLOCK;
 233                 }
 234                 block -= MINIX_NDIR_BLOCKS;
 235         }
 236 
 237         if(level < MINIX_NDIR_BLOCKS) {
 238                 if(!i->u.minix.u.i2_zone[block] && mode == FOR_WRITING) {
 239                         if((newblock = minix_balloc(i->sb)) < 0) {
 240                                 return -ENOSPC;
 241                         }
 242                         /* initialize the new block */
 243                         if(!(buf = bread(i->dev, newblock, blksize))) {
 244                                 minix_bfree(i->sb, newblock);
 245                                 return -EIO;
 246                         }
 247                         memset_b(buf->data, 0, blksize);
 248                         bwrite(buf);
 249                         i->u.minix.u.i2_zone[block] = newblock;
 250                 }
 251                 return i->u.minix.u.i2_zone[block];
 252         }
 253 
 254         if(!i->u.minix.u.i2_zone[level]) {
 255                 if(mode == FOR_WRITING) {
 256                         if((newblock = minix_balloc(i->sb)) < 0) {
 257                                 return -ENOSPC;
 258                         }
 259                         /* initialize the new block */
 260                         if(!(buf = bread(i->dev, newblock, blksize))) {
 261                                 minix_bfree(i->sb, newblock);
 262                                 return -EIO;
 263                         }
 264                         memset_b(buf->data, 0, blksize);
 265                         bwrite(buf);
 266                         i->u.minix.u.i2_zone[level] = newblock;
 267                 } else {
 268                         return 0;
 269                 }
 270         }
 271         if(!(buf = bread(i->dev, i->u.minix.u.i2_zone[level], blksize))) {
 272                 return -EIO;
 273         }
 274         indblock = (__u32 *)buf->data;
 275         dblock = block - BLOCKS_PER_IND_BLOCK(i->sb);
 276         tblock = block - (BLOCKS_PER_IND_BLOCK(i->sb) * BLOCKS_PER_IND_BLOCK(i->sb)) - BLOCKS_PER_IND_BLOCK(i->sb);
 277 
 278         if(level == MINIX_DIND_BLOCK) {
 279                 block = dblock / BLOCKS_PER_IND_BLOCK(i->sb);
 280         }
 281         if(level == MINIX_TIND_BLOCK) {
 282                 block = tblock / (BLOCKS_PER_IND_BLOCK(i->sb) * BLOCKS_PER_IND_BLOCK(i->sb));
 283         }
 284 
 285         if(!indblock[block]) {
 286                 if(mode == FOR_WRITING) {
 287                         if((newblock = minix_balloc(i->sb)) < 0) {
 288                                 brelse(buf);
 289                                 return -ENOSPC;
 290                         }
 291                         /* initialize the new block */
 292                         if(!(buf2 = bread(i->dev, newblock, blksize))) {
 293                                 minix_bfree(i->sb, newblock);
 294                                 brelse(buf);
 295                                 return -EIO;
 296                         }
 297                         memset_b(buf2->data, 0, blksize);
 298                         bwrite(buf2);
 299                         indblock[block] = newblock;
 300                         if(level == MINIX_IND_BLOCK) {
 301                                 bwrite(buf);
 302                                 return newblock;
 303                         }
 304                         buf->flags |= (BUFFER_DIRTY | BUFFER_VALID);
 305                 } else {
 306                         brelse(buf);
 307                         return 0;
 308                 }
 309         }
 310         if(level == MINIX_IND_BLOCK) {
 311                 newblock = indblock[block];
 312                 brelse(buf);
 313                 return newblock;
 314         }
 315 
 316         if(level == MINIX_TIND_BLOCK) {
 317                 if(!(buf3 = bread(i->dev, indblock[block], blksize))) {
 318                         printk("%s(): returning -EIO\n", __FUNCTION__);
 319                         brelse(buf);
 320                         return -EIO;
 321                 }
 322                 tindblock = (__u32 *)buf3->data;
 323                 block = tindblock[tblock / BLOCKS_PER_IND_BLOCK(i->sb)];
 324                 if(!block) {
 325                         if(mode == FOR_WRITING) {
 326                                 if((newblock = minix_balloc(i->sb)) < 0) {
 327                                         brelse(buf);
 328                                         brelse(buf3);
 329                                         return -ENOSPC;
 330                                 }
 331                                 /* initialize the new block */
 332                                 if(!(buf4 = bread(i->dev, newblock, blksize))) {
 333                                         minix_bfree(i->sb, newblock);
 334                                         brelse(buf);
 335                                         brelse(buf3);
 336                                         return -EIO;
 337                                 }
 338                                 memset_b(buf4->data, 0, blksize);
 339                                 bwrite(buf4);
 340                                 tindblock[tblock / BLOCKS_PER_IND_BLOCK(i->sb)] = newblock;
 341                                 buf3->flags |= (BUFFER_DIRTY | BUFFER_VALID);
 342                                 block = newblock;
 343                         } else {
 344                                 brelse(buf);
 345                                 brelse(buf3);
 346                                 return 0;
 347                         }
 348                 }
 349                 dblock = tblock;
 350                 iblock = tblock / BLOCKS_PER_IND_BLOCK(i->sb);
 351                 if(!(buf2 = bread(i->dev, block, blksize))) {
 352                         printk("%s(): returning -EIO\n", __FUNCTION__);
 353                         brelse(buf);
 354                         brelse(buf3);
 355                         return -EIO;
 356                 }
 357         } else {
 358                 iblock = block;
 359                 if(!(buf2 = bread(i->dev, indblock[iblock], blksize))) {
 360                         printk("%s(): returning -EIO\n", __FUNCTION__);
 361                         brelse(buf);
 362                         return -EIO;
 363                 }
 364         }
 365 
 366         dindblock = (__u32 *)buf2->data;
 367         block = dindblock[dblock - (iblock * BLOCKS_PER_IND_BLOCK(i->sb))];
 368         if(!block && mode == FOR_WRITING) {
 369                 if((newblock = minix_balloc(i->sb)) < 0) {
 370                         brelse(buf);
 371                         if(level == MINIX_TIND_BLOCK) {
 372                                 brelse(buf3);
 373                         }
 374                         brelse(buf2);
 375                         return -ENOSPC;
 376                 }
 377                 /* initialize the new block */
 378                 if(!(buf4 = bread(i->dev, newblock, blksize))) {
 379                         minix_bfree(i->sb, newblock);
 380                         brelse(buf);
 381                         if(level == MINIX_TIND_BLOCK) {
 382                                 brelse(buf3);
 383                         }
 384                         brelse(buf2);
 385                         return -EIO;
 386                 }
 387                 memset_b(buf4->data, 0, blksize);
 388                 bwrite(buf4);
 389                 dindblock[dblock - (iblock * BLOCKS_PER_IND_BLOCK(i->sb))] = newblock;
 390                 buf2->flags |= (BUFFER_DIRTY | BUFFER_VALID);
 391                 block = newblock;
 392         }
 393         brelse(buf);
 394         if(level == MINIX_TIND_BLOCK) {
 395                 brelse(buf3);
 396         }
 397         brelse(buf2);
 398         return block;
 399 }
 400 
 401 int v2_minix_truncate(struct inode *i, __off_t length)
 402 {
 403         int n;
 404         __blk_t block, dblock;
 405         __u32 *zone;
 406         struct buffer *buf;
 407 
 408         block = length / i->sb->s_blocksize;
 409 
 410         if(!S_ISDIR(i->i_mode) && !S_ISREG(i->i_mode) && !S_ISLNK(i->i_mode)) {
 411                 return -EINVAL;
 412         }
 413 
 414         if(block < MINIX_NDIR_BLOCKS) {
 415                 for(n = block; n < MINIX_NDIR_BLOCKS; n++) {
 416                         if(i->u.minix.u.i2_zone[n]) {
 417                                 minix_bfree(i->sb, i->u.minix.u.i2_zone[n]);
 418                                 i->u.minix.u.i2_zone[n] = 0;
 419                         }
 420                 }
 421                 block = 0;
 422         }
 423 
 424         if(!block || block < (BLOCKS_PER_IND_BLOCK(i->sb) + MINIX_NDIR_BLOCKS)) {
 425                 if(block) {
 426                         block -= MINIX_NDIR_BLOCKS;
 427                 }
 428                 if(i->u.minix.u.i2_zone[MINIX_IND_BLOCK]) {
 429                         free_zone(i, i->u.minix.u.i2_zone[MINIX_IND_BLOCK], block);
 430                         if(!block) {
 431                                 minix_bfree(i->sb, i->u.minix.u.i2_zone[MINIX_IND_BLOCK]);
 432                                 i->u.minix.u.i2_zone[MINIX_IND_BLOCK] = 0;
 433                         }
 434                 }
 435                 block = 0;
 436         }
 437 
 438         if(block) {
 439                 block -= MINIX_NDIR_BLOCKS;
 440                 block -= BLOCKS_PER_IND_BLOCK(i->sb);
 441         }
 442         if(i->u.minix.u.i2_zone[MINIX_DIND_BLOCK]) {
 443                 if(!(buf = bread(i->dev, i->u.minix.u.i2_zone[MINIX_DIND_BLOCK], i->sb->s_blocksize))) {
 444                         printk("%s(): error reading block %d.\n", __FUNCTION__, i->u.minix.u.i2_zone[MINIX_DIND_BLOCK]);
 445                 }
 446                 zone = (__u32 *)buf->data;
 447                 dblock = block % BLOCKS_PER_IND_BLOCK(i->sb);
 448                 for(n = block / BLOCKS_PER_IND_BLOCK(i->sb); n < BLOCKS_PER_IND_BLOCK(i->sb); n++) {
 449                         if(zone[n]) {
 450                                 free_zone(i, zone[n], dblock);
 451                                 if(!dblock) {
 452                                         minix_bfree(i->sb, zone[n]);
 453                                 }
 454                         }
 455                         dblock = 0;
 456                 }
 457                 bwrite(buf);
 458                 if(!block) {
 459                         minix_bfree(i->sb, i->u.minix.u.i2_zone[MINIX_DIND_BLOCK]);
 460                         i->u.minix.u.i2_zone[MINIX_DIND_BLOCK] = 0;
 461                 }
 462         }
 463 
 464         i->i_mtime = CURRENT_TIME;
 465         i->i_ctime = CURRENT_TIME;
 466         i->i_size = length;
 467         i->dirty = 1;
 468 
 469         return 0;
 470 }

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