diff options
author | Jan Kara <jack@suse.cz> | 2007-11-14 20:00:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-14 21:45:43 -0500 |
commit | 7c06a8dc64a2d1884bd19b4c6353d9267ae4e3e1 (patch) | |
tree | 67afad25e4de3139d3b993e22327096c3e015013 | |
parent | dbaf4c024a657175f43b5091c4fab8b9f0e17078 (diff) |
Fix 64KB blocksize in ext3 directories
With 64KB blocksize, a directory entry can have size 64KB which does not
fit into 16 bits we have for entry lenght. So we store 0xffff instead and
convert value when read from / written to disk. The patch also converts
some places to use ext3_next_entry() when we are changing them anyway.
[akpm@linux-foundation.org: coding-style cleanups]
Signed-off-by: Jan Kara <jack@suse.cz>
Cc: <linux-ext4@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/ext3/dir.c | 10 | ||||
-rw-r--r-- | fs/ext3/namei.c | 92 | ||||
-rw-r--r-- | include/linux/ext3_fs.h | 20 |
3 files changed, 70 insertions, 52 deletions
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index c8e4ee3af1d0..8ca3bfd72427 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
@@ -67,7 +67,7 @@ int ext3_check_dir_entry (const char * function, struct inode * dir, | |||
67 | unsigned long offset) | 67 | unsigned long offset) |
68 | { | 68 | { |
69 | const char * error_msg = NULL; | 69 | const char * error_msg = NULL; |
70 | const int rlen = le16_to_cpu(de->rec_len); | 70 | const int rlen = ext3_rec_len_from_disk(de->rec_len); |
71 | 71 | ||
72 | if (rlen < EXT3_DIR_REC_LEN(1)) | 72 | if (rlen < EXT3_DIR_REC_LEN(1)) |
73 | error_msg = "rec_len is smaller than minimal"; | 73 | error_msg = "rec_len is smaller than minimal"; |
@@ -173,10 +173,10 @@ revalidate: | |||
173 | * least that it is non-zero. A | 173 | * least that it is non-zero. A |
174 | * failure will be detected in the | 174 | * failure will be detected in the |
175 | * dirent test below. */ | 175 | * dirent test below. */ |
176 | if (le16_to_cpu(de->rec_len) < | 176 | if (ext3_rec_len_from_disk(de->rec_len) < |
177 | EXT3_DIR_REC_LEN(1)) | 177 | EXT3_DIR_REC_LEN(1)) |
178 | break; | 178 | break; |
179 | i += le16_to_cpu(de->rec_len); | 179 | i += ext3_rec_len_from_disk(de->rec_len); |
180 | } | 180 | } |
181 | offset = i; | 181 | offset = i; |
182 | filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | 182 | filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) |
@@ -197,7 +197,7 @@ revalidate: | |||
197 | ret = stored; | 197 | ret = stored; |
198 | goto out; | 198 | goto out; |
199 | } | 199 | } |
200 | offset += le16_to_cpu(de->rec_len); | 200 | offset += ext3_rec_len_from_disk(de->rec_len); |
201 | if (le32_to_cpu(de->inode)) { | 201 | if (le32_to_cpu(de->inode)) { |
202 | /* We might block in the next section | 202 | /* We might block in the next section |
203 | * if the data destination is | 203 | * if the data destination is |
@@ -219,7 +219,7 @@ revalidate: | |||
219 | goto revalidate; | 219 | goto revalidate; |
220 | stored ++; | 220 | stored ++; |
221 | } | 221 | } |
222 | filp->f_pos += le16_to_cpu(de->rec_len); | 222 | filp->f_pos += ext3_rec_len_from_disk(de->rec_len); |
223 | } | 223 | } |
224 | offset = 0; | 224 | offset = 0; |
225 | brelse (bh); | 225 | brelse (bh); |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index ec8170adac53..4ab6f76e63d0 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -177,6 +177,16 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
177 | struct inode *inode); | 177 | struct inode *inode); |
178 | 178 | ||
179 | /* | 179 | /* |
180 | * p is at least 6 bytes before the end of page | ||
181 | */ | ||
182 | static inline struct ext3_dir_entry_2 * | ||
183 | ext3_next_entry(struct ext3_dir_entry_2 *p) | ||
184 | { | ||
185 | return (struct ext3_dir_entry_2 *)((char *)p + | ||
186 | ext3_rec_len_from_disk(p->rec_len)); | ||
187 | } | ||
188 | |||
189 | /* | ||
180 | * Future: use high four bits of block for coalesce-on-delete flags | 190 | * Future: use high four bits of block for coalesce-on-delete flags |
181 | * Mask them off for now. | 191 | * Mask them off for now. |
182 | */ | 192 | */ |
@@ -280,7 +290,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_ent | |||
280 | space += EXT3_DIR_REC_LEN(de->name_len); | 290 | space += EXT3_DIR_REC_LEN(de->name_len); |
281 | names++; | 291 | names++; |
282 | } | 292 | } |
283 | de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); | 293 | de = ext3_next_entry(de); |
284 | } | 294 | } |
285 | printk("(%i)\n", names); | 295 | printk("(%i)\n", names); |
286 | return (struct stats) { names, space, 1 }; | 296 | return (struct stats) { names, space, 1 }; |
@@ -547,14 +557,6 @@ static int ext3_htree_next_block(struct inode *dir, __u32 hash, | |||
547 | 557 | ||
548 | 558 | ||
549 | /* | 559 | /* |
550 | * p is at least 6 bytes before the end of page | ||
551 | */ | ||
552 | static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p) | ||
553 | { | ||
554 | return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len)); | ||
555 | } | ||
556 | |||
557 | /* | ||
558 | * This function fills a red-black tree with information from a | 560 | * This function fills a red-black tree with information from a |
559 | * directory block. It returns the number directory entries loaded | 561 | * directory block. It returns the number directory entries loaded |
560 | * into the tree. If there is an error it is returned in err. | 562 | * into the tree. If there is an error it is returned in err. |
@@ -720,7 +722,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size, | |||
720 | cond_resched(); | 722 | cond_resched(); |
721 | } | 723 | } |
722 | /* XXX: do we need to check rec_len == 0 case? -Chris */ | 724 | /* XXX: do we need to check rec_len == 0 case? -Chris */ |
723 | de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); | 725 | de = ext3_next_entry(de); |
724 | } | 726 | } |
725 | return count; | 727 | return count; |
726 | } | 728 | } |
@@ -822,7 +824,7 @@ static inline int search_dirblock(struct buffer_head * bh, | |||
822 | return 1; | 824 | return 1; |
823 | } | 825 | } |
824 | /* prevent looping on a bad block */ | 826 | /* prevent looping on a bad block */ |
825 | de_len = le16_to_cpu(de->rec_len); | 827 | de_len = ext3_rec_len_from_disk(de->rec_len); |
826 | if (de_len <= 0) | 828 | if (de_len <= 0) |
827 | return -1; | 829 | return -1; |
828 | offset += de_len; | 830 | offset += de_len; |
@@ -1130,7 +1132,7 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) | |||
1130 | rec_len = EXT3_DIR_REC_LEN(de->name_len); | 1132 | rec_len = EXT3_DIR_REC_LEN(de->name_len); |
1131 | memcpy (to, de, rec_len); | 1133 | memcpy (to, de, rec_len); |
1132 | ((struct ext3_dir_entry_2 *) to)->rec_len = | 1134 | ((struct ext3_dir_entry_2 *) to)->rec_len = |
1133 | cpu_to_le16(rec_len); | 1135 | ext3_rec_len_to_disk(rec_len); |
1134 | de->inode = 0; | 1136 | de->inode = 0; |
1135 | map++; | 1137 | map++; |
1136 | to += rec_len; | 1138 | to += rec_len; |
@@ -1149,13 +1151,12 @@ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) | |||
1149 | 1151 | ||
1150 | prev = to = de; | 1152 | prev = to = de; |
1151 | while ((char*)de < base + size) { | 1153 | while ((char*)de < base + size) { |
1152 | next = (struct ext3_dir_entry_2 *) ((char *) de + | 1154 | next = ext3_next_entry(de); |
1153 | le16_to_cpu(de->rec_len)); | ||
1154 | if (de->inode && de->name_len) { | 1155 | if (de->inode && de->name_len) { |
1155 | rec_len = EXT3_DIR_REC_LEN(de->name_len); | 1156 | rec_len = EXT3_DIR_REC_LEN(de->name_len); |
1156 | if (de > to) | 1157 | if (de > to) |
1157 | memmove(to, de, rec_len); | 1158 | memmove(to, de, rec_len); |
1158 | to->rec_len = cpu_to_le16(rec_len); | 1159 | to->rec_len = ext3_rec_len_to_disk(rec_len); |
1159 | prev = to; | 1160 | prev = to; |
1160 | to = (struct ext3_dir_entry_2 *) (((char *) to) + rec_len); | 1161 | to = (struct ext3_dir_entry_2 *) (((char *) to) + rec_len); |
1161 | } | 1162 | } |
@@ -1229,8 +1230,8 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | |||
1229 | /* Fancy dance to stay within two buffers */ | 1230 | /* Fancy dance to stay within two buffers */ |
1230 | de2 = dx_move_dirents(data1, data2, map + split, count - split); | 1231 | de2 = dx_move_dirents(data1, data2, map + split, count - split); |
1231 | de = dx_pack_dirents(data1,blocksize); | 1232 | de = dx_pack_dirents(data1,blocksize); |
1232 | de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); | 1233 | de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de); |
1233 | de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); | 1234 | de2->rec_len = ext3_rec_len_to_disk(data2 + blocksize - (char *) de2); |
1234 | dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); | 1235 | dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); |
1235 | dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); | 1236 | dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); |
1236 | 1237 | ||
@@ -1300,7 +1301,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1300 | return -EEXIST; | 1301 | return -EEXIST; |
1301 | } | 1302 | } |
1302 | nlen = EXT3_DIR_REC_LEN(de->name_len); | 1303 | nlen = EXT3_DIR_REC_LEN(de->name_len); |
1303 | rlen = le16_to_cpu(de->rec_len); | 1304 | rlen = ext3_rec_len_from_disk(de->rec_len); |
1304 | if ((de->inode? rlen - nlen: rlen) >= reclen) | 1305 | if ((de->inode? rlen - nlen: rlen) >= reclen) |
1305 | break; | 1306 | break; |
1306 | de = (struct ext3_dir_entry_2 *)((char *)de + rlen); | 1307 | de = (struct ext3_dir_entry_2 *)((char *)de + rlen); |
@@ -1319,11 +1320,11 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1319 | 1320 | ||
1320 | /* By now the buffer is marked for journaling */ | 1321 | /* By now the buffer is marked for journaling */ |
1321 | nlen = EXT3_DIR_REC_LEN(de->name_len); | 1322 | nlen = EXT3_DIR_REC_LEN(de->name_len); |
1322 | rlen = le16_to_cpu(de->rec_len); | 1323 | rlen = ext3_rec_len_from_disk(de->rec_len); |
1323 | if (de->inode) { | 1324 | if (de->inode) { |
1324 | struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen); | 1325 | struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen); |
1325 | de1->rec_len = cpu_to_le16(rlen - nlen); | 1326 | de1->rec_len = ext3_rec_len_to_disk(rlen - nlen); |
1326 | de->rec_len = cpu_to_le16(nlen); | 1327 | de->rec_len = ext3_rec_len_to_disk(nlen); |
1327 | de = de1; | 1328 | de = de1; |
1328 | } | 1329 | } |
1329 | de->file_type = EXT3_FT_UNKNOWN; | 1330 | de->file_type = EXT3_FT_UNKNOWN; |
@@ -1400,17 +1401,18 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1400 | 1401 | ||
1401 | /* The 0th block becomes the root, move the dirents out */ | 1402 | /* The 0th block becomes the root, move the dirents out */ |
1402 | fde = &root->dotdot; | 1403 | fde = &root->dotdot; |
1403 | de = (struct ext3_dir_entry_2 *)((char *)fde + le16_to_cpu(fde->rec_len)); | 1404 | de = (struct ext3_dir_entry_2 *)((char *)fde + |
1405 | ext3_rec_len_from_disk(fde->rec_len)); | ||
1404 | len = ((char *) root) + blocksize - (char *) de; | 1406 | len = ((char *) root) + blocksize - (char *) de; |
1405 | memcpy (data1, de, len); | 1407 | memcpy (data1, de, len); |
1406 | de = (struct ext3_dir_entry_2 *) data1; | 1408 | de = (struct ext3_dir_entry_2 *) data1; |
1407 | top = data1 + len; | 1409 | top = data1 + len; |
1408 | while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top) | 1410 | while ((char *)(de2 = ext3_next_entry(de)) < top) |
1409 | de = de2; | 1411 | de = de2; |
1410 | de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); | 1412 | de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de); |
1411 | /* Initialize the root; the dot dirents already exist */ | 1413 | /* Initialize the root; the dot dirents already exist */ |
1412 | de = (struct ext3_dir_entry_2 *) (&root->dotdot); | 1414 | de = (struct ext3_dir_entry_2 *) (&root->dotdot); |
1413 | de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2)); | 1415 | de->rec_len = ext3_rec_len_to_disk(blocksize - EXT3_DIR_REC_LEN(2)); |
1414 | memset (&root->info, 0, sizeof(root->info)); | 1416 | memset (&root->info, 0, sizeof(root->info)); |
1415 | root->info.info_length = sizeof(root->info); | 1417 | root->info.info_length = sizeof(root->info); |
1416 | root->info.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version; | 1418 | root->info.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version; |
@@ -1490,7 +1492,7 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry, | |||
1490 | return retval; | 1492 | return retval; |
1491 | de = (struct ext3_dir_entry_2 *) bh->b_data; | 1493 | de = (struct ext3_dir_entry_2 *) bh->b_data; |
1492 | de->inode = 0; | 1494 | de->inode = 0; |
1493 | de->rec_len = cpu_to_le16(blocksize); | 1495 | de->rec_len = ext3_rec_len_to_disk(blocksize); |
1494 | return add_dirent_to_buf(handle, dentry, inode, de, bh); | 1496 | return add_dirent_to_buf(handle, dentry, inode, de, bh); |
1495 | } | 1497 | } |
1496 | 1498 | ||
@@ -1553,7 +1555,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
1553 | goto cleanup; | 1555 | goto cleanup; |
1554 | node2 = (struct dx_node *)(bh2->b_data); | 1556 | node2 = (struct dx_node *)(bh2->b_data); |
1555 | entries2 = node2->entries; | 1557 | entries2 = node2->entries; |
1556 | node2->fake.rec_len = cpu_to_le16(sb->s_blocksize); | 1558 | node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize); |
1557 | node2->fake.inode = 0; | 1559 | node2->fake.inode = 0; |
1558 | BUFFER_TRACE(frame->bh, "get_write_access"); | 1560 | BUFFER_TRACE(frame->bh, "get_write_access"); |
1559 | err = ext3_journal_get_write_access(handle, frame->bh); | 1561 | err = ext3_journal_get_write_access(handle, frame->bh); |
@@ -1651,9 +1653,9 @@ static int ext3_delete_entry (handle_t *handle, | |||
1651 | BUFFER_TRACE(bh, "get_write_access"); | 1653 | BUFFER_TRACE(bh, "get_write_access"); |
1652 | ext3_journal_get_write_access(handle, bh); | 1654 | ext3_journal_get_write_access(handle, bh); |
1653 | if (pde) | 1655 | if (pde) |
1654 | pde->rec_len = | 1656 | pde->rec_len = ext3_rec_len_to_disk( |
1655 | cpu_to_le16(le16_to_cpu(pde->rec_len) + | 1657 | ext3_rec_len_from_disk(pde->rec_len) + |
1656 | le16_to_cpu(de->rec_len)); | 1658 | ext3_rec_len_from_disk(de->rec_len)); |
1657 | else | 1659 | else |
1658 | de->inode = 0; | 1660 | de->inode = 0; |
1659 | dir->i_version++; | 1661 | dir->i_version++; |
@@ -1661,10 +1663,9 @@ static int ext3_delete_entry (handle_t *handle, | |||
1661 | ext3_journal_dirty_metadata(handle, bh); | 1663 | ext3_journal_dirty_metadata(handle, bh); |
1662 | return 0; | 1664 | return 0; |
1663 | } | 1665 | } |
1664 | i += le16_to_cpu(de->rec_len); | 1666 | i += ext3_rec_len_from_disk(de->rec_len); |
1665 | pde = de; | 1667 | pde = de; |
1666 | de = (struct ext3_dir_entry_2 *) | 1668 | de = ext3_next_entry(de); |
1667 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1668 | } | 1669 | } |
1669 | return -ENOENT; | 1670 | return -ENOENT; |
1670 | } | 1671 | } |
@@ -1798,13 +1799,13 @@ retry: | |||
1798 | de = (struct ext3_dir_entry_2 *) dir_block->b_data; | 1799 | de = (struct ext3_dir_entry_2 *) dir_block->b_data; |
1799 | de->inode = cpu_to_le32(inode->i_ino); | 1800 | de->inode = cpu_to_le32(inode->i_ino); |
1800 | de->name_len = 1; | 1801 | de->name_len = 1; |
1801 | de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(de->name_len)); | 1802 | de->rec_len = ext3_rec_len_to_disk(EXT3_DIR_REC_LEN(de->name_len)); |
1802 | strcpy (de->name, "."); | 1803 | strcpy (de->name, "."); |
1803 | ext3_set_de_type(dir->i_sb, de, S_IFDIR); | 1804 | ext3_set_de_type(dir->i_sb, de, S_IFDIR); |
1804 | de = (struct ext3_dir_entry_2 *) | 1805 | de = ext3_next_entry(de); |
1805 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1806 | de->inode = cpu_to_le32(dir->i_ino); | 1806 | de->inode = cpu_to_le32(dir->i_ino); |
1807 | de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1)); | 1807 | de->rec_len = ext3_rec_len_to_disk(inode->i_sb->s_blocksize - |
1808 | EXT3_DIR_REC_LEN(1)); | ||
1808 | de->name_len = 2; | 1809 | de->name_len = 2; |
1809 | strcpy (de->name, ".."); | 1810 | strcpy (de->name, ".."); |
1810 | ext3_set_de_type(dir->i_sb, de, S_IFDIR); | 1811 | ext3_set_de_type(dir->i_sb, de, S_IFDIR); |
@@ -1856,8 +1857,7 @@ static int empty_dir (struct inode * inode) | |||
1856 | return 1; | 1857 | return 1; |
1857 | } | 1858 | } |
1858 | de = (struct ext3_dir_entry_2 *) bh->b_data; | 1859 | de = (struct ext3_dir_entry_2 *) bh->b_data; |
1859 | de1 = (struct ext3_dir_entry_2 *) | 1860 | de1 = ext3_next_entry(de); |
1860 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1861 | if (le32_to_cpu(de->inode) != inode->i_ino || | 1861 | if (le32_to_cpu(de->inode) != inode->i_ino || |
1862 | !le32_to_cpu(de1->inode) || | 1862 | !le32_to_cpu(de1->inode) || |
1863 | strcmp (".", de->name) || | 1863 | strcmp (".", de->name) || |
@@ -1868,9 +1868,9 @@ static int empty_dir (struct inode * inode) | |||
1868 | brelse (bh); | 1868 | brelse (bh); |
1869 | return 1; | 1869 | return 1; |
1870 | } | 1870 | } |
1871 | offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len); | 1871 | offset = ext3_rec_len_from_disk(de->rec_len) + |
1872 | de = (struct ext3_dir_entry_2 *) | 1872 | ext3_rec_len_from_disk(de1->rec_len); |
1873 | ((char *) de1 + le16_to_cpu(de1->rec_len)); | 1873 | de = ext3_next_entry(de1); |
1874 | while (offset < inode->i_size ) { | 1874 | while (offset < inode->i_size ) { |
1875 | if (!bh || | 1875 | if (!bh || |
1876 | (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { | 1876 | (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { |
@@ -1899,9 +1899,8 @@ static int empty_dir (struct inode * inode) | |||
1899 | brelse (bh); | 1899 | brelse (bh); |
1900 | return 0; | 1900 | return 0; |
1901 | } | 1901 | } |
1902 | offset += le16_to_cpu(de->rec_len); | 1902 | offset += ext3_rec_len_from_disk(de->rec_len); |
1903 | de = (struct ext3_dir_entry_2 *) | 1903 | de = ext3_next_entry(de); |
1904 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1905 | } | 1904 | } |
1906 | brelse (bh); | 1905 | brelse (bh); |
1907 | return 1; | 1906 | return 1; |
@@ -2255,8 +2254,7 @@ retry: | |||
2255 | } | 2254 | } |
2256 | 2255 | ||
2257 | #define PARENT_INO(buffer) \ | 2256 | #define PARENT_INO(buffer) \ |
2258 | ((struct ext3_dir_entry_2 *) ((char *) buffer + \ | 2257 | (ext3_next_entry((struct ext3_dir_entry_2 *)(buffer))->inode) |
2259 | le16_to_cpu(((struct ext3_dir_entry_2 *) buffer)->rec_len)))->inode | ||
2260 | 2258 | ||
2261 | /* | 2259 | /* |
2262 | * Anybody can rename anything with this: the permission checks are left to the | 2260 | * Anybody can rename anything with this: the permission checks are left to the |
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 64134456ed8c..241c01cb92b2 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h | |||
@@ -656,6 +656,26 @@ struct ext3_dir_entry_2 { | |||
656 | #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1) | 656 | #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1) |
657 | #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \ | 657 | #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \ |
658 | ~EXT3_DIR_ROUND) | 658 | ~EXT3_DIR_ROUND) |
659 | #define EXT3_MAX_REC_LEN ((1<<16)-1) | ||
660 | |||
661 | static inline unsigned ext3_rec_len_from_disk(__le16 dlen) | ||
662 | { | ||
663 | unsigned len = le16_to_cpu(dlen); | ||
664 | |||
665 | if (len == EXT3_MAX_REC_LEN) | ||
666 | return 1 << 16; | ||
667 | return len; | ||
668 | } | ||
669 | |||
670 | static inline __le16 ext3_rec_len_to_disk(unsigned len) | ||
671 | { | ||
672 | if (len == (1 << 16)) | ||
673 | return cpu_to_le16(EXT3_MAX_REC_LEN); | ||
674 | else if (len > (1 << 16)) | ||
675 | BUG(); | ||
676 | return cpu_to_le16(len); | ||
677 | } | ||
678 | |||
659 | /* | 679 | /* |
660 | * Hash Tree Directory indexing | 680 | * Hash Tree Directory indexing |
661 | * (c) Daniel Phillips, 2001 | 681 | * (c) Daniel Phillips, 2001 |