1 /* -*- mode: c; c-basic-offset: 8; -*-
2 * vim:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
19 * Copyright (c) 2004 Hewlett-Packard Co.
21 /*****************************************************************************
22 * e2fsck extentions: code for gathering data from the ost & mds filesystems
23 * when e2fsck is run against them. The best description and knowledge of the
24 * layout and information gathered is in lfsck.h where the structures
25 * defining each entry in the tables are declared. Basically the ost file
26 * contains one table with each entry holding the object id and size.
27 * In addition there is header information at the start of the file.
28 * The mds file contains multiple tables one per ost. Each mds/ost table
29 * contains an entry describing the mds fid and the ost object associated
30 * with this fid on an ost. In addition the mds also contains a table
31 * with the mds_fid and the fid of the containg directory. Header information
32 * for each table is also included.
33 * lfsck is run afterwards where the data gathered and stored here is cross
34 * checked to ensure consistency and correctness
36 *****************************************************************************/
43 #include "ext2fs/ext2_fs.h"
44 #include "ext2fs/ext2fs.h"
48 #include "ext2fs/lfsck.h"
52 #define VERBOSE(ctx, fmt, args...) \
53 do { if (ctx->options & E2F_OPT_VERBOSE) printf(fmt, ##args); } while (0)
55 #define DEBUG(ctx, fmt, args...) \
56 do { if (ctx->options & E2F_OPT_DEBUG) printf(fmt, ##args); } while (0)
58 struct lfsck_mds_ctx {
67 struct lfsck_ost_ctx {
76 int e2fsck_lfsck_cleanupdb(e2fsck_t ctx)
82 if (ctx->lfsck_oinfo == NULL)
85 for (i = 0; i < ctx->lfsck_oinfo->ost_count; i++) {
86 if (ctx->lfsck_oinfo->ofile_ctx[i].dbp != NULL) {
87 dbp = ctx->lfsck_oinfo->ofile_ctx[i].dbp;
88 rc += dbp->close(dbp, 0);
89 ctx->lfsck_oinfo->ofile_ctx[i].dbp = NULL;
92 if (ctx->lfsck_oinfo->mds_sizeinfo_dbp != NULL) {
93 dbp = ctx->lfsck_oinfo->mds_sizeinfo_dbp;
94 rc += dbp->close(dbp, 0);
95 ctx->lfsck_oinfo->mds_sizeinfo_dbp = NULL;
97 if (ctx->lfsck_oinfo->ofile_ctx)
98 ext2fs_free_mem(ctx->lfsck_oinfo->ofile_ctx);
99 ext2fs_free_mem(&ctx->lfsck_oinfo);
104 /* What is the last object id for the OST on the MDS */
105 int e2fsck_get_lov_objids(e2fsck_t ctx, struct lfsck_outdb_info *outdb)
107 ext2_filsys fs = ctx->fs;
110 __u64 *lov_objids = NULL;
115 block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3,
116 "block iterate buffer");
118 rc = ext2fs_lookup(fs, EXT2_ROOT_INO, LOV_OBJID,
119 strlen(LOV_OBJID), block_buf, &inode);
123 lov_objids = e2fsck_allocate_memory(ctx,
124 sizeof(*lov_objids) * LOV_MAX_OSTS,
126 if (lov_objids == NULL) {
131 rc = ext2fs_file_open(fs, inode, 0, &e2_file);
135 rc = ext2fs_file_read(e2_file, lov_objids,
136 sizeof(*lov_objids) * LOV_MAX_OSTS, &got);
137 rc = ext2fs_file_close(e2_file);
139 outdb->ost_count = got / sizeof(*lov_objids);
140 for (i = 0; i < outdb->ost_count; i++) {
141 VERBOSE(ctx,"MDS: ost_idx %d max_id "LPU64"\n",i,lov_objids[i]);
142 outdb->ofile_ctx[i].max_id = lov_objids[i];
143 outdb->ofile_ctx[i].have_max_id = 1;
144 outdb->have_ost_count = 1;
148 ext2fs_free_mem(&block_buf);
150 ext2fs_free_mem(&lov_objids);
152 VERBOSE(ctx, "MDS: unable to read lov_objids: rc %d\n", rc);
154 VERBOSE(ctx, "MDS: got %d bytes = %d entries in lov_objids\n",
155 got, outdb->ost_count);
159 static int lfsck_write_mds_hdrinfo(e2fsck_t ctx, struct lfsck_outdb_info *outdb)
161 struct lfsck_mds_hdr mds_hdr;
162 ext2_filsys fs = ctx->fs;
164 DB *mds_hdrdb = NULL;
169 mds_hdrname = e2fsck_allocate_memory(ctx, PATH_MAX,
171 sprintf(mds_hdrname, "%s.mdshdr", ctx->lustre_mdsdb);
173 if (unlink(mds_hdrname)) {
174 if (errno != ENOENT) {
175 fprintf(stderr, "Failure to remove old db file %s\n",
177 ctx->flags |= E2F_FLAG_ABORT;
182 rc = lfsck_opendb(mds_hdrname, MDS_HDR, &mds_hdrdb, 0, 0, 0);
184 fprintf(stderr, "failure to open database for mdsdhr "
185 "info%s: %s\n", MDS_HDR, db_strerror(rc));
186 ctx->flags |= E2F_FLAG_ABORT;
187 ext2fs_free_mem(&mds_hdrname);
191 /* read in e2fsck_lfsck_save_ea() already if we opened read/write */
192 if (ctx->lfsck_oinfo->ost_count == 0)
193 e2fsck_get_lov_objids(ctx, ctx->lfsck_oinfo);
195 memset(&mds_hdr, 0, sizeof(mds_hdr));
196 mds_hdr.mds_magic = MDS_MAGIC;
197 mds_hdr.mds_flags = ctx->options & E2F_OPT_READONLY;
198 mds_hdr.mds_max_files = fs->super->s_inodes_count -
199 fs->super->s_free_inodes_count;
200 VERBOSE(ctx, "MDS: max_files = "LPU64"\n", mds_hdr.mds_max_files);
201 mds_hdr.mds_num_osts = ctx->lfsck_oinfo->ost_count;
202 VERBOSE(ctx, "MDS: num_osts = %u\n", mds_hdr.mds_num_osts);
203 for (i = 0; i < mds_hdr.mds_num_osts; i++) {
204 mds_hdr.mds_max_ost_id[i] =
205 ctx->lfsck_oinfo->ofile_ctx[i].max_id;
208 memset(&key, 0, sizeof(key));
209 memset(&data, 0, sizeof(data));
210 key.data = &mds_hdr.mds_magic;
211 key.size = sizeof(mds_hdr.mds_magic);
212 cputole_mds_hdr(&mds_hdr);
213 data.data = &mds_hdr;
214 data.size = sizeof(mds_hdr);
215 rc = mds_hdrdb->put(mds_hdrdb, NULL, &key, &data, 0);
217 fprintf(stderr, "error: db put %s: %s\n", MDS_HDR,
219 ctx->flags |= E2F_FLAG_ABORT;
224 mds_hdrdb->close(mds_hdrdb, 0);
225 ext2fs_free_mem(&mds_hdrname);
227 printf("mds info db file written \n");
234 int e2fsck_lfsck_save_ea(e2fsck_t ctx, ext2_ino_t ino, __u32 generation,
235 struct lov_user_md *lmm, struct lustre_mdt_attrs *lma)
237 ext2_filsys fs = ctx->fs;
238 #ifdef LFSCK_CHECK_SIZE
239 struct lfsck_mds_szinfo szinfo;
240 #endif /* LFSCK_CHECK_SIZE */
241 struct lov_user_ost_data_v1 *loi;
245 __u32 numfiles = fs->super->s_inodes_count -
246 fs->super->s_free_inodes_count;
248 if (!ctx->lfsck_oinfo) {
249 /* remove old db file */
250 if (unlink(ctx->lustre_mdsdb)) {
253 fprintf(stderr,"Error removing old db %s: %s\n",
254 ctx->lustre_mdsdb, strerror(rc));
255 ctx->flags |= E2F_FLAG_ABORT;
260 rc = ext2fs_get_mem(sizeof(struct lfsck_outdb_info),
263 ctx->lfsck_oinfo = NULL;
264 ctx->flags |= E2F_FLAG_ABORT;
267 memset(ctx->lfsck_oinfo, 0, sizeof(struct lfsck_outdb_info));
268 rc = ext2fs_get_mem(sizeof(struct lfsck_ofile_ctx)*LOV_MAX_OSTS,
269 &ctx->lfsck_oinfo->ofile_ctx);
271 ext2fs_free_mem(&ctx->lfsck_oinfo);
272 ctx->flags |= E2F_FLAG_ABORT;
275 memset(ctx->lfsck_oinfo->ofile_ctx, 0,
276 sizeof(struct lfsck_ofile_ctx) * LOV_MAX_OSTS);
277 #ifdef LFSCK_CHECK_SIZE
278 if (lfsck_opendb(ctx->lustre_mdsdb, MDS_SIZEINFO,
279 &ctx->lfsck_oinfo->mds_sizeinfo_dbp, 0,
280 sizeof(szinfo.mds_fid) + sizeof(szinfo),
282 fprintf(stderr, "Failed to open db file %s\n",
284 ctx->flags |= E2F_FLAG_ABORT;
287 #endif /* LFSCK_CHECK_SIZE */
289 if (ctx->options & E2F_OPT_READONLY) {
290 e2fsck_get_lov_objids(ctx, ctx->lfsck_oinfo);
291 lfsck_write_mds_hdrinfo(ctx, ctx->lfsck_oinfo);
294 if (lmm->lmm_magic == LOV_USER_MAGIC_V3)
295 loi = ((struct lov_user_md_v3 *)lmm)->lmm_objects;
296 else /* if (lmm->lmm_magic == LOV_USER_MAGIC_V1) */
297 loi = lmm->lmm_objects;
299 #ifdef LFSCK_CHECK_SIZE
300 /* XXX: We don't save the layout type here. This doesn't matter for
301 * now, we don't really need the pool information for lfsck, but
302 * in the future we may need it for RAID-1 and other layouts. */
303 memset(&szinfo, 0, sizeof(szinfo));
304 szinfo.mds_fid = ino;
305 szinfo.mds_seq = lmm->lmm_object_seq;
306 szinfo.mds_stripe_size = lmm->lmm_stripe_size;
307 szinfo.mds_stripe_start = loi->l_ost_idx;
308 szinfo.mds_calc_size = 0;
309 szinfo.mds_stripe_pattern = lmm->lmm_pattern;
311 memset(&key, 0, sizeof(key));
312 memset(&data, 0, sizeof(data));
313 key.data = &szinfo.mds_fid;
314 key.size = sizeof(szinfo.mds_fid);
315 cputole_mds_szinfo(&szinfo);
317 data.size = sizeof(szinfo);
318 dbp = ctx->lfsck_oinfo->mds_sizeinfo_dbp;
320 rc = dbp->put(dbp, NULL, &key, &data, 0);
322 dbp->err(ctx->lfsck_oinfo->mds_sizeinfo_dbp, rc,
324 e2fsck_lfsck_cleanupdb(ctx);
325 ctx->flags |= E2F_FLAG_ABORT;
329 #endif /* LFSCK_CHECK_SIZE */
330 for (i = 0; i < lmm->lmm_stripe_count; i++, loi++) {
331 int ost_idx = loi->l_ost_idx;
332 struct lfsck_mds_objent mds_ent;
333 struct lfsck_ofile_ctx *ofile_ctx =
334 &ctx->lfsck_oinfo->ofile_ctx[ost_idx];
336 if (ost_idx >= LOV_MAX_OSTS) {
337 fprintf(stderr, "invalid OST index %u ino %u[%d]\n",
342 if (ost_idx + 1 > ctx->lfsck_oinfo->ost_count) {
343 if (ctx->lfsck_oinfo->have_ost_count) {
344 fprintf(stderr, "bad OST index %u ino %u[%d]\n",
348 ctx->lfsck_oinfo->ost_count = ost_idx + 1;
351 if (ofile_ctx->dbp == NULL) {
354 sprintf(dbname, "%s.%d", MDS_OSTDB, ost_idx);
355 rc = lfsck_opendb(ctx->lustre_mdsdb, dbname,
357 sizeof(mds_ent), numfiles);
359 e2fsck_lfsck_cleanupdb(ctx);
360 ctx->flags |= E2F_FLAG_ABORT;
365 memset(&mds_ent, 0, sizeof(mds_ent));
367 mds_ent.mds_fid = lma->lma_self_fid;
369 mds_ent.mds_fid.f_seq = ino;
370 mds_ent.mds_fid.f_oid = generation;
371 mds_ent.mds_fid.f_ver = 0;
373 mds_ent.mds_oi = *(struct ost_id *)&loi->l_object_id;
374 mds_ent.mds_ostidx = ost_idx;
375 mds_ent.mds_ostoffset = i;
377 if (mds_ent.mds_oi.oi_id > ofile_ctx->max_id) {
378 if (ofile_ctx->have_max_id) {
380 "[%d] skip obj "LPU64" > max "LPU64"\n",
381 ost_idx, mds_ent.mds_oi.oi_id,
385 ofile_ctx->max_id = mds_ent.mds_oi.oi_id;
388 memset(&key, 0, sizeof(key));
389 memset(&data, 0, sizeof(data));
390 key.data = &mds_ent.mds_oi;
391 key.size = sizeof(mds_ent.mds_oi);
392 cputole_mds_objent(&mds_ent);
393 data.data = &mds_ent;
394 data.size = sizeof(mds_ent);
395 dbp = ofile_ctx->dbp;
397 DEBUG(ctx, "OST[%u]: inode FID "DFID" oi "DOIF"\n", ost_idx,
398 PFID(&mds_ent.mds_fid), POIF(&mds_ent.mds_oi));
400 rc = dbp->put(dbp, NULL, &key, &data, 0);
402 dbp->err(dbp, rc, "db->put failed\n");
403 e2fsck_lfsck_cleanupdb(ctx);
404 ctx->flags |= E2F_FLAG_ABORT;
405 /* XXX - Free lctx memory */
412 static int lfsck_check_lov_ea(e2fsck_t ctx, struct lov_user_md *lmm)
414 if (lmm->lmm_magic != LOV_USER_MAGIC_V1 &&
415 lmm->lmm_magic != LOV_USER_MAGIC_V3) {
416 VERBOSE(ctx, "error: only handle v1/v3 LOV EAs, not %08x\n",
424 static int lfsck_check_lma_ea(e2fsck_t ctx, struct lustre_mdt_attrs *lma)
430 * e2fsck pass1 has found a file with an EA let's save the information in
431 * the correct table(s). This is only called for an MDS search.
433 int e2fsck_lfsck_find_ea(e2fsck_t ctx, struct ext2_inode_large *inode,
434 struct ext2_ext_attr_entry *entry, void *value,
435 struct lov_user_md **lmm,
436 struct lustre_mdt_attrs **lma)
443 /* This ensures that we don't open the file here if traversing an OST */
444 if ((ctx->lustre_devtype & LUSTRE_TYPE) != LUSTRE_MDS)
447 if (!LINUX_S_ISREG(inode->i_mode))
450 if (entry->e_name_len == 0)
453 if (entry->e_name_index == EXT3_XATTR_INDEX_TRUSTED &&
454 entry->e_name_index == EXT3_XATTR_INDEX_LUSTRE)
457 ea = e2fsck_allocate_memory(ctx, entry->e_value_size, "EA");
459 if (entry->e_value_inum != 0) {
460 /* EA in external inode */
461 retval = ext2fs_file_open(ctx->fs, entry->e_value_inum,
464 retval = ext2fs_file_read(file, ea,
465 entry->e_value_size, &got);
466 ext2fs_file_close(file);
468 ext2fs_free_mem(&ea);
472 ext2fs_free_mem(&ea);
476 memcpy(ea, value, entry->e_value_size);
479 if (entry->e_name_len == strlen(XATTR_LUSTRE_MDS_LOV_EA) &&
480 strncmp(entry->e_name, XATTR_LUSTRE_MDS_LOV_EA,
481 entry->e_name_len) == 0) {
483 ext2fs_free_mem(&ea);
487 letocpu_lov_user_md(*lmm);
489 if (lfsck_check_lov_ea(ctx, *lmm)) {
491 ctx->flags |= E2F_FLAG_ABORT;
492 ext2fs_free_mem(&ea);
495 } else if (entry->e_name_len == strlen(XATTR_LUSTRE_MDT_LMA_EA) &&
496 strncmp(entry->e_name, XATTR_LUSTRE_MDT_LMA_EA,
497 entry->e_name_len) == 0) {
499 ext2fs_free_mem(&ea);
503 if (lfsck_check_lma_ea(ctx, *lma)) {
505 ctx->flags |= E2F_FLAG_ABORT;
506 ext2fs_free_mem(&ea);
510 ext2fs_free_mem(&ea);
516 /* make sure that the mds data is on file */
517 int e2fsck_lfsck_flush_ea(e2fsck_t ctx)
522 if ((ctx->lustre_devtype & LUSTRE_TYPE) != LUSTRE_MDS)
525 if (ctx->lfsck_oinfo == 0)
528 for (i = 0; i < ctx->lfsck_oinfo->ost_count; i++) {
529 if (ctx->lfsck_oinfo->ofile_ctx == NULL)
532 if (ctx->lfsck_oinfo->ofile_ctx[i].dbp != NULL) {
533 dbp = ctx->lfsck_oinfo->ofile_ctx[i].dbp;
534 rc += dbp->close(dbp, 0);
535 ctx->lfsck_oinfo->ofile_ctx[i].dbp = NULL;
538 if (ctx->lfsck_oinfo->mds_sizeinfo_dbp != NULL) {
539 dbp = ctx->lfsck_oinfo->mds_sizeinfo_dbp;
540 rc += dbp->close(dbp, 0);
541 ctx->lfsck_oinfo->mds_sizeinfo_dbp = NULL;
545 ctx->flags |= E2F_FLAG_ABORT;
550 /* From debugfs.c for file removal */
551 static int lfsck_release_blocks_proc(ext2_filsys fs, blk_t *blocknr,
552 int blockcnt, void *private)
557 ext2fs_block_alloc_stats(fs, block, -1);
561 static void lfsck_kill_file_by_inode(ext2_filsys fs, ext2_ino_t inode)
563 struct ext2_inode inode_buf;
565 if (ext2fs_read_inode(fs, inode, &inode_buf))
568 inode_buf.i_dtime = time(NULL);
569 if (ext2fs_write_inode(fs, inode, &inode_buf))
572 ext2fs_block_iterate(fs, inode, 0, NULL,
573 lfsck_release_blocks_proc, NULL);
574 ext2fs_inode_alloc_stats2(fs, inode, -1,
575 LINUX_S_ISDIR(inode_buf.i_mode));
579 * remove a file. Currently this removes the lov_objids file
580 * since otherwise the automatic deletion of precreated objects on
581 * mds/ost connection could potentially remove objects with
582 * data - this would be especially the case if the mds has being
583 * restored from backup
585 static int lfsck_rm_file(e2fsck_t ctx, ext2_ino_t dir, char *name)
587 ext2_filsys fs = ctx->fs;
589 struct ext2_inode inode;
592 rc = ext2fs_lookup(fs, dir, name, strlen(name),
597 if (ext2fs_read_inode(fs, ino, &inode))
600 --inode.i_links_count;
602 if (ext2fs_write_inode(fs, ino, &inode))
605 if (ext2fs_unlink(fs, dir, name, ino, 0))
608 if (inode.i_links_count == 0)
609 lfsck_kill_file_by_inode(fs, ino);
614 /* called for each ost object - save the object id and size */
615 static int lfsck_list_objs(ext2_ino_t dir, int entry,
616 struct ext2_dir_entry *dirent, int offset,
617 int blocksize, char *buf, void *priv_data)
619 struct lfsck_ost_ctx *lctx = priv_data;
620 struct lfsck_ost_objent objent;
621 struct ext2_inode inode;
624 char name[32]; /* same as filter_fid2dentry() */
626 if (!ext2fs_check_directory(lctx->ctx->fs, dirent->inode))
629 memset(name, 0, sizeof(name));
630 strncpy(name, dirent->name, dirent->name_len & 0xFF);
631 memset(&objent, 0, sizeof(objent));
632 objent.ost_oi.oi_id = STRTOUL(name, NULL, 10);
633 if (objent.ost_oi.oi_id == STRTOUL_MAX) {
635 lctx->ctx->flags |= E2F_FLAG_ABORT;
639 if (ext2fs_read_inode(lctx->ctx->fs, dirent->inode, &inode)) {
641 lctx->ctx->flags |= E2F_FLAG_ABORT;
645 if (LINUX_S_ISREG(inode.i_mode))
646 objent.ost_size = EXT2_I_SIZE(&inode);
648 objent.ost_size = inode.i_size;
649 objent.ost_bytes = (__u64)inode.i_blocks * 512;
651 if (objent.ost_oi.oi_id > lctx->max_objid)
652 lctx->max_objid = objent.ost_oi.oi_id;
654 memset(&key, 0, sizeof(key));
655 memset(&data, 0, sizeof(data));
656 key.data = &objent.ost_oi;
657 key.size = sizeof(objent.ost_oi);
658 cputole_ost_objent(&objent);
660 data.size = sizeof(objent);
662 if (dbp->put(dbp, NULL, &key, &data, 0) != 0) {
663 fprintf(stderr, "Failure to put data into db\n");
664 lctx->ctx->flags |= E2F_FLAG_ABORT;
672 /* For each file on the mds save the fid and the containing directory */
673 static int lfsck_mds_dirs(ext2_ino_t dir, int entry,
674 struct ext2_dir_entry *de, int offset,
675 int blocksize, char *buf, void *priv_data)
677 struct ext2_dir_entry_2 *dirent = (struct ext2_dir_entry_2 *)de;
678 struct lfsck_mds_ctx *lctx = priv_data;
679 struct lfsck_mds_ctx lctx2;
680 struct lfsck_mds_dirent mds_dirent;
682 DB *dbp = lctx->outdb;
686 DEBUG(lctx->ctx, "MDT: inode %u, file %.*s, type %u\n",
687 dirent->inode, dirent->name_len, dirent->name,
688 dirent->file_type & 0x15);
689 if (dirent->inode == lctx->dot || dirent->inode == lctx->dotdot)
692 /* only the low 4 bits are used to specify file type */
693 file_type = dirent->file_type & 15;
694 if (file_type != EXT2_FT_DIR && file_type != EXT2_FT_REG_FILE)
699 rc = lfsck_get_fid(lctx->ctx->fs, dirent->inode, &mds_dirent.mds_fid);
703 DEBUG(lctx->ctx, "MDT: dirfid "DFID" child "DFID" file %.*s\n",
704 PFID(&mds_dirent.mds_dirfid), PFID(&mds_dirent.mds_fid),
705 dirent->name_len, dirent->name);
707 mds_dirent.mds_dirfid = lctx->dotfid;
708 cputole_mds_dirent(&mds_dirent);
710 memset(&key, 0, sizeof(key));
711 memset(&data, 0, sizeof(data));
712 key.data = &mds_dirent.mds_fid;
713 key.size = sizeof(mds_dirent.mds_fid);
714 data.data = &mds_dirent;
715 data.size = sizeof(mds_dirent);
717 rc = dbp->put(dbp, NULL, &key, &data, 0);
719 if (rc != DB_KEYEXIST) {
721 "error adding MDS inode %.*s (inum %u): %s\n",
722 dirent->name_len & 0xFF, dirent->name,
723 dirent->inode, db_strerror(rc));
724 lctx->ctx->flags |= E2F_FLAG_ABORT;
728 if (file_type == EXT2_FT_DIR) {
730 lctx2.dot = dirent->inode;
731 lctx2.dotdot = lctx->dot;
732 lctx2.dotfid = mds_dirent.mds_fid;
733 if (ext2fs_dir_iterate2(lctx->ctx->fs, dirent->inode, 0, NULL,
734 lfsck_mds_dirs, &lctx2)) {
737 lctx->numfiles = lctx2.numfiles;
742 /* For each directory get the objects and save the data */
743 static int lfsck_iterate_obj_dirs(ext2_ino_t dir, int entry,
744 struct ext2_dir_entry *dirent, int offset,
745 int blocksize, char *buf, void *priv_data)
747 struct lfsck_ost_ctx *lctx = priv_data;
749 if (ext2fs_check_directory(lctx->ctx->fs, dirent->inode))
752 /* Traverse the d* directories */
753 if (*dirent->name != 'd')
756 ext2fs_dir_iterate2(lctx->ctx->fs, dirent->inode, 0, NULL,
757 lfsck_list_objs, priv_data);
758 if (lctx->status != 0)
764 /* Get the starting point of where the objects reside */
765 static int lfsck_get_object_dir(e2fsck_t ctx, char *block_buf,ext2_ino_t *inode)
767 ext2_filsys fs = ctx->fs;
771 rc = ext2fs_lookup(fs, EXT2_ROOT_INO, OBJECT_DIR, strlen(OBJECT_DIR),
774 fprintf(stderr, "error looking up OST object parent dir\n");
777 rc = ext2fs_check_directory(fs, tinode);
781 rc = ext2fs_lookup(fs, tinode, OBJECT_DIR_V1, strlen(OBJECT_DIR_V1),
784 rc = ext2fs_lookup(fs, tinode, OBJECT_DIR_V2,
785 strlen(OBJECT_DIR_V2), block_buf, inode);
787 fprintf(stderr, "error looking up OST object subdir\n");
791 rc = ext2fs_check_directory(fs, *inode);
798 /* create a new LAST_ID file */
799 static int create_last_id_file(ext2_filsys fs, ext2_ino_t dir_ino,
802 struct ext2_inode inode;
806 rc = ext2fs_new_inode(fs, dir_ino, S_IFREG | S_IRWXU, 0, &inum);
808 fprintf(stderr, "Creating LAST_ID file failed!\n");
812 /* Allocate and write new inode before adding the direntry.
813 * If that fails or the program is interrupted, at worst some inode
814 * space will be leaked. But without visible direntry issues */
815 ext2fs_inode_alloc_stats2(fs, inum, +1, 0);
817 memset(&inode, 0, sizeof(inode));
818 inode.i_mode = LINUX_S_IFREG | S_IRUSR | S_IWUSR;
819 inode.i_atime = inode.i_ctime = inode.i_mtime =
820 fs->now ? fs->now : time(NULL);
821 inode.i_links_count = 1;
823 rc = ext2fs_write_new_inode(fs, inum, &inode);
825 fprintf(stderr, "Failed to write new inode\n");
829 rc = ext2fs_link(fs, dir_ino, "LAST_ID", inum, EXT2_FT_REG_FILE);
830 if (rc == EXT2_ET_DIR_NO_SPACE) {
831 rc = ext2fs_expand_dir(fs, dir_ino);
833 fprintf(stderr, "Failed to expand directory");
836 rc = ext2fs_link(fs, dir_ino, "LAST_ID", inum, EXT2_FT_REG_FILE);
838 fprintf(stderr, "Failed to link directory");
847 int lfsck_set_last_id(e2fsck_t ctx, __u64 last_id)
849 ext2_filsys fs = ctx->fs;
850 ext2_ino_t inode, tinode;
853 unsigned int written;
856 block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3,
859 rc = lfsck_get_object_dir(ctx, block_buf, &inode);
863 rc = ext2fs_lookup(fs, inode, LAST_ID,
864 strlen(LAST_ID), block_buf, &tinode);
865 if (rc == EXT2_ET_FILE_NOT_FOUND) {
866 /* Create a new file */
867 VERBOSE(ctx, "Recreating missing LAST_ID\n");
868 rc = create_last_id_file(fs, inode, &tinode);
872 fprintf(stderr, "LAST_ID lookup failed: %d\n",
877 rc = ext2fs_file_open(fs, tinode, EXT2_FILE_WRITE, &e2_file);
881 if (ext2fs_file_get_size(e2_file) < sizeof(__u64)) {
882 rc = ext2fs_file_set_size(e2_file, sizeof(__u64));
884 fprintf(stderr, "Failed to resize LAST_ID\n");
889 last_id = ext2fs_cpu_to_le64(last_id);
891 rc = ext2fs_file_write(e2_file, &last_id, sizeof(__u64), &written);
893 fprintf(stderr, "Failure to update last id on file\n");
894 ext2fs_file_close(e2_file);
898 if (written != sizeof(__u64)) {
900 fprintf(stderr, "Failure to update last id on file\n");
901 ext2fs_file_close(e2_file);
905 rc = ext2fs_file_close(e2_file);
908 ext2fs_free_mem(&block_buf);
912 int e2fsck_get_last_rcvd_info(e2fsck_t ctx, struct obd_uuid *local_uuid,
913 struct obd_uuid *peer_uuid, __u32 *subdircount,
914 __u32 *index, __u32 *compat, __u32 *rocompat,
917 ext2_filsys fs = ctx->fs;
920 struct lustre_server_data *lsd = NULL;
926 block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3,
927 "block iterate buffer");
929 rc = ext2fs_lookup(fs, EXT2_ROOT_INO, LAST_RCVD, strlen(LAST_RCVD),
934 rc = ext2fs_file_open(fs, inode, 0, &e2_file);
938 lsd = e2fsck_allocate_memory(ctx, sizeof(*lsd), "lustre server data");
944 rc = ext2fs_file_read(e2_file, lsd, sizeof(*lsd), &got);
947 if (got != sizeof(*lsd)) {
953 memcpy(local_uuid, &lsd->lsd_uuid, sizeof(lsd->lsd_uuid));
956 memcpy(peer_uuid, &lsd->lsd_peeruuid,sizeof(lsd->lsd_peeruuid));
959 *subdircount = ext2fs_le16_to_cpu(lsd->lsd_subdir_count);
963 *compat = ext2fs_le32_to_cpu(lsd->lsd_feature_compat);
965 *rocompat = ext2fs_le32_to_cpu(lsd->lsd_feature_rocompat);
966 if (incompat == NULL)
968 *incompat = ext2fs_le32_to_cpu(lsd->lsd_feature_incompat);
970 if (*compat & OBD_COMPAT_OST || *incompat & OBD_INCOMPAT_OST)
971 *index = ext2fs_le32_to_cpu(lsd->lsd_ost_index);
972 else if (*compat & OBD_COMPAT_MDT||*incompat & OBD_INCOMPAT_MDT)
973 *index = ext2fs_le32_to_cpu(lsd->lsd_mdt_index);
978 rc = ext2fs_file_close(e2_file);
981 ext2fs_free_mem(&block_buf);
983 ext2fs_free_mem(&lsd);
987 int lfsck_rm_log(ext2_ino_t dir, int entry, struct ext2_dir_entry *dirent,
988 int offset, int blocksize, char *buf, void *priv_data)
990 struct lfsck_ost_ctx *lctx = priv_data;
991 char name[EXT2_NAME_LEN + 1];
993 if (!ext2fs_check_directory(lctx->ctx->fs, dirent->inode))
996 strncpy(name, dirent->name, dirent->name_len & 0xFF);
997 name[EXT2_NAME_LEN] = '\0';
998 if (memcmp(name, LAST_ID, strlen(LAST_ID)) == 0)
1002 if (lfsck_rm_file(lctx->ctx, lctx->dirinode, name))
1003 return DIRENT_ABORT;
1008 /* Not 100% sure that this is correct so not activated yet */
1009 int lfsck_remove_ost_logs(e2fsck_t ctx, char *block_buf)
1011 ext2_filsys fs = ctx->fs;
1012 struct lfsck_ost_ctx lctx;
1017 if (lfsck_rm_file(ctx, EXT2_ROOT_INO, CATLIST)) {
1018 ctx->flags |= E2F_FLAG_ABORT;
1022 rc = ext2fs_lookup(fs, EXT2_ROOT_INO, OBJECT_DIR, strlen(OBJECT_DIR),
1023 block_buf, &tinode);
1025 ctx->flags |= E2F_FLAG_ABORT;
1028 rc = ext2fs_check_directory(fs, tinode);
1030 ctx->flags |= E2F_FLAG_ABORT;
1034 rc = ext2fs_lookup(fs, tinode, LOG_DIR, strlen(LOG_DIR),
1037 ctx->flags |= E2F_FLAG_ABORT;
1040 rc = ext2fs_check_directory(fs, inode);
1042 ctx->flags |= E2F_FLAG_ABORT;
1046 lctx.dirinode = inode;
1048 if (ext2fs_dir_iterate2(fs, inode, 0, block_buf, lfsck_rm_log, &lctx)) {
1049 ctx->flags |= E2F_FLAG_ABORT;
1055 /* Remove files from PENDING dir - this needs to be done before getting ea from
1056 * blocks but we need the inode_map bitmap loaded beforehand so load write any
1057 * changes then remove references
1059 int e2fsck_lfsck_remove_pending(e2fsck_t ctx, char *block_buf)
1061 ext2_filsys fs = ctx->fs;
1062 struct lfsck_ost_ctx lctx;
1066 rc = ext2fs_lookup(fs, EXT2_ROOT_INO, PENDING_DIR, strlen(PENDING_DIR),
1067 block_buf, &tinode);
1069 ctx->flags |= E2F_FLAG_ABORT;
1072 rc = ext2fs_check_directory(fs, tinode);
1074 ctx->flags |= E2F_FLAG_ABORT;
1079 lctx.dirinode = tinode;
1081 e2fsck_read_bitmaps(ctx);
1083 if (ext2fs_dir_iterate2(fs, tinode, 0, block_buf, lfsck_rm_log, &lctx)){
1084 ctx->flags |= E2F_FLAG_ABORT;
1087 e2fsck_write_bitmaps(ctx);
1088 ext2fs_free_inode_bitmap(fs->inode_map);
1089 ext2fs_free_block_bitmap(fs->block_map);
1090 fs->inode_map = NULL;
1091 fs->block_map = NULL;
1095 /* partially using code from debugfs do_write() */
1096 int lfsck_create_objid(e2fsck_t ctx, __u64 objid)
1102 __u32 compat, incompat, subdircount;
1103 ext2_ino_t inode, tinode, cinode;
1104 struct ext2_inode ext2inode;
1107 block_buf = e2fsck_allocate_memory(ctx, ctx->fs->blocksize * 3,
1110 memset(name, 0, 32);
1111 memset(dirname, 0, 32);
1113 len = sprintf(name, LPU64, objid);
1115 fprintf(stderr, "creating %s\n", name);
1117 rc = e2fsck_get_last_rcvd_info(ctx, NULL, NULL, &subdircount, NULL,
1118 &compat, NULL, &incompat);
1120 fprintf(stderr, "Error: reading OST last_rcvd file\n");
1125 if (compat & OBD_COMPAT_MDT || incompat & OBD_INCOMPAT_MDT) {
1126 fprintf(stderr, "Error: MDS last_rcvd file doing OST check\n");
1131 if (lfsck_get_object_dir(ctx, block_buf, &inode)) {
1136 dirlen = sprintf(dirname, "d%u", (int)objid & (subdircount - 1));
1138 rc = ext2fs_lookup(ctx->fs, inode, dirname,
1139 dirlen, block_buf, &tinode);
1145 if (ext2fs_namei(ctx->fs, EXT2_ROOT_INO, tinode, name, &cinode) == 0) {
1146 fprintf(stderr, "Failure to create obj\n");
1151 rc = ext2fs_new_inode(ctx->fs, tinode, 010755, 0, &cinode);
1153 fprintf(stderr, "Failure to create obj\n");
1158 rc = ext2fs_link(ctx->fs, tinode, name, cinode, EXT2_FT_REG_FILE);
1160 fprintf(stderr, "Failure to create obj\n");
1165 if (ext2fs_test_inode_bitmap2(ctx->fs->inode_map, cinode))
1166 fprintf(stderr, "Warning: inode already set");
1168 ext2fs_inode_alloc_stats2(ctx->fs, cinode, +1, 0);
1169 memset(&ext2inode, 0, sizeof(ext2inode));
1170 ext2inode.i_mode = LINUX_S_IFREG;
1171 ext2inode.i_atime = ext2inode.i_ctime = ext2inode.i_mtime = time(NULL);
1172 ext2inode.i_links_count = 1;
1173 ext2inode.i_size = 0;
1174 if (ext2fs_write_inode(ctx->fs, cinode, &ext2inode)) {
1175 fprintf(stderr, "Failure to create obj\n");
1181 ext2fs_free_mem((void *)&(block_buf));
1186 * For on ost iterate for the direcories and save the object information.
1188 void e2fsck_pass6_ost(e2fsck_t ctx)
1190 ext2_filsys fs = ctx->fs;
1191 struct lfsck_ost_ctx lctx;
1192 struct lfsck_ost_hdr ost_hdr;
1193 struct lfsck_mds_hdr mds_hdr;
1194 struct lfsck_ost_objent objent;
1196 DB *mds_hdrdb = NULL;
1200 __u32 compat, rocompat, incompat;
1202 char *block_buf = NULL;
1204 if (unlink(ctx->lustre_ostdb)) {
1205 if (errno != ENOENT) {
1206 fprintf(stderr, "Failure to remove old db file %s\n",
1208 ctx->flags |= E2F_FLAG_ABORT;
1213 block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3,
1214 "block iterate buffer");
1216 rc = lfsck_opendb(ctx->lustre_mdsdb, MDS_HDR, &mds_hdrdb, 0, 0, 0);
1218 fprintf(stderr, "failure to open database %s: %s\n",
1219 MDS_HDR, db_strerror(rc));
1220 ctx->flags |= E2F_FLAG_ABORT;
1224 memset(&mds_hdr, 0, sizeof(mds_hdr));
1225 mds_hdr.mds_magic = MDS_MAGIC;
1226 memset(&key, 0, sizeof(key));
1227 memset(&data, 0, sizeof(data));
1228 key.data = &mds_hdr.mds_magic;
1229 key.size = sizeof(mds_hdr.mds_magic);
1230 data.data = &mds_hdr;
1231 data.size = sizeof(mds_hdr);
1232 data.ulen = sizeof(mds_hdr);
1233 data.flags = DB_DBT_USERMEM;
1234 rc = mds_hdrdb->get(mds_hdrdb, NULL, &key, &data, 0);
1236 fprintf(stderr,"error getting mds_hdr ("LPU64":%u) in %s: %s\n",
1237 mds_hdr.mds_magic, (int)sizeof(mds_hdr.mds_magic),
1238 ctx->lustre_mdsdb, db_strerror(rc));
1239 ctx->flags |= E2F_FLAG_ABORT;
1243 memcpy(&mds_hdr, data.data, sizeof(mds_hdr));
1244 letocpu_mds_hdr(&mds_hdr);
1246 rc = lfsck_opendb(ctx->lustre_ostdb, OST_HDR, &osthdr, 0, 0, 0);
1248 fprintf(stderr, "failure to open database %s: %s\n",
1249 OST_HDR, db_strerror(rc));
1250 ctx->flags |= E2F_FLAG_ABORT;
1254 rc = lfsck_opendb(ctx->lustre_ostdb, OST_OSTDB, &outdb, 0,
1255 sizeof(objent.ost_oi) + sizeof(objent),
1256 fs->super->s_inodes_count -
1257 fs->super->s_free_inodes_count);
1259 fprintf(stderr, "error getting ost_hdr in %s: %s\n",
1260 ctx->lustre_ostdb, db_strerror(rc));
1261 ctx->flags |= E2F_FLAG_ABORT;
1265 memset(&ost_hdr, 0, sizeof(ost_hdr));
1266 if (e2fsck_get_last_rcvd_info(ctx, &ost_hdr.ost_uuid,
1267 &ost_hdr.ost_mds_uuid, NULL,
1269 &compat, &rocompat, &incompat)) {
1270 fprintf(stderr, "Failure to read OST last_rcvd file\n");
1271 ctx->flags |= E2F_FLAG_ABORT;
1275 VERBOSE(ctx, "OST: '%s' ost idx %u: compat %#x rocomp %#x incomp %#x\n",
1276 (char *)&ost_hdr.ost_uuid.uuid, ost_hdr.ost_index,
1277 compat, rocompat, incompat);
1279 if (compat & OBD_COMPAT_MDT) {
1280 fprintf(stderr, "Found MDS last_rcvd file doing OST check\n");
1281 ctx->flags |= E2F_FLAG_ABORT;
1286 * Get /O/R or /O/0 directory
1287 * for each entry scan all the dirents and get the object id
1289 if (lfsck_get_object_dir(ctx, block_buf, &dir)) {
1290 ctx->flags |= E2F_FLAG_ABORT;
1295 * Okay so we have the containing directory so let's iterate over the
1296 * containing d* dirs and then iterate again inside
1303 lctx.status = ext2fs_dir_iterate2(fs, dir, 0, block_buf,
1304 lfsck_iterate_obj_dirs, &lctx);
1306 fprintf(stderr, "Failure in iterating object dirs\n");
1307 ctx->flags |= E2F_FLAG_ABORT;
1311 ost_hdr.ost_magic = OST_MAGIC;
1312 ost_hdr.ost_flags = ctx->options & E2F_OPT_READONLY;
1313 ost_hdr.ost_num_files = lctx.numfiles;
1314 VERBOSE(ctx, "OST: num files = %u\n", lctx.numfiles);
1316 /* Update the last_id value on the OST if necessary/possible to the
1317 * MDS value if larger. Otherwise we risk creating duplicate objects.
1318 * If running read-only, we skip this so new objects are ignored. */
1319 ost_hdr.ost_last_id = lctx.max_objid;
1320 if (!(ctx->options & E2F_OPT_READONLY) &&
1321 !(mds_hdr.mds_flags & E2F_OPT_READONLY)) {
1322 for (i = 0; i < mds_hdr.mds_num_osts; i++) {
1323 if (strcmp((char *)mds_hdr.mds_ost_info[i].uuid,
1324 (char *)ost_hdr.ost_uuid.uuid) == 0 &&
1325 mds_hdr.mds_max_ost_id[i] >= ost_hdr.ost_last_id)
1326 ost_hdr.ost_last_id=mds_hdr.mds_max_ost_id[i]+1;
1329 if (lfsck_set_last_id(ctx, ost_hdr.ost_last_id)) {
1330 fprintf(stderr, "Failure to set last id\n");
1331 ctx->flags |= E2F_FLAG_ABORT;
1336 if (lfsck_remove_ost_logs(ctx, block_buf))
1337 ctx->flags |= E2F_FLAG_ABORT;
1341 memset(&key, 0, sizeof(key));
1342 memset(&data, 0, sizeof(data));
1343 key.data = &ost_hdr.ost_magic;
1344 key.size = sizeof(ost_hdr.ost_magic);
1345 cputole_ost_hdr(&ost_hdr);
1346 data.data = &ost_hdr;
1347 data.size = sizeof(ost_hdr);
1348 if (osthdr->put(osthdr, NULL, &key, &data, 0)) {
1349 fprintf(stderr, "Failed to db_put data\n");
1350 ctx->flags |= E2F_FLAG_ABORT;
1356 mds_hdrdb->close(mds_hdrdb, 0);
1358 outdb->close(outdb, 0);
1360 osthdr->close(osthdr, 0);
1362 ext2fs_free_mem((void *)&(block_buf));
1366 int lfsck_remove_mds_logs(e2fsck_t ctx)
1368 ext2_filsys fs = ctx->fs;
1369 struct lfsck_ost_ctx lctx;
1373 if (lfsck_rm_file(ctx, EXT2_ROOT_INO, CATLIST)) {
1374 ctx->flags |= E2F_FLAG_ABORT;
1378 rc = ext2fs_lookup(fs, EXT2_ROOT_INO, OBJECTS, strlen(OBJECTS),
1381 ctx->flags |= E2F_FLAG_ABORT;
1384 rc = ext2fs_check_directory(fs, tinode);
1386 ctx->flags |= E2F_FLAG_ABORT;
1391 lctx.dirinode = tinode;
1393 if (ext2fs_dir_iterate2(fs, tinode, 0, NULL, lfsck_rm_log, &lctx)) {
1394 ctx->flags |= E2F_FLAG_ABORT;
1402 * On the mds save the fid and directory information for each file.
1403 * The mds ost tables have already been populated by pass1
1405 void e2fsck_pass6_mdt(e2fsck_t ctx)
1407 ext2_filsys fs = ctx->fs;
1408 struct problem_context pctx;
1409 struct lfsck_mds_ctx lctx;
1410 struct lfsck_mds_dirent mds_dirent;
1411 struct lfsck_mds_hdr mds_hdr;
1413 DB *outdb = NULL, *dbhdr = NULL;
1414 __u32 compat, rocompat, incompat, index;
1417 clear_problem_context(&pctx);
1419 memset(&lctx, 0, sizeof(lctx));
1422 /* Found no files with EA on filesystem - empty */
1423 if (ctx->lfsck_oinfo == NULL) {
1424 if (unlink(ctx->lustre_mdsdb)) {
1425 if (errno != ENOENT) {
1426 fprintf(stderr, "Failure to remove old "
1427 "db file %s\n", ctx->lustre_mdsdb);
1428 ctx->flags |= E2F_FLAG_ABORT;
1432 rc = ext2fs_get_mem(sizeof(struct lfsck_outdb_info),
1435 ctx->lfsck_oinfo = NULL;
1436 ctx->flags |= E2F_FLAG_ABORT;
1439 memset(ctx->lfsck_oinfo, 0, sizeof(struct lfsck_outdb_info));
1440 rc = ext2fs_get_mem(sizeof(struct lfsck_ofile_ctx)*LOV_MAX_OSTS,
1441 &ctx->lfsck_oinfo->ofile_ctx);
1443 ext2fs_free_mem(&ctx->lfsck_oinfo);
1444 ctx->lfsck_oinfo = NULL;
1445 ctx->flags |= E2F_FLAG_ABORT;
1448 memset(ctx->lfsck_oinfo->ofile_ctx, 0,
1449 sizeof(struct lfsck_ofile_ctx) * LOV_MAX_OSTS);
1452 if (!(ctx->options & E2F_OPT_READONLY))
1453 lfsck_write_mds_hdrinfo(ctx, ctx->lfsck_oinfo);
1455 if (lfsck_opendb(ctx->lustre_mdsdb, MDS_DIRINFO, &outdb, 1,
1456 sizeof(mds_dirent.mds_fid) + sizeof(mds_dirent),
1457 fs->super->s_inodes_count -
1458 fs->super->s_free_inodes_count)) {
1459 fprintf(stderr, "failure to open database %s\n", MDS_DIRINFO);
1460 ctx->flags |= E2F_FLAG_ABORT;
1466 lctx.dot = EXT2_ROOT_INO;
1467 lctx.dotdot = EXT2_ROOT_INO;
1468 lctx.dotfid.f_seq = EXT2_ROOT_INO;
1470 rc = ext2fs_dir_iterate2(fs, EXT2_ROOT_INO,0,NULL,lfsck_mds_dirs,&lctx);
1472 fprintf(stderr, "Error iterating directories: %d\n", rc);
1473 ctx->flags |= E2F_FLAG_ABORT;
1477 /* read in e2fsck_lfsck_save_ea() already if we opened read/write */
1478 if (ctx->lfsck_oinfo->ost_count == 0)
1479 e2fsck_get_lov_objids(ctx, ctx->lfsck_oinfo);
1481 memset(&mds_hdr, 0, sizeof(mds_hdr));
1482 mds_hdr.mds_magic = MDS_MAGIC;
1483 mds_hdr.mds_flags = ctx->options & E2F_OPT_READONLY;
1484 mds_hdr.mds_max_files = fs->super->s_inodes_count -
1485 fs->super->s_free_inodes_count;
1486 VERBOSE(ctx, "MDS: max_files = "LPU64"\n", mds_hdr.mds_max_files);
1487 mds_hdr.mds_num_osts = ctx->lfsck_oinfo->ost_count;
1488 VERBOSE(ctx, "MDS: num_osts = %u\n", mds_hdr.mds_num_osts);
1489 for (i = 0; i < mds_hdr.mds_num_osts; i++) {
1490 mds_hdr.mds_max_ost_id[i] =
1491 ctx->lfsck_oinfo->ofile_ctx[i].max_id;
1494 if (e2fsck_get_last_rcvd_info(ctx, &mds_hdr.mds_uuid, NULL, NULL,
1495 &index, &compat, &rocompat, &incompat)) {
1496 fprintf(stderr, "Failure to read MDS last_rcvd file\n");
1497 ctx->flags |= E2F_FLAG_ABORT;
1501 VERBOSE(ctx, "MDS: '%s' mdt idx %u: compat %#x rocomp %#x incomp %#x\n",
1502 (char *)&mds_hdr.mds_uuid.uuid, index,compat,rocompat,incompat);
1504 if (compat & OBD_COMPAT_OST || incompat & OBD_INCOMPAT_OST) {
1505 fprintf(stderr, "Found OST last_rcvd file doing MDS check\n");
1506 ctx->flags |= E2F_FLAG_ABORT;
1510 if (!(ctx->options & E2F_OPT_READONLY)) {
1511 if (lfsck_rm_file(ctx, EXT2_ROOT_INO, LOV_OBJID)) {
1512 ctx->flags |= E2F_FLAG_ABORT;
1516 if (lfsck_remove_mds_logs(ctx)) {
1517 ctx->flags |= E2F_FLAG_ABORT;
1523 rc = lfsck_opendb(ctx->lustre_mdsdb, MDS_HDR, &dbhdr, 0, 0, 0);
1525 fprintf(stderr, "failure to open database %s: %s\n", MDS_HDR,
1527 ctx->flags |= E2F_FLAG_ABORT;
1531 memset(&key, 0, sizeof(key));
1532 memset(&data, 0, sizeof(data));
1533 key.data = &mds_hdr.mds_magic;
1534 key.size = sizeof(mds_hdr.mds_magic);
1535 cputole_mds_hdr(&mds_hdr);
1536 data.data = &mds_hdr;
1537 data.size = sizeof(mds_hdr);
1538 rc = dbhdr->put(dbhdr, NULL, &key, &data, 0);
1540 fprintf(stderr, "error: db put %s: %s\n", MDS_HDR,
1542 ctx->flags |= E2F_FLAG_ABORT;
1547 dbhdr->close(dbhdr, 0);
1549 outdb->close(outdb, 0);
1552 /* If lfsck checking requested then gather the data */
1553 void e2fsck_pass6(e2fsck_t ctx)
1555 if (ctx->lustre_devtype == LUSTRE_NULL)
1558 printf("Pass 6: Acquiring %s information for lfsck\n",
1559 ctx->lustre_devtype & LUSTRE_OST ? "OST" :
1560 ctx->lustre_devtype & LUSTRE_MDS ? "MDT" : "device");
1564 if (ctx->lustre_devtype & LUSTRE_OST)
1565 e2fsck_pass6_ost(ctx);
1566 else if (ctx->lustre_devtype & LUSTRE_MDS)
1567 e2fsck_pass6_mdt(ctx);
1569 fprintf(stderr, "Invalid lustre dev %x\n", ctx->lustre_devtype);
1573 #endif /* HAVE_LFSCK */