From b853b96b1dbdc05fc8eae141a595366d8172962b Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Mon, 22 Nov 2010 12:29:17 +0100 Subject: ext3: Add batched discard support for ext3 Walk through allocation groups and trim all free extents. It can be invoked through FITRIM ioctl on the file system. The main idea is to provide a way to trim the whole file system if needed, since some SSD's may suffer from performance loss after the whole device was filled (it does not mean that fs is full!). It search for free extents in allocation groups specified by Byte range start -> start+len. When the free extent is within this range, blocks are marked as used and then trimmed. Afterwards these blocks are marked as free in per-group bitmap. [JK: Fixed up error handling and trimming of a single group] Signed-off-by: Lukas Czerner Reviewed-by: Jan Kara Reviewed-by: Dmitry Monakhov Signed-off-by: Jan Kara --- include/linux/ext3_fs.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 6ce1bca0172..a443965946b 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -856,6 +856,7 @@ extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb, extern int ext3_should_retry_alloc(struct super_block *sb, int *retries); extern void ext3_init_block_alloc_info(struct inode *); extern void ext3_rsv_window_add(struct super_block *sb, struct ext3_reserve_window_node *rsv); +extern int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range); /* dir.c */ extern int ext3_check_dir_entry(const char *, struct inode *, -- cgit v1.2.3-70-g09d2 From 055adcbd7da75868697e767adc4f3272f6cae76c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 23 Nov 2010 18:49:54 -0800 Subject: quota: Use %pV and __attribute__((format (printf in __quota_error and fix fallout Use %pV in __quota_error so a single printk can not be interleaved with other logging messages. Add __attribute__((format (printf, 3, 4))) so format and arguments can be verified by compiler. Make sure printk formats and arguments match. Block # needed a pointer dereference. Signed-off-by: Joe Perches Signed-off-by: Jan Kara --- fs/quota/dquot.c | 18 +++++++++++------- fs/quota/quota_tree.c | 9 +++++---- include/linux/quotaops.h | 5 +++-- 3 files changed, 19 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 0fed41e6efc..84becd3e477 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -133,16 +133,20 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_data_lock); EXPORT_SYMBOL(dq_data_lock); void __quota_error(struct super_block *sb, const char *func, - const char *fmt, ...) + const char *fmt, ...) { - va_list args; - if (printk_ratelimit()) { + va_list args; + struct va_format vaf; + va_start(args, fmt); - printk(KERN_ERR "Quota error (device %s): %s: ", - sb->s_id, func); - vprintk(fmt, args); - printk("\n"); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_ERR "Quota error (device %s): %s: %pV\n", + sb->s_id, func, &vaf); + va_end(args); } } diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c index 9e48874eabc..e41c1becf09 100644 --- a/fs/quota/quota_tree.c +++ b/fs/quota/quota_tree.c @@ -468,8 +468,8 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, return -ENOMEM; ret = read_blk(info, *blk, buf); if (ret < 0) { - quota_error(dquot->dq_sb, "Can't read quota data " - "block %u", blk); + quota_error(dquot->dq_sb, "Can't read quota data block %u", + *blk); goto out_buf; } newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); @@ -493,8 +493,9 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, } else { ret = write_blk(info, *blk, buf); if (ret < 0) - quota_error(dquot->dq_sb, "Can't write quota " - "tree block %u", blk); + quota_error(dquot->dq_sb, + "Can't write quota tree block %u", + *blk); } } out_buf: diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index d1a9193960f..223b14cd129 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -31,8 +31,9 @@ static inline bool is_quota_modification(struct inode *inode, struct iattr *ia) #define quota_error(sb, fmt, args...) \ __quota_error((sb), __func__, fmt , ## args) -extern void __quota_error(struct super_block *sb, const char *func, - const char *fmt, ...); +extern __attribute__((format (printf, 3, 4))) +void __quota_error(struct super_block *sb, const char *func, + const char *fmt, ...); /* * declaration of quota_function calls in kernel. -- cgit v1.2.3-70-g09d2 From a4ae3094869f18e26ece25ad175bbe4cd740e60b Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Tue, 7 Dec 2010 11:55:27 -0600 Subject: ext3: speed up file creates by optimizing rec_len functions The addition of 64k block capability in the rec_len_from_disk and rec_len_to_disk functions added a bit of math overhead which slows down file create workloads needlessly when the architecture cannot even support 64k blocks, thanks to page size limits. Similar changes already exist in the ext4 codebase. The directory entry checking can also be optimized a bit by sprinkling in some unlikely() conditions to move the error handling out of line. bonnie++ sequential file creates on a 512MB ramdisk speeds up from about 77,000/s to about 82,000/s, about a 6% improvement. Signed-off-by: Eric Sandeen Signed-off-by: Jan Kara --- fs/ext3/dir.c | 15 ++++++++------- include/linux/ext3_fs.h | 9 +++++++++ 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index e2e72c367cf..34f0a072b93 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -69,25 +69,26 @@ int ext3_check_dir_entry (const char * function, struct inode * dir, const char * error_msg = NULL; const int rlen = ext3_rec_len_from_disk(de->rec_len); - if (rlen < EXT3_DIR_REC_LEN(1)) + if (unlikely(rlen < EXT3_DIR_REC_LEN(1))) error_msg = "rec_len is smaller than minimal"; - else if (rlen % 4 != 0) + else if (unlikely(rlen % 4 != 0)) error_msg = "rec_len % 4 != 0"; - else if (rlen < EXT3_DIR_REC_LEN(de->name_len)) + else if (unlikely(rlen < EXT3_DIR_REC_LEN(de->name_len))) error_msg = "rec_len is too small for name_len"; - else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize) + else if (unlikely((((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize))) error_msg = "directory entry across blocks"; - else if (le32_to_cpu(de->inode) > - le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count)) + else if (unlikely(le32_to_cpu(de->inode) > + le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))) error_msg = "inode out of bounds"; - if (error_msg != NULL) + if (unlikely(error_msg != NULL)) ext3_error (dir->i_sb, function, "bad entry in directory #%lu: %s - " "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", dir->i_ino, error_msg, offset, (unsigned long) le32_to_cpu(de->inode), rlen, de->name_len); + return error_msg == NULL ? 1 : 0; } diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index a443965946b..65990ef612f 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -724,21 +724,30 @@ struct ext3_dir_entry_2 { ~EXT3_DIR_ROUND) #define EXT3_MAX_REC_LEN ((1<<16)-1) +/* + * Tests against MAX_REC_LEN etc were put in place for 64k block + * sizes; if that is not possible on this arch, we can skip + * those tests and speed things up. + */ static inline unsigned ext3_rec_len_from_disk(__le16 dlen) { unsigned len = le16_to_cpu(dlen); +#if (PAGE_CACHE_SIZE >= 65536) if (len == EXT3_MAX_REC_LEN) return 1 << 16; +#endif return len; } static inline __le16 ext3_rec_len_to_disk(unsigned len) { +#if (PAGE_CACHE_SIZE >= 65536) if (len == (1 << 16)) return cpu_to_le16(EXT3_MAX_REC_LEN); else if (len > (1 << 16)) BUG(); +#endif return cpu_to_le16(len); } -- cgit v1.2.3-70-g09d2 From d96336b05d718b03ff03c94c0dc0cc283a29d534 Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Mon, 27 Dec 2010 13:46:38 -0800 Subject: ext2: Resolve 'dereferencing pointer to incomplete type' when enabling EXT2_XATTR_DEBUG When I enable EXT2_XATTR_DEBUG in fs/ext2/xattr.c I get a build error stating the following: CC fs/ext2/xattr.o fs/ext2/xattr.c: In function 'ext2_xattr_cache_insert': fs/ext2/xattr.c:841: error: dereferencing pointer to incomplete type fs/ext2/xattr.c:846: error: dereferencing pointer to incomplete type make[2]: *** [fs/ext2/xattr.o] Error 1 make[1]: *** [fs/ext2] Error 2 make: *** [fs] Error 2 These lines reference ext2_xattr_cache->c_entry_count which is defined in struct mb_cache. struct mb_cache is currently only defined in fs/mbcache.c. Moving struct mb_cache definition to include/linux/mbcache.h to resolve the issue. Signed-off-by: Josh Hunt Signed-off-by: Jan Kara --- fs/mbcache.c | 12 ------------ include/linux/mbcache.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/fs/mbcache.c b/fs/mbcache.c index 93444747237..a25444ab2ba 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -76,18 +76,6 @@ EXPORT_SYMBOL(mb_cache_entry_find_first); EXPORT_SYMBOL(mb_cache_entry_find_next); #endif -struct mb_cache { - struct list_head c_cache_list; - const char *c_name; - atomic_t c_entry_count; - int c_max_entries; - int c_bucket_bits; - struct kmem_cache *c_entry_cache; - struct list_head *c_block_hash; - struct list_head *c_index_hash; -}; - - /* * Global data: list of all mbcache's, lru list, and a spinlock for * accessing cache data structures on SMP machines. The lru list is diff --git a/include/linux/mbcache.h b/include/linux/mbcache.h index 54cbbac1e71..5525d370701 100644 --- a/include/linux/mbcache.h +++ b/include/linux/mbcache.h @@ -18,6 +18,17 @@ struct mb_cache_entry { } e_index; }; +struct mb_cache { + struct list_head c_cache_list; + const char *c_name; + atomic_t c_entry_count; + int c_max_entries; + int c_bucket_bits; + struct kmem_cache *c_entry_cache; + struct list_head *c_block_hash; + struct list_head *c_index_hash; +}; + /* Functions on caches */ struct mb_cache *mb_cache_create(const char *, int); -- cgit v1.2.3-70-g09d2