Hi,
On Wed, 02 Dec 2009 18:20:10 +0100, David Smid <[email protected]> wrote:
> Ryusuke Konishi napsal(a):
> > On Wed, 02 Dec 2009 00:44:22 +0900 (JST), Ryusuke Konishi 
> > <[email protected]> wrote:
> >> Hi,
> >> On Sat, 28 Nov 2009 22:16:31 +0100, David Smid <[email protected]>
> >> wrote:
> >>> Thanks you for your valuable comments.
> >>>
> >>> You are right, of course. No kernel code changes are needed.
> >>> Here is my take #2.
> >>>
> >>> David
> >> Thank you, David.  I reviewed the patch in detail, and no worrisome
> >> point found.
> >>
> >> During tests, I noticed that remount doesn't work for this option:
> >>
> >>   For instance, after doing
> >>   # mount -t nilfs2 -o pp=600 /dev/sdb1 /test
> >>   # mount -t nilfs2 -o remount,pp=400 /dev/sdb1 /test
> > 
> > Ryusuke
> 
> Good point, remount should definitely work because it is quite useful to 
> change
> pp on the fly.
> 
> This patch should work.
> 
> David

Thank you for revising the patch.  I reviewed the code anew.

I will comment inline.

> --- sbin/mount/mount.nilfs2.h.mount_pp_opt    2009-07-19 16:53:00.000000000 
> +0200
> +++ sbin/mount/mount.nilfs2.h 2009-12-02 10:27:26.000000000 +0100
> @@ -13,12 +13,13 @@
>  #define NILFS2_FS_NAME               "nilfs2"
>  #define CLEANERD_NAME                "nilfs_cleanerd"
>  #define PIDOPT_NAME          "gcpid"
> +#define PPOPT_NAME           "pp"
> 
>  #define CLEANERD_WAIT_RETRY_COUNT    3
>  #define CLEANERD_WAIT_RETRY_INTERVAL 2  /* in seconds */
> 
> 
> -extern int start_cleanerd(const char *, const char *, pid_t *);
> +extern int start_cleanerd(const char *, const char *, unsigned long, pid_t 
> *);
>  extern int stop_cleanerd(const char *, pid_t);
>  extern int check_cleanerd(const char *, pid_t);
> 
> --- sbin/mount/cleaner_ctl.c.mount_pp_opt     2009-07-19 16:53:00.000000000 
> +0200
> +++ sbin/mount/cleaner_ctl.c  2009-12-02 18:16:16.000000000 +0100
> @@ -45,6 +45,7 @@
> 
>  const char cleanerd[] = "/sbin/" CLEANERD_NAME;
>  const char cleanerd_nofork_opt[] = "-n";
> +const char cleanerd_protperiod_opt[] = "-p";
> 
>  extern char *progname;
> 
> @@ -54,12 +55,14 @@
>       return (kill(pid, 0) == 0);
>  }
> 
> -int start_cleanerd(const char *device, const char *mntdir, pid_t *ppid)
> +int start_cleanerd(const char *device, const char *mntdir,
> +                unsigned long protperiod, pid_t *ppid)
>  {
> -     const char *dargs[5];
> +     const char *dargs[7];
>       struct stat statbuf;
>       int i = 0;
>       int res;
> +     char buf[256];
> 
>       if (stat(cleanerd, &statbuf) != 0) {
>               error(_("Warning: %s not found"), CLEANERD_NAME);
> @@ -80,6 +83,11 @@
>               }
>               dargs[i++] = cleanerd;
>               dargs[i++] = cleanerd_nofork_opt;
> +             if (protperiod != ULONG_MAX) {
> +                     dargs[i++] = cleanerd_protperiod_opt;
> +                     snprintf(buf, sizeof(buf), "%lu", protperiod);
> +                     dargs[i++] = buf;
> +             }
>               dargs[i++] = device;
>               dargs[i++] = mntdir;
>               dargs[i] = NULL;
> --- sbin/mount/umount.nilfs2.c.mount_pp_opt   2009-07-19 16:53:00.000000000 
> +0200
> +++ sbin/mount/umount.nilfs2.c        2009-12-02 18:15:37.000000000 +0100
> @@ -69,6 +69,9 @@
>  const char gcpid_opt_fmt[] = PIDOPT_NAME "=%d";
>  typedef int gcpid_opt_t;
> 
> +const char pp_opt_fmt[] = PPOPT_NAME "=%lu";
> +typedef unsigned long pp_opt_t;
> +
>  struct umount_options {
>       int flags;
>       int force;
> @@ -317,6 +320,7 @@
>       int res, alive = 0;
>       const char *loopdev;
>       pid_t pid;
> +     pp_opt_t prot_period;
> 
>       if (streq (node, "/") || streq (node, "root"))
>               nomtab++;
> @@ -349,7 +353,11 @@
>                                     progname, spec);
>                       }
>               } else if (alive && !check_cleanerd(spec, pid)) {
> -                     if (start_cleanerd(spec, node, &pid) == 0) {
> +                     if (find_opt(mc->m.mnt_opts, pp_opt_fmt, &prot_period)
> +                         < 0)
> +                             prot_period = ULONG_MAX;
> +
> +                     if (start_cleanerd(spec, node, prot_period, &pid) == 0) 
> {
>                               if (verbose)
>                                       printf(_("%s: restarted %s(pid=%d)\n"),
>                                              progname, CLEANERD_NAME,
> --- sbin/mount/mount.nilfs2.c.mount_pp_opt    2009-07-19 16:53:00.000000000 
> +0200
> +++ sbin/mount/mount.nilfs2.c 2009-12-02 18:14:50.000000000 +0100
> @@ -71,6 +71,9 @@
>  const char gcpid_opt_fmt[] = PIDOPT_NAME "=%d";
>  typedef int gcpid_opt_t;
> 
> +const char pp_opt_fmt[] = PPOPT_NAME "=%lu";
> +typedef unsigned long pp_opt_t;
> +
>  struct mount_options {
>       char *fstype;
>       char *opts;
> @@ -225,16 +228,43 @@
>       *opts = newopts;
>  }
> 
> -static char *fix_extra_opts_string(const char *extra_opts, pid_t gcpid)
> +static void update_pp_opt(char **opts, pp_opt_t protection_period)
> +{
> +     char buf[256], *newopts;
> +     pp_opt_t oldpp;
> +
> +     *buf = 0;
> +     if (protection_period != ULONG_MAX) {
> +             snprintf(buf, sizeof(buf), pp_opt_fmt, protection_period);
> +     }

In case of the kernel code, these braces (i.e '{' and '}') are removed
because it's a single statement.  (for your information.  This is not
important.)

> +     newopts = change_opt(*opts, pp_opt_fmt, &oldpp, buf);
> +     my_free(*opts);
> +     *opts = newopts;
> +}
> +
> +static char *fix_extra_opts_string(const char *extra_opts, pid_t gcpid,
> +                                pp_opt_t protection_period)
>  {
>       char buf[256];
>       gcpid_opt_t id;
> +     pp_opt_t pp;
> +     char *tmpres;
> +     char *res;
> 
>       buf[0] = '\0';
>       if (gcpid)
>               snprintf(buf, sizeof(buf), gcpid_opt_fmt, (int)gcpid);
>       /* The gcpid option will be removed if gcpid == 0 */
> -     return change_opt(extra_opts, gcpid_opt_fmt, &id, buf);
> +     tmpres = change_opt(extra_opts, gcpid_opt_fmt, &id, buf);
> +     
> +     buf[0] = '\0';
> +     if (protection_period != ULONG_MAX)
> +             snprintf(buf, sizeof(buf), pp_opt_fmt, protection_period);
> +     /* The pp option will be removed if pp == ULONG_MAX */
> +     res = change_opt(tmpres, pp_opt_fmt, &pp, buf);
> +
> +     my_free(tmpres);
> +     return res;
>  }
> 
>  /*
> @@ -312,6 +342,7 @@
>       pid_t gcpid;
>       int type;
>       int mounted;
> +     pp_opt_t protperiod;
>  };
> 
>  static int check_mtab(void)
> @@ -348,6 +379,7 @@
>  {
>       struct mntentchn *mc;
>       gcpid_opt_t pid;
> +     pp_opt_t prot_period;
>       int res = -1;
> 
>       if (!(mo->flags & MS_REMOUNT) && mounted(NULL, mi->mntdir)) {
> @@ -359,6 +391,9 @@
>       mi->gcpid = 0;
>       mi->optstr = NULL;
>       mi->mounted = mounted(mi->device, mi->mntdir);
> +     mi->protperiod = ULONG_MAX;

> +     if (find_opt(mo->extra_opts, pp_opt_fmt, &prot_period) >= 0)
> +             mi->protperiod = prot_period;

These two lines should be removed because prepare_mount() is the
function to find an existing mount and extract its options from mtab.
mo->extra_opts has new mount options.

Please see the code I add below.
 
>       if (mo->flags & MS_BIND)
>               return 0;
> @@ -375,15 +410,13 @@
>               goto failed;
>       case MS_RDONLY: /* ro-mount (a rw-mount exists) */
>               break;
> -     case MS_REMOUNT: /* rw->rw remount */
> -             if (check_remount_dir(mc, mi->mntdir) < 0)
> -                     goto failed;
> -             if (find_opt(mc->m.mnt_opts, gcpid_opt_fmt, &pid) >= 0)
> -                     mi->gcpid = pid;
> -             mi->optstr = xstrdup(mc->m.mnt_opts); /* previous opts */
> -             mi->type = RW2RW_REMOUNT;
> -             break;
> -     case MS_RDONLY | MS_REMOUNT:  /* rw->ro remount */
> +     case MS_REMOUNT | MS_RDONLY: /* rw->ro remount */
> +             mi->type = RW2RO_REMOUNT;
> +             mi->protperiod = ULONG_MAX;
> +             /* fallthrough */
> +     case MS_REMOUNT:
> +             if (!(mo->flags & MS_RDONLY))
> +                     mi->type = RW2RW_REMOUNT; /* rw->rw remount */          
>         
Trailing space chars. should be removed.
>               if (check_remount_dir(mc, mi->mntdir) < 0)
>                       goto failed;

Here, can get the existing pp value:

                prot_period = ULONG_MAX;
                if (find_opt(mc->m.mnt_opts, pp_opt_fmt, &prot_period) >= 0)
                        mi->protperiod = prot_period;

This previous value is used in do_mount_one(), for example, when
remount fails and it restarts cleanerd.

>               pid = 0;
> @@ -395,7 +428,6 @@
>               }
>               mi->gcpid = pid;
>               mi->optstr = xstrdup(mc->m.mnt_opts); /* previous opts */
> -             mi->type = RW2RO_REMOUNT;
>               break;
>       }
> 
> @@ -408,9 +440,13 @@
>  do_mount_one(struct nilfs_mount_info *mi, const struct mount_options *mo)
>  {
>       int res, errsv;
> +     char *exopts;
> +     pp_opt_t prot_period;
> +
> +     exopts = change_opt(mo->extra_opts, pp_opt_fmt, &prot_period, "");
> 
>       res = mount(mi->device, mi->mntdir, fstype, mo->flags & ~MS_NOSYS,
> -                 mo->extra_opts);
> +                 exopts);
>       if (!res)
>               goto out;
> 
> @@ -425,15 +461,19 @@
>                     progname, mi->device, mi->mntdir, strerror(errsv));
>               break;
>       }
> -     if (mi->type != RW2RO_REMOUNT)
> +     if (mi->type != RW2RO_REMOUNT && mi->type != RW2RW_REMOUNT)
>               goto out;
> +     /* Cleaner daemon was stopped and it needs to run */
> +     /* because filesystem is still mounted */
>       if (check_mtab()) {
>               /* Restarting cleaner daemon */
> -             if (start_cleanerd(mi->device, mi->mntdir, &mi->gcpid) == 0) {
> +             if (start_cleanerd(mi->device, mi->mntdir, mi->protperiod,
> +                                &mi->gcpid) == 0) {
>                       if (verbose)
>                               printf(_("%s: restarted %s\n"),
>                                      progname, CLEANERD_NAME);
>                       update_gcpid_opt(&mi->optstr, mi->gcpid);
> +                     update_pp_opt(&mi->optstr, mi->protperiod);

This update_pp_opt() is redundant because this is an error path and
the pp option should keep the previous value.  On the other hand,
update_gcpid_opt() is necessary since GC pid is always changed after
the restart.

>                       update_mtab_entry(mi->device, mi->mntdir, fstype,
>                                         mi->optstr, 0, 0, !mi->mounted);
>               } else {
> @@ -443,31 +483,39 @@
>       } else
>               printf(_("%s not restarted\n"), CLEANERD_NAME);
>   out:
> +     my_free(exopts);
>       return res;
>  }
> 
>  static void update_mount_state(struct nilfs_mount_info *mi,
>                              const struct mount_options *mo)
>  {
> -     pid_t pid = (mi->type == RW2RW_REMOUNT) ? mi->gcpid : 0;
> +     pid_t pid = fake ? mi->gcpid : 0;

Right.  The old gcpid will break except for the fake mode.

>       char *exopts;
>       int rungc;
> 

> +     if (mo->flags & MS_RDONLY)
> +             mi->protperiod = ULONG_MAX;
> +

New pp option can be parsed here.

        if ((mo->flags & MS_RDONLY) || (mo->flags & MS_BIND) ||
            find_opt(mo->extra_opts, pp_opt_fmt, &prot_period) < 0)
                mi->protperiod = ULONG_MAX;
        else
                mi->protperiod = prot_period;

Note that we don't invoke cleanerd for a bind mount.

>       rungc = !(mo->flags & MS_RDONLY) && !(mo->flags & MS_BIND) &&
> -             (mi->type != RW2RW_REMOUNT || mi->gcpid == 0);
> +             (pid == 0);
>       if (!check_mtab()) {
>               if (rungc)
>                       printf(_("%s not started\n"), CLEANERD_NAME);
>               return;
>       }
>       if (rungc) {
> -             if (start_cleanerd(mi->device, mi->mntdir, &pid) < 0)
> +             if (start_cleanerd(mi->device, mi->mntdir, mi->protperiod,
> +                                &pid) < 0)
>                       error(_("%s aborted"), CLEANERD_NAME);
>               else if (verbose)
>                       printf(_("%s: started %s\n"), progname, CLEANERD_NAME);
> -     }
> +     } else
> +             if (!fake)
> +                     pid = 0;
> +     
>       my_free(mi->optstr);
> -     exopts = fix_extra_opts_string(mo->extra_opts, pid);
> +     exopts = fix_extra_opts_string(mo->extra_opts, pid, mi->protperiod);
>       mi->optstr = fix_opts_string(((mo->flags & ~MS_NOMTAB) | MS_NETDEV),
>                                    exopts, NULL);
>               
> --- man/mount.nilfs2.8.mount_pp_opt   2009-07-19 16:53:00.000000000 +0200
> +++ man/mount.nilfs2.8        2009-12-02 10:27:26.000000000 +0100
> @@ -103,6 +103,12 @@
>  remount the file system read-only, or panic and halt the system.)  The
>  default is continue.
>  .TP
> +.BR pp=\fP\fIprotection-period\fP
> +Specify the \fIprotection-period\fP for the cleaner daemon (in
> +seconds). nilfs_cleanerd never deletes recent checkpoints whose
> +elapsed time from its creation is smaller than
> +\fIprotection-period\fP.
> +.TP
>  .BR order=relaxed " / " order=strict
>  Specify order semantics for file data.  Metadata is always written to
>  follow the POSIX semantics about the order of filesystem operations.


Thanks,
Ryusuke Konishi
_______________________________________________
users mailing list
[email protected]
https://www.nilfs.org/mailman/listinfo/users

Reply via email to