diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index 924bf3247fe295b7e4f355d423cbcf93abd9fe73..f00ee9f19f5cdcc2c9a9925cb0676d8fde7780e9 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.652 2008/02/02 18:10:48 chrfranke Exp $
+$Id: CHANGELOG,v 1.653 2008/02/17 00:30:47 dpgilbert Exp $
 
 The most recent version of this file is:
 http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup
@@ -34,6 +34,11 @@ NOTES FOR FUTURE RELEASES: see TODO file.
 
 <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
 
+  [DG] smartd re-opens "SCSI" devices as ATA devices if a SAT layer is
+       detected (smartd bug IMO). In Linux this upsets scsi generic
+       device nodes (e.g. /dev/sg0). Detect the re-open in os_linux.cpp
+       and set the O_RDWR flag (ATA uses the O_RDONLY flag).
+
   [CF] Drive database: Added Fujitsu MHW2 BH, Maxtor DiamondMax 17, 20, 21,
        Hitachi Travelstar 4K40, 5K120, 7K200, Deskstar 7K160, T7K500,
        T7K1000, Toshiba 1.8", Seagate Momentus 5400.3, 5400.3 ED, 7200.2,
diff --git a/sm5/os_linux.cpp b/sm5/os_linux.cpp
index a0cf122b244e816ee3a852aadcfc4457de62a5eb..1aeb9f36f47551a4e74ca320fdb908e5920281e6 100644
--- a/sm5/os_linux.cpp
+++ b/sm5/os_linux.cpp
@@ -79,9 +79,9 @@ typedef unsigned long long u8;
 
 #define ARGUSED(x) ((void)(x))
 
-static const char *filenameandversion="$Id: os_linux.cpp,v 1.97 2007/09/06 08:48:55 ballen4705 Exp $";
+static const char *filenameandversion="$Id: os_linux.cpp,v 1.98 2008/02/17 00:30:47 dpgilbert Exp $";
 
-const char *os_XXXX_c_cvsid="$Id: os_linux.cpp,v 1.97 2007/09/06 08:48:55 ballen4705 Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_linux.cpp,v 1.98 2008/02/17 00:30:47 dpgilbert Exp $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_LINUX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
@@ -167,17 +167,29 @@ int setup_3ware_nodes(char *nodename, char *driver_name) {
   return 0;
 }
 
+static char prev_scsi_dev[128];
+
 // equivalent to open(path, flags)
 int deviceopen(const char *pathname, char *type){
-  if (!strcmp(type,"SCSI")) {
-    int fd = open(pathname, O_RDWR | O_NONBLOCK);
+  int fd;
+
+  if (0 == strcmp(type,"SCSI")) {
+    strncpy(prev_scsi_dev, pathname, sizeof(prev_scsi_dev) - 1);
+    fd = open(pathname, O_RDWR | O_NONBLOCK);
     if (fd < 0 && errno == EROFS)
       fd = open(pathname, O_RDONLY | O_NONBLOCK);
     return fd;
-  }
-  else if (!strcmp(type,"ATA"))
-    return open(pathname, O_RDONLY | O_NONBLOCK);
-  else if (!strcmp(type,"ATA_3WARE_9000")) {
+  } else if (0 == strcmp(type,"ATA")) {
+    // smartd re-opens SCSI devices with "type"==ATA for some reason.
+    // If that was a SCSI generic device (e.g. /dev/sg0) then the
+    // sg driver wants O_RDWR to allow through ATA PASS-THROUGH commands.
+    // The purpose of the next code line is to limit the scope of
+    // this change as a release is pending (and smartd needs a rewrite).
+    if (0 == strncmp(pathname, prev_scsi_dev, sizeof(prev_scsi_dev)))
+      return open(pathname, O_RDWR | O_NONBLOCK);
+    else
+      return open(pathname, O_RDONLY | O_NONBLOCK);
+  } else if (0 == strcmp(type,"ATA_3WARE_9000")) {
     // the device nodes for this controller are dynamically assigned,
     // so we need to check that they exist with the correct major
     // numbers and if not, create them
@@ -188,7 +200,7 @@ int deviceopen(const char *pathname, char *type){
     }
     return open(pathname, O_RDONLY | O_NONBLOCK);
   }
-  else if (!strcmp(type,"ATA_3WARE_678K")) {
+  else if (0 == strcmp(type,"ATA_3WARE_678K")) {
     // the device nodes for this controller are dynamically assigned,
     // so we need to check that they exist with the correct major
     // numbers and if not, create them
@@ -199,7 +211,7 @@ int deviceopen(const char *pathname, char *type){
     }
     return open(pathname, O_RDONLY | O_NONBLOCK);
   }
-  else if(!strcmp(type, "CCISS")) {
+  else if(0 == strcmp(type, "CCISS")) {
     // the device is a cciss smart array device.
     return open(pathname, O_RDWR | O_NONBLOCK);
   }