/* This version is for the extended slot map */ staticvoid ocfs2_update_slot_info_extended(struct ocfs2_slot_info *si)
{ int b, i, slotno; struct ocfs2_slot_map_extended *se;
slotno = 0; for (b = 0; b < si->si_blocks; b++) {
se = (struct ocfs2_slot_map_extended *)si->si_bh[b]->b_data; for (i = 0;
(i < si->si_slots_per_block) &&
(slotno < si->si_num_slots);
i++, slotno++) { if (se->se_slots[i].es_valid)
ocfs2_set_slot(si, slotno,
le32_to_cpu(se->se_slots[i].es_node_num)); else
ocfs2_invalidate_slot(si, slotno);
}
}
}
/* * Post the slot information on disk into our slot_info struct. * Must be protected by osb_lock.
*/ staticvoid ocfs2_update_slot_info_old(struct ocfs2_slot_info *si)
{ int i; struct ocfs2_slot_map *sm;
sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data;
for (i = 0; i < si->si_num_slots; i++) { if (le16_to_cpu(sm->sm_slots[i]) == (u16)OCFS2_INVALID_SLOT)
ocfs2_invalidate_slot(si, i); else
ocfs2_set_slot(si, i, le16_to_cpu(sm->sm_slots[i]));
}
}
staticvoid ocfs2_update_slot_info(struct ocfs2_slot_info *si)
{ /* * The slot data will have been refreshed when ocfs2_super_lock * was taken.
*/ if (si->si_extended)
ocfs2_update_slot_info_extended(si); else
ocfs2_update_slot_info_old(si);
}
int ocfs2_refresh_slot_info(struct ocfs2_super *osb)
{ int ret; struct ocfs2_slot_info *si = osb->slot_info;
/* * We pass -1 as blocknr because we expect all of si->si_bh to * be !NULL. Thus, ocfs2_read_blocks() will ignore blocknr. If * this is not true, the read of -1 (UINT64_MAX) will fail.
*/
ret = ocfs2_read_blocks(INODE_CACHE(si->si_inode), -1, si->si_blocks,
si->si_bh, OCFS2_BH_IGNORE_CACHE, NULL); if (ret == 0) {
spin_lock(&osb->osb_lock);
ocfs2_update_slot_info(si);
spin_unlock(&osb->osb_lock);
}
return ret;
}
/* post the our slot info stuff into it's destination bh and write it
* out. */ staticvoid ocfs2_update_disk_slot_extended(struct ocfs2_slot_info *si, int slot_num, struct buffer_head **bh)
{ int blkind = slot_num / si->si_slots_per_block; int slotno = slot_num % si->si_slots_per_block; struct ocfs2_slot_map_extended *se;
BUG_ON(blkind >= si->si_blocks);
se = (struct ocfs2_slot_map_extended *)si->si_bh[blkind]->b_data;
se->se_slots[slotno].es_valid = si->si_slots[slot_num].sl_valid; if (si->si_slots[slot_num].sl_valid)
se->se_slots[slotno].es_node_num =
cpu_to_le32(si->si_slots[slot_num].sl_node_num);
*bh = si->si_bh[blkind];
}
staticvoid ocfs2_update_disk_slot_old(struct ocfs2_slot_info *si, int slot_num, struct buffer_head **bh)
{ int i; struct ocfs2_slot_map *sm;
sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; for (i = 0; i < si->si_num_slots; i++) { if (si->si_slots[i].sl_valid)
sm->sm_slots[i] =
cpu_to_le16(si->si_slots[i].sl_node_num); else
sm->sm_slots[i] = cpu_to_le16(OCFS2_INVALID_SLOT);
}
*bh = si->si_bh[0];
}
staticint ocfs2_update_disk_slot(struct ocfs2_super *osb, struct ocfs2_slot_info *si, int slot_num)
{ int status; struct buffer_head *bh;
status = ocfs2_write_block(osb, bh, INODE_CACHE(si->si_inode)); if (status < 0)
mlog_errno(status);
return status;
}
/* * Calculate how many bytes are needed by the slot map. Returns * an error if the slot map file is too small.
*/ staticint ocfs2_slot_map_physical_size(struct ocfs2_super *osb, struct inode *inode, unsignedlonglong *bytes)
{ unsignedlonglong bytes_needed;
if (ocfs2_uses_extended_slot_map(osb)) {
bytes_needed = osb->max_slots * sizeof(struct ocfs2_extended_slot);
} else {
bytes_needed = osb->max_slots * sizeof(__le16);
} if (bytes_needed > i_size_read(inode)) {
mlog(ML_ERROR, "Slot map file is too small! (size %llu, needed %llu)\n",
i_size_read(inode), bytes_needed); return -ENOSPC;
}
*bytes = bytes_needed; return 0;
}
/* try to find global node in the slot info. Returns -ENOENT
* if nothing is found. */ staticint __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, unsignedint node_num)
{ int i, ret = -ENOENT;
for(i = 0; i < si->si_num_slots; i++) { if (si->si_slots[i].sl_valid &&
(node_num == si->si_slots[i].sl_node_num)) {
ret = i; break;
}
}
return ret;
}
staticint __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, int preferred)
{ int i, ret = -ENOSPC;
if ((preferred >= 0) && (preferred < si->si_num_slots)) { if (!si->si_slots[preferred].sl_valid) {
ret = preferred; goto out;
}
}
for(i = 0; i < si->si_num_slots; i++) { if (!si->si_slots[i].sl_valid) {
ret = i; break;
}
}
out: return ret;
}
int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsignedint node_num)
{ int slot; struct ocfs2_slot_info *si = osb->slot_info;
iput(si->si_inode); if (si->si_bh) { for (i = 0; i < si->si_blocks; i++) { if (si->si_bh[i]) {
brelse(si->si_bh[i]);
si->si_bh[i] = NULL;
}
}
kfree(si->si_bh);
}
kfree(si);
}
int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num)
{ struct ocfs2_slot_info *si = osb->slot_info;
si->si_bh = kcalloc(si->si_blocks, sizeof(struct buffer_head *),
GFP_KERNEL); if (!si->si_bh) {
status = -ENOMEM;
mlog_errno(status); goto bail;
}
for (i = 0; i < si->si_blocks; i++) {
status = ocfs2_extent_map_get_blocks(si->si_inode, i,
&blkno, NULL, NULL); if (status < 0) {
mlog_errno(status); goto bail;
}
/* search for ourselves first and take the slot if it already * exists. Perhaps we need to mark this in a variable for our * own journal recovery? Possibly not, though we certainly
* need to warn to the user */
slot = __ocfs2_node_num_to_slot(si, osb->node_num); if (slot < 0) { /* if no slot yet, then just take 1st available
* one. */
slot = __ocfs2_find_empty_slot(si, osb->preferred_slot); if (slot < 0) {
spin_unlock(&osb->osb_lock);
mlog(ML_ERROR, "no free slots available!\n");
status = -EINVAL; goto bail;
}
} else
printk(KERN_INFO "ocfs2: Slot %d on device (%s) was already " "allocated to this node!\n", slot, osb->dev_str);
status = ocfs2_update_disk_slot(osb, si, osb->slot_num); if (status < 0) {
mlog_errno(status); /* * if write block failed, invalidate slot to avoid overwrite * slot during dismount in case another node rightly has mounted
*/
spin_lock(&osb->osb_lock);
ocfs2_invalidate_slot(si, osb->slot_num);
osb->slot_num = OCFS2_INVALID_SLOT;
spin_unlock(&osb->osb_lock);
}
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.