diff options
author | Simon J. Gerraty <sjg@FreeBSD.org> | 2014-05-08 23:54:15 +0000 |
---|---|---|
committer | Simon J. Gerraty <sjg@FreeBSD.org> | 2014-05-08 23:54:15 +0000 |
commit | cc3f4b99653c34ae64f8a1fddea370abefef680e (patch) | |
tree | 8ce0ddd0e6f508bd20c77429c448969589170fae /sys/geom/part/g_part_mbr.c | |
parent | f974b33f6ed6f35170c520d2be111bfc2c3954cd (diff) | |
parent | 16aa1f0950a3b4407a36ecc96acc8ca0710ebd91 (diff) | |
download | src-test-cc3f4b99653c34ae64f8a1fddea370abefef680e.tar.gz src-test-cc3f4b99653c34ae64f8a1fddea370abefef680e.zip |
Notes
Diffstat (limited to 'sys/geom/part/g_part_mbr.c')
-rw-r--r-- | sys/geom/part/g_part_mbr.c | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c index e9085b120980a..73101ff6929bb 100644 --- a/sys/geom/part/g_part_mbr.c +++ b/sys/geom/part/g_part_mbr.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/sysctl.h> #include <geom/geom.h> +#include <geom/geom_int.h> #include <geom/part/g_part.h> #include "g_part_if.h" @@ -195,34 +196,39 @@ mbr_set_chs(struct g_part_table *table, uint32_t lba, u_char *cylp, u_char *hdp, } static int +mbr_align(struct g_part_table *basetable, uint32_t *start, uint32_t *size) +{ + uint32_t sectors; + + sectors = basetable->gpt_sectors; + if (*size < sectors) + return (EINVAL); + if (start != NULL && (*start % sectors)) { + *size += (*start % sectors) - sectors; + *start -= (*start % sectors) - sectors; + } + if (*size % sectors) + *size -= (*size % sectors); + if (*size < sectors) + return (EINVAL); + return (0); +} + +static int g_part_mbr_add(struct g_part_table *basetable, struct g_part_entry *baseentry, struct g_part_parms *gpp) { struct g_part_mbr_entry *entry; - struct g_part_mbr_table *table; - uint32_t start, size, sectors; + uint32_t start, size; if (gpp->gpp_parms & G_PART_PARM_LABEL) return (EINVAL); - sectors = basetable->gpt_sectors; - entry = (struct g_part_mbr_entry *)baseentry; - table = (struct g_part_mbr_table *)basetable; - start = gpp->gpp_start; size = gpp->gpp_size; - if (size < sectors) - return (EINVAL); - if (start % sectors) { - size = size - sectors + (start % sectors); - start = start - (start % sectors) + sectors; - } - if (size % sectors) - size = size - (size % sectors); - if (size < sectors) + if (mbr_align(basetable, &start, &size) != 0) return (EINVAL); - if (baseentry->gpe_deleted) bzero(&entry->ent, sizeof(entry->ent)); @@ -337,7 +343,7 @@ g_part_mbr_resize(struct g_part_table *basetable, { struct g_part_mbr_entry *entry; struct g_provider *pp; - uint32_t size, sectors; + uint32_t size; if (baseentry == NULL) { pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider; @@ -345,16 +351,14 @@ g_part_mbr_resize(struct g_part_table *basetable, UINT32_MAX) - 1; return (0); } - sectors = basetable->gpt_sectors; size = gpp->gpp_size; - - if (size < sectors) + if (mbr_align(basetable, NULL, &size) != 0) return (EINVAL); - if (size % sectors) - size = size - (size % sectors); - if (size < sectors) - return (EINVAL); - + /* XXX: prevent unexpected shrinking. */ + pp = baseentry->gpe_pp; + if ((g_debugflags & 0x10) == 0 && size < gpp->gpp_size && + pp->mediasize / pp->sectorsize > size) + return (EBUSY); entry = (struct g_part_mbr_entry *)baseentry; baseentry->gpe_end = baseentry->gpe_start + size - 1; entry->ent.dp_size = size; |