Skip to content

Commit b31172c

Browse files
authored
Fix: start_block misalignment caused by SIGSTOP (#552)
1 parent 1287159 commit b31172c

File tree

6 files changed

+106
-3
lines changed

6 files changed

+106
-3
lines changed

messages/libltfs/root.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,8 @@ v
834834
17290I:string { "Partitioning the medium with the destructive method." }
835835
17291I:string { "Unpartitioning the medium with the destructive method." }
836836
17292I:string { "Current position is (%llu, %llu), Error position is (%llu, %llu)." }
837+
17293E:string { "Position mismatch. Cached tape position = %llu. Current tape position = %llu." }
838+
17294I:string { "Continue signal (%d) received" }
837839

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

src/libltfs/ltfs.c

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,58 @@ bool ltfs_is_interrupted(void)
205205
return interrupted;
206206
}
207207

208+
bool caught_sigcont = false;
209+
void _ltfs_sigcont(int signal)
210+
{
211+
ltfsmsg(LTFS_INFO, 17294I, signal);
212+
ltfs_sigcont_set(true);
213+
}
214+
215+
void ltfs_sigcont_set(bool sig_val)
216+
{
217+
caught_sigcont = sig_val;
218+
}
219+
220+
bool ltfs_caught_sigcont(void)
221+
{
222+
return caught_sigcont;
223+
}
224+
225+
int ltfs_extra_signal_handlers(void)
226+
#ifdef mingw_PLATFORM
227+
{
228+
return 0;
229+
}
230+
#else
231+
{
232+
ltfs_sighandler_t ret;
233+
ret = signal(SIGCONT, _ltfs_sigcont);
234+
if (ret == SIG_ERR) {
235+
return -LTFS_SIG_HANDLER_ERR;
236+
}
237+
238+
return 0;
239+
}
240+
#endif
241+
242+
int ltfs_unset_extra_signal_handler(void)
243+
#ifdef mingw_PLATFORM
244+
{
245+
return 0;
246+
}
247+
#else
248+
{
249+
ltfs_sighandler_t rc;
250+
int ret = 0;
251+
252+
rc = signal(SIGCONT, SIG_DFL);
253+
if (rc == SIG_ERR)
254+
ret = -LTFS_SIG_HANDLER_ERR;
255+
256+
return ret;
257+
}
258+
#endif
259+
208260
/**
209261
* This function can be used to enable libltfs signal handler
210262
* to kill ltfs, mkltfs, ltfsck cleanly
@@ -2383,12 +2435,13 @@ int ltfs_write_index(char partition, char *reason, struct ltfs_volume *vol)
23832435
struct tape_offset old_selfptr, old_backptr;
23842436
struct ltfs_timespec modtime_old = { .tv_sec = 0, .tv_nsec = 0 };
23852437
bool generation_inc = false;
2386-
struct tc_position physical_selfptr;
2438+
struct tc_position physical_selfptr, current_position;
23872439
char *cache_path_save = NULL;
23882440
bool write_perm = (strcmp(reason, SYNC_WRITE_PERM) == 0);
23892441
bool update_vollock = false;
23902442
int volstat = -1, new_volstat = 0;
23912443
char *bc_print = NULL;
2444+
unsigned long long diff;
23922445

23932446
CHECK_ARG_NULL(vol, -LTFS_NULL_ARG);
23942447

@@ -2505,6 +2558,24 @@ int ltfs_write_index(char partition, char *reason, struct ltfs_volume *vol)
25052558
vol->index->backptr = old_backptr;
25062559
goto out_write_perm;
25072560
}
2561+
2562+
/* Get the tape position from the tape drive by using the SCSI command READPOS*/
2563+
ret = tape_get_position_from_drive(vol->device, &current_position);
2564+
if (ret < 0) {
2565+
/* Return error since the current tape position was unable to be determined, so there could be an undetected position mismatch */
2566+
ltfsmsg(LTFS_ERR, 11081E, ret);
2567+
return -1;
2568+
}
2569+
2570+
/* Prior to writing the index, compare the current location of the head position to the head location
2571+
that is kept in the cache of ltfs (physical_selfptr). If they are different return error (-1) */
2572+
diff = ((unsigned long long)physical_selfptr.block - (unsigned long long)current_position.block);
2573+
if (diff) {
2574+
/* Position mismatch, diff not equal zero */
2575+
ltfsmsg(LTFS_INFO, 17293E, (unsigned long long)physical_selfptr.block, (unsigned long long)current_position.block);
2576+
return -1;
2577+
}
2578+
25082579
old_selfptr = vol->index->selfptr;
25092580
vol->index->selfptr.partition = partition;
25102581
vol->index->selfptr.partition = vol->label->part_num2id[physical_selfptr.partition];

src/libltfs/ltfs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,8 +592,12 @@ int ltfs_fs_init(void);
592592
void ltfs_set_log_level(int log_level);
593593
void ltfs_set_syslog_level(int syslog_level);
594594
bool ltfs_is_interrupted(void);
595+
bool ltfs_caught_sigcont(void);
596+
void ltfs_sigcont_set(bool sig_val);
595597
int ltfs_set_signal_handlers(void);
596598
int ltfs_unset_signal_handlers(void);
599+
int ltfs_extra_signal_handlers(void);
600+
int ltfs_unset_extra_signal_handler(void);
597601
int ltfs_finish();
598602

599603
/* Public wrappers for tape_* functions */

src/libltfs/tape.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1105,7 +1105,7 @@ int tape_get_position(struct device_data *dev, struct tc_position *pos)
11051105
/**
11061106
* Get current tape position by querying the device.
11071107
*/
1108-
int tape_update_position(struct device_data *dev, struct tc_position *pos)
1108+
int tape_get_position_from_drive(struct device_data *dev, struct tc_position *pos)
11091109
{
11101110
int ret;
11111111

@@ -1187,6 +1187,9 @@ int tape_spacefm(struct device_data *dev, int count)
11871187
ssize_t tape_write(struct device_data *dev, const char *buf, size_t count, bool ignore_less, bool ignore_nospc)
11881188
{
11891189
ssize_t ret;
1190+
struct tc_position current_position;
1191+
int ret_for_current_position = 0;
1192+
unsigned long long diff = 0;
11901193

11911194
CHECK_ARG_NULL(dev, -LTFS_NULL_ARG);
11921195
CHECK_ARG_NULL(buf, -LTFS_NULL_ARG);
@@ -1241,6 +1244,25 @@ ssize_t tape_write(struct device_data *dev, const char *buf, size_t count, bool
12411244
count = -LTFS_LESS_SPACE;
12421245
}
12431246

1247+
if (ltfs_caught_sigcont()) {
1248+
// Unset flag to avoid checking it again if it is not needed
1249+
ltfs_sigcont_set(false);
1250+
1251+
ret_for_current_position = tape_get_position_from_drive(dev, &current_position);
1252+
if (ret_for_current_position) {
1253+
/* Return error since the current tape position was unable to be determined, so there could be an undetected position mismatch */
1254+
ltfsmsg(LTFS_ERR, 11081E, ret);
1255+
return -LTFS_WRITE_ERROR;
1256+
}
1257+
1258+
diff = ((unsigned long long)dev->position.block - (unsigned long long)current_position.block);
1259+
if (diff) {
1260+
/* Position mismatch, diff not equal zero */
1261+
ltfsmsg(LTFS_INFO, 17293E, (unsigned long long)dev->position.block, (unsigned long long)current_position.block);
1262+
return -LTFS_WRITE_ERROR;
1263+
}
1264+
}
1265+
12441266
ltfs_mutex_lock(&dev->append_pos_mutex);
12451267
dev->append_pos[dev->position.partition] = dev->position.block;
12461268
ltfs_mutex_unlock(&dev->append_pos_mutex);

src/libltfs/tape.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ int tape_force_read_only(struct device_data *dev);
160160

161161
int tape_rewind(struct device_data *dev);
162162
int tape_get_position(struct device_data *dev, struct tc_position *pos);
163-
int tape_update_position(struct device_data *dev, struct tc_position *pos);
163+
int tape_get_position_from_drive(struct device_data *dev, struct tc_position *pos);
164164

165165
int tape_seek(struct device_data *dev, struct tc_position *pos);
166166
int tape_seek_eod(struct device_data *dev, tape_partition_t partition);

src/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,10 +1241,14 @@ int single_drive_main(struct fuse_args *args, struct ltfs_fuse_data *priv)
12411241
ltfsmsg(LTFS_INFO, 14111I);
12421242
ltfsmsg(LTFS_INFO, 14112I);
12431243
ltfsmsg(LTFS_INFO, 14113I);
1244+
/* Set handlers for signals that need to be caught while fuse main is running*/
1245+
ltfs_extra_signal_handlers();
12441246
ret = fuse_main(args->argc, args->argv, &ltfs_ops, priv);
12451247
if (ret != 0) {
12461248
ltfsmsg(LTFS_WARN, 14123W, ret);
12471249
}
1250+
/* Unset extra handlers once fuse main exits */
1251+
ltfs_unset_extra_signal_handler();
12481252

12491253
/* Setup signal handler again to terminate cleanly */
12501254
ret = ltfs_set_signal_handlers();

0 commit comments

Comments
 (0)