From 9f8c89965e9f2d7e4fb55e9fd79a2aa83b85c985 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sun, 25 Aug 2002 21:50:28 +0000 Subject: [PATCH] First cut new SD lock + restore buffer bug fix git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@121 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/cats/bdb.c | 13 +-- bacula/src/cats/mysql.c | 7 +- bacula/src/cats/sqlite.c | 6 +- bacula/src/dird/restore.c | 6 +- bacula/src/dird/ua_restore.c | 16 ++- bacula/src/lib/bnet.c | 22 ++++- bacula/src/lib/bnet_server.c | 4 +- bacula/src/lib/cram-md5.c | 3 +- bacula/src/lib/mem_pool.c | 4 + bacula/src/lib/message.c | 3 +- bacula/src/lib/rwlock.h | 6 ++ bacula/src/stored/acquire.c | 20 ++++ bacula/src/stored/authenticate.c | 6 +- bacula/src/stored/block.c | 4 + bacula/src/stored/bls.c | 2 +- bacula/src/stored/dev.c | 10 +- bacula/src/stored/dev.h | 7 ++ bacula/src/stored/device.c | 88 ++++++++++++++++- bacula/src/stored/dircmd.c | 23 ++++- bacula/src/stored/job.c | 1 + bacula/src/stored/parse_bsr.c | 3 + bacula/src/stored/protos.h | 163 ++++++++++++++++--------------- bacula/src/stored/read.c | 6 +- bacula/src/stored/record.c | 4 +- 24 files changed, 309 insertions(+), 118 deletions(-) diff --git a/bacula/src/cats/bdb.c b/bacula/src/cats/bdb.c index dea6aff127..c19fdc5b79 100644 --- a/bacula/src/cats/bdb.c +++ b/bacula/src/cats/bdb.c @@ -142,13 +142,14 @@ db_open_database(B_DB *mdb) char *dbf; int fd, badctl; off_t filend; + int errstat; Dmsg1(200, "db_open_database() %s\n", mdb->db_name); P(mutex); - if (rwl_init(&mdb->lock) != 0) { - Mmsg1(&mdb->errmsg, "Unable to initialize DB lock. ERR=%s\n", strerror(errno)); + if ((errstat=rwl_init(&mdb->lock)) != 0) { + Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), strerror(errstat)); V(mutex); return 0; } @@ -158,7 +159,7 @@ db_open_database(B_DB *mdb) mdb->cfd = open(dbf, O_CREAT|O_RDWR, 0600); free_memory(dbf); if (mdb->cfd < 0) { - Mmsg2(&mdb->errmsg, "Unable to open Catalog DB control file %s: ERR=%s\n", + Mmsg2(&mdb->errmsg, _("Unable to open Catalog DB control file %s: ERR=%s\n"), dbf, strerror(errno)); V(mutex); return 0; @@ -213,12 +214,12 @@ db_open_database(B_DB *mdb) badctl = 0; lseek(mdb->cfd, 0, SEEK_SET); /* seek to begining of control file */ if (read(mdb->cfd, &mdb->control, sizeof(mdb->control)) != sizeof(mdb->control)) { - Mmsg1(&mdb->errmsg, "Error reading catalog DB control file. ERR=%s\n", strerror(errno)); + Mmsg1(&mdb->errmsg, _("Error reading catalog DB control file. ERR=%s\n"), strerror(errno)); badctl = 1; } else if (mdb->control.bdb_version != BDB_VERSION) { - Mmsg2(&mdb->errmsg, "Error, catalog DB control file wrong version. \ + Mmsg2(&mdb->errmsg, _("Error, catalog DB control file wrong version. \ Wanted %d, got %d\n\ -Please reinitialize the working directory.\n", +Please reinitialize the working directory.\n"), BDB_VERSION, mdb->control.bdb_version); badctl = 1; } diff --git a/bacula/src/cats/mysql.c b/bacula/src/cats/mysql.c index 89539ccc64..b4f139f65b 100644 --- a/bacula/src/cats/mysql.c +++ b/bacula/src/cats/mysql.c @@ -96,6 +96,8 @@ db_init_database(void *jcr, char *db_name, char *db_user, char *db_password) int db_open_database(B_DB *mdb) { + int errstat; + P(mutex); if (mdb->connected) { V(mutex); @@ -103,8 +105,9 @@ db_open_database(B_DB *mdb) } mdb->connected = FALSE; - if (rwl_init(&mdb->lock) != 0) { - Mmsg1(&mdb->errmsg, "Unable to initialize DB lock. ERR=%s\n", strerror(errno)); + if ((errstat=rwl_init(&mdb->lock)) != 0) { + Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), + strerror(errstat)); V(mutex); return 0; } diff --git a/bacula/src/cats/sqlite.c b/bacula/src/cats/sqlite.c index 4628f698c8..1e9781906e 100644 --- a/bacula/src/cats/sqlite.c +++ b/bacula/src/cats/sqlite.c @@ -100,6 +100,7 @@ db_open_database(B_DB *mdb) char *db_name; int len; struct stat statbuf; + int errstat; P(mutex); if (mdb->connected) { @@ -108,8 +109,9 @@ db_open_database(B_DB *mdb) } mdb->connected = FALSE; - if (rwl_init(&mdb->lock) != 0) { - Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), strerror(errno)); + if ((errstat=rwl_init(&mdb->lock)) != 0) { + Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), + strerror(errstat)); V(mutex); return 0; } diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index 1cae3457ca..8414843c52 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -69,7 +69,6 @@ static int send_bootstrap_file(JCR *jcr); */ int do_restore(JCR *jcr) { - char dt[MAX_TIME_LENGTH]; BSOCK *fd; JOB_DBR rjr; /* restore job record */ int ok = FALSE; @@ -129,10 +128,7 @@ int do_restore(JCR *jcr) /* Print Job Start message */ - bstrftime(dt, sizeof(dt), jcr->start_time); - Jmsg(jcr, M_INFO, 0, _("%s Start Restore Job %s Name=%s, Client=%s, FileSet=%s\n"), - dt, jcr->Job, jcr->job->hdr.name, jcr->client->hdr.name, - jcr->fileset->hdr.name); + Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job); /* * Open a message channel connection with the Storage diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index 97104ebe64..be073043d2 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -225,7 +225,11 @@ int restorecmd(UAContext *ua, char *cmd) free_tree(tree.root); /* free the directory tree */ if (bsr->JobId) { - complete_bsr(ua, bsr); /* find Vol, SessId, SessTime from JobIds */ + if (!complete_bsr(ua, bsr)) { /* find Vol, SessId, SessTime from JobIds */ + bsendmsg(ua, _("Unable to construct a valid BSR. Cannot continue.\n")); + free_bsr(bsr); + return 0; + } // print_bsr(ua, bsr); write_bsr_file(ua, bsr); } else { @@ -1117,7 +1121,9 @@ static void free_name_list(NAME_LIST *name_list) for (i=0; i < name_list->num_ids; i++) { free(name_list->name[i]); } - free(name_list->name); + if (name_list->name) { + free(name_list->name); + } name_list->max_ids = 0; name_list->num_ids = 0; } @@ -1135,6 +1141,12 @@ static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, JobI return; } + if (name_list->num_ids == 0) { + bsendmsg(ua, _("No MediaType found for your JobIds.\n")); + ji->store = select_storage_resource(ua); + return; + } + start_prompt(ua, _("The defined Storage resources are:\n")); LockRes(); while ((store = (STORE *)GetNextRes(R_STORAGE, (RES *)store))) { diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 670bdd4d5a..48aa1ee650 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -657,10 +657,24 @@ bnet_close(BSOCK *bsock) void term_bsock(BSOCK *bsock) { - free_pool_memory(bsock->msg); - free_pool_memory(bsock->errmsg); - free(bsock->who); - free(bsock->host); + if (bsock->msg) { + free_pool_memory(bsock->msg); + bsock->msg = NULL; + } else { + ASSERT(1=0); /* double close */ + } + if (bsock->errmsg) { + free_pool_memory(bsock->errmsg); + bsock->errmsg = NULL; + } + if (bsock->who) { + free(bsock->who); + bsock->who = NULL; + } + if (bsock->host) { + free(bsock->host); + bsock->host = NULL; + } free(bsock); } diff --git a/bacula/src/lib/bnet_server.c b/bacula/src/lib/bnet_server.c index 1c2150226e..0b9f6ebee2 100644 --- a/bacula/src/lib/bnet_server.c +++ b/bacula/src/lib/bnet_server.c @@ -201,7 +201,7 @@ bnet_bind(int port) sleep(5); } listen(sockfd, 1); /* tell system we are ready */ - return init_bsock(sockfd, _("Server socket"), _("client"), port); + return init_bsock(NULL, sockfd, _("Server socket"), _("client"), port); } /* @@ -290,7 +290,7 @@ bnet_accept(BSOCK *bsock, char *who) strcpy(buf, who); strcat(buf, ": "); strcat(buf, caller); - bs = init_bsock(newsockfd, "client", buf, bsock->port); + bs = init_bsock(NULL, newsockfd, "client", buf, bsock->port); free(buf); return bs; /* return new BSOCK */ } diff --git a/bacula/src/lib/cram-md5.c b/bacula/src/lib/cram-md5.c index f1658044e9..f40b35dfff 100644 --- a/bacula/src/lib/cram-md5.c +++ b/bacula/src/lib/cram-md5.c @@ -57,7 +57,7 @@ int cram_md5_auth(BSOCK *bs, char *password) bin_to_base64(host, (char *)hmac, 16); ok = strcmp(bs->msg, host) == 0; if (ok) { - Dmsg3(399, "Authenticate %s: wanted %s, got %s\n", + Dmsg3(99, "Authenticate %s: wanted %s, got %s\n", ok ? "OK" : "NOT OK", host, bs->msg); } else { Dmsg3(99, "Authenticate %s: wanted %s, got %s\n", @@ -82,6 +82,7 @@ int cram_md5_get_auth(BSOCK *bs, char *password) return 0; } if (sscanf(bs->msg, "auth cram-md5 %s", chal) != 1) { + Dmsg1(99, "Wanted auth cram... Got: %s\n", bs->msg); sleep(5); return 0; } diff --git a/bacula/src/lib/mem_pool.c b/bacula/src/lib/mem_pool.c index 9eddd47ad1..2af3a7b8b6 100644 --- a/bacula/src/lib/mem_pool.c +++ b/bacula/src/lib/mem_pool.c @@ -195,6 +195,10 @@ void free_pool_memory(POOLMEM *obuf) if (pool == 0) { free((char *)buf); /* free nonpooled memory */ } else { /* otherwise link it to the free pool chain */ + struct abufhead *next; + for (next=pool_ctl[pool].free_buf; next; next=next->next) { + ASSERT(next != buf); /* attempt to free twice */ + } buf->next = pool_ctl[pool].free_buf; pool_ctl[pool].free_buf = buf; } diff --git a/bacula/src/lib/message.c b/bacula/src/lib/message.c index 003b76a0a4..09d58ec275 100755 --- a/bacula/src/lib/message.c +++ b/bacula/src/lib/message.c @@ -461,7 +461,7 @@ void close_msg(void *vjcr) if (msgs == NULL) { return; } - Dmsg1(050, "close msg resource at 0x%x\n", msgs); + Dmsg1(150, "begin close msg resource at 0x%x\n", msgs); cmd = get_pool_memory(PM_MESSAGE); for (d=msgs->dest_chain; d; ) { if (d->fd) { @@ -521,6 +521,7 @@ rem_temp_file: free_msgs_res(msgs); msgs = NULL; + Dmsg0(150, "end close msg resource\n"); } /* diff --git a/bacula/src/lib/rwlock.h b/bacula/src/lib/rwlock.h index 6e2a594238..4b7ca78852 100644 --- a/bacula/src/lib/rwlock.h +++ b/bacula/src/lib/rwlock.h @@ -45,6 +45,12 @@ typedef struct s_rwlock_tag { int w_wait; /* writers waiting */ } brwlock_t; +typedef struct s_rwsteal_tag { + pthread_t writer_id; /* writer's thread id */ + int state; +} brwsteal_t; + + #define RWLOCK_VALID 0xfacade #define RWL_INIIALIZER \ diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 8ec4bb3766..9c39b0391f 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -41,9 +41,11 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) { int stat; + new_lock_device_state(dev, BST_DOING_ACQUIRE); lock_device(dev); if (dev->state & ST_READ || dev->num_writers > 0) { Jmsg(jcr, M_FATAL, 0, _("Device %s is busy.\n"), dev_name(dev)); + new_unlock_device(dev); unlock_device(dev); return 0; } @@ -51,9 +53,12 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) block_device(dev, BST_DOING_ACQUIRE); unlock_device(dev); stat = ready_dev_for_read(jcr, dev, block); +#ifndef NEW_LOCK P(dev->mutex); unblock_device(dev); V(dev->mutex); +#endif + new_unlock_device(dev); return stat; } @@ -69,6 +74,7 @@ int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) int release = 0; int do_mount = 0; + new_lock_device_state(dev, BST_DOING_ACQUIRE); lock_device(dev); Dmsg1(190, "acquire_append device is %s\n", dev_is_tape(dev)?"tape":"disk"); @@ -91,6 +97,7 @@ int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (dev->num_writers != 0) { Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing with another Volume.\n"), dev_name(dev)); unlock_device(dev); + new_unlock_device(dev); return 0; } /* Wrong tape mounted, release it, then fall through to get correct one */ @@ -102,6 +109,7 @@ int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (dev->state & ST_READ) { Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev)); unlock_device(dev); + new_unlock_device(dev); return 0; } ASSERT(dev->num_writers == 0); @@ -114,13 +122,18 @@ int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (!mount_next_write_volume(jcr, dev, block, release)) { Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"), dev_name(dev)); +#ifndef NEW_LOCK P(dev->mutex); unblock_device(dev); unlock_device(dev); +#endif + new_unlock_device(dev); return 0; } +#ifndef NEW_LOCK P(dev->mutex); unblock_device(dev); +#endif } dev->num_writers++; @@ -133,6 +146,7 @@ int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) } attach_jcr_to_device(dev, jcr); /* attach jcr to device */ unlock_device(dev); + new_unlock_device(dev); return 1; /* got it */ } @@ -143,7 +157,10 @@ int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) */ int release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) { +#ifndef NEW_LOCK P(dev->mutex); +#endif + new_lock_device(dev); Dmsg1(100, "release_device device is %s\n", dev_is_tape(dev)?"tape":"disk"); if (dev->state & ST_READ) { dev->state &= ~ST_READ; /* clear read bit */ @@ -183,7 +200,10 @@ int release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) Jmsg1(jcr, M_ERROR, 0, _("BAD ERROR: release_device %s not in use.\n"), dev_name(dev)); } detach_jcr_from_device(dev, jcr); +#ifndef NEW_LOCK V(dev->mutex); +#endif + new_unlock_device(dev); return 1; } diff --git a/bacula/src/stored/authenticate.c b/bacula/src/stored/authenticate.c index be18fb9ca0..1709705960 100644 --- a/bacula/src/stored/authenticate.c +++ b/bacula/src/stored/authenticate.c @@ -39,15 +39,15 @@ static char OK_hello[] = "3000 OK Hello\n"; */ static int authenticate(int rcode, BSOCK *bs) { - char *name; + POOLMEM *name; DIRRES *director = NULL; if (rcode != R_DIRECTOR) { Emsg1(M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode); return 0; } - name = (char *) get_pool_memory(PM_MESSAGE); - name = (char *) check_pool_memory_size(name, bs->msglen); + name = get_pool_memory(PM_MESSAGE); + name = check_pool_memory_size(name, bs->msglen); if (sscanf(bs->msg, "Hello Director %127s calling\n", name) != 1) { Emsg1(M_FATAL, 0, _("Bad Hello command from Director: %s\n"), bs->msg); diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index 22ad24def5..312c3ab65b 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -240,10 +240,12 @@ static int unser_block_header(DEVICE *dev, DEV_BLOCK *block) int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) { int stat = 1; + new_lock_device(dev); lock_device(dev); if (!write_block_to_dev(dev, block)) { stat = fixup_device_block_write_error(jcr, dev, block); } + new_unlock_device(dev); unlock_device(dev); return stat; } @@ -368,8 +370,10 @@ int read_block_from_device(DEVICE *dev, DEV_BLOCK *block) { int stat; Dmsg0(90, "Enter read_block_from_device\n"); + new_lock_device(dev); lock_device(dev); stat = read_block_from_dev(dev, block); + new_unlock_device(dev); unlock_device(dev); Dmsg0(90, "Leave read_block_from_device\n"); return stat; diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index b2db38f144..63fef7f34c 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -270,7 +270,7 @@ static void do_setup(char *infname) } pm_strcpy(&jcr->VolumeName, VolName); - Dmsg1(000, "Volume=%s\n", jcr->VolumeName); + Dmsg1(100, "Volume=%s\n", jcr->VolumeName); if (!acquire_device_for_read(jcr, dev, block)) { Emsg0(M_ERROR, 0, dev->errmsg); exit(1); diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 4f5773f2b0..7882e678b7 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -138,12 +138,17 @@ init_dev(DEVICE *dev, char *dev_name) if (tape) { dev->state |= ST_TAPE; } - dev->dev_name = (char *) get_memory(strlen(dev_name)+1); + dev->dev_name = get_memory(strlen(dev_name)+1); strcpy(dev->dev_name, dev_name); - dev->errmsg = (char *) get_pool_memory(PM_EMSG); + dev->errmsg = get_pool_memory(PM_EMSG); *dev->errmsg = 0; + if ((errstat=rwl_init(&dev->lock)) != 0) { + Mmsg1(&dev->errmsg, _("Unable to initialize dev lock. ERR=%s\n"), strerror(errstat)); + Emsg0(M_FATAL, 0, dev->errmsg); + } + if ((errstat = pthread_mutex_init(&dev->mutex, NULL)) != 0) { dev->dev_errno = errstat; Mmsg1(&dev->errmsg, _("Unable to init mutex: ERR=%s\n"), strerror(errstat)); @@ -1068,6 +1073,7 @@ term_dev(DEVICE *dev) free_pool_memory(dev->errmsg); dev->errmsg = NULL; } + rwl_destroy(&dev->lock); pthread_mutex_destroy(&dev->mutex); pthread_cond_destroy(&dev->wait); pthread_cond_destroy(&dev->wait_next_vol); diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 908ea0201d..a6c263ab18 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -29,6 +29,12 @@ #ifndef __DEV_H #define __DEV_H 1 +/* #define NEW_LOCK 1 */ + +#define new_lock_device(dev) _lock_device(__FILE__, __LINE__, (dev)) +#define new_lock_device_state(dev,state) _lock_device(__FILE__, __LINE__, (dev), (state)) +#define new_unlock_device(dev) _unlock_device(__FILE__, __LINE__, (dev)) + /* Arguments to open_dev() */ #define READ_WRITE 0 #define READ_ONLY 1 @@ -108,6 +114,7 @@ typedef struct s_volume_catalog_info { typedef struct s_device { struct s_device *next; /* pointer to next open device */ void *attached_jcrs; /* attached JCR list */ + brwlock_t lock; /* new device locking mechanism */ pthread_mutex_t mutex; /* access control */ pthread_cond_t wait; /* thread wait variable */ pthread_cond_t wait_next_vol; /* wait for tape to be mounted */ diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index 4f21e2fdb6..24adab2ebe 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -82,6 +82,7 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (stat & MT_EOD) { Dmsg0(190, "======= Got EOD ========\n"); + new_lock_device_state(dev, BST_DOING_ACQUIRE); block_device(dev, BST_DOING_ACQUIRE); /* @@ -105,6 +106,7 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (!dir_update_volume_info(jcr, &dev->VolCatInfo, 0)) { /* send Volume info to Director */ Jmsg(jcr, M_ERROR, 0, _("Could not update Volume info Volume=%s Job=%s\n"), dev->VolCatInfo.VolCatName, jcr->Job); + new_unlock_device(dev); return 0; /* device locked */ } Dmsg0(190, "Back from update_vol_info\n"); @@ -122,12 +124,16 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) /* Unlock, but leave BLOCKED */ unlock_device(dev); if (!mount_next_write_volume(jcr, dev, label_blk, 1)) { + new_unlock_device(dev); +#ifndef NEW_LOCK P(dev->mutex); +#endif unblock_device(dev); return 0; /* device locked */ } - +#ifndef NEW_LOCK P(dev->mutex); /* lock again */ +#endif Jmsg(jcr, M_INFO, 0, _("New volume %s mounted on device %s\n"), jcr->VolumeName, dev_name(dev)); @@ -143,6 +149,7 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) Pmsg1(0, "write_block_to_device Volume label failed. ERR=%s", strerror_dev(dev)); free_block(label_blk); + new_unlock_device(dev); unblock_device(dev); return 0; /* device locked */ } @@ -153,6 +160,7 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) Pmsg1(0, "write_block_to_device overflow block failed. ERR=%s", strerror_dev(dev)); free_block(label_blk); + new_unlock_device(dev); unblock_device(dev); return 0; /* device locked */ } @@ -167,12 +175,14 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) mjcr->VolFirstFile = mjcr->JobFiles; mjcr->run_time += time(NULL) - wait_time; /* correct run time */ } + new_unlock_device(dev); unblock_device(dev); return 1; /* device locked */ } if (label_blk) { free_block(label_blk); } + new_unlock_device(dev); return 0; /* device locked */ } @@ -198,11 +208,13 @@ int open_device(DEVICE *dev) return 0; } + new_lock_device(dev); lock_device(dev); /* Defer opening files */ if (!dev_is_tape(dev)) { Dmsg0(129, "Device is file, deferring open.\n"); + new_unlock_device(dev); unlock_device(dev); return 1; } @@ -211,17 +223,18 @@ int open_device(DEVICE *dev) Dmsg0(129, "Opening device.\n"); if (open_dev(dev, NULL, READ_WRITE) < 0) { Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg); + new_unlock_device(dev); unlock_device(dev); return 0; } } Dmsg1(129, "open_dev %s OK\n", dev_name(dev)); + new_unlock_device(dev); unlock_device(dev); return 1; } - /* * When dev_blocked is set, all threads EXCEPT thread with id no_wait_id * must wait. The no_wait_id thread is out obtaining a new volume @@ -229,8 +242,8 @@ int open_device(DEVICE *dev) */ void lock_device(DEVICE *dev) { +#ifndef NEW_LOCK int stat; - Dmsg1(190, "lock %d\n", dev->dev_blocked); P(dev->mutex); if (dev->dev_blocked && !pthread_equal(dev->no_wait_id, pthread_self())) { @@ -244,12 +257,15 @@ void lock_device(DEVICE *dev) } dev->num_waiting--; /* no longer waiting */ } +#endif } void unlock_device(DEVICE *dev) { +#ifndef NEW_LOCK Dmsg0(190, "unlock\n"); V(dev->mutex); +#endif } /* @@ -262,10 +278,12 @@ void unlock_device(DEVICE *dev) */ void block_device(DEVICE *dev, int state) { +#ifndef NEW_LOCK Dmsg1(190, "block set %d\n", state); ASSERT(dev->dev_blocked == BST_NOT_BLOCKED); dev->dev_blocked = state; /* make other threads wait */ dev->no_wait_id = pthread_self(); /* allow us to continue */ +#endif } /* @@ -273,10 +291,74 @@ void block_device(DEVICE *dev, int state) */ void unblock_device(DEVICE *dev) { +#ifndef NEW_LOCK Dmsg1(190, "unblock %d\n", dev->dev_blocked); ASSERT(dev->dev_blocked); dev->dev_blocked = BST_NOT_BLOCKED; if (dev->num_waiting > 0) { pthread_cond_broadcast(&dev->wait); /* wake them up */ } +#endif +} + +/* + * New device locking scheme + */ +void _lock_device(char *file, int line, DEVICE *dev) +{ +#ifdef NEW_LOCK + int errstat; + if ((errstat=rwl_writelock(&dev->lock)) != 0) { + e_msg(file, line, M_ABORT, 0, "rwl_writelock failure. ERR=%s\n", + strerror(errstat)); + } +#endif +} + +void _lock_device(char *file, int line, DEVICE *dev, int state) +{ +#ifdef NEW_LOCK + int errstat; + if ((errstat=rwl_writelock(&dev->lock)) != 0) { + e_msg(file, line, M_ABORT, 0, "rwl_writelock failure. ERR=%s\n", + strerror(errstat)); + } + dev->dev_blocked = state; +#endif +} + +void _unlock_device(char *file, int line, DEVICE *dev) +{ +#ifdef NEW_LOCK + int errstat; + if (dev->lock.w_active == 1) { + dev->dev_blocked = BST_NOT_BLOCKED; + } + if ((errstat=rwl_writeunlock(&dev->lock)) != 0) { + e_msg(file, line, M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n", + strerror(errstat)); + } +#endif +} + +void new_steal_device_lock(DEVICE *dev, brwsteal_t *hold, int state) +{ +#ifdef NEW_LOCK + P(dev->lock.mutex); + hold->state = dev->dev_blocked; + hold->writer_id = dev->lock.writer_id; + dev->dev_blocked = state; + dev->lock.writer_id = pthread_self(); + V(dev->lock.mutex); +#endif +} + +void new_return_device_lock(DEVICE *dev, brwsteal_t *hold) +{ +#ifdef NEW_LOCK + P(dev->lock.mutex); + dev->dev_blocked = hold->state; + dev->lock.writer_id = hold->writer_id; + V(dev->lock.mutex); +#endif } diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 26bd3cbffa..759dd2fa2a 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -257,6 +257,7 @@ static int label_cmd(JCR *jcr) /******FIXME**** compare MediaTypes */ jcr->device = device; dev = device->dev; + P(dev->mutex); if (!(dev->state & ST_OPENED)) { if (open_dev(dev, volname, READ_WRITE) < 0) { @@ -306,15 +307,19 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolnam { BSOCK *dir = jcr->dir_bsock; DEV_BLOCK *block; + brwsteal_t hold; +#ifndef NEW_LOCK int blocked; pthread_t no_wait_id; blocked = dev->dev_blocked; /* save any prev blocked state */ - no_wait_id = dev->no_wait_id; dev->dev_blocked = BST_WRITING_LABEL; + no_wait_id = dev->no_wait_id; dev->no_wait_id = pthread_self(); /* let us use the tape */ - V(dev->mutex); /* release lock */ +#endif + new_steal_device_lock(dev, &hold, BST_WRITING_LABEL); + V(dev->mutex); strcpy(jcr->VolumeName, vname); block = new_block(dev); switch (read_dev_volume_label(jcr, dev, block)) { @@ -339,8 +344,11 @@ Unknown status %d from read_volume_label()\n"), jcr->label_status); } free_block(block); P(dev->mutex); + new_return_device_lock(dev, &hold); +#ifndef NEW_LOCK dev->dev_blocked = blocked; /* reset blocked state */ dev->no_wait_id = no_wait_id; /* reset blocking thread id */ +#endif } @@ -351,16 +359,20 @@ Unknown status %d from read_volume_label()\n"), jcr->label_status); */ static int read_label(JCR *jcr, DEVICE *dev) { + int stat; BSOCK *dir = jcr->dir_bsock; DEV_BLOCK *block; + brwsteal_t hold; +#ifndef NEW_LOCK int blocked; pthread_t no_wait_id; - int stat; blocked = dev->dev_blocked; /* save any prev blocked state */ no_wait_id = dev->no_wait_id; dev->dev_blocked = BST_DOING_ACQUIRE; dev->no_wait_id = pthread_self(); /* let us use the tape */ +#endif + new_steal_device_lock(dev, &hold, BST_DOING_ACQUIRE); V(dev->mutex); /* release lock */ jcr->VolumeName[0] = 0; @@ -379,8 +391,11 @@ static int read_label(JCR *jcr, DEVICE *dev) } free_block(block); P(dev->mutex); + new_return_device_lock(dev, &hold); +#ifndef NEW_LOCK dev->dev_blocked = blocked; /* reset blocked state */ dev->no_wait_id = no_wait_id; /* reset blocking thread id */ +#endif return stat; } @@ -436,6 +451,7 @@ static int mount_cmd(JCR *jcr) if (dev->dev_blocked == BST_UNMOUNTED) { Dmsg0(90, "Unmounted unblocking device\n"); read_label(jcr, dev); + new_unlock_device(dev); unblock_device(dev); } else { Dmsg0(90, "Unmounted waiting for mount attempt to wake thread\n"); @@ -571,6 +587,7 @@ static int unmount_cmd(JCR *jcr) } else { /* device not being used */ Dmsg0(90, "Device not in use, unmounting\n"); + new_lock_device_state(dev, BST_UNMOUNTED); block_device(dev, BST_UNMOUNTED); if (dev->capabilities & CAP_OFFLINEUNMOUNT) { offline_dev(dev); diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index 68aec7c356..1181641bed 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -308,6 +308,7 @@ void stored_free_jcr(JCR *jcr) { if (jcr->file_bsock) { bnet_close(jcr->file_bsock); + jcr->file_bsock = NULL; } if (jcr->pool_name) { free_memory(jcr->pool_name); diff --git a/bacula/src/stored/parse_bsr.c b/bacula/src/stored/parse_bsr.c index 7daab8c21c..ca141da4b9 100755 --- a/bacula/src/stored/parse_bsr.c +++ b/bacula/src/stored/parse_bsr.c @@ -698,6 +698,9 @@ void create_vol_list(JCR *jcr) jcr->CurVolume = 1; if (jcr->bsr) { BSR *bsr = jcr->bsr; + if (!bsr->volume || !bsr->volume->VolumeName) { + return; + } strcpy(jcr->VolumeName, bsr->volume->VolumeName); /* setup first volume */ for ( ; bsr; bsr=bsr->next) { BSR_VOLUME *bsrvol = bsr->volume; diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 62872c2005..c43d312de5 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -28,114 +28,119 @@ uint32_t new_VolSessionId(); /* From acquire.c */ -int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int ready_dev_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int ready_dev_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); /* From askdir.c */ -int dir_get_volume_info(JCR *jcr); -int dir_find_next_appendable_volume(JCR *jcr); -int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel); -int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev); -int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev); -int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec); -int dir_send_job_status(JCR *jcr); -int dir_create_jobmedia_record(JCR *jcr); +int dir_get_volume_info(JCR *jcr); +int dir_find_next_appendable_volume(JCR *jcr); +int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel); +int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev); +int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev); +int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec); +int dir_send_job_status(JCR *jcr); +int dir_create_jobmedia_record(JCR *jcr); /* authenticate.c */ -int authenticate_director(JCR *jcr); -int authenticate_filed(JCR *jcr); +int authenticate_director(JCR *jcr); +int authenticate_filed(JCR *jcr); /* From block.c */ -void dump_block(DEV_BLOCK *b, char *msg); +void dump_block(DEV_BLOCK *b, char *msg); DEV_BLOCK *new_block(DEVICE *dev); -void init_block_write(DEV_BLOCK *block); -void empty_block(DEV_BLOCK *block); -void free_block(DEV_BLOCK *block); -int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block); -int read_block_from_device(DEVICE *dev, DEV_BLOCK *block); -int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block); +void init_block_write(DEV_BLOCK *block); +void empty_block(DEV_BLOCK *block); +void free_block(DEV_BLOCK *block); +int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block); +int read_block_from_device(DEVICE *dev, DEV_BLOCK *block); +int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block); /* From dev.c */ -DEVICE *init_dev(DEVICE *dev, char *device); -int open_dev(DEVICE *dev, char *VolName, int mode); -void close_dev(DEVICE *dev); -void force_close_dev(DEVICE *dev); -int truncate_dev(DEVICE *dev); -void term_dev(DEVICE *dev); -char * strerror_dev(DEVICE *dev); -void clrerror_dev(DEVICE *dev, int func); -int update_pos_dev(DEVICE *dev); -int rewind_dev(DEVICE *dev); -int load_dev(DEVICE *dev); -int offline_dev(DEVICE *dev); -int flush_dev(DEVICE *dev); -int weof_dev(DEVICE *dev, int num); -int write_block(DEVICE *dev); -int write_dev(DEVICE *dev, char *buf, size_t len); -int read_dev(DEVICE *dev, char *buf, size_t len); -int status_dev(DEVICE *dev, uint32_t *status); -int eod_dev(DEVICE *dev); -int fsf_dev(DEVICE *dev, int num); -int fsr_dev(DEVICE *dev, int num); -int bsf_dev(DEVICE *dev, int num); -int bsr_dev(DEVICE *dev, int num); -void attach_jcr_to_device(DEVICE *dev, JCR *jcr); -void detach_jcr_from_device(DEVICE *dev, JCR *jcr); -JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); +DEVICE *init_dev(DEVICE *dev, char *device); +int open_dev(DEVICE *dev, char *VolName, int mode); +void close_dev(DEVICE *dev); +void force_close_dev(DEVICE *dev); +int truncate_dev(DEVICE *dev); +void term_dev(DEVICE *dev); +char * strerror_dev(DEVICE *dev); +void clrerror_dev(DEVICE *dev, int func); +int update_pos_dev(DEVICE *dev); +int rewind_dev(DEVICE *dev); +int load_dev(DEVICE *dev); +int offline_dev(DEVICE *dev); +int flush_dev(DEVICE *dev); +int weof_dev(DEVICE *dev, int num); +int write_block(DEVICE *dev); +int write_dev(DEVICE *dev, char *buf, size_t len); +int read_dev(DEVICE *dev, char *buf, size_t len); +int status_dev(DEVICE *dev, uint32_t *status); +int eod_dev(DEVICE *dev); +int fsf_dev(DEVICE *dev, int num); +int fsr_dev(DEVICE *dev, int num); +int bsf_dev(DEVICE *dev, int num); +int bsr_dev(DEVICE *dev, int num); +void attach_jcr_to_device(DEVICE *dev, JCR *jcr); +void detach_jcr_from_device(DEVICE *dev, JCR *jcr); +JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); /* Get info about device */ -char * dev_name(DEVICE *dev); -char * dev_vol_name(DEVICE *dev); +char * dev_name(DEVICE *dev); +char * dev_vol_name(DEVICE *dev); uint32_t dev_block(DEVICE *dev); uint32_t dev_file(DEVICE *dev); -int dev_is_tape(DEVICE *dev); +int dev_is_tape(DEVICE *dev); /* From device.c */ -int open_device(DEVICE *dev); -void block_device(DEVICE *dev, int state); -void unblock_device(DEVICE *dev); -void lock_device(DEVICE *dev); -void unlock_device(DEVICE *dev); -int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int open_device(DEVICE *dev); +void block_device(DEVICE *dev, int state); +void unblock_device(DEVICE *dev); +void lock_device(DEVICE *dev); +void unlock_device(DEVICE *dev); +int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void _lock_device(char *file, int line, DEVICE *dev); +void _lock_device(char *file, int line, DEVICE *dev, int state); +void _unlock_device(char *file, int line, DEVICE *dev); +void new_steal_device_lock(DEVICE *dev, brwsteal_t *hold, int state); +void new_return_device_lock(DEVICE *dev, brwsteal_t *hold); /* From dircmd.c */ -void connection_request(void *arg); +void connection_request(void *arg); /* From fd_cmds.c */ -void run_job(JCR *jcr); +void run_job(JCR *jcr); /* From fdmsg.c */ -int bget_msg(BSOCK *sock); +int bget_msg(BSOCK *sock); /* From job.c */ -void stored_free_jcr(JCR *jcr); -void connection_from_filed(void *arg); -void handle_filed_connection(BSOCK *fd, char *job_name); +void stored_free_jcr(JCR *jcr); +void connection_from_filed(void *arg); +void handle_filed_connection(BSOCK *fd, char *job_name); /* From label.c */ -int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void create_session_label(JCR *jcr, DEV_RECORD *rec, int label); -int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName); -int write_session_label(JCR *jcr, DEV_BLOCK *block, int label); -int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void dump_volume_label(DEVICE *dev); -void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); -int unser_volume_label(DEVICE *dev, DEV_RECORD *rec); -int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); +int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void create_session_label(JCR *jcr, DEV_RECORD *rec, int label); +int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName); +int write_session_label(JCR *jcr, DEV_BLOCK *block, int label); +int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void dump_volume_label(DEVICE *dev); +void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); +int unser_volume_label(DEVICE *dev, DEV_RECORD *rec); +int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); /* From match_bsr.c */ int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, - SESSION_LABEL *sesrec); + SESSION_LABEL *sesrec); /* From mount.c */ -int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release); -int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release); +int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); /* From parse_bsr.c */ @@ -150,8 +155,8 @@ extern void create_vol_list(JCR *jcr); /* From record.c */ char *FI_to_ascii(int fi); char *stream_to_ascii(int stream); -int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); +int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); DEV_RECORD *new_record(); -void free_record(DEV_RECORD *rec); +void free_record(DEV_RECORD *rec); diff --git a/bacula/src/stored/read.c b/bacula/src/stored/read.c index 5f9fdaa931..59851434f0 100644 --- a/bacula/src/stored/read.c +++ b/bacula/src/stored/read.c @@ -95,6 +95,7 @@ int do_read_data(JCR *jcr) } rec = new_record(); + free_pool_memory(rec->data); rec->data = ds->msg; /* use socket message buffer */ hdr = get_pool_memory(PM_MESSAGE); @@ -207,6 +208,7 @@ int do_read_data(JCR *jcr) if (!bnet_fsend(ds, rec_header, rec->VolSessionId, rec->VolSessionTime, rec->FileIndex, rec->Stream, rec->data_len)) { Dmsg1(30, ">filed: Error Hdr=%s\n", ds->msg); + hdr = ds->msg; ds->msg = rec->data; ok = FALSE; break; @@ -214,7 +216,8 @@ int do_read_data(JCR *jcr) Dmsg1(30, ">filed: Hdr=%s\n", ds->msg); } - ds->msg = rec->data; /* restore data record address */ + hdr = ds->msg; /* restore hdr buffer */ + ds->msg = rec->data; /* restore data record address */ /* Send data record to File daemon */ ds->msglen = rec->data_len; @@ -235,6 +238,7 @@ int do_read_data(JCR *jcr) } free_pool_memory(hdr); free_block(block); + rec->data = NULL; /* previously released */ free_record(rec); free_vol_list(jcr); Dmsg0(30, "Done reading.\n"); diff --git a/bacula/src/stored/record.c b/bacula/src/stored/record.c index 2183f49817..eebb5af25b 100644 --- a/bacula/src/stored/record.c +++ b/bacula/src/stored/record.c @@ -107,7 +107,9 @@ DEV_RECORD *new_record(void) void free_record(DEV_RECORD *rec) { Dmsg0(150, "Enter free_record.\n"); - free_pool_memory(rec->data); + if (rec->data) { + free_pool_memory(rec->data); + } Dmsg0(150, "Data buf is freed.\n"); free_pool_memory((POOLMEM *)rec); Dmsg0(150, "Leave free_record.\n"); -- 2.39.5