Whamcloud - gitweb
LU-3569 utils: remove ll_recover_lost_found_obj 77/16477/6
authorLai Siyao <lai.siyao@intel.com>
Tue, 13 Oct 2015 09:22:40 +0000 (17:22 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Thu, 10 Dec 2015 17:47:51 +0000 (17:47 +0000)
remove obsolete tool ll_recover_lost_found_obj.

Signed-off-by: Fan Yong <fan.yong@intel.com>
Signed-off-by: Lai Siyao <lai.siyao@intel.com>
Signed-off-by: James Simmons <uja.ornl@yahoo.com>
Change-Id: I5d5f33f5c9d68bb1f05d7ab0da6fb2986e873501
Reviewed-on: http://review.whamcloud.com/16477
Tested-by: Jenkins
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/doc/Makefile.am
lustre/doc/ll_decode_filter_fid.8
lustre/doc/lustre.7
lustre/tests/conf-sanity.sh
lustre/utils/.gitignore
lustre/utils/Makefile.am
lustre/utils/ll_recover_lost_found_objs.c [deleted file]

index eb98b01..9ab9b0d 100644 (file)
@@ -38,9 +38,8 @@
 
 MANFILES = lustre.7 lfs.1 mount.lustre.8 lctl.8 lnetctl.8 \
        llverdev.8 llbackup.8 llapi_quotactl.3 llobdstat.8 llstat.8 \
-       plot-llstat.8 l_getgroups.8 lst.8 routerstat.8 \
-       ll_recover_lost_found_objs.8 llog_reader.8 llapi_file_open.3 \
-       llapi_file_create.3 llapi_file_get_stripe.3 \
+       plot-llstat.8 l_getgroups.8 lst.8 routerstat.8 llog_reader.8 \
+       llapi_file_open.3 llapi_file_create.3 llapi_file_get_stripe.3 \
        lustre_rsync.8 lfs_migrate.1 lhbadm.8 ldev.8 ldev.conf.5 nids.5 \
        lfs-hsm.1 llapi_hsm_state_get.3 llapi_hsm_state_set.3 \
        lustre_routes_config.8 lustre_routes_conversion.8 \
index a436a52..b3ff422 100644 (file)
@@ -20,12 +20,6 @@ modified by Lustre after that time.
 .PP
 The OST object ID (objid) is useful in case of OST directory corruption,
 though normally the
-.BR ll_recover_lost_found_objs (8)
-utility is able to reconstruct the entire OST object directory hierarchy.
-The MDS FID can be useful to determine which MDS inode an OST object
-is (or was) used by.  The stripe index can be used in conjunction with
-other OST objects to reconstruct the layout of a file even if the MDT
-inode was lost.
 .SH EXAMPLE
 .fi
 root@oss1# cd /mnt/ost/lost+found
@@ -56,4 +50,3 @@ The idx field shows the stripe number of this OST object in the Lustre
 RAID-0 striped file.
 .SH SEE ALSO
 .BR lustre (7),
-.BR ll_recover_lost_found_objs (8)
index 3e05ff6..a8f013a 100644 (file)
@@ -54,7 +54,7 @@ A low-level interface to control various aspects of Lustre
 .TP
 .BR lfs (1)
 A user-level interface to control Lustre-specific information for
-individual files. 
+individual files.
 .B lustre_config.sh
 Format multiple Lustre targets simultaneously from definitions in a CSV
 file.
@@ -62,7 +62,7 @@ file.
 Please report all bugs https://jira.hpdd.intel.com/
 .SH AVAILABILITY
 .B The
-.BR Lustre (7) 
+.BR Lustre (7)
 filesystem package is available via
 .br
 https://downloads.hpdd.intel.com/
@@ -76,7 +76,6 @@ https://downloads.hpdd.intel.com/
 .BR liblustreapi (7),
 .BR l_getgroups (8),
 .BR llstat (8),
-.BR ll_recover_lost_found_objs (8),
 .BR llverdev (8),
 .BR lst (8),
 .BR llobdstat (8),
index 41909f1..30eb1ff 100644 (file)
@@ -3692,29 +3692,18 @@ test_52() {
        do_node $ost1node 'mv '$objects' '${ost1mnt}'/lost+found'
        [ $? -eq 0 ] || { error "Unable to move objects"; return 14; }
 
-       # recover objects dry-run
-       if [ $(lustre_version_code ost1) -ge $(version_code 2.5.56) ]; then
-               echo "ll_recover_lost_found_objs dry_run"
-               do_node $ost1node \
-                       "ll_recover_lost_found_objs -n -d $ost1mnt/O" ||
-                       error "ll_recover_lost_found_objs failed"
-       fi
-
-       # recover objects
-       echo "ll_recover_lost_found_objs fix run"
-       do_node $ost1node "ll_recover_lost_found_objs -d $ost1mnt/lost+found" ||
-                error "ll_recover_lost_found_objs failed"
-
-       # compare restored objects against saved ones
-       diff_files_xattrs $ost1node $ost1tmp/objects $ost1tmp/object_xattrs $objects
-       [ $? -eq 0 ] || error "Unable to diff objects"
-
        do_node $ost1node "umount $ost1mnt" ||
                error "Unable to umount ost1 as ldiskfs"
 
        start_ost || error "Unable to start OST1"
        mount_client $MOUNT || error "Unable to mount client"
 
+       local REPAIRED=$(do_node $ost1node "$LCTL get_param \
+                        -n osd-ldiskfs.$FSNAME-OST0000.oi_scrub" |
+                        awk '/^lf_repa[ri]*ed/ { print $2 }')
+       [ $REPAIRED -gt 0 ] ||
+               error "Some entry under /lost+found should be repaired"
+
        # compare files
        diff_files_xattrs $(hostname) $TMP/files $TMP/file_xattrs $files ||
                error "Unable to diff files"
index 3b8dc53..197a83d 100644 (file)
@@ -19,7 +19,6 @@
 /mount_lustre
 /tunefs_lustre
 /lreplicate
-/ll_recover_lost_found_objs
 /ltrack_stats
 /lustre_rsync
 /ll_decode_filter_fid
index b8afa14..90ef883 100644 (file)
@@ -35,7 +35,7 @@ endif # TESTS
 
 if SERVER
 sbin_PROGRAMS += mkfs.lustre tunefs.lustre llverdev lr_reader \
-       ll_recover_lost_found_objs ll_decode_filter_fid llog_reader
+                ll_decode_filter_fid llog_reader
 endif
 if LIBPTHREAD
 sbin_PROGRAMS += lhsmtool_posix
@@ -61,10 +61,6 @@ lustre_rsync_SOURCES = lustre_rsync.c obd.c lustre_cfg.c lustre_rsync.h
 lustre_rsync_LDADD :=  liblustreapi.a $(LIBPTLCTL) $(LIBREADLINE) $(PTHREAD_LIBS)
 lustre_rsync_DEPENDENCIES := $(LIBPTLCTL) liblustreapi.a
 
-ll_recover_lost_found_objs_SOURCES = ll_recover_lost_found_objs.c
-ll_recover_lost_found_objs_LDADD := $(LIBPTLCTL)
-ll_recover_lost_found_objs_DEPENDENCIES := $(LIBPTLCTL)
-
 if EXT2FS_DEVEL
 EXT2FSLIB = -lext2fs
 E2PLIB = -le2p
diff --git a/lustre/utils/ll_recover_lost_found_objs.c b/lustre/utils/ll_recover_lost_found_objs.c
deleted file mode 100644 (file)
index cd9a6f4..0000000
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, 2014, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/utils/ll_recover_lost_found_objs.c
- *
- * Tool for recovering objects from lost+found that might result from a
- * Lustre OST with a corrupted directory. Running e2fsck will fix the
- * directory, but puts all of the objects into lost+found, where they are
- * inaccessible to Lustre.
- *
- * Author: Kalpak Shah <kalpak.shah@sun.com>
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/xattr.h>
-#include <sys/stat.h>
-
-#include <lustre/lustre_idl.h>
-#include <libcfs/list.h>
-
-#define MAX_GROUPS 64
-
-int verbose;
-bool dry_run;
-
-struct obd_group_info {
-       __u64                   grp_last_id;
-       __u64                   grp_seq;
-       struct list_head        grp_list;
-};
-
-struct list_head grp_info_list;
-
-static void grp_info_list_destroy(struct list_head *list)
-{
-       struct obd_group_info *grp, *tmp;
-
-       list_for_each_entry_safe(grp, tmp, list, grp_list) {
-               list_del_init(&grp->grp_list);
-               free(grp);
-       }
-}
-
-static void usage(char *progname)
-{
-       fprintf(stderr, "Usage: %s [-hnv] -d directory\n"
-               "Recover Lustre OST objects put in lost+found by e2fsck.\n"
-               "\t-d: Check directory, usually '/lost+found' (required).\n"
-               "\t    Alternately, verify object directories under '/O'.\n"
-               "\t-n: Do not modify filesystem, only report changes.\n"
-               "\t-h: Print help message.\n"
-               "\t-v: Print changes verbosely.\n",
-               progname);
-       exit(1);
-}
-
-static int _ll_sprintf(char *buf, size_t size, const char *func, int line,
-                      const char *format, ...)
-{
-        int rc;
-        va_list ap;
-
-        va_start(ap, format);
-        rc = vsnprintf(buf, size, format, ap);
-        if (!(rc > -1 && rc < size)) {
-                fprintf(stderr,
-                        "error: %s:%d: path \"", func, line);
-                vfprintf(stderr, format, ap);
-                va_end(ap);
-                fprintf(stderr, "\" is too long\n");
-                return 1;
-        }
-        va_end(ap);
-        return 0;
-}
-
-#define ll_sprintf(buf, size, format, ...) \
-        _ll_sprintf(buf, size, __FUNCTION__, __LINE__, format, ## __VA_ARGS__)
-
-static int mkdir_p(const char *dest_path, mode_t mode)
-{
-       struct stat stat_buf;
-       int rc;
-
-       rc = stat(dest_path, &stat_buf);
-       if (rc == 0) {
-               if (S_ISDIR(stat_buf.st_mode))
-                       goto out;
-               if (!S_ISDIR(stat_buf.st_mode)) {
-                       fprintf(stderr, "error: '%s' is not a directory (%o)\n",
-                               dest_path, stat_buf.st_mode);
-                       rc = -ENOTDIR;
-                       goto out;
-               }
-       } else if (errno != ENOENT) {
-               rc = -errno;
-               fprintf(stderr, "error: error checking directory '%s': %s\n",
-                       dest_path, strerror(errno));
-               goto out;
-       }
-
-       if (dry_run) {
-               fprintf(stderr, "dry_run: not creating directory '%s'\n",
-                       dest_path);
-               rc = 0;
-               goto out;
-       }
-
-       rc = mkdir(dest_path, mode);
-       if (rc != 0)
-               fprintf(stderr, "error: creating directory '%s': %s\n",
-                       dest_path, strerror(errno));
-out:
-       return rc;
-}
-
-/* This is returning 0 for an error */
-static __u64 read_last_id(char *file_path)
-{
-       __u64 last_id;
-       int fd;
-       int count;
-
-       fd = open(file_path, O_RDONLY);
-       if (fd < 0) {
-               if (errno != ENOENT)
-                       fprintf(stderr, "error: opening '%s': %s\n",
-                               file_path, strerror(errno));
-               return 0;
-       }
-
-       count = read(fd, &last_id, sizeof(last_id));
-       if (count < 0) {
-               fprintf(stderr, "error: reading file '%s': %s\n",
-                       file_path, strerror(errno));
-               close(fd);
-               return 0;
-       }
-       if (count != sizeof(last_id)) {
-               fprintf(stderr, "error: only read %d bytes from '%s'\n",
-                       count, file_path);
-               close(fd);
-               return 0;
-       }
-
-       close(fd);
-       return le64_to_cpu(last_id);
-}
-
-struct obd_group_info *find_or_create_grp(struct list_head *list, __u64 seq,
-                                         const char *mount)
-{
-       struct obd_group_info   *grp;
-       struct list_head        *entry;
-       char                    tmp_path[PATH_MAX];
-       char                    seq_name[32];
-       int                     retval;
-       __u64                   tmp_last_id;
-
-       list_for_each(entry, list) {
-               grp = (struct obd_group_info *)list_entry(entry,
-                                               struct obd_group_info,
-                                               grp_list);
-               if (grp->grp_seq == seq)
-                       return grp;
-       }
-
-       grp = malloc(sizeof(struct obd_group_info));
-       if (grp == NULL)
-               return NULL;
-
-       sprintf(seq_name, (fid_seq_is_rsvd(seq) ||
-                          fid_seq_is_mdt0(seq)) ? LPU64 : LPX64i,
-                          fid_seq_is_idif(seq) ? 0 : seq);
-
-       /* Check whether the obj dir has been created */
-       if (ll_sprintf(tmp_path, PATH_MAX, "%s/O/%s", mount, seq_name)) {
-               free(grp);
-               return NULL;
-       }
-
-       retval = mkdir_p(tmp_path, 0700);
-       if (retval < 0) {
-               free(grp);
-               fprintf(stderr, "error: creating directory %s: %s\n",
-                       tmp_path, strerror(errno));
-               return NULL;
-       }
-
-       if (ll_sprintf(tmp_path, PATH_MAX, "%s/O/%s/LAST_ID",
-                      mount, seq_name)) {
-               free(grp);
-               return NULL;
-       }
-
-       /*
-        * Object ID needs to be verified against last_id.
-        * LAST_ID file may not be present in the group directory
-        * due to corruption. In case of any error try to recover
-        * as many objects as possible by setting last_id to ~0ULL.
-        */
-       tmp_last_id = read_last_id(tmp_path);
-       if (tmp_last_id == 0)
-               tmp_last_id = ~0ULL;
-       grp->grp_last_id = tmp_last_id;
-       grp->grp_seq = seq;
-
-       list_add(&grp->grp_list, list);
-       return grp;
-}
-
-static unsigned filetype_dir_table[] = {
-        [0]= DT_UNKNOWN,
-        [S_IFIFO]= DT_FIFO,
-        [S_IFCHR] = DT_CHR,
-        [S_IFDIR] = DT_DIR,
-        [S_IFBLK] = DT_BLK,
-        [S_IFREG] = DT_REG,
-        [S_IFLNK] = DT_LNK,
-        [S_IFSOCK]= DT_SOCK,
-#if defined(DT_DOOR) && defined(S_IFDOOR)
-        [S_IFDOOR]= DT_DOOR,
-#endif
-};
-
-static int traverse_lost_found(char *src_dir, const char *mount_path)
-{
-       DIR *dir_ptr;
-       struct lustre_mdt_attrs lma;
-       struct dirent64 *dirent;
-       __u64 ff_seq, ff_objid;
-        char *file_path;
-        char dest_path[PATH_MAX];
-        struct stat st;
-        int obj_exists, xattr_len;
-        int len, ret = 0, error = 0;
-       char seq_name[32];
-       char obj_name[32];
-       struct obd_group_info *grp_info;
-
-        len = strlen(src_dir);
-
-        dir_ptr = opendir(src_dir);
-        if (!dir_ptr) {
-                fprintf(stderr, "error: opening directory: %s\n",
-                        strerror(errno));
-                return 1;
-        }
-
-        while ((dirent = readdir64(dir_ptr)) != NULL) {
-                if (!strcmp(dirent->d_name, ".") ||
-                    !strcmp(dirent->d_name, ".."))
-                        continue;
-
-                src_dir[len] = 0;
-                if ((len + strlen(dirent->d_name) + 2) > PATH_MAX) {
-                        fprintf(stderr, "error: %s/%s: path too long\n",
-                                src_dir, dirent->d_name);
-                        break;
-                }
-                strcat(src_dir, "/");
-                strcat(src_dir, dirent->d_name);
-
-                if (dirent->d_type == DT_UNKNOWN) {
-                        ret = stat(src_dir, &st);
-                        if (ret == -1) {
-                                fprintf(stderr,
-                                        "error: stating %s: %s\n",
-                                        src_dir, strerror(errno));
-                                continue;
-                        }
-                        dirent->d_type = filetype_dir_table[st.st_mode &
-                                                            S_IFMT];
-                        if (dirent->d_type == DT_UNKNOWN) {
-                                fprintf(stderr,
-                                        "error: %s of unknown type 0%o\n",
-                                        src_dir, st.st_mode);
-                                continue;
-                        }
-                }
-
-                switch(dirent->d_type) {
-                case DT_DIR:
-                ret = traverse_lost_found(src_dir, mount_path);
-                if (ret) {
-                        closedir(dir_ptr);
-                        return ret;
-                }
-                break;
-
-               case DT_REG:
-               file_path = src_dir;
-               xattr_len = getxattr(file_path, "trusted.lma",
-                                    (void *)&lma, sizeof(lma));
-               if (xattr_len == -1 || xattr_len < sizeof(lma)) {
-                       struct filter_fid_old   ff;
-
-                       /* try old filter_fid EA */
-                       xattr_len = getxattr(file_path, "trusted.fid",
-                                            (void *)&ff, sizeof(ff));
-                       /* It's very much possible that we don't find any
-                        * FID on precreated or unused objects or LAST_ID.
-                        * The xattr needs to hold the full filter_fid_old
-                        * with the OID/parent to be useful. */
-                       if (xattr_len == -1 || xattr_len < sizeof(ff))
-                               continue;
-
-                       ff_seq = le64_to_cpu(ff.ff_seq);
-                       ff_objid = le64_to_cpu(ff.ff_objid);
-                       if (verbose)
-                               printf(DOSTID": ", ff_seq, ff_objid);
-               } else {
-                       if (verbose)
-                               printf(DFID": ", PFID(&lma.lma_self_fid));
-                       ff_seq = le64_to_cpu(lma.lma_self_fid.f_seq);
-                       ff_objid = le32_to_cpu(lma.lma_self_fid.f_oid);
-               }
-
-               sprintf(seq_name, (fid_seq_is_rsvd(ff_seq) ||
-                                  fid_seq_is_mdt0(ff_seq)) ? LPU64 : LPX64i,
-                       fid_seq_is_idif(ff_seq) ? 0 : ff_seq);
-
-               /* LAST_ID uses OID = 0.  It will be regenerated later. */
-               if (ff_objid == 0) {
-                       if (verbose)
-                               printf("'%s': LAST_ID\n", file_path);
-                       continue;
-               }
-
-               sprintf(obj_name, (fid_seq_is_rsvd(ff_seq) ||
-                                  fid_seq_is_mdt0(ff_seq) ||
-                                  fid_seq_is_idif(ff_seq)) ?
-                                  LPU64 : LPX64i, ff_objid);
-
-               grp_info = find_or_create_grp(&grp_info_list, ff_seq,
-                                             mount_path);
-               if (grp_info == NULL) {
-                       closedir(dir_ptr);
-                       return 1;
-               }
-
-               /* Might need to create the parent directory for this object */
-               if (ll_sprintf(dest_path, PATH_MAX, "%s/O/%s/d"LPU64,
-                               mount_path, seq_name, ff_objid % 32)) {
-                       closedir(dir_ptr);
-                       return 1;
-               }
-
-               /* The O/{seq} directory was created in find_or_create_grp() */
-               ret = mkdir_p(dest_path, 0700);
-               if (ret < 0) {
-                       closedir(dir_ptr);
-                       return ret;
-               }
-
-               if (ff_objid > grp_info->grp_last_id) {
-                       fprintf(stderr, "error: file skipped because object ID "
-                               "greater than LAST_ID\nFilename: %s\n"
-                               "Group: "LPU64"\nObjectid: "LPU64"\n"
-                               "LAST_ID: "LPU64, file_path, ff_seq, ff_objid,
-                               grp_info->grp_last_id);
-                       continue;
-               }
-
-               /* move file from lost+found to proper object directory */
-               if (ll_sprintf(dest_path, PATH_MAX,
-                               "%s/O/%s/d"LPU64"/%s", mount_path,
-                               seq_name, ff_objid % 32, obj_name)) {
-                       closedir(dir_ptr);
-                       return 1;
-               }
-
-               /* Source and destination are the same file, do nothing. */
-               if (strcmp(file_path, dest_path) == 0) {
-                       if (verbose)
-                               printf("'%s': OK\n", file_path);
-                       continue;
-               }
-
-               obj_exists = 1;
-               ret = stat(dest_path, &st);
-               if (ret == 0) {
-                       if (st.st_size == 0)
-                               obj_exists = 0;
-               } else {
-                       if (errno != ENOENT)
-                               fprintf(stderr, "warning: stat for %s: %s\n",
-                                       dest_path, strerror(errno));
-                       obj_exists = 0;
-               }
-
-               if (obj_exists) {
-                       fprintf(dry_run ? stdout : stderr,
-                               "%s: '%s' exists, will not replace with '%s'\n",
-                               dry_run ? "dry_run" : "error",
-                               dest_path, file_path);
-                       continue;
-               }
-               if (dry_run) {
-                       printf("dry_run: not renaming '%s' to '%s'\n",
-                              file_path, dest_path);
-                       continue;
-               }
-               if (rename(file_path, dest_path) < 0) {
-                       fprintf(stderr, "error: rename failed for '%s': %s\n",
-                               file_path, strerror(errno));
-                       error++;
-                       continue;
-               }
-
-               printf("object '%s' restored.\n", dest_path);
-               break;
-               }
-       }
-
-       closedir(dir_ptr);
-
-       return error;
-}
-
-/*
- * If LAST_ID file is not present in some group then restore it with the highest
- * object ID found in that group. By the time we come here all possible objects
- * have been restored.
- */
-static int check_last_id(const char *mount_path)
-{
-        char lastid_path[PATH_MAX];
-        char dirname[PATH_MAX], subdirname[PATH_MAX];
-        DIR *groupdir, *subdir;
-        struct stat st;
-        struct dirent *dirent;
-        __u64 group;
-        __u64 max_objid;
-        int fd;
-        int ret;
-
-        for (group = 0; group < MAX_GROUPS; group++) {
-                max_objid = 0;
-
-                if (ll_sprintf(dirname, PATH_MAX, "%s/O/"LPU64,
-                               mount_path, group))
-                        return 1;
-                if (ll_sprintf(lastid_path, PATH_MAX, "%s/LAST_ID", dirname))
-                        return 1;
-
-                if (stat(lastid_path, &st) == 0)
-                        continue;
-
-                groupdir = opendir(dirname);
-                if (groupdir == NULL) {
-                        if (errno != ENOENT)
-                                fprintf(stderr, "error: opening %s: %s\n",
-                                        dirname, strerror(errno));
-                        continue;
-                }
-
-                while ((dirent = readdir(groupdir)) != NULL) {
-                        if (!strcmp(dirent->d_name, ".") ||
-                            !strcmp(dirent->d_name, ".."))
-                                continue;
-
-                        if (ll_sprintf(subdirname, PATH_MAX, "%s/%s",
-                                       dirname, dirent->d_name)) {
-                                closedir(groupdir);
-                                return 1;
-                        }
-                        subdir = opendir(subdirname);
-                        if (subdir == NULL) {
-                                fprintf(stderr, "error: opening %s: %s\n",
-                                        subdirname, strerror(errno));
-                                continue;
-                        }
-
-                        while ((dirent = readdir(subdir)) != NULL) {
-                                __u64 objid;
-                                char *end;
-
-                                if (!strcmp(dirent->d_name, ".") ||
-                                    !strcmp(dirent->d_name, ".."))
-                                        continue;
-
-                                objid = strtoull(dirent->d_name, &end, 0);
-                                if (end == dirent->d_name || *end != 0) {
-                                        fprintf(stderr, "error: unknown object"
-                                                "ID %s/%s\n", subdirname,
-                                                dirent->d_name);
-                                        continue;
-                                }
-                                if (objid > max_objid)
-                                       max_objid = objid;
-                        }
-                        closedir(subdir);
-                }
-                closedir(groupdir);
-
-               if (dry_run) {
-                       fprintf(stderr, "dry_run: not updating '%s' to "
-                               LPU64"\n", lastid_path, max_objid);
-                       return 0;
-               }
-               fd = open(lastid_path, O_RDWR | O_CREAT, 0700);
-               if (fd < 0) {
-                       fprintf(stderr, "error: open '%s' failed: %s\n",
-                               lastid_path, strerror(errno));
-                       return 1;
-               }
-
-               max_objid = cpu_to_le64(max_objid);
-               ret = write(fd, &max_objid, sizeof(__u64));
-               if (ret < sizeof(__u64)) {
-                       fprintf(stderr, "error: write '%s' failed: %s\n",
-                               lastid_path, strerror(errno));
-                       close(fd);
-                       return 1;
-               }
-
-               close(fd);
-       }
-
-       return 0;
-}
-
-int main(int argc, char **argv)
-{
-       char *progname;
-       char src_dir[PATH_MAX] = "";
-       char mount_path[PATH_MAX];
-       char tmp_path[PATH_MAX];
-       int rc;
-       int c;
-
-       progname = strrchr(argv[0], '/');
-       if (progname++ == NULL)
-               progname = argv[0];
-
-       while ((c = getopt(argc, argv, "d:hnv")) != EOF) {
-                switch (c) {
-                case 'd':
-                        if (chdir(optarg)) {
-                                fprintf(stderr, "error: chdir to %s: %s\n",
-                                        optarg, strerror(errno));
-                                return 1;
-                        }
-                        if (getcwd(src_dir, PATH_MAX) == NULL) {
-                                fprintf(stderr,
-                                        "error: getcwd of lost+found: %s\n",
-                                        strerror(errno));
-                                return 1;
-                        }
-                        if (chdir("..")) {
-                                fprintf(stderr, "error: chdir to \"..\": %s\n",
-                                        strerror(errno));
-                                return 1;
-                        }
-                        if (getcwd(mount_path, PATH_MAX) == NULL) {
-                                fprintf(stderr,
-                                        "error: getcwd of mount point: %s\n",
-                                        strerror(errno));
-                                return 1;
-                        }
-                        if (!strcmp(src_dir, mount_path)) {
-                                fprintf(stderr,
-                                        "error: root directory is detected\n");
-                                return 1;
-                        }
-                       fprintf(stdout, "%s: %sscan directory path: %s\n",
-                               progname, dry_run ? "read_only " : "", src_dir);
-                       break;
-               case 'n':
-                       dry_run = true;
-                       break;
-               case 'v':
-                       verbose = true;
-                       break;
-                case 'h':
-                        usage(progname);
-                default:
-                        fprintf(stderr, "%s: bad option '%c'\n",
-                                progname, c);
-                        usage(progname);
-                }
-        }
-
-        if (src_dir[0] == 0)
-                usage(progname);
-
-        /* Check if 'O' directory exists and create it if needed */
-        if (ll_sprintf(tmp_path, PATH_MAX, "%s/O",  mount_path))
-                return 1;
-
-       rc = mkdir_p(tmp_path, 0700);
-       if (rc == -1) {
-               fprintf(stderr, "error: creating objects directory %s:"
-                       " %s\n", tmp_path, strerror(errno));
-               return 1;
-        }
-
-       INIT_LIST_HEAD(&grp_info_list);
-       rc = traverse_lost_found(src_dir, mount_path);
-       if (rc) {
-               fprintf(stderr, "error: traversing lost+found looking for "
-                       "orphan objects.\n");
-               goto grp_destory;
-       }
-
-       rc = check_last_id(mount_path);
-       if (rc)
-               fprintf(stderr, "error: while checking/restoring LAST_ID.\n");
-
-grp_destory:
-       grp_info_list_destroy(&grp_info_list);
-
-       printf("%s: scan finished: rc = %d\n", progname, rc);
-       return rc;
-}