]> err.no Git - util-linux/commitdiff
losetup: use /sys/dev/block/.../loop/backing_file
authorKarel Zak <kzak@redhat.com>
Wed, 1 Dec 2010 13:04:35 +0000 (14:04 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 1 Dec 2010 13:04:35 +0000 (14:04 +0100)
The basic loopdev attributes are available in sysfs since kernel
2.6.37. This patch uses the backing_file attribute from sysfs for very
long filenames (the LOOP_GET_STATUS ioctl uses only 64 bytes for the
filename).

old version:
 # losetup -a
 /dev/loop0: [0804]:12865322 (/home/images/filesystems/this_is_really_really_long_directory_*)

new version:
 # losetup -a
 /dev/loop0: [0804]:12865322 (/home/images/filesystems/this_is_really_really_long_directory_name/ext2.img)

Signed-off-by: Karel Zak <kzak@redhat.com>
TODO
include/pathnames.h
mount/lomount.c

diff --git a/TODO b/TODO
index 99a651db6b6e188edf00d401fca5e09982d512cc..ecd67c67bd25e339831ab9cdad6f484919732ab3 100644 (file)
--- a/TODO
+++ b/TODO
@@ -4,6 +4,25 @@ login-utils:
  - clean up error codes
  - use err() and warn() macros rather than fprintf(stderr, ...)
 
+
+losetup
+-------
+
+ - don't use ioclts if sysfs supports loop attributes (since 2.6.37,
+   block/loopN/loop/* files)
+
+    - don't open loopdev in looplist_next(), check if /sys/block/loopN/loop
+      exists and returns ll.name rather than file descriptor
+
+    - add sysfs based version of show_loop() and use it for non-root users
+
+sysfs
+-----
+
+ - add lib/sysfs.c with functions that read block device attributes from /sys.
+   For more details see devno.c from libblkid, lsblk.c and lomount.c.
+
+
 libblkid
 --------
 
@@ -17,6 +36,7 @@ libblkid
 
  - add support for dasd PT (used for example on s390)
 
+
 blkid(8)
 -------
 
index c0572954e055ef847c7b7161ebbdf5ed3b1e63e8..efbd6a65c393c6c18e0ea2f4517898d0675f64f2 100644 (file)
@@ -82,6 +82,7 @@
 #define _PATH_PROC_MOUNTINFO   "/proc/self/mountinfo"
 
 #define _PATH_SYS_BLOCK                "/sys/block"
+#define _PATH_SYS_DEVBLOCK     "/sys/dev/block"
 
 #ifndef _PATH_MOUNTED
 # ifdef MOUNTED                                        /* deprecated */
index d6556fc71d1e10c8d5e1c665f85cbbda32c60120..90149536a5ccbfaaae9d340a2de1acb44e4b4b8b 100644 (file)
@@ -80,6 +80,35 @@ struct looplist {
 #define LLFLG_SUBDIR   (1 << 5)        /* /dev/loop/N */
 #define LLFLG_DFLT     (1 << 6)        /* directly try to check default loops */
 
+/* TODO: move to lib/sysfs.c */
+static char *loopfile_from_sysfs(const char *device)
+{
+       FILE *f;
+       struct stat st;
+       char buf[PATH_MAX], *res = NULL;
+
+       if (stat(device, &st) || !S_ISBLK(st.st_mode))
+               return NULL;
+
+       snprintf(buf, sizeof(buf), _PATH_SYS_DEVBLOCK "/%d:%d/loop/backing_file",
+                       major(st.st_rdev), minor(st.st_rdev));
+
+       f = fopen(buf, "r");
+       if (!f)
+               return NULL;
+
+       if (fgets(buf, sizeof(buf), f)) {
+               size_t sz = strlen(buf);
+               if (sz) {
+                       buf[sz - 1] = '\0';
+                       res = xstrdup(buf);
+               }
+       }
+
+       fclose(f);
+       return res;
+}
+
 int
 is_loop_device (const char *device) {
        struct stat st;
@@ -379,13 +408,26 @@ show_loop_fd(int fd, char *device) {
 
        if (ioctl(fd, LOOP_GET_STATUS64, &loopinfo64) == 0) {
 
+               char *lofile = NULL;
+
                loopinfo64.lo_file_name[LO_NAME_SIZE-2] = '*';
                loopinfo64.lo_file_name[LO_NAME_SIZE-1] = 0;
                loopinfo64.lo_crypt_name[LO_NAME_SIZE-1] = 0;
 
+               /* ioctl has limited buffer for backing file name, since
+                * kernel 2.6.37 the filename is available in sysfs too
+                */
+               if (strlen((char *) loopinfo64.lo_file_name) == LO_NAME_SIZE - 1)
+                       lofile = loopfile_from_sysfs(device);
+               if (!lofile)
+                       lofile = (char *) loopinfo64.lo_file_name;
+
                printf("%s: [%04" PRIx64 "]:%" PRIu64 " (%s)",
                       device, loopinfo64.lo_device, loopinfo64.lo_inode,
-                      loopinfo64.lo_file_name);
+                      lofile);
+
+               if (lofile != (char *) loopinfo64.lo_file_name)
+                       free(lofile);
 
                if (loopinfo64.lo_offset)
                        printf(_(", offset %" PRIu64 ), loopinfo64.lo_offset);