Tizen 2.1 base
[external/device-mapper.git] / lib / metadata / lv.c
1 /*
2  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3  * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
4  *
5  * This file is part of LVM2.
6  *
7  * This copyrighted material is made available to anyone wishing to use,
8  * modify, copy, or redistribute it subject to the terms and conditions
9  * of the GNU Lesser General Public License v.2.1.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this program; if not, write to the Free Software Foundation,
13  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14  */
15
16 #include "lib.h"
17 #include "metadata.h"
18 #include "display.h"
19 #include "activate.h"
20 #include "toolcontext.h"
21 #include "segtype.h"
22 #include "str_list.h"
23
24 char *lvseg_tags_dup(const struct lv_segment *seg)
25 {
26         return tags_format_and_copy(seg->lv->vg->vgmem, &seg->tags);
27 }
28
29 char *lvseg_segtype_dup(const struct lv_segment *seg)
30 {
31         if (seg->area_count == 1) {
32                 return (char *)"linear";
33         }
34
35         return dm_pool_strdup(seg->lv->vg->vgmem, seg->segtype->ops->name(seg));
36 }
37
38 uint64_t lvseg_chunksize(const struct lv_segment *seg)
39 {
40         uint64_t size;
41
42         if (lv_is_cow(seg->lv))
43                 size = (uint64_t) find_cow(seg->lv)->chunk_size;
44         else
45                 size = UINT64_C(0);
46         return size;
47 }
48
49 uint64_t lvseg_start(const struct lv_segment *seg)
50 {
51         return (uint64_t) seg->le * seg->lv->vg->extent_size;
52 }
53
54 uint64_t lvseg_size(const struct lv_segment *seg)
55 {
56         return (uint64_t) seg->len * seg->lv->vg->extent_size;
57 }
58
59 uint32_t lv_kernel_read_ahead(const struct logical_volume *lv)
60 {
61         struct lvinfo info;
62
63         if (!lv_info(lv->vg->cmd, lv, 0, &info, 0, 1) || !info.exists)
64                 return UINT32_MAX;
65         return info.read_ahead;
66 }
67
68 char *lv_origin_dup(struct dm_pool *mem, const struct logical_volume *lv)
69 {
70         if (lv_is_cow(lv))
71                 return lv_name_dup(mem, origin_from_cow(lv));
72         return NULL;
73 }
74
75 char *lv_name_dup(struct dm_pool *mem, const struct logical_volume *lv)
76 {
77         return dm_pool_strdup(mem, lv->name);
78 }
79
80 char *lv_modules_dup(struct dm_pool *mem, const struct logical_volume *lv)
81 {
82         struct dm_list *modules;
83
84         if (!(modules = str_list_create(mem))) {
85                 log_error("modules str_list allocation failed");
86                 return NULL;
87         }
88
89         if (!list_lv_modules(mem, lv, modules))
90                 return_NULL;
91         return tags_format_and_copy(mem, modules);
92 }
93
94 char *lv_mirror_log_dup(struct dm_pool *mem, const struct logical_volume *lv)
95 {
96         struct lv_segment *seg;
97
98         dm_list_iterate_items(seg, &lv->segments) {
99                 if (!seg_is_mirrored(seg) || !seg->log_lv)
100                         continue;
101                 return dm_pool_strdup(mem, seg->log_lv->name);
102         }
103         return NULL;
104 }
105
106 int lv_kernel_minor(const struct logical_volume *lv)
107 {
108         struct lvinfo info;
109
110         if (lv_info(lv->vg->cmd, lv, 0, &info, 0, 0) && info.exists)
111                 return info.minor;
112         return -1;
113 }
114
115 int lv_kernel_major(const struct logical_volume *lv)
116 {
117         struct lvinfo info;
118         if (lv_info(lv->vg->cmd, lv, 0, &info, 0, 0) && info.exists)
119                 return info.major;
120         return -1;
121 }
122
123 char *lv_convert_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
124 {
125         struct lv_segment *seg;
126
127         if (lv->status & (CONVERTING|MIRRORED)) {
128                 seg = first_seg(lv);
129
130                 /* Temporary mirror is always area_num == 0 */
131                 if (seg_type(seg, 0) == AREA_LV &&
132                     is_temporary_mirror_layer(seg_lv(seg, 0)))
133                         return dm_pool_strdup(mem, seg_lv(seg, 0)->name);
134         }
135         return NULL;
136 }
137
138 char *lv_move_pv_dup(struct dm_pool *mem, const struct logical_volume *lv)
139 {
140         struct lv_segment *seg;
141
142         dm_list_iterate_items(seg, &lv->segments) {
143                 if (seg->status & PVMOVE)
144                         return dm_pool_strdup(mem, dev_name(seg_dev(seg, 0)));
145         }
146         return NULL;
147 }
148
149 uint64_t lv_origin_size(const struct logical_volume *lv)
150 {
151         if (lv_is_cow(lv))
152                 return (uint64_t) find_cow(lv)->len * lv->vg->extent_size;
153         if (lv_is_origin(lv))
154                 return lv->size;
155         return 0;
156 }
157
158 char *lv_path_dup(struct dm_pool *mem, const struct logical_volume *lv)
159 {
160         char *repstr;
161         size_t len;
162
163         len = strlen(lv->vg->cmd->dev_dir) + strlen(lv->vg->name) +
164                 strlen(lv->name) + 2;
165
166         if (!(repstr = dm_pool_zalloc(mem, len))) {
167                 log_error("dm_pool_alloc failed");
168                 return 0;
169         }
170
171         if (dm_snprintf(repstr, len, "%s%s/%s",
172                         lv->vg->cmd->dev_dir, lv->vg->name, lv->name) < 0) {
173                 log_error("lvpath snprintf failed");
174                 return 0;
175         }
176         return repstr;
177 }
178
179 char *lv_uuid_dup(const struct logical_volume *lv)
180 {
181         return id_format_and_copy(lv->vg->vgmem, &lv->lvid.id[1]);
182 }
183
184 char *lv_tags_dup(const struct logical_volume *lv)
185 {
186         return tags_format_and_copy(lv->vg->vgmem, &lv->tags);
187 }
188
189 uint64_t lv_size(const struct logical_volume *lv)
190 {
191         return lv->size;
192 }
193
194 static int _lv_mimage_in_sync(const struct logical_volume *lv)
195 {
196         percent_t percent;
197         struct lv_segment *mirror_seg = find_mirror_seg(first_seg(lv));
198
199         if (!(lv->status & MIRROR_IMAGE) || !mirror_seg)
200                 return_0;
201
202         if (!lv_mirror_percent(lv->vg->cmd, mirror_seg->lv, 0, &percent,
203                                NULL))
204                 return_0;
205
206         return (percent == PERCENT_100) ? 1 : 0;
207 }
208
209 char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
210 {
211         percent_t snap_percent;
212         struct lvinfo info;
213         char *repstr;
214
215         if (!(repstr = dm_pool_zalloc(mem, 7))) {
216                 log_error("dm_pool_alloc failed");
217                 return 0;
218         }
219
220         /* Blank if this is a "free space" LV. */
221         if (!*lv->name)
222                 goto out;
223
224         if (lv->status & PVMOVE)
225                 repstr[0] = 'p';
226         else if (lv->status & CONVERTING)
227                 repstr[0] = 'c';
228         else if (lv->status & VIRTUAL)
229                 repstr[0] = 'v';
230         /* Origin takes precedence over Mirror */
231         else if (lv_is_origin(lv)) {
232                 repstr[0] = (lv_is_merging_origin(lv)) ? 'O' : 'o';
233         }
234         else if (lv->status & MIRRORED) {
235                 repstr[0] = (lv->status & MIRROR_NOTSYNCED) ? 'M' : 'm';
236         }else if (lv->status & MIRROR_IMAGE)
237                 repstr[0] = (_lv_mimage_in_sync(lv)) ? 'i' : 'I';
238         else if (lv->status & MIRROR_LOG)
239                 repstr[0] = 'l';
240         else if (lv_is_cow(lv)) {
241                 repstr[0] = (lv_is_merging_cow(lv)) ? 'S' : 's';
242         } else
243                 repstr[0] = '-';
244
245         if (lv->status & PVMOVE)
246                 repstr[1] = '-';
247         else if (lv->status & LVM_WRITE)
248                 repstr[1] = 'w';
249         else if (lv->status & LVM_READ)
250                 repstr[1] = 'r';
251         else
252                 repstr[1] = '-';
253
254         repstr[2] = alloc_policy_char(lv->alloc);
255
256         if (lv->status & LOCKED)
257                 repstr[2] = toupper(repstr[2]);
258
259         repstr[3] = (lv->status & FIXED_MINOR) ? 'm' : '-';
260
261         if (lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) && info.exists) {
262                 if (info.suspended)
263                         repstr[4] = 's';        /* Suspended */
264                 else if (info.live_table)
265                         repstr[4] = 'a';        /* Active */
266                 else if (info.inactive_table)
267                         repstr[4] = 'i';        /* Inactive with table */
268                 else
269                         repstr[4] = 'd';        /* Inactive without table */
270
271                 /* Snapshot dropped? */
272                 if (info.live_table && lv_is_cow(lv) &&
273                     (!lv_snapshot_percent(lv, &snap_percent) ||
274                      snap_percent == PERCENT_INVALID)) {
275                         repstr[0] = toupper(repstr[0]);
276                         if (info.suspended)
277                                 repstr[4] = 'S'; /* Susp Inv snapshot */
278                         else
279                                 repstr[4] = 'I'; /* Invalid snapshot */
280                 }
281
282                 repstr[5] = (info.open_count) ? 'o' : '-';
283         } else {
284                 repstr[4] = '-';
285                 repstr[5] = '-';
286         }
287 out:
288         return repstr;
289 }