#include "sysfs.h"
#include "fileutils.h"
#include "all-io.h"
+#include "debug.h"
static void sysfs_blkdev_deinit_path(struct path_cxt *pc);
static int sysfs_blkdev_enoent_redirect(struct path_cxt *pc, const char *path, int *dirfd);
-static dev_t __sysfs_devname_to_devno(const char *prefix, const char *name, const char *parent);
+
+/*
+ * Debug stuff (based on include/debug.h)
+ */
+static UL_DEBUG_DEFINE_MASK(ulsysfs);
+UL_DEBUG_DEFINE_MASKNAMES(ulsysfs) = UL_DEBUG_EMPTY_MASKNAMES;
+
+#define ULSYSFS_DEBUG_INIT (1 << 1)
+#define ULSYSFS_DEBUG_CXT (1 << 2)
+
+#define DBG(m, x) __UL_DBG(ulsysfs, ULSYSFS_DEBUG_, m, x)
+#define ON_DBG(m, x) __UL_DBG_CALL(ulsysfs, ULSYSFS_DEBUG_, m, x)
+
+#define UL_DEBUG_CURRENT_MASK UL_DEBUG_MASK(ulsysfs)
+#include "debugobj.h"
+
+void ul_sysfs_init_debug(void)
+{
+ if (ulsysfs_debug_mask)
+ return;
+ __UL_INIT_DEBUG_FROM_ENV(ulsysfs, ULSYSFS_DEBUG_, 0, ULSYSFS_DEBUG);
+}
+
+struct path_cxt *ul_new_sysfs_path(dev_t devno, struct path_cxt *parent, const char *prefix)
+{
+ struct path_cxt *pc = ul_new_path(NULL);
+
+ if (!pc)
+ return NULL;
+ if (prefix)
+ ul_path_set_prefix(pc, prefix);
+
+ if (sysfs_blkdev_init_path(pc, devno, parent) != 0) {
+ ul_unref_path(pc);
+ return NULL;
+ }
+
+ DBG(CXT, ul_debugobj(pc, "alloc"));
+ return pc;
+}
/*
* sysfs_blkdev_* is sysfs extension to ul_path_* API for block devices.
*
+ * The function is possible to call in loop and without sysfs_blkdev_deinit_path().
+ * The sysfs_blkdev_deinit_path() is automatically called by ul_unref_path().
+ *
*/
int sysfs_blkdev_init_path(struct path_cxt *pc, dev_t devno, struct path_cxt *parent)
{
return rc;
/* initialize sysfs blkdev specific stuff */
- blk = calloc(1, sizeof(struct sysfs_blkdev));
- if (!blk)
- return -ENOMEM;
+ blk = ul_path_get_dialect(pc);
+ if (!blk) {
+ DBG(CXT, ul_debugobj(pc, "alloc new sysfs handler"));
+ blk = calloc(1, sizeof(struct sysfs_blkdev));
+ if (!blk)
+ return -ENOMEM;
- blk->devno = devno;
- ul_path_set_dialect(pc, blk, sysfs_blkdev_deinit_path);
+ ul_path_set_dialect(pc, blk, sysfs_blkdev_deinit_path);
+ ul_path_set_enoent_redirect(pc, sysfs_blkdev_enoent_redirect);
+ }
+ DBG(CXT, ul_debugobj(pc, "init sysfs stuff"));
+
+ blk->devno = devno;
sysfs_blkdev_set_parent(pc, parent);
- ul_path_set_enoent_redirect(pc, sysfs_blkdev_enoent_redirect);
return 0;
}
if (!pc)
return;
+
+ DBG(CXT, ul_debugobj(pc, "deinit"));
+
blk = ul_path_get_dialect(pc);
if (!blk)
return;
ul_ref_path(blk->parent);
free(blk);
+
+ ul_path_set_dialect(pc, NULL, NULL);
}
int sysfs_blkdev_set_parent(struct path_cxt *pc, struct path_cxt *parent)
} else
blk->parent = NULL;
+ DBG(CXT, ul_debugobj(pc, "new parent"));
return 0;
}
+struct path_cxt *sysfs_blkdev_get_parent(struct path_cxt *pc)
+{
+ struct sysfs_blkdev *blk = ul_path_get_dialect(pc);
+ return blk ? blk->parent : NULL;
+}
+
/*
* Redirects ENOENT errors to the parent, if the path is to the queue/
* sysfs directory. For example
if (blk && blk->parent && strncmp(path, "queue/", 6) == 0) {
*dirfd = ul_path_get_dirfd(blk->parent);
- if (*dirfd >= 0)
+ if (*dirfd >= 0) {
+ DBG(CXT, ul_debugobj(pc, "%s redirected to parent", path));
return 0;
+ }
}
return 1; /* no redirect */
}
}
closedir(dir);
+ DBG(CXT, ul_debugobj(pc, "partno (%d) -> devno (%d)", (int) partno, (int) devno));
return devno;
}
}
if (diskdevno) {
- *diskdevno = __sysfs_devname_to_devno(ul_path_get_prefix(pc), diskname, NULL);
+ *diskdevno = __sysfs_devname_to_devno(ul_path_get_prefix(pc), name, NULL);
if (!*diskdevno)
goto err;
}
if (!devno)
return -EINVAL;
- pc = ul_new_path(NULL);
+ pc = ul_new_sysfs_path(devno, NULL, NULL);
if (!pc)
return -ENOMEM;
- rc = sysfs_blkdev_init_path(pc, devno, NULL);
- if (!rc)
- rc = sysfs_blkdev_get_wholedisk(pc, diskname, len, diskdevno);
+ rc = sysfs_blkdev_get_wholedisk(pc, diskname, len, diskdevno);
ul_unref_path(pc);
return rc;
}
char *id = NULL;
int rc = 0;
- pc = ul_new_path(NULL);
+ pc = ul_new_sysfs_path(devno, NULL, NULL);
if (!pc)
goto done;
- if (sysfs_blkdev_init_path(pc, devno, NULL) != 0)
- goto done;
if (ul_path_read_string(pc, &id, "dm/uuid") <= 0 || !id)
goto done;
return (len < 0 || (size_t) len >= bufsz) ? NULL : buf;
}
-int sysfs_scsi_has_attribute(struct path_cxt *pc, const char *attr)
+int sysfs_blkdev_scsi_has_attribute(struct path_cxt *pc, const char *attr)
{
char path[PATH_MAX];
struct stat st;
return stat(path, &st) == 0;
}
-int sysfs_scsi_path_contains(struct path_cxt *pc, const char *pattern)
+int sysfs_blkdev_scsi_path_contains(struct path_cxt *pc, const char *pattern)
{
char path[PATH_MAX], linkc[PATH_MAX];
struct stat st;
return dev;
}
-static dev_t __sysfs_devname_to_devno(const char *prefix, const char *name, const char *parent)
+dev_t __sysfs_devname_to_devno(const char *prefix, const char *name, const char *parent)
{
char buf[PATH_MAX];
char *_name = NULL; /* name as encoded in sysfs */
if (!prefix)
prefix = "";
+ assert(name);
+
if (strncmp("/dev/", name, 5) == 0) {
/*
* Read from /dev
*/
char *sysfs_devno_to_devpath(dev_t devno, char *buf, size_t bufsiz)
{
- struct path_cxt *pc = ul_new_path(NULL);
+ struct path_cxt *pc = ul_new_sysfs_path(devno, NULL, NULL);
char *res = NULL;
- if (sysfs_blkdev_init_path(pc, devno, NULL) == 0)
+ if (pc) {
res = sysfs_blkdev_get_path(pc, buf, bufsiz);
-
- ul_unref_path(pc);
+ ul_unref_path(pc);
+ }
return res;
}
char *sysfs_devno_to_devname(dev_t devno, char *buf, size_t bufsiz)
{
- struct path_cxt *pc = ul_new_path(NULL);
+ struct path_cxt *pc = ul_new_sysfs_path(devno, NULL, NULL);
char *res = NULL;
- if (sysfs_blkdev_init_path(pc, devno, NULL) == 0)
+ if (pc) {
res = sysfs_blkdev_get_name(pc, buf, bufsiz);
-
- ul_unref_path(pc);
+ ul_unref_path(pc);
+ }
return res;
}
if (argc != 2)
errx(EXIT_FAILURE, "usage: %s <devname>", argv[0]);
+ ul_sysfs_init_debug();
+
devname = argv[1];
devno = sysfs_devname_to_devno(devname);
printf(" WHOLEDISK-DEVNO: %u (%d:%d)\n", (unsigned int) disk_devno, major(disk_devno), minor(disk_devno));
printf(" WHOLEDISK-DEVNAME: %s\n", diskname);
- pc = ul_new_path(NULL);
- if (sysfs_blkdev_init_path(pc, devno, NULL) != 0)
+ pc = ul_new_sysfs_path(devno, NULL, NULL);
+ if (!pc)
goto done;
printf("context based:\n");
printf(" PARTITION: %s\n", is_part ? "YES" : "NOT");
if (is_part && disk_devno) {
- struct path_cxt *disk_pc = ul_new_path(NULL);
-
- sysfs_blkdev_init_path(disk_pc, disk_devno, NULL);
+ struct path_cxt *disk_pc = ul_new_sysfs_path(disk_devno, NULL, NULL);
sysfs_blkdev_set_parent(pc, disk_pc);
+
+ ul_unref_path(disk_pc);
}
printf(" HOTPLUG: %s\n", sysfs_blkdev_is_hotpluggable(pc) ? "yes" : "no");