Issue 6: Discussion - What if two LV's are created already ?
Project Member Reported by sandeepksinha, Dec 18, 2008
Hi Vineet,

What if there are two LV's created on the machine ?
Don't run and see the output of the code, you should be able to make that
out logically if your code would be able to make out.

Also, how would you determine that which one's information you have to fetch.
That means that your interface should be something like, You pass a dev_t
and it should give you the complete table.
dev_t would be the device number of the logical volume on which the file
system is installed.

I am looking into the code for more details. Kindly update your findings.
Dec 19, 2008
Project Member #1 sandeepksinha
Hi Guys,
I have found out a simple solution, say just a matter of 5-10 lines, and if you pass
the dev_t of a volume, I will provide you will the complete table of the same.
Its quite simple and easy.

For exact details, stay tuned. I am playing around with the code for a while. Just on
the verge of concluding this issue.
Dec 19, 2008
Project Member #2 sandeepksinha
Hi Vineet,
I need your insights on this issue,

The changes that you made into __table_get_device will capture information about all
the LV's that are created on the machine, Un-necessarily. What if your array overflows ??

I think this is just a work-around and not a practical solution to be taken into
consideration for implementation.

Wat Say ?

RKS were you too involved ?
Dec 19, 2008
Project Member #4 sandeepksinha
(No comment was entered for this change.)
Cc: checkout.vineet
Dec 19, 2008
Project Member #5 imreckless@gmail.com
Yes sir i was involved.
Dec 19, 2008
Project Member #6 imreckless@gmail.com
Yes sir its just a work around, we will modify it.
Dec 19, 2008
Project Member #7 checkout...@gmail.com
yes sir my code would definitely inform you about the other LV present on the system 
and the array too would overflow .

i have just coded to fetch the information. I thought that to use pointer instead of
array and allocate memory for each structure created as no of devices cannot be
restricted. it could be more than ten. 


Dec 19, 2008
Project Member #8 sandeepksinha
Hi friends,

Read the following doc below. I have uploaded it under the downloads section as well.
All of you must read this doc. 



HOW DEVICE MAPPER WORKS
sandeepksinha@gmail.com

All information in this document is in context with ohsm.


The device mapper initially creates a structure called mapped_device, which basically
is the new LV that’s created and which is visible from the user space too. i.e.
/dev/vg/lvol0. Now for each of the devices used by this LV internally, the device
mapper maintains a structure called dm_target.


struct mapped_device {
  88        struct rw_semaphore io_lock;
  89        struct mutex suspend_lock;
  90        spinlock_t pushback_lock;
  91        rwlock_t map_lock;
  92        atomic_t holders;
  93        atomic_t open_count;
  94
  95        unsigned long flags;
  96
  97        struct request_queue *queue;
  98        struct gendisk *disk;
  99        char name[16];
 100
 101        void *interface_ptr;
 102
 103        /*
 104         * A list of ios that arrived while we were suspended.
 105         */
 106        atomic_t pending;
 107        wait_queue_head_t wait;
 108        struct bio_list deferred;
 109        struct bio_list pushback;
 110
 111        /*
 112         * Processing queue (flush/barriers)
 113         */
 114        struct workqueue_struct *wq;
 115
 116        /*
 117         * The current mapping.
 118         */
 119        struct dm_table *map;
 120
 121        /*
 122         * io objects are allocated from here.
 123         */
 124        mempool_t *io_pool;
 125        mempool_t *tio_pool;
 126
 127        struct bio_set *bs;
 128
 129        /*
 130         * Event handling.
 131         */
 132        atomic_t event_nr;
 133        wait_queue_head_t eventq;
 134        atomic_t uevent_seq;
 135        struct list_head uevent_list;
 136        spinlock_t uevent_lock; /* Protect access to uevent_list */
 137
 138        /*
 139         * freeze/thaw support require holding onto a super block
 140         */
 141        struct super_block *frozen_sb;
 142        struct block_device *suspended_bdev;
 143
 144        /* forced geometry settings */
 145        struct hd_geometry geometry;
 146};
 147


Now, if you look at this structure, one of the most important information that it
holds is that struct dm_table *map. This holds all the mapping information pertaining
to the newly created LV. There are other fields too in this structure but those are
used majorly for the purpose of i/o, event handling, work queues and other
information. It also holds struct gendisk *disk, which is of some interest to us but
not exactly required for the device mapper table of ohsm. We will discuss struct
gendisk later. For now our major focus is on the struct dm_table *map, which holds
all the mapping information for this LV. The structure is illustrated below. 


struct dm_table {
  28        struct mapped_device *md;
  29        atomic_t holders;
  30
  31        /* btree table */
  32        unsigned int depth;
  33        unsigned int counts[MAX_DEPTH]; /* in nodes */
  34        sector_t *index[MAX_DEPTH];
  35
  36        unsigned int num_targets;
  37        unsigned int num_allocated;
  38        sector_t *highs;
  39        struct dm_target *targets;
  40
  41        /*
  42         * Indicates the rw permissions for the new logical
  43         * device.  This should be a combination of FMODE_READ
  44         * and FMODE_WRITE.
  45         */
  46        int mode;
  47
  48        /* a list of devices used by this table */
  49        struct list_head devices;
  50
  51        /*
  52         * These are optimistic limits taken from all the
  53         * targets, some targets will need smaller limits.
  54         */
  55        struct io_restrictions limits;
  56
  57        /* events get handed up using this callback */
  58        void (*event_fn)(void *);
  59        void *event_context;
  60};

Well, we should not forget that this device mapper becomes a layer between the file
system and the actual physical device. So, all together there are three block levels.
One at the file system, another at the device mapper level and finally there is one
at the physical device level, which we usually refer through the bio structure. 

So, the use of the btree table above is to keep the mapping between the device mapper
and the actual physical device. Now, this again becomes a topic of least interest to
us for now as we are more interested in the mapping between the file system and the
device mapper.

This information is held by struct dm_target *targets in the above structure. 
The device mapper creates an instance of this for each device that it used internally
by this LV. Say, for example, if the LV is using /dev/sdc1, /dev/sdc2 and /dev/sda1
then, it will have pointers to these three structures. It can be accessed through the
targets member of the above structure 

The total number of targets is maintained by unsigned int num_targets, which can be
used to figure out the number of underlying devices used by this LV at any instance
of time. Let me take you through the dm_target structure now.

This is how it looks:

struct dm_target {
 131        struct dm_table *table;
 132        struct target_type *type;
 133
 134        /* target limits */
 135        sector_t begin;
 136        sector_t len;
 137
 138        /* FIXME: turn this into a mask, and merge with io_restrictions */
 139        /* Always a power of 2 */
 140        sector_t split_io;
 141
 142        /*
 143         * These are automatically filled in by
 144         * dm_table_get_device.
 145         */
 146        struct io_restrictions limits;
 147
 148        /* target specific data */
 149        void *private;
 150
 151        /* Used to provide an error string from the ctr */
 152        char *error;
 153};
 154

I think we are almost done, what we required was the beginning and end boundaries of
each of these devices that’s being mapped on this LV.
You can easily see it right there under the roof of target limits. The  members are
sector_t begin and sector_t len. 

We can simply use this information to get the beginning and end boundaries of each of
these devices.

Solutions:

Now we have different approaches to get this information.

1.	If you have the name of the LV.
a.	Convert it to dev_t
b.	Struct mapped_device *md = dm_find_md(dev_t);
c.	Struct dm_table *map = md->map;
d.	Int num_target = map->num_targets;
e.	Struct dm_target *tgt = map->targets;

2.	If you have the inode structure.
a.	Struct mapped_device *md = inode->i_bdev->bd_disk->private_data;
b.	Follow the previous steps.
			
3.	Add a case to the dm-ioctl’s.
a.	I will illustrate this in the sample example code.


Sample code to get this mapping table printed using method 3:

md = inode->i_bdev->bd_disk->private_data;
map = dm_get_table(md); 				/* md->map */
i = dm_table_get_num_targets(map); 	/* map->num_targets */
tgt = dm_table_get_target(map,0); 		/* map->targets */

while (i--)
	{
		Print tgt->begin;
		Print tgt->len;
		tgt++;
	}


Hope this helps you get the basics of device mapper in place.

Status: Needs-Review
Dec 19, 2008
Project Member #9 sandeepksinha
Will soon close this issue as soon as you all confirm to this. I know the Lead for
this module is not here but still I need to take a call for this asap.

Let me know guys.... if you still see issues.
Status: Review-Req
Dec 20, 2008
Project Member #10 checkout...@gmail.com
yes sir/
it would definitely work. Moreover the problem of printing the existing Logical
Volumes on the system is solved. It would only print the Logical Volume that is
passed to it like /dev/vgname/lvol0.
Status: Done
Dec 21, 2008
Project Member #11 sandeepksinha
I hope this issue is resolved.
Vineet can you just confirm, I have already uploaded the doc as well.

Can I go ahead and mark it as done?
Dec 21, 2008
Project Member #12 checkout...@gmail.com
yes sir u can turn the status as done as the above solution is indeed satisfactory