unlock_reservations();
if (stat == 1) {
DCR *ndcr = jcr->read_dcr;
- dev->dunblock(dev_unlocked);
+ dev->dunblock(DEV_UNLOCKED);
detach_dcr_from_dev(dcr); /* release old device */
/* Copy important info from the new dcr */
dev = dcr->dev = ndcr->dev;
Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
dcr->reserved_device = false;
}
- dev->dunblock(dev_locked);
+ dev->dunblock(DEV_LOCKED);
Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
return ok;
}
Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
dcr->reserved_device = false;
}
- dev->dunblock(dev_locked);
+ dev->dunblock(DEV_LOCKED);
return dcr;
/*
Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
dcr->reserved_device = false;
}
- dev->dunblock(dev_locked);
+ dev->dunblock(DEV_LOCKED);
return NULL;
}
bool ok = true;
/* lock only if not already locked by this thread */
- if (!dcr->dev_locked) {
+ if (!dcr->is_dev_locked()) {
dev->r_dlock();
}
Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
return stat;
}
- if (!dcr->dev_locked) { /* device already locked? */
+ if (!dcr->is_dev_locked()) { /* device already locked? */
+ /* note, do not change this to dcr->r_dlock */
dev->r_dlock(); /* no, lock it */
}
}
bail_out:
- if (!dcr->dev_locked) { /* did we lock dev above? */
+ if (!dcr->is_dev_locked()) { /* did we lock dev above? */
+ /* note, do not change this to dcr->dunlock */
dev->dunlock(); /* unlock it now */
}
return stat;
bool spooling; /* set when actually spooling */
bool despooling; /* set when despooling */
bool despool_wait; /* waiting for despooling */
- bool dev_locked; /* set if dev already locked */
+ bool m_dev_locked; /* set if dev already locked */
bool NewVol; /* set if new Volume mounted */
bool WroteVol; /* set if Volume written */
bool NewFile; /* set when EOF written */
int Copy; /* identical copy number */
int Stripe; /* RAIT stripe */
VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */
+
+ /* Methods */
+ bool is_dev_locked() { return m_dev_locked; }
+ void dlock() { dev->dlock(); m_dev_locked = true; }
+ void dunlock() { dev->dunlock(); m_dev_locked = false;}
+ void dblock(int why) { dev->dblock(why); }
+
};
/*
char dt[MAX_TIME_LENGTH];
JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
+ int blocked = dev->blocked(); /* save any previous blocked status */
+ bool ok = false;
wait_time = time(NULL);
Dmsg0(100, "Enter fixup_device_block_write_error\n");
+ /*
+ * If we are blocked at entry, unblock it, and set our own block status
+ */
+ if (blocked != BST_NOT_BLOCKED) {
+ unblock_device(dev);
+ }
block_device(dev, BST_DOING_ACQUIRE);
- /* Unlock, but leave BLOCKED */
+
+ /* Continue unlocked, but leave BLOCKED */
dev->dunlock();
bstrncpy(PrevVolName, dev->VolCatInfo.VolCatName, sizeof(PrevVolName));
free_block(label_blk);
dcr->block = block;
dev->dlock();
- unblock_device(dev);
- return false; /* device locked */
+ goto bail_out;
}
dev->dlock(); /* lock again */
be.bstrerror(dev->dev_errno));
free_block(label_blk);
dcr->block = block;
- unblock_device(dev);
- return false; /* device locked */
+ goto bail_out;
}
free_block(label_blk);
dcr->block = block;
berrno be;
Pmsg1(0, _("write_block_to_device overflow block failed. ERR=%s"),
be.bstrerror(dev->dev_errno));
- unblock_device(dev);
- return false; /* device locked */
+ goto bail_out;
}
+ ok = true;
+bail_out:
+ /*
+ * At this point, the device is locked and blocked.
+ * Unblock the device, restore any entry blocked condition, then
+ * return leaving the device locked (as it was on entry).
+ */
unblock_device(dev);
- return true; /* device locked */
+ if (blocked != BST_NOT_BLOCKED) {
+ block_device(dev, blocked);
+ }
+ return ok; /* device locked */
}
/*
* Used in unblock() call
*/
enum {
- dev_locked = true,
- dev_unlocked = false
+ DEV_LOCKED = true,
+ DEV_UNLOCKED = false
};
#endif
}
dcr->despool_wait = true;
dcr->spooling = false;
- dcr->dev->r_dlock();
+ /*
+ * We work with device blocked, but not locked so that
+ * other threads -- e.g. reservations can lock the device
+ * structure.
+ */
+ dcr->dblock(BST_DESPOOLING);
dcr->despool_wait = false;
dcr->despooling = true;
- dcr->dev_locked = true;
/*
* This is really quite kludgy and should be fixed some time.
free(rdev);
dcr->spooling = true; /* turn on spooling again */
dcr->despooling = false;
+ /*
+ * We are done, so unblock the device, but if we have done a
+ * commit, leave it locked so that the job cleanup does not
+ * need to wait to release the device (no re-acquire of the lock).
+ */
+ dcr->dlock();
+ unblock_device(dcr->dev);
/* If doing a commit, leave the device locked -- unlocked in release_device() */
if (!commit) {
- dcr->dev_locked = false;
- dcr->dev->dunlock();
+ dcr->dunlock();
}
return ok;
}
#undef VERSION
#define VERSION "2.1.23"
-#define BDATE "28 June 2007"
-#define LSMDATE "28Jun07"
+#define BDATE "29 June 2007"
+#define LSMDATE "29Jun07"
#define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
#define BYEAR "2007" /* year for copyright messages in progs */
Technical notes on version 2.1
General:
-
+29Jun07
+kes Implement new BST_DESPOOLING blocked state. Change from locking
+ during despooling in SD to blocking. This means that other threads
+ can work with the device structure, in particular the reservations
+ system while despooling.
+28Jun07
+kes Fix return in reservation message queue that missed clearing
+ the jcr lock (implemented 26Jun07 below).
+kes Rename a number of dev methods to make locking function names
+ a bit clearer.
+kes Document locking in lock.c. Move lock structures to new file
+ lock.h.
26Jun07
kes Move reservations message lock to lock jcr only this
fixes bug #861.