linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6] fat: Batched discard support for fat
@ 2011-03-28 10:34 Kyungmin Park
  2011-03-29  5:04 ` OGAWA Hirofumi
  2011-03-30 13:22 ` Arnd Bergmann
  0 siblings, 2 replies; 33+ messages in thread
From: Kyungmin Park @ 2011-03-28 10:34 UTC (permalink / raw)
  To: OGAWA Hirofumi, linux-kernel; +Cc: linux-fsdevel, Lukas Czerner

From: Kyungmin Park <kyungmin.park@samsung.com>

FAT supports batched discard as ext4.

Cited from Lukas words.
"The current solution is not ideal because of its bad performance impact.
So basic idea to improve things is to avoid discarding every time some
blocks are freed. and instead batching is together into bigger trims,
which tends to be more effective."

You can find an information in detail at following URLs.
http://lwn.net/Articles/397538/
http://lwn.net/Articles/383933/

Clearify the meaning of "len" (Cited form Lukas mail)

Let the "O" be free (bytes, blocks, whatever), and "=" be used.
Now, we have a filesystem like this.

  OOOO==O===OO===OOOOO==O===O===OOOOOOO===
  ^                                      ^
  0                                      40

This is how it supposed to wotk if you have called FITIRM with parameters:

start = 0
minlen = 2
len = 20

So you will go through (blocks, bytes...) 0 -> 20

  OOOO==O===OO===OOOOO==O===O===OOOOOOO===
  ^                   ^
  0                   20

So, you will call discard on extents:

0-3
You'll skip 6 because is smaller than minlen
10-11
15-19

instead of 

0-3
10-11
15-19
30-36

Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Changelog v6:
	Check the user input tightly
	Fix cyclic trim routine from OGAWA

Changelog v5:
	Exit when start cluster is grater than max cluster

Changelog v4:
	Simplify the exit condition

Changelog v3:
	Adjust the minlen from queue discard_granularity
	Use the corrent len usage
Changelog v2:
	Use the given start and len as Lukas comments
	Check the queue supports discard feature
---
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index f504089..08b53e1 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -299,6 +299,7 @@ extern int fat_alloc_clusters(struct inode *inode, int *cluster,
 			      int nr_cluster);
 extern int fat_free_clusters(struct inode *inode, int cluster);
 extern int fat_count_free_clusters(struct super_block *sb);
+extern int fat_trim_fs(struct super_block *sb, struct fstrim_range *range);
 
 /* fat/file.c */
 extern long fat_generic_ioctl(struct file *filp, unsigned int cmd,
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index b47d2c9..81efef2 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -1,6 +1,8 @@
 /*
  * Copyright (C) 2004, OGAWA Hirofumi
  * Released under GPL v2.
+ *
+ * Batched discard support by Kyungmin Park <kyungmin.park@samsung.com>
  */
 
 #include <linux/module.h>
@@ -541,6 +543,16 @@ out:
 	return err;
 }
 
+static int fat_issue_discard(struct super_block *sb, int cluster, int nr_clus)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	sector_t block, nr_blocks;
+
+	block = fat_clus_to_blknr(sbi, cluster);
+	nr_blocks = nr_clus * sbi->sec_per_clus;
+	return sb_issue_discard(sb, block, nr_blocks, GFP_NOFS, 0);
+}
+
 int fat_free_clusters(struct inode *inode, int cluster)
 {
 	struct super_block *sb = inode->i_sb;
@@ -575,11 +587,7 @@ int fat_free_clusters(struct inode *inode, int cluster)
 			if (cluster != fatent.entry + 1) {
 				int nr_clus = fatent.entry - first_cl + 1;
 
-				sb_issue_discard(sb,
-					fat_clus_to_blknr(sbi, first_cl),
-					nr_clus * sbi->sec_per_clus,
-					GFP_NOFS, 0);
-
+				fat_issue_discard(sb, first_cl, nr_clus);
 				first_cl = cluster;
 			}
 		}
@@ -683,3 +691,80 @@ out:
 	unlock_fat(sbi);
 	return err;
 }
+
+int fat_trim_fs(struct super_block *sb, struct fstrim_range *range)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct fatent_operations *ops = sbi->fatent_ops;
+	struct fat_entry fatent;
+	unsigned long reada_blocks, reada_mask, cur_block;
+	int err, free, count, entry;
+	int start, len, minlen, trimmed;
+
+	start = range->start >> sb->s_blocksize_bits;
+	len = range->len >> sb->s_blocksize_bits;
+	len = round_down(start + len, sbi->sec_per_clus);
+	start = round_up(start, sbi->sec_per_clus);
+	minlen = range->minlen >> sb->s_blocksize_bits;
+	minlen = round_up(minlen, sbi->sec_per_clus);
+	trimmed = 0;
+	count = 0;
+	err = -EINVAL;
+
+	if (start >= sbi->max_cluster)
+		goto out;
+
+	len = (len > sbi->max_cluster) ? sbi->max_cluster : len;
+
+	lock_fat(sbi);
+
+	reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits;
+	reada_mask = reada_blocks - 1;
+	cur_block = 0;
+	entry = 0;
+	free = 0;
+	fatent_init(&fatent);
+
+	if (start < FAT_START_ENT)
+		start = FAT_START_ENT;
+
+	fatent_set_entry(&fatent, start);
+
+	for (count = start; count <= len; count++) {
+		/* readahead of fat blocks */
+		if ((cur_block & reada_mask) == 0) {
+			unsigned long rest = sbi->fat_length - cur_block;
+			fat_ent_reada(sb, &fatent, min(reada_blocks, rest));
+		}
+		cur_block++;
+
+		err = fat_ent_read_block(sb, &fatent);
+		if (err)
+			goto out;
+
+		do {
+			if (ops->ent_get(&fatent) == FAT_ENT_FREE) {
+				free++;
+				if (!entry)
+					entry = fatent.entry;
+			} else if (entry) {
+				if (free >= minlen) {
+					fat_issue_discard(sb, entry, free);
+					trimmed += free;
+				}
+				free = 0;
+				entry = 0;
+			}
+		} while (fat_ent_next(sbi, &fatent));
+	}
+
+	if (free >= minlen) {
+		fat_issue_discard(sb, entry, free);
+		trimmed += free;
+	}
+	range->len = (u64)(trimmed * sbi->sec_per_clus) << sb->s_blocksize_bits;
+	fatent_brelse(&fatent);
+out:
+	unlock_fat(sbi);
+	return err;
+}
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 7257752..8d7901f 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -125,6 +125,36 @@ long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		return fat_ioctl_get_attributes(inode, user_attr);
 	case FAT_IOCTL_SET_ATTRIBUTES:
 		return fat_ioctl_set_attributes(filp, user_attr);
+	case FITRIM:
+	{
+		struct super_block *sb = inode->i_sb;
+		struct request_queue *q = bdev_get_queue(sb->s_bdev);
+		struct fstrim_range range;
+		int ret = 0;
+
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		if (!blk_queue_discard(q))
+			return -EOPNOTSUPP;
+
+		if (copy_from_user(&range, (struct fstrim_range __user *)arg,
+					sizeof(range)))
+			return -EFAULT;
+
+		range.minlen = max_t(unsigned int, range.minlen,
+					q->limits.discard_granularity);
+		ret = fat_trim_fs(sb, &range);
+		if (ret < 0)
+			return ret;
+
+		if (copy_to_user((struct fstrim_range __user *)arg, &range,
+					sizeof(range)))
+			return -EFAULT;
+
+		return 0;
+	}
+
 	default:
 		return -ENOTTY;	/* Inappropriate ioctl for device */
 	}

^ permalink raw reply related	[flat|nested] 33+ messages in thread
* Re: Re: [PATCH v6] fat: Batched discard support for fat
@ 2017-06-15 16:10 Alex Ivanov
  2017-06-16  1:50 ` OGAWA Hirofumi
  0 siblings, 1 reply; 33+ messages in thread
From: Alex Ivanov @ 2017-06-15 16:10 UTC (permalink / raw)
  To: OGAWA Hirofumi; +Cc: Kyungmin Park, linux-fsdevel

Hello gentlemen.

Sorry for the noise, but what are the plans for this? ext4 has FITRIM 
support for a long time.

And we're now in the era of UEFI and SSD, where modern devices do 
require FAT partition for boot.

FAT definitely need some love too.

Thanks.

On 31.08.2011 17:51, OGAWA Hirofumi wrote:
> Kyungmin Park <kmpark@infradead.org> writes:
>
>> Hi Ogawa,
> Hi,
>
>> Do you still object to merge batched discard support on fat?
>>
>> If the current batched discard concept doesn't changed, it can't merge it?
> I'm not blaming "concept". I'm saying current implements (and due to
> current interface confusion) is confusing and makes userland hard to use it.
>
> I really think I explained all my concerns and current implement
> confusion.
>
> Last time I checked, those implementations had even the different error
> code at EOF. How can I say your implement will work without knowing
> right implement?
>
> Again, it is reason, and I'm not blaming "concept" or your implement
> itself.
>
> Thanks.

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2017-06-16  2:15 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-28 10:34 [PATCH v6] fat: Batched discard support for fat Kyungmin Park
2011-03-29  5:04 ` OGAWA Hirofumi
2011-03-29  5:11   ` Kyungmin Park
2011-03-29  6:37     ` OGAWA Hirofumi
2011-03-29  6:42       ` Kyungmin Park
2011-03-29  7:28         ` OGAWA Hirofumi
2011-03-30 13:22 ` Arnd Bergmann
2011-03-30 13:50   ` Lukas Czerner
2011-03-30 13:58     ` Kyungmin Park
2011-03-30 14:45       ` Arnd Bergmann
2011-03-30 14:20     ` Arnd Bergmann
2011-03-30 14:44       ` Kyungmin Park
2011-03-30 15:06         ` Arnd Bergmann
2011-05-24  1:18           ` Kyungmin Park
2011-05-24  4:47             ` OGAWA Hirofumi
2011-05-24  5:21               ` Kyungmin Park
2011-05-24  6:39                 ` OGAWA Hirofumi
2011-05-24  6:55                   ` Kyungmin Park
2011-05-24  7:32                     ` OGAWA Hirofumi
2011-05-24  8:54                       ` Kyungmin Park
2011-05-24  9:44                         ` OGAWA Hirofumi
2011-05-24  9:25                       ` Lukas Czerner
2011-05-24 10:07                         ` OGAWA Hirofumi
2011-05-24 10:44                           ` Lukas Czerner
2011-05-24 11:14                             ` OGAWA Hirofumi
2011-05-24 11:32                               ` Lukas Czerner
2011-05-24 12:19                                 ` OGAWA Hirofumi
2011-05-24 13:30                                   ` Lukas Czerner
2011-05-24 14:19                                     ` OGAWA Hirofumi
2011-08-31 13:02                                       ` Kyungmin Park
2011-08-31 17:51                                         ` OGAWA Hirofumi
2011-10-05 14:38                                           ` Lukas Czerner
  -- strict thread matches above, loose matches on Subject: below --
2017-06-15 16:10 Alex Ivanov
2017-06-16  1:50 ` OGAWA Hirofumi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).