Attila,

The attached patch fix amstatus and amdump to report that the tape is write protected.

I do not have a tape drive on hand so I can't test it. I appreciate if someone can test it.

Jean-Louis

On 10/02/2012 08:46 AM, Attila Bogár wrote:
Hi Jean-Louis,

On 02/10/12 13:30, Jean-Louis Martineau wrote:
I'd refine the bug: amanda flushes to the write-protected tape, the dump is removed from the holding disk (of course it's not on tape), reports the dump were to Daily-24 and re-expects the same tape.


Amanda flushed nothing to the write-protected tape, it tried but it failed to write it.
The dump should have been left on holding disk.
It's hard to believe it removed the dump from holding disk? Can you prove it? Show that a dump was done (log file) and it is not on holding disk (ls)
Sorry - You are right, it did not dropped the data.

Somewhat confused me, that there was a very small delta between Sep 26 and Sep 27. I checked the reports thoroughly and it was almost all level 1, so I understand now.

Your bug definition is the correct one.


What is strange is that it didn't write to Daily-25, there might be a lot of reason.
Daily-25 wasn't loaded into any of the tape drives.
Daily-23 and Daily-24 was loaded.

-- APPENDIX BEGIN
Date    : September 24, 2012
*** A TAPE ERROR OCCURRED: [No acceptable volumes found].
There are 607419M of dumps left in the holding disk.
They will be flushed on the next run.
The next 2 tapes Amanda expects to use are: Daily-23, Daily-24.


diff --git a/device-src/device.c b/device-src/device.c
index 821f255..197858d 100644
--- a/device-src/device.c
+++ b/device-src/device.c
@@ -1558,6 +1558,20 @@ device_use_connection(
     }
 }
 
+gboolean
+device_check_writable(
+    Device *self)
+{
+    DeviceClass *klass;
+
+    klass = DEVICE_GET_CLASS(self);
+    if (klass->check_writable) {
+	return (klass->check_writable)(self);
+    } else {
+	return TRUE;
+    }
+}
+
 /* Property handling */
 
 void
diff --git a/device-src/device.h b/device-src/device.h
index 0945b0b..4beaf64 100644
--- a/device-src/device.h
+++ b/device-src/device.h
@@ -218,6 +218,7 @@ struct _DeviceClass {
     gboolean (* write_from_connection)(Device *self, guint64 size, guint64 *actual_size);
     gboolean (* read_to_connection)(Device *self, guint64 size, guint64 *actual_size);
     gboolean (* use_connection)(Device *self, DirectTCPConnection *conn);
+    gboolean (* check_writable)(Device *self);
 
     /* array of DeviceProperty objects for this class, keyed by ID */
     GArray *class_properties;
@@ -359,6 +360,7 @@ gboolean device_connect_with_cond(Device *self, gboolean for_writing,
 gboolean device_write_from_connection(Device *self, guint64 size, guint64 *actual_size);
 gboolean device_read_to_connection(Device *self, guint64 size, guint64 *actual_size);
 gboolean device_use_connection(Device *self, DirectTCPConnection *conn);
+gboolean device_check_writable(Device *self);
 
 /* Protected methods. Don't call these except in subclass implementations. */
 
diff --git a/device-src/tape-device.c b/device-src/tape-device.c
index c77a5b6..68ecfe7 100644
--- a/device-src/tape-device.c
+++ b/device-src/tape-device.c
@@ -202,6 +202,7 @@ static dumpfile_t * tape_device_seek_file (Device * self, guint file);
 static gboolean tape_device_seek_block (Device * self, guint64 block);
 static gboolean tape_device_eject (Device * self);
 static gboolean tape_device_finish (Device * self);
+static gboolean tape_device_check_writable(Device *self);
 static IoResult tape_device_robust_read (TapeDevice * self, void * buf,
                                                int * count, char **errmsg);
 static IoResult tape_device_robust_write (TapeDevice * self, void * buf, int count, char **errmsg);
@@ -383,6 +384,7 @@ tape_device_class_init (TapeDeviceClass * c)
     device_class->seek_block = tape_device_seek_block;
     device_class->eject = tape_device_eject;
     device_class->finish = tape_device_finish;
+    device_class->check_writable = tape_device_check_writable;
 
     g_object_class->finalize = tape_device_finalize;
 }
@@ -1180,11 +1182,16 @@ tape_device_start (Device * d_self, DeviceAccessMode mode, char * label,
 			    self->private->device_filename, strerror(self->write_open_errno)),
 		DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
             return FALSE;
-        } else if (!tape_rewind(self->fd)) {
-	    device_set_error(d_self,
-		g_strdup_printf(_("Error rewinding device to start: %s"), strerror(errno)),
-		DEVICE_STATUS_DEVICE_ERROR);
-	    return FALSE;
+        } else {
+	    if (!tape_device_check_writable(d_self)) {
+		return FALSE;
+	    }
+	    if (!tape_rewind(self->fd)) {
+		device_set_error(d_self,
+			g_strdup_printf(_("Error rewinding device to start: %s"), strerror(errno)),
+			DEVICE_STATUS_DEVICE_ERROR);
+		return FALSE;
+	    }
         }
     }
 
@@ -1640,6 +1647,34 @@ finish_error:
     return FALSE;
 }
 
+static gboolean
+tape_device_check_writable(Device * d_self)
+{
+    TapeDevice *self;
+    struct mtget get;
+
+    self = TAPE_DEVICE(d_self);
+
+    if (device_in_error(self))
+	return TRUE;
+
+    if (ioctl(self->fd, MTIOCGET, &get) == 0) {
+	if (GMT_WR_PROT(get.mt_gstat)) {
+	    device_set_error(d_self,
+		g_strdup_printf("Device '%s' is write protected", self->private->device_filename),
+		DEVICE_STATUS_VOLUME_ERROR);
+	    return FALSE;
+	}
+    } else {
+	device_set_error(d_self,
+	    g_strdup_printf("ioctl failed on device '%s'", self->private->device_filename),
+	    DEVICE_STATUS_VOLUME_ERROR);
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
 /* Works just like read(), except for the following:
  * 1) Retries on EINTR & friends.
  * 2) Stores count in parameter, not return value.
diff --git a/perl/Amanda/Device.swg b/perl/Amanda/Device.swg
index ea46300..479f249 100644
--- a/perl/Amanda/Device.swg
+++ b/perl/Amanda/Device.swg
@@ -413,6 +413,11 @@ typedef struct Device {
 	    return device_use_connection(self, conn);
 	}
 
+	gboolean
+	check_writable() {
+	    return device_check_writable(self);
+	}
+
 	%typemap(in,numinputs=0) guint64 *actual_size (guint64 sz) {
 	    sz = 0;
 	    $1 = &sz;
diff --git a/server-src/amcheck-device.pl b/server-src/amcheck-device.pl
index 7228a08..bf66603 100644
--- a/server-src/amcheck-device.pl
+++ b/server-src/amcheck-device.pl
@@ -224,6 +224,15 @@ sub do_check {
 		print "WARNING: DEVICE-OUTPUT-BUFFER-SIZE is not at least twice the block size of the device, it should be increased for better throughput\n";
 	    }
 	}
+	$steps->{'check_writable'}->();
+    };
+
+    step check_writable => sub {
+
+	if($res->{'device'} and !$res->{'device'}->check_writable()) {
+	    print "ERROR: " . $res->{'device'}->error_or_status() . "\n";
+	    return $steps->{'release'}->();
+	}
 	$steps->{'check_overwrite'}->();
     };
 

Reply via email to