source: mainline/uspace/lib/fdisk/src/fdisk.c@ 100b1d1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 100b1d1 was c02d098, checked in by Jiri Svoboda <jiri@…>, 10 years ago

Most of logical partition support.

  • Property mode set to 100644
File size: 19.1 KB
Line 
1/*
2 * Copyright (c) 2015 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libfdisk
30 * @{
31 */
32/**
33 * @file Disk management library.
34 */
35
36#include <adt/list.h>
37#include <block.h>
38#include <errno.h>
39#include <fdisk.h>
40#include <loc.h>
41#include <mem.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <str.h>
45#include <vbd.h>
46#include <vol.h>
47
48static const char *cu_str[] = {
49 [cu_byte] = "B",
50 [cu_kbyte] = "kB",
51 [cu_mbyte] = "MB",
52 [cu_gbyte] = "GB",
53 [cu_tbyte] = "TB",
54 [cu_pbyte] = "PB",
55 [cu_ebyte] = "EB",
56 [cu_zbyte] = "ZB",
57 [cu_ybyte] = "YB"
58};
59
60static int fdisk_part_spec_prepare(fdisk_dev_t *, fdisk_part_spec_t *,
61 vbd_part_spec_t *);
62static void fdisk_pri_part_insert_lists(fdisk_dev_t *, fdisk_part_t *);
63static void fdisk_log_part_insert_lists(fdisk_dev_t *, fdisk_part_t *);
64static int fdisk_update_dev_info(fdisk_dev_t *);
65
66static void fdisk_dev_info_delete(fdisk_dev_info_t *info)
67{
68 if (info == NULL)
69 return;
70
71 if (info->blk_inited)
72 block_fini(info->svcid);
73
74 free(info->svcname);
75 free(info);
76}
77
78int fdisk_create(fdisk_t **rfdisk)
79{
80 fdisk_t *fdisk = NULL;
81 int rc;
82
83 fdisk = calloc(1, sizeof(fdisk_t));
84 if (fdisk == NULL) {
85 rc = ENOMEM;
86 goto error;
87 }
88
89 rc = vol_create(&fdisk->vol);
90 if (rc != EOK) {
91 rc = EIO;
92 goto error;
93 }
94
95 rc = vbd_create(&fdisk->vbd);
96 if (rc != EOK) {
97 rc = EIO;
98 goto error;
99 }
100
101 *rfdisk = fdisk;
102 return EOK;
103error:
104 fdisk_destroy(fdisk);
105
106 return rc;
107}
108
109void fdisk_destroy(fdisk_t *fdisk)
110{
111 if (fdisk == NULL)
112 return;
113
114 vol_destroy(fdisk->vol);
115 vbd_destroy(fdisk->vbd);
116 free(fdisk);
117}
118
119int fdisk_dev_list_get(fdisk_t *fdisk, fdisk_dev_list_t **rdevlist)
120{
121 fdisk_dev_list_t *devlist = NULL;
122 fdisk_dev_info_t *info;
123 service_id_t *svcs = NULL;
124 size_t count, i;
125 int rc;
126
127 devlist = calloc(1, sizeof(fdisk_dev_list_t));
128 if (devlist == NULL)
129 return ENOMEM;
130
131 list_initialize(&devlist->devinfos);
132
133 rc = vol_get_disks(fdisk->vol, &svcs, &count);
134 if (rc != EOK) {
135 rc = EIO;
136 goto error;
137 }
138
139 for (i = 0; i < count; i++) {
140 info = calloc(1, sizeof(fdisk_dev_info_t));
141 if (info == NULL) {
142 rc = ENOMEM;
143 goto error;
144 }
145
146 info->svcid = svcs[i];
147 info->devlist = devlist;
148 list_append(&info->ldevlist, &devlist->devinfos);
149 }
150
151 *rdevlist = devlist;
152 free(svcs);
153 return EOK;
154error:
155 free(svcs);
156 fdisk_dev_list_free(devlist);
157 return rc;
158}
159
160void fdisk_dev_list_free(fdisk_dev_list_t *devlist)
161{
162 fdisk_dev_info_t *info;
163
164 if (devlist == NULL)
165 return;
166
167 while (!list_empty(&devlist->devinfos)) {
168 info = list_get_instance(list_first(
169 &devlist->devinfos), fdisk_dev_info_t,
170 ldevlist);
171
172 list_remove(&info->ldevlist);
173 fdisk_dev_info_delete(info);
174 }
175
176 free(devlist);
177}
178
179fdisk_dev_info_t *fdisk_dev_first(fdisk_dev_list_t *devlist)
180{
181 if (list_empty(&devlist->devinfos))
182 return NULL;
183
184 return list_get_instance(list_first(&devlist->devinfos),
185 fdisk_dev_info_t, ldevlist);
186}
187
188fdisk_dev_info_t *fdisk_dev_next(fdisk_dev_info_t *devinfo)
189{
190 link_t *lnext;
191
192 lnext = list_next(&devinfo->ldevlist,
193 &devinfo->devlist->devinfos);
194 if (lnext == NULL)
195 return NULL;
196
197 return list_get_instance(lnext, fdisk_dev_info_t,
198 ldevlist);
199}
200
201void fdisk_dev_info_get_svcid(fdisk_dev_info_t *info, service_id_t *rsid)
202{
203 *rsid = info->svcid;
204}
205
206int fdisk_dev_info_get_svcname(fdisk_dev_info_t *info, char **rname)
207{
208 char *name;
209 int rc;
210
211 if (info->svcname == NULL) {
212 rc = loc_service_get_name(info->svcid,
213 &info->svcname);
214 if (rc != EOK)
215 return rc;
216 }
217
218 name = str_dup(info->svcname);
219 if (name == NULL)
220 return ENOMEM;
221
222 *rname = name;
223 return EOK;
224}
225
226int fdisk_dev_info_capacity(fdisk_dev_info_t *info, fdisk_cap_t *cap)
227{
228 size_t bsize;
229 aoff64_t nblocks;
230 int rc;
231
232 if (!info->blk_inited) {
233 rc = block_init(EXCHANGE_SERIALIZE, info->svcid, 2048);
234 if (rc != EOK)
235 return rc;
236
237 info->blk_inited = true;
238 }
239
240 rc = block_get_bsize(info->svcid, &bsize);
241 if (rc != EOK)
242 return EIO;
243
244 rc = block_get_nblocks(info->svcid, &nblocks);
245 if (rc != EOK)
246 return EIO;
247
248 cap->value = bsize * nblocks;
249 cap->cunit = cu_byte;
250
251 return EOK;
252}
253
254static int fdisk_part_add(fdisk_dev_t *dev, vbd_part_id_t partid,
255 fdisk_part_t **rpart)
256{
257 fdisk_part_t *part;
258 vbd_part_info_t pinfo;
259 int rc;
260
261 part = calloc(1, sizeof(fdisk_part_t));
262 if (part == NULL)
263 return ENOMEM;
264
265 rc = vbd_part_get_info(dev->fdisk->vbd, partid, &pinfo);
266 if (rc != EOK) {
267 rc = EIO;
268 goto error;
269 }
270
271 part->dev = dev;
272 part->index = pinfo.index;
273 part->block0 = pinfo.block0;
274 part->nblocks = pinfo.nblocks;
275 part->pkind = pinfo.pkind;
276
277 switch (part->pkind) {
278 case lpk_primary:
279 case lpk_extended:
280 fdisk_pri_part_insert_lists(dev, part);
281 break;
282 case lpk_logical:
283 fdisk_log_part_insert_lists(dev, part);
284 break;
285 }
286
287 list_append(&part->lparts, &dev->parts);
288
289 if (part->pkind == lpk_extended)
290 dev->ext_part = part;
291
292 part->capacity.cunit = cu_byte;
293 part->capacity.value = part->nblocks * dev->dinfo.block_size;
294 part->part_id = partid;
295
296 if (rpart != NULL)
297 *rpart = part;
298 return EOK;
299error:
300 free(part);
301 return rc;
302}
303
304static void fdisk_pri_part_insert_lists(fdisk_dev_t *dev, fdisk_part_t *part)
305{
306 link_t *link;
307 fdisk_part_t *p;
308
309 /* Insert to list by block address */
310 link = list_first(&dev->pri_ba);
311 while (link != NULL) {
312 p = list_get_instance(link, fdisk_part_t, lpri_ba);
313 if (p->block0 > part->block0) {
314 list_insert_before(&part->lpri_ba, &p->lpri_ba);
315 break;
316 }
317
318 link = list_next(link, &dev->pri_ba);
319 }
320
321 if (link == NULL)
322 list_append(&part->lpri_ba, &dev->pri_ba);
323
324 /* Insert to list by index */
325 link = list_first(&dev->pri_idx);
326 while (link != NULL) {
327 p = list_get_instance(link, fdisk_part_t, lpri_idx);
328 if (p->index > part->index) {
329 list_insert_before(&part->lpri_idx, &p->lpri_idx);
330 break;
331 }
332
333 link = list_next(link, &dev->pri_idx);
334 }
335
336 if (link == NULL)
337 list_append(&part->lpri_idx, &dev->pri_idx);
338}
339
340static void fdisk_log_part_insert_lists(fdisk_dev_t *dev, fdisk_part_t *part)
341{
342 link_t *link;
343 fdisk_part_t *p;
344
345 /* Insert to list by block address */
346 link = list_first(&dev->log_ba);
347 while (link != NULL) {
348 p = list_get_instance(link, fdisk_part_t, llog_ba);
349 if (p->block0 > part->block0) {
350 list_insert_before(&part->llog_ba, &p->llog_ba);
351 break;
352 }
353
354 link = list_next(link, &dev->log_ba);
355 }
356
357 if (link == NULL)
358 list_append(&part->llog_ba, &dev->log_ba);
359}
360
361int fdisk_dev_open(fdisk_t *fdisk, service_id_t sid, fdisk_dev_t **rdev)
362{
363 vol_disk_info_t vinfo;
364 fdisk_dev_t *dev = NULL;
365 service_id_t *psids = NULL;
366 size_t nparts, i;
367 int rc;
368
369 dev = calloc(1, sizeof(fdisk_dev_t));
370 if (dev == NULL)
371 return ENOMEM;
372
373 dev->fdisk = fdisk;
374 dev->sid = sid;
375 list_initialize(&dev->parts);
376 list_initialize(&dev->pri_idx);
377 list_initialize(&dev->pri_ba);
378 list_initialize(&dev->log_ba);
379
380 rc = vol_disk_info(fdisk->vol, sid, &vinfo);
381 if (rc != EOK) {
382 rc = EIO;
383 goto error;
384 }
385
386 dev->dcnt = vinfo.dcnt;
387
388 if (dev->dcnt != dc_label)
389 goto done;
390
391 printf("get label info\n");
392 rc = fdisk_update_dev_info(dev);
393 if (rc != EOK) {
394 printf("failed\n");
395 rc = EIO;
396 goto error;
397 }
398
399 printf("block size: %zu\n", dev->dinfo.block_size);
400 printf("get partitions\n");
401 rc = vbd_label_get_parts(fdisk->vbd, sid, &psids, &nparts);
402 if (rc != EOK) {
403 printf("failed\n");
404 rc = EIO;
405 goto error;
406 }
407 printf("OK\n");
408
409 printf("found %zu partitions.\n", nparts);
410 for (i = 0; i < nparts; i++) {
411 printf("add partition sid=%zu\n", psids[i]);
412 rc = fdisk_part_add(dev, psids[i], NULL);
413 if (rc != EOK) {
414 printf("failed\n");
415 goto error;
416 }
417 printf("OK\n");
418 }
419
420 free(psids);
421done:
422 *rdev = dev;
423 return EOK;
424error:
425 fdisk_dev_close(dev);
426 return rc;
427}
428
429void fdisk_dev_close(fdisk_dev_t *dev)
430{
431 if (dev == NULL)
432 return;
433
434 /* XXX Clean up partitions */
435 free(dev);
436}
437
438int fdisk_dev_get_svcname(fdisk_dev_t *dev, char **rname)
439{
440 char *name;
441 int rc;
442
443 rc = loc_service_get_name(dev->sid, &name);
444 if (rc != EOK)
445 return rc;
446
447 *rname = name;
448 return EOK;
449}
450
451int fdisk_dev_capacity(fdisk_dev_t *dev, fdisk_cap_t *cap)
452{
453 size_t bsize;
454 aoff64_t nblocks;
455 int rc;
456
457 rc = block_init(EXCHANGE_SERIALIZE, dev->sid, 2048);
458 if (rc != EOK)
459 return rc;
460
461 rc = block_get_bsize(dev->sid, &bsize);
462 if (rc != EOK)
463 return EIO;
464
465 rc = block_get_nblocks(dev->sid, &nblocks);
466 if (rc != EOK)
467 return EIO;
468
469 block_fini(dev->sid);
470
471 cap->value = bsize * nblocks;
472 cap->cunit = cu_byte;
473
474 return EOK;
475}
476
477int fdisk_label_get_info(fdisk_dev_t *dev, fdisk_label_info_t *info)
478{
479 vol_disk_info_t vinfo;
480 int rc;
481
482 rc = vol_disk_info(dev->fdisk->vol, dev->sid, &vinfo);
483 if (rc != EOK) {
484 rc = EIO;
485 goto error;
486 }
487
488 info->dcnt = vinfo.dcnt;
489 info->ltype = vinfo.ltype;
490 info->flags = vinfo.flags;
491 return EOK;
492error:
493 return rc;
494}
495
496int fdisk_label_create(fdisk_dev_t *dev, label_type_t ltype)
497{
498 int rc;
499
500 rc = vol_label_create(dev->fdisk->vol, dev->sid, ltype);
501 if (rc != EOK)
502 return rc;
503
504 rc = fdisk_update_dev_info(dev);
505 if (rc != EOK)
506 return rc;
507
508 return EOK;
509}
510
511int fdisk_label_destroy(fdisk_dev_t *dev)
512{
513 fdisk_part_t *part;
514 int rc;
515
516 part = fdisk_part_first(dev);
517 while (part != NULL) {
518 (void) fdisk_part_destroy(part); /* XXX */
519 part = fdisk_part_first(dev);
520 }
521
522 rc = vol_disk_empty(dev->fdisk->vol, dev->sid);
523 if (rc != EOK)
524 return EIO;
525
526 dev->dcnt = dc_empty;
527 return EOK;
528}
529
530fdisk_part_t *fdisk_part_first(fdisk_dev_t *dev)
531{
532 link_t *link;
533
534 link = list_first(&dev->parts);
535 if (link == NULL)
536 return NULL;
537
538 return list_get_instance(link, fdisk_part_t, lparts);
539}
540
541fdisk_part_t *fdisk_part_next(fdisk_part_t *part)
542{
543 link_t *link;
544
545 link = list_next(&part->lparts, &part->dev->parts);
546 if (link == NULL)
547 return NULL;
548
549 return list_get_instance(link, fdisk_part_t, lparts);
550}
551
552int fdisk_part_get_info(fdisk_part_t *part, fdisk_part_info_t *info)
553{
554 info->capacity = part->capacity;
555 info->fstype = part->fstype;
556 info->pkind = part->pkind;
557 return EOK;
558}
559
560int fdisk_part_get_max_avail(fdisk_dev_t *dev, fdisk_cap_t *cap)
561{
562 return EOK;
563}
564
565int fdisk_part_create(fdisk_dev_t *dev, fdisk_part_spec_t *pspec,
566 fdisk_part_t **rpart)
567{
568 fdisk_part_t *part;
569 vbd_part_spec_t vpspec;
570 vbd_part_id_t partid;
571 int rc;
572
573 printf("fdisk_part_create()\n");
574
575 rc = fdisk_part_spec_prepare(dev, pspec, &vpspec);
576 if (rc != EOK)
577 return EIO;
578
579 printf("fdisk_part_create() - call vbd_part_create\n");
580 rc = vbd_part_create(dev->fdisk->vbd, dev->sid, &vpspec, &partid);
581 if (rc != EOK)
582 return EIO;
583
584 printf("fdisk_part_create() - call fdisk_part_add\n");
585 rc = fdisk_part_add(dev, partid, &part);
586 if (rc != EOK) {
587 /* Try rolling back */
588 (void) vbd_part_delete(dev->fdisk->vbd, partid);
589 return EIO;
590 }
591
592 printf("fdisk_part_create() - done\n");
593 part->fstype = pspec->fstype;
594 part->capacity = pspec->capacity;
595
596 if (rpart != NULL)
597 *rpart = part;
598 return EOK;
599}
600
601int fdisk_part_destroy(fdisk_part_t *part)
602{
603 int rc;
604
605 rc = vbd_part_delete(part->dev->fdisk->vbd, part->part_id);
606 if (rc != EOK)
607 return EIO;
608
609 list_remove(&part->lparts);
610 if (link_used(&part->lpri_ba))
611 list_remove(&part->lpri_ba);
612 if (link_used(&part->lpri_idx))
613 list_remove(&part->lpri_idx);
614 if (link_used(&part->llog_ba))
615 list_remove(&part->llog_ba);
616 free(part);
617 return EOK;
618}
619
620void fdisk_pspec_init(fdisk_part_spec_t *pspec)
621{
622 memset(pspec, 0, sizeof(fdisk_part_spec_t));
623}
624
625int fdisk_cap_format(fdisk_cap_t *cap, char **rstr)
626{
627 int rc;
628 const char *sunit;
629
630 sunit = NULL;
631
632 if (cap->cunit < 0 || cap->cunit >= CU_LIMIT)
633 assert(false);
634
635 sunit = cu_str[cap->cunit];
636 rc = asprintf(rstr, "%" PRIu64 " %s", cap->value, sunit);
637 if (rc < 0)
638 return ENOMEM;
639
640 return EOK;
641}
642
643int fdisk_cap_parse(const char *str, fdisk_cap_t *cap)
644{
645 char *eptr;
646 char *p;
647 unsigned long val;
648 int i;
649
650 val = strtoul(str, &eptr, 10);
651
652 while (*eptr == ' ')
653 ++eptr;
654
655 if (*eptr == '\0') {
656 cap->cunit = cu_byte;
657 } else {
658 for (i = 0; i < CU_LIMIT; i++) {
659 if (str_lcasecmp(eptr, cu_str[i],
660 str_length(cu_str[i])) == 0) {
661 p = eptr + str_size(cu_str[i]);
662 while (*p == ' ')
663 ++p;
664 if (*p == '\0')
665 goto found;
666 }
667 }
668
669 return EINVAL;
670found:
671 cap->cunit = i;
672 }
673
674 cap->value = val;
675 return EOK;
676}
677
678int fdisk_ltype_format(label_type_t ltype, char **rstr)
679{
680 const char *sltype;
681 char *s;
682
683 sltype = NULL;
684 switch (ltype) {
685 case lt_mbr:
686 sltype = "MBR";
687 break;
688 case lt_gpt:
689 sltype = "GPT";
690 break;
691 }
692
693 s = str_dup(sltype);
694 if (s == NULL)
695 return ENOMEM;
696
697 *rstr = s;
698 return EOK;
699}
700
701int fdisk_fstype_format(fdisk_fstype_t fstype, char **rstr)
702{
703 const char *sfstype;
704 char *s;
705
706 sfstype = NULL;
707 switch (fstype) {
708 case fdfs_none:
709 sfstype = "None";
710 break;
711 case fdfs_unknown:
712 sfstype = "Unknown";
713 break;
714 case fdfs_exfat:
715 sfstype = "ExFAT";
716 break;
717 case fdfs_fat:
718 sfstype = "FAT";
719 break;
720 case fdfs_minix:
721 sfstype = "MINIX";
722 break;
723 case fdfs_ext4:
724 sfstype = "Ext4";
725 break;
726 }
727
728 s = str_dup(sfstype);
729 if (s == NULL)
730 return ENOMEM;
731
732 *rstr = s;
733 return EOK;
734}
735
736int fdisk_pkind_format(label_pkind_t pkind, char **rstr)
737{
738 const char *spkind;
739 char *s;
740
741 spkind = NULL;
742 switch (pkind) {
743 case lpk_primary:
744 spkind = "Primary";
745 break;
746 case lpk_extended:
747 spkind = "Extended";
748 break;
749 case lpk_logical:
750 spkind = "Logical";
751 break;
752 }
753
754 s = str_dup(spkind);
755 if (s == NULL)
756 return ENOMEM;
757
758 *rstr = s;
759 return EOK;
760}
761
762/** Get free partition index. */
763static int fdisk_part_get_free_idx(fdisk_dev_t *dev, int *rindex)
764{
765 link_t *link;
766 fdisk_part_t *part;
767 int nidx;
768
769 link = list_first(&dev->pri_idx);
770 nidx = 1;
771 while (link != NULL) {
772 part = list_get_instance(link, fdisk_part_t, lpri_idx);
773 if (part->index > nidx)
774 break;
775 nidx = part->index + 1;
776 link = list_next(link, &dev->pri_idx);
777 }
778
779 if (nidx > 4 /* XXXX actual number of slots*/) {
780 return ELIMIT;
781 }
782
783 *rindex = nidx;
784 return EOK;
785}
786
787/** Get free range of blocks.
788 *
789 * Get free range of blocks of at least the specified size (first fit).
790 */
791static int fdisk_part_get_free_range(fdisk_dev_t *dev, aoff64_t nblocks,
792 aoff64_t *rblock0, aoff64_t *rnblocks)
793{
794 link_t *link;
795 fdisk_part_t *part;
796 uint64_t avail;
797 int nba;
798
799 link = list_first(&dev->pri_ba);
800 nba = dev->dinfo.ablock0;
801 while (link != NULL) {
802 part = list_get_instance(link, fdisk_part_t, lpri_ba);
803 if (part->block0 - nba >= nblocks)
804 break;
805 nba = part->block0 + part->nblocks;
806 link = list_next(link, &dev->pri_ba);
807 }
808
809 if (link != NULL) {
810 /* Free range before a partition */
811 avail = part->block0 - nba;
812 } else {
813 /* Free range at the end */
814 avail = dev->dinfo.ablock0 + dev->dinfo.anblocks - nba;
815
816 /* Verify that the range is large enough */
817 if (avail < nblocks)
818 return ELIMIT;
819 }
820
821 *rblock0 = nba;
822 *rnblocks = avail;
823 return EOK;
824}
825
826/** Get free range of blocks in extended partition.
827 *
828 * Get free range of blocks in extended partition that can accomodate
829 * a partition of at least the specified size plus the header (EBR + padding).
830 * Returns the header size in blocks, the start and length of the partition.
831 */
832static int fdisk_part_get_log_free_range(fdisk_dev_t *dev, aoff64_t nblocks,
833 aoff64_t *rhdrb, aoff64_t *rblock0, aoff64_t *rnblocks)
834{
835 link_t *link;
836 fdisk_part_t *part;
837 uint64_t avail;
838 uint64_t hdrb;
839 int nba;
840
841 /* Number of header blocks */
842 hdrb = max(1, dev->align);
843
844 link = list_first(&dev->log_ba);
845 nba = dev->ext_part->block0;
846 while (link != NULL) {
847 part = list_get_instance(link, fdisk_part_t, llog_ba);
848 if (part->block0 - nba >= nblocks)
849 break;
850 nba = part->block0 + part->nblocks;
851 link = list_next(link, &dev->log_ba);
852 }
853
854 if (link != NULL) {
855 /* Free range before a partition */
856 avail = part->block0 - nba;
857 } else {
858 /* Free range at the end */
859 avail = dev->ext_part->block0 + dev->ext_part->nblocks - nba;
860
861 /* Verify that the range is large enough */
862 if (avail < hdrb + nblocks)
863 return ELIMIT;
864 }
865
866 *rhdrb = hdrb;
867 *rblock0 = nba + hdrb;
868 *rnblocks = avail;
869 return EOK;
870}
871
872/** Prepare new partition specification for VBD. */
873static int fdisk_part_spec_prepare(fdisk_dev_t *dev, fdisk_part_spec_t *pspec,
874 vbd_part_spec_t *vpspec)
875{
876 uint64_t cbytes;
877 aoff64_t req_blocks;
878 aoff64_t fhdr;
879 aoff64_t fblock0;
880 aoff64_t fnblocks;
881 uint64_t block_size;
882 unsigned i;
883 int index;
884 int rc;
885
886// pspec->fstype
887 printf("fdisk_part_spec_prepare() - dev=%p pspec=%p vpspec=%p\n", dev, pspec,
888 vpspec);
889 printf("fdisk_part_spec_prepare() - block size\n");
890 block_size = dev->dinfo.block_size;
891 printf("fdisk_part_spec_prepare() - cbytes\n");
892 cbytes = pspec->capacity.value;
893 printf("fdisk_part_spec_prepare() - cunit\n");
894 for (i = 0; i < pspec->capacity.cunit; i++)
895 cbytes = cbytes * 1000;
896
897 printf("fdisk_part_spec_prepare() - req_blocks block_size=%zu\n",
898 block_size);
899 req_blocks = (cbytes + block_size - 1) / block_size;
900
901 printf("fdisk_part_spec_prepare() - switch\n");
902 switch (pspec->pkind) {
903 case lpk_primary:
904 case lpk_extended:
905 printf("fdisk_part_spec_prepare() - pri/ext\n");
906 rc = fdisk_part_get_free_idx(dev, &index);
907 if (rc != EOK)
908 return EIO;
909
910 printf("fdisk_part_spec_prepare() - get free range\n");
911 rc = fdisk_part_get_free_range(dev, req_blocks, &fblock0, &fnblocks);
912 if (rc != EOK)
913 return EIO;
914
915 printf("fdisk_part_spec_prepare() - memset\n");
916 memset(vpspec, 0, sizeof(vbd_part_spec_t));
917 vpspec->index = index;
918 vpspec->block0 = fblock0;
919 vpspec->nblocks = req_blocks;
920 vpspec->pkind = pspec->pkind;
921 if (pspec->pkind != lpk_extended)
922 vpspec->ptype = 42;
923 break;
924 case lpk_logical:
925 printf("fdisk_part_spec_prepare() - log\n");
926 rc = fdisk_part_get_log_free_range(dev, req_blocks, &fhdr,
927 &fblock0, &fnblocks);
928 if (rc != EOK)
929 return EIO;
930
931 memset(vpspec, 0, sizeof(vbd_part_spec_t));
932 vpspec->hdr_blocks = fhdr;
933 vpspec->block0 = fblock0;
934 vpspec->nblocks = req_blocks;
935 vpspec->pkind = lpk_logical;
936 vpspec->ptype = 42;
937 break;
938 }
939
940 return EOK;
941}
942
943static int fdisk_update_dev_info(fdisk_dev_t *dev)
944{
945 int rc;
946 size_t align_bytes;
947
948 rc = vbd_disk_info(dev->fdisk->vbd, dev->sid, &dev->dinfo);
949 if (rc != EOK)
950 return EIO;
951
952 align_bytes = 512; //1024 * 1024; /* 1 MiB */ /* XXX */
953 dev->align = align_bytes / dev->dinfo.block_size;
954 if (dev->align < 1)
955 dev->align = 1;
956 return EOK;
957}
958
959/** @}
960 */
Note: See TracBrowser for help on using the repository browser.