Skip to contentSkip to conversation

xfs: batched discard support

RFC PATCH In review Christoph Hellwig 9 participants 29 messages Aug 16, 2009 – Aug 21, 2009

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 xfs: batched discard support

Given that everyone is so big in the discard discussion I'd like to present what I had started to prepare for XFS. I didn't plan to send it out until I get my hands onto a TRIM capable device (or at least get time to add support to qemu), and so far it's only been tested in dry-run mode.

The basic idea is to add an ioctl which walks the free space btrees in each allocation group and simply discard everythin that is free. Given that XFS doesn't gragment freespace very much that's a very efficient way to do it. In addition we also already support setting a threshold under which we don't bother to discard an extent, it's currently hardcoded in the helper tool. In the future we could also add things like a sequence number in the AG headers if anything has changed at all, but let's leave those optimizations until we need them.

XFS locks the allocation btree using the btree buffers, so we do not block allocations from any extent which we're not currenly discarding.

Now the caveat for that is that we really do want to do the discard synchronously, that is wait for the request to finish. That's what I've implemented in this patch, but it's the part I haven't been able to test so far. (and yes, this should be separate patch, but it's really just an RFC for now)

Mark, any chance to try it? Just create an XFS filesystem, age it a bit and then call the attached little trim.c program on the mountmoint (or any file inside the filesystem for that matter)

fs/xfs/linux-2.6/xfs_ioctl.c +28 -0
Index: linux-2.6/fs/xfs/linux-2.6/xfs_ioctl.c
===================================================================
@@ -1275,6 +1275,31 @@ xfs_ioc_getbmapx(
 	return 0;
 }
 
+STATIC int
+xfs_ioc_trim(
+	struct xfs_mount	*mp,
+	__uint32_t		*argp)
+{
+	xfs_agnumber_t		agno;
+	int			error = 0;
+	__uint32_t		minlen;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (get_user(minlen, argp))
+		return -EFAULT;
+
+	down_read(&mp->m_peraglock);
+	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
+		error = -xfs_trim_extents(mp, agno, minlen);
+		if (error)
+			break;
+	}
+	up_read(&mp->m_peraglock);
+
+	return error;
+}
+
 /*
  * Note: some of the ioctl's return positive numbers as a
  * byte count indicating success, such as readlink_by_handle.
@@ -1524,6 +1549,9 @@ xfs_file_ioctl(
 		error = xfs_errortag_clearall(mp, 1);
 		return -error;
 
+	case XFS_IOC_TRIM:
+		return xfs_ioc_trim(mp, arg);
+
 	default:
 		return -ENOTTY;
 	}
fs/xfs/xfs_alloc.c +90 -0

96 lines not on this page · raw message

fs/xfs/xfs_alloc.h +3 -0
Index: linux-2.6/fs/xfs/xfs_alloc.h
===================================================================
@@ -217,4 +217,7 @@ xfs_free_extent(
 	xfs_fsblock_t	bno,	/* starting block number of extent */
 	xfs_extlen_t	len);	/* length of extent */
 
+int xfs_trim_extents(struct xfs_mount *mp, xfs_agnumber_t agno,
+	xfs_extlen_t minlen);
+
 #endif	/* __XFS_ALLOC_H__ */
fs/xfs/xfs_fs.h +1 -0
Index: linux-2.6/fs/xfs/xfs_fs.h
===================================================================
@@ -475,6 +475,7 @@ typedef struct xfs_handle {
 #define XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
 #define XFS_IOC_FSGEOMETRY	     _IOR ('X', 124, struct xfs_fsop_geom)
 #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, __uint32_t)
+#define XFS_IOC_TRIM		     _IOR ('X', 126, __uint32_t)
 /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
 
 
block/blk-barrier.c +14 -5
Index: linux-2.6/block/blk-barrier.c
===================================================================
@@ -348,22 +348,27 @@ static void blkdev_discard_end_io(struct
 		clear_bit(BIO_UPTODATE, &bio->bi_flags);
 	}
 
+	if (bio->bi_private)
+		complete(bio->bi_private);
 	bio_put(bio);
 }
 
 /**
- * blkdev_issue_discard - queue a discard
+ * __blkdev_issue_discard - queue a discard
  * @bdev:	blockdev to issue discard for
  * @sector:	start sector
  * @nr_sects:	number of sectors to discard
  * @gfp_mask:	memory allocation flags (for bio_alloc)
+ * @wait:	if %1 wait for the discard to finish
  *
  * Description:
- *    Issue a discard request for the sectors in question. Does not wait.
+ *    Issue a discard request for the sectors in question.
  */
-int blkdev_issue_discard(struct block_device *bdev,
-			 sector_t sector, sector_t nr_sects, gfp_t gfp_mask)
+int __blkdev_issue_discard(struct block_device *bdev,
+			 sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
+			 int wait)
 {
+	DECLARE_COMPLETION_ONSTACK(done);
 	struct request_queue *q;
 	struct bio *bio;
 	int ret = 0;
@@ -385,6 +390,7 @@ int blkdev_issue_discard(struct block_de
 
 		bio->bi_end_io = blkdev_discard_end_io;
 		bio->bi_bdev = bdev;
+		bio->bi_private = wait ? &done : NULL;
 
 		bio->bi_sector = sector;
 
@@ -399,6 +405,9 @@ int blkdev_issue_discard(struct block_de
 		bio_get(bio);
 		submit_bio(DISCARD_BARRIER, bio);
 
+		if (wait)
+			wait_for_completion(&done);
+
 		/* Check if it failed immediately */
 		if (bio_flagged(bio, BIO_EOPNOTSUPP))
 			ret = -EOPNOTSUPP;
@@ -408,4 +417,4 @@ int blkdev_issue_discard(struct block_de
 	}
 	return ret;
 }
-EXPORT_SYMBOL(blkdev_issue_discard);
+EXPORT_SYMBOL(__blkdev_issue_discard);
include/linux/blkdev.h +8 -2
Index: linux-2.6/include/linux/blkdev.h
===================================================================
@@ -977,8 +977,14 @@ static inline struct request *blk_map_qu
 }
 
 extern int blkdev_issue_flush(struct block_device *, sector_t *);
-extern int blkdev_issue_discard(struct block_device *,
-				sector_t sector, sector_t nr_sects, gfp_t);
+extern int __blkdev_issue_discard(struct block_device *, sector_t sector,
+		sector_t nr_sects, gfp_t, int wait);
+
+static inline int blkdev_issue_discard(struct block_device *bdev,
+		sector_t sector, sector_t nr_sects, gfp_t gfp_mask)
+{
+	return __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, 0);
+}
 
 static inline int sb_issue_discard(struct super_block *sb,
 				   sector_t block, sector_t nr_blocks)

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/ioctl.h>

#define XFS_IOC_TRIM _IOR ('X', 126, uint32_t)

int main(int argc, char **argv)

{
	int minsize = 4096;
	int fd;

	if (argc != 2) {
		fprintf(stderr, "usage: %s mountpoint\n", argv[0]);
		return 1;
	}

	fd = open(argv[1], O_RDONLY);
	if (fd < 0) {
		perror("open");
		return 1;
	}

	if (ioctl(fd, XFS_IOC_TRIM, &minsize)) {
		if (errno == EOPNOTSUPP)
			fprintf(stderr, "TRIM not supported\n");
		else
			perror("XFS_IOC_TRIM");
		return 1;
	}

	return 0;
}

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#1 lore raw
Quoted 24 lines · Christoph Hellwig

Given that everyone is so big in the discard discussion I'd like to present what I had started to prepare for XFS. I didn't plan to send it out until I get my hands onto a TRIM capable device (or at least get time to add support to qemu), and so far it's only been tested in dry-run mode.

The basic idea is to add an ioctl which walks the free space btrees in each allocation group and simply discard everythin that is free. Given that XFS doesn't gragment freespace very much that's a very efficient way to do it. In addition we also already support setting a threshold under which we don't bother to discard an extent, it's currently hardcoded in the helper tool. In the future we could also add things like a sequence number in the AG headers if anything has changed at all, but let's leave those optimizations until we need them.

XFS locks the allocation btree using the btree buffers, so we do not block allocations from any extent which we're not currenly discarding.

Now the caveat for that is that we really do want to do the discard synchronously, that is wait for the request to finish. That's what I've implemented in this patch, but it's the part I haven't been able to test so far. (and yes, this should be separate patch, but it's really just an RFC for now)

Quoted 3 lines

Mark, any chance to try it? Just create an XFS filesystem, age it a bit and then call the attached little trim.c program on the mountmoint (or any file inside the filesystem for that matter)

..

Looking at it now. Thanks, Christoph!

#2 lore raw
Quoted 1 line · Mark Lord

Christoph Hellwig wrote:

..

Quoted 6 lines
Quoted 3 lines

Mark, any chance to try it? Just create an XFS filesystem, age it a bit and then call the attached little trim.c program on the mountmoint (or any file inside the filesystem for that matter)

..

Looking at it now. Thanks, Christoph!

..

Fails to work on 64-bit kernel w/ 32-bit userspace (no compat ioctl). Rebuilding with 32-bit kernel now..

#3 lore raw
Quoted 6 lines · Mark Lord
Quoted 1 line · Mark Lord

Christoph Hellwig wrote:

..

Quoted 3 lines
Quoted 3 lines

Mark, any chance to try it? Just create an XFS filesystem, age it a bit and then call the attached little trim.c program on the mountmoint (or any file inside the filesystem for that matter)

Quoted 7 lines
Quoted 3 lines

..

Looking at it now. Thanks, Christoph!

..

Fails to work on 64-bit kernel w/ 32-bit userspace (no compat ioctl). Rebuilding with 32-bit kernel now..

The actual ioctl is compatible, just add the

	case XFS_IOC_TRIM:
		return xfs_ioc_trim(mp, arg);

to xfs_file_compat_ioctl(). I'll add this to the next spin of the patch.

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#4 lore raw
Quoted 15 lines · Christoph Hellwig
Quoted 6 lines · Mark Lord
Quoted 1 line · Mark Lord

Christoph Hellwig wrote:

..

Quoted 3 lines
Quoted 3 lines

Mark, any chance to try it? Just create an XFS filesystem, age it a bit and then call the attached little trim.c program on the mountmoint (or any file inside the filesystem for that matter)

Quoted 7 lines
Quoted 3 lines

..

Looking at it now. Thanks, Christoph!

..

Fails to work on 64-bit kernel w/ 32-bit userspace (no compat ioctl). Rebuilding with 32-bit kernel now..

Quoted 6 lines

The actual ioctl is compatible, just add the

	case XFS_IOC_TRIM:
		return xfs_ioc_trim(mp, arg);

to xfs_file_compat_ioctl(). I'll add this to the next spin of the patch.

..

Peachy. Rebuilding again now..

Don't wait up for this .. I'll finish it on Sunday. Bedtime. :)

#5 lore raw
Quoted 21 lines · Mark Lord
Quoted 20 lines · Christoph Hellwig
Quoted 6 lines · Mark Lord
Quoted 1 line · Mark Lord

Christoph Hellwig wrote:

..

Quoted 3 lines
Quoted 3 lines

Mark, any chance to try it? Just create an XFS filesystem, age it a bit and then call the attached little trim.c program on the mountmoint (or any file inside the filesystem for that matter)

Quoted 7 lines
Quoted 3 lines

..

Looking at it now. Thanks, Christoph!

..

Fails to work on 64-bit kernel w/ 32-bit userspace (no compat ioctl). Rebuilding with 32-bit kernel now..

The actual ioctl is compatible, just add the

    case XFS_IOC_TRIM:
        return xfs_ioc_trim(mp, arg);
Quoted 6 lines
Quoted 1 line

to xfs_file_compat_ioctl(). I'll add this to the next spin of the patch.

..

Peachy. Rebuilding again now..

Don't wait up for this .. I'll finish it on Sunday. Bedtime. :)

..

Mmm.. doesn't work on stock 2.6.31-rc6.
It must also require Matthew's patches for discard/trim support.

Later.

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#6 lore raw
In reply to Christoph Hellwig
Quoted 15 lines · Christoph Hellwig
Quoted 6 lines · Mark Lord
Quoted 1 line · Mark Lord

Christoph Hellwig wrote:

..

Quoted 3 lines
Quoted 3 lines

Mark, any chance to try it? Just create an XFS filesystem, age it a bit and then call the attached little trim.c program on the mountmoint (or any file inside the filesystem for that matter)

Quoted 7 lines
Quoted 3 lines

..

Looking at it now. Thanks, Christoph!

..

Fails to work on 64-bit kernel w/ 32-bit userspace (no compat ioctl). Rebuilding with 32-bit kernel now..

Quoted 6 lines

The actual ioctl is compatible, just add the

	case XFS_IOC_TRIM:
		return xfs_ioc_trim(mp, arg);

to xfs_file_compat_ioctl(). I'll add this to the next spin of the patch.

..

Okay, this gives me ENOSYS now --> discard/trim support is missing from the lower layers.

What other patches do I need to make this work?

The latest from Matthew's discard tree (May 2009) don't appear to be sufficient, even after updating them for 2.6.31-rc6.

???

#7 lore raw
Quoted 2 lines · Mark Lord

Okay, this gives me ENOSYS now --> discard/trim support is missing from the lower layers.

ENOSYS or EOPNOTSUPP?

Quoted 4 lines

What other patches do I need to make this work?

The latest from Matthew's discard tree (May 2009) don't appear to be sufficient, even after updating them for 2.6.31-rc6.

Hmm. That was kinda the reason why I didn't want to post stuff yet. In current mainline only MTD implements the prepare_discard_fn, and we'll need it implemented and working. I think Matthews patches should be sufficient, unless they have some ATA revision check to not issue the TRIM for your device.

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#8 lore raw
In reply to Mark Lord
Quoted 24 lines · Mark Lord
Quoted 21 lines · Christoph Hellwig
Quoted 6 lines · Mark Lord
Quoted 1 line · Mark Lord

Christoph Hellwig wrote:

..

Quoted 3 lines
Quoted 3 lines

Mark, any chance to try it? Just create an XFS filesystem, age it a bit and then call the attached little trim.c program on the mountmoint (or any file inside the filesystem for that matter)

Quoted 7 lines
Quoted 3 lines

..

Looking at it now. Thanks, Christoph!

..

Fails to work on 64-bit kernel w/ 32-bit userspace (no compat ioctl). Rebuilding with 32-bit kernel now..

The actual ioctl is compatible, just add the

    case XFS_IOC_TRIM:
        return xfs_ioc_trim(mp, arg);

to xfs_file_compat_ioctl(). I'll add this to the next spin of the patch.

..

Quoted 7 lines

Okay, this gives me ENOSYS now --> discard/trim support is missing from the lower layers.

What other patches do I need to make this work?

The latest from Matthew's discard tree (May 2009) don't appear to be sufficient, even after updating them for 2.6.31-rc6.

..

Okay, I got Matthews patches updated onto 2.6.31, and fixed the incompatibilities between those and the XFS TRIM patch (from Christoph), plus a sector_t printk issue.

My apologies for attachments, but I am attaching the updated Christoph patch, as well as my hacked-up forward-port of Matthew's patches.

Not pretty, but they work. :)

Now.. running Christoph's "xfs trim" on a 4.6GB mostly already-trimmed XFS partition gave this for the first time around:

[   25.961891] Filesystem "sdb3": discarding sectors [0xc558-0x102328]
[   27.814553] Filesystem "sdb3": discarding sectors [0x10ea78-0x10e688]
[   29.771218] Filesystem "sdb3": discarding sectors [0x21d120-0x10e860]
[   31.726444] Filesystem "sdb3": discarding sectors [0x32b9a0-0x10e860]
[   33.679023] Filesystem "sdb3": discarding sectors [0x43f220-0x109860]
[   35.629948] Filesystem "sdb3": discarding sectors [0x548aa0-0x10e860]
[   37.583142] Filesystem "sdb3": discarding sectors [0x657320-0x10e860]
[   39.531822] Filesystem "sdb3": discarding sectors [0x765ba0-0x10e860]

Slow, but presumably thorough.
Subsequent runs were equally slow.

The problem is, it still issues TRIMs to the LLD one extent at a time. Compare this with doing it all in a single TRIM command with the wiper.sh script (filesystem unmounted):

[~] time wiper.sh /dev/sdb3 --commit

wiper.sh: Linux SATA SSD TRIM utility, version 1.9b, by Mark Lord. Preparing for offline TRIM of free space on /dev/sdb3 (xfs non-mounted). This operation could destroy your data. Are you sure (y/N)? y Syncing disks..
Beginning TRIM operations..
Trimming 168 free extents encompassing 8793136 sectors (4294 MB) Done.

real 0m1.249s
user 0m0.110s
sys 0m0.063s

That includes the time for me to type 'y' and hit enter. :)

Cheers

block/blk-barrier.c +37 -21
diff -u --recursive --new-file --exclude-from=linux-2.6.31-rc6/Documentation/dontdiff --exclude='*.lds' --exclude-from=linux-2.6.31-rc6/.gitignore linux-2.6.31-rc6/block/blk-barrier.c linux/block/blk-barrier.c
@@ -348,30 +348,22 @@
 		clear_bit(BIO_UPTODATE, &bio->bi_flags);
 	}
 
+	if (bio_has_data(bio))
+		__free_page(bio_page(bio));
+
+	if (bio->bi_private)
+		complete(bio->bi_private);
+
 	bio_put(bio);
 }
 
-/**
- * blkdev_issue_discard - queue a discard
- * @bdev:	blockdev to issue discard for
- * @sector:	start sector
- * @nr_sects:	number of sectors to discard
- * @gfp_mask:	memory allocation flags (for bio_alloc)
- *
- * Description:
- *    Issue a discard request for the sectors in question. Does not wait.
- */
-int blkdev_issue_discard(struct block_device *bdev,
-			 sector_t sector, sector_t nr_sects, gfp_t gfp_mask)
+int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
+				sector_t nr_sects, gfp_t gfp_mask,
+				unsigned type, struct completion *completion)
 {
-	struct request_queue *q;
-	struct bio *bio;
 	int ret = 0;
+	struct request_queue *q = bdev_get_queue(bdev);
 
-	if (bdev->bd_disk == NULL)
-		return -ENXIO;
-
-	q = bdev_get_queue(bdev);
 	if (!q)
 		return -ENXIO;
 
@@ -379,12 +371,13 @@
 		return -EOPNOTSUPP;
 
 	while (nr_sects && !ret) {
-		bio = bio_alloc(gfp_mask, 0);
+		struct bio *bio = bio_alloc(gfp_mask, 1);
 		if (!bio)
 			return -ENOMEM;
 
 		bio->bi_end_io = blkdev_discard_end_io;
 		bio->bi_bdev = bdev;
+		bio->bi_private = completion;
 
 		bio->bi_sector = sector;
 
@@ -396,10 +389,13 @@
 			bio->bi_size = nr_sects << 9;
 			nr_sects = 0;
 		}
+
 		bio_get(bio);
-		submit_bio(DISCARD_BARRIER, bio);
+		submit_bio(type, bio);
+
+		if (completion)
+			wait_for_completion(completion);
 
-		/* Check if it failed immediately */
 		if (bio_flagged(bio, BIO_EOPNOTSUPP))
 			ret = -EOPNOTSUPP;
 		else if (!bio_flagged(bio, BIO_UPTODATE))
@@ -408,4 +404,24 @@
 	}
 	return ret;
 }
+
+/**
+ * blkdev_issue_discard - queue a discard
+ * @bdev:	blockdev to issue discard for
+ * @sector:	start sector
+ * @nr_sects:	number of sectors to discard
+ * @gfp_mask:	memory allocation flags (for bio_alloc)
+ *
+ * Description:
+ *    Issue a discard request for the sectors in question. Does not wait.
+ */
+int blkdev_issue_discard(struct block_device *bdev,
+			 sector_t sector, sector_t nr_sects, gfp_t gfp_mask)
+{
+	if (bdev->bd_disk == NULL)
+		return -ENXIO;
+
+	return __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
+					DISCARD_BARRIER, NULL);
+}
 EXPORT_SYMBOL(blkdev_issue_discard);
block/blk-core.c +3 -1
diff -u --recursive --new-file --exclude-from=linux-2.6.31-rc6/Documentation/dontdiff --exclude='*.lds' --exclude-from=linux-2.6.31-rc6/.gitignore linux-2.6.31-rc6/block/blk-core.c linux/block/blk-core.c
@@ -1107,6 +1107,8 @@
 
 void init_request_from_bio(struct request *req, struct bio *bio)
 {
+	might_sleep();
+
 	req->cpu = bio->bi_comp_cpu;
 	req->cmd_type = REQ_TYPE_FS;
 
@@ -1127,7 +1129,7 @@
 		req->cmd_flags |= REQ_DISCARD;
 		if (bio_barrier(bio))
 			req->cmd_flags |= REQ_SOFTBARRIER;
-		req->q->prepare_discard_fn(req->q, req);
+		req->q->prepare_discard_fn(req->q, req, bio);
 	} else if (unlikely(bio_barrier(bio)))
 		req->cmd_flags |= REQ_HARDBARRIER;
 
block/blk.h +4 -0
diff -u --recursive --new-file --exclude-from=linux-2.6.31-rc6/Documentation/dontdiff --exclude='*.lds' --exclude-from=linux-2.6.31-rc6/.gitignore linux-2.6.31-rc6/block/blk.h linux/block/blk.h
@@ -17,6 +17,10 @@
 		      struct bio *bio);
 void blk_dequeue_request(struct request *rq);
 void __blk_queue_free_tags(struct request_queue *q);
+int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
+				sector_t nr_sects, gfp_t gfp_mask,
+				unsigned type, struct completion *completion);
+
 
 void blk_unplug_work(struct work_struct *work);
 void blk_unplug_timeout(unsigned long data);
block/ioctl.c +4 -45

70 lines not on this page · raw message

drivers/ata/libata-scsi.c +49 -0

67 lines not on this page · raw message

drivers/mtd/mtd_blkdevs.c +1 -1
diff -u --recursive --new-file --exclude-from=linux-2.6.31-rc6/Documentation/dontdiff --exclude='*.lds' --exclude-from=linux-2.6.31-rc6/.gitignore linux-2.6.31-rc6/drivers/mtd/mtd_blkdevs.c linux/drivers/mtd/mtd_blkdevs.c
@@ -33,7 +33,7 @@
 };
 
 static int blktrans_discard_request(struct request_queue *q,
-				    struct request *req)
+				    struct request *req, struct bio *bio)
 {
 	req->cmd_type = REQ_TYPE_LINUX_BLOCK;
 	req->cmd[0] = REQ_LB_OP_DISCARD;
include/linux/blkdev.h +2 -1
diff -u --recursive --new-file --exclude-from=linux-2.6.31-rc6/Documentation/dontdiff --exclude='*.lds' --exclude-from=linux-2.6.31-rc6/.gitignore linux-2.6.31-rc6/include/linux/blkdev.h linux/include/linux/blkdev.h
@@ -255,7 +255,8 @@
 typedef int (make_request_fn) (struct request_queue *q, struct bio *bio);
 typedef int (prep_rq_fn) (struct request_queue *, struct request *);
 typedef void (unplug_fn) (struct request_queue *);
-typedef int (prepare_discard_fn) (struct request_queue *, struct request *);
+typedef int (prepare_discard_fn) (struct request_queue *, struct request *,
+							struct bio *bio);
 
 struct bio_vec;
 struct bvec_merge_data {
include/linux/fs.h +2 -2
diff -u --recursive --new-file --exclude-from=linux-2.6.31-rc6/Documentation/dontdiff --exclude='*.lds' --exclude-from=linux-2.6.31-rc6/.gitignore linux-2.6.31-rc6/include/linux/fs.h linux/include/linux/fs.h
@@ -161,8 +161,8 @@
  * These aren't really reads or writes, they pass down information about
  * parts of device that are now unused by the file system.
  */
-#define DISCARD_NOBARRIER (1 << BIO_RW_DISCARD)
-#define DISCARD_BARRIER ((1 << BIO_RW_DISCARD) | (1 << BIO_RW_BARRIER))
+#define DISCARD_NOBARRIER (WRITE | (1 << BIO_RW_DISCARD))
+#define DISCARD_BARRIER (DISCARD_NOBARRIER | (1 << BIO_RW_BARRIER))
 
 #define SEL_IN		1
 #define SEL_OUT		2
block/blk-barrier.c +1 -0
diff -u --recursive --new-file --exclude-from=linux-2.6.31-rc6//Documentation/dontdiff --exclude='*.lds' --exclude-from=linux-2.6.31-rc6//.gitignore linux-2.6.31-rc6/block/blk-barrier.c linux/block/blk-barrier.c
@@ -425,3 +425,4 @@
 					DISCARD_BARRIER, NULL);
 }
 EXPORT_SYMBOL(blkdev_issue_discard);
+EXPORT_SYMBOL(__blkdev_issue_discard);
fs/xfs/linux-2.6/xfs_ioctl.c +28 -0
diff -u --recursive --new-file --exclude-from=linux-2.6.31-rc6//Documentation/dontdiff --exclude='*.lds' --exclude-from=linux-2.6.31-rc6//.gitignore linux-2.6.31-rc6/fs/xfs/linux-2.6/xfs_ioctl.c linux/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -1274,6 +1274,31 @@
 	return 0;
 }
 
+int
+xfs_ioc_trim(
+	struct xfs_mount	*mp,
+	__uint32_t		*argp)
+{
+	xfs_agnumber_t		agno;
+	int			error = 0;
+	__uint32_t		minlen;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (get_user(minlen, argp))
+		return -EFAULT;
+
+	down_read(&mp->m_peraglock);
+	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
+		error = -xfs_trim_extents(mp, agno, minlen);
+		if (error)
+			break;
+	}
+	up_read(&mp->m_peraglock);
+
+	return error;
+}
+
 /*
  * Note: some of the ioctl's return positive numbers as a
  * byte count indicating success, such as readlink_by_handle.
@@ -1523,6 +1548,9 @@
 		error = xfs_errortag_clearall(mp, 1);
 		return -error;
 
+	case XFS_IOC_TRIM:
+		return xfs_ioc_trim(mp, arg);
+
 	default:
 		return -ENOTTY;
 	}
fs/xfs/linux-2.6/xfs_ioctl32.c +3 -0
diff -u --recursive --new-file --exclude-from=linux-2.6.31-rc6//Documentation/dontdiff --exclude='*.lds' --exclude-from=linux-2.6.31-rc6//.gitignore linux-2.6.31-rc6/fs/xfs/linux-2.6/xfs_ioctl32.c linux/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -539,6 +539,7 @@
 	void			__user *arg = (void __user *)p;
 	int			ioflags = 0;
 	int			error;
+	extern int xfs_ioc_trim(struct xfs_mount *mp, __uint32_t *argp);
 
 	if (filp->f_mode & FMODE_NOCMTIME)
 		ioflags |= IO_INVIS;
@@ -564,6 +565,8 @@
 	case XFS_IOC_ERROR_INJECTION:
 	case XFS_IOC_ERROR_CLEARALL:
 		return xfs_file_ioctl(filp, cmd, p);
+	case XFS_IOC_TRIM:
+		return xfs_ioc_trim(mp, arg);
 #ifndef BROKEN_X86_ALIGNMENT
 	/* These are handled fine if no alignment issues */
 	case XFS_IOC_ALLOCSP:
fs/xfs/xfs_alloc.h +3 -0
diff -u --recursive --new-file --exclude-from=linux-2.6.31-rc6//Documentation/dontdiff --exclude='*.lds' --exclude-from=linux-2.6.31-rc6//.gitignore linux-2.6.31-rc6/fs/xfs/xfs_alloc.h linux/fs/xfs/xfs_alloc.h
@@ -215,4 +215,7 @@
 	xfs_fsblock_t	bno,	/* starting block number of extent */
 	xfs_extlen_t	len);	/* length of extent */
 
+int xfs_trim_extents(struct xfs_mount *mp, xfs_agnumber_t agno,
+	xfs_extlen_t minlen);
+
 #endif	/* __XFS_ALLOC_H__ */
fs/xfs/xfs_fs.h +1 -0
diff -u --recursive --new-file --exclude-from=linux-2.6.31-rc6//Documentation/dontdiff --exclude='*.lds' --exclude-from=linux-2.6.31-rc6//.gitignore linux-2.6.31-rc6/fs/xfs/xfs_fs.h linux/fs/xfs/xfs_fs.h
@@ -475,6 +475,7 @@
 #define XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
 #define XFS_IOC_FSGEOMETRY	     _IOR ('X', 124, struct xfs_fsop_geom)
 #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, __uint32_t)
+#define XFS_IOC_TRIM		     _IOR ('X', 126, __uint32_t)
 /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
 
 
fs/xfs/xfs_alloc.c +94 -0

106 lines not on this page · raw message

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#9 lore raw

Mark Lord wrote:
..

Quoted 18 lines

Slow, but presumably thorough.
Subsequent runs were equally slow.

The problem is, it still issues TRIMs to the LLD one extent at a time. Compare this with doing it all in a single TRIM command with the wiper.sh script (filesystem unmounted):

[~] time wiper.sh /dev/sdb3 --commit

wiper.sh: Linux SATA SSD TRIM utility, version 1.9b, by Mark Lord. Preparing for offline TRIM of free space on /dev/sdb3 (xfs
non-mounted).
This operation could destroy your data. Are you sure (y/N)? y Syncing disks..
Beginning TRIM operations..
Trimming 168 free extents encompassing 8793136 sectors (4294 MB) Done.

Quoted 5 lines

real 0m1.249s
user 0m0.110s
sys 0m0.063s

That includes the time for me to type 'y' and hit enter. :)

..

For completeness, here's the same operation again, except this time on the *mounted* xfs filesystem. It won't be trimming quite as many blocks (leaves 1% free space in reserve),
but otherwise is similar:

[~] time wiper.sh /dev/sdb3 --commit

wiper.sh: Linux SATA SSD TRIM utility, version 1.9b, by Mark Lord. Preparing for online TRIM of free space on /dev/sdb3 (xfs mounted read-write at /x). This operation could destroy your data. Are you sure (y/N)? y Creating temporary file (4348405 KB)..
Syncing disks..
Beginning TRIM operations..
Trimming 134 free extents encompassing 8696816 sectors (4246 MB) Removing temporary file..
Syncing disks..
Done.

real 0m1.212s
user 0m0.043s
sys 0m0.053s

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#10 lore raw
In reply to Mark Lord
Quoted 6 lines · Mark Lord

Okay, I got Matthews patches updated onto 2.6.31, and fixed the incompatibilities between those and the XFS TRIM patch (from Christoph), plus a sector_t printk issue.

My apologies for attachments, but I am attaching the updated Christoph patch, as well as my hacked-up forward-port of Matthew's patches.

Quoted 8 lines

Not pretty, but they work. :)

Now.. running Christoph's "xfs trim" on a 4.6GB mostly already-trimmed XFS partition gave this for the first time around:

The problem is, it still issues TRIMs to the LLD one extent at a time. Compare this with doing it all in a single TRIM command with the wiper.sh script (filesystem unmounted):

I could do a variant which issues a single TRIM, but that would require us to lock out all other allocations for the time the trim takes. I'll hack that up once I get some time.

#11 lore raw
Quoted 12 lines · Christoph Hellwig
Quoted 10 lines · Mark Lord

Okay, I got Matthews patches updated onto 2.6.31, and fixed the incompatibilities between those and the XFS TRIM patch (from Christoph), plus a sector_t printk issue.

My apologies for attachments, but I am attaching the updated Christoph patch, as well as my hacked-up forward-port of Matthew's patches.

Not pretty, but they work. :)

Now.. running Christoph's "xfs trim" on a 4.6GB mostly already-trimmed XFS partition gave this for the first time around:

Quoted 7 lines
Quoted 3 lines

The problem is, it still issues TRIMs to the LLD one extent at a time. Compare this with doing it all in a single TRIM command with the wiper.sh script (filesystem unmounted):

I could do a variant which issues a single TRIM, but that would require us to lock out all other allocations for the time the trim takes. I'll hack that up once I get some time.

..

Matthew's stuff will have to change to support that, too.

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#12 lore raw
In reply to Christoph Hellwig
Quoted 10 lines · Christoph Hellwig

Given that everyone is so big in the discard discussion I'd like to present what I had started to prepare for XFS. I didn't plan to send it out until I get my hands onto a TRIM capable device (or at least get time to add support to qemu), and so far it's only been tested in dry-run mode.

The basic idea is to add an ioctl which walks the free space btrees in each allocation group and simply discard everythin that is free. [...]

A general interface design question: you added a new ioctl XFS_IOC_TRIM case. It's a sub-case of an ugly-looking demultiplexing xfs_file_ioctl().

What is your threshold for turning something into a syscall? When are ioctls acceptable in your opinion?

I'm asking this because we are facing a similar problem with perfcounters: we need to extend the ioctl functionality there but introducing a new syscall looks wasteful.

So i'm torn about the 'syscall versus ioctl' issue, i'd like to avoid making interface design mistakes and i'd like to solicit some opinions about this. I've attached the perfcounters ioctl patch below.

Thanks,

Ingo

----- Forwarded message from Peter Zijlstra <[email protected]> -----

Date: Wed, 19 Aug 2009 11:18:27 +0200
From: Peter Zijlstra <[email protected]>
To: Ingo Molnar <[email protected]>, Paul Mackerras <[email protected]>
Subject: [PATCH 4/4][RFC] perf_counter: Allow sharing of output channels
Cc: Arnaldo Carvalho de Melo <[email protected]>,
Frederic Weisbecker <[email protected]>,
Mike Galbraith <[email protected]>, [email protected], stephane eranian <[email protected]>,
Peter Zijlstra <[email protected]>

Provide the ability to configure a counter to send its output to another (already existing) counter's output stream.

[ compile tested only ]

Cc stephane eranian <[email protected]>
---
 include/linux/perf_counter.h |    5 ++
 kernel/perf_counter.c        |   83 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 85 insertions(+), 3 deletions(-)
include/linux/perf_counter.h +5 -0
Index: linux-2.6/include/linux/perf_counter.h
===================================================================
@@ -216,6 +216,7 @@ struct perf_counter_attr {
 #define PERF_COUNTER_IOC_REFRESH	_IO ('$', 2)
 #define PERF_COUNTER_IOC_RESET		_IO ('$', 3)
 #define PERF_COUNTER_IOC_PERIOD		_IOW('$', 4, u64)
+#define PERF_COUNTER_IOC_SET_OUTPUT	_IO ('$', 5)
 
 enum perf_counter_ioc_flags {
 	PERF_IOC_FLAG_GROUP		= 1U << 0,
@@ -415,6 +416,9 @@ enum perf_callchain_context {
 	PERF_CONTEXT_MAX		= (__u64)-4095,
 };
 
+#define PERF_FLAG_FD_NO_GROUP	(1U << 0)
+#define PERF_FLAG_FD_OUTPUT	(1U << 1)
+
 #ifdef __KERNEL__
 /*
  * Kernel-internal data types and definitions:
@@ -536,6 +540,7 @@ struct perf_counter {
 	struct list_head		sibling_list;
 	int				nr_siblings;
 	struct perf_counter		*group_leader;
+	struct perf_counter		*output;
 	const struct pmu		*pmu;
 
 	enum perf_counter_active_state	state;
kernel/perf_counter.c +80 -3

149 lines not on this page · raw message

Signature · 1 line
----- End forwarded message -----
#13 lore raw
Quoted 3 lines · Ingo Molnar

A general interface design question: you added a new ioctl XFS_IOC_TRIM case. It's a sub-case of an ugly-looking demultiplexing xfs_file_ioctl().

ioctl is per defintion a multiplexer.

Quoted 8 lines

What is your threshold for turning something into a syscall? When are ioctls acceptable in your opinion?

I'm asking this because we are facing a similar problem with perfcounters: we need to extend the ioctl functionality there but introducing a new syscall looks wasteful.

Quoted 4 lines

So i'm torn about the 'syscall versus ioctl' issue, i'd like to avoid making interface design mistakes and i'd like to solicit some opinions about this. I've attached the perfcounters ioctl patch below.

Only add a syscall if it has _one_ clear defined purpose, which has kernel-wide meaning.

Do not add an syscall that is just another multiplexer without structure. Most likely it will just be even worse than sys_ioctl.

Also really don't bother adding a system call that is specific to one singler driver or filesystem. Besides horrible logistics - you'd need some always built-in stub calling out to the possibly modular drivers/filesystem - it also simply doesn't make any semantical sense. I can't say I like the ioctl use in perfcounters much, but adding a special syscalls instead would be even more horrible.

As for the trim support this really just was an RFC to start bringing some code into play instead of the endless masturbation about hat code that doesn't exist happens on hardware most people don't have. The interface will most ceetainly change and I hope we will have a common interface for all filesystems (or at least those that care).

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#14 lore raw
Quoted 7 lines · Christoph Hellwig
Quoted 4 lines

So i'm torn about the 'syscall versus ioctl' issue, i'd like to avoid making interface design mistakes and i'd like to solicit some opinions about this. I've attached the perfcounters ioctl patch below.

Only add a syscall if it has _one_ clear defined purpose, which has kernel-wide meaning.

One clear defined purpose which comes to mind is a "trim" or "punch" system call, for making holes in files as well as trimming block devices. Several other OSes have that capability on files.

I don't remember - does TRIM guarantee the blocks read zeros afterwards?

It would be tidy if it does, as it could have the same meaning with files.

-- Jamie

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#15 lore raw
Quoted 5 lines · Jamie Lokier
Quoted 3 lines · Christoph Hellwig
Quoted 1 line

So i'm torn about the 'syscall versus ioctl' issue, i'd like to avoid making interface design mistakes and i'd like to solicit some opinions about this. I've attached the perfcounters ioctl patch below.

Only add a syscall if it has _one_ clear defined purpose, which has kernel-wide meaning.

Quoted 7 lines

One clear defined purpose which comes to mind is a "trim" or "punch" system call, for making holes in files as well as trimming block devices. Several other OSes have that capability on files.

I don't remember - does TRIM guarantee the blocks read zeros afterwards?

It would be tidy if it does, as it could have the same meaning with files.

Both ATA and SCSI leave it up to the device to decide whether reads after a trim on a logical block are determinate (i.e. zeroes are returned) or indeterminate.

In the case of ATA the IDENTIFY DEVICE data word 69 bit 14 gives the indication. In the case of SCSI the READ CAPACITY(16) command response TPRZ bit gives the indication. In both case a value of one indicates determinate.

Doug Gilbert

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#20 lore raw
In reply to Ingo Molnar

[resending, after fixing the Cc: list; somebody trimmed it earlier]

Jamie Lokier wrote:
..

Quoted 1 line

I don't remember - does TRIM guarantee the blocks read zeros afterwards?

..

No, it doesn't.

A drive can optionally support "deterministic TRIM", whereby it will return consistent data for any given trimmed sector afterwards, but that doesn't mean zeros.

-ml

#21 lore raw
Quoted 5 lines · Mark Lord

[resending, after fixing the Cc: list; somebody trimmed it earlier]

Jamie Lokier wrote:
..

Quoted 1 line

I don't remember - does TRIM guarantee the blocks read zeros afterwards?

Quoted 8 lines

..

No, it doesn't.

A drive can optionally support "deterministic TRIM", whereby it will return consistent data for any given trimmed sector afterwards, but that doesn't mean zeros.

-ml

Note that returning consistent data is critical for devices that are used in a RAID group since you will need each RAID block that is used to compute the parity to continue to return the same data until you overwrite it with new data :-)

If we have a device that does not support this (or is misconfigured not to do this), we should not use those devices in an MD group & do discard against it...

ric

#22 lore raw
Quoted 4 lines · Ric Wheeler

Note that returning consistent data is critical for devices that are used in a RAID group since you will need each RAID block that is used to compute the parity to continue to return the same data until you overwrite it with new data :-)

If we have a device that does not support this (or is misconfigured not to do this), we should not use those devices in an MD group & do discard against it...

..

Well, that's a bit drastic. But the RAID software should at least not issue TRIM commands in ignorance of such.

Would it still be okay to do the TRIMs when the entire parity stripe (across all members) is being discarded? (As opposed to just partial data there being dropped)

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#23 lore raw
Quoted 7 lines · Mark Lord
Quoted 6 lines · Ric Wheeler

Note that returning consistent data is critical for devices that are used in a RAID group since you will need each RAID block that is used to compute the parity to continue to return the same data until you overwrite it with new data :-)

Quoted 7 lines
Quoted 3 lines

If we have a device that does not support this (or is misconfigured not to do this), we should not use those devices in an MD group & do discard against it...

..

Well, that's a bit drastic. But the RAID software should at least not issue TRIM commands in ignorance of such.

If the storage can return different data in a sequence of READ requests of the same sector (with no writes), there is nothing RAID could do. It would see total garbage...

Quoted 3 lines

Would it still be okay to do the TRIMs when the entire parity stripe (across all members) is being discarded? (As opposed to just partial data there being dropped)

This should be safe if the MD bitmaps would prevent us from trying to READ/regenerate parity for that stripe...

ric

#25 lore raw
In reply to Mark Lord
Quoted 3 lines · Mark Lord

Would it still be okay to do the TRIMs when the entire parity stripe (across all members) is being discarded? (As opposed to just partial data there being dropped)

Not really. The problem is that array verification is done at the block level not the fs level (although, I suppose, we could change that). So a fully discarded stripe still has to verify OK (as in what's read for the parity must match what's read for the data). All of this is the reason for the TPRZ bit for SCSI UNMAP ... and why WRITE_SAME is also under consideration for discards in T10.

James

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#28 lore raw
In reply to Ric Wheeler
Quoted 10 lines · Ric Wheeler
Quoted 9 lines · Mark Lord

[resending, after fixing the Cc: list; somebody trimmed it earlier]

Jamie Lokier wrote:
..

Quoted 1 line

I don't remember - does TRIM guarantee the blocks read zeros afterwards?

..

No, it doesn't.

Quoted 8 lines
Quoted 4 lines

A drive can optionally support "deterministic TRIM", whereby it will return consistent data for any given trimmed sector afterwards, but that doesn't mean zeros.

-ml

Note that returning consistent data is critical for devices that are used in a RAID group since you will need each RAID block that is used to compute the parity to continue to return the same data until you overwrite it with new data :-)

If we have a device that does not support this (or is misconfigured not to do this), we should not use those devices in an MD group & do discard against it...

A closer reading of d2015r2-ATAATAPI_Command_Set_-_2_ACS-2.pdf section 7.10.3.2 (latest ACS-2 draft from www.t13.org) shows that there are 3 possible variants for data read from a logical block that has been trimmed (or "unmapped"):
a) indeterminate
b) determinate
c) determinate, return all zeroes

In the case of b) the same data is returned for each subsequent read. And that data must not be something that has previously be written to some other LBA!

In the case of SCSI (sbc3r19.pdf) case b) is not supported (very sensibly IMO).

Another difference I noticed between SCSI and ATA drafts is with the SECURITY ERASE UNIT command which is somewhat similar to the SCSI FORMAT UNIT command (which includes a security erase option). The ATA draft says that all blocks are determinate ("mapped" in the SCSI state model) after a SECURITY ERASE UNIT. The SCSI draft says that all logical blocks may be unmapped after FORMAT UNIT.

Doug Gilbert

#26 lore raw
In reply to Mark Lord
Quoted 10 lines · Mark Lord
Quoted 8 lines · Ric Wheeler

Note that returning consistent data is critical for devices that are used in a RAID group since you will need each RAID block that is used to compute the parity to continue to return the same data until you overwrite it with new data :-)

If we have a device that does not support this (or is misconfigured not to do this), we should not use those devices in an MD group & do discard against it...

Quoted 8 lines

..

Well, that's a bit drastic. But the RAID software should at least not issue TRIM commands in ignorance of such.

Would it still be okay to do the TRIMs when the entire parity stripe (across all members) is being discarded? (As opposed to just partial data there being dropped)

I think there might be a related usecase that could benefit from TRIM/UNMAP/whatever support in file systems even if the physical devices do not support that. I have a RAID5 at work with LVM over it. This week I deleted an old logical volume of some 200GB that has been moved to a different volume group, tomorrow I will start to replace all the disks in the raid with bigger ones. So if the LVM told the raid "hey, this space is totally garbage from now on" the raid would not have to do any calculation when it has to rebuild that but could simply write fixed patterns to all disks (e.g. 0 to first data, 0 to second data and 0 as "0 xor 0" to parity). With the knowledge that some of the underlying devices would support "write all to zero" this operation could be speed up even more, with "write all fixed pattern" every unused chunk would go down to a single write operation (per disk) on rebuild regardless which parity algorithm is used.

And even if things are in use the RAID can benefit from such things. If we just define that every unmapped space will always be 0 when read and I write to a raid volume and the other part of the checksum calculation is unmapped checksumming becomes easy as we already know half of the values before: 0. So we can save the reads from the second data stripe and most of the calculation. "dd if=/dev/md0" on an unmapped space is more or less the same as "dd if=/dev/zero" than.

I only fear that these things are too obviously as I would be the first to have this idea ;)

Greetings,

Eike

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#27 lore raw
Quoted 22 lines · Rolf Eike Beer
Quoted 11 lines · Mark Lord
Quoted 9 lines · Ric Wheeler

Note that returning consistent data is critical for devices that are used in a RAID group since you will need each RAID block that is used to compute the parity to continue to return the same data until you overwrite it with new data :-)

If we have a device that does not support this (or is misconfigured not to do this), we should not use those devices in an MD group& do discard against it...

Quoted 9 lines

..

Well, that's a bit drastic. But the RAID software should at least not issue TRIM commands in ignorance of such.

Would it still be okay to do the TRIMs when the entire parity stripe (across all members) is being discarded? (As opposed to just partial data there being dropped)

Quoted 14 lines

I think there might be a related usecase that could benefit from TRIM/UNMAP/whatever support in file systems even if the physical devices do not support that. I have a RAID5 at work with LVM over it. This week I deleted an old logical volume of some 200GB that has been moved to a different volume group, tomorrow I will start to replace all the disks in the raid with bigger ones. So if the LVM told the raid "hey, this space is totally garbage from now on" the raid would not have to do any calculation when it has to rebuild that but could simply write fixed patterns to all disks (e.g. 0 to first data, 0 to second data and 0 as "0 xor 0" to parity). With the knowledge that some of the underlying devices would support "write all to zero" this operation could be speed up even more, with "write all fixed pattern" every unused chunk would go down to a single write operation (per disk) on rebuild regardless which parity algorithm is used.

In the SCSI world, RAID array vendors use "WRITE_SAME" to do this. For the SCSI discard, the write same command has a discard bit set if I remember correctly so you basically get what you are describing above.

ric

Quoted 8 lines

And even if things are in use the RAID can benefit from such things. If we just define that every unmapped space will always be 0 when read and I write to a raid volume and the other part of the checksum calculation is unmapped checksumming becomes easy as we already know half of the values before: 0. So we can save the reads from the second data stripe and most of the calculation. "dd if=/dev/md0" on an unmapped space is more or less the same as "dd if=/dev/zero" than.

Quoted 7 lines

I only fear that these things are too obviously as I would be the first to have this idea ;)

Greetings,

Eike

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#24 lore raw
In reply to Ric Wheeler
Quoted 22 lines · Ric Wheeler
Quoted 8 lines · Mark Lord
Quoted 6 lines · Ric Wheeler

Note that returning consistent data is critical for devices that are used in a RAID group since you will need each RAID block that is used to compute the parity to continue to return the same data until you overwrite it with new data :-)

Quoted 8 lines
Quoted 3 lines

If we have a device that does not support this (or is misconfigured not to do this), we should not use those devices in an MD group & do discard against it...

..

Well, that's a bit drastic. But the RAID software should at least not issue TRIM commands in ignorance of such.

If the storage can return different data in a sequence of READ requests of the same sector (with no writes), there is nothing RAID could do. It would see total garbage...

Quoted 8 lines
Quoted 3 lines

Would it still be okay to do the TRIMs when the entire parity stripe (across all members) is being discarded? (As opposed to just partial data there being dropped)

This should be safe if the MD bitmaps would prevent us from trying to READ/regenerate parity for that stripe...

ric

The harder thing for mdraid is putting a stripe back in service. If even a single sector is written to a "discarded" stripe, the entire stripe has to be written with determinate data that has the right parity.

ie. Only full stripes can be discarded and only full-stripes can be put back in service.

Greg

Signature · 15 lines
Greg Freemyer
Head of EDD Tape Extraction and Processing team
Litigation Triage Solutions Specialist
http://www.linkedin.com/in/gregfreemyer
Preservation and Forensic processing of Exchange Repositories White Paper -
<http://www.norcrossgroup.com/forms/whitepapers/tng_whitepaper_fpe.html>

The Norcross Group
The Intersection of Evidence & Technology
http://www.norcrossgroup.com

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
#17 lore raw
In reply to Christoph Hellwig
Quoted 6 lines · Christoph Hellwig
Quoted 3 lines · Ingo Molnar

A general interface design question: you added a new ioctl XFS_IOC_TRIM case. It's a sub-case of an ugly-looking demultiplexing xfs_file_ioctl().

ioctl is per defintion a multiplexer.

Yes, and? There's two variants of multiplexing:

- multiplex something rather straightforward and related
- multiplex unrelated fields, data, structures

I consider the second one 'ugly', the first one 'ok-ish'. YMMV.

Quoted 26 lines
Quoted 11 lines

What is your threshold for turning something into a syscall? When are ioctls acceptable in your opinion?

I'm asking this because we are facing a similar problem with
perfcounters: we need to extend the ioctl functionality there but introducing a new syscall looks wasteful.

So i'm torn about the 'syscall versus ioctl' issue, i'd like to avoid making interface design mistakes and i'd like to solicit some opinions about this. I've attached the perfcounters ioctl patch below.

Only add a syscall if it has _one_ clear defined purpose, which has kernel-wide meaning.

Do not add an syscall that is just another multiplexer without structure. Most likely it will just be even worse than sys_ioctl.

Also really don't bother adding a system call that is specific to one singler driver or filesystem. Besides horrible logistics - you'd need some always built-in stub calling out to the possibly modular drivers/filesystem - it also simply doesn't make any semantical sense. I can't say I like the ioctl use in perfcounters much, but adding a special syscalls instead would be even more horrible.

Quoted 6 lines

As for the trim support this really just was an RFC to start bringing some code into play instead of the endless masturbation about hat code that doesn't exist happens on hardware most people don't have. The interface will most ceetainly change and I hope we will have a common interface for all filesystems (or at least those that care).

Okay, i'm confused.

I'd like to understand the technical basis of your critisism and i'd like to address any deficiencies of the perfcounters code. You said you dont like the ioctl solution we have, but that you'd like a separate syscall even less.

Perfcounters are a kernel-wide concept, encompassing 100% of all Linux installations, not just some special hardware.

So by your own standard above they seem to be more than eligible for system calls (i hope i'm not mis-stating it), as long as they are cleanly structured. Yet you dont like the interface nor any future pushing of the currently ioctl bits of the interface into syscalls.

Is there any other interface form you'd like more?

Thanks,

Ingo

#18 lore raw

ioctls vs syscalls once again

[chaged the subject and droped the cc list down as this is not about
discard support anymore]

Quoted 8 lines · Ingo Molnar
Quoted 1 line

ioctl is per defintion a multiplexer.

Yes, and? There's two variants of multiplexing:

- multiplex something rather straightforward and related
- multiplex unrelated fields, data, structures

I consider the second one 'ugly', the first one 'ok-ish'. YMMV.

Exactly. And ioctl is per defintion the latter. sys_ioctl is a way to give drivers (and in Linux filesystem, too) a way to implement their own syscall table extension for file descritors they control. While there might be a few "ok-ish" or "nice" ioctl handlers most of them are ugly. That's why people don't like them too much, btw :)

Quoted 4 lines

I'd like to understand the technical basis of your critisism and i'd like to address any deficiencies of the perfcounters code. You said you dont like the ioctl solution we have, but that you'd like a separate syscall even less.

I really don't like any ioctl solution very much. But sometimes it's the lesser of the evils, often by a bug margin.

Quoted 2 lines

Perfcounters are a kernel-wide concept, encompassing 100% of all Linux installations, not just some special hardware.

That doesn't really matter. The tty code is also used by 100% of the Linux installation, and still it implements the tty controls as ioctls.

Generally having system calls that don't operate on file descriptor genericly (that doesn't mean implemented everywhere, but beeing a generic concept dispatched through file operations) is pretty ugly. We have a lot of them anyway, e.g. the socket system calls, eventfd, inotify. They don't really buy us anything over ioctls, but they are accepted. So if you design a clean system call working on perfcounters file descriptor no one could have hard objection (as in actually saying no). But if you really just do another stupid muliplexer just go for ioctl instead of reinventing the dispatching and multiplexing.

#19 lore raw

Re: ioctls vs syscalls once again

Quoted 2 lines · Christoph Hellwig

[ chaged the subject and droped the cc list down as this is not
about discard support anymore]

( it was a good example though, showing where a new ioctl gets
introduced/proposed. )

Quoted 11 lines · Ingo Molnar
Quoted 8 lines
Quoted 1 line

ioctl is per defintion a multiplexer.

Yes, and? There's two variants of multiplexing:

- multiplex something rather straightforward and related
- multiplex unrelated fields, data, structures

I consider the second one 'ugly', the first one 'ok-ish'. YMMV.

Exactly. And ioctl is per defintion the latter. [...]

Just to nitpick: not necessarily. A single-purpose ioctl with no parameter is obviously not going to multiplex anything - and we have some (although not typical - ioctls are addictive and quickly attract messy extensions).

( it might still be considered slightly bad style simply due to the
generic suckiness of type-opaque ioctls as an interface - but that's another matter. )

Quoted 5 lines

[...] sys_ioctl is a way to give drivers (and in Linux filesystem, too) a way to implement their own syscall table extension for file descritors they control. While there might be a few "ok-ish" or "nice" ioctl handlers most of them are ugly. That's why people don't like them too much, btw :)

Can you name a single ok-ish ioctl from the kernel source?

Quoted 7 lines
Quoted 4 lines

I'd like to understand the technical basis of your critisism and i'd like to address any deficiencies of the perfcounters code. You said you dont like the ioctl solution we have, but that you'd like a separate syscall even less.

I really don't like any ioctl solution very much. But sometimes it's the lesser of the evils, often by a bug margin.

Well if something is the best possible technical solution, how can it be evil? (even if lesser than another evil)

That's what i dont understand about your position: i've yet to see you react _positively_ to any perfcounters interface, be that syscall, ioctl or any proposed imaginery API. Is there _anything_ you would react positively to? :-)

Quoted 6 lines
Quoted 2 lines

Perfcounters are a kernel-wide concept, encompassing 100% of all Linux installations, not just some special hardware.

That doesn't really matter. The tty code is also used by 100% of the Linux installation, and still it implements the tty controls as ioctls.

I consider the tty ioctls rather ugly: they have multiple demux layers often hiding important details deep in the bowels of the Nth level of obfuscation. The variants go into the several dozens.

But ... the ioctl interface for TTYs was really inherited as an external compatibility constraint early on, used by a ton of applications, so there was not much to be done about that.

Hindsight is always easy but it might have lead to a cleaner TTY subsystem in general, had it gotten its own system calls (i mean, controlling/setting details of terminal output and input is certainly important enough to be raised to the level of system calls), nicely abstracted out.

Not possible for TTY - but for new code there's no such excuse though.

Quoted 10 lines

Generally having system calls that don't operate on file descriptor genericly (that doesn't mean implemented everywhere, but beeing a generic concept dispatched through file operations) is pretty ugly. We have a lot of them anyway, e.g. the socket system calls, eventfd, inotify. They don't really buy us anything over ioctls, but they are accepted. So if you design a clean system call working on perfcounters file descriptor no one could have hard objection (as in actually saying no). But if you really just do another stupid muliplexer just go for ioctl instead of reinventing the dispatching and multiplexing.

Well, but that's what we have for perfcounters really: there's a clean system call plus an ioctl that multiplexes very simple IO-alike ops. (which borderline passes as an 'IO control' as well)

I'm trying to figure out where the boundary is - how long should we extend the ioctls and when should we start shuffling that functionality into new system calls (cleanly designed and done of course).

Ingo