summaryrefslogtreecommitdiffstats
path: root/sys/geom/part
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2009-02-20 04:48:40 +0000
committermarcel <marcel@FreeBSD.org>2009-02-20 04:48:40 +0000
commitc0f13aca4f82041b9d69bedf27f4211b3f75d0d9 (patch)
tree8268bfa14bb04240846607b3f81f7e3c66956a79 /sys/geom/part
parent06849d431c7d471f1488eb982edef98712a3f262 (diff)
downloadFreeBSD-src-c0f13aca4f82041b9d69bedf27f4211b3f75d0d9.zip
FreeBSD-src-c0f13aca4f82041b9d69bedf27f4211b3f75d0d9.tar.gz
Provide compatibility symlink for logical partitions:
1. Extend geom_dev by having it create the symlink (i.e. call make_dev_alias) based on the DIOCGPROVIDERALIAS ioctl. In this way the functionaility is generic and thus usable by any geom/provider. 2. Have g_part handle said ioctl through the devalias method, so that it's under control of the scheme itself. By design the alias will not be created for newly added partitions.
Diffstat (limited to 'sys/geom/part')
-rw-r--r--sys/geom/part/g_part.c34
-rw-r--r--sys/geom/part/g_part_ebr.c27
-rw-r--r--sys/geom/part/g_part_if.m9
3 files changed, 69 insertions, 1 deletions
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index f82958c..2e8bb98 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bio.h>
+#include <sys/disk.h>
#include <sys/diskmbr.h>
#include <sys/endian.h>
#include <sys/kernel.h>
@@ -87,6 +88,7 @@ static g_taste_t g_part_taste;
static g_access_t g_part_access;
static g_dumpconf_t g_part_dumpconf;
+static g_ioctl_t g_part_ioctl;
static g_orphan_t g_part_orphan;
static g_spoiled_t g_part_spoiled;
static g_start_t g_part_start;
@@ -103,6 +105,7 @@ static struct g_class g_part_class = {
/* Geom methods. */
.access = g_part_access,
.dumpconf = g_part_dumpconf,
+ .ioctl = g_part_ioctl,
.orphan = g_part_orphan,
.spoiled = g_part_spoiled,
.start = g_part_start,
@@ -566,6 +569,8 @@ g_part_ctl_commit(struct gctl_req *req, struct g_part_parms *gpp)
return (EPERM);
}
+ g_topology_unlock();
+
cp = LIST_FIRST(&gp->consumer);
if ((table->gpt_smhead | table->gpt_smtail) != 0) {
pp = cp->provider;
@@ -594,6 +599,7 @@ g_part_ctl_commit(struct gctl_req *req, struct g_part_parms *gpp)
}
if (table->gpt_scheme == &g_part_null_scheme) {
+ g_topology_lock();
g_access(cp, -1, -1, -1);
g_part_wither(gp, ENXIO);
return (0);
@@ -614,10 +620,13 @@ g_part_ctl_commit(struct gctl_req *req, struct g_part_parms *gpp)
}
table->gpt_created = 0;
table->gpt_opened = 0;
+
+ g_topology_lock();
g_access(cp, -1, -1, -1);
return (0);
fail:
+ g_topology_lock();
gctl_error(req, "%d", error);
return (error);
}
@@ -1591,6 +1600,31 @@ g_part_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
}
}
+static int
+g_part_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag,
+ struct thread *td)
+{
+ struct g_geom *gp;
+ struct g_part_table *table;
+ struct g_part_entry *entry;
+ int error;
+
+ gp = pp->geom;
+ table = gp->softc;
+ entry = pp->private;
+
+ switch (cmd) {
+ case DIOCGPROVIDERALIAS:
+ error = G_PART_DEVALIAS(table, entry, data, MAXPATHLEN);
+ break;
+ default:
+ error = ENOTTY;
+ break;
+ }
+
+ return (error);
+}
+
static void
g_part_orphan(struct g_consumer *cp)
{
diff --git a/sys/geom/part/g_part_ebr.c b/sys/geom/part/g_part_ebr.c
index 44580b2..184ab60 100644
--- a/sys/geom/part/g_part_ebr.c
+++ b/sys/geom/part/g_part_ebr.c
@@ -54,12 +54,15 @@ struct g_part_ebr_table {
struct g_part_ebr_entry {
struct g_part_entry base;
struct dos_partition ent;
+ int alias;
};
static int g_part_ebr_add(struct g_part_table *, struct g_part_entry *,
struct g_part_parms *);
static int g_part_ebr_create(struct g_part_table *, struct g_part_parms *);
static int g_part_ebr_destroy(struct g_part_table *, struct g_part_parms *);
+static int g_part_ebr_devalias(struct g_part_table *, struct g_part_entry *,
+ char *, size_t);
static void g_part_ebr_dumpconf(struct g_part_table *, struct g_part_entry *,
struct sbuf *, const char *);
static int g_part_ebr_dumpto(struct g_part_table *, struct g_part_entry *);
@@ -81,6 +84,7 @@ static kobj_method_t g_part_ebr_methods[] = {
KOBJMETHOD(g_part_add, g_part_ebr_add),
KOBJMETHOD(g_part_create, g_part_ebr_create),
KOBJMETHOD(g_part_destroy, g_part_ebr_destroy),
+ KOBJMETHOD(g_part_devalias, g_part_ebr_devalias),
KOBJMETHOD(g_part_dumpconf, g_part_ebr_dumpconf),
KOBJMETHOD(g_part_dumpto, g_part_ebr_dumpto),
KOBJMETHOD(g_part_modify, g_part_ebr_modify),
@@ -267,6 +271,25 @@ g_part_ebr_destroy(struct g_part_table *basetable, struct g_part_parms *gpp)
return (0);
}
+static int
+g_part_ebr_devalias(struct g_part_table *table, struct g_part_entry *baseentry,
+ char *buf, size_t bufsz)
+{
+ struct g_part_ebr_entry *entry;
+ size_t len;
+
+ entry = (struct g_part_ebr_entry *)baseentry;
+ if (entry->alias == 0)
+ return (ENOENT);
+
+ len = strlcpy(buf, table->gpt_gp->name, bufsz);
+ if (len == 0)
+ return (EINVAL);
+
+ snprintf(buf + len - 1, bufsz - len, "%d", entry->alias);
+ return (0);
+}
+
static void
g_part_ebr_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry,
struct sbuf *sb, const char *indent)
@@ -413,12 +436,13 @@ g_part_ebr_read(struct g_part_table *basetable, struct g_consumer *cp)
u_char *buf;
off_t ofs, msize;
u_int lba;
- int error, index;
+ int alias, error, index;
pp = cp->provider;
table = (struct g_part_ebr_table *)basetable;
msize = pp->mediasize / pp->sectorsize;
+ alias = 5;
lba = 0;
while (1) {
ofs = (off_t)lba * pp->sectorsize;
@@ -445,6 +469,7 @@ g_part_ebr_read(struct g_part_table *basetable, struct g_consumer *cp)
pp->sectorsize;
entry = (struct g_part_ebr_entry *)baseentry;
entry->ent = ent[0];
+ entry->alias = alias++;
if (ent[1].dp_typ == 0)
break;
diff --git a/sys/geom/part/g_part_if.m b/sys/geom/part/g_part_if.m
index b9e47f3..8d2e7b5 100644
--- a/sys/geom/part/g_part_if.m
+++ b/sys/geom/part/g_part_if.m
@@ -75,6 +75,15 @@ METHOD int destroy {
struct g_part_parms *gpp;
};
+# devalias() - return the name (if any) to be used as an alias for
+# the device special file created for the partition entry.
+METHOD int devalias {
+ struct g_part_table *table;
+ struct g_part_entry *entry;
+ char *buf;
+ size_t bufsz;
+};
+
# dumpconf()
METHOD void dumpconf {
struct g_part_table *table;
OpenPOWER on IntegriCloud