Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102825986
D3343.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D3343.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D3343: Add "Logical Block Mode" to geom multipath
Attached
Detach File
Event Timeline
Log In to Comment