On 11/29/2011 11:02 AM, Petr Uzel wrote:
I was also thinking about some new BLKPG-like ioctl()s. Could you
please elaborate more on your new ioctl() proposal? Perhaps we could
combine the ideas...

I just added one to update the length of the partition.  Attaching the patch so 
far ( untested ).

Features of the new ioctl()/s I was thinking about are:
- get largest number of partition known to the kernel
- atomically add/remove more than one partition

What benefit would those provide?


>From 4c533c3198031378eb80c919e00d7875db466ac8 Mon Sep 17 00:00:00 2001
From: Phillip Susi <[email protected]>
Date: Tue, 29 Nov 2011 16:01:29 -0500
Subject: [PATCH] Add partition resize function to BLKPG ioctl

Add a new operation code ( BLKPG_RES_PARTITION ) to the
BLKPG ioctl that allows altering the size of an existing
partition, even if it is currently in use.
---
 block/ioctl.c         |   42 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/blkpg.h |    1 +
 2 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/block/ioctl.c b/block/ioctl.c
index ca939fc..3787f59 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -92,6 +92,48 @@ static int blkpg_ioctl(struct block_device *bdev, struct 
blkpg_ioctl_arg __user
                        bdput(bdevp);
 
                        return 0;
+               case BLKPG_RES_PARTITION:
+                       start = p.start >> 9;
+                       length = p.length >> 9;
+                       /* check for fit in a hd_struct */ 
+                       if (sizeof(sector_t) == sizeof(long) && 
+                           sizeof(long long) > sizeof(long)) {
+                               long pstart = start, plength = length;
+                               if (pstart != start || plength != length
+                                   || pstart < 0 || plength < 0)
+                                       return -EINVAL;
+                       }
+
+                       mutex_lock(&bdev->bd_mutex);
+
+                       /* overlap? */
+                       disk_part_iter_init(&piter, disk,
+                                           DISK_PITER_INCL_EMPTY);
+                       while ((part = disk_part_iter_next(&piter))) {
+                               if (part->partno != partno && !(start + length 
<= part->start_sect ||
+                                     start >= part->start_sect + 
part->nr_sects)) {
+                                       disk_part_iter_exit(&piter);
+                                       mutex_unlock(&bdev->bd_mutex);
+                                       return -EBUSY;
+                               }
+                       }
+                       disk_part_iter_exit(&piter);
+                       part = disk_get_part(disk, partno);
+                       if (!part)
+                       {
+                               mutex_unlock(&bdev->bd_mutex);
+                               return -ENXIO;
+                       }
+                       if (start != part->start_sect)
+                       {
+                               mutex_unlock(&bdev->bd_mutex);
+                               disk_put_part(part);
+                               return -EINVAL;
+                       }
+                       part->nr_sects = length;
+                       disk_put_part(part);
+                       mutex_unlock(&bdev->bd_mutex);
+                       return 0;
                default:
                        return -EINVAL;
        }
diff --git a/include/linux/blkpg.h b/include/linux/blkpg.h
index faf8a45..103da38 100644
--- a/include/linux/blkpg.h
+++ b/include/linux/blkpg.h
@@ -40,6 +40,7 @@ struct blkpg_ioctl_arg {
 /* The subfunctions (for the op field) */
 #define BLKPG_ADD_PARTITION    1
 #define BLKPG_DEL_PARTITION    2
+#define BLKPG_RES_PARTITION    3
 
 /* Sizes of name fields. Unused at present. */
 #define BLKPG_DEVNAMELTH       64
-- 
1.7.5.4


Reply via email to