Skip to content

Commit

Permalink
Handle unupdated MAM tape at write perm (#307)
Browse files Browse the repository at this point in the history
  • Loading branch information
Atsushi Abe authored Aug 10, 2021
1 parent fec9a78 commit 3287850
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 8 deletions.
11 changes: 9 additions & 2 deletions messages/libltfs/root.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ root:table {
11029E:string { "Cannot mount volume: failed to save the append position for the index partition." }
11030I:string { "Failed to sync volume (%d). Stop the periodic sync thread." }
//unused 11030E:string { "Cannot release the device lock (%s)." }
11031I:string { "Volume mounted successfully %s (Gen = %lld, (%c, %lld) -> (%c, %lld), %s)." }
11031I:string { "Volume mounted successfully. %s : Gen = %lld / (%c, %lld) -> (%c, %lld) / %s." }
11032D:string { "Unmounting the volume." }
11033E:string { "Cannot unmount: failed to write an index." }
11034I:string { "Volume unmounted successfully." }
Expand Down Expand Up @@ -427,7 +427,7 @@ root:table {
11330I:string { "Loading cartridge." }
11331E:string { "Failed to load the cartridge (%s)." }
11332I:string { "Load successful." }
11333I:string { "A cartridge with write-perm error is detected on %s. Seek the newest index (IP Gen = %llu, VCR = %llu) (DP Gen = %llu, VCR = %llu) (VCR = %llu)." }
11333I:string { "A cartridge with write-perm error is detected on %s. Seek the newest index (IP: Gen = %llu, VCR = %llu) (DP: Gen = %llu, VCR = %llu) (VCR = %llu)." }
11334I:string { "Remove extent : %s (%llu, %llu)." }
11335D:string { "Get physical block position (%d - %d)." }
11336I:string { "The attribute does not exist. Ignore the expected error." }
Expand Down Expand Up @@ -824,6 +824,13 @@ v
17280I:string { "Failed to get the length of the RAO input file: %s (%d)." }
17281I:string { "Failed to read from RAO input file: %s (%d)." }
17282I:string { "Read length from RAO input file is unexpected: %s (Actual %ld, Expected %ld)." }
17283I:string { "Detected unmatched VCR value between MAM and VCR (%llu, %llu)." }
17284I:string { "Seaching the final index in %s." }
17285E:string { "Failed to search the final index in %s (%d)." }
17286I:string { "VCR value is matched between %s-MAM and VCR (%llu)." }
17287I:string { "Making R/O mount from the location (%c, %llu)." }
17288I:string { "Detected the final indexes (IP: Gen = %llu, Pos = %llu) (DP: Gen = %llu, Pos = %llu)." }
17289I:string { "Skip parsing the final index on IP." }

// For Debug 19999I:string { "%s %s %d." }

Expand Down
99 changes: 93 additions & 6 deletions src/libltfs/ltfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1461,6 +1461,51 @@ int ltfs_start_mount(bool trial, struct ltfs_volume *vol)
return 0;
}

static inline int _ltfs_search_index_wp(bool recover_symlink, bool can_skip_ip,
struct tc_position *seekpos, struct ltfs_volume *vol)
{
int ret = 0;
tape_block_t end_pos, index_end_pos;
bool fm_after, blocks_after;

ltfsmsg(LTFS_INFO, 17284I, "IP");
ret = ltfs_seek_index(vol->label->partid_ip, &end_pos, &index_end_pos, &fm_after,
&blocks_after, recover_symlink, vol);
if (ret) {
if (can_skip_ip) {
ltfsmsg(LTFS_INFO, 17289I);
vol->ip_coh.count = 0;
vol->ip_coh.set_id = 0;
} else {
ltfsmsg(LTFS_ERR, 17285E, "IP", ret);
return -LTFS_INDEX_INVALID;
}
}

ltfsmsg(LTFS_INFO, 17284I, "DP");
ret = ltfs_seek_index(vol->label->partid_dp, &end_pos, &index_end_pos, &fm_after,
&blocks_after, recover_symlink, vol);
if (ret < 0) {
ltfsmsg(LTFS_ERR, 17285E, "DP", ret);
return -LTFS_INDEX_INVALID;
}

/* Use the latest index on the tape */
ltfsmsg(LTFS_INFO, 17288I,
(unsigned long long)vol->ip_coh.count, (unsigned long long)vol->ip_coh.set_id,
(unsigned long long)vol->dp_coh.count, (unsigned long long)vol->dp_coh.set_id);

if (vol->ip_coh.count > vol->dp_coh.count) {
seekpos->partition = ltfs_part_id2num(vol->label->partid_ip, vol);
seekpos->block = vol->ip_coh.set_id;
} else {
seekpos->partition = ltfs_part_id2num(vol->label->partid_dp, vol);
seekpos->block = vol->dp_coh.set_id;
}

return 0;
}

/**
* Read LTFS data structures from a tape, checking for consistency (and restoring it
* if possible). This function doesn't bother locking vol->index, as it must complete before any
Expand Down Expand Up @@ -1602,8 +1647,26 @@ int ltfs_mount(bool force_full, bool deep_recovery, bool recover_extra, bool rec
*/
ltfsmsg(LTFS_INFO, 17264I, "DP", vl_print);
}
seekpos.partition = ltfs_part_id2num(vol->label->partid_dp, vol);
seekpos.block = vol->dp_coh.set_id;

if (volume_change_ref != vol->dp_coh.volume_change_ref) {
/*
* Cannot trust the index info on MAM, search the last indexes
* This would happen when the drive returns an error against acquiring the VCR
* while write error handling.
*/
ltfsmsg(LTFS_INFO, 17283I,
(unsigned long long)vol->dp_coh.volume_change_ref,
(unsigned long long)volume_change_ref);

ret = _ltfs_search_index_wp(recover_symlink, false, &seekpos, vol);
if (ret < 0)
goto out_unlock;

} else {
ltfsmsg(LTFS_INFO, 17286I, "DP", (unsigned long long)volume_change_ref);
seekpos.partition = ltfs_part_id2num(vol->label->partid_dp, vol);
seekpos.block = vol->dp_coh.set_id;
}
} else {
if (vollock != PWE_MAM_DP && vollock != PWE_MAM) {
/*
Expand All @@ -1612,13 +1675,37 @@ int ltfs_mount(bool force_full, bool deep_recovery, bool recover_extra, bool rec
* so this condition wouldn't happen logically.
*/
ltfsmsg(LTFS_INFO, 17264I, "IP", vl_print);
tape_takedump_drive(vol->device, false);
}
seekpos.partition = ltfs_part_id2num(vol->label->partid_ip, vol);
seekpos.block = vol->ip_coh.set_id;
read_ip = true;

if (volume_change_ref != vol->ip_coh.volume_change_ref) {
/*
* Cannot trust the index info on MAM, search the last indexes
* This would happen when the drive returns an error against acquiring the VCR
* while write error handling.
*/
ltfsmsg(LTFS_INFO, 17283I,
(unsigned long long)vol->dp_coh.volume_change_ref,
(unsigned long long)volume_change_ref);

/* Index of IP could be corrupted. So set skip flag */
ret = _ltfs_search_index_wp(recover_symlink, true, &seekpos, vol);
if (ret < 0)
goto out_unlock;

} else {
ltfsmsg(LTFS_INFO, 17286I, "IP", (unsigned long long)volume_change_ref);
seekpos.partition = ltfs_part_id2num(vol->label->partid_ip, vol);
seekpos.block = vol->ip_coh.set_id;
}
}

if (vol->label->part_num2id[seekpos.partition] == vol->label->partid_ip)
read_ip = true;

ltfsmsg(LTFS_INFO, 17287I,
vol->label->part_num2id[seekpos.partition],
(unsigned long long)seekpos.block);

ret = tape_seek(vol->device, &seekpos);
if (ret == -EDEV_EOD_DETECTED) {
INTERRUPTED_GOTO(ret, out_unlock);
Expand Down

0 comments on commit 3287850

Please sign in to comment.