- Add a new ioctl for getting the provider name of a geom provider.
- Add a routine for looking up a device and checking if it is a valid geom provider given a partial or full path to its device node. Reviewed by: phk Approved by: pjd (mentor)
This commit is contained in:
parent
6f4745d575
commit
f805f204b6
@ -42,29 +42,22 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <libgeom.h>
|
||||
|
||||
static char *g_device_path_open(const char *, int *, int);
|
||||
|
||||
/*
|
||||
* Open the given provider and at least check if this is a block device.
|
||||
*/
|
||||
int
|
||||
g_open(const char *name, int dowrite)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
char *path;
|
||||
int fd;
|
||||
|
||||
if (name[0] == '/')
|
||||
strlcpy(path, name, sizeof(path));
|
||||
else
|
||||
snprintf(path, sizeof(path), "%s%s", _PATH_DEV, name);
|
||||
|
||||
fd = open(path, dowrite ? O_RDWR : O_RDONLY);
|
||||
path = g_device_path_open(name, &fd, dowrite);
|
||||
if (path != NULL)
|
||||
free(path);
|
||||
if (fd == -1)
|
||||
return (-1);
|
||||
/* Let try to get sectorsize, which will prove it is a GEOM provider. */
|
||||
if (g_sectorsize(fd) == -1) {
|
||||
close(fd);
|
||||
errno = EFTYPE;
|
||||
return (-1);
|
||||
}
|
||||
return (fd);
|
||||
}
|
||||
|
||||
@ -120,6 +113,19 @@ g_sectorsize(int fd)
|
||||
return ((ssize_t)sectorsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the correct provider name.
|
||||
*/
|
||||
char *
|
||||
g_providername(int fd)
|
||||
{
|
||||
char name[MAXPATHLEN];
|
||||
|
||||
if (g_ioctl_arg(fd, DIOCGPROVIDERNAME, name) == -1)
|
||||
return (NULL);
|
||||
return (strdup(name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Call BIO_FLUSH for the given provider.
|
||||
*/
|
||||
@ -234,3 +240,77 @@ end:
|
||||
}
|
||||
return (fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the device path device given a partial or full path to its node.
|
||||
* A pointer can be provided, which will be set to an opened file descriptor of
|
||||
* not NULL.
|
||||
*/
|
||||
static char *
|
||||
g_device_path_open(const char *devpath, int *fdp, int dowrite)
|
||||
{
|
||||
char *path;
|
||||
int fd;
|
||||
|
||||
/* Make sure that we can fail. */
|
||||
if (fdp != NULL)
|
||||
*fdp = -1;
|
||||
/* Use the device node if we're able to open it. */
|
||||
do {
|
||||
fd = open(devpath, dowrite ? O_RDWR : O_RDONLY);
|
||||
if (fd == -1)
|
||||
break;
|
||||
/*
|
||||
* Let try to get sectorsize, which will prove it is a GEOM
|
||||
* provider.
|
||||
*/
|
||||
if (g_sectorsize(fd) == -1) {
|
||||
close(fd);
|
||||
errno = EFTYPE;
|
||||
return (NULL);
|
||||
}
|
||||
if ((path = strdup(devpath)) == NULL) {
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
if (fdp != NULL)
|
||||
*fdp = fd;
|
||||
else
|
||||
close(fd);
|
||||
return (path);
|
||||
} while (0);
|
||||
|
||||
/* If we're not given an absolute path, assume /dev/ prefix. */
|
||||
if (*devpath != '/') {
|
||||
asprintf(&path, "%s%s", _PATH_DEV, devpath);
|
||||
if (path == NULL)
|
||||
return (NULL);
|
||||
fd = open(path, dowrite ? O_RDWR : O_RDONLY);
|
||||
if (fd == -1) {
|
||||
free(path);
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* Let try to get sectorsize, which will prove it is a GEOM
|
||||
* provider.
|
||||
*/
|
||||
if (g_sectorsize(fd) == -1) {
|
||||
free(path);
|
||||
close(fd);
|
||||
errno = EFTYPE;
|
||||
return (NULL);
|
||||
}
|
||||
if (fdp != NULL)
|
||||
*fdp = fd;
|
||||
else
|
||||
close(fd);
|
||||
return (path);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
g_device_path(const char *devpath)
|
||||
{
|
||||
return (g_device_path_open(devpath, NULL, 0));
|
||||
}
|
||||
|
@ -154,6 +154,8 @@ int g_delete(int, off_t, off_t);
|
||||
int g_get_ident(int, char *, size_t);
|
||||
int g_get_name(const char *, char *, size_t);
|
||||
int g_open_by_ident(const char *, int, char *, size_t);
|
||||
char *g_device_path(const char *);
|
||||
char *g_providername(int);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
@ -244,6 +244,7 @@ g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread
|
||||
{
|
||||
struct g_geom *gp;
|
||||
struct g_consumer *cp;
|
||||
struct g_provider *pp;
|
||||
struct g_kerneldump kd;
|
||||
off_t offset, length, chunk;
|
||||
int i, error;
|
||||
@ -251,6 +252,7 @@ g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread
|
||||
|
||||
gp = dev->si_drv1;
|
||||
cp = dev->si_drv2;
|
||||
pp = cp->provider;
|
||||
|
||||
error = 0;
|
||||
KASSERT(cp->acr || cp->acw,
|
||||
@ -329,6 +331,11 @@ g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread
|
||||
case DIOCGIDENT:
|
||||
error = g_io_getattr("GEOM::ident", cp, &i, data);
|
||||
break;
|
||||
case DIOCGPROVIDERNAME:
|
||||
if (pp == NULL)
|
||||
return (ENOENT);
|
||||
strlcpy(data, pp->name, i);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (cp->provider->geom->ioctl != NULL) {
|
||||
|
@ -98,4 +98,10 @@ void disk_err(struct bio *bp, const char *what, int blkdone, int nl);
|
||||
* - ident is optional and applications can't relay on its presence.
|
||||
*/
|
||||
|
||||
#define DIOCGPROVIDERNAME _IOR('d', 138, char[MAXPATHLEN])
|
||||
/*-
|
||||
* Store the provider name, given a device path, in a buffer. The buffer
|
||||
* must be at least MAXPATHLEN bytes long.
|
||||
*/
|
||||
|
||||
#endif /* _SYS_DISK_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user