tools/biolatpcts: Accept device name/node for target device selection

MAJ:MIN is cumbersome. Update it to accept DEVNAME and /dev/DEVNAME too.
diff --git a/tools/biolatpcts.py b/tools/biolatpcts.py
index 358414d..9db210e 100755
--- a/tools/biolatpcts.py
+++ b/tools/biolatpcts.py
@@ -2,8 +2,8 @@
 #
 # biolatpcts.py  Monitor IO latency distribution of a block device.
 #
-#  $ ./biolatpcts.py 259:0
-#  259:0      p1    p5   p10   p16   p25   p50   p75   p84   p90   p95   p99  p100
+#  $ ./biolatpcts.py /dev/nvme0n1
+#  nvme0n1    p1    p5   p10   p16   p25   p50   p75   p84   p90   p95   p99  p100
 #  read     95us 175us 305us 515us 895us 985us 995us 1.5ms 2.5ms 3.5ms 4.5ms  10ms
 #  write     5us   5us   5us  15us  25us 135us 765us 855us 885us 895us 965us 1.5ms
 #  discard   5us   5us   5us   5us 135us 145us 165us 205us 385us 875us 1.5ms 2.5ms
@@ -18,6 +18,7 @@
 import argparse
 import json
 import sys
+import os
 
 description = """
 Monitor IO latency distribution of a block device
@@ -25,8 +26,8 @@
 
 parser = argparse.ArgumentParser(description = description,
                                  formatter_class = argparse.ArgumentDefaultsHelpFormatter)
-parser.add_argument('devno', metavar='MAJ:MIN', type=str,
-                    help='Target block device number')
+parser.add_argument('dev', metavar='DEV', type=str,
+                    help='Target block device (/dev/DEVNAME, DEVNAME or MAJ:MIN)')
 parser.add_argument('-i', '--interval', type=int, default=3,
                     help='Report interval')
 parser.add_argument('-w', '--which', choices=['from-rq-alloc', 'after-rq-alloc', 'on-device'],
@@ -100,6 +101,18 @@
 args.pcts = args.pcts.split(',')
 args.pcts.sort(key=lambda x: float(x))
 
+try:
+    major = int(args.dev.split(':')[0])
+    minor = int(args.dev.split(':')[1])
+except Exception:
+    if '/' in args.dev:
+        stat = os.stat(args.dev)
+    else:
+        stat = os.stat('/dev/' + args.dev)
+
+    major = os.major(stat.st_rdev)
+    minor = os.minor(stat.st_rdev)
+
 if args.which == 'from-rq-alloc':
     start_time_field = 'alloc_time_ns'
 elif args.which == 'after-rq-alloc':
@@ -110,8 +123,8 @@
     die()
 
 bpf_source = bpf_source.replace('__START_TIME_FIELD__', start_time_field)
-bpf_source = bpf_source.replace('__MAJOR__', str(int(args.devno.split(':')[0])))
-bpf_source = bpf_source.replace('__MINOR__', str(int(args.devno.split(':')[1])))
+bpf_source = bpf_source.replace('__MAJOR__', str(major))
+bpf_source = bpf_source.replace('__MINOR__', str(minor))
 
 bpf = BPF(text=bpf_source)
 bpf.attach_kprobe(event="blk_account_io_done", fn_name="kprobe_blk_account_io_done")
@@ -236,7 +249,7 @@
             result[io_type[iot]] = lats
         print(json.dumps(result), flush=True)
     else:
-        print('\n{:<7}'.format(args.devno), end='')
+        print('\n{:<7}'.format(os.path.basename(args.dev)), end='')
         widths = []
         for pct in args.pcts:
             widths.append(max(len(pct), 5))