/*- * Routine: ifree * * Purpose: * Libera un inodo y lo añade a la lista de inodos libres. * Si este inodo referencia a algún bloque de datos, también * lo libera y lo añade a su lista correspondiente * Conditions: * dev debe corresponder a un gnordofs válido. * sb debe apuntar a un superbloque válido. * inode debe apuntar a un inodo. * Returns: * -1 on error. * */ int ifree(int dev, superblock_t * const sb, inode_t *inode) { int i, block; DEBUG_VERBOSE(">> ifree(inode->n = %d)\n", inode->n); for (i=0; i < N_DIRECT_BLOCKS; i++) { block = inode_getblk(dev, sb, inode, i); if (!unassigned_p(block)) freeblk(dev, sb, block); } if (!unassigned_p(inode->single_indirect_blocks)) { for (i=N_DIRECT_BLOCKS; i < N_DIRECT_BLOCKS+N_SINGLE_INDIRECT_BLOCKS; i++) { block = inode_getblk(dev, sb, inode, i); if (!unassigned_p(block)) freeblk(dev, sb, block); } freeblk(dev, sb, inode->single_indirect_blocks); } if (sb->free_inode_index == FREE_INODE_LIST_SIZE) { DEBUG_VERBOSE(">> ialloc >> Lista de inodos libres llena..."); /* Si la lista está vacía y el nuevo inodo libre es anterior al primero de esta lista, insertarlo (reemplazando) en dicha posición. */ if (sb->free_inode_list[0] > inode->n) { DEBUG_VERBOSE(" reemplazando primera entrada."); sb->free_inode_list[0] = inode->n; } } else { /* Si no, añadirlo a ella e incrementar el índice. */ sb->free_inode_list[sb->free_inode_index] = inode->n; sb->free_inode_index++; } inode->type = I_FREE; iput(dev, sb, inode); /* Incrementar contador de inodos libres. */ sb->free_inodes++; return 0; }
struct buffer_head * sysv_getblk(struct inode * inode, unsigned int block, int create, char * *start) { struct super_block * sb = inode->i_sb; struct buffer_head * bh; if (block < 10) return inode_getblk(inode,block,create,start); block -= 10; if (block < sb->sv_ind_per_block) { bh = inode_getblk(inode,10,create,start); return block_getblk(inode, bh, block, create, start); } block -= sb->sv_ind_per_block; if (block < sb->sv_ind_per_block_2) { bh = inode_getblk(inode,11,create,start); bh = block_getblk(inode, bh, block >> sb->sv_ind_per_block_bits, create, start); return block_getblk(inode, bh, block & sb->sv_ind_per_block_1, create, start); }
struct buffer_head * minix_getblk(struct inode * inode, int block, int create) { struct buffer_head * bh; if (block<0) { printk("minix_getblk: block<0"); return NULL; } if (block >= 7+512+512*512) { printk("minix_getblk: block>big"); return NULL; } if (block < 7) return inode_getblk(inode,block,create); block -= 7; if (block < 512) { bh = inode_getblk(inode,7,create); return block_getblk(bh,block,create); } block -= 512; bh = inode_getblk(inode,8,create); bh = block_getblk(bh,block>>9,create); return block_getblk(bh,block & 511,create); }
/*- * Routine: inode_truncate * * Purpose: * Trunca un archivo a partir de su inodo. * Conditions: * dev debe corresponder a un gnordofs válido. * sb debe apuntar a un superbloque válido. * inode debe apuntar a un inodo válido. * size debe ser no-negativo. * Returns: * -1 on error. * */ int inode_truncate(int dev, superblock_t * const sb, inode_t *inode, int size) { int blk, last_blk; int absolute_blk; if (size < 0) return -1; /* Para truncar al alza, tan sólo hay que tocar el campo size del inodo. */ if (size >= inode->size) { if (size > inode->size) inode->size = size; return 0; } /* Para truncar de toda la vida, hay que liberar los bloques que quedan fuera tras meter las tijeras. */ /* Calcular último bloque interno que hay que liberar. */ last_blk = (inode->size-1) / sizeof(struct block); /* Calcular primer bloque interno que hay que liberar. */ blk = size ? (size-1)/sizeof(struct block) : 0; while (blk <= last_blk) { absolute_blk = inode_getblk(dev, sb, inode, blk); if (absolute_blk == -1) return -1; if (!unassigned_p(absolute_blk)) { if (freeblk(dev, sb, absolute_blk) < 0) return -1; inode_freeblk(dev, sb, inode, blk); } blk++; } inode->size = size; return 0; }