Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 03661d1 in mainline


Ignore:
Timestamp:
2015-10-29T10:16:08Z (5 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
55f8c6e7
Parents:
9854a8f
Message:

Handle simplified capacity entry.

Location:
uspace
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/fdisk/fdisk.c

    r9854a8f r03661d1  
    429429        }
    430430
     431        fdisk_cap_simplify(&mcap);
     432
    431433        rc = fdisk_cap_format(&mcap, &smcap);
    432434        if (rc != EOK) {
  • uspace/lib/fdisk/include/fdisk.h

    r9854a8f r03661d1  
    7575extern void fdisk_cap_simplify(fdisk_cap_t *);
    7676extern void fdisk_cap_from_blocks(uint64_t, size_t, fdisk_cap_t *);
    77 extern int fdisk_cap_to_blocks(fdisk_cap_t *, size_t, uint64_t *);
     77extern int fdisk_cap_to_blocks(fdisk_cap_t *, fdisk_cvsel_t, size_t, uint64_t *);
    7878
    7979extern int fdisk_ltype_format(label_type_t, char **);
  • uspace/lib/fdisk/include/types/fdisk.h

    r9854a8f r03661d1  
    5757        cu_ybyte
    5858} fdisk_cunit_t;
     59
     60/** Which of values within the precision of the capacity */
     61typedef enum {
     62        /** The nominal (middling) value */
     63        fcv_nom,
     64        /** The minimum value */
     65        fcv_min,
     66        /** The maximum value */
     67        fcv_max
     68} fdisk_cvsel_t;
    5969
    6070typedef enum {
  • uspace/lib/fdisk/src/cap.c

    r9854a8f r03661d1  
    7676 * of bytes is not divisible by the number of blocks, it is rounded
    7777 * up to an integer number of blocks.
    78  */
    79 int fdisk_cap_to_blocks(fdisk_cap_t *cap, size_t block_size,
    80     uint64_t *blocks)
     78 *
     79 * A capacity value entails precision, i.e. it corresponds to a range
     80 * of values. @a cvsel selects the value to return. @c fcv_nom gives
     81 * the nominal (middle) value, @c fcv_min gives the minimum value
     82 * and @c fcv_max gives the maximum value.
     83 */
     84int fdisk_cap_to_blocks(fdisk_cap_t *cap, fdisk_cvsel_t cvsel,
     85    size_t block_size, uint64_t *rblocks)
    8186{
    8287        int exp;
    8388        uint64_t bytes;
    8489        uint64_t f;
     90        uint64_t adj;
     91        uint64_t blocks;
     92        uint64_t rem;
    8593        int rc;
    8694
    87         // XXX Check for overflow
     95        printf("fdisk_cap_to_blocks: m=%" PRIu64 ", dp=%d, cunit=%d\n",
     96            cap->m, cap->dp, cap->cunit);
    8897
    8998        exp = cap->cunit * 3 - cap->dp;
     
    93102                        return ERANGE;
    94103                bytes = (cap->m + (f / 2)) / f;
     104                if (bytes * f - (f / 2) != cap->m)
     105                        return ERANGE;
    95106        } else {
    96107                rc = ipow10_u64(exp, &f);
    97108                if (rc != EOK)
    98109                        return ERANGE;
    99                 bytes = cap->m * f;
    100         }
    101 
    102         *blocks = (bytes + block_size - 1) / block_size;
     110
     111                adj = 0;
     112                switch (cvsel) {
     113                case fcv_nom:
     114                        adj = 0;
     115                        break;
     116                case fcv_min:
     117                        adj = -(f / 2);
     118                        break;
     119                case fcv_max:
     120                        adj = f / 2 - 1;
     121                        break;
     122                }
     123
     124                printf("f=%" PRIu64 ", adj=%" PRId64 "\n", f, adj);
     125                bytes = cap->m * f + adj;
     126                printf("bytes=%" PRIu64 "\n", bytes);
     127                if ((bytes - adj) / f != cap->m)
     128                        return ERANGE;
     129        }
     130
     131        rem = bytes % block_size;
     132        if ((bytes + rem) < bytes)
     133                return ERANGE;
     134
     135        blocks = (bytes + rem) / block_size;
     136        printf("blocks=%" PRIu64 "\n", blocks);
     137
     138        *rblocks = blocks;
    103139        return EOK;
    104140}
     
    185221}
    186222
     223static int fdisk_digit_val(char c, int *val)
     224{
     225        switch (c) {
     226        case '0': *val = 0; break;
     227        case '1': *val = 1; break;
     228        case '2': *val = 2; break;
     229        case '3': *val = 3; break;
     230        case '4': *val = 4; break;
     231        case '5': *val = 5; break;
     232        case '6': *val = 6; break;
     233        case '7': *val = 7; break;
     234        case '8': *val = 8; break;
     235        case '9': *val = 9; break;
     236        default:
     237                return EINVAL;
     238        }
     239
     240        return EOK;
     241}
     242
    187243int fdisk_cap_parse(const char *str, fdisk_cap_t *cap)
    188244{
    189         char *eptr;
    190         char *p;
    191         unsigned long val;
     245        const char *eptr;
     246        const char *p;
     247        int d;
     248        int dp;
     249        unsigned long m;
    192250        int i;
    193251
    194         val = strtoul(str, &eptr, 10);
     252        m = 0;
     253
     254        eptr = str;
     255        while (fdisk_digit_val(*eptr, &d) == EOK) {
     256                m = m * 10 + d;
     257                ++eptr;
     258        }
     259
     260        if (*eptr == '.') {
     261                ++eptr;
     262                dp = 0;
     263                while (fdisk_digit_val(*eptr, &d) == EOK) {
     264                        m = m * 10 + d;
     265                        ++dp;
     266                        ++eptr;
     267                }
     268        } else {
     269                m = 0; dp = 0;
     270        }
    195271
    196272        while (*eptr == ' ')
     
    216292        }
    217293
    218         cap->m = val;
    219         cap->dp = 0;
     294        cap->m = m;
     295        cap->dp = dp;
    220296        return EOK;
    221297}
  • uspace/lib/fdisk/src/fdisk.c

    r9854a8f r03661d1  
    10371037    vbd_part_spec_t *vpspec)
    10381038{
    1039         aoff64_t req_blocks;
     1039        aoff64_t nom_blocks;
     1040        aoff64_t min_blocks;
     1041        aoff64_t max_blocks;
     1042        aoff64_t act_blocks;
    10401043        aoff64_t fblock0;
    10411044        aoff64_t fnblocks;
    10421045        aoff64_t hdrb;
    10431046        label_pcnt_t pcnt;
     1047        fdisk_spc_t spc;
    10441048        int index;
    10451049        int rc;
     
    10471051        printf("fdisk_part_spec_prepare() - dev=%p pspec=%p vpspec=%p\n", dev, pspec,
    10481052            vpspec);
    1049         fdisk_cap_to_blocks(&pspec->capacity, dev->dinfo.block_size, &req_blocks);
    1050 
    1051         req_blocks = fdisk_ba_align_up(dev, req_blocks);
     1053        rc = fdisk_cap_to_blocks(&pspec->capacity, fcv_nom, dev->dinfo.block_size,
     1054            &nom_blocks);
     1055        if (rc != EOK)
     1056                return rc;
     1057
     1058        rc = fdisk_cap_to_blocks(&pspec->capacity, fcv_min, dev->dinfo.block_size,
     1059            &min_blocks);
     1060        if (rc != EOK)
     1061                return rc;
     1062
     1063        rc = fdisk_cap_to_blocks(&pspec->capacity, fcv_max, dev->dinfo.block_size,
     1064            &max_blocks);
     1065        if (rc != EOK)
     1066                return rc;
     1067
     1068        nom_blocks = fdisk_ba_align_up(dev, nom_blocks);
     1069        min_blocks = fdisk_ba_align_up(dev, min_blocks);
     1070        max_blocks = fdisk_ba_align_up(dev, max_blocks);
     1071
     1072        printf("fdisk_part_spec_prepare: nom=%" PRIu64 ", min=%" PRIu64
     1073            ", max=%" PRIu64, nom_blocks, min_blocks, max_blocks);
    10521074
    10531075        pcnt = -1;
     
    10711093                return EINVAL;
    10721094
    1073         printf("fdisk_part_spec_prepare() - switch\n");
    1074         switch (pspec->pkind) {
    1075         case lpk_primary:
    1076         case lpk_extended:
    1077                 printf("fdisk_part_spec_prepare() - pri/ext\n");
     1095        if (pspec->pkind == lpk_logical) {
     1096                hdrb = max(1, dev->align);
     1097                spc = spc_log;
     1098        } else {
     1099                hdrb = 0;
     1100                spc = spc_pri;
     1101        }
     1102
     1103        rc = fdisk_part_get_free_range(dev, hdrb + nom_blocks, spc,
     1104            &fblock0, &fnblocks);
     1105
     1106        if (rc == EOK) {
     1107                /*
     1108                 * If the size of the free range would still give the same capacity
     1109                 * when rounded, allocate entire range. Otherwise allocate exactly
     1110                 * what we were asked for.
     1111                 */
     1112                if (fnblocks <= max_blocks) {
     1113                        act_blocks = fnblocks;
     1114                } else {
     1115                        act_blocks = hdrb + nom_blocks;
     1116                }
     1117        } else {
     1118                assert(rc == ENOSPC);
     1119
     1120                /*
     1121                 * There is no free range that can contain exactly the requested
     1122                 * capacity. Try to allocate at least such number of blocks
     1123                 * that would still fullfill the request within the limits
     1124                 * of the precision with witch the capacity was specified
     1125                 * (i.e. when rounded up).
     1126                 */
     1127                rc = fdisk_part_get_free_range(dev, hdrb + min_blocks, spc,
     1128                    &fblock0, &fnblocks);
     1129                if (rc != EOK)
     1130                        return rc;
     1131
     1132                assert(fnblocks < hdrb + nom_blocks);
     1133                act_blocks = fnblocks;
     1134        }
     1135
     1136        if (pspec->pkind != lpk_logical) {
    10781137                rc = fdisk_part_get_free_idx(dev, &index);
    10791138                if (rc != EOK)
    10801139                        return EIO;
    1081 
    1082                 printf("fdisk_part_spec_prepare() - get free range\n");
    1083                 rc = fdisk_part_get_free_range(dev, req_blocks, spc_pri,
    1084                     &fblock0, &fnblocks);
    1085                 if (rc != EOK)
    1086                         return EIO;
    1087 
    1088                 printf("fdisk_part_spec_prepare() - memset\n");
    1089                 memset(vpspec, 0, sizeof(vbd_part_spec_t));
    1090                 vpspec->index = index;
    1091                 vpspec->block0 = fblock0;
    1092                 vpspec->nblocks = req_blocks;
    1093                 vpspec->pkind = pspec->pkind;
    1094                 break;
    1095         case lpk_logical:
    1096                 printf("fdisk_part_spec_prepare() - log\n");
    1097                 hdrb = max(1, dev->align);
    1098                 rc = fdisk_part_get_free_range(dev, hdrb + req_blocks, spc_log,
    1099                     &fblock0, &fnblocks);
    1100                 if (rc != EOK)
    1101                         return EIO;
    1102 
    1103                 memset(vpspec, 0, sizeof(vbd_part_spec_t));
    1104                 vpspec->hdr_blocks = hdrb;
    1105                 vpspec->block0 = fblock0 + hdrb;
    1106                 vpspec->nblocks = req_blocks;
    1107                 vpspec->pkind = lpk_logical;
    1108                 break;
    1109         }
     1140        } else {
     1141                index = 0;
     1142        }
     1143
     1144        memset(vpspec, 0, sizeof(vbd_part_spec_t));
     1145        vpspec->index = index;
     1146        vpspec->hdr_blocks = hdrb;
     1147        vpspec->block0 = fblock0 + hdrb;
     1148        vpspec->nblocks = act_blocks;
     1149        vpspec->pkind = pspec->pkind;
    11101150
    11111151        if (pspec->pkind != lpk_extended) {
     
    11151155                        return EIO;
    11161156        }
     1157
     1158        printf("fdisk_part_spec_prepare: hdrb=%" PRIu64 ", b0=%" PRIu64
     1159            ", nblocks=%" PRIu64 ", pkind=%d\n", vpspec->hdr_blocks,
     1160            vpspec->block0, vpspec->nblocks, vpspec->pkind);
    11171161
    11181162        return EOK;
  • uspace/lib/label/src/mbr.c

    r9854a8f r03661d1  
    512512        int rc;
    513513
     514        log_msg(LOG_DEFAULT, LVL_NOTE, "mbr_part_create");
    514515        if (pspec->ptype.fmt != lptf_num)
    515516                return EINVAL;
     
    521522
    522523        /* XXX Check if index is used */
    523 
    524524        part->label = label;
    525525        part->index = pspec->index;
     
    545545                break;
    546546        case lpk_logical:
    547                 log_msg(LOG_DEFAULT, LVL_NOTE, "check index");
    548547                part->ptype = pspec->ptype;
    549548                if (pspec->index != 0) {
     
    587586        } else {
    588587                /* Logical partition */
    589 
    590                 log_msg(LOG_DEFAULT, LVL_NOTE, "call mbr_log_part_insert");
    591588                rc = mbr_log_part_insert(label, part);
    592589                if (rc != EOK)
    593590                        goto error;
    594591
    595                 log_msg(LOG_DEFAULT, LVL_NOTE, "call mbr_ebr_create");
    596592                /* Create EBR for new partition */
    597593                rc = mbr_ebr_create(label, part);
     
    601597                prev = mbr_log_part_prev(part);
    602598                if (prev != NULL) {
    603                         log_msg(LOG_DEFAULT, LVL_NOTE, "update next");
    604599                        /* Update 'next' PTE in EBR of previous partition */
    605600                        rc = mbr_ebr_update_next(label, prev);
    606601                        if (rc != EOK) {
    607                                 log_msg(LOG_DEFAULT, LVL_NOTE, "failed to update next");
    608602                                goto error;
    609603                        }
    610604                } else {
    611                         log_msg(LOG_DEFAULT, LVL_NOTE, "relocate first EBR");
    612605                        /* New partition is now the first one */
    613606                        next = mbr_log_part_next(part);
Note: See TracChangeset for help on using the changeset viewer.