1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-28 11:57:28 +00:00

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.
This commit is contained in:
Marcel Moolenaar 2009-02-20 04:48:40 +00:00
parent 507a0d4a6c
commit 59c532c500
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=188839
5 changed files with 87 additions and 1 deletions

View File

@ -113,6 +113,7 @@ g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
{
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_provider *pp, int insist __unused)
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);
}

View File

@ -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)
{

View File

@ -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;

View File

@ -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;

View File

@ -104,4 +104,10 @@ void disk_err(struct bio *bp, const char *what, int blkdone, int nl);
* 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_ */