aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/dir.c28
-rw-r--r--fs/ocfs2/dir.h7
-rw-r--r--fs/ocfs2/journal.c118
3 files changed, 70 insertions, 83 deletions
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index dbfa6f66291a..a75c340fc689 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -81,10 +81,10 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
81 struct ocfs2_alloc_context *meta_ac, 81 struct ocfs2_alloc_context *meta_ac,
82 struct buffer_head **new_bh); 82 struct buffer_head **new_bh);
83 83
84int ocfs2_check_dir_entry(struct inode * dir, 84static int ocfs2_check_dir_entry(struct inode * dir,
85 struct ocfs2_dir_entry * de, 85 struct ocfs2_dir_entry * de,
86 struct buffer_head * bh, 86 struct buffer_head * bh,
87 unsigned long offset) 87 unsigned long offset)
88{ 88{
89 const char *error_msg = NULL; 89 const char *error_msg = NULL;
90 const int rlen = le16_to_cpu(de->rec_len); 90 const int rlen = le16_to_cpu(de->rec_len);
@@ -532,6 +532,26 @@ out:
532} 532}
533 533
534/* 534/*
535 * This is intended to be called from inside other kernel functions,
536 * so we fake some arguments.
537 */
538int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv,
539 filldir_t filldir)
540{
541 int ret = 0;
542 unsigned long version = inode->i_version;
543
544 while (*f_pos < i_size_read(inode)) {
545 ret = ocfs2_dir_foreach_blk(inode, &version, f_pos, priv,
546 filldir);
547 if (ret)
548 break;
549 }
550
551 return 0;
552}
553
554/*
535 * ocfs2_readdir() 555 * ocfs2_readdir()
536 * 556 *
537 */ 557 */
diff --git a/fs/ocfs2/dir.h b/fs/ocfs2/dir.h
index 7bf9c0a01cdf..075d0e9fd459 100644
--- a/fs/ocfs2/dir.h
+++ b/fs/ocfs2/dir.h
@@ -62,6 +62,8 @@ int ocfs2_find_files_on_disk(const char *name,
62 struct buffer_head **dirent_bh, 62 struct buffer_head **dirent_bh,
63 struct ocfs2_dir_entry **dirent); 63 struct ocfs2_dir_entry **dirent);
64int ocfs2_readdir(struct file *filp, void *dirent, filldir_t filldir); 64int ocfs2_readdir(struct file *filp, void *dirent, filldir_t filldir);
65int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv,
66 filldir_t filldir);
65int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, 67int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
66 struct inode *dir, 68 struct inode *dir,
67 struct buffer_head *parent_fe_bh, 69 struct buffer_head *parent_fe_bh,
@@ -76,9 +78,4 @@ int ocfs2_fill_new_dir(struct ocfs2_super *osb,
76 struct buffer_head *fe_bh, 78 struct buffer_head *fe_bh,
77 struct ocfs2_alloc_context *data_ac); 79 struct ocfs2_alloc_context *data_ac);
78 80
79int ocfs2_check_dir_entry(struct inode *dir,
80 struct ocfs2_dir_entry *de,
81 struct buffer_head *bh,
82 unsigned long offset);
83
84#endif /* OCFS2_DIR_H */ 81#endif /* OCFS2_DIR_H */
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 8bbfc80e5c5c..f9d01e25298d 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -1213,17 +1213,49 @@ bail:
1213 return status; 1213 return status;
1214} 1214}
1215 1215
1216struct ocfs2_orphan_filldir_priv {
1217 struct inode *head;
1218 struct ocfs2_super *osb;
1219};
1220
1221static int ocfs2_orphan_filldir(void *priv, const char *name, int name_len,
1222 loff_t pos, u64 ino, unsigned type)
1223{
1224 struct ocfs2_orphan_filldir_priv *p = priv;
1225 struct inode *iter;
1226
1227 if (name_len == 1 && !strncmp(".", name, 1))
1228 return 0;
1229 if (name_len == 2 && !strncmp("..", name, 2))
1230 return 0;
1231
1232 /* Skip bad inodes so that recovery can continue */
1233 iter = ocfs2_iget(p->osb, ino,
1234 OCFS2_FI_FLAG_ORPHAN_RECOVERY);
1235 if (IS_ERR(iter))
1236 return 0;
1237
1238 mlog(0, "queue orphan %llu\n",
1239 (unsigned long long)OCFS2_I(iter)->ip_blkno);
1240 /* No locking is required for the next_orphan queue as there
1241 * is only ever a single process doing orphan recovery. */
1242 OCFS2_I(iter)->ip_next_orphan = p->head;
1243 p->head = iter;
1244
1245 return 0;
1246}
1247
1216static int ocfs2_queue_orphans(struct ocfs2_super *osb, 1248static int ocfs2_queue_orphans(struct ocfs2_super *osb,
1217 int slot, 1249 int slot,
1218 struct inode **head) 1250 struct inode **head)
1219{ 1251{
1220 int status; 1252 int status;
1221 struct inode *orphan_dir_inode = NULL; 1253 struct inode *orphan_dir_inode = NULL;
1222 struct inode *iter; 1254 struct ocfs2_orphan_filldir_priv priv;
1223 unsigned long offset, blk, local; 1255 loff_t pos = 0;
1224 struct buffer_head *bh = NULL; 1256
1225 struct ocfs2_dir_entry *de; 1257 priv.osb = osb;
1226 struct super_block *sb = osb->sb; 1258 priv.head = *head;
1227 1259
1228 orphan_dir_inode = ocfs2_get_system_file_inode(osb, 1260 orphan_dir_inode = ocfs2_get_system_file_inode(osb,
1229 ORPHAN_DIR_SYSTEM_INODE, 1261 ORPHAN_DIR_SYSTEM_INODE,
@@ -1241,77 +1273,15 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
1241 goto out; 1273 goto out;
1242 } 1274 }
1243 1275
1244 offset = 0; 1276 status = ocfs2_dir_foreach(orphan_dir_inode, &pos, &priv,
1245 iter = NULL; 1277 ocfs2_orphan_filldir);
1246 while(offset < i_size_read(orphan_dir_inode)) { 1278 if (status) {
1247 blk = offset >> sb->s_blocksize_bits; 1279 mlog_errno(status);
1248 1280 goto out;
1249 bh = ocfs2_bread(orphan_dir_inode, blk, &status, 0);
1250 if (!bh)
1251 status = -EINVAL;
1252 if (status < 0) {
1253 if (bh)
1254 brelse(bh);
1255 mlog_errno(status);
1256 goto out_unlock;
1257 }
1258
1259 local = 0;
1260 while(offset < i_size_read(orphan_dir_inode)
1261 && local < sb->s_blocksize) {
1262 de = (struct ocfs2_dir_entry *) (bh->b_data + local);
1263
1264 if (!ocfs2_check_dir_entry(orphan_dir_inode,
1265 de, bh, local)) {
1266 status = -EINVAL;
1267 mlog_errno(status);
1268 brelse(bh);
1269 goto out_unlock;
1270 }
1271
1272 local += le16_to_cpu(de->rec_len);
1273 offset += le16_to_cpu(de->rec_len);
1274
1275 /* I guess we silently fail on no inode? */
1276 if (!le64_to_cpu(de->inode))
1277 continue;
1278 if (de->file_type > OCFS2_FT_MAX) {
1279 mlog(ML_ERROR,
1280 "block %llu contains invalid de: "
1281 "inode = %llu, rec_len = %u, "
1282 "name_len = %u, file_type = %u, "
1283 "name='%.*s'\n",
1284 (unsigned long long)bh->b_blocknr,
1285 (unsigned long long)le64_to_cpu(de->inode),
1286 le16_to_cpu(de->rec_len),
1287 de->name_len,
1288 de->file_type,
1289 de->name_len,
1290 de->name);
1291 continue;
1292 }
1293 if (de->name_len == 1 && !strncmp(".", de->name, 1))
1294 continue;
1295 if (de->name_len == 2 && !strncmp("..", de->name, 2))
1296 continue;
1297
1298 iter = ocfs2_iget(osb, le64_to_cpu(de->inode),
1299 OCFS2_FI_FLAG_ORPHAN_RECOVERY);
1300 if (IS_ERR(iter))
1301 continue;
1302
1303 mlog(0, "queue orphan %llu\n",
1304 (unsigned long long)OCFS2_I(iter)->ip_blkno);
1305 /* No locking is required for the next_orphan
1306 * queue as there is only ever a single
1307 * process doing orphan recovery. */
1308 OCFS2_I(iter)->ip_next_orphan = *head;
1309 *head = iter;
1310 }
1311 brelse(bh);
1312 } 1281 }
1313 1282
1314out_unlock: 1283 *head = priv.head;
1284
1315 ocfs2_meta_unlock(orphan_dir_inode, 0); 1285 ocfs2_meta_unlock(orphan_dir_inode, 0);
1316out: 1286out:
1317 mutex_unlock(&orphan_dir_inode->i_mutex); 1287 mutex_unlock(&orphan_dir_inode->i_mutex);