General:
Changes to 1.37.41:
+13Oct05
+- Modify DVD code so that it keeps a state flag that indicates
+ when the freespace variable is valid. freespace_errno, now has
+ either 0 or an errno. There are no negative errnos.
+- Create is_freespace_ok() to test state flag. Also, set_freespace_ok()
+ and clear_freespace_ok(). Modify code to use them. This
+ simplifies a bit the logic of the freespace code.
+- Edit 64bit debug values correctly in dvd.c
+- Fix %e variable to check num_parts rather than part.
+- Use static buffer instead of static buffers for FI_to_ascii()
+ and stream_to_ascii() debug routines in SD. This is to prevent
+ possible race conditions between two threads (possibly Phil's
+ unmount problem).
12Oct05
- Add a .dir command that separates arguments with commas. It
is intended to be used in the tree routines to get a
DEV_RECORD rec;
DCR *dcr = jcr->dcr;
DEVICE *dev = dcr->dev;
+ char buf1[100], buf2[100];
Dmsg0(100, "Start append data.\n");
rec.data = ds->msg; /* use message buffer */
Dmsg4(850, "before writ_rec FI=%d SessId=%d Strm=%s len=%d\n",
- rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream,rec.FileIndex),
+ rec.FileIndex, rec.VolSessionId,
+ stream_to_ascii(buf1, rec.Stream,rec.FileIndex),
rec.data_len);
while (!write_record_to_block(dcr->block, &rec)) {
}
jcr->JobBytes += rec.data_len; /* increment bytes this job */
Dmsg4(850, "write_record FI=%s SessId=%d Strm=%s len=%d\n",
- FI_to_ascii(rec.FileIndex), rec.VolSessionId,
- stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len);
+ FI_to_ascii(buf1, rec.FileIndex), rec.VolSessionId,
+ stream_to_ascii(buf2, rec.Stream, rec.FileIndex), rec.data_len);
/* Send attributes and MD5 to Director for Catalog */
if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_MD5_SIGNATURE ||
int32_t FileIndex;
int32_t Stream;
int bhl, rhl;
+ char buf1[100], buf2[100];
unser_begin(b->buf, BLKHDR1_LENGTH);
unser_uint32(CheckSum);
unser_int32(Stream);
unser_uint32(data_len);
Pmsg6(000, _(" Rec: VId=%u VT=%u FI=%s Strm=%s len=%d p=%x\n"),
- VolSessionId, VolSessionTime, FI_to_ascii(FileIndex),
- stream_to_ascii(Stream, FileIndex), data_len, p);
+ VolSessionId, VolSessionTime, FI_to_ascii(buf1, FileIndex),
+ stream_to_ascii(buf2, Stream, FileIndex), data_len, p);
p += data_len + rhl;
}
}
}
}
- if (dev->free_space_errno < 0) { /* Error while getting free space */
+ if (!dev->is_freespace_ok()) { /* Error while getting free space */
char ed1[50], ed2[50];
Dmsg1(10, "Cannot get free space on the device ERR=%s.\n", dev->errmsg);
Jmsg(jcr, M_FATAL, 0, _("End of Volume \"%s\" at %u:%u on device %s "
dev->file, dev->block_num, dev->print_name(),
edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
dev->free_space_errno, dev->errmsg);
- dev->dev_errno = -dev->free_space_errno;
+ dev->dev_errno = dev->free_space_errno;
return false;
}
- if ((dev->free_space_errno > 0 && (dev->part_size + block->binbuf) >= dev->free_space)) {
+ if ((dev->is_freespace_ok() && (dev->part_size + block->binbuf) >= dev->free_space)) {
char ed1[50], ed2[50];
Dmsg0(10, "==== Just enough free space on the device to write the current part...\n");
Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s "
/* List just block information */
static void do_blocks(char *infname)
{
+ char buf1[100], buf2[100];
for ( ;; ) {
if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
Dmsg1(100, "!read_block(): ERR=%s\n", dev->strerror());
Pmsg9(-1, _("File:blk=%u:%u blk_num=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n"),
dev->file, dev->block_num,
block->BlockNumber, block->block_len,
- FI_to_ascii(rec->FileIndex), rec->VolSessionId, rec->VolSessionTime,
- stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len);
+ FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, rec->VolSessionTime,
+ stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);
rec->remainder = 0;
} else if (verbose > 1) {
dump_block(block, "");
uint64_t bytes;
DEV_BLOCK *block = dcr->block;
char ec1[50];
+ char buf1[100], buf2[100];
blocks = block_size = tot_blocks = 0;
bytes = 0;
read_record_from_block(block, rec);
Pmsg8(-1, _("Blk_block: %u dev_blk=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n"),
block->BlockNumber, dev->block_num, block->block_len,
- FI_to_ascii(rec->FileIndex), rec->VolSessionId, rec->VolSessionTime,
- stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len);
+ FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, rec->VolSessionTime,
+ stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);
rec->remainder = 0;
free_record(rec);
} else if (verbose > 1) {
DEV_RECORD rec;
DEV_BLOCK *block = dcr->block;
char ec1[50];
+ char buf1[100], buf2[100];
int fd;
uint32_t i;
uint32_t min_block_size;
}
Dmsg4(250, "before write_rec FI=%d SessId=%d Strm=%s len=%d\n",
- rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream, rec.FileIndex),
+ rec.FileIndex, rec.VolSessionId,
+ stream_to_ascii(buf1, rec.Stream, rec.FileIndex),
rec.data_len);
while (!write_record_to_block(block, &rec)) {
}
jcr->JobBytes += rec.data_len; /* increment bytes this job */
Dmsg4(190, "write_record FI=%s SessId=%d Strm=%s len=%d\n",
- FI_to_ascii(rec.FileIndex), rec.VolSessionId,
- stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len);
+ FI_to_ascii(buf1, rec.FileIndex), rec.VolSessionId,
+ stream_to_ascii(buf2, rec.Stream, rec.FileIndex), rec.data_len);
/* Get out after writing 10 blocks to the second tape */
if (BlockNumber > 10 && stop != 0) { /* get out */
#define ST_MEDIA (1<<16) /* Media found in mounted device */
#define ST_OFFLINE (1<<17) /* set offline by operator */
#define ST_PART_SPOOLED (1<<18) /* spooling part */
+#define ST_FREESPACE_OK (1<<19) /* Have valid freespace for DVD */
/* dev_blocked states (mutually exclusive) */
enum {
uint32_t part; /* current part number (starts at 0) */
uint64_t part_start; /* current part start address (relative to the whole volume) */
uint32_t num_parts; /* number of parts WRITTEN on the DVD */
+ /* state ST_FREESPACE_OK is set if free_space is valid */
uint64_t free_space; /* current free space on medium (without the current part) */
- int free_space_errno; /* indicates:
- * - free_space_errno == 0: ignore free_space.
- * - free_space_errno < 0: an error occured.
- * - free_space_errno > 0: free_space is valid. */
+ int free_space_errno; /* indicates errno getting freespace */
bool truncating; /* if set, we are currently truncating the DVD */
int at_eot() const { return state & ST_EOT; }
int at_weot() const { return state & ST_WEOT; }
int can_append() const { return state & ST_APPEND; }
+ int is_freespace_ok() const { return state & ST_FREESPACE_OK; }
/*
* can_write() is meant for checking at the end of a job to see
* if we still have a tape (perhaps not if at end of tape
void set_mounted() { state |= ST_MOUNTED; };
void set_media() { state |= ST_MEDIA; };
void set_short_block() { state |= ST_SHORT; };
+ void set_freespace_ok() { state |= ST_FREESPACE_OK; }
void set_part_spooled(int val) { if (val) state |= ST_PART_SPOOLED; \
else state &= ~ST_PART_SPOOLED; };
void set_mounted(int val) { if (val) state |= ST_MOUNTED; \
void clear_mounted() { state &= ~ST_MOUNTED; };
void clear_media() { state &= ~ST_MEDIA; };
void clear_short_block() { state &= ~ST_SHORT; };
+ void clear_freespace_ok() { state &= ~ST_FREESPACE_OK; }
void block(int why); /* in dev.c */
void unblock(); /* in dev.c */
if (!icmd) {
dev->free_space = 0;
dev->free_space_errno = 0;
+ dev->clear_freespace_ok(); /* No valid freespace */
dev->clear_media();
- Dmsg2(29, "update_free_space_dev: free_space=%d, free_space_errno=%d (!icmd)\n", dev->free_space, dev->free_space_errno);
+ Dmsg2(29, "update_free_space_dev: free_space=%s, free_space_errno=%d (!icmd)\n",
+ edit_uint64(dev->free_space, ed1), dev->free_space_errno);
return;
}
free = str_to_int64(results);
if (free >= 0) {
dev->free_space = free;
- dev->free_space_errno = 1;
+ dev->free_space_errno = 0;
+ dev->set_freespace_ok(); /* have valid freespace */
dev->set_media();
Mmsg0(dev->errmsg, "");
break;
}
}
dev->free_space = 0;
- dev->free_space_errno = -EPIPE;
+ dev->free_space_errno = EPIPE;
+ dev->clear_freespace_ok(); /* no valid freespace */
Mmsg1(dev->errmsg, _("Cannot run free space command (%s)\n"), results);
if (--timeout > 0) {
continue;
}
- dev->dev_errno = -dev->free_space_errno;
+ dev->dev_errno = dev->free_space_errno;
Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
"free_space_errno=%d ERR=%s\n",
dev->print_name(), edit_uint64(dev->free_space, ed1),
}
free_pool_memory(results);
- Dmsg3(29, "update_free_space_dev: free_space=%s, free_space_errno=%d have_media=%d\n",
- edit_uint64(dev->free_space, ed1), dev->free_space_errno, dev->have_media());
+ Dmsg4(29, "update_free_space_dev: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n",
+ edit_uint64(dev->free_space, ed1), !!dev->is_freespace_ok(), dev->free_space_errno, !!dev->have_media());
sm_check(__FILE__, __LINE__, false);
return;
}
{
DCR *dcr;
off_t pos;
+ char ed1[50], ed2[50];
Dmsg3(100, "Enter lseek_dev fd=%d part=%d nparts=%d\n", dev->fd,
dev->part, dev->num_parts);
dcr = (DCR *)dev->attached_dcrs->first(); /* any dcr will do */
switch(whence) {
case SEEK_SET:
- Dmsg2(100, "lseek_dev SEEK_SET to %d (part_start=%d)\n", (int)offset, (int)dev->part_start);
+ Dmsg2(100, "lseek_dev SEEK_SET to %s (part_start=%s)\n",
+ edit_uint64(offset, ed1), edit_uint64(dev->part_start, ed2));
if ((uint64_t)offset >= dev->part_start) {
if (((uint64_t)offset == dev->part_start) || ((uint64_t)offset < (dev->part_start+dev->part_size))) {
/* We are staying in the current part, just seek */
}
break;
case SEEK_CUR:
- Dmsg1(100, "lseek_dev SEEK_CUR to %d\n", (int)offset);
+ Dmsg1(100, "lseek_dev SEEK_CUR to %s\n", edit_uint64(offset, ed1));
if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) {
return pos;
}
pos += dev->part_start;
if (offset == 0) {
- Dmsg1(100, "lseek_dev SEEK_CUR returns %d\n", pos);
+ Dmsg1(100, "lseek_dev SEEK_CUR returns %s\n", edit_uint64(pos, ed1));
return pos;
} else { /* Not used in Bacula, but should work */
return lseek_dev(dev, pos, SEEK_SET);
}
break;
case SEEK_END:
- Dmsg1(100, "lseek_dev SEEK_END to %d\n", (int)offset);
+ Dmsg1(100, "lseek_dev SEEK_END to %s\n", edit_uint64(offset, ed1));
/*
* Bacula does not use offsets for SEEK_END
* Also, Bacula uses seek_end only when it wants to
* itself is read-only (as currently implemented).
*/
if (offset > 0) { /* Not used by bacula */
- Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %d\n", (int)offset);
+ Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %s\n",
+ edit_uint64(offset, ed1));
errno = EINVAL;
return -1;
}
if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
return pos;
} else {
- Dmsg1(100, "lseek_dev SEEK_END returns %d\n", pos + dev->part_start);
+ Dmsg1(100, "lseek_dev SEEK_END returns %s\n",
+ edit_uint64(pos + dev->part_start, ed1));
return pos + dev->part_start;
}
} else {
* %% = %
* %a = archive device name
* %e = erase (set if cannot mount and first part)
+ * %n = part number
* %m = mount point
* %v = last part name
*
str = dev->dev_name;
break;
case 'e':
- if (dev->part == 0) {
+ if (dev->num_parts == 0) {
str = "1";
} else {
str = "0";
struct date_time dt;
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
+ char buf[100];
/* Serialize the label into the device record. */
rec->VolSessionId = jcr->VolSessionId;
rec->VolSessionTime = jcr->VolSessionTime;
rec->Stream = jcr->NumVolumes;
- Dmsg2(100, "Created Vol label rec: FI=%s len=%d\n", FI_to_ascii(rec->FileIndex),
+ Dmsg2(100, "Created Vol label rec: FI=%s len=%d\n", FI_to_ascii(buf, rec->FileIndex),
rec->data_len);
}
DEVICE *dev = dcr->dev;
DEV_RECORD *rec;
DEV_BLOCK *block = dcr->block;
+ char buf1[100], buf2[100];
rec = new_record();
Dmsg1(90, "session_label record=%x\n", rec);
Dmsg6(20, "Write sesson_label record JobId=%d FI=%s SessId=%d Strm=%s len=%d "
"remainder=%d\n", jcr->JobId,
- FI_to_ascii(rec->FileIndex), rec->VolSessionId,
- stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len,
+ FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
+ stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
rec->remainder);
free_record(rec);
bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec)
{
ser_declare;
+ char buf1[100], buf2[100];
if (rec->FileIndex != VOL_LABEL && rec->FileIndex != PRE_LABEL) {
Mmsg3(dev->errmsg, _("Expecting Volume Label, got FI=%s Stream=%s len=%d\n"),
- FI_to_ascii(rec->FileIndex),
- stream_to_ascii(rec->Stream, rec->FileIndex),
+ FI_to_ascii(buf1, rec->FileIndex),
+ stream_to_ascii(buf2, rec->Stream, rec->FileIndex),
rec->data_len);
if (!forge_on) {
return false;
void create_restore_volume_list(JCR *jcr);
/* From record.c */
-const char *FI_to_ascii(int fi);
-const char *stream_to_ascii(int stream, int fi);
+const char *FI_to_ascii(char *buf, int fi);
+const char *stream_to_ascii(char *buf, int stream, int fi);
bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
* record as a Label, otherwise it is simply
* the FileIndex of the current file.
*/
-const char *FI_to_ascii(int fi)
+const char *FI_to_ascii(char *buf, int fi)
{
- static char buf[20];
if (fi >= 0) {
sprintf(buf, "%d", fi);
return buf;
* dealing with a Label, hence the
* stream is the JobId.
*/
-const char *stream_to_ascii(int stream, int fi)
+const char *stream_to_ascii(char *buf, int stream, int fi)
{
- static char buf[20];
if (fi < 0) {
sprintf(buf, "%d", stream);
return buf;
{
ser_declare;
uint32_t remlen;
+ char buf1[100], buf2[100];
remlen = block->buf_len - block->binbuf;
Dmsg6(890, "write_record_to_block() FI=%s SessId=%d Strm=%s len=%d\n"
"rem=%d remainder=%d\n",
- FI_to_ascii(rec->FileIndex), rec->VolSessionId,
- stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len,
+ FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
+ stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
remlen, rec->remainder);
/*
/* We damaged a buffer */
Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n"
"rem=%d remainder=%d\n",
- FI_to_ascii(rec->FileIndex), rec->VolSessionId,
- stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len,
+ FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
+ stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
remlen, rec->remainder);
Dmsg5(0, "Damaged block: bufp=%x binbuf=%d buf_len=%d rem=%d moved=%d\n",
block->bufp, block->binbuf, block->buf_len, block->buf_len-block->binbuf,
int32_t Stream;
uint32_t data_bytes;
uint32_t rhl;
+ char buf1[100], buf2[100];
remlen = block->binbuf;
rec->Block = block->BlockNumber;
Dmsg6(450, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%u\n"
"remlen=%d data_len=%d\n",
- FI_to_ascii(rec->FileIndex), rec->VolSessionId,
- stream_to_ascii(rec->Stream, rec->FileIndex), data_bytes, remlen,
+ FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
+ stream_to_ascii(buf2, rec->Stream, rec->FileIndex), data_bytes, remlen,
rec->data_len);
} else {
/*
}
rec->remainder = 0;
Dmsg4(450, "Rtn full rd_rec_blk FI=%s SessId=%d Strm=%s len=%d\n",
- FI_to_ascii(rec->FileIndex), rec->VolSessionId,
- stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len);
+ FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
+ stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);
return true; /* transferred full record */
}
#undef VERSION
#define VERSION "1.37.41"
-#define BDATE "12 October 2005"
-#define LSMDATE "12Oct05"
+#define BDATE "13 October 2005"
+#define LSMDATE "13Oct05"
/* Debug flags */
#undef DEBUG