@@ -308,6 +308,7 @@ struct sg_device { /* holds the state of each scsi generic device */
int max_sgat_elems; /* adapter's max number of elements in sgat */
int max_sgat_sz; /* max number of bytes in sgat list */
u32 index; /* device index number */
+ u64 create_ns; /* nanoseconds since bootup device created */
atomic_t open_cnt; /* count of opens (perhaps < num(sfds) ) */
unsigned long fdev_bm[1]; /* see SG_FDEV_* defines above */
struct gendisk *disk;
@@ -4462,6 +4463,12 @@ sg_extended_read_value(struct sg_fd *sfp, struct sg_extended_info *seip)
case SG_SEIRV_MAX_RSV_REQS:
seip->read_value = SG_MAX_RSV_REQS;
break;
+ case SG_SEIRV_DEV_TS_LOWER: /* timestamp is 64 bits */
+ seip->read_value = sfp->parentdp->create_ns & U32_MAX;
+ break;
+ case SG_SEIRV_DEV_TS_UPPER:
+ seip->read_value = (sfp->parentdp->create_ns >> 32) & U32_MAX;
+ break;
default:
SG_LOG(6, sfp, "%s: can't decode %d --> read_value\n",
__func__, seip->read_value);
@@ -5530,6 +5537,7 @@ sg_add_device(struct device *cl_dev, struct class_interface *cl_intf)
} else
pr_warn("%s: sg_sys Invalid\n", __func__);
+ sdp->create_ns = ktime_get_boottime_ns();
sg_calc_sgat_param(sdp);
sdev_printk(KERN_NOTICE, scsidp, "Attached scsi generic sg%d "
"type %d\n", sdp->index, scsidp->type);
@@ -223,6 +223,8 @@ typedef struct sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
#define SG_SEIRV_SUBMITTED 0x5 /* number of mrqs submitted+unread */
#define SG_SEIRV_DEV_SUBMITTED 0x6 /* sum(submitted) on all dev's fds */
#define SG_SEIRV_MAX_RSV_REQS 0x7 /* maximum reserve requests */
+#define SG_SEIRV_DEV_TS_LOWER 0x8 /* device timestamp's lower 32 bits */
+#define SG_SEIRV_DEV_TS_UPPER 0x9 /* device timestamp's upper 32 bits */
/*
* A pointer to the following structure is passed as the third argument to
Add timestamp to each sg_device object that is written when the object is created. The timestamp is the number nanoseconds since the boot time of the machine. The purpose is to allow the user to detect, via the extended ioctl()s SG_SEIRV_DEV_TS_LOWER and SG_SEIRV_DEV_TS_UPPER, if a given sg device object (e.g. /dev/sg3) may have possibly changed. One worrisome scenario is when a device disappears and a newly connected device takes the same sg device object number (e.g. /dev/sg3) as the recently disappeared device. Linux gives no guarantees that this type of behaviour will _not_ happen. Recording the device creation timestamp is one way an application can detect when this happens. The uptime command in Linux shows, in humanly readable form, how long a machine has been "up", that is the time that has elapsed since the machine was started or "rebooted". Signed-off-by: Douglas Gilbert <dgilbert@interlog.com> --- drivers/scsi/sg.c | 8 ++++++++ include/uapi/scsi/sg.h | 2 ++ 2 files changed, 10 insertions(+)