Page MenuHomeFreeBSD

D13360.id36182.diff
No OneTemporary

D13360.id36182.diff

Index: sys/cam/cam_ccb.h
===================================================================
--- sys/cam/cam_ccb.h
+++ sys/cam/cam_ccb.h
@@ -1268,6 +1268,7 @@
#define CDAI_TYPE_EXT_INQ 5
#define CDAI_TYPE_NVME_CNTRL 6 /* NVMe Identify Controller data */
#define CDAI_TYPE_NVME_NS 7 /* NVMe Identify Namespace data */
+#define CDAI_TYPE_MODE_DEV_SPEC 8 /* Device specific byte of mode header */
off_t bufsiz; /* IN: Size of external buffer */
#define CAM_SCSI_DEVID_MAXLEN 65536 /* length in buffer is an uint16_t */
off_t provsiz; /* OUT: Size required/used */
Index: sys/cam/cam_xpt_internal.h
===================================================================
--- sys/cam/cam_xpt_internal.h
+++ sys/cam/cam_xpt_internal.h
@@ -133,6 +133,7 @@
* queuing for a device.
*/
u_int8_t queue_flags; /* Queue flags from the control page */
+ u_int8_t dev_spec; /* Device specific byte of mode header */
u_int8_t serial_num_len;
u_int8_t *serial_num;
u_int32_t flags;
Index: sys/cam/scsi/scsi_da.c
===================================================================
--- sys/cam/scsi/scsi_da.c
+++ sys/cam/scsi/scsi_da.c
@@ -5596,6 +5596,34 @@
softc->disk->d_devstat->block_size = softc->params.secsize;
softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE;
+ /* Refresh the write protect status as well. */
+ {
+ struct ccb_dev_advinfo cdai;
+ uint8_t dev_spec;
+
+ xpt_setup_ccb(&cdai.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+ cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
+ cdai.buftype = CDAI_TYPE_MODE_DEV_SPEC;
+ cdai.flags = 0;
+ cdai.bufsiz = 1;
+ cdai.buf = &dev_spec;
+ xpt_action((union ccb *)&cdai);
+ if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
+ cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
+ if (cdai.ccb_h.status != CAM_REQ_CMP) {
+ xpt_print(periph->path, "%s: failed to get dev_spec\n",
+ __func__);
+ /* Use cam_error_print() to decode the status */
+ cam_error_print((union ccb *)&cdai, CAM_ESF_CAM_STATUS,
+ CAM_EPF_ALL);
+ } else {
+ if ((dev_spec & 0x80) != 0)
+ softc->disk->d_flags |= DISKFLAG_WRITE_PROTECT;
+ else
+ softc->disk->d_flags &= ~DISKFLAG_WRITE_PROTECT;
+ }
+ }
+
error = disk_resize(softc->disk, M_NOWAIT);
if (error != 0)
xpt_print(periph->path, "disk_resize(9) failed, error = %d\n", error);
Index: sys/cam/scsi/scsi_xpt.c
===================================================================
--- sys/cam/scsi/scsi_xpt.c
+++ sys/cam/scsi/scsi_xpt.c
@@ -1423,6 +1423,7 @@
+ mode_hdr->blk_desc_len;
page = (struct scsi_control_page *)offset;
path->device->queue_flags = page->queue_flags;
+ path->device->dev_spec = mode_hdr->dev_spec;
} else if (cam_periph_error(done_ccb, 0,
SF_RETRY_UA|SF_NO_PRINT,
&softc->saved_ccb) == ERESTART) {
@@ -2615,6 +2616,18 @@
amt = cdai->bufsiz;
memcpy(cdai->buf, device->ext_inq, amt);
break;
+ case CDAI_TYPE_MODE_DEV_SPEC:
+ /*
+ * We fetch mode parameter header during probe.
+ * We don't allow changing it.
+ */
+ if (cdai->flags & CDAI_FLAG_STORE)
+ return;
+ cdai->provsiz = 1;
+ if (cdai->bufsiz == 0)
+ break;
+ cdai->buf[0] = device->dev_spec;
+ break;
default:
return;
}
Index: sys/geom/geom_disk.h
===================================================================
--- sys/geom/geom_disk.h
+++ sys/geom/geom_disk.h
@@ -124,13 +124,14 @@
LIST_HEAD(,disk_alias) d_aliases;
};
-#define DISKFLAG_RESERVED 0x1 /* Was NEEDSGIANT */
-#define DISKFLAG_OPEN 0x2
-#define DISKFLAG_CANDELETE 0x4
-#define DISKFLAG_CANFLUSHCACHE 0x8
-#define DISKFLAG_UNMAPPED_BIO 0x10
-#define DISKFLAG_DIRECT_COMPLETION 0x20
-#define DISKFLAG_CANZONE 0x80
+#define DISKFLAG_RESERVED 0x0001 /* Was NEEDSGIANT */
+#define DISKFLAG_OPEN 0x0002
+#define DISKFLAG_CANDELETE 0x0004
+#define DISKFLAG_CANFLUSHCACHE 0x0008
+#define DISKFLAG_UNMAPPED_BIO 0x0010
+#define DISKFLAG_DIRECT_COMPLETION 0x0020
+#define DISKFLAG_CANZONE 0x0080
+#define DISKFLAG_WRITE_PROTECT 0x0100
struct disk *disk_alloc(void);
void disk_create(struct disk *disk, int version);
Index: sys/geom/geom_disk.c
===================================================================
--- sys/geom/geom_disk.c
+++ sys/geom/geom_disk.c
@@ -120,14 +120,18 @@
e += pp->ace;
error = 0;
if ((pp->acr + pp->acw + pp->ace) == 0 && (r + w + e) > 0) {
- if (dp->d_open != NULL) {
+ /*
+ * It would be better to defer this decision to d_open if
+ * it was able to take flags.
+ */
+ if (w > 0 && (dp->d_flags & DISKFLAG_WRITE_PROTECT) != 0)
+ error = ENODEV;
+ if (error == 0 && dp->d_open != NULL)
error = dp->d_open(dp);
- if (bootverbose && error != 0)
- printf("Opened disk %s -> %d\n",
- pp->name, error);
- if (error != 0)
- return (error);
- }
+ if (bootverbose && error != 0)
+ printf("Opened disk %s -> %d\n", pp->name, error);
+ if (error != 0)
+ return (error);
pp->sectorsize = dp->d_sectorsize;
if (dp->d_maxsize == 0) {
printf("WARNING: Disk drive %s%d has no d_maxsize\n",
@@ -1041,7 +1045,8 @@
"\4CANFLUSHCACHE"
"\5UNMAPPEDBIO"
"\6DIRECTCOMPLETION"
- "\10CANZONE");
+ "\10CANZONE"
+ "\11WRITEPROTECT");
sbuf_finish(sb);
error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);

File Metadata

Mime Type
text/plain
Expires
Fri, Dec 19, 11:25 PM (5 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27088996
Default Alt Text
D13360.id36182.diff (5 KB)

Event Timeline