[dm-devel] Device Mapper Persistent Configuration

Doug Dumitru doug at easyco.com
Mon Jun 29 14:22:49 UTC 2015


Gili,

For some reason, reply-all did not pick up your email address.  My mistake.

1)  This is usually done from user space.  User space programs can run
really early.  mdadm does this to start software raid sets.  It is probably
possible to scan devices from the module, but a lot of stuff may not be
there yet if you statically load it.  device-mapper block devices are
allowed to "stack", so one of your constituent devices could be /dev/md0,
or crypt target, or a network mount, or who knows.

In terms of "how early" your user space program can run, the answer is that
it can run from initrd before the root file system is even mounted
read/write.

2)  Creating stuff in proc has a number of articles on-line.  I don't have
a link handy right now.  One thing to watch out for is that the proc
interface changed pretty radically in 3.10.0.  Before this, files uses a
simple buffer API.  After this, file use the stock system sequential file
API.  The buffer API had an edge condition deadlock, thus the change.

The "pieces" are proc_mkdir(...) to create a directory (pretty simple), and
here are helper functions from some of my code to create and delete an
actual proc "file".  Note that this code does not use function prototypes,
so RdFn and WtFn should actually be prototyped as:

int ProcRead_vars_stream(struct seq_file *m, void *dev, void *pv)

I use "dev" as a pointer to the "device context" that device mapper uses to
track instances.  Device context is actually a windows driver term for
block filters, which are the analog of a device mapper block filter.  "pv"
is a pointer to more local data.  This can let you write a single proc
handler function, but give it multiple tasks based on the data parameter.

This code is from a really big and convoluted module, so I can't give you
much more of it.


void * _shim_create_proc_seq_entry(char *name, void *parent, int mode, void
*RdFn, void *WtFn, void *dev, void *data, u64 MaxIdx)

{
    struct _PROC_RES *r;

    if ( !( r = kzalloc(sizeof(*r), GFP_KERNEL) ) ) return NULL;

    r->file_ops.owner    = THIS_MODULE;

    strcpy(r->name, name);
    r->mode       = mode;
    r->RdFn       = RdFn;
    r->ShowFn     = RdFn;
    r->WtFn       = WtFn;
    r->dev        = dev;
    r->data       = data;
    r->ProcParent = parent;
    r->MaxIdx     = MaxIdx;

    switch ( mode ) {
        case 0 :            // Read only - single access
            r->file_ops.open    = _shim_proc_open;
            r->file_ops.read    = seq_read;
            r->file_ops.llseek  = seq_lseek;
            r->file_ops.release = single_release;
            r->ProcHandle = proc_create_data(r->name, 0, parent,
&r->file_ops, r);
            break;
        case 1 :            // Read only - multiple access
            r->file_ops.open    = _shim_proc_open_mul;
            r->file_ops.read    = seq_read;
            r->file_ops.llseek  = seq_lseek;
            r->file_ops.release = seq_release;

            r->seq_ops.start = _shim_proc_seq_start;
            r->seq_ops.next  = _shim_proc_seq_next;
            r->seq_ops.stop  = _shim_proc_seq_stop;
            r->seq_ops.show  = _shim_proc_seq_show;

            r->ProcHandle = proc_create_data(r->name, 0, parent,
&r->file_ops, r);
            break;
        case 2 :            // Write only
            BUG();
            break;
        case 3 :            // Read write - single access
            r->file_ops.open    = _shim_proc_open;
            r->file_ops.read    = seq_read;
            r->file_ops.write   = _shim_proc_seq_write;
            r->file_ops.llseek  = seq_lseek;
            r->file_ops.release = single_release;
            r->ProcHandle = proc_create_data(r->name, 0644, parent,
&r->file_ops, r);
            break;
    }

    return r;
}

void _shim_remove_proc_seq_entry(void *data)

{
    struct _PROC_RES    *r = data;

    remove_proc_entry(r->name, r->ProcParent);
    kfree(r);
}


On Sun, Jun 28, 2015 at 11:42 PM, Gili B <gilib123 at hotmail.com> wrote:

> Hi
> I didnt receive the email below, so I've copied and pasted it from the
> archive , sory .
>
> Thanks for the reply ..
> I have a few followup quesions:
> 1) If I use a special signature to identify disks, like in mdraid, why
> must I have a user space tool to discover disks?
> If I want all volumes up and ready during a reboot, I prefer that the
> module do it when it loads.
> A user space program will start too late in the boot process.
> 2)Can you point me to some guide on how to export stuff in proc ?
>
> Thanks
> -gili
>
>
>  On Sun, Jun 28, 2015 at 8:21 AM, Gili B <gilib123 hotmail com> wrote:
>
> hi
>> We are starting working on a new device mapper module which has targets
>> similar
>> to the ones in thin module (pool and thin),  but it adds some additional
>> features.
>> The user should be able to create and use file systems on the thin
>> volumes.
>> I wanted to know what is the recommended  way to make the configuration
>> with dmsetup
>> persistent ?
>>
>
> ​You should probably use mdraid as an inspiration.  Put a signature block
> on every member device.  You can then write a user-space tool to scan
> devices and find the collections.  Be sure to use a good "signature" for
> your type of device, plus a good UUID signature so that different
> generations can be identified.
>>
>
>> We want that all file systems will be available after reboot.
>>
>
> ​If you get the device running early enough, then fstab should be able to
> mount file systems.
>>
>
>> Should we write our own configuration tool?  should we add special
>> configuration files?
>>
>
> ​You will probably need a user-space tool.  You can probably get away with
> no configuration file, but you should again use mdraid as inspiration so
> that your user-space tool gets limits of where to look for member pieces.
>>
>
>> Should the kernel module we write , automatically discover all the
>> configration and initialize accordingly?
>>
>>
>> Regarding debug - Is there a generic way to run dmsetup for example that
>> prints some inside details on the targets? (for example number of
>> outstanding ios, memory used etc)
>>
>
> ​You can do this three ways.  1)  build in IOCTL into your module that can
> query stuff.  2) export stuff in /sys.  3) export stuff in /proc.  I
> personally like exporting debug stuff into /proc.  Remember that printk is
> your friend.  I have even created "command" file in proc that then dump
> debug information with printk.  If you use /proc, you need to handle
> multiple instances of your mapper.  I use
> /proc/{my_project_name}/{instance_name}/...
>
>
>
> --
> dm-devel mailing list
> dm-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
>



-- 
Doug Dumitru
EasyCo LLC
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/dm-devel/attachments/20150629/665674ff/attachment.htm>


More information about the dm-devel mailing list