Author: marcel
Date: Fri Apr 23 03:11:39 2010
New Revision: 207094
URL: http://svn.freebsd.org/changeset/base/207094

Log:
  Implement the resize verb and add support for resizing partitions
  for all schemes but EBR. Quality work by Andrey!
  
  Submitted by: "Andrey V. Elsukov" <bu7c...@yandex.ru>

Modified:
  head/sys/geom/part/g_part.c
  head/sys/geom/part/g_part_apm.c
  head/sys/geom/part/g_part_bsd.c
  head/sys/geom/part/g_part_gpt.c
  head/sys/geom/part/g_part_if.m
  head/sys/geom/part/g_part_mbr.c
  head/sys/geom/part/g_part_pc98.c
  head/sys/geom/part/g_part_vtoc8.c

Modified: head/sys/geom/part/g_part.c
==============================================================================
--- head/sys/geom/part/g_part.c Fri Apr 23 02:31:28 2010        (r207093)
+++ head/sys/geom/part/g_part.c Fri Apr 23 03:11:39 2010        (r207094)
@@ -971,9 +971,85 @@ g_part_ctl_recover(struct gctl_req *req,
 static int
 g_part_ctl_resize(struct gctl_req *req, struct g_part_parms *gpp)
 {
-       gctl_error(req, "%d verb 'resize'", ENOSYS);
-       return (ENOSYS);
-} 
+       struct g_geom *gp;
+       struct g_provider *pp;
+       struct g_part_entry *pe, *entry;
+       struct g_part_table *table;
+       struct sbuf *sb;
+       quad_t end;
+       int error;
+
+       gp = gpp->gpp_geom;
+       G_PART_TRACE((G_T_TOPOLOGY, "%s(%s)", __func__, gp->name));
+       g_topology_assert();
+       table = gp->softc;
+
+       /* check gpp_index */
+       LIST_FOREACH(entry, &table->gpt_entry, gpe_entry) {
+               if (entry->gpe_deleted || entry->gpe_internal)
+                       continue;
+               if (entry->gpe_index == gpp->gpp_index)
+                       break;
+       }
+       if (entry == NULL) {
+               gctl_error(req, "%d index '%d'", ENOENT, gpp->gpp_index);
+               return (ENOENT);
+       }
+
+       /* check gpp_size */
+       end = entry->gpe_start + gpp->gpp_size - 1;
+       if (gpp->gpp_size < 1 || end > table->gpt_last) {
+               gctl_error(req, "%d size '%jd'", EINVAL,
+                   (intmax_t)gpp->gpp_size);
+               return (EINVAL);
+       }
+
+       LIST_FOREACH(pe, &table->gpt_entry, gpe_entry) {
+               if (pe->gpe_deleted || pe->gpe_internal || pe == entry)
+                       continue;
+               if (end >= pe->gpe_start && end <= pe->gpe_end) {
+                       gctl_error(req, "%d end '%jd'", ENOSPC,
+                           (intmax_t)end);
+                       return (ENOSPC);
+               }
+               if (entry->gpe_start < pe->gpe_start && end > pe->gpe_end) {
+                       gctl_error(req, "%d size '%jd'", ENOSPC,
+                           (intmax_t)gpp->gpp_size);
+                       return (ENOSPC);
+               }
+       }
+
+       pp = entry->gpe_pp;
+       if ((g_debugflags & 16) == 0 &&
+           (pp->acr > 0 || pp->acw > 0 || pp->ace > 0)) {
+               gctl_error(req, "%d", EBUSY);
+               return (EBUSY);
+       }
+
+       error = G_PART_RESIZE(table, entry, gpp);
+       if (error) {
+               gctl_error(req, "%d", error);
+               return (error);
+       }
+
+       if (!entry->gpe_created)
+               entry->gpe_modified = 1;
+
+       /* update mediasize of changed provider */
+       pp->mediasize = (entry->gpe_end - entry->gpe_start + 1) *
+               pp->sectorsize;
+
+       /* Provide feedback if so requested. */
+       if (gpp->gpp_parms & G_PART_PARM_OUTPUT) {
+               sb = sbuf_new_auto();
+               G_PART_FULLNAME(table, entry, sb, gp->name);
+               sbuf_cat(sb, " resized\n");
+               sbuf_finish(sb);
+               gctl_set_param(req, "output", sbuf_data(sb), sbuf_len(sb) + 1);
+               sbuf_delete(sb);
+       }
+       return (0);
+}
 
 static int
 g_part_ctl_setunset(struct gctl_req *req, struct g_part_parms *gpp,
@@ -1194,7 +1270,8 @@ g_part_ctlreq(struct gctl_req *req, stru
                        mparms |= G_PART_PARM_GEOM;
                } else if (!strcmp(verb, "resize")) {
                        ctlreq = G_PART_CTL_RESIZE;
-                       mparms |= G_PART_PARM_GEOM | G_PART_PARM_INDEX;
+                       mparms |= G_PART_PARM_GEOM | G_PART_PARM_INDEX |
+                           G_PART_PARM_SIZE;
                }
                break;
        case 's':

Modified: head/sys/geom/part/g_part_apm.c
==============================================================================
--- head/sys/geom/part/g_part_apm.c     Fri Apr 23 02:31:28 2010        
(r207093)
+++ head/sys/geom/part/g_part_apm.c     Fri Apr 23 03:11:39 2010        
(r207094)
@@ -74,6 +74,8 @@ static int g_part_apm_read(struct g_part
 static const char *g_part_apm_type(struct g_part_table *, struct g_part_entry 
*,
     char *, size_t);
 static int g_part_apm_write(struct g_part_table *, struct g_consumer *);
+static int g_part_apm_resize(struct g_part_table *, struct g_part_entry *,
+    struct g_part_parms *);
 
 static kobj_method_t g_part_apm_methods[] = {
        KOBJMETHOD(g_part_add,          g_part_apm_add),
@@ -82,6 +84,7 @@ static kobj_method_t g_part_apm_methods[
        KOBJMETHOD(g_part_dumpconf,     g_part_apm_dumpconf),
        KOBJMETHOD(g_part_dumpto,       g_part_apm_dumpto),
        KOBJMETHOD(g_part_modify,       g_part_apm_modify),
+       KOBJMETHOD(g_part_resize,       g_part_apm_resize),
        KOBJMETHOD(g_part_name,         g_part_apm_name),
        KOBJMETHOD(g_part_probe,        g_part_apm_probe),
        KOBJMETHOD(g_part_read,         g_part_apm_read),
@@ -318,6 +321,19 @@ g_part_apm_modify(struct g_part_table *b
        return (0);
 }
 
+static int
+g_part_apm_resize(struct g_part_table *basetable,
+    struct g_part_entry *baseentry, struct g_part_parms *gpp)
+{
+       struct g_part_apm_entry *entry;
+
+       entry = (struct g_part_apm_entry *)baseentry;
+       baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
+       entry->ent.ent_size = gpp->gpp_size;
+
+       return (0);
+}
+
 static const char *
 g_part_apm_name(struct g_part_table *table, struct g_part_entry *baseentry,
     char *buf, size_t bufsz)

Modified: head/sys/geom/part/g_part_bsd.c
==============================================================================
--- head/sys/geom/part/g_part_bsd.c     Fri Apr 23 02:31:28 2010        
(r207093)
+++ head/sys/geom/part/g_part_bsd.c     Fri Apr 23 03:11:39 2010        
(r207094)
@@ -73,6 +73,8 @@ static int g_part_bsd_read(struct g_part
 static const char *g_part_bsd_type(struct g_part_table *, struct g_part_entry 
*,
     char *, size_t);
 static int g_part_bsd_write(struct g_part_table *, struct g_consumer *);
+static int g_part_bsd_resize(struct g_part_table *, struct g_part_entry *,
+    struct g_part_parms *);
 
 static kobj_method_t g_part_bsd_methods[] = {
        KOBJMETHOD(g_part_add,          g_part_bsd_add),
@@ -82,6 +84,7 @@ static kobj_method_t g_part_bsd_methods[
        KOBJMETHOD(g_part_dumpconf,     g_part_bsd_dumpconf),
        KOBJMETHOD(g_part_dumpto,       g_part_bsd_dumpto),
        KOBJMETHOD(g_part_modify,       g_part_bsd_modify),
+       KOBJMETHOD(g_part_resize,       g_part_bsd_resize),
        KOBJMETHOD(g_part_name,         g_part_bsd_name),
        KOBJMETHOD(g_part_probe,        g_part_bsd_probe),
        KOBJMETHOD(g_part_read,         g_part_bsd_read),
@@ -288,6 +291,19 @@ g_part_bsd_modify(struct g_part_table *b
        return (0);
 }
 
+static int
+g_part_bsd_resize(struct g_part_table *basetable,
+    struct g_part_entry *baseentry, struct g_part_parms *gpp)
+{
+       struct g_part_bsd_entry *entry;
+
+       entry = (struct g_part_bsd_entry *)baseentry;
+       baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
+       entry->part.p_size = gpp->gpp_size;
+
+       return (0);
+}
+
 static const char *
 g_part_bsd_name(struct g_part_table *table, struct g_part_entry *baseentry,
     char *buf, size_t bufsz)

Modified: head/sys/geom/part/g_part_gpt.c
==============================================================================
--- head/sys/geom/part/g_part_gpt.c     Fri Apr 23 02:31:28 2010        
(r207093)
+++ head/sys/geom/part/g_part_gpt.c     Fri Apr 23 03:11:39 2010        
(r207094)
@@ -103,6 +103,8 @@ static int g_part_gpt_read(struct g_part
 static const char *g_part_gpt_type(struct g_part_table *, struct g_part_entry 
*,
     char *, size_t);
 static int g_part_gpt_write(struct g_part_table *, struct g_consumer *);
+static int g_part_gpt_resize(struct g_part_table *, struct g_part_entry *,
+    struct g_part_parms *);
 
 static kobj_method_t g_part_gpt_methods[] = {
        KOBJMETHOD(g_part_add,          g_part_gpt_add),
@@ -112,6 +114,7 @@ static kobj_method_t g_part_gpt_methods[
        KOBJMETHOD(g_part_dumpconf,     g_part_gpt_dumpconf),
        KOBJMETHOD(g_part_dumpto,       g_part_gpt_dumpto),
        KOBJMETHOD(g_part_modify,       g_part_gpt_modify),
+       KOBJMETHOD(g_part_resize,       g_part_gpt_resize),
        KOBJMETHOD(g_part_name,         g_part_gpt_name),
        KOBJMETHOD(g_part_probe,        g_part_gpt_probe),
        KOBJMETHOD(g_part_read,         g_part_gpt_read),
@@ -550,6 +553,19 @@ g_part_gpt_modify(struct g_part_table *b
        return (0);
 }
 
+static int
+g_part_gpt_resize(struct g_part_table *basetable,
+    struct g_part_entry *baseentry, struct g_part_parms *gpp)
+{
+       struct g_part_gpt_entry *entry;
+       entry = (struct g_part_gpt_entry *)baseentry;
+
+       baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
+       entry->ent.ent_lba_end = baseentry->gpe_end;
+
+       return (0);
+}
+
 static const char *
 g_part_gpt_name(struct g_part_table *table, struct g_part_entry *baseentry,
     char *buf, size_t bufsz)

Modified: head/sys/geom/part/g_part_if.m
==============================================================================
--- head/sys/geom/part/g_part_if.m      Fri Apr 23 02:31:28 2010        
(r207093)
+++ head/sys/geom/part/g_part_if.m      Fri Apr 23 03:11:39 2010        
(r207094)
@@ -58,6 +58,13 @@ CODE {
        {
                return (0);
        }
+
+       static int
+       default_resize(struct g_part_table *t __unused,
+           struct g_part_entry *e __unused, struct g_part_parms *p __unused)
+       {
+               return (ENOSYS);
+       }
 };
 
 # add() - scheme specific processing for the add verb.
@@ -114,6 +121,13 @@ METHOD int modify {
        struct g_part_parms *gpp;
 };
 
+# resize() - scheme specific processing for the resize verb.
+METHOD int resize {
+       struct g_part_table *table;
+       struct g_part_entry *entry;
+       struct g_part_parms *gpp;
+} DEFAULT default_resize;
+
 # name() - return the name of the given partition entry.
 # Typical names are "p1", "s0" or "c".
 METHOD const char * name {

Modified: head/sys/geom/part/g_part_mbr.c
==============================================================================
--- head/sys/geom/part/g_part_mbr.c     Fri Apr 23 02:31:28 2010        
(r207093)
+++ head/sys/geom/part/g_part_mbr.c     Fri Apr 23 03:11:39 2010        
(r207094)
@@ -76,6 +76,8 @@ static int g_part_mbr_setunset(struct g_
 static const char *g_part_mbr_type(struct g_part_table *, struct g_part_entry 
*,
     char *, size_t);
 static int g_part_mbr_write(struct g_part_table *, struct g_consumer *);
+static int g_part_mbr_resize(struct g_part_table *, struct g_part_entry *,
+    struct g_part_parms *);
 
 static kobj_method_t g_part_mbr_methods[] = {
        KOBJMETHOD(g_part_add,          g_part_mbr_add),
@@ -85,6 +87,7 @@ static kobj_method_t g_part_mbr_methods[
        KOBJMETHOD(g_part_dumpconf,     g_part_mbr_dumpconf),
        KOBJMETHOD(g_part_dumpto,       g_part_mbr_dumpto),
        KOBJMETHOD(g_part_modify,       g_part_mbr_modify),
+       KOBJMETHOD(g_part_resize,       g_part_mbr_resize),
        KOBJMETHOD(g_part_name,         g_part_mbr_name),
        KOBJMETHOD(g_part_probe,        g_part_mbr_probe),
        KOBJMETHOD(g_part_read,         g_part_mbr_read),
@@ -302,6 +305,31 @@ g_part_mbr_modify(struct g_part_table *b
        return (0);
 }
 
+static int
+g_part_mbr_resize(struct g_part_table *basetable,
+    struct g_part_entry *baseentry, struct g_part_parms *gpp)
+{
+       struct g_part_mbr_entry *entry;
+       uint32_t size, sectors;
+
+       sectors = basetable->gpt_sectors;
+       size = gpp->gpp_size;
+
+       if (size < sectors)
+               return (EINVAL);
+       if (size % sectors)
+               size = size - (size % sectors);
+       if (size < sectors)
+               return (EINVAL);
+
+       entry = (struct g_part_mbr_entry *)baseentry;
+       baseentry->gpe_end = baseentry->gpe_start + size - 1;
+       entry->ent.dp_size = size;
+       mbr_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl,
+           &entry->ent.dp_ehd, &entry->ent.dp_esect);
+       return (0);
+}
+
 static const char *
 g_part_mbr_name(struct g_part_table *table, struct g_part_entry *baseentry,
     char *buf, size_t bufsz)

Modified: head/sys/geom/part/g_part_pc98.c
==============================================================================
--- head/sys/geom/part/g_part_pc98.c    Fri Apr 23 02:31:28 2010        
(r207093)
+++ head/sys/geom/part/g_part_pc98.c    Fri Apr 23 03:11:39 2010        
(r207094)
@@ -77,6 +77,8 @@ static int g_part_pc98_setunset(struct g
 static const char *g_part_pc98_type(struct g_part_table *,
     struct g_part_entry *, char *, size_t);
 static int g_part_pc98_write(struct g_part_table *, struct g_consumer *);
+static int g_part_pc98_resize(struct g_part_table *, struct g_part_entry *,  
+    struct g_part_parms *);
 
 static kobj_method_t g_part_pc98_methods[] = {
        KOBJMETHOD(g_part_add,          g_part_pc98_add),
@@ -86,6 +88,7 @@ static kobj_method_t g_part_pc98_methods
        KOBJMETHOD(g_part_dumpconf,     g_part_pc98_dumpconf),
        KOBJMETHOD(g_part_dumpto,       g_part_pc98_dumpto),
        KOBJMETHOD(g_part_modify,       g_part_pc98_modify),
+       KOBJMETHOD(g_part_resize,       g_part_pc98_resize),
        KOBJMETHOD(g_part_name,         g_part_pc98_name),
        KOBJMETHOD(g_part_probe,        g_part_pc98_probe),
        KOBJMETHOD(g_part_read,         g_part_pc98_read),
@@ -308,6 +311,31 @@ g_part_pc98_modify(struct g_part_table *
        return (0);
 }
 
+static int
+g_part_pc98_resize(struct g_part_table *basetable,
+    struct g_part_entry *baseentry, struct g_part_parms *gpp)
+{
+       struct g_part_pc98_entry *entry;
+       uint32_t size, cyl;
+
+       cyl = basetable->gpt_heads * basetable->gpt_sectors;
+       size = gpp->gpp_size;
+
+       if (size < cyl)
+               return (EINVAL);
+       if (size % cyl)
+               size = size - (size % cyl);
+       if (size < cyl)
+               return (EINVAL);
+
+       entry = (struct g_part_pc98_entry *)baseentry;
+       baseentry->gpe_end = baseentry->gpe_start + size - 1;
+       pc98_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl,
+           &entry->ent.dp_ehd, &entry->ent.dp_esect);
+
+       return (0);
+}
+
 static const char *
 g_part_pc98_name(struct g_part_table *table, struct g_part_entry *baseentry,
     char *buf, size_t bufsz)

Modified: head/sys/geom/part/g_part_vtoc8.c
==============================================================================
--- head/sys/geom/part/g_part_vtoc8.c   Fri Apr 23 02:31:28 2010        
(r207093)
+++ head/sys/geom/part/g_part_vtoc8.c   Fri Apr 23 03:11:39 2010        
(r207094)
@@ -67,6 +67,8 @@ static int g_part_vtoc8_read(struct g_pa
 static const char *g_part_vtoc8_type(struct g_part_table *, struct 
g_part_entry *,
     char *, size_t);
 static int g_part_vtoc8_write(struct g_part_table *, struct g_consumer *);
+static int g_part_vtoc8_resize(struct g_part_table *, struct g_part_entry *,  
+    struct g_part_parms *);
 
 static kobj_method_t g_part_vtoc8_methods[] = {
        KOBJMETHOD(g_part_add,          g_part_vtoc8_add),
@@ -75,6 +77,7 @@ static kobj_method_t g_part_vtoc8_method
        KOBJMETHOD(g_part_dumpconf,     g_part_vtoc8_dumpconf),
        KOBJMETHOD(g_part_dumpto,       g_part_vtoc8_dumpto),
        KOBJMETHOD(g_part_modify,       g_part_vtoc8_modify),
+       KOBJMETHOD(g_part_resize,       g_part_vtoc8_resize),
        KOBJMETHOD(g_part_name,         g_part_vtoc8_name),
        KOBJMETHOD(g_part_probe,        g_part_vtoc8_probe),
        KOBJMETHOD(g_part_read,         g_part_vtoc8_read),
@@ -294,6 +297,26 @@ g_part_vtoc8_modify(struct g_part_table 
        return (0);
 }
 
+static int
+g_part_vtoc8_resize(struct g_part_table *basetable,
+    struct g_part_entry *entry, struct g_part_parms *gpp)
+{
+       struct g_part_vtoc8_table *table;
+       uint64_t size;
+
+       table = (struct g_part_vtoc8_table *)basetable;
+       size = gpp->gpp_size;
+       if (size % table->secpercyl)
+               size = size - (size % table->secpercyl);
+       if (size < table->secpercyl)
+               return (EINVAL);
+
+       entry->gpe_end = entry->gpe_start + size - 1;
+       be32enc(&table->vtoc.map[entry->gpe_index - 1].nblks, size);
+
+       return (0);
+}
+
 static const char *
 g_part_vtoc8_name(struct g_part_table *table, struct g_part_entry *baseentry,
     char *buf, size_t bufsz)
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to