Re: [PATCH 22/22] lockfile: allow new file contents to be written while retaining lock

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Apr 1, 2014 at 11:58 AM, Michael Haggerty <mhagger@xxxxxxxxxxxx> wrote:
> Add a new option flag, LOCK_SEPARATE_STAGING_FILE, that can be passed
> to hold_lock_file_for_update() or hold_lock_file_for_append() to use a
> staging file that is independent of the lock file.
>
> Add a new function activate_staging_file() that activates the contents
> that have been written to the staging file without releasing the lock.
>
> This functionality can be used to ensure that changes to two files are
> seen by other processes in one order even if correctness requires the
> locks to be released in another order.
>
> Signed-off-by: Michael Haggerty <mhagger@xxxxxxxxxxxx>
> ---
> diff --git a/lockfile.c b/lockfile.c
> index c06e134..336b914 100644
> --- a/lockfile.c
> +++ b/lockfile.c
> @@ -271,19 +325,54 @@ int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
>         return fd;
>  }
>
> -int close_lock_file(struct lock_file *lk)
> +static int close_staging_file(struct lock_file *lk)
>  {
>         int fd = lk->fd;
> +
>         lk->fd = -1;
>         return close(fd);
>  }
>
> -int commit_lock_file(struct lock_file *lk)
> +int close_lock_file(struct lock_file *lk)
>  {
> -       if (lk->fd >= 0 && close_lock_file(lk))
> -               return -1;
> -       if (rename(lk->staging_filename.buf, lk->filename.buf))
> +       assert(!(lk->flags & LOCK_FLAGS_SEPARATE_STAGING_FILE));
> +       return close_staging_file(lk);
> +}
> +
> +int activate_staging_file(struct lock_file *lk)
> +{
> +       int err;
> +
> +       assert(lk->flags & LOCK_FLAGS_SEPARATE_STAGING_FILE);
> +       assert(lk->fd >= 0);
> +       assert(lk->staging_filename.len);
> +
> +       if (close_staging_file(lk))
>                 return -1;
> +
> +       err = rename(lk->staging_filename.buf, lk->filename.buf);
> +       strbuf_setlen(&lk->staging_filename, 0);

strbuf_reset()?

> +
> +       return err;
> +}
> +
> +int commit_lock_file(struct lock_file *lk)
> +{
> +       if (lk->flags & LOCK_FLAGS_SEPARATE_STAGING_FILE) {
> +               if (lk->staging_filename.len) {
> +                       assert(lk->fd >= 0);
> +                       if (activate_staging_file(lk))
> +                               return -1;
> +               }
> +               strbuf_addbuf(&lk->staging_filename, &lk->filename);
> +               strbuf_addstr(&lk->staging_filename, ".lock");
> +               unlink_or_warn(lk->staging_filename.buf);
> +       } else {
> +               if (lk->fd >= 0 && close_lock_file(lk))
> +                       return -1;
> +               if (rename(lk->staging_filename.buf, lk->filename.buf))
> +                       return -1;
> +       }
>         reset_lock_file(lk);
>         return 0;
>  }
> @@ -318,10 +407,21 @@ int commit_locked_index(struct lock_file *lk)
>
>  void rollback_lock_file(struct lock_file *lk)
>  {
> -       if (lk->filename.len) {
> -               if (lk->fd >= 0)
> -                       close_lock_file(lk);
> -               unlink_or_warn(lk->staging_filename.buf);
> -               reset_lock_file(lk);
> +       if (!lk->filename.len)
> +               return;
> +
> +       if (lk->fd >= 0)
> +               close_staging_file(lk);
> +
> +       if (lk->flags & LOCK_FLAGS_SEPARATE_STAGING_FILE) {
> +               if (lk->staging_filename.len) {
> +                       unlink_or_warn(lk->staging_filename.buf);
> +                       strbuf_setlen(&lk->staging_filename, 0);

strbuf_reset()?

> +               }
> +               strbuf_addbuf(&lk->staging_filename, &lk->filename);
> +               strbuf_addstr(&lk->staging_filename, ".lock");
>         }
> +
> +       unlink_or_warn(lk->staging_filename.buf);
> +       reset_lock_file(lk);
>  }
> --
> 1.9.0
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]