static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create) { int tmp; unsigned short *p; struct buffer_head * result; p = inode->u.minix_i.i_data + nr; repeat: tmp = *p; if (tmp) { result = getblk(inode->i_dev, tmp, BLOCK_SIZE); if (tmp == *p) return result; brelse(result); goto repeat; } if (!create) return NULL; tmp = minix_new_block(inode->i_dev); if (!tmp) return NULL; result = getblk(inode->i_dev, tmp, BLOCK_SIZE); if (*p) { minix_free_block(inode->i_dev,tmp); brelse(result); goto repeat; } *p = tmp; inode->i_ctime = CURRENT_TIME; inode->i_dirt = 1; return result; }
struct inode *minix_inode_mkdir(struct inode *dir, char *base, int len) { struct minix_dentry *de; struct inode *inode; struct block *block; if (!(inode = minix_inode_create(dir, base, len))) return NULL; /* update dir inode information */ minix_inc_link(dir); /* update inode information */ i2mdi(inode)->i_mode = 0755 | S_IFDIR; i2mdi(inode)->i_nlinks = 2; inode->i_mode = 0755 | S_IFDIR; inode->i_ops = &minix_dir_iops; inode_update_size(inode, 2 * MINIX_DENTRY_SIZE); /* create dir entry "." and ".." */ block = minix_new_block(dir->i_sb, &i2mdi(inode)->i_zone[0]); if (!block) panic("Cannot alloc new block for minixfs"); /* "." */ de = (struct minix_dentry *)block->b_data; strcpy(de->d_name, "."); de->d_ino = inode->i_ino; /* ".." */ de++; strcpy(de->d_name, ".."); de->d_ino = dir->i_ino; minix_inode_dirty_block(inode, block); put_block(block); return inode; }
static int alloc_branch(struct inode *inode, int num, int *offsets, Indirect *branch) { int n = 0; int i; int parent = minix_new_block(inode); printk("parent new block %d\n",parent); branch[0].key = cpu_to_block(parent); if (parent) for (n = 1; n < num; n++) { struct buffer_head *bh; /* Allocate the next block */ int nr = minix_new_block(inode); printk("loop new block %d",nr); if (!nr) break; branch[n].key = cpu_to_block(nr); bh = sb_getblk(inode->i_sb, parent); lock_buffer(bh); memset(bh->b_data, 0, bh->b_size); branch[n].bh = bh; branch[n].p = (block_t*) bh->b_data + offsets[n]; *branch[n].p = branch[n].key; set_buffer_uptodate(bh); unlock_buffer(bh); mark_buffer_dirty_inode(bh, inode); parent = nr; } if (n == num) return 0; /* Allocation failed, free what we already allocated */ for (i = 1; i < n; i++) bforget(branch[i].bh); for (i = 0; i < n; i++) minix_free_block(inode, block_to_cpu(branch[i].key)); return -ENOSPC; }
static struct buffer_head * block_getblk(struct inode * inode, struct buffer_head * bh, int nr, int create) { int tmp; unsigned short *p; struct buffer_head * result; if (!bh) return NULL; if (!bh->b_uptodate) { ll_rw_block(READ, 1, &bh); wait_on_buffer(bh); if (!bh->b_uptodate) { brelse(bh); return NULL; } } p = nr + (unsigned short *) bh->b_data; repeat: tmp = *p; if (tmp) { result = getblk(bh->b_dev, tmp, BLOCK_SIZE); if (tmp == *p) { brelse(bh); return result; } brelse(result); goto repeat; } if (!create) { brelse(bh); return NULL; } tmp = minix_new_block(inode->i_sb); if (!tmp) { brelse(bh); return NULL; } result = getblk(bh->b_dev, tmp, BLOCK_SIZE); if (*p) { minix_free_block(inode->i_sb,tmp); brelse(result); goto repeat; } *p = tmp; mark_buffer_dirty(bh, 1); brelse(bh); return result; }
int bmap(struct inode *inode, int blk, int create) { struct minix_d_inode *mdi = i2mdi(inode); struct super_block *sb = inode->i_sb; struct block *block , *block2, *blockn; unsigned short *pblk; int rblk; /* max block number */ if (blk >= 7 + 512 + 512 * 512) return -1; /* init parameters */ block = block2 = blockn = NULL; rblk = -1; /* direct block */ if (blk < 7) { rblk = mdi->i_zone[blk]; if (!rblk) { if (!create) return 0; rblk = minix_new_block_nr(sb); if (rblk > 0) { mdi->i_zone[blk] = rblk; minix_inode_dirty(inode); } } return rblk; } /* one-level indirect block */ blk -= 7; if (blk < 512) { pblk = &mdi->i_zone[7]; if (!*pblk) { if (!create) return 0; block = minix_new_block(sb, pblk); if (!block) return -1; minix_inode_dirty(inode); } else if (!(block = minix_get_block(sb, *pblk))) return -1; rblk = MINIX_BDATA_BLK(block, blk); if (!rblk) { if (!create) { rblk = 0; goto out_block; } rblk = minix_new_block_nr(sb); if (rblk > 0) { MINIX_BDATA_BLK(block, blk) = rblk; minix_inode_dirty_block(inode, block); } } goto out_block; } /* two-level indirect block */ blk -= 512; /* first level */ pblk = &mdi->i_zone[8]; if (!*pblk) { if (!create) return 0; block = minix_new_block(sb, pblk); if (!block) return -1; minix_inode_dirty(inode); } else if (!(block = minix_get_block(sb, *pblk))) return -1; /* second level */ pblk = &MINIX_BDATA_BLK(block, blk / 512); if (!*pblk) { if (!create) { rblk = 0; goto out_block; } block2 = minix_new_block(sb, pblk); if (!block2) goto out_block; minix_inode_dirty_block(inode, block); } else if (!(block2 = minix_get_block(sb, *pblk))) goto out_block; rblk = MINIX_BDATA_BLK(block2, blk & 511); if (!rblk) { if (!create) { rblk = 0; goto out_block2; } rblk = minix_new_block_nr(sb); if (rblk > 0) { MINIX_BDATA_BLK(block2, blk & 511) = rblk; minix_inode_dirty_block(inode, block2); } } out_block2: put_block(block2); out_block: put_block(block); return rblk; }