Whamcloud - gitweb
LU-266 e2fsck: regenerate LAST_ID file
[tools/e2fsprogs.git] / e2fsck / pass6.c
1 /* -*- mode: c; c-basic-offset: 8; -*-
2  * vim:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
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.
11  *
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).
17  *
18  *
19  * Copyright (c) 2004  Hewlett-Packard Co.
20  */
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
35  *
36  *****************************************************************************/
37 #include "config.h"
38 #include <string.h>
39 #include <time.h>
40 #include <errno.h>
41 #include <limits.h>
42 #include <stdlib.h>
43 #include "ext2fs/ext2_fs.h"
44 #include "ext2fs/ext2fs.h"
45
46 #ifdef HAVE_LFSCK
47 #include "e2fsck.h"
48 #include "ext2fs/lfsck.h"
49 #include "problem.h"
50 //#define LOG_REMOVAL
51
52 #define VERBOSE(ctx, fmt, args...) \
53 do { if (ctx->options & E2F_OPT_VERBOSE) printf(fmt, ##args); } while (0)
54
55 #define DEBUG(ctx, fmt, args...) \
56 do { if (ctx->options & E2F_OPT_DEBUG) printf(fmt, ##args); } while (0)
57
58 struct lfsck_mds_ctx {
59         e2fsck_t        ctx;
60         DB              *outdb;
61         ext2_ino_t      dot;
62         ext2_ino_t      dotdot;
63         struct lu_fid   dotfid;
64         int             numfiles;
65 };
66
67 struct lfsck_ost_ctx {
68         e2fsck_t        ctx;
69         DB              *outdb;
70         ext2_ino_t      dirinode;
71         int             numfiles;
72         int             status;
73         __u64           max_objid;
74 };
75
76 int e2fsck_lfsck_cleanupdb(e2fsck_t ctx)
77 {
78         int i;
79         int rc = 0;
80         DB *dbp;
81
82         if (ctx->lfsck_oinfo == NULL)
83                 return 0;
84
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;
90                 }
91         }
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;
96         }
97         if (ctx->lfsck_oinfo->ofile_ctx)
98                 ext2fs_free_mem(ctx->lfsck_oinfo->ofile_ctx);
99         ext2fs_free_mem(&ctx->lfsck_oinfo);
100
101         return rc;
102 }
103
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)
106 {
107         ext2_filsys fs = ctx->fs;
108         ext2_ino_t inode;
109         ext2_file_t e2_file;
110         __u64 *lov_objids = NULL;
111         unsigned int got;
112         char *block_buf;
113         int i, rc = 0;
114
115         block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3,
116                                            "block iterate buffer");
117
118         rc = ext2fs_lookup(fs, EXT2_ROOT_INO, LOV_OBJID,
119                            strlen(LOV_OBJID), block_buf, &inode);
120         if (rc)
121                 goto out;
122
123         lov_objids = e2fsck_allocate_memory(ctx,
124                                             sizeof(*lov_objids) * LOV_MAX_OSTS,
125                                             "lov_objids array");
126         if (lov_objids == NULL) {
127                 rc = ENOMEM;
128                 goto out;
129         }
130
131         rc = ext2fs_file_open(fs, inode, 0, &e2_file);
132         if (rc)
133                 goto out;
134
135         rc = ext2fs_file_read(e2_file, lov_objids,
136                               sizeof(*lov_objids) * LOV_MAX_OSTS, &got);
137         rc = ext2fs_file_close(e2_file);
138
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;
145         }
146
147 out:
148         ext2fs_free_mem(&block_buf);
149         if (lov_objids)
150                 ext2fs_free_mem(&lov_objids);
151         if (rc)
152                 VERBOSE(ctx, "MDS: unable to read lov_objids: rc %d\n", rc);
153         else
154                 VERBOSE(ctx, "MDS: got %d bytes = %d entries in lov_objids\n",
155                         got, outdb->ost_count);
156         return rc;
157 }
158
159 static int lfsck_write_mds_hdrinfo(e2fsck_t ctx, struct lfsck_outdb_info *outdb)
160 {
161         struct lfsck_mds_hdr mds_hdr;
162         ext2_filsys fs = ctx->fs;
163         char *mds_hdrname;
164         DB *mds_hdrdb = NULL;
165         DBT key, data;
166         int rc = 0;
167         int i;
168
169         mds_hdrname = e2fsck_allocate_memory(ctx, PATH_MAX,
170                                              "mds_hdr filename");
171         sprintf(mds_hdrname, "%s.mdshdr", ctx->lustre_mdsdb);
172
173         if (unlink(mds_hdrname)) {
174                 if (errno != ENOENT) {
175                         fprintf(stderr, "Failure to remove old db file %s\n",
176                                 mds_hdrname);
177                         ctx->flags |= E2F_FLAG_ABORT;
178                         return -EINVAL;
179                 }
180         }
181
182         rc = lfsck_opendb(mds_hdrname, MDS_HDR, &mds_hdrdb, 0, 0, 0);
183         if (rc != 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);
188                 return rc;
189         }
190
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);
194
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;
206         }
207
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);
216         if (rc != 0) {
217                 fprintf(stderr, "error: db put %s: %s\n", MDS_HDR,
218                         db_strerror(rc));
219                 ctx->flags |= E2F_FLAG_ABORT;
220                 goto out;
221         }
222
223 out:
224         mds_hdrdb->close(mds_hdrdb, 0);
225         ext2fs_free_mem(&mds_hdrname);
226         if (rc == 0) {
227                 printf("mds info db file written \n");
228                 fflush(stdout);
229
230         }
231         return rc;
232 }
233
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)
236 {
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;
242         int rc, i;
243         DBT key, data;
244         DB *dbp;
245         __u32 numfiles = fs->super->s_inodes_count -
246                          fs->super->s_free_inodes_count;
247
248         if (!ctx->lfsck_oinfo) {
249                 /* remove old db file */
250                 if (unlink(ctx->lustre_mdsdb)) {
251                         rc = errno;
252                         if (rc != ENOENT) {
253                                 fprintf(stderr,"Error removing old db %s: %s\n",
254                                         ctx->lustre_mdsdb, strerror(rc));
255                                 ctx->flags |= E2F_FLAG_ABORT;
256                                 return rc;
257                         }
258                 }
259
260                 rc = ext2fs_get_mem(sizeof(struct lfsck_outdb_info),
261                                     &ctx->lfsck_oinfo);
262                 if (rc) {
263                         ctx->lfsck_oinfo = NULL;
264                         ctx->flags |= E2F_FLAG_ABORT;
265                         return rc;
266                 }
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);
270                 if (rc) {
271                         ext2fs_free_mem(&ctx->lfsck_oinfo);
272                         ctx->flags |= E2F_FLAG_ABORT;
273                         return rc;
274                 }
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),
281                                  numfiles)) {
282                         fprintf(stderr, "Failed to open db file %s\n",
283                                 MDS_SIZEINFO);
284                         ctx->flags |= E2F_FLAG_ABORT;
285                         return EIO;
286                 }
287 #endif /* LFSCK_CHECK_SIZE */
288
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);
292                 }
293         }
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;
298
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;
310
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);
316         data.data = &szinfo;
317         data.size = sizeof(szinfo);
318         dbp = ctx->lfsck_oinfo->mds_sizeinfo_dbp;
319
320         rc = dbp->put(dbp, NULL, &key, &data, 0);
321         if (rc != 0) {
322                 dbp->err(ctx->lfsck_oinfo->mds_sizeinfo_dbp, rc,
323                          "db->put failed\n");
324                 e2fsck_lfsck_cleanupdb(ctx);
325                 ctx->flags |= E2F_FLAG_ABORT;
326
327                 return EIO;
328         }
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];
335
336                 if (ost_idx >= LOV_MAX_OSTS) {
337                         fprintf(stderr, "invalid OST index %u ino %u[%d]\n",
338                                 ost_idx, ino, i);
339                         continue;
340                 }
341
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",
345                                         ost_idx, ino, i);
346                                 continue;
347                         }
348                         ctx->lfsck_oinfo->ost_count = ost_idx + 1;
349                 }
350
351                 if (ofile_ctx->dbp == NULL) {
352                         char dbname[256];
353
354                         sprintf(dbname, "%s.%d", MDS_OSTDB, ost_idx);
355                         rc = lfsck_opendb(ctx->lustre_mdsdb, dbname,
356                                           &ofile_ctx->dbp, 1,
357                                           sizeof(mds_ent), numfiles);
358                         if (rc) {
359                                 e2fsck_lfsck_cleanupdb(ctx);
360                                 ctx->flags |= E2F_FLAG_ABORT;
361                                 return EIO;
362                         }
363                 }
364
365                 memset(&mds_ent, 0, sizeof(mds_ent));
366                 if (lma) {
367                         mds_ent.mds_fid = lma->lma_self_fid;
368                 } else {
369                         mds_ent.mds_fid.f_seq = ino;
370                         mds_ent.mds_fid.f_oid = generation;
371                         mds_ent.mds_fid.f_ver = 0;
372                 }
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;
376
377                 if (mds_ent.mds_oi.oi_id > ofile_ctx->max_id) {
378                         if (ofile_ctx->have_max_id) {
379                                 DEBUG(ctx,
380                                       "[%d] skip obj "LPU64" > max "LPU64"\n",
381                                       ost_idx, mds_ent.mds_oi.oi_id,
382                                       ofile_ctx->max_id);
383                                 continue;
384                         }
385                         ofile_ctx->max_id = mds_ent.mds_oi.oi_id;
386                 }
387
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;
396 #if 0
397                 DEBUG(ctx, "OST[%u]: inode FID "DFID" oi "DOIF"\n", ost_idx,
398                       PFID(&mds_ent.mds_fid), POIF(&mds_ent.mds_oi));
399 #endif
400                 rc = dbp->put(dbp, NULL, &key, &data, 0);
401                 if (rc != 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 */
406                         return EIO;
407                 }
408         }
409         return 0;
410 }
411
412 static int lfsck_check_lov_ea(e2fsck_t ctx, struct lov_user_md *lmm)
413 {
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",
417                         lmm->lmm_magic);
418                 return -EINVAL;
419         }
420
421         return 0;
422 }
423
424 static int lfsck_check_lma_ea(e2fsck_t ctx, struct lustre_mdt_attrs *lma)
425 {
426         return 0;
427 }
428
429 /*
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.
432  */
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)
437 {
438         void *ea = NULL;
439         int retval;
440         unsigned int got;
441         ext2_file_t file;
442
443         /* This ensures that we don't open the file here if traversing an OST */
444         if ((ctx->lustre_devtype & LUSTRE_TYPE) != LUSTRE_MDS)
445                 return 0;
446
447         if (!LINUX_S_ISREG(inode->i_mode))
448                 return 0;
449
450         if (entry->e_name_len == 0)
451                 return 0;
452
453         if (entry->e_name_index == EXT3_XATTR_INDEX_TRUSTED &&
454             entry->e_name_index == EXT3_XATTR_INDEX_LUSTRE)
455                 return 0;
456
457         ea = e2fsck_allocate_memory(ctx, entry->e_value_size, "EA");
458
459         if (entry->e_value_inum != 0) {
460                 /* EA in external inode */
461                 retval = ext2fs_file_open(ctx->fs, entry->e_value_inum,
462                                           0, &file);
463                 if (!retval) {
464                         retval = ext2fs_file_read(file, ea,
465                                                   entry->e_value_size, &got);
466                         ext2fs_file_close(file);
467                         if (retval != 0) {
468                                 ext2fs_free_mem(&ea);
469                                 return 0;
470                         }
471                 } else {
472                         ext2fs_free_mem(&ea);
473                         return 0;
474                 }
475         } else {
476                 memcpy(ea, value, entry->e_value_size);
477         }
478
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) {
482                 if (*lmm) {
483                         ext2fs_free_mem(&ea);
484                         return -EINVAL;
485                 }
486                 *lmm = ea;
487                 letocpu_lov_user_md(*lmm);
488
489                 if (lfsck_check_lov_ea(ctx, *lmm)) {
490                         *lmm = NULL;
491                         ctx->flags |= E2F_FLAG_ABORT;
492                         ext2fs_free_mem(&ea);
493                         return -EINVAL;
494                 }
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) {
498                 if (*lma) {
499                         ext2fs_free_mem(&ea);
500                         return -EINVAL;
501                 }
502                 *lma = ea;
503                 if (lfsck_check_lma_ea(ctx, *lma)) {
504                         *lma = NULL;
505                         ctx->flags |= E2F_FLAG_ABORT;
506                         ext2fs_free_mem(&ea);
507                         return -EINVAL;
508                 }
509         } else {
510                 ext2fs_free_mem(&ea);
511         }
512
513         return 0;
514 }
515
516 /* make sure that the mds data is on file */
517 int e2fsck_lfsck_flush_ea(e2fsck_t ctx)
518 {
519         int i, rc = 0;
520         DB *dbp;
521
522         if ((ctx->lustre_devtype & LUSTRE_TYPE) != LUSTRE_MDS)
523                 return 0;
524
525         if (ctx->lfsck_oinfo == 0)
526                 return 0;
527
528         for (i = 0; i < ctx->lfsck_oinfo->ost_count; i++) {
529                 if (ctx->lfsck_oinfo->ofile_ctx == NULL)
530                         break;
531
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;
536                 }
537         }
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;
542         }
543
544         if (rc)
545                 ctx->flags |= E2F_FLAG_ABORT;
546
547         return rc;
548 }
549
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)
553 {
554         blk_t   block;
555
556         block = *blocknr;
557         ext2fs_block_alloc_stats(fs, block, -1);
558         return 0;
559 }
560
561 static void lfsck_kill_file_by_inode(ext2_filsys fs, ext2_ino_t inode)
562 {
563         struct ext2_inode inode_buf;
564
565         if (ext2fs_read_inode(fs, inode, &inode_buf))
566                 return;
567
568         inode_buf.i_dtime = time(NULL);
569         if (ext2fs_write_inode(fs, inode, &inode_buf))
570                 return;
571
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));
576 }
577
578 /*
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
584  */
585 static int lfsck_rm_file(e2fsck_t ctx, ext2_ino_t dir, char *name)
586 {
587         ext2_filsys fs = ctx->fs;
588         ext2_ino_t ino;
589         struct ext2_inode inode;
590         int rc;
591
592         rc = ext2fs_lookup(fs, dir, name, strlen(name),
593                            NULL, &ino);
594         if (rc)
595                 return 0;
596
597         if (ext2fs_read_inode(fs, ino, &inode))
598                 return -EINVAL;
599
600         --inode.i_links_count;
601
602         if (ext2fs_write_inode(fs, ino, &inode))
603                 return -EINVAL;
604
605         if (ext2fs_unlink(fs, dir, name, ino, 0))
606                 return -EIO;
607
608         if (inode.i_links_count == 0)
609                 lfsck_kill_file_by_inode(fs, ino);
610
611         return 0;
612 }
613
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)
618 {
619         struct lfsck_ost_ctx *lctx = priv_data;
620         struct lfsck_ost_objent objent;
621         struct ext2_inode inode;
622         DBT key, data;
623         DB *dbp;
624         char name[32]; /* same as filter_fid2dentry() */
625
626         if (!ext2fs_check_directory(lctx->ctx->fs, dirent->inode))
627                 return 0;
628
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) {
634                 lctx->status = 1;
635                 lctx->ctx->flags |= E2F_FLAG_ABORT;
636                 return DIRENT_ABORT;
637         }
638
639         if (ext2fs_read_inode(lctx->ctx->fs, dirent->inode, &inode)) {
640                 lctx->status = 1;
641                 lctx->ctx->flags |= E2F_FLAG_ABORT;
642                 return DIRENT_ABORT;
643         }
644
645         if (LINUX_S_ISREG(inode.i_mode))
646                 objent.ost_size = EXT2_I_SIZE(&inode);
647         else
648                 objent.ost_size = inode.i_size;
649         objent.ost_bytes = (__u64)inode.i_blocks * 512;
650
651         if (objent.ost_oi.oi_id > lctx->max_objid)
652                 lctx->max_objid = objent.ost_oi.oi_id;
653
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);
659         data.data = &objent;
660         data.size = sizeof(objent);
661         dbp = lctx->outdb;
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;
665                 return DIRENT_ABORT;
666         }
667
668         lctx->numfiles++;
669         return 0;
670 }
671
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)
676 {
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;
681         DBT key, data;
682         DB *dbp = lctx->outdb;
683         int file_type;
684         int rc = 0;
685
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)
690                 return 0;
691
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)
695                 return 0;
696
697         lctx->numfiles++;
698
699         rc = lfsck_get_fid(lctx->ctx->fs, dirent->inode, &mds_dirent.mds_fid);
700         if (rc != 0)
701                 return 0;
702
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);
706
707         mds_dirent.mds_dirfid = lctx->dotfid;
708         cputole_mds_dirent(&mds_dirent);
709
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);
716
717         rc = dbp->put(dbp, NULL, &key, &data, 0);
718         if (rc != 0) {
719                 if (rc != DB_KEYEXIST) {
720                         fprintf(stderr,
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;
725                         return DIRENT_ABORT;
726                 }
727         }
728         if (file_type == EXT2_FT_DIR) {
729                 lctx2 = *lctx;
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)) {
735                         return DIRENT_ABORT;
736                 }
737                 lctx->numfiles = lctx2.numfiles;
738         }
739         return 0;
740 }
741
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)
746 {
747         struct lfsck_ost_ctx *lctx = priv_data;
748
749         if (ext2fs_check_directory(lctx->ctx->fs, dirent->inode))
750                 return 0;
751
752         /* Traverse the d* directories */
753         if (*dirent->name != 'd')
754                 return 0;
755
756         ext2fs_dir_iterate2(lctx->ctx->fs, dirent->inode, 0, NULL,
757                             lfsck_list_objs, priv_data);
758         if (lctx->status != 0)
759                 return DIRENT_ABORT;
760
761         return 0;
762 }
763
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)
766 {
767         ext2_filsys fs = ctx->fs;
768         ext2_ino_t  tinode;
769         int rc;
770
771         rc = ext2fs_lookup(fs, EXT2_ROOT_INO, OBJECT_DIR, strlen(OBJECT_DIR),
772                            block_buf, &tinode);
773         if (rc) {
774                 fprintf(stderr, "error looking up OST object parent dir\n");
775                 return ENOENT;
776         }
777         rc = ext2fs_check_directory(fs, tinode);
778         if (rc)
779                 return ENOENT;
780
781         rc = ext2fs_lookup(fs, tinode, OBJECT_DIR_V1, strlen(OBJECT_DIR_V1),
782                            block_buf, inode);
783         if (rc) {
784                 rc = ext2fs_lookup(fs, tinode, OBJECT_DIR_V2,
785                                    strlen(OBJECT_DIR_V2), block_buf, inode);
786                 if (rc) {
787                         fprintf(stderr, "error looking up OST object subdir\n");
788                         return -ENOENT;
789                 }
790         }
791         rc = ext2fs_check_directory(fs, *inode);
792         if (rc)
793                 return -ENOENT;
794
795         return 0;
796 }
797
798 /* create a new LAST_ID file */
799 static int create_last_id_file(ext2_filsys fs, ext2_ino_t dir_ino,
800                                ext2_ino_t *new_ino)
801 {
802         struct ext2_inode inode;
803         ext2_ino_t inum;
804         int rc;
805
806         rc = ext2fs_new_inode(fs, dir_ino, S_IFREG | S_IRWXU, 0, &inum);
807         if (rc) {
808                 fprintf(stderr, "Creating LAST_ID file failed!\n");
809                 return rc;
810         }
811
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);
816
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;
822         inode.i_size = 0;
823         rc = ext2fs_write_new_inode(fs, inum, &inode);
824         if (rc) {
825                 fprintf(stderr, "Failed to write new inode\n");
826                 return rc;
827         }
828
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);
832                 if (rc) {
833                         fprintf(stderr, "Failed to expand directory");
834                         return rc;
835                 }
836                 rc = ext2fs_link(fs, dir_ino, "LAST_ID", inum, EXT2_FT_REG_FILE);
837                 if (rc) {
838                         fprintf(stderr, "Failed to link directory");
839                         return rc;
840                 }
841         }
842
843         *new_ino = inum;
844         return 0;
845 }
846
847 int lfsck_set_last_id(e2fsck_t ctx,  __u64 last_id)
848 {
849         ext2_filsys fs = ctx->fs;
850         ext2_ino_t  inode, tinode;
851         ext2_file_t  e2_file;
852         char *block_buf;
853         unsigned int written;
854         int rc;
855
856         block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3,
857                                            "lookup buffer");
858
859         rc = lfsck_get_object_dir(ctx, block_buf, &inode);
860         if (rc)
861                 goto out;
862
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);
869                 if (rc)
870                         goto out;
871         } else if (rc) {
872                 fprintf(stderr, "LAST_ID lookup failed: %d\n",
873                         rc);
874                 goto out;
875         }
876
877         rc = ext2fs_file_open(fs, tinode, EXT2_FILE_WRITE, &e2_file);
878         if (rc)
879                 goto out;
880
881         if (ext2fs_file_get_size(e2_file) < sizeof(__u64)) {
882                 rc = ext2fs_file_set_size(e2_file, sizeof(__u64));
883                 if (rc) {
884                         fprintf(stderr, "Failed to resize LAST_ID\n");
885                         goto out;
886                 }
887         }
888
889         last_id = ext2fs_cpu_to_le64(last_id);
890
891         rc = ext2fs_file_write(e2_file, &last_id, sizeof(__u64), &written);
892         if (rc) {
893                 fprintf(stderr, "Failure to update last id on file\n");
894                 ext2fs_file_close(e2_file);
895                 goto out;
896         }
897
898         if (written != sizeof(__u64)) {
899                 rc = EIO;
900                 fprintf(stderr, "Failure to update last id on file\n");
901                 ext2fs_file_close(e2_file);
902                 goto out;
903         }
904
905         rc = ext2fs_file_close(e2_file);
906
907 out:
908         ext2fs_free_mem(&block_buf);
909         return rc;
910 }
911
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,
915                               __u32 *incompat)
916 {
917         ext2_filsys fs = ctx->fs;
918         ext2_ino_t inode;
919         ext2_file_t e2_file;
920         struct lustre_server_data *lsd = NULL;
921         unsigned int got;
922         char *block_buf;
923         __u32 cmp, inc;
924         int rc = 0;
925
926         block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3,
927                                            "block iterate buffer");
928
929         rc = ext2fs_lookup(fs, EXT2_ROOT_INO, LAST_RCVD, strlen(LAST_RCVD),
930                            block_buf, &inode);
931         if (rc)
932                 goto out;
933
934         rc = ext2fs_file_open(fs, inode, 0, &e2_file);
935         if (rc)
936                 goto out;
937
938         lsd = e2fsck_allocate_memory(ctx, sizeof(*lsd), "lustre server data");
939         if (lsd == NULL) {
940                 rc = ENOMEM;
941                 goto out;
942         }
943
944         rc = ext2fs_file_read(e2_file, lsd, sizeof(*lsd), &got);
945         if (rc)
946                 goto out;
947         if (got != sizeof(*lsd)) {
948                 rc = EIO;
949                 goto out;
950         }
951
952         if (local_uuid)
953                 memcpy(local_uuid, &lsd->lsd_uuid, sizeof(lsd->lsd_uuid));
954
955         if (peer_uuid)
956                 memcpy(peer_uuid, &lsd->lsd_peeruuid,sizeof(lsd->lsd_peeruuid));
957
958         if (subdircount)
959                 *subdircount = ext2fs_le16_to_cpu(lsd->lsd_subdir_count);
960
961         if (compat == NULL)
962                 compat = &cmp;
963         *compat = ext2fs_le32_to_cpu(lsd->lsd_feature_compat);
964         if (rocompat)
965                 *rocompat = ext2fs_le32_to_cpu(lsd->lsd_feature_rocompat);
966         if (incompat == NULL)
967                 incompat = &inc;
968         *incompat = ext2fs_le32_to_cpu(lsd->lsd_feature_incompat);
969         if (index) {
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);
974                 else
975                         *index = -1;
976         }
977
978         rc = ext2fs_file_close(e2_file);
979
980 out:
981         ext2fs_free_mem(&block_buf);
982         if (lsd)
983                 ext2fs_free_mem(&lsd);
984         return rc;
985 }
986
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)
989 {
990         struct lfsck_ost_ctx *lctx = priv_data;
991         char name[EXT2_NAME_LEN + 1];
992
993         if (!ext2fs_check_directory(lctx->ctx->fs, dirent->inode))
994                 return 0;
995
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)
999                 return 0;
1000
1001
1002         if (lfsck_rm_file(lctx->ctx, lctx->dirinode, name))
1003                 return DIRENT_ABORT;
1004
1005         return 0;
1006 }
1007
1008 /* Not 100% sure that this is correct so not activated yet */
1009 int lfsck_remove_ost_logs(e2fsck_t ctx, char *block_buf)
1010 {
1011         ext2_filsys fs = ctx->fs;
1012         struct lfsck_ost_ctx lctx;
1013         ext2_ino_t inode;
1014         ext2_ino_t  tinode;
1015         int rc;
1016
1017         if (lfsck_rm_file(ctx, EXT2_ROOT_INO, CATLIST)) {
1018                 ctx->flags |= E2F_FLAG_ABORT;
1019                 return -EINVAL;
1020         }
1021
1022         rc = ext2fs_lookup(fs, EXT2_ROOT_INO, OBJECT_DIR, strlen(OBJECT_DIR),
1023                            block_buf, &tinode);
1024         if (rc) {
1025                 ctx->flags |= E2F_FLAG_ABORT;
1026                 return -ENOENT;
1027         }
1028         rc = ext2fs_check_directory(fs, tinode);
1029         if (rc) {
1030                 ctx->flags |= E2F_FLAG_ABORT;
1031                 return -ENOENT;
1032         }
1033
1034         rc = ext2fs_lookup(fs, tinode, LOG_DIR, strlen(LOG_DIR),
1035                            block_buf, &inode);
1036         if (rc) {
1037                 ctx->flags |= E2F_FLAG_ABORT;
1038                 return -ENOENT;
1039         }
1040         rc = ext2fs_check_directory(fs, inode);
1041         if (rc) {
1042                 ctx->flags |= E2F_FLAG_ABORT;
1043                 return -ENOENT;
1044         }
1045         lctx.ctx   = ctx;
1046         lctx.dirinode = inode;
1047
1048         if (ext2fs_dir_iterate2(fs, inode, 0, block_buf, lfsck_rm_log, &lctx)) {
1049                 ctx->flags |= E2F_FLAG_ABORT;
1050                 return -EIO;
1051         }
1052         return 0;
1053 }
1054
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
1058  */
1059 int e2fsck_lfsck_remove_pending(e2fsck_t ctx, char *block_buf)
1060 {
1061         ext2_filsys fs = ctx->fs;
1062         struct lfsck_ost_ctx lctx;
1063         ext2_ino_t  tinode;
1064         int rc = 0;
1065
1066         rc = ext2fs_lookup(fs, EXT2_ROOT_INO, PENDING_DIR, strlen(PENDING_DIR),
1067                            block_buf, &tinode);
1068         if (rc) {
1069                 ctx->flags |= E2F_FLAG_ABORT;
1070                 return -ENOENT;
1071         }
1072         rc = ext2fs_check_directory(fs, tinode);
1073         if (rc) {
1074                 ctx->flags |= E2F_FLAG_ABORT;
1075                 return -ENOENT;
1076         }
1077
1078         lctx.ctx   = ctx;
1079         lctx.dirinode = tinode;
1080
1081         e2fsck_read_bitmaps(ctx);
1082
1083         if (ext2fs_dir_iterate2(fs, tinode, 0, block_buf, lfsck_rm_log, &lctx)){
1084                 ctx->flags |= E2F_FLAG_ABORT;
1085                 rc = -EIO;
1086         }
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;
1092         return rc;
1093 }
1094
1095 /* partially using code from debugfs do_write() */
1096 int lfsck_create_objid(e2fsck_t ctx, __u64 objid)
1097 {
1098         int rc = 0;
1099         char dirname[32];
1100         char name[32];
1101         int len, dirlen;
1102         __u32 compat, incompat, subdircount;
1103         ext2_ino_t  inode, tinode, cinode;
1104         struct ext2_inode ext2inode;
1105         char *block_buf;
1106
1107         block_buf = e2fsck_allocate_memory(ctx, ctx->fs->blocksize * 3,
1108                                            "lookup buffer");
1109
1110         memset(name, 0, 32);
1111         memset(dirname, 0, 32);
1112
1113         len = sprintf(name, LPU64, objid);
1114
1115         fprintf(stderr, "creating %s\n", name);
1116
1117         rc = e2fsck_get_last_rcvd_info(ctx, NULL, NULL, &subdircount, NULL,
1118                                        &compat, NULL, &incompat);
1119         if (rc) {
1120                 fprintf(stderr, "Error: reading OST last_rcvd file\n");
1121                 rc = EINVAL;
1122                 goto out;
1123         }
1124
1125         if (compat & OBD_COMPAT_MDT || incompat & OBD_INCOMPAT_MDT) {
1126                 fprintf(stderr, "Error: MDS last_rcvd file doing OST check\n");
1127                 rc = EINVAL;
1128                 goto out;
1129         }
1130
1131         if (lfsck_get_object_dir(ctx, block_buf, &inode)) {
1132                 rc = EINVAL;
1133                 goto out;
1134         }
1135
1136         dirlen = sprintf(dirname, "d%u", (int)objid & (subdircount - 1));
1137
1138         rc = ext2fs_lookup(ctx->fs, inode, dirname,
1139                            dirlen, block_buf, &tinode);
1140         if (rc) {
1141                 rc = EINVAL;
1142                 goto out;
1143         }
1144
1145         if (ext2fs_namei(ctx->fs, EXT2_ROOT_INO, tinode, name, &cinode) == 0) {
1146                 fprintf(stderr, "Failure to create obj\n");
1147                 rc = EINVAL;
1148                 goto out;
1149         }
1150
1151         rc = ext2fs_new_inode(ctx->fs, tinode, 010755, 0, &cinode);
1152         if (rc) {
1153                 fprintf(stderr, "Failure to create obj\n");
1154                 rc = EINVAL;
1155                 goto out;
1156         }
1157
1158         rc = ext2fs_link(ctx->fs, tinode, name, cinode, EXT2_FT_REG_FILE);
1159         if (rc) {
1160                 fprintf(stderr, "Failure to create obj\n");
1161                 rc = EINVAL;
1162                 goto out;
1163         }
1164
1165         if (ext2fs_test_inode_bitmap2(ctx->fs->inode_map, cinode))
1166                 fprintf(stderr, "Warning: inode already set");
1167
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");
1176                 rc = EINVAL;
1177                 goto out;
1178         }
1179
1180 out:
1181         ext2fs_free_mem((void *)&(block_buf));
1182         return rc;
1183 }
1184
1185 /*
1186  * For on ost iterate for the direcories and save the object information.
1187  */
1188 void e2fsck_pass6_ost(e2fsck_t ctx)
1189 {
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;
1195         DB *outdb = NULL;
1196         DB *mds_hdrdb = NULL;
1197         DB *osthdr = NULL;
1198         DBT key, data;
1199         ext2_ino_t dir;
1200         __u32 compat, rocompat, incompat;
1201         int i, rc;
1202         char *block_buf = NULL;
1203
1204         if (unlink(ctx->lustre_ostdb)) {
1205                 if (errno != ENOENT) {
1206                         fprintf(stderr, "Failure to remove old db file %s\n",
1207                                 ctx->lustre_ostdb);
1208                         ctx->flags |= E2F_FLAG_ABORT;
1209                         return;
1210                 }
1211         }
1212
1213         block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3,
1214                                            "block iterate buffer");
1215
1216         rc = lfsck_opendb(ctx->lustre_mdsdb, MDS_HDR, &mds_hdrdb, 0, 0, 0);
1217         if (rc != 0) {
1218                 fprintf(stderr, "failure to open database %s: %s\n",
1219                         MDS_HDR, db_strerror(rc));
1220                 ctx->flags |= E2F_FLAG_ABORT;
1221                 goto out;
1222         }
1223
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);
1235         if (rc) {
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;
1240                 goto out;
1241         }
1242
1243         memcpy(&mds_hdr, data.data, sizeof(mds_hdr));
1244         letocpu_mds_hdr(&mds_hdr);
1245
1246         rc = lfsck_opendb(ctx->lustre_ostdb, OST_HDR, &osthdr, 0, 0, 0);
1247         if (rc != 0) {
1248                 fprintf(stderr, "failure to open database %s: %s\n",
1249                         OST_HDR, db_strerror(rc));
1250                 ctx->flags |= E2F_FLAG_ABORT;
1251                 goto out;
1252         }
1253
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);
1258         if (rc != 0) {
1259                 fprintf(stderr, "error getting ost_hdr in %s: %s\n",
1260                         ctx->lustre_ostdb, db_strerror(rc));
1261                 ctx->flags |= E2F_FLAG_ABORT;
1262                 goto out;
1263         }
1264
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,
1268                                       &ost_hdr.ost_index,
1269                                       &compat, &rocompat, &incompat)) {
1270                 fprintf(stderr, "Failure to read OST last_rcvd file\n");
1271                 ctx->flags |= E2F_FLAG_ABORT;
1272                 goto out;
1273         }
1274
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);
1278
1279         if (compat & OBD_COMPAT_MDT) {
1280                 fprintf(stderr, "Found MDS last_rcvd file doing OST check\n");
1281                 ctx->flags |= E2F_FLAG_ABORT;
1282                 goto out;
1283         }
1284
1285         /*
1286          * Get /O/R or /O/0 directory
1287          * for each entry scan all the dirents and get the object id
1288          */
1289         if (lfsck_get_object_dir(ctx, block_buf, &dir)) {
1290                 ctx->flags |= E2F_FLAG_ABORT;
1291                 goto out;
1292         }
1293
1294         /*
1295          * Okay so we have the containing directory so let's iterate over the
1296          * containing d* dirs and then iterate again inside
1297          */
1298         lctx.ctx = ctx;
1299         lctx.outdb = outdb;
1300         lctx.status = 0;
1301         lctx.numfiles = 0;
1302         lctx.max_objid = 0;
1303         lctx.status = ext2fs_dir_iterate2(fs, dir, 0, block_buf,
1304                                           lfsck_iterate_obj_dirs, &lctx);
1305         if (lctx.status) {
1306                 fprintf(stderr, "Failure in iterating object dirs\n");
1307                 ctx->flags |= E2F_FLAG_ABORT;
1308                 return;
1309         }
1310
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);
1315
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;
1327                 }
1328
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;
1332                         goto out;
1333                 }
1334
1335 #ifdef LOG_REMOVAL
1336                 if (lfsck_remove_ost_logs(ctx, block_buf))
1337                         ctx->flags |= E2F_FLAG_ABORT;
1338 #endif
1339         }
1340
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;
1351                 goto out;
1352         }
1353
1354 out:
1355         if (mds_hdrdb)
1356                 mds_hdrdb->close(mds_hdrdb, 0);
1357         if (outdb)
1358                 outdb->close(outdb, 0);
1359         if (osthdr)
1360                 osthdr->close(osthdr, 0);
1361         if (block_buf)
1362                 ext2fs_free_mem((void *)&(block_buf));
1363         return;
1364 }
1365
1366 int lfsck_remove_mds_logs(e2fsck_t ctx)
1367 {
1368         ext2_filsys fs = ctx->fs;
1369         struct lfsck_ost_ctx lctx;
1370         ext2_ino_t  tinode;
1371         int rc = 0;
1372
1373         if (lfsck_rm_file(ctx, EXT2_ROOT_INO, CATLIST)) {
1374                 ctx->flags |= E2F_FLAG_ABORT;
1375                 return -EINVAL;
1376         }
1377
1378         rc = ext2fs_lookup(fs, EXT2_ROOT_INO, OBJECTS, strlen(OBJECTS),
1379                            NULL, &tinode);
1380         if (rc) {
1381                 ctx->flags |= E2F_FLAG_ABORT;
1382                 return -ENOENT;
1383         }
1384         rc = ext2fs_check_directory(fs, tinode);
1385         if (rc) {
1386                 ctx->flags |= E2F_FLAG_ABORT;
1387                 return -ENOENT;
1388         }
1389
1390         lctx.ctx   = ctx;
1391         lctx.dirinode = tinode;
1392
1393         if (ext2fs_dir_iterate2(fs, tinode, 0, NULL, lfsck_rm_log, &lctx)) {
1394                 ctx->flags |= E2F_FLAG_ABORT;
1395                 rc = -EIO;
1396         }
1397         return rc;
1398 }
1399
1400
1401 /*
1402  * On the mds save the fid and directory information for each file.
1403  * The mds ost tables have already been populated by pass1
1404  */
1405 void e2fsck_pass6_mdt(e2fsck_t ctx)
1406 {
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;
1412         DBT key, data;
1413         DB *outdb = NULL, *dbhdr = NULL;
1414         __u32 compat, rocompat, incompat, index;
1415         int rc, i;
1416
1417         clear_problem_context(&pctx);
1418
1419         memset(&lctx, 0, sizeof(lctx));
1420         lctx.ctx = ctx;
1421
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;
1429                                 goto out;
1430                         }
1431                 }
1432                 rc = ext2fs_get_mem(sizeof(struct lfsck_outdb_info),
1433                                     &ctx->lfsck_oinfo);
1434                 if (rc) {
1435                         ctx->lfsck_oinfo = NULL;
1436                         ctx->flags |= E2F_FLAG_ABORT;
1437                         goto out;
1438                 }
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);
1442                 if (rc) {
1443                         ext2fs_free_mem(&ctx->lfsck_oinfo);
1444                         ctx->lfsck_oinfo = NULL;
1445                         ctx->flags |= E2F_FLAG_ABORT;
1446                         goto out;
1447                 }
1448                 memset(ctx->lfsck_oinfo->ofile_ctx, 0,
1449                        sizeof(struct lfsck_ofile_ctx) * LOV_MAX_OSTS);
1450         }
1451
1452         if (!(ctx->options & E2F_OPT_READONLY))
1453                  lfsck_write_mds_hdrinfo(ctx, ctx->lfsck_oinfo);
1454
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;
1461                 goto out;
1462         }
1463
1464         lctx.outdb = outdb;
1465         lctx.numfiles = 0;
1466         lctx.dot = EXT2_ROOT_INO;
1467         lctx.dotdot = EXT2_ROOT_INO;
1468         lctx.dotfid.f_seq = EXT2_ROOT_INO;
1469
1470         rc = ext2fs_dir_iterate2(fs, EXT2_ROOT_INO,0,NULL,lfsck_mds_dirs,&lctx);
1471         if (rc != 0) {
1472                 fprintf(stderr, "Error iterating directories: %d\n", rc);
1473                 ctx->flags |= E2F_FLAG_ABORT;
1474                 goto out;
1475         }
1476
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);
1480
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;
1492         }
1493
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;
1498                 goto out;
1499         }
1500
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);
1503
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;
1507                 goto out;
1508         }
1509
1510         if (!(ctx->options & E2F_OPT_READONLY)) {
1511                 if (lfsck_rm_file(ctx, EXT2_ROOT_INO, LOV_OBJID)) {
1512                         ctx->flags |= E2F_FLAG_ABORT;
1513                         goto out;
1514                 }
1515 #ifdef LOG_REMOVAL
1516                 if (lfsck_remove_mds_logs(ctx)) {
1517                         ctx->flags |= E2F_FLAG_ABORT;
1518                         return;
1519                 }
1520 #endif
1521         }
1522
1523         rc = lfsck_opendb(ctx->lustre_mdsdb, MDS_HDR, &dbhdr, 0, 0, 0);
1524         if (rc != 0) {
1525                 fprintf(stderr, "failure to open database %s: %s\n", MDS_HDR,
1526                         db_strerror(rc));
1527                 ctx->flags |= E2F_FLAG_ABORT;
1528                 goto out;
1529         }
1530
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);
1539         if (rc != 0) {
1540                 fprintf(stderr, "error: db put %s: %s\n", MDS_HDR,
1541                         db_strerror(rc));
1542                 ctx->flags |= E2F_FLAG_ABORT;
1543                 goto out;
1544         }
1545 out:
1546         if (dbhdr)
1547                 dbhdr->close(dbhdr, 0);
1548         if (outdb)
1549                 outdb->close(outdb, 0);
1550 }
1551
1552 /* If lfsck checking requested then gather the data */
1553 void e2fsck_pass6(e2fsck_t ctx)
1554 {
1555         if (ctx->lustre_devtype == LUSTRE_NULL)
1556                 return;
1557
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");
1561
1562         fflush(stdout);
1563
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);
1568         else
1569                 fprintf(stderr, "Invalid lustre dev %x\n", ctx->lustre_devtype);
1570
1571         return;
1572 }
1573 #endif /* HAVE_LFSCK */