aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext3')
-rw-r--r--fs/ext3/dir.c2
-rw-r--r--fs/ext3/file.c2
-rw-r--r--fs/ext3/inode.c139
-rw-r--r--fs/ext3/ioctl.c59
-rw-r--r--fs/ext3/namei.c29
5 files changed, 115 insertions, 116 deletions
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index 5853f4440af4..3d724a95882f 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -42,7 +42,7 @@ const struct file_operations ext3_dir_operations = {
42 .llseek = generic_file_llseek, 42 .llseek = generic_file_llseek,
43 .read = generic_read_dir, 43 .read = generic_read_dir,
44 .readdir = ext3_readdir, /* we take BKL. needed?*/ 44 .readdir = ext3_readdir, /* we take BKL. needed?*/
45 .ioctl = ext3_ioctl, /* BKL held */ 45 .unlocked_ioctl = ext3_ioctl,
46#ifdef CONFIG_COMPAT 46#ifdef CONFIG_COMPAT
47 .compat_ioctl = ext3_compat_ioctl, 47 .compat_ioctl = ext3_compat_ioctl,
48#endif 48#endif
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 3be1e0689c9a..521f8238b2fa 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -112,7 +112,7 @@ const struct file_operations ext3_file_operations = {
112 .write = do_sync_write, 112 .write = do_sync_write,
113 .aio_read = generic_file_aio_read, 113 .aio_read = generic_file_aio_read,
114 .aio_write = ext3_file_write, 114 .aio_write = ext3_file_write,
115 .ioctl = ext3_ioctl, 115 .unlocked_ioctl = ext3_ioctl,
116#ifdef CONFIG_COMPAT 116#ifdef CONFIG_COMPAT
117 .compat_ioctl = ext3_compat_ioctl, 117 .compat_ioctl = ext3_compat_ioctl,
118#endif 118#endif
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 4a09ff169870..d3ef6566b019 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1149,12 +1149,15 @@ static int ext3_write_begin(struct file *file, struct address_space *mapping,
1149 struct page **pagep, void **fsdata) 1149 struct page **pagep, void **fsdata)
1150{ 1150{
1151 struct inode *inode = mapping->host; 1151 struct inode *inode = mapping->host;
1152 int ret, needed_blocks = ext3_writepage_trans_blocks(inode); 1152 int ret;
1153 handle_t *handle; 1153 handle_t *handle;
1154 int retries = 0; 1154 int retries = 0;
1155 struct page *page; 1155 struct page *page;
1156 pgoff_t index; 1156 pgoff_t index;
1157 unsigned from, to; 1157 unsigned from, to;
1158 /* Reserve one block more for addition to orphan list in case
1159 * we allocate blocks but write fails for some reason */
1160 int needed_blocks = ext3_writepage_trans_blocks(inode) + 1;
1158 1161
1159 index = pos >> PAGE_CACHE_SHIFT; 1162 index = pos >> PAGE_CACHE_SHIFT;
1160 from = pos & (PAGE_CACHE_SIZE - 1); 1163 from = pos & (PAGE_CACHE_SIZE - 1);
@@ -1184,15 +1187,20 @@ retry:
1184 } 1187 }
1185write_begin_failed: 1188write_begin_failed:
1186 if (ret) { 1189 if (ret) {
1187 ext3_journal_stop(handle);
1188 unlock_page(page);
1189 page_cache_release(page);
1190 /* 1190 /*
1191 * block_write_begin may have instantiated a few blocks 1191 * block_write_begin may have instantiated a few blocks
1192 * outside i_size. Trim these off again. Don't need 1192 * outside i_size. Trim these off again. Don't need
1193 * i_size_read because we hold i_mutex. 1193 * i_size_read because we hold i_mutex.
1194 *
1195 * Add inode to orphan list in case we crash before truncate
1196 * finishes.
1194 */ 1197 */
1195 if (pos + len > inode->i_size) 1198 if (pos + len > inode->i_size)
1199 ext3_orphan_add(handle, inode);
1200 ext3_journal_stop(handle);
1201 unlock_page(page);
1202 page_cache_release(page);
1203 if (pos + len > inode->i_size)
1196 vmtruncate(inode, inode->i_size); 1204 vmtruncate(inode, inode->i_size);
1197 } 1205 }
1198 if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) 1206 if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
@@ -1211,6 +1219,18 @@ int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
1211 return err; 1219 return err;
1212} 1220}
1213 1221
1222/* For ordered writepage and write_end functions */
1223static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh)
1224{
1225 /*
1226 * Write could have mapped the buffer but it didn't copy the data in
1227 * yet. So avoid filing such buffer into a transaction.
1228 */
1229 if (buffer_mapped(bh) && buffer_uptodate(bh))
1230 return ext3_journal_dirty_data(handle, bh);
1231 return 0;
1232}
1233
1214/* For write_end() in data=journal mode */ 1234/* For write_end() in data=journal mode */
1215static int write_end_fn(handle_t *handle, struct buffer_head *bh) 1235static int write_end_fn(handle_t *handle, struct buffer_head *bh)
1216{ 1236{
@@ -1221,26 +1241,20 @@ static int write_end_fn(handle_t *handle, struct buffer_head *bh)
1221} 1241}
1222 1242
1223/* 1243/*
1224 * Generic write_end handler for ordered and writeback ext3 journal modes. 1244 * This is nasty and subtle: ext3_write_begin() could have allocated blocks
1225 * We can't use generic_write_end, because that unlocks the page and we need to 1245 * for the whole page but later we failed to copy the data in. Update inode
1226 * unlock the page after ext3_journal_stop, but ext3_journal_stop must run 1246 * size according to what we managed to copy. The rest is going to be
1227 * after block_write_end. 1247 * truncated in write_end function.
1228 */ 1248 */
1229static int ext3_generic_write_end(struct file *file, 1249static void update_file_sizes(struct inode *inode, loff_t pos, unsigned copied)
1230 struct address_space *mapping,
1231 loff_t pos, unsigned len, unsigned copied,
1232 struct page *page, void *fsdata)
1233{ 1250{
1234 struct inode *inode = file->f_mapping->host; 1251 /* What matters to us is i_disksize. We don't write i_size anywhere */
1235 1252 if (pos + copied > inode->i_size)
1236 copied = block_write_end(file, mapping, pos, len, copied, page, fsdata); 1253 i_size_write(inode, pos + copied);
1237 1254 if (pos + copied > EXT3_I(inode)->i_disksize) {
1238 if (pos+copied > inode->i_size) { 1255 EXT3_I(inode)->i_disksize = pos + copied;
1239 i_size_write(inode, pos+copied);
1240 mark_inode_dirty(inode); 1256 mark_inode_dirty(inode);
1241 } 1257 }
1242
1243 return copied;
1244} 1258}
1245 1259
1246/* 1260/*
@@ -1260,35 +1274,29 @@ static int ext3_ordered_write_end(struct file *file,
1260 unsigned from, to; 1274 unsigned from, to;
1261 int ret = 0, ret2; 1275 int ret = 0, ret2;
1262 1276
1263 from = pos & (PAGE_CACHE_SIZE - 1); 1277 copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
1264 to = from + len;
1265 1278
1279 from = pos & (PAGE_CACHE_SIZE - 1);
1280 to = from + copied;
1266 ret = walk_page_buffers(handle, page_buffers(page), 1281 ret = walk_page_buffers(handle, page_buffers(page),
1267 from, to, NULL, ext3_journal_dirty_data); 1282 from, to, NULL, journal_dirty_data_fn);
1268 1283
1269 if (ret == 0) { 1284 if (ret == 0)
1270 /* 1285 update_file_sizes(inode, pos, copied);
1271 * generic_write_end() will run mark_inode_dirty() if i_size 1286 /*
1272 * changes. So let's piggyback the i_disksize mark_inode_dirty 1287 * There may be allocated blocks outside of i_size because
1273 * into that. 1288 * we failed to copy some data. Prepare for truncate.
1274 */ 1289 */
1275 loff_t new_i_size; 1290 if (pos + len > inode->i_size)
1276 1291 ext3_orphan_add(handle, inode);
1277 new_i_size = pos + copied;
1278 if (new_i_size > EXT3_I(inode)->i_disksize)
1279 EXT3_I(inode)->i_disksize = new_i_size;
1280 ret2 = ext3_generic_write_end(file, mapping, pos, len, copied,
1281 page, fsdata);
1282 copied = ret2;
1283 if (ret2 < 0)
1284 ret = ret2;
1285 }
1286 ret2 = ext3_journal_stop(handle); 1292 ret2 = ext3_journal_stop(handle);
1287 if (!ret) 1293 if (!ret)
1288 ret = ret2; 1294 ret = ret2;
1289 unlock_page(page); 1295 unlock_page(page);
1290 page_cache_release(page); 1296 page_cache_release(page);
1291 1297
1298 if (pos + len > inode->i_size)
1299 vmtruncate(inode, inode->i_size);
1292 return ret ? ret : copied; 1300 return ret ? ret : copied;
1293} 1301}
1294 1302
@@ -1299,25 +1307,22 @@ static int ext3_writeback_write_end(struct file *file,
1299{ 1307{
1300 handle_t *handle = ext3_journal_current_handle(); 1308 handle_t *handle = ext3_journal_current_handle();
1301 struct inode *inode = file->f_mapping->host; 1309 struct inode *inode = file->f_mapping->host;
1302 int ret = 0, ret2; 1310 int ret;
1303 loff_t new_i_size;
1304
1305 new_i_size = pos + copied;
1306 if (new_i_size > EXT3_I(inode)->i_disksize)
1307 EXT3_I(inode)->i_disksize = new_i_size;
1308
1309 ret2 = ext3_generic_write_end(file, mapping, pos, len, copied,
1310 page, fsdata);
1311 copied = ret2;
1312 if (ret2 < 0)
1313 ret = ret2;
1314 1311
1315 ret2 = ext3_journal_stop(handle); 1312 copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
1316 if (!ret) 1313 update_file_sizes(inode, pos, copied);
1317 ret = ret2; 1314 /*
1315 * There may be allocated blocks outside of i_size because
1316 * we failed to copy some data. Prepare for truncate.
1317 */
1318 if (pos + len > inode->i_size)
1319 ext3_orphan_add(handle, inode);
1320 ret = ext3_journal_stop(handle);
1318 unlock_page(page); 1321 unlock_page(page);
1319 page_cache_release(page); 1322 page_cache_release(page);
1320 1323
1324 if (pos + len > inode->i_size)
1325 vmtruncate(inode, inode->i_size);
1321 return ret ? ret : copied; 1326 return ret ? ret : copied;
1322} 1327}
1323 1328
@@ -1338,15 +1343,23 @@ static int ext3_journalled_write_end(struct file *file,
1338 if (copied < len) { 1343 if (copied < len) {
1339 if (!PageUptodate(page)) 1344 if (!PageUptodate(page))
1340 copied = 0; 1345 copied = 0;
1341 page_zero_new_buffers(page, from+copied, to); 1346 page_zero_new_buffers(page, from + copied, to);
1347 to = from + copied;
1342 } 1348 }
1343 1349
1344 ret = walk_page_buffers(handle, page_buffers(page), from, 1350 ret = walk_page_buffers(handle, page_buffers(page), from,
1345 to, &partial, write_end_fn); 1351 to, &partial, write_end_fn);
1346 if (!partial) 1352 if (!partial)
1347 SetPageUptodate(page); 1353 SetPageUptodate(page);
1348 if (pos+copied > inode->i_size) 1354
1349 i_size_write(inode, pos+copied); 1355 if (pos + copied > inode->i_size)
1356 i_size_write(inode, pos + copied);
1357 /*
1358 * There may be allocated blocks outside of i_size because
1359 * we failed to copy some data. Prepare for truncate.
1360 */
1361 if (pos + len > inode->i_size)
1362 ext3_orphan_add(handle, inode);
1350 EXT3_I(inode)->i_state |= EXT3_STATE_JDATA; 1363 EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
1351 if (inode->i_size > EXT3_I(inode)->i_disksize) { 1364 if (inode->i_size > EXT3_I(inode)->i_disksize) {
1352 EXT3_I(inode)->i_disksize = inode->i_size; 1365 EXT3_I(inode)->i_disksize = inode->i_size;
@@ -1361,6 +1374,8 @@ static int ext3_journalled_write_end(struct file *file,
1361 unlock_page(page); 1374 unlock_page(page);
1362 page_cache_release(page); 1375 page_cache_release(page);
1363 1376
1377 if (pos + len > inode->i_size)
1378 vmtruncate(inode, inode->i_size);
1364 return ret ? ret : copied; 1379 return ret ? ret : copied;
1365} 1380}
1366 1381
@@ -1428,17 +1443,11 @@ static int bput_one(handle_t *handle, struct buffer_head *bh)
1428 return 0; 1443 return 0;
1429} 1444}
1430 1445
1431static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh)
1432{
1433 if (buffer_mapped(bh))
1434 return ext3_journal_dirty_data(handle, bh);
1435 return 0;
1436}
1437
1438static int buffer_unmapped(handle_t *handle, struct buffer_head *bh) 1446static int buffer_unmapped(handle_t *handle, struct buffer_head *bh)
1439{ 1447{
1440 return !buffer_mapped(bh); 1448 return !buffer_mapped(bh);
1441} 1449}
1450
1442/* 1451/*
1443 * Note that we always start a transaction even if we're not journalling 1452 * Note that we always start a transaction even if we're not journalling
1444 * data. This is to preserve ordering: any hole instantiation within 1453 * data. This is to preserve ordering: any hole instantiation within
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 5e86ce9a86e0..88974814783a 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -15,12 +15,11 @@
15#include <linux/mount.h> 15#include <linux/mount.h>
16#include <linux/time.h> 16#include <linux/time.h>
17#include <linux/compat.h> 17#include <linux/compat.h>
18#include <linux/smp_lock.h>
19#include <asm/uaccess.h> 18#include <asm/uaccess.h>
20 19
21int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, 20long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
22 unsigned long arg)
23{ 21{
22 struct inode *inode = filp->f_dentry->d_inode;
24 struct ext3_inode_info *ei = EXT3_I(inode); 23 struct ext3_inode_info *ei = EXT3_I(inode);
25 unsigned int flags; 24 unsigned int flags;
26 unsigned short rsv_window_size; 25 unsigned short rsv_window_size;
@@ -39,29 +38,25 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
39 unsigned int oldflags; 38 unsigned int oldflags;
40 unsigned int jflag; 39 unsigned int jflag;
41 40
41 if (!is_owner_or_cap(inode))
42 return -EACCES;
43
44 if (get_user(flags, (int __user *) arg))
45 return -EFAULT;
46
42 err = mnt_want_write(filp->f_path.mnt); 47 err = mnt_want_write(filp->f_path.mnt);
43 if (err) 48 if (err)
44 return err; 49 return err;
45 50
46 if (!is_owner_or_cap(inode)) {
47 err = -EACCES;
48 goto flags_out;
49 }
50
51 if (get_user(flags, (int __user *) arg)) {
52 err = -EFAULT;
53 goto flags_out;
54 }
55
56 flags = ext3_mask_flags(inode->i_mode, flags); 51 flags = ext3_mask_flags(inode->i_mode, flags);
57 52
58 mutex_lock(&inode->i_mutex); 53 mutex_lock(&inode->i_mutex);
54
59 /* Is it quota file? Do not allow user to mess with it */ 55 /* Is it quota file? Do not allow user to mess with it */
60 if (IS_NOQUOTA(inode)) { 56 err = -EPERM;
61 mutex_unlock(&inode->i_mutex); 57 if (IS_NOQUOTA(inode))
62 err = -EPERM;
63 goto flags_out; 58 goto flags_out;
64 } 59
65 oldflags = ei->i_flags; 60 oldflags = ei->i_flags;
66 61
67 /* The JOURNAL_DATA flag is modifiable only by root */ 62 /* The JOURNAL_DATA flag is modifiable only by root */
@@ -74,11 +69,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
74 * This test looks nicer. Thanks to Pauline Middelink 69 * This test looks nicer. Thanks to Pauline Middelink
75 */ 70 */
76 if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) { 71 if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
77 if (!capable(CAP_LINUX_IMMUTABLE)) { 72 if (!capable(CAP_LINUX_IMMUTABLE))
78 mutex_unlock(&inode->i_mutex);
79 err = -EPERM;
80 goto flags_out; 73 goto flags_out;
81 }
82 } 74 }
83 75
84 /* 76 /*
@@ -86,17 +78,12 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
86 * the relevant capability. 78 * the relevant capability.
87 */ 79 */
88 if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) { 80 if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
89 if (!capable(CAP_SYS_RESOURCE)) { 81 if (!capable(CAP_SYS_RESOURCE))
90 mutex_unlock(&inode->i_mutex);
91 err = -EPERM;
92 goto flags_out; 82 goto flags_out;
93 }
94 } 83 }
95 84
96
97 handle = ext3_journal_start(inode, 1); 85 handle = ext3_journal_start(inode, 1);
98 if (IS_ERR(handle)) { 86 if (IS_ERR(handle)) {
99 mutex_unlock(&inode->i_mutex);
100 err = PTR_ERR(handle); 87 err = PTR_ERR(handle);
101 goto flags_out; 88 goto flags_out;
102 } 89 }
@@ -116,15 +103,13 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
116 err = ext3_mark_iloc_dirty(handle, inode, &iloc); 103 err = ext3_mark_iloc_dirty(handle, inode, &iloc);
117flags_err: 104flags_err:
118 ext3_journal_stop(handle); 105 ext3_journal_stop(handle);
119 if (err) { 106 if (err)
120 mutex_unlock(&inode->i_mutex); 107 goto flags_out;
121 return err;
122 }
123 108
124 if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) 109 if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
125 err = ext3_change_inode_journal_flag(inode, jflag); 110 err = ext3_change_inode_journal_flag(inode, jflag);
126 mutex_unlock(&inode->i_mutex);
127flags_out: 111flags_out:
112 mutex_unlock(&inode->i_mutex);
128 mnt_drop_write(filp->f_path.mnt); 113 mnt_drop_write(filp->f_path.mnt);
129 return err; 114 return err;
130 } 115 }
@@ -140,6 +125,7 @@ flags_out:
140 125
141 if (!is_owner_or_cap(inode)) 126 if (!is_owner_or_cap(inode))
142 return -EPERM; 127 return -EPERM;
128
143 err = mnt_want_write(filp->f_path.mnt); 129 err = mnt_want_write(filp->f_path.mnt);
144 if (err) 130 if (err)
145 return err; 131 return err;
@@ -147,6 +133,7 @@ flags_out:
147 err = -EFAULT; 133 err = -EFAULT;
148 goto setversion_out; 134 goto setversion_out;
149 } 135 }
136
150 handle = ext3_journal_start(inode, 1); 137 handle = ext3_journal_start(inode, 1);
151 if (IS_ERR(handle)) { 138 if (IS_ERR(handle)) {
152 err = PTR_ERR(handle); 139 err = PTR_ERR(handle);
@@ -299,9 +286,6 @@ group_add_out:
299#ifdef CONFIG_COMPAT 286#ifdef CONFIG_COMPAT
300long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 287long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
301{ 288{
302 struct inode *inode = file->f_path.dentry->d_inode;
303 int ret;
304
305 /* These are just misnamed, they actually get/put from/to user an int */ 289 /* These are just misnamed, they actually get/put from/to user an int */
306 switch (cmd) { 290 switch (cmd) {
307 case EXT3_IOC32_GETFLAGS: 291 case EXT3_IOC32_GETFLAGS:
@@ -341,9 +325,6 @@ long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
341 default: 325 default:
342 return -ENOIOCTLCMD; 326 return -ENOIOCTLCMD;
343 } 327 }
344 lock_kernel(); 328 return ext3_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
345 ret = ext3_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
346 unlock_kernel();
347 return ret;
348} 329}
349#endif 330#endif
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index e2fc63cbba8b..6ddaa0a42b24 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -161,12 +161,12 @@ static struct dx_frame *dx_probe(struct qstr *entry,
161 struct dx_frame *frame, 161 struct dx_frame *frame,
162 int *err); 162 int *err);
163static void dx_release (struct dx_frame *frames); 163static void dx_release (struct dx_frame *frames);
164static int dx_make_map (struct ext3_dir_entry_2 *de, int size, 164static int dx_make_map(struct ext3_dir_entry_2 *de, unsigned blocksize,
165 struct dx_hash_info *hinfo, struct dx_map_entry map[]); 165 struct dx_hash_info *hinfo, struct dx_map_entry map[]);
166static void dx_sort_map(struct dx_map_entry *map, unsigned count); 166static void dx_sort_map(struct dx_map_entry *map, unsigned count);
167static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to, 167static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to,
168 struct dx_map_entry *offsets, int count); 168 struct dx_map_entry *offsets, int count);
169static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size); 169static struct ext3_dir_entry_2 *dx_pack_dirents(char *base, unsigned blocksize);
170static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); 170static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
171static int ext3_htree_next_block(struct inode *dir, __u32 hash, 171static int ext3_htree_next_block(struct inode *dir, __u32 hash,
172 struct dx_frame *frame, 172 struct dx_frame *frame,
@@ -708,14 +708,14 @@ errout:
708 * Create map of hash values, offsets, and sizes, stored at end of block. 708 * Create map of hash values, offsets, and sizes, stored at end of block.
709 * Returns number of entries mapped. 709 * Returns number of entries mapped.
710 */ 710 */
711static int dx_make_map (struct ext3_dir_entry_2 *de, int size, 711static int dx_make_map(struct ext3_dir_entry_2 *de, unsigned blocksize,
712 struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) 712 struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
713{ 713{
714 int count = 0; 714 int count = 0;
715 char *base = (char *) de; 715 char *base = (char *) de;
716 struct dx_hash_info h = *hinfo; 716 struct dx_hash_info h = *hinfo;
717 717
718 while ((char *) de < base + size) 718 while ((char *) de < base + blocksize)
719 { 719 {
720 if (de->name_len && de->inode) { 720 if (de->name_len && de->inode) {
721 ext3fs_dirhash(de->name, de->name_len, &h); 721 ext3fs_dirhash(de->name, de->name_len, &h);
@@ -1047,8 +1047,16 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
1047 return ERR_PTR(-EIO); 1047 return ERR_PTR(-EIO);
1048 } 1048 }
1049 inode = ext3_iget(dir->i_sb, ino); 1049 inode = ext3_iget(dir->i_sb, ino);
1050 if (IS_ERR(inode)) 1050 if (unlikely(IS_ERR(inode))) {
1051 return ERR_CAST(inode); 1051 if (PTR_ERR(inode) == -ESTALE) {
1052 ext3_error(dir->i_sb, __func__,
1053 "deleted inode referenced: %lu",
1054 ino);
1055 return ERR_PTR(-EIO);
1056 } else {
1057 return ERR_CAST(inode);
1058 }
1059 }
1052 } 1060 }
1053 return d_splice_alias(inode, dentry); 1061 return d_splice_alias(inode, dentry);
1054} 1062}
@@ -1120,13 +1128,14 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
1120 * Compact each dir entry in the range to the minimal rec_len. 1128 * Compact each dir entry in the range to the minimal rec_len.
1121 * Returns pointer to last entry in range. 1129 * Returns pointer to last entry in range.
1122 */ 1130 */
1123static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) 1131static struct ext3_dir_entry_2 *dx_pack_dirents(char *base, unsigned blocksize)
1124{ 1132{
1125 struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base; 1133 struct ext3_dir_entry_2 *next, *to, *prev;
1134 struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *)base;
1126 unsigned rec_len = 0; 1135 unsigned rec_len = 0;
1127 1136
1128 prev = to = de; 1137 prev = to = de;
1129 while ((char*)de < base + size) { 1138 while ((char *)de < base + blocksize) {
1130 next = ext3_next_entry(de); 1139 next = ext3_next_entry(de);
1131 if (de->inode && de->name_len) { 1140 if (de->inode && de->name_len) {
1132 rec_len = EXT3_DIR_REC_LEN(de->name_len); 1141 rec_len = EXT3_DIR_REC_LEN(de->name_len);