Page MenuHomeFreeBSD

D3343.diff
No OneTemporary

D3343.diff

Index: sbin/geom/class/multipath/geom_multipath.c
===================================================================
--- sbin/geom/class/multipath/geom_multipath.c
+++ sbin/geom/class/multipath/geom_multipath.c
@@ -57,27 +57,31 @@
{
{ 'A', "active_active", NULL, G_TYPE_BOOL },
{ 'R', "active_read", NULL, G_TYPE_BOOL },
+ { 'L', "logicalblock", 0, G_TYPE_NUMBER },
G_OPT_SENTINEL
},
- "[-vAR] name prov ..."
+ "[-vAR] [-L logicalblock] name prov ..."
},
{
"label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, mp_main,
{
{ 'A', "active_active", NULL, G_TYPE_BOOL },
{ 'R', "active_read", NULL, G_TYPE_BOOL },
+ { 'L', "logicalblock", 0, G_TYPE_NUMBER },
G_OPT_SENTINEL
},
- "[-vAR] name prov ..."
+ "[-vAR] [-L logicalblock] name prov ..."
},
- { "configure", G_FLAG_VERBOSE, NULL,
+ {
+ "configure", G_FLAG_VERBOSE, NULL,
{
{ 'A', "active_active", NULL, G_TYPE_BOOL },
{ 'P', "active_passive", NULL, G_TYPE_BOOL },
{ 'R', "active_read", NULL, G_TYPE_BOOL },
+ { 'L', "logicalblock", 0, G_TYPE_NUMBER },
G_OPT_SENTINEL
},
- "[-vAPR] name"
+ "[-vAPR] [-L logicalblock] name"
},
{
"add", G_FLAG_VERBOSE, NULL, G_NULL_OPTS,
@@ -148,7 +152,7 @@
{
struct g_multipath_metadata md;
off_t disksize = 0, msize;
- uint8_t *sector, *rsector;
+ uint8_t *sector, *rsector, val;
char *ptr;
uuid_t uuid;
ssize_t secsize = 0, ssize;
@@ -213,10 +217,20 @@
return;
}
strlcpy(md.md_uuid, ptr, sizeof (md.md_uuid));
+ free(ptr);
+
md.md_active_active = gctl_get_int(req, "active_active");
if (gctl_get_int(req, "active_read"))
md.md_active_active = 2;
- free(ptr);
+ val = gctl_get_int(req, "logicalblock");
+ if (val == 0 || (val > 8 && val < 32))
+ md.md_logicalblock = val;
+ else {
+ gctl_error(req, "Invalid logicalblock bitshift value: %u. "
+ "Must be a value between 9 and 31, or 0 to disable.",
+ val);
+ return;
+ }
/*
* Allocate a sector to write as metadata.
Index: sbin/geom/class/multipath/gmultipath.8
===================================================================
--- sbin/geom/class/multipath/gmultipath.8
+++ sbin/geom/class/multipath/gmultipath.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 18, 2015
+.Dd August 8, 2015
.Dt GMULTIPATH 8
.Os
.Sh NAME
@@ -34,16 +34,19 @@
.Nm
.Cm create
.Op Fl ARv
+.Op Fl L Ar logicalblock
.Ar name
.Ar prov ...
.Nm
.Cm label
.Op Fl ARv
+.Op Fl L Ar logicalblock
.Ar name
.Ar prov ...
.Nm
.Cm configure
.Op Fl APRv
+.Op Fl L Ar logicalblock
.Ar name
.Nm
.Cm add
@@ -134,6 +137,12 @@
.Fl R
option enables Active/Read mode, otherwise Active/Passive mode is used
by default.
+.Pp
+.Fl L
+option enables Logical Block mode, the device is divided into stripes of
+.No 2** Ns Ar logicalblock
+bytes, and all requests to a stripe are served via the same path.
+This can improve performance by taking advantage of read-ahead and caching.
.It Cm label
Create multipath device with
.Dq automatic
@@ -149,6 +158,12 @@
.Fl R
option enables Active/Read mode, otherwise Active/Passive mode is used
by default.
+.Pp
+.Fl L
+option enables Logical Block mode, the device is divided into stripes of
+.No 2** Ns Ar logicalblock
+bytes, and all requests to a stripe are served via the same path.
+This can improve performance by taking advantage of read-ahead and caching.
.It Cm configure
Configure the given multipath device.
.Pp
@@ -158,6 +173,12 @@
option enables Active/Passive mode,
.Fl R
option enables Active/Read mode.
+.Pp
+.Fl L
+option enables Logical Block mode, the device is divided into stripes of
+.No 2** Ns Ar logicalblock
+bytes, and all requests to a stripe are served via the same path.
+This can improve performance by taking advantage of read-ahead and caching.
.It Cm add
Add the given provider as a path to the given multipath device.
Should normally be used only for devices created with
Index: sys/geom/multipath/g_multipath.h
===================================================================
--- sys/geom/multipath/g_multipath.h
+++ sys/geom/multipath/g_multipath.h
@@ -35,9 +35,19 @@
#define _G_MULTIPATH_H_
#define G_MULTIPATH_CLASS_NAME "MULTIPATH"
-#define G_MULTIPATH_VERSION 1
#define G_MULTIPATH_MAGIC "GEOM::MULTIPATH"
+/*
+ * Version history:
+ * 1 - Initial version number.
+ * 2 - Added Logical Block mode, selects the same path for reads and writes to
+ * nearby sectors, improving cache hit ratios on the controller.
+ */
+#define G_MULTIPATH_VERSION_01 1
+#define G_MULTIPATH_VERSION_02 2
+#define G_MULTIPATH_VERSION G_MULTIPATH_VERSION_02
+
+
#include <sys/endian.h>
#ifdef _KERNEL
@@ -53,6 +63,7 @@
int sc_stopping;
int sc_ndisks;
int sc_active_active; /* Active/Active mode */
+ int sc_logicalblock; /* logical block mode */
};
#endif /* _KERNEL */
@@ -64,16 +75,25 @@
uint32_t md_sectorsize; /* sectorsize of provider */
uint64_t md_size; /* absolute size of provider */
uint8_t md_active_active; /* Active/Active mode */
+ uint16_t md_logicalblock; /* Logical Block mode */
};
static __inline void
+multipath_metadata_encode_v1(const struct g_multipath_metadata *, u_char *);
+static __inline void
+multipath_metadata_encode_v2(const struct g_multipath_metadata *, u_char *);
+static __inline void
multipath_metadata_encode(const struct g_multipath_metadata *, u_char *);
static __inline void
+multipath_metadata_decode_v1(u_char *, struct g_multipath_metadata *);
+static __inline void
+multipath_metadata_decode_v2(u_char *, struct g_multipath_metadata *);
+static __inline int
multipath_metadata_decode(u_char *, struct g_multipath_metadata *);
static __inline void
-multipath_metadata_encode(const struct g_multipath_metadata *md, u_char *data)
+multipath_metadata_encode_v1(const struct g_multipath_metadata *md, u_char *data)
{
bcopy(md->md_magic, data, sizeof(md->md_magic));
data += sizeof(md->md_magic);
@@ -91,7 +111,27 @@
}
static __inline void
-multipath_metadata_decode(u_char *data, struct g_multipath_metadata *md)
+multipath_metadata_encode_v2(const struct g_multipath_metadata *md, u_char *data)
+{
+ bcopy(md->md_magic, data, sizeof(md->md_magic));
+ data += sizeof(md->md_magic);
+ bcopy(md->md_uuid, data, sizeof(md->md_uuid));
+ data += sizeof(md->md_uuid);
+ bcopy(md->md_name, data, sizeof(md->md_name));
+ data += sizeof(md->md_name);
+ le32enc(data, md->md_version);
+ data += sizeof(md->md_version);
+ le32enc(data, md->md_sectorsize);
+ data += sizeof(md->md_sectorsize);
+ le64enc(data, md->md_size);
+ data += sizeof(md->md_size);
+ *data = md->md_active_active;
+ data += sizeof(md->md_active_active);
+ le16enc(data, md->md_logicalblock);
+}
+
+static __inline void
+multipath_metadata_decode_v1(u_char *data, struct g_multipath_metadata *md)
{
bcopy(data, md->md_magic, sizeof(md->md_magic));
data += sizeof(md->md_magic);
@@ -107,4 +147,80 @@
data += sizeof(md->md_size);
md->md_active_active = *data;
}
+
+static __inline void
+multipath_metadata_decode_v2(u_char *data, struct g_multipath_metadata *md)
+{
+ bcopy(data, md->md_magic, sizeof(md->md_magic));
+ data += sizeof(md->md_magic);
+ bcopy(data, md->md_uuid, sizeof(md->md_uuid));
+ data += sizeof(md->md_uuid);
+ bcopy(data, md->md_name, sizeof(md->md_name));
+ data += sizeof(md->md_name);
+ md->md_version = le32dec(data);
+ data += sizeof(md->md_version);
+ md->md_sectorsize = le32dec(data);
+ data += sizeof(md->md_sectorsize);
+ md->md_size = le64dec(data);
+ data += sizeof(md->md_size);
+ md->md_active_active = *data;
+ data += sizeof(md->md_active_active);
+ md->md_logicalblock = le16dec(data);
+}
+
+static __inline void
+multipath_metadata_encode(const struct g_multipath_metadata *md, u_char *data)
+{
+ u_char *p;
+
+ p = data;
+ p += sizeof(md->md_magic);
+ p += sizeof(md->md_uuid);
+ p += sizeof(md->md_name);
+ le32enc(p, md->md_version);
+ switch (md->md_version) {
+ case G_MULTIPATH_VERSION_01:
+ multipath_metadata_encode_v1(md, data);
+ break;
+ case G_MULTIPATH_VERSION_02:
+ multipath_metadata_encode_v2(md, data);
+ break;
+ default:
+#ifdef _KERNEL
+ panic("%s: Unsupported version %u.", __func__,
+ (u_int)md->md_version);
+#else
+ assert(!"Unsupported metadata version.");
+#endif
+ }
+}
+
+static __inline int
+multipath_metadata_decode(u_char *data, struct g_multipath_metadata *md)
+{
+ int error;
+ u_char *p;
+
+ error = 0;
+ p = data;
+ bcopy(data, md->md_magic, sizeof(md->md_magic));
+ if (strcmp(md->md_magic, G_MULTIPATH_MAGIC) != 0)
+ return (EINVAL);
+ p += sizeof(md->md_magic);
+ p += sizeof(md->md_uuid);
+ p += sizeof(md->md_name);
+ md->md_version = le32dec(p);
+ switch (md->md_version) {
+ case G_MULTIPATH_VERSION_01:
+ multipath_metadata_decode_v1(data, md);
+ break;
+ case G_MULTIPATH_VERSION_02:
+ multipath_metadata_decode_v2(data, md);
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ return (error);
+}
#endif /* _G_MULTIPATH_H_ */
Index: sys/geom/multipath/g_multipath.c
===================================================================
--- sys/geom/multipath/g_multipath.c
+++ sys/geom/multipath/g_multipath.c
@@ -170,12 +170,42 @@
{
struct g_multipath_softc *sc;
struct g_consumer *best, *cp;
+ int lbselect, cidx;
sc = gp->softc;
+ /*
+ * If mode is Active/Passive, use the active component.
+ * If mode is Active/Read and the request is not a read, use the active
+ * component.
+ */
if (sc->sc_active_active == 0 ||
(sc->sc_active_active == 2 && bp->bio_cmd != BIO_READ))
return (sc->sc_active);
+ /*
+ * If Mode is Active/Active of Active/Read and Logical Block mode is
+ * enabled, choose the component based on which Logical Block is being
+ * requested
+ */
best = NULL;
+ if (sc->sc_logicalblock > 0) {
+ lbselect = (bp->bio_offset >> sc->sc_logicalblock)
+ % sc->sc_ndisks;
+
+ cidx = 0;
+ LIST_FOREACH(cp, &gp->consumer, consumer) {
+ if (cp->index & MP_BAD) {
+ cidx++;
+ continue;
+ }
+ if (lbselect == cidx)
+ return (cp);
+ cidx++;
+ }
+ /*
+ * If the consumer we wanted to use is not available,
+ * fallthrough to the usual algorithm
+ */
+ }
LIST_FOREACH(cp, &gp->consumer, consumer) {
if (cp->index & MP_BAD)
continue;
@@ -311,6 +341,7 @@
md.md_size = size;
md.md_sectorsize = ssize;
md.md_active_active = sc->sc_active_active;
+ md.md_logicalblock = sc->sc_logicalblock;
error = g_multipath_write_metadata(cp, &md);
if (error != 0)
printf("GEOM_MULTIPATH: Can't update metadata on %s "
@@ -531,6 +562,7 @@
memcpy(sc->sc_uuid, md->md_uuid, sizeof (sc->sc_uuid));
memcpy(sc->sc_name, md->md_name, sizeof (sc->sc_name));
sc->sc_active_active = md->md_active_active;
+ sc->sc_logicalblock = md->md_logicalblock;
sc->sc_size = md->md_size;
gp->softc = sc;
gp->start = g_multipath_start;
@@ -758,9 +790,9 @@
g_access(cp, -1, 0, 0);
if (buf == NULL)
return (error);
- multipath_metadata_decode(buf, md);
+ error = multipath_metadata_decode(buf, md);
g_free(buf);
- return (0);
+ return (error);
}
static int
@@ -817,7 +849,7 @@
printf("%s is not MULTIPATH\n", pp->name);
return (NULL);
}
- if (md.md_version != G_MULTIPATH_VERSION) {
+ if (md.md_version > G_MULTIPATH_VERSION) {
printf("%s has version %d multipath id- this module is version "
" %d: rejecting\n", pp->name, md.md_version,
G_MULTIPATH_VERSION);
@@ -1120,6 +1152,17 @@
val = gctl_get_paraml(req, "active_read", sizeof(*val));
if (val != NULL && *val != 0)
md.md_active_active = 2;
+ val = gctl_get_paraml(req, "logicalblock", sizeof(*val));
+ if (val == NULL)
+ md.md_logicalblock = 0;
+ else if (*val == 0 || (*val > 8 && *val < 32))
+ md.md_logicalblock = *val;
+ else {
+ gctl_error(req, "Invalid logicalblock bitshift value: %u. "
+ "Must be a value between 9 and 31, or 0 to disable.",
+ *val);
+ return;
+ }
gp = g_multipath_create(mp, &md);
if (gp == NULL) {
gctl_error(req, "GEOM_MULTIPATH: cannot create geom %s/%s\n",
@@ -1171,6 +1214,17 @@
val = gctl_get_paraml(req, "active_passive", sizeof(*val));
if (val != NULL && *val != 0)
sc->sc_active_active = 0;
+ val = gctl_get_paraml(req, "logicalblock", sizeof(*val));
+ if (val == NULL)
+ sc->sc_logicalblock = 0;
+ else if (*val == 0 || (*val > 8 && *val < 32))
+ sc->sc_logicalblock = *val;
+ else {
+ gctl_error(req, "Invalid logicalblock bitshift value: %u. "
+ "Must be a value between 9 and 31, or 0 to disable.",
+ *val);
+ return;
+ }
if (sc->sc_uuid[0] != 0 && sc->sc_active != NULL) {
cp = sc->sc_active;
pp = cp->provider;
@@ -1181,6 +1235,7 @@
md.md_size = pp->mediasize;
md.md_sectorsize = pp->sectorsize;
md.md_active_active = sc->sc_active_active;
+ md.md_logicalblock = sc->sc_logicalblock;
error = g_multipath_write_metadata(cp, &md);
if (error != 0)
gctl_error(req, "Can't update metadata on %s (%d)",

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 18, 4:47 PM (22 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14701091
Default Alt Text
D3343.diff (12 KB)

Event Timeline