diff --git a/autopart.py b/autopart.py
index 8886241..9036224 100644
--- a/autopart.py
+++ b/autopart.py
@@ -865,6 +865,23 @@ def setPreexistParts(diskset, requests):
         part = disk.next_partition()
         while part:
             if part.geom.start == request.start and part.geom.end == request.end:
+                # if the partition is being resized, we do that now
+                if request.targetSize is not None:
+                    startSec = part.geom.start
+                    endSec = part.geom.start + long(((request.targetSize * 1024L * 1024L) / disk.dev.sector_size)) - 1
+
+                    try:
+                        g = part.geom.duplicate()
+                        g.set_end(endSec)
+                        constraint = g.constraint_exact()
+                        part.set_geometry(constraint, startSec, endSec)
+                    except parted.error, msg:
+                        log.error("error setting geometry for partition %s: %s" %(partedUtils.get_partition_name(part), msg))
+                        raise PartitioningError, _("Error resizing partition %s.\n\n%s") %(partedUtils.get_partition_name(part), msg)
+
+                    if startSec != part.geom.start:
+                        raise PartitioningError, _("Start of partition %s was moved when resizing") %(partedUtils.get_partition_name(part),)
+
                 request.device = partedUtils.get_partition_name(part)
                 if request.fstype:
                     if request.fstype.getName() != request.origfstype.getName():
@@ -987,13 +1004,18 @@ def processPartitioning(diskset, requests, newParts):
     for request in requests.requests:
         if request.type == REQUEST_RAID:
             request.size = request.getActualSize(requests, diskset)
-        if request.type == REQUEST_VG:
+        elif request.type == REQUEST_VG:
             request.size = request.getActualSize(requests, diskset)
-        if request.type == REQUEST_LV:
+        elif request.type == REQUEST_LV:
 	    if request.grow:
 		request.setSize(request.getStartSize())
 	    else:
 		request.size = request.getActualSize(requests, diskset)
+        elif request.preexist:
+            # we need to keep track of the max size of preexisting partitions
+            # FIXME: we should also get the max size for LVs at some point
+            part = partedUtils.get_partition_by_name(diskset.disks, request.device)
+            request.maxSize = partedUtils.getMaxAvailPartSizeMB(part)
 
 ##     print "disk layout after everything is done"
 ##     print diskset.diskState()
diff --git a/cmdline.py b/cmdline.py
index c343eb9..972ce9c 100644
--- a/cmdline.py
+++ b/cmdline.py
@@ -38,6 +38,9 @@ class ProgressWindow:
     def pop(self):
         print ""
 
+    def pulse(self):
+        pass
+
     def set(self, amount):
         if amount == self.total:
             print _("Completed"),
@@ -45,7 +48,7 @@ class ProgressWindow:
     def refresh(self):
         pass
 
-    def __init__(self, title, text, total, updpct = 0.05):
+    def __init__(self, title, text, total, updpct = 0.05, pulse = False):
         self.total = total
         print text
         print _("In progress...   "),
@@ -61,8 +64,8 @@ class InstallInterface:
     def shutdown(self):
         pass
 
-    def progressWindow(self, title, text, total, updpct = 0.05):
-        return ProgressWindow(title, text, total, updpct)
+    def progressWindow(self, title, text, total, updpct = 0.05, pulse = False):
+        return ProgressWindow(title, text, total, updpct, pulse)
 
     def kickstartErrorWindow(self, text):
         s = _("The following error was found while parsing your "
diff --git a/dispatch.py b/dispatch.py
index 5775108..8d36483 100644
--- a/dispatch.py
+++ b/dispatch.py
@@ -78,8 +78,10 @@ installSteps = [
     ("upgradeswapsuggestion", upgradeSwapSuggestion, ),
     ("addswap", ),
     ("partitiondone", partitioningComplete, ),
+    ("enablefilesystems", turnOnFilesystems, ),
     ("upgrademigfind", upgradeMigrateFind, ),
     ("upgrademigratefs", ),
+    ("migratefilesystems", doMigrateFilesystems, ),
     ("upgbootloader", ),
     ("bootloadersetup", bootloaderSetupChoices, ),
     ("bootloader", ),
@@ -96,8 +98,6 @@ installSteps = [
     ("confirminstall", ),
     ("confirmupgrade", ),
     ("install", ),
-    ("enablefilesystems", turnOnFilesystems, ),
-    ("migratefilesystems", doMigrateFilesystems, ),
     ("setuptime", setupTimezone, ),
     ("preinstallconfig", doPreInstall, ),
     ("installpackages", doInstall, ),
diff --git a/fsset.py b/fsset.py
index 61ba6a0..9141411 100644
--- a/fsset.py
+++ b/fsset.py
@@ -2,6 +2,7 @@
 # fsset.py: filesystem management
 #
 # Matt Wilson <msw@redhat.com>
+# Jeremy Katz <katzj@redhat.com>
 #
 # Copyright 2001-2007 Red Hat, Inc.
 #
@@ -13,6 +14,7 @@
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 #
 
+import math
 import string
 import isys
 import iutil
@@ -177,10 +179,18 @@ class FileSystemType:
         self.extraFormatArgs = []
         self.maxLabelChars = 16
         self.packages = []
+        self.resizable = False
         self.supportsFsProfiles = False
         self.fsProfileSpecifier = None
         self.fsprofile = None
 
+    def isResizable(self):
+        return self.resizable
+    def resize(self, entry, size, progress, chroot='/'):
+        pass
+    def getMinimumSize(self, device):
+        pass
+
     def isKernelFS(self):
         """Returns True if this is an in-kernel pseudo-filesystem."""
         return False
@@ -505,6 +515,81 @@ class extFileSystem(FileSystemType):
         self.packages = [ "e2fsprogs" ]
         self.supportsFsProfiles = True
         self.fsProfileSpecifier = "-T"
+        self.resizable = True
+
+    def resize(self, entry, size, progress, chroot='/'):
+        devicePath = entry.device.setupDevice(chroot)
+
+        log.info("checking %s prior to resize" %(devicePath,))
+        w = None
+        if progress:
+            w = progress(_("Checking"),
+                         _("Checking filesystem on %s...") %(devicePath), 
+                         100, pulse = True)
+            
+        rc = iutil.execWithPulseProgress("e2fsck", ["-f", "-p", "-C", "0", devicePath],
+                                         stdout="/dev/tty5", 
+                                         stderr="/dev/tty5", progress = w)
+        if rc >= 4:
+            raise RuntimeError, "Check of %s failed" %(devicePath,)
+        if progress:
+            w.pop()
+            w = progress(_("Resizing"),
+                         _("Resizing filesystem on %s...") %(devicePath), 
+                         100, pulse = True)
+
+        log.info("resizing %s" %(devicePath,))
+        rc = iutil.execWithPulseProgress("resize2fs", 
+                                         ["-p", devicePath, "%sM" %(size,)],
+                                         stdout="/dev/tty5", stderr="/dev/tty5",
+                                         progress = w)
+        if progress:
+            w.pop()
+        if rc:
+            raise RuntimeError, "Resize of %s failed" %(devicePath,)
+
+    def getMinimumSize(self, device):
+        """Return the minimum filesystem size in megabytes"""
+        devicePath = "/dev/%s" % (device,)
+        if not os.path.exists(devicePath):
+            isys.makeDevInode(device, devicePath)
+
+        # FIXME: it'd be nice if we didn't have to parse this out ourselves
+        buf = iutil.execWithCapture("/tmp/updates/dumpe2fs",
+                                    ["-h", devicePath],
+                                    stderr = "/dev/tty5")
+        blocks = free = bs = 0
+        for l in buf.split("\n"):
+            if l.startswith("Free blocks"):
+                try:
+                    free = l.split()[2]
+                    free = int(free)
+                except Exception, e:
+                    log.warning("error determining free blocks on %s: %s" %(devicePath, e))
+                    free = 0
+            elif l.startswith("Block size"):
+                try:
+                    bs = l.split()[2]
+                    bs = int(bs)
+                except Exception, e:
+                    log.warning("error determining block size of %s: %s" %(devicePath, e))
+                    bs = 0
+            elif l.startswith("Block count"):
+                try:
+                    blocks = l.split()[2]
+                    blocks = int(blocks)
+                except Exception, e:
+                    log.warning("error determining block count of %s: %s" %(devicePath, e))
+                    blocks = 0
+
+        if free == 0 or bs == 0:
+            log.warning("Unable to determinine minimal size for %s", devicePath)
+            return 1
+
+        used = math.ceil((blocks - free) * bs / 1024.0 / 1024.0)
+        log.info("used size of %s is %s" %(devicePath, used))
+        # FIXME: should we bump this beyond the absolute minimum?
+        return used
 
     def labelDevice(self, entry, chroot):
         devicePath = entry.device.setupDevice(chroot)
@@ -1376,6 +1461,24 @@ MAILADDR root
             if bootPart:
                 del bootPart
 
+    def resizeFilesystems (self, chroot = '/', shrink = False, grow = False):
+        for entry in self.entries:
+            if not entry.fsystem or not entry.fsystem.isResizable():
+                continue
+            if entry.resizeTargetSize is None:
+                continue
+            if shrink and not (entry.resizeTargetSize < entry.resizeOrigSize):
+                continue
+            if grow and not (entry.resizeTargetSize > entry.resizeOrigSize):
+                continue
+            entry.fsystem.resize(entry, entry.resizeTargetSize,
+                                 self.progressWindow, chroot)
+
+    def shrinkFilesystems (self, chroot):
+        self.resizeFilesystems(chroot, shrink = True)
+    def growFilesystems (self, chroot):
+        self.resizeFilesystems(chroot, grow = True)
+
     def formatSwap (self, chroot, forceFormat=False):
         formatted = []
         notformatted = []
@@ -1826,6 +1929,8 @@ class FileSystemSetEntry:
         self.fsystem = fsystem
         self.origfsystem = origfsystem
         self.migrate = migrate
+        self.resizeTargetSize = None
+        self.resizeOrigSize = None
         self.options = options
         self.mountcount = 0
         self.label = None
@@ -1907,6 +2012,15 @@ class FileSystemSetEntry:
     def getMigrate (self):
         return self.migrate
 
+    def setResizeTarget (self, targetsize, size):
+        if not self.fsystem.isResizable() and targetsize is not None:
+            raise ValueError, "Can't set a resize target for a non-resizable filesystem"
+        self.resizeTargetSize = targetsize
+        self.resizeOrigSize = size
+
+    def getResizeTarget (self):
+        return self.targetsize
+
     def isMounted (self):
         return self.mountcount > 0
 
diff --git a/gui.py b/gui.py
index b8ebb63..686ba76 100755
--- a/gui.py
+++ b/gui.py
@@ -511,7 +511,7 @@ class WaitWindow:
 
 class ProgressWindow:
     def __init__(self, title, text, total, updpct = 0.05, updsecs=10,
-                 parent = None):
+                 parent = None, pulse = False):
         if flags.rootpath or not runningMiniWm():
             self.window = gtk.Window()
             if parent:
@@ -543,6 +543,11 @@ class ProgressWindow:
     def refresh(self):
         processEvents()
 
+    def pulse(self):
+        self.progress.set_pulse_step(self.updpct)
+        self.progress.pulse()
+        processEvents()
+
     def set (self, amount):
         # only update widget if we've changed by 5% or our timeout has
         # expired
@@ -940,11 +945,12 @@ class InstallInterface:
         else:
             return WaitWindow (title, text)
 
-    def progressWindow (self, title, text, total, updpct = 0.05):
+    def progressWindow (self, title, text, total, updpct = 0.05, pulse = False):
         if self.icw:
-            return ProgressWindow (title, text, total, updpct, self.icw.window)
+            return ProgressWindow (title, text, total, updpct,
+                                   parent = self.icw.window, pulse = pulse)
         else:
-            return ProgressWindow (title, text, total, updpct)
+            return ProgressWindow (title, text, total, updpct, pulse = pulse)
 
     def packageProgressWindow (self, total, totalSize):
         self.ppw.setSizes (total, totalSize)
diff --git a/iutil.py b/iutil.py
index 926b0c6..f617487 100644
--- a/iutil.py
+++ b/iutil.py
@@ -96,6 +96,66 @@ def execWithCapture(command, argv, stdin = 0, stderr = 2, root='/'):
     pipe.wait()
     return rc
 
+def execWithPulseProgress(command, argv, stdin = 0, stdout = 1, stderr = 2,
+                          progress = None, root = '/'):
+    def chroot():
+        os.chroot(root)
+
+    argv = list(argv)
+    if type(stdin) == type("string"):
+        if os.access(stdin, os.R_OK):
+            stdin = open(stdin)
+        else:
+            stdin = 0
+    if type(stdout) == type("string"):
+        stdout = open(stdout, "w")
+    if type(stderr) == type("string"):
+        stderr = open(stderr, "w")
+
+    p = os.pipe()
+    childpid = os.fork()
+    if not childpid:
+        os.close(p[0])
+        os.dup2(p[1], 1)
+        os.dup2(stderr.fileno(), 2)
+        os.close(p[1])
+        stderr.close()
+
+        os.execvp(command, [command] + argv)
+        os._exit(1)
+
+    os.close(p[1])
+
+    while 1:
+        try:
+            s = os.read(p[0], 1)
+        except OSError, args:
+            (num, str) = args
+            if (num != 4):
+                raise IOError, args
+
+        stdout.write(s)
+        if progress: progress.pulse()
+
+        if len(s) < 1:
+            break
+
+    try:
+        (pid, status) = os.waitpid(childpid, 0)
+    except OSError, (num, msg):
+        log.critical("exception from waitpid: %s %s" %(num, msg))
+
+    progress and progress.pop()
+
+    # *shrug*  no clue why this would happen, but hope that things are fine
+    if status is None:
+        return 0
+
+    if os.WIFEXITED(status):
+        return os.WEXITSTATUS(status)
+
+    return 1
+
 ## Run a shell.
 def execConsole():
     try:
diff --git a/iw/lvm_dialog_gui.py b/iw/lvm_dialog_gui.py
index ae9c614..5368598 100644
--- a/iw/lvm_dialog_gui.py
+++ b/iw/lvm_dialog_gui.py
@@ -479,25 +479,15 @@ class VolumeGroupEditor:
                 format = 1
                 migrate = 0
             else:
-		if self.fsoptionsDict.has_key("formatrb"):
-		    formatrb = self.fsoptionsDict["formatrb"]
-		else:
-		    formatrb = None
-
-		if formatrb:
-                    format = formatrb.get_active()
+		if self.fsoptionsDict.has_key("formatcb"):
+                    format = self.fsoptionsDict["formatcb"].get_active()
                     if format:
                         fsystem = self.fsoptionsDict["fstypeCombo"].get_active_value()
                 else:
                     format = 0
 
-		if self.fsoptionsDict.has_key("migraterb"):
-		    migraterb = self.fsoptionsDict["migraterb"]
-		else:
-		    migraterb = None
-		    
-		if migraterb:
-                    migrate = migraterb.get_active()
+		if self.fsoptionsDict.has_key("migratecb"):
+		    migrate = self.fsoptionsDict["migratecb"].get_active()
                     if migrate:
                         fsystem = self.fsoptionsDict["migfstypeCombo"].get_active_value()
                 else:
diff --git a/iw/partition_dialog_gui.py b/iw/partition_dialog_gui.py
index 042be17..69849c3 100644
--- a/iw/partition_dialog_gui.py
+++ b/iw/partition_dialog_gui.py
@@ -190,30 +190,26 @@ class PartitionEditor:
                 # preexisting partition, just set mount point and format flag
                 request = copy.copy(self.origrequest)
 		
-		if self.fsoptionsDict.has_key("formatrb"):
-		    formatrb = self.fsoptionsDict["formatrb"]
-		else:
-		    formatrb = None
-
-		if formatrb:
-                    request.format = formatrb.get_active()
+		if self.fsoptionsDict.has_key("formatcb"):
+                    request.format = self.fsoptionsDict["formatcb"].get_active()
                     if request.format:
                         request.fstype = self.fsoptionsDict["fstypeCombo"].get_active_value()
                 else:
                     request.format = 0
 
-		if self.fsoptionsDict.has_key("migraterb"):
-		    migraterb = self.fsoptionsDict["migraterb"]
-		else:
-		    migraterb = None
-		    
-		if migraterb:
-                    request.migrate = migraterb.get_active()
+		if self.fsoptionsDict.has_key("migratecb"):
+                    request.migrate = self.fsoptionsDict["migratecb"].get_active()
                     if request.migrate:
                         request.fstype =self.fsoptionsDict["migfstypeCombo"].get_active_value()
                 else:
                     request.migrate = 0
 
+                if self.fsoptionsDict.has_key("resizecb") and self.fsoptionsDict["resizecb"].get_active():
+                    request.targetSize = self.fsoptionsDict["resizesb"].get_value_as_int()
+                else:
+                    request.targetSize = None
+                print "the target size for %s is %s" %(request.mountpoint, request.targetSize)
+
                 # set back if we are not formatting or migrating
 		origfstype = self.origrequest.origfstype
                 if not request.format and not request.migrate:
@@ -299,21 +295,6 @@ class PartitionEditor:
 	    lbl.set_mnemonic_widget(self.newfstypeCombo)
             maintable.attach(self.newfstypeCombo, 1, 2, row, row + 1)
         else:
-            maintable.attach(createAlignedLabel(_("Original File System "
-                                                  "Type:")),
-                             0, 1, row, row + 1)
-
-            if self.origrequest.origfstype:
-                typestr = self.origrequest.origfstype.getName()
-                if self.origrequest.origfstype.getName() == "foreign":
-                    part = get_partition_by_name(self.diskset.disks,
-                                                 self.origrequest.device)
-                    typestr = map_foreign_to_fsname(part.native_type)
-            else:
-                typestr = _("Unknown")
-
-            fstypelabel = gtk.Label(typestr)
-            maintable.attach(fstypelabel, 1, 2, row, row + 1)
             self.newfstypeCombo = None
             
         row = row + 1
@@ -417,10 +398,6 @@ class PartitionEditor:
                 cursize = (endsec - startsec)/2048
                 bycyl_sizelabel.set_text("%s" % (int(cursize)))
         else:
-            maintable.attach(createAlignedLabel(_("Size (MB):")),
-                             0, 1, row, row + 1)
-            sizelabel = gtk.Label("%d" % (origrequest.size))
-            maintable.attach(sizelabel, 1, 2, row, row + 1)
             self.sizespin = None
             
         row = row + 1
diff --git a/iw/partition_ui_helpers_gui.py b/iw/partition_ui_helpers_gui.py
index be66780..89a45d2 100644
--- a/iw/partition_ui_helpers_gui.py
+++ b/iw/partition_ui_helpers_gui.py
@@ -29,6 +29,11 @@ from partedUtils import *
 import rhpl
 from rhpl.translate import _, N_
 
+def istruefalse(val):
+    if val is None or not val:
+        return False
+    return True
+
 class WideCheckList(checklist.CheckList):
     def toggled_item(self, data, row):
 
@@ -206,6 +211,9 @@ def mountptchangeCB(widget, fstypecombo):
     if rhpl.getArch() == "ia64" and widget.get_children()[0].get_text() == "/boot/efi":
         fstypecombo.set_active_text("vfat")
 
+def resizeOptionCB(widget, resizesb):
+    resizesb.set_sensitive(widget.get_active())
+
 def formatOptionCB(widget, data):
     (combowidget, mntptcombo, ofstype) = data
     combowidget.set_sensitive(widget.get_active())
@@ -232,87 +240,80 @@ def noformatCB(widget, data):
 
     Returns the value of row after packing into the maintable,
     and a dictionary consistenting of:
-       noformatrb    - radiobutton for 'leave fs unchanged'
-       formatrb      - radiobutton for 'format as new fs'
+       noformatcb    - checkbutton for 'format as new fs'
        fstype        - part of format fstype menu
        fstypeMenu    - part of format fstype menu
-       migraterb     - radiobutton for migrate fs
-       migfstype     - menu for migrate fs types
+       migratecb     - checkbutton for migrate fs
        migfstypeMenu - menu for migrate fs types
+       resizecb      - checkbutton for 'resize fs'
+       resizesb      - spinbutton with resize target
 """
 def createPreExistFSOptionSection(origrequest, maintable, row, mountCombo,
                                   ignorefs=[]):
+    rc = {}
     ofstype = origrequest.fstype
 
-    maintable.attach(gtk.HSeparator(), 0, 2, row, row + 1)
-    row = row + 1
-
-    label = gtk.Label(_("How would you like to prepare the file system "
-		       "on this partition?"))
-    label.set_line_wrap(1)
-    label.set_alignment(0.0, 0.0)
+    formatcb = gtk.CheckButton(label=_("_Format as:"))
+    maintable.attach(formatcb, 0, 1, row, row + 1)
+    formatcb.set_active(istruefalse(origrequest.format))
+    rc["formatcb"] = formatcb
 
-    maintable.attach(label, 0, 2, row, row + 1)
-    row = row + 1
-
-    noformatrb = gtk.RadioButton(label=_("Leave _unchanged "
-					 "(preserve data)"))
-    noformatrb.set_active(1)
-    maintable.attach(noformatrb, 0, 2, row, row + 1)
-    row = row + 1
-
-    formatrb = gtk.RadioButton(label=_("_Format partition as:"),
-				    group=noformatrb)
-    formatrb.set_active(0)
-    if origrequest.format:
-	formatrb.set_active(1)
-
-    maintable.attach(formatrb, 0, 1, row, row + 1)
     fstypeCombo = createFSTypeMenu(ofstype, fstypechangeCB,
                                    mountCombo, ignorefs=ignorefs)
-    fstypeCombo.set_sensitive(formatrb.get_active())
+    fstypeCombo.set_sensitive(formatcb.get_active())
     maintable.attach(fstypeCombo, 1, 2, row, row + 1)
-    row = row + 1
+    row += 1
+    rc["fstypeCombo"] = fstypeCombo
 
-    if not formatrb.get_active() and not origrequest.migrate:
+    if not formatcb.get_active() and not origrequest.migrate:
 	mountCombo.set_data("prevmountable", ofstype.isMountable())
 
-    formatrb.connect("toggled", formatOptionCB,
-		     (fstypeCombo, mountCombo, ofstype))
+    formatcb.connect("toggled", formatOptionCB,
+                     (fstypeCombo, mountCombo, ofstype))
 
-    noformatrb.connect("toggled", noformatCB,
-		     (fstypeCombo, mountCombo, origrequest.origfstype))
 
     if origrequest.origfstype.isMigratable():
-	migraterb = gtk.RadioButton(label=_("Mi_grate partition to:"),
-				    group=noformatrb)
-	migraterb.set_active(0)
-	if origrequest.migrate:
-	    migraterb.set_active(1)
+	migratecb = gtk.CheckButton(label=_("Mi_grate filesystem to:"))
+        migratecb.set_active(istruefalse(origrequest.migrate))
 
 	migtypes = origrequest.origfstype.getMigratableFSTargets()
 
-	maintable.attach(migraterb, 0, 1, row, row + 1)
+	maintable.attach(migratecb, 0, 1, row, row + 1)
 	migfstypeCombo = createFSTypeMenu(ofstype, None, None,
                                           availablefstypes = migtypes)
-	migfstypeCombo.set_sensitive(migraterb.get_active())
+	migfstypeCombo.set_sensitive(migratecb.get_active())
 	maintable.attach(migfstypeCombo, 1, 2, row, row + 1)
-	row = row + 1
-
-	migraterb.connect("toggled", formatOptionCB,
+        row += 1
+	migratecb.connect("toggled", formatOptionCB,
                           (migfstypeCombo, mountCombo, ofstype))
-    else:
-	migraterb = None
-	migfstypeCombo = None
-
-    row = row + 1
-
-    rc = {}
-    for var in ['noformatrb', 'formatrb', 'fstypeCombo',
-                'migraterb', 'migfstypeCombo']:
-        if eval("%s" % (var,)) is not None:
-            rc[var] = eval("%s" % (var,))
-
+        rc["migratecb"] = migratecb
+        rc["migfstypeCombo"] = migfstypeCombo
+
+    # FIXME: we should support resizing LVs too
+    if origrequest.origfstype.isResizable() and origrequest.type == REQUEST_PREEXIST:
+        resizecb = gtk.CheckButton(label=_("_Resize partition"))
+        resizecb.set_active(origrequest.targetSize is not None)
+        rc["resizecb"] = resizecb
+        maintable.attach(resizecb, 0, 1, row, row + 1)
+
+        if origrequest.targetSize is not None:
+            value = origrequest.targetSize
+        else:
+            value = origrequest.size
+        adj = gtk.Adjustment(value = value,
+                             lower = origrequest.getMinimumResizeMB(),
+                             upper = origrequest.getMaximumResizeMB(),
+                             step_incr = 1)
+        resizesb = gtk.SpinButton(adj, digits = 0)
+        resizesb.set_property('numeric', True)
+        rc["resizesb"] = resizesb
+        maintable.attach(resizesb, 1, 2, row, row + 1)
+
+        resizecb.connect('toggled', resizeOptionCB, resizesb)
+        resizeOptionCB(resizecb, resizesb)
+
+        row += 1
+        
     return (row, rc)
 
 # do tests we just want in UI for now, not kickstart
diff --git a/iw/raid_dialog_gui.py b/iw/raid_dialog_gui.py
index 69e1cf6..09de387 100644
--- a/iw/raid_dialog_gui.py
+++ b/iw/raid_dialog_gui.py
@@ -167,27 +167,17 @@ class RaidEditor:
 		else:
 		    request.format = 0
 	    else:
-		if self.fsoptionsDict.has_key("formatrb"):
-		    formatrb = self.fsoptionsDict["formatrb"]
-		else:
-		    formatrb = None
-
-		if formatrb:
-                    request.format = formatrb.get_active()
+		if self.fsoptionsDict.has_key("formatcb"):
+                    request.format = self.fsoptionsDict["formatcb"].get_active()
                     if request.format:
-                        request.fstype = self.fsoptionsDict["fstypeCombo"].get_active_value()
+                        request.fsystem = self.fsoptionsDict["fstypeCombo"].get_active_value()
                 else:
                     request.format = 0
 
-		if self.fsoptionsDict.has_key("migraterb"):
-		    migraterb = self.fsoptionsDict["migraterb"]
-		else:
-		    migraterb = None
-		    
-		if migraterb:
-                    request.migrate = migraterb.get_active()
+		if self.fsoptionsDict.has_key("migratecb"):
+		    request.migrate = self.fsoptionsDict["migratecb"].get_active()
                     if request.migrate:
-                        request.fstype =self.fsoptionsDict["migfstypeCombo"].get_active_value()
+                        request.fsystem = self.fsoptionsDict["migfstypeCombo"].get_active_value()
                 else:
                     request.migrate = 0
 
diff --git a/packages.py b/packages.py
index aeefde2..09f3685 100644
--- a/packages.py
+++ b/packages.py
@@ -148,8 +148,10 @@ def turnOnFilesystems(anaconda):
                                        searchPath = 1)
             anaconda.id.partitions.doMetaDeletes(anaconda.id.diskset)
             anaconda.id.fsset.setActive(anaconda.id.diskset)
+            anaconda.id.fsset.shrinkFilesystems(anaconda.rootPath)
             if not anaconda.id.fsset.isActive():
                 anaconda.id.diskset.savePartitions ()
+            anaconda.id.fsset.growFilesystems(anaconda.rootPath)
             if not anaconda.id.fsset.volumesCreated:
                 anaconda.id.fsset.createLogicalVolumes(anaconda.rootPath)
             anaconda.id.fsset.formatSwap(anaconda.rootPath)
diff --git a/partRequests.py b/partRequests.py
index 3fbb812..fbb5e13 100644
--- a/partRequests.py
+++ b/partRequests.py
@@ -152,6 +152,9 @@ class RequestSpec:
         self.dev = None
         """A Device() as defined in fsset.py to correspond to this request."""
 
+        self.targetSize = None
+        """Size to resize to"""
+
     def __str__(self):
         if self.fstype:
             fsname = self.fstype.getName()
@@ -209,6 +212,9 @@ class RequestSpec:
         if self.fslabel:
             entry.setLabel(self.fslabel)
 
+        if self.targetSize and self.fstype.isResizable():
+            entry.setResizeTarget(self.targetSize, self.size)
+
         return entry
 
     def setProtected(self, val):
@@ -558,6 +564,18 @@ class PreexistingPartitionSpec(PartitionSpec):
                                mountpoint = mountpoint, preexist = 1)
         self.type = REQUEST_PREEXIST
 
+        self.maxResizeSize = None
+        """Maximum size of this partition request"""
+
+    def getMaximumResizeMB(self):
+        if self.maxResizeSize is not None:
+            return self.maxResizeSize
+        log.warning("%s doesn't have a max size set" %(self.device,))
+        return MAX_PART_SIZE
+
+    def getMinimumResizeMB(self):
+        return self.fstype.getMinimumSize(self.device)
+
 class RaidRequestSpec(RequestSpec):
     """Request to represent RAID devices."""
     
diff --git a/partedUtils.py b/partedUtils.py
index 273f372..a4bac97 100644
--- a/partedUtils.py
+++ b/partedUtils.py
@@ -96,6 +96,24 @@ def getDeviceSizeMB(dev):
     return (float(dev.heads * dev.cylinders * dev.sectors) / (1024 * 1024)
             * dev.sector_size)
 
+def getMaxAvailPartSizeMB(part):
+    """Return the maximum size this partition can grow to by looking
+    at contiguous freespace partitions."""
+
+    disk = part.disk
+    maxlen = part.geom.length
+
+    # let's look at the next partition(s) and if they're freespace,
+    # they can add to our maximum size.
+    np = disk.next_partition(part)
+    while np:
+        if np.type & parted.PARTITION_FREESPACE:
+            maxlen += np.geom.length
+        else:
+            break
+        np = disk.next_partition(np)
+    return math.floor(maxlen * part.geom.dev.sector_size / 1024.0 / 1024.0)
+
 def get_partition_by_name(disks, partname):
     """Return the parted part object associated with partname.  
 
diff --git a/partitions.py b/partitions.py
index 101b3f9..2d3fda0 100644
--- a/partitions.py
+++ b/partitions.py
@@ -101,30 +101,6 @@ def partitioningComplete(anaconda):
             raise RuntimeError, ("Managed to not get an entry back from "
                                  "request.toEntry")
 
-    if (not flags.setupFilesystems
-        or iutil.memAvailable() > isys.EARLY_SWAP_RAM):
-        return
-
-    if not anaconda.isKickstart:
-        rc = anaconda.intf.messageWindow(_("Low Memory"),
-                            _("As you don't have much memory in this "
-                              "machine, we need to turn on swap space "
-                              "immediately. To do this we'll have to "
-                              "write your new partition table to the disk "
-                              "immediately. Is that OK?"), "yesno")
-    else:
-        rc = 1
-
-    if rc:
-        anaconda.id.partitions.doMetaDeletes(anaconda.id.diskset)
-        anaconda.id.fsset.setActive(anaconda.id.diskset)
-        anaconda.id.diskset.savePartitions ()
-        anaconda.id.fsset.createLogicalVolumes(anaconda.rootPath)
-        anaconda.id.fsset.formatSwap(anaconda.rootPath)
-        anaconda.id.fsset.turnOnSwap(anaconda.rootPath)
-
-    return
-
 
 class Partitions:
     """Defines all of the partition requests and delete requests."""
@@ -217,6 +193,7 @@ class Partitions:
                                                              drive = drive,
                                                              format = format)
                 spec.device = fsset.PartedPartitionDevice(part).getDevice()
+                spec.maxSize = partedUtils.getMaxAvailPartSizeMB(part)
 
                 # set label if makes sense
                 if ptype and ptype.isMountable() and \
@@ -225,6 +202,7 @@ class Partitions:
                         if labels[spec.device] and len(labels[spec.device])>0:
                             spec.fslabel = labels[spec.device]
 
+                print "added %s of size %s with max size of %s" %(spec.device, size, spec.maxSize)
                 self.addRequest(spec)
                 part = disk.next_partition(part)
 
diff --git a/scripts/upd-instroot b/scripts/upd-instroot
index 8312eb9..4d695df 100755
--- a/scripts/upd-instroot
+++ b/scripts/upd-instroot
@@ -416,6 +416,7 @@ sbin/busybox.anaconda
 sbin/clock
 sbin/debugfs
 sbin/dosfslabel
+sbin/dumpe2fs
 sbin/e2fsck
 sbin/e2fsadm
 sbin/e2label
diff --git a/text.py b/text.py
index a5eefb5..87b8bc2 100644
--- a/text.py
+++ b/text.py
@@ -115,6 +115,9 @@ class ProgressWindow:
         del self.scale
         self.scale = None
 
+    def pulse(self):
+        pass
+
     def set(self, amount):
         self.scale.set(int(float(amount) * self.multiplier))
         self.screen.refresh()
@@ -122,7 +125,7 @@ class ProgressWindow:
     def refresh(self):
         pass
 
-    def __init__(self, screen, title, text, total, updpct = 0.05):
+    def __init__(self, screen, title, text, total, updpct = 0.05, pulse = False):
         self.multiplier = 1
         if total == 1.0:
             self.multiplier = 100
@@ -136,7 +139,8 @@ class ProgressWindow:
 	g.add(t, 0, 0, (0, 0, 0, 1), anchorLeft=1)
 
         self.scale = Scale(int(width), int(float(total) * self.multiplier))
-        g.add(self.scale, 0, 1)
+        if not pulse:
+            g.add(self.scale, 0, 1)
                 
 	g.draw()
 	self.screen.refresh()
@@ -351,8 +355,8 @@ class InstallInterface:
 		pdb.post_mortem(tb)
 	    os._exit(1)
 
-    def progressWindow(self, title, text, total, updpct = 0.05):
-        return ProgressWindow(self.screen, title, text, total, updpct)
+    def progressWindow(self, title, text, total, updpct = 0.05, pulse = False):
+        return ProgressWindow(self.screen, title, text, total, updpct, pulse)
 
     def messageWindow(self, title, text, type="ok", default = None,
 		      custom_icon=None, custom_buttons=[]):
