Skip to content

Commit 3d0518f

Browse files
Wei Yongjuntytso
authored andcommitted
ext4: New rec_len encoding for very large blocksizes
The rec_len field in the directory entry is 16 bits, so to encode blocksizes larger than 64k becomes problematic. This patch allows us to supprot block sizes up to 256k, by using the low 2 bits to extend the range of rec_len to 2**18-1 (since valid rec_len sizes must be a multiple of 4). We use the convention that a rec_len of 0 or 65535 means the filesystem block size, for compatibility with older kernels. It's unlikely we'll see VM pages of up to 256k, but at some point we might find that the Linux VM has been enhanced to support filesystem block sizes > than the VM page size, at which point it might be useful for some applications to allow very large filesystem block sizes. Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
1 parent 8bad459 commit 3d0518f

File tree

3 files changed

+98
-69
lines changed

3 files changed

+98
-69
lines changed

fs/ext4/dir.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ int ext4_check_dir_entry(const char *function, struct inode *dir,
6767
unsigned int offset)
6868
{
6969
const char *error_msg = NULL;
70-
const int rlen = ext4_rec_len_from_disk(de->rec_len);
70+
const int rlen = ext4_rec_len_from_disk(de->rec_len,
71+
dir->i_sb->s_blocksize);
7172

7273
if (rlen < EXT4_DIR_REC_LEN(1))
7374
error_msg = "rec_len is smaller than minimal";
@@ -178,10 +179,11 @@ static int ext4_readdir(struct file *filp,
178179
* least that it is non-zero. A
179180
* failure will be detected in the
180181
* dirent test below. */
181-
if (ext4_rec_len_from_disk(de->rec_len)
182-
< EXT4_DIR_REC_LEN(1))
182+
if (ext4_rec_len_from_disk(de->rec_len,
183+
sb->s_blocksize) < EXT4_DIR_REC_LEN(1))
183184
break;
184-
i += ext4_rec_len_from_disk(de->rec_len);
185+
i += ext4_rec_len_from_disk(de->rec_len,
186+
sb->s_blocksize);
185187
}
186188
offset = i;
187189
filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
@@ -203,7 +205,8 @@ static int ext4_readdir(struct file *filp,
203205
ret = stored;
204206
goto out;
205207
}
206-
offset += ext4_rec_len_from_disk(de->rec_len);
208+
offset += ext4_rec_len_from_disk(de->rec_len,
209+
sb->s_blocksize);
207210
if (le32_to_cpu(de->inode)) {
208211
/* We might block in the next section
209212
* if the data destination is
@@ -225,7 +228,8 @@ static int ext4_readdir(struct file *filp,
225228
goto revalidate;
226229
stored++;
227230
}
228-
filp->f_pos += ext4_rec_len_from_disk(de->rec_len);
231+
filp->f_pos += ext4_rec_len_from_disk(de->rec_len,
232+
sb->s_blocksize);
229233
}
230234
offset = 0;
231235
brelse(bh);

fs/ext4/ext4.h

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -855,24 +855,6 @@ struct ext4_dir_entry_2 {
855855
~EXT4_DIR_ROUND)
856856
#define EXT4_MAX_REC_LEN ((1<<16)-1)
857857

858-
static inline unsigned ext4_rec_len_from_disk(__le16 dlen)
859-
{
860-
unsigned len = le16_to_cpu(dlen);
861-
862-
if (len == EXT4_MAX_REC_LEN || len == 0)
863-
return 1 << 16;
864-
return len;
865-
}
866-
867-
static inline __le16 ext4_rec_len_to_disk(unsigned len)
868-
{
869-
if (len == (1 << 16))
870-
return cpu_to_le16(EXT4_MAX_REC_LEN);
871-
else if (len > (1 << 16))
872-
BUG();
873-
return cpu_to_le16(len);
874-
}
875-
876858
/*
877859
* Hash Tree Directory indexing
878860
* (c) Daniel Phillips, 2001
@@ -1097,7 +1079,10 @@ extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
10971079

10981080
/* migrate.c */
10991081
extern int ext4_ext_migrate(struct inode *);
1082+
11001083
/* namei.c */
1084+
extern unsigned int ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize);
1085+
extern __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize);
11011086
extern int ext4_orphan_add(handle_t *, struct inode *);
11021087
extern int ext4_orphan_del(handle_t *, struct inode *);
11031088
extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,

0 commit comments

Comments
 (0)