]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fsck: use libmount for filesystem list
authorKarel Zak <kzak@redhat.com>
Wed, 15 Feb 2012 13:07:06 +0000 (14:07 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 20 Mar 2012 10:22:08 +0000 (11:22 +0100)
libmount provides all necessary functionality required in fsck for
work with filesystems descriptions.

This patch seems large and invasive, because removes fsck_fs struct,
changes:

  - use libmnt to parse fstab
  - use libmnt_fs from libmount
  - replace "fs->" with mnt_fs_* or fs_* functions

Signed-off-by: Karel Zak <kzak@redhat.com>
fsck/Makefile.am
fsck/fsck.c
fsck/fsck.h

index ebb5b672cc01d149b8c8899dd7c0d4b00ac6365d..a197fd558bc5b7035a0125edaed70f5d6a4564d4 100644 (file)
@@ -4,9 +4,6 @@ sbin_PROGRAMS = fsck
 dist_man_MANS = fsck.8
 
 fsck_SOURCES = fsck.c fsck.h $(top_srcdir)/lib/ismounted.c \
-              $(top_srcdir)/lib/fsprobe.c $(top_srcdir)/lib/canonicalize.c
-fsck_LDADD =
-fsck_CFLAGS = $(AM_CFLAGS)
-
-fsck_LDADD += $(ul_libblkid_la)
-fsck_CFLAGS += -I$(ul_libblkid_incdir)
+              $(top_srcdir)/lib/fsprobe.c
+fsck_LDADD = $(ul_libmount_la) $(ul_libblkid_la)
+fsck_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) -I$(ul_libblkid_incdir)
index 903192917e5a16a73b6cf55397a67d7eed0f2329..903ee71654c561f90fd9541c88964122c86f076d 100644 (file)
@@ -46,6 +46,7 @@
 #include <blkid.h>
 
 #include "fsprobe.h"
+#include <libmount.h>
 
 #include "nls.h"
 #include "pathnames.h"
 #include "xalloc.h"
 
 static const char *ignored_types[] = {
-       "9p",
-       "afs",
-       "autofs",
-       "binfmt_misc",
-       "cgroup",
-       "cifs",
-       "cpuset",
-       "debugfs",
-       "devfs",
-       "devpts",
-       "devtmpfs",
-       "dlmfs",
-       "fusectl",
-       "fuse.gvfs-fuse-daemon",
-       "hugetlbfs",
        "ignore",
        "iso9660",
-       "mqueue"
-       "ncpfs",
-       "nfs",
-       "proc",
-       "rpc_pipefs",
-       "securityfs",
-       "smbfs",
-       "spufs",
        "sw",
-       "swap",
-       "sysfs",
-       "tmpfs",
        NULL
 };
 
@@ -129,11 +104,15 @@ int max_running = 0;
 volatile int cancel_requested = 0;
 int kill_sent = 0;
 char *fstype = NULL;
-struct fs_info *filesys_info = NULL, *filesys_last = NULL;
 struct fsck_instance *instance_list;
 const char fsck_prefix_path[] = FS_SEARCH_PATH;
 char *fsck_path = 0;
 
+/* parsed fstab */
+static struct libmnt_table *fstab;
+
+static int count_slaves(dev_t disk);
+
 static char *string_copy(const char *s)
 {
        char    *ret;
@@ -157,99 +136,92 @@ static int string_to_int(const char *s)
                return (int) l;
 }
 
-static int ignore(struct fs_info *);
+static int ignore(struct libmnt_fs *);
 
-static char *skip_over_blank(char *cp)
+static struct fsck_fs_data *fs_create_data(struct libmnt_fs *fs)
 {
-       while (*cp && isspace(*cp))
-               cp++;
-       return cp;
-}
+       struct fsck_fs_data *data = mnt_fs_get_userdata(fs);
 
-static char *skip_over_word(char *cp)
-{
-       while (*cp && !isspace(*cp))
-               cp++;
-       return cp;
+       if (!data) {
+               data = xcalloc(1, sizeof(*data));
+               mnt_fs_set_userdata(fs, data);
+       }
+       return data;
 }
 
-static void strip_line(char *line)
+/*
+ * fs from fstab might contains real device name as well as symlink,
+ * LABEL or UUID, this function returns canonicalized result.
+ */
+static const char *fs_get_device(struct libmnt_fs *fs)
 {
-       char    *p;
+       struct fsck_fs_data *data = mnt_fs_get_userdata(fs);
 
-       while (*line) {
-               p = line + strlen(line) - 1;
-               if ((*p == '\n') || (*p == '\r'))
-                       *p = 0;
-               else
-                       break;
+       if (!data || !data->eval_device) {
+               const char *spec = mnt_fs_get_source(fs);
+
+               if (!data)
+                       data = fs_create_data(fs);
+
+               data->eval_device = 1;
+               data->device = mnt_resolve_spec(spec, mnt_table_get_cache(fstab));
+               if (!data->device)
+                       data->device = string_copy(spec);
        }
+
+       return data->device;
 }
 
-static char *parse_word(char **buf)
+static dev_t fs_get_disk(struct libmnt_fs *fs, int check)
 {
-       char *word, *next;
+       struct fsck_fs_data *data;
+       const char *device;
+       struct stat st;
+
+       data = mnt_fs_get_userdata(fs);
+       if (data && data->disk)
+               return data->disk;
 
-       word = *buf;
-       if (*word == 0)
+       if (!check)
                return 0;
 
-       word = skip_over_blank(word);
-       next = skip_over_word(word);
-       if (*next)
-               *next++ = 0;
-       *buf = next;
-       return word;
-}
+       if (mnt_fs_is_netfs(fs) || mnt_fs_is_pseudofs(fs))
+               return 0;
 
-static void parse_escape(char *word)
-{
-       char    *p, *q;
-       int     ac, i;
+       device = fs_get_device(fs);
+       if (!device)
+               return 0;
 
-       if (!word)
-               return;
+       data = fs_create_data(fs);
 
-       for (p = word, q = word; *p; p++, q++) {
-               *q = *p;
-               if (*p != '\\')
-                       continue;
-               if (*++p == 0)
-                       break;
-               if (*p == 't') {
-                       *q = '\t';
-                       continue;
-               }
-               if (*p == 'n') {
-                       *q = '\n';
-                       continue;
-               }
-               if (!isdigit(*p)) {
-                       *q = *p;
-                       continue;
-               }
-               ac = 0;
-               for (i = 0; i < 3; i++, p++) {
-                       if (!isdigit(*p))
-                               break;
-                       ac = (ac * 8) + (*p - '0');
-               }
-               *q = ac;
-               p--;
+       if (!stat(device, &st) &&
+           !blkid_devno_to_wholedisk(st.st_rdev, NULL, 0, &data->disk)) {
+
+               if (data->disk)
+                       data->stacked = count_slaves(data->disk) > 0 ? 1 : 0;
+               return data->disk;
        }
-       *q = 0;
+       return 0;
 }
 
-static dev_t get_disk(const char *device)
+static int fs_is_stacked(struct libmnt_fs *fs)
 {
-       struct stat st;
-       dev_t disk;
+       struct fsck_fs_data *data = mnt_fs_get_userdata(fs);
+       return data ? data->stacked : 0;
+}
 
-       if (!stat(device, &st) &&
-           !blkid_devno_to_wholedisk(st.st_rdev, NULL, 0, &disk))
-               return disk;
+static int fs_is_done(struct libmnt_fs *fs)
+{
+       struct fsck_fs_data *data = mnt_fs_get_userdata(fs);
+       return data ? data->done : 0;
+}
 
-       return 0;
+static void fs_set_done(struct libmnt_fs *fs)
+{
+       struct fsck_fs_data *data = fs_create_data(fs);
+
+       if (data)
+               data->done = 1;
 }
 
 static int is_irrotational_disk(dev_t disk)
@@ -258,6 +230,7 @@ static int is_irrotational_disk(dev_t disk)
        FILE *f;
        int rc, x;
 
+
        rc = snprintf(path, sizeof(path),
                        "/sys/dev/block/%d:%d/queue/rotational",
                        major(disk), minor(disk));
@@ -283,7 +256,7 @@ static int is_irrotational_disk(dev_t disk)
 
 static void lock_disk(struct fsck_instance *inst)
 {
-       dev_t disk = inst->fs->disk ? inst->fs->disk : get_disk(inst->fs->device);
+       dev_t disk = fs_get_disk(inst->fs, 1);
        char *diskname;
 
        if (!disk || is_irrotational_disk(disk))
@@ -340,162 +313,96 @@ static void free_instance(struct fsck_instance *i)
        return;
 }
 
-static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
-                                       const char *type, const char *opts,
-                                       int freq, int passno)
+static struct libmnt_fs *add_dummy_fs(const char *device)
 {
-       struct fs_info *fs;
-
-       fs = xmalloc(sizeof(struct fs_info));
-
-       fs->device = string_copy(device);
-       fs->mountpt = string_copy(mntpnt);
-       fs->type = string_copy(type);
-       fs->opts = string_copy(opts ? opts : "");
-       fs->freq = freq;
-       fs->passno = passno;
-       fs->flags = 0;
-       fs->next = NULL;
-       fs->disk = 0;
-       fs->stacked = 0;
-
-       if (!filesys_info)
-               filesys_info = fs;
-       else
-               filesys_last->next = fs;
-       filesys_last = fs;
-
-       return fs;
-}
+       struct libmnt_fs *fs = mnt_new_fs();
 
+       if (fs && mnt_fs_set_source(fs, device) == 0 &&
+                 mnt_table_add_fs(fstab, fs) == 0)
+               return fs;
 
+       mnt_free_fs(fs);
+       err(FSCK_EX_ERROR, _("failed to setup description for %s"), device);
+}
 
-static int parse_fstab_line(char *line, struct fs_info **ret_fs)
+static void fs_interpret_type(struct libmnt_fs *fs)
 {
-       char    *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
-       struct fs_info *fs;
-
-       *ret_fs = 0;
-       strip_line(line);
-       cp = line;
-
-       device = parse_word(&cp);
-       if (!device || *device == '#')
-               return 0;       /* Ignore blank lines and comments */
-       mntpnt = parse_word(&cp);
-       type = parse_word(&cp);
-       opts = parse_word(&cp);
-       freq = parse_word(&cp);
-       passno = parse_word(&cp);
-
-       if (!mntpnt || !type)
-               return -1;
-
-       parse_escape(device);
-       parse_escape(mntpnt);
-       parse_escape(type);
-       parse_escape(opts);
-       parse_escape(freq);
-       parse_escape(passno);
+       const char *device;
+       const char *type = mnt_fs_get_fstype(fs);
 
-       dev = fsprobe_get_devname_by_spec(device);
-       if (dev)
-               device = dev;
+       if (type && strcmp(type, "auto") != 0)
+               return;
 
-       if (strchr(type, ','))
-               type = 0;
+       mnt_fs_set_fstype(fs, NULL);
 
-       fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
-                             freq ? atoi(freq) : -1,
-                             passno ? atoi(passno) : -1);
-       free(dev);
+       device = fs_get_device(fs);
+       if (device) {
+               int ambi = 0;
 
-       if (!fs)
-               return -1;
-       *ret_fs = fs;
-       return 0;
+               type = mnt_get_fstype(device, &ambi, mnt_table_get_cache(fstab));
+               if (!ambi)
+                       mnt_fs_set_fstype(fs, type);
+       }
 }
 
-static void interpret_type(struct fs_info *fs)
+static int parser_errcb(struct libmnt_table *tb __attribute__ ((__unused__)),
+                       const char *filename, int line)
 {
-       char    *t;
-
-       if (fs->type && strcmp(fs->type, "auto") != 0)
-               return;
-       t = fsprobe_get_fstype_by_devname(fs->device);
-       if (t) {
-               free(fs->type);
-               fs->type = t;
-       }
+       warnx(_("%s: parse error at line %d -- ignore"), filename, line);
+       return 0;
 }
 
 /*
  * Load the filesystem database from /etc/fstab
  */
-static void load_fs_info(const char *filename)
+static void load_fs_info(void)
 {
-       FILE    *f;
-       char    buf[1024];
-       int     lineno = 0;
-       int     old_fstab = 1;
-       struct fs_info *fs;
-
-       if ((f = fopen(filename, "r")) == NULL) {
-               warn(_("WARNING: couldn't open %s"), filename);
-               return;
-       }
-       while (!feof(f)) {
-               lineno++;
-               if (!fgets(buf, sizeof(buf), f))
-                       break;
-               buf[sizeof(buf)-1] = 0;
-               if (parse_fstab_line(buf, &fs) < 0) {
-                       warnx(_("WARNING: bad format "
-                               "on line %d of %s"), lineno, filename);
-                       continue;
-               }
-               if (!fs)
-                       continue;
-               if (fs->passno < 0)
-                       fs->passno = 0;
-               else
-                       old_fstab = 0;
-       }
+       const char *path;
 
-       fclose(f);
+       mnt_init_debug(0);
 
-       if (old_fstab && filesys_info) {
-               warnx(_(
-               "WARNING: Your /etc/fstab does not contain the fsck passno\n"
-               "       field.  I will kludge around things for you, but you\n"
-               "       should fix your /etc/fstab file as soon as you can.\n"));
+       fstab = mnt_new_table();
+       if (!fstab)
+               err(FSCK_EX_ERROR, ("failed to initialize libmount table"));
 
-               for (fs = filesys_info; fs; fs = fs->next) {
-                       fs->passno = 1;
-               }
+       mnt_table_set_parser_errcb(fstab, parser_errcb);
+       mnt_table_set_cache(fstab, mnt_new_cache());
+
+       errno = 0;
+
+       /*
+        * Let's follow libmount defauls if $FSTAB_FILE is not specified
+        */
+       path = getenv("FSTAB_FILE");
+
+       if (mnt_table_parse_fstab(fstab, path)) {
+               mnt_free_table(fstab);
+               if (!path)
+                       path = mnt_get_fstab_path();
+               if (errno)
+                       warn(_("%s: failed to parse fstab"), path);
+               else
+                       warnx(_("%s: failed to parse fstab"), path);
        }
 }
 
 /* Lookup filesys in /etc/fstab and return the corresponding entry. */
-static struct fs_info *lookup(char *filesys)
+static struct libmnt_fs *lookup(char *spec)
 {
-       struct fs_info *fs;
+       struct libmnt_fs *fs;
 
-       /* No filesys name given. */
-       if (filesys == NULL)
+       if (!spec)
                return NULL;
 
-       for (fs = filesys_info; fs; fs = fs->next) {
-               if (!strcmp(filesys, fs->device) ||
-                   (fs->mountpt && !strcmp(filesys, fs->mountpt)))
-                       break;
-       }
+       fs = mnt_table_find_source(fstab, spec, MNT_ITER_FORWARD);
+       if (!fs)
+               fs = mnt_table_find_target(fstab, spec, MNT_ITER_FORWARD);
 
        return fs;
 }
 
 /* Find fsck program for a given fs type. */
-static char *find_fsck(char *type)
+static char *find_fsck(const char *type)
 {
        char *s;
        const char *tpl;
@@ -532,7 +439,7 @@ static int progress_active(NOARGS)
  * Execute a particular fsck program, and link it into the list of
  * child processes we are waiting for.
  */
-static int execute(const char *type, struct fs_info *fs, int interactive)
+static int execute(const char *type, struct libmnt_fs *fs, int interactive)
 {
        char *s, *argv[80], prog[80];
        int  argc, i;
@@ -567,7 +474,7 @@ static int execute(const char *type, struct fs_info *fs, int interactive)
                }
        }
 
-       argv[argc++] = string_copy(fs->device);
+       argv[argc++] = string_copy(fs_get_device(fs));
        argv[argc] = 0;
 
        s = find_fsck(prog);
@@ -578,14 +485,16 @@ static int execute(const char *type, struct fs_info *fs, int interactive)
        }
 
        if (verbose || noexecute) {
-               printf("[%s (%d) -- %s] ", s, num_running,
-                      fs->mountpt ? fs->mountpt : fs->device);
+               const char *tgt = mnt_fs_get_target(fs);
+
+               if (!tgt)
+                       tgt = fs_get_device(fs);
+               printf("[%s (%d) -- %s] ", s, num_running, tgt);
                for (i=0; i < argc; i++)
                        printf("%s ", argv[i]);
                printf("\n");
        }
 
-
        inst->fs = fs;
        inst->lock = -1;
 
@@ -715,12 +624,12 @@ static struct fsck_instance *wait_one(int flags)
                } else {
                        warnx(_("Warning... %s for device %s exited "
                               "with signal %d."),
-                              inst->prog, inst->fs->device, sig);
+                              inst->prog, fs_get_device(inst->fs), sig);
                        status = FSCK_EX_ERROR;
                }
        } else {
                warnx(_("%s %s: status is %x, should never happen."),
-                      inst->prog, inst->fs->device, status);
+                      inst->prog, fs_get_device(inst->fs), status);
                status = FSCK_EX_ERROR;
        }
        inst->exit_status = status;
@@ -759,7 +668,7 @@ ret_inst:
                instance_list = inst->next;
        if (verbose > 1)
                printf(_("Finished with %s (exit status %d)\n"),
-                      inst->fs->device, inst->exit_status);
+                      fs_get_device(inst->fs), inst->exit_status);
        num_running--;
        return inst;
 }
@@ -799,15 +708,17 @@ static int wait_many(int flags)
  * If the type isn't specified by the user, then use either the type
  * specified in /etc/fstab, or DEFAULT_FSTYPE.
  */
-static int fsck_device(struct fs_info *fs, int interactive)
+static int fsck_device(struct libmnt_fs *fs, int interactive)
 {
        const char *type;
        int retval;
 
-       interpret_type(fs);
+       fs_interpret_type(fs);
+
+       type = mnt_fs_get_fstype(fs);
 
-       if (strcmp(fs->type, "auto") != 0)
-               type = fs->type;
+       if (type && strcmp(type, "auto") != 0)
+               ;
        else if (fstype && strncmp(fstype, "no", 2) &&
            strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&
            !strchr(fstype, ','))
@@ -819,7 +730,7 @@ static int fsck_device(struct fs_info *fs, int interactive)
        retval = execute(type, fs, interactive);
        if (retval) {
                warnx(_("error %d while executing fsck.%s for %s"),
-                       retval, type, fs->device);
+                       retval, type, fs_get_device(fs));
                num_running--;
                return FSCK_EX_ERROR;
        }
@@ -906,7 +817,7 @@ static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
  * This function returns true if a particular option appears in a
  * comma-delimited options list
  */
-static int opt_in_list(const char *opt, char *optlist)
+static int opt_in_list(const char *opt, const char *optlist)
 {
        char    *list, *s;
 
@@ -927,7 +838,7 @@ static int opt_in_list(const char *opt, char *optlist)
 }
 
 /* See if the filesystem matches the criteria given by the -t option */
-static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
+static int fs_match(struct libmnt_fs *fs, struct fs_type_compile *cmp)
 {
        int n, ret = 0, checked_type = 0;
        char *cp;
@@ -938,17 +849,20 @@ static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
        for (n=0; (cp = cmp->list[n]); n++) {
                switch (cmp->type[n]) {
                case FS_TYPE_NORMAL:
+               {
+                       const char *type = mnt_fs_get_fstype(fs);
+
                        checked_type++;
-                       if (strcmp(cp, fs->type) == 0) {
+                       if (type && strcmp(cp, type) == 0)
                                ret = 1;
-                       }
                        break;
+               }
                case FS_TYPE_NEGOPT:
-                       if (opt_in_list(cp, fs->opts))
+                       if (opt_in_list(cp, mnt_fs_get_options(fs)))
                                return 0;
                        break;
                case FS_TYPE_OPT:
-                       if (!opt_in_list(cp, fs->opts))
+                       if (!opt_in_list(cp, mnt_fs_get_options(fs)))
                                return 0;
                        break;
                }
@@ -974,12 +888,17 @@ static int device_exists(const char *device)
        return 1;
 }
 
-static int ignored_type(const char *fstype)
+static int fs_ignored_type(struct libmnt_fs *fs)
 {
-       const char **ip;
+       const char **ip, *type;
+
+       if (mnt_fs_is_netfs(fs) || mnt_fs_is_pseudofs(fs) || mnt_fs_is_swaparea(fs))
+               return 1;
+
+       type = mnt_fs_get_fstype(fs);
 
-       for(ip = ignored_types; *ip; ip++) {
-               if (strcmp(fstype, *ip) == 0)
+       for(ip = ignored_types; type && *ip; ip++) {
+               if (strcmp(type, *ip) == 0)
                        return 1;
        }
 
@@ -987,44 +906,44 @@ static int ignored_type(const char *fstype)
 }
 
 /* Check if we should ignore this filesystem. */
-static int ignore(struct fs_info *fs)
+static int ignore(struct libmnt_fs *fs)
 {
-       const char **ip;
+       const char **ip, *type;
        int wanted = 0;
 
        /*
         * If the pass number is 0, ignore it.
         */
-       if (fs->passno == 0)
+       if (mnt_fs_get_passno(fs) == 0)
                return 1;
 
        /*
         * If this is a bind mount, ignore it.
         */
-       if (opt_in_list("bind", fs->opts)) {
+       if (opt_in_list("bind", mnt_fs_get_options(fs))) {
                warnx(_("%s: skipping bad line in /etc/fstab: "
                        "bind mount with nonzero fsck pass number"),
-                       fs->mountpt);
+                       mnt_fs_get_target(fs));
                return 1;
        }
 
        /*
         * ignore devices that don't exist and have the "nofail" mount option
         */
-       if (!device_exists(fs->device)) {
-               if (opt_in_list("nofail", fs->opts)) {
+       if (!device_exists(fs_get_device(fs))) {
+               if (opt_in_list("nofail", mnt_fs_get_options(fs))) {
                        if (verbose)
                                printf(_("%s: skipping nonexistent device\n"),
-                                                               fs->device);
+                                                       fs_get_device(fs));
                        return 1;
                }
                if (verbose)
                        printf(_("%s: nonexistent device (\"nofail\" fstab "
                                 "option may be used to skip this device)\n"),
-                                fs->device);
+                               fs_get_device(fs));
        }
 
-       interpret_type(fs);
+       fs_interpret_type(fs);
 
        /*
         * If a specific fstype is specified, and it doesn't match,
@@ -1033,25 +952,26 @@ static int ignore(struct fs_info *fs)
        if (!fs_match(fs, &fs_type_compiled))
                return 1;
 
+       type = mnt_fs_get_fstype(fs);
+       if (!type)
+               return 0;               /* should not happen */
+
        /* Are we ignoring this type? */
-       if (fs->type && ignored_type(fs->type))
+       if (fs_ignored_type(fs))
                return 1;
 
-       if (!fs->type)
-               return 0;               /* should not happen */
-
        /* Do we really really want to check this fs? */
        for(ip = really_wanted; *ip; ip++)
-               if (strcmp(fs->type, *ip) == 0) {
+               if (strcmp(type, *ip) == 0) {
                        wanted = 1;
                        break;
                }
 
        /* See if the <fsck.fs> program is available. */
-       if (find_fsck(fs->type) == NULL) {
+       if (find_fsck(type) == NULL) {
                if (wanted)
                        warnx(_("cannot check %s: fsck.%s not found"),
-                               fs->device, fs->type);
+                               fs_get_device(fs), type);
                return 1;
        }
 
@@ -1093,22 +1013,19 @@ static int count_slaves(dev_t disk)
  * Returns TRUE if a partition on the same disk is already being
  * checked.
  */
-static int disk_already_active(struct fs_info *fs)
+static int disk_already_active(struct libmnt_fs *fs)
 {
        struct fsck_instance *inst;
+       dev_t disk;
 
        if (force_all_parallel)
                return 0;
 
-       if (instance_list && instance_list->fs->stacked)
+       if (instance_list && fs_is_stacked(instance_list->fs))
                /* any instance for a stacked device is already running */
                return 1;
 
-       if (!fs->disk) {
-               fs->disk = get_disk(fs->device);
-               if (fs->disk)
-                       fs->stacked = count_slaves(fs->disk);
-       }
+       disk = fs_get_disk(fs, 1);
 
        /*
         * If we don't know the base device, assume that the device is
@@ -1116,86 +1033,105 @@ static int disk_already_active(struct fs_info *fs)
         *
         * Don't check a stacked device with any other disk too.
         */
-       if (!fs->disk || fs->stacked)
+       if (!disk || fs_is_stacked(fs))
                return (instance_list != 0);
 
        for (inst = instance_list; inst; inst = inst->next) {
-               if (!inst->fs->disk || fs->disk == inst->fs->disk)
+               dev_t idisk = fs_get_disk(inst->fs, 0);
+
+               if (!idisk || disk == idisk)
                        return 1;
        }
        return 0;
 }
 
 /* Check all file systems, using the /etc/fstab table. */
-static int check_all(NOARGS)
+static int check_all(void)
 {
-       struct fs_info *fs = NULL;
-       int status = FSCK_EX_OK;
        int not_done_yet = 1;
        int passno = 1;
        int pass_done;
+       int status = FSCK_EX_OK;
 
-       if (verbose)
-               fputs(_("Checking all file systems.\n"), stdout);
+       struct libmnt_fs *fs;
+       struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_FORWARD);
+
+       if (!itr)
+               err(FSCK_EX_ERROR, _("failed to allocate iterator"));
 
        /*
         * Do an initial scan over the filesystem; mark filesystems
         * which should be ignored as done, and resolve any "auto"
         * filesystem types (done as a side-effect of calling ignore()).
         */
-       for (fs = filesys_info; fs; fs = fs->next) {
-               if (ignore(fs))
-                       fs->flags |= FLAG_DONE;
+       while (mnt_table_next_fs(fstab, itr, &fs) == 0) {
+               if (ignore(fs)) {
+                       fs_set_done(fs);
+                       continue;
+               }
        }
 
+       if (verbose)
+               fputs(_("Checking all file systems.\n"), stdout);
+
        /*
         * Find and check the root filesystem.
         */
        if (!parallel_root) {
-               for (fs = filesys_info; fs; fs = fs->next) {
-                       if (!strcmp(fs->mountpt, "/"))
-                               break;
-               }
+               fs = mnt_table_find_target(fstab, "/", MNT_ITER_FORWARD);
                if (fs) {
-                       if (!skip_root && !ignore(fs) &&
-                           !(ignore_mounted && is_mounted(fs->device))) {
+                       if (!skip_root &&
+                           !fs_is_done(fs) &&
+                           !(ignore_mounted && is_mounted(fs_get_device(fs)))) {
                                status |= fsck_device(fs, 1);
                                status |= wait_many(FLAG_WAIT_ALL);
-                               if (status > FSCK_EX_NONDESTRUCT)
+                               if (status > FSCK_EX_NONDESTRUCT) {
+                                       mnt_free_iter(itr);
                                        return status;
+                               }
                        }
-                       fs->flags |= FLAG_DONE;
+                       fs_set_done(fs);
                }
        }
+
        /*
         * This is for the bone-headed user who enters the root
         * filesystem twice.  Skip root will skep all root entries.
         */
-       if (skip_root)
-               for (fs = filesys_info; fs; fs = fs->next)
-                       if (!strcmp(fs->mountpt, "/"))
-                               fs->flags |= FLAG_DONE;
+       if (skip_root) {
+               mnt_reset_iter(itr, MNT_ITER_FORWARD);
+
+               while(mnt_table_next_fs(fstab, itr, &fs) == 0) {
+                       const char *tgt = mnt_fs_get_target(fs);
+
+                       if (tgt && strcmp(tgt, "/") == 0)
+                               fs_set_done(fs);
+               }
+       }
 
        while (not_done_yet) {
                not_done_yet = 0;
                pass_done = 1;
 
-               for (fs = filesys_info; fs; fs = fs->next) {
+               mnt_reset_iter(itr, MNT_ITER_FORWARD);
+
+               while(mnt_table_next_fs(fstab, itr, &fs) == 0) {
+
                        if (cancel_requested)
                                break;
-                       if (fs->flags & FLAG_DONE)
+                       if (fs_is_done(fs))
                                continue;
                        /*
                         * If the filesystem's pass number is higher
                         * than the current pass number, then we don't
                         * do it yet.
                         */
-                       if (fs->passno > passno) {
+                       if (mnt_fs_get_passno(fs) > passno) {
                                not_done_yet++;
                                continue;
                        }
-                       if (ignore_mounted && is_mounted(fs->device)) {
-                               fs->flags |= FLAG_DONE;
+                       if (ignore_mounted && is_mounted(fs_get_device(fs))) {
+                               fs_set_done(fs);
                                continue;
                        }
                        /*
@@ -1211,7 +1147,7 @@ static int check_all(NOARGS)
                         * Spawn off the fsck process
                         */
                        status |= fsck_device(fs, serialize);
-                       fs->flags |= FLAG_DONE;
+                       fs_set_done(fs);
 
                        /*
                         * Only do one filesystem at a time, or if we
@@ -1228,6 +1164,7 @@ static int check_all(NOARGS)
                        break;
                if (verbose > 1)
                        printf(_("--waiting-- (pass %d)\n"), passno);
+
                status |= wait_many(pass_done ? FLAG_WAIT_ALL :
                                    FLAG_WAIT_ATLEAST_ONE);
                if (pass_done) {
@@ -1237,11 +1174,14 @@ static int check_all(NOARGS)
                } else
                        not_done_yet++;
        }
+
        if (cancel_requested && !kill_sent) {
                kill_all(SIGTERM);
                kill_sent++;
        }
+
        status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
+       mnt_free_iter(itr);
        return status;
 }
 
@@ -1433,8 +1373,7 @@ int main(int argc, char *argv[])
        int i, status = 0;
        int interactive = 0;
        char *oldpath = getenv("PATH");
-       const char *fstab;
-       struct fs_info *fs;
+       struct libmnt_fs *fs;
 
        setvbuf(stdout, NULL, _IONBF, BUFSIZ);
        setvbuf(stderr, NULL, _IONBF, BUFSIZ);
@@ -1450,10 +1389,7 @@ int main(int argc, char *argv[])
        if (!notitle)
                printf(_("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING);
 
-       fstab = getenv("FSTAB_FILE");
-       if (!fstab)
-               fstab = _PATH_MNTTAB;
-       load_fs_info(fstab);
+       load_fs_info();
 
        /* Update our search path to include uncommon directories. */
        if (oldpath) {
@@ -1493,15 +1429,12 @@ int main(int argc, char *argv[])
                        break;
                }
                fs = lookup(devices[i]);
-               if (!fs) {
-                       fs = create_fs_device(devices[i], 0, "auto",
-                                             0, -1, -1);
-                       if (!fs)
-                               continue;
-               } else if (fs->type && ignored_type(fs->type))
+               if (!fs)
+                       fs = add_dummy_fs(devices[i]);
+               else if (fs_ignored_type(fs))
                        continue;
 
-               if (ignore_mounted && is_mounted(fs->device))
+               if (ignore_mounted && is_mounted(fs_get_device(fs)))
                        continue;
                status |= fsck_device(fs, interactive);
                if (serialize ||
@@ -1520,6 +1453,8 @@ int main(int argc, char *argv[])
        status |= wait_many(FLAG_WAIT_ALL);
        free(fsck_path);
        fsprobe_exit();
+       mnt_free_cache(mnt_table_get_cache(fstab));
+       mnt_free_table(fstab);
        return status;
 }
 
index 52988067715df2ff97883d64a5bf35afda03f233..bb39dc236d65b5decd94290ad2cb1de61f26b371 100644 (file)
  * Internal structure for mount tabel entries.
  */
 
-struct fs_info {
-       char  *device;
-       char  *mountpt;
-       char  *type;
-       char  *opts;
-       int   freq;
-       int   passno;
-       int   flags;
-       dev_t disk;
-       int   stacked;
-       struct fs_info *next;
+struct fsck_fs_data
+{
+       const char      *device;
+       dev_t           disk;
+       unsigned int    stacked:1,
+                       done:1,
+                       eval_device:1;
 };
 
 #define FLAG_DONE 1
@@ -55,7 +51,7 @@ struct fsck_instance {
        time_t  start_time;
        char *  prog;
        char *  type;
-       struct fs_info *fs;
+       struct libmnt_fs *fs;
        struct fsck_instance *next;
 };