staticint alloc_branch(struct inode *inode, int num, int *offsets,
Indirect *branch)
{ int n = 0; int i; int parent = minix_new_block(inode); int err = -ENOSPC;
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); if (!nr) break;
branch[n].key = cpu_to_block(nr);
bh = sb_getblk(inode->i_sb, parent); if (!bh) {
minix_free_block(inode, nr);
err = -ENOMEM; break;
}
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 err;
}
staticinlineint splice_branch(struct inode *inode,
Indirect chain[DEPTH],
Indirect *where, int num)
{ int i;
write_lock(&pointers_lock);
/* Verify that place we are splicing to is still there and vacant */ if (!verify_chain(chain, where-1) || *where->p) goto changed;
*where->p = where->key;
write_unlock(&pointers_lock);
/* We are done with atomic stuff, now do the rest of housekeeping */
inode_set_ctime_current(inode);
/* had we spliced it onto indirect block? */ if (where->bh)
mark_buffer_dirty_inode(where->bh, inode);
mark_inode_dirty(inode); return 0;
changed:
write_unlock(&pointers_lock); for (i = 1; i < num; i++)
bforget(where[i].bh); for (i = 0; i < num; i++)
minix_free_block(inode, block_to_cpu(where[i].key)); return -EAGAIN;
}
staticint get_block(struct inode * inode, sector_t block, struct buffer_head *bh, int create)
{ int err = -EIO; int offsets[DEPTH];
Indirect chain[DEPTH];
Indirect *partial; int left; int depth = block_to_path(inode, block, offsets);
/* Simplest case - block found, no allocation needed */ if (!partial) {
got_it:
map_bh(bh, inode->i_sb, block_to_cpu(chain[depth-1].key)); /* Clean up and exit */
partial = chain+depth-1; /* the whole chain */ goto cleanup;
}
/* Next simple case - plain lookup or failed read of indirect block */ if (!create || err == -EIO) {
cleanup: while (partial > chain) {
brelse(partial->bh);
partial--;
}
out: return err;
}
/* * Indirect block might be removed by truncate while we were * reading it. Handling of that case (forget what we've got and * reread) is taken out of the main path.
*/ if (err == -EAGAIN) goto changed;
left = (chain + depth) - partial;
err = alloc_branch(inode, left, offsets+(partial-chain), partial); if (err) goto cleanup;
if (splice_branch(inode, chain, partial, left) < 0) goto changed;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.