All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arno Wagner <arno@wagner.name>
To: dm-crypt@saout.de
Subject: Re: [dm-crypt] From /dev/mapper to the real device
Date: Tue, 18 Jan 2011 15:25:46 +0100	[thread overview]
Message-ID: <20110118142546.GA4056@tansi.org> (raw)
In-Reply-To: <4D355EC0.6090402@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 1618 bytes --]



On Tue, Jan 18, 2011 at 10:34:56AM +0100, Milan Broz wrote:
> On 01/18/2011 10:01 AM, Xavier Nicollet wrote:
> > I did something like that:
> > cryptsetup luksOpen /dev/mapper/lv_device crypto_device
> > 
> > I would like to find a way, given /dev/mapper/crypto_device, to find
> > which lv_device it was built from.
> 
> cryptsetup status crypto_device (for active mapping)?
> 
> (But note this device name is not always the same you used, for LV you can
> have several symlinks /dev/mapper/vg-lv or /dev/vg/lv or /dev/by-uuid/... 
> so there are hardcoded priorities)

I have a Python script, that does a traversal of /dev/
to find all devices mapped to the same object as a node 
in /dev/mapper/ for each node in /dev/mapper/. This works
by comparing not names, but major and minor device number.
It does not work for symlinks though, only for duplicate
device special files. Symliks could be added easily though.

Not very elegant, but works. Copy for current cryptsetup 
is attached. Sample output:

/dev/mapper/c1 is active and is in use.
  type:  PLAIN
  cipher:  aes-cbc-essiv:sha256
  keysize: 256 bits
  devices: (9, 6)  /dev/md6  
  offset:  0 sectors
  size:    387462831 sectors
  mode:    read/write
  mounted: /opt

Gruesse,
Arno

-- 
Arno Wagner, Dr. sc. techn., Dipl. Inform., CISSP -- Email: arno@wagner.name 
GnuPG:  ID: 1E25338F  FP: 0C30 5782 9D93 F785 E79C  0296 797F 6B50 1E25 338F
----
Cuddly UI's are the manifestation of wishful thinking. -- Dylan Evans

If it's in the news, don't worry about it.  The very definition of 
"news" is "something that hardly ever happens." -- Bruce Schneier 

[-- Attachment #2: cryptstat --]
[-- Type: text/plain, Size: 6036 bytes --]

#!/usr/bin/python

# cryptstat.py

# Displays all matching devices in /dev/ for a cryptsetup target

# Calls "cryptsetup status <target>" to get the initial info,
# then determines major/minor of the reported device and does
# a traversal of /dev/ to find all matches.
# Reports an augemented result of "cryptsetup status", also
# including mount points.

# Arguments are any number of cryptsetup targets. Does a validity
# check and refuses targets not found in /dev/mapper/
# Without argument, displays info on all targets found in /dev/mapper/

# (c) Arno Wagner 2010, distributed under the modified BSD license.
# Version 0.03 
# Version history
# 0.03 Adjustments for cryptsrtup 1.2.0
# 0.02 fixed error on unmounted but mapped devices

import sys, os, stat, subprocess, re

dev_path = '/dev' 
mapper_path = '/dev/mapper'
cryptsetup_path = '/usr/sbin/cryptsetup'

# Utility functions

def normalize_path(path):
    """Replaces any number of occurences of '/' with a single '/'"""
    # Note: INefficient, but should not matter
    while path.find('//') > -1:
        path = path.replace('//','/')
    return(path)    

def dir_walk(dir):
    """Returns a list of all filenames with full paths
       (including dirs, specials, etc.) below the argument.
       "." and ".." are omitted. Does not follow symblinks
       to avoid loops, but there is no real loop prevention."""
    names = []
    dir = normalize_path(dir)
    # process current directory 
    current = os.listdir(dir)
    for d in current:
        d = dir + '/' + d
        # Test whether d is a directory. If so, recurse.
        s = os.lstat(d)
        if stat.S_ISDIR( s[stat.ST_MODE] ):
            names.extend(dir_walk(d))  
        else:
            names.append(d)
    return(names)        

def dir_walk_block(dir):
    """Returns the names of all block devices in the subtree at dir"""
    names = dir_walk(dir)
    block_dev = []
    for n in names:
        if stat.S_ISBLK(os.lstat(n)[stat.ST_MODE]):
            block_dev.append(n)
    return(block_dev)

def special_dev_major_minor(n):
    """Returns (major,minor) for a device special file name"""
    s = os.lstat(n)
    if not stat.S_ISBLK(s[stat.ST_MODE]) and \
       not stat.S_ISCHR(s[stat.ST_MODE]) :
       return None
    else:
       maj = os.major(s.st_rdev)
       min = os.minor(s.st_rdev)
       return (maj, min)

def build_block_major_minor_tables(dir):
    """Returns 
       1) a table of filenames that are all block special files
       2) a dict mapping each name to (major,minor)
       3) a dict mapping each (major,minor) pair to a table of filenames"""
    names = []
    name2pair = {}
    pair2name = {}

    names = dir_walk_block(dir)
    for n in names:
        maj, min = special_dev_major_minor(n)
        name2pair[n] = (maj, min)
        if (maj, min) not in pair2name:
            pair2name[(maj, min)] = [n]
        else:
            pair2name[(maj, min)].append(n) 
        
    return (names, name2pair, pair2name)


# Start of main action

# determine list of targets to be processed
targets = []
# first get all in mapper_path except 'control'
mapper_targets = []
mapper_entries = os.listdir(mapper_path)
tmp = []
for e in mapper_entries:
    if e != 'control':
        tmp.append(e)
mapper_entries = tmp

# if argument list empty, copy mapper_entries
if len(sys.argv) == 1:
    targets = mapper_entries
    targets.sort()
else:
    targets = sys.argv[1:]

# Make sure all targets are in mapper_entries 
tbl = {}
for e in mapper_entries:
    tbl[e] = None
for e in targets:
    if e not in tbl:
        print '\nError: Command argument "'+e+'" is not present in '+\
              'mapper dir '+mapper_path+'!\nAborting\n'
        sys.exit(1)    

# print targets

# Create mappings (major,minor) <-> name
names, name2pair, pair2names = build_block_major_minor_tables(dev_path)

print

for t in targets:
    # do call to "cryptsetup status"
    cmd = cryptsetup_path + ' status ' + t
#    print 'calling "' + cmd + '"'
    p = subprocess.Popen(cmd, shell=True, bufsize=0,
             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
             stderr=subprocess.PIPE, close_fds=True)
    (out, err) = p.communicate()
    out_lines = out.splitlines()
    if (p.returncode != 0): raise IOError(p.returncode, err)  
#    print('command output = [' + out + ']')
    # check output line 7 for '  device:  <device name>'
    if not re.match('\ \ device\:\ \ \S+', out_lines[4]):
        print '\nError: Line 7 of cryptsetup output has unexpected form'
        print 'Expected: "  device:  <device name>'
        print 'found: [' + out_lines[4]+ ']'
        print 'complete cryptsetup output:\m'
        print out
        print '\nAborting!\n'
        sys.exit(1)
    device = out_lines[4][11:]
#    print 'device found: [' + device + ']'
    (maj, min) = name2pair[device]
#    print '(maj, min) = ', (maj, min)
    devices = pair2names[(maj, min)]
    dev_str = ''
    for d in devices: dev_str = dev_str + d + '  '
#    print 'devices: ', dev_str
    out_lines[4] = '  devices: '+str((maj, min))+'  '+dev_str
    for l in out_lines: print l
    # determine mounts and print them
    mounts = '  mounted:'
    # ';echo' in next command is so that we have at least one line
    # of output to avoid an error from subprocess
    cmd = 'mount | grep '+mapper_path+'/'+t+'; echo'
#    print 'calling "' + cmd + '"'
    p = subprocess.Popen(cmd, shell=True, bufsize=0,
             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
             stderr=subprocess.PIPE, close_fds=True)
    (out, err) = p.communicate()
    out_lines = out.splitlines()
#    print('command output = [' + out + ']')
    if (p.returncode != 0): raise IOError(p.returncode, err)  
    if len(out_lines) == 1:
        mounts = mounts + ' not mounted'
    else:
        for l in out_lines:       
#           print 'l = ', l
           match = re.search(' on (\S+) type', l)
           if match != None:
               mounts = mounts + ' ' + match.group(1)
    print mounts
    print













  reply	other threads:[~2011-01-18 14:25 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-18  9:01 [dm-crypt] From /dev/mapper to the real device Xavier Nicollet
2011-01-18  9:34 ` Milan Broz
2011-01-18 14:25   ` Arno Wagner [this message]
2011-01-18 16:31     ` Thomas Bächler
2011-01-18 15:38   ` [dm-crypt] Another corrupt luks header thread Viktor Ekmark
2011-01-18 16:36     ` Thomas Bächler
2011-01-18 18:54     ` Arno Wagner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110118142546.GA4056@tansi.org \
    --to=arno@wagner.name \
    --cc=dm-crypt@saout.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.