svn commit: r188839 - in head/sys: geom geom/part sys
Marcel Moolenaar
marcel at FreeBSD.org
Thu Feb 19 20:48:42 PST 2009
Author: marcel
Date: Fri Feb 20 04:48:40 2009
New Revision: 188839
URL: http://svn.freebsd.org/changeset/base/188839
Log:
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.
Modified:
head/sys/geom/geom_dev.c
head/sys/geom/part/g_part.c
head/sys/geom/part/g_part_ebr.c
head/sys/geom/part/g_part_if.m
head/sys/sys/disk.h
Modified: head/sys/geom/geom_dev.c
==============================================================================
--- head/sys/geom/geom_dev.c Fri Feb 20 04:10:31 2009 (r188838)
+++ head/sys/geom/geom_dev.c Fri Feb 20 04:48:40 2009 (r188839)
@@ -113,6 +113,7 @@ g_dev_taste(struct g_class *mp, struct g
{
struct g_geom *gp;
struct g_consumer *cp;
+ char *alias;
int error;
struct cdev *dev;
@@ -134,6 +135,17 @@ g_dev_taste(struct g_class *mp, struct g
gp->softc = dev;
dev->si_drv1 = gp;
dev->si_drv2 = cp;
+
+ g_topology_unlock();
+
+ alias = g_malloc(MAXPATHLEN, M_WAITOK | M_ZERO);
+ error = (pp->geom->ioctl == NULL) ? ENODEV :
+ pp->geom->ioctl(pp, DIOCGPROVIDERALIAS, alias, 0, curthread);
+ if (!error && alias[0] != '\0')
+ make_dev_alias(dev, "%s", alias);
+ g_free(alias);
+
+ g_topology_lock();
return (gp);
}
Modified: head/sys/geom/part/g_part.c
==============================================================================
--- head/sys/geom/part/g_part.c Fri Feb 20 04:10:31 2009 (r188838)
+++ head/sys/geom/part/g_part.c Fri Feb 20 04:48:40 2009 (r188839)
@@ -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,
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,
}
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,
}
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 c
}
}
+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)
{
Modified: head/sys/geom/part/g_part_ebr.c
==============================================================================
--- head/sys/geom/part/g_part_ebr.c Fri Feb 20 04:10:31 2009 (r188838)
+++ head/sys/geom/part/g_part_ebr.c Fri Feb 20 04:48:40 2009 (r188839)
@@ -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 *
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 *bas
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 *bas
pp->sectorsize;
entry = (struct g_part_ebr_entry *)baseentry;
entry->ent = ent[0];
+ entry->alias = alias++;
if (ent[1].dp_typ == 0)
break;
Modified: head/sys/geom/part/g_part_if.m
==============================================================================
--- head/sys/geom/part/g_part_if.m Fri Feb 20 04:10:31 2009 (r188838)
+++ head/sys/geom/part/g_part_if.m Fri Feb 20 04:48:40 2009 (r188839)
@@ -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;
Modified: head/sys/sys/disk.h
==============================================================================
--- head/sys/sys/disk.h Fri Feb 20 04:10:31 2009 (r188838)
+++ head/sys/sys/disk.h Fri Feb 20 04:48:40 2009 (r188839)
@@ -104,4 +104,10 @@ void disk_err(struct bio *bp, const char
* must be at least MAXPATHLEN bytes long.
*/
+#define DIOCGPROVIDERALIAS _IOR('d', 139, char[MAXPATHLEN])
+ /*-
+ * Store the provider alias, if present, in a buffer. The buffer must
+ * be at least MAXPATHLEN bytes long.
+ */
+
#endif /* _SYS_DISK_H_ */
More information about the svn-src-head
mailing list