LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: "Anton Salikhmetov" <salikhmetov@gmail.com>
To: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org, joe@evalesco.com
Subject: Re: [PATCH][RFC][BUG] updating the ctime and mtime time stamps in msync()
Date: Wed, 9 Jan 2008 14:32:53 +0300	[thread overview]
Message-ID: <4df4ef0c0801090332y345ccb67se98409edc65fd6bf@mail.gmail.com> (raw)
In-Reply-To: <1199728459.26463.11.camel@codedot>

Since no reaction in LKML was recieved for this message it seemed
logical to suggest closing the bug #2645 as "WONTFIX":

http://bugzilla.kernel.org/show_bug.cgi?id=2645#c15

However, the reporter of the bug, Jacob Oestergaard, insisted the
solution to be resubmitted once more:

>>>

Please re-submit to LKML.

This bug causes backup systems to *miss* changed files.

This bug does cause data loss in common real-world deployments (I gave an
example with a database when posting the bug, but this affects the data from
all mmap using applications with common backup systems).

Silent exclusion from backups is very very nasty.

<<<

Please comment on my solution or commit it if it's acceptable in its
present form.

2008/1/7, Anton Salikhmetov <salikhmetov@gmail.com>:
> From: Anton Salikhmetov <salikhmetov@gmail.com>
>
> Due to the lack of reaction in LKML I presume the message was lost
> in the high traffic of that list. Resending it now with the addressee changed
> to the memory management mailing list.
>
> I would like to propose my solution for the bug #2645 from the kernel bug tracker:
>
> http://bugzilla.kernel.org/show_bug.cgi?id=2645
>
> The Open Group defines the behavior of the mmap() function as follows.
>
> The st_ctime and st_mtime fields of a file that is mapped with MAP_SHARED
> and PROT_WRITE shall be marked for update at some point in the interval
> between a write reference to the mapped region and the next call to msync()
> with MS_ASYNC or MS_SYNC for that portion of the file by any process.
> If there is no such call and if the underlying file is modified as a result
> of a write reference, then these fields shall be marked for update at some
> time after the write reference.
>
> The above citation was taken from the following link:
>
> http://www.opengroup.org/onlinepubs/009695399/functions/mmap.html
>
> Therefore, the msync() function should be called before verifying the time
> stamps st_mtime and st_ctime in the test program Badari wrote in the context
> of the bug #2645. Otherwise, the time stamps may be updated
> at some unspecified moment according to the POSIX standard.
>
> I changed his test program a little. The changed unit test can be downloaded
> using the following link:
>
> http://pygx.sourceforge.net/mmap.c
>
> This program showed that the msync() function had a bug:
> it did not update the st_mtime and st_ctime fields.
>
> The program shows appropriate behavior of the msync()
> function using the kernel with the proposed patch applied.
> Specifically, the ctime and mtime time stamps do change
> when modifying the mapped memory and do not change when
> there have been no write references between the mmap()
> and msync() system calls.
>
> Additionally, the test cases for the msync() system call from
> the LTP test suite (msync01 - msync05, mmapstress01, mmapstress09,
> and mmapstress10) successfully passed using the kernel
> with the patch included into this email.
>
> The patch adds a call to the file_update_time() function to change
> the file metadata before syncing. The patch also contains
> substantial code cleanup: consolidated error check
> for function parameters, using the PAGE_ALIGN() macro instead of
> "manual" alignment, improved readability of the loop,
> which traverses the process memory regions, updated comments.
>
> Signed-off-by: Anton Salikhmetov <salikhmetov@gmail.com>
>
> ---
>
> diff --git a/mm/msync.c b/mm/msync.c
> index 144a757..cb973eb 100644
> --- a/mm/msync.c
> +++ b/mm/msync.c
> @@ -1,26 +1,32 @@
>  /*
>   *     linux/mm/msync.c
>   *
> + * The msync() system call.
>   * Copyright (C) 1994-1999  Linus Torvalds
> + *
> + * Updating the mtime and ctime stamps for mapped files
> + * and code cleanup.
> + * Copyright (C) 2008 Anton Salikhmetov <salikhmetov@gmail.com>
>   */
>
> -/*
> - * The msync() system call.
> - */
> +#include <linux/file.h>
>  #include <linux/fs.h>
>  #include <linux/mm.h>
>  #include <linux/mman.h>
> -#include <linux/file.h>
> -#include <linux/syscalls.h>
>  #include <linux/sched.h>
> +#include <linux/syscalls.h>
>
>  /*
>   * MS_SYNC syncs the entire file - including mappings.
>   *
>   * MS_ASYNC does not start I/O (it used to, up to 2.5.67).
> - * Nor does it marks the relevant pages dirty (it used to up to 2.6.17).
> + * Nor does it mark the relevant pages dirty (it used to up to 2.6.17).
>   * Now it doesn't do anything, since dirty pages are properly tracked.
>   *
> + * The msync() system call updates the ctime and mtime fields for
> + * the mapped file when called with the MS_SYNC or MS_ASYNC flags
> + * according to the POSIX standard.
> + *
>   * The application may now run fsync() to
>   * write out the dirty pages and wait on the writeout and check the result.
>   * Or the application may run fadvise(FADV_DONTNEED) against the fd to start
> @@ -33,70 +39,68 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags)
>         unsigned long end;
>         struct mm_struct *mm = current->mm;
>         struct vm_area_struct *vma;
> -       int unmapped_error = 0;
> -       int error = -EINVAL;
> +       int error = 0, unmapped_error = 0;
>
> -       if (flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC))
> -               goto out;
> -       if (start & ~PAGE_MASK)
> +       if ((flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC)) ||
> +                       (start & ~PAGE_MASK) ||
> +                       ((flags & MS_ASYNC) && (flags & MS_SYNC))) {
> +               error = -EINVAL;
>                 goto out;
> -       if ((flags & MS_ASYNC) && (flags & MS_SYNC))
> -               goto out;
> -       error = -ENOMEM;
> -       len = (len + ~PAGE_MASK) & PAGE_MASK;
> +       }
> +
> +       len = PAGE_ALIGN(len);
>         end = start + len;
> -       if (end < start)
> +       if (end < start) {
> +               error = -ENOMEM;
>                 goto out;
> -       error = 0;
> +       }
>         if (end == start)
>                 goto out;
> +
>         /*
>          * If the interval [start,end) covers some unmapped address ranges,
>          * just ignore them, but return -ENOMEM at the end.
>          */
>         down_read(&mm->mmap_sem);
>         vma = find_vma(mm, start);
> -       for (;;) {
> +       do {
>                 struct file *file;
>
> -               /* Still start < end. */
> -               error = -ENOMEM;
> -               if (!vma)
> -                       goto out_unlock;
> -               /* Here start < vma->vm_end. */
> +               if (!vma) {
> +                       error = -ENOMEM;
> +                       break;
> +               }
>                 if (start < vma->vm_start) {
>                         start = vma->vm_start;
> -                       if (start >= end)
> -                               goto out_unlock;
> +                       if (start >= end) {
> +                               error = -ENOMEM;
> +                               break;
> +                       }
>                         unmapped_error = -ENOMEM;
>                 }
> -               /* Here vma->vm_start <= start < vma->vm_end. */
>                 if ((flags & MS_INVALIDATE) &&
>                                 (vma->vm_flags & VM_LOCKED)) {
>                         error = -EBUSY;
> -                       goto out_unlock;
> +                       break;
>                 }
>                 file = vma->vm_file;
> -               start = vma->vm_end;
> -               if ((flags & MS_SYNC) && file &&
> -                               (vma->vm_flags & VM_SHARED)) {
> +               if (file && (vma->vm_flags & VM_SHARED)) {
>                         get_file(file);
> -                       up_read(&mm->mmap_sem);
> -                       error = do_fsync(file, 0);
> -                       fput(file);
> -                       if (error || start >= end)
> -                               goto out;
> -                       down_read(&mm->mmap_sem);
> -                       vma = find_vma(mm, start);
> -               } else {
> -                       if (start >= end) {
> -                               error = 0;
> -                               goto out_unlock;
> +                       if (file->f_mapping->host->i_state & I_DIRTY_PAGES)
> +                               file_update_time(file);
> +                       if (flags & MS_SYNC) {
> +                               up_read(&mm->mmap_sem);
> +                               error = do_fsync(file, 0);
> +                               down_read(&mm->mmap_sem);
>                         }
> -                       vma = vma->vm_next;
> +                       fput(file);
> +                       if (error)
> +                               break;
>                 }
> -       }
> -out_unlock:
> +
> +               start = vma->vm_end;
> +               vma = vma->vm_next;
> +       } while (start < end);
>         up_read(&mm->mmap_sem);
>  out:
>         return error ? : unmapped_error;
>
>

  reply	other threads:[~2008-01-09 11:33 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-07 17:54 Anton Salikhmetov
2008-01-09 11:32 ` Anton Salikhmetov [this message]
2008-01-09 11:47   ` Jakob Oestergaard
2008-01-09 12:22   ` Jakob Oestergaard
2008-01-09 14:41   ` Jesper Juhl
2008-01-09 15:31     ` Anton Salikhmetov
2008-01-09 21:28   ` Peter Staubach
2008-01-09 20:50 ` Rik van Riel
2008-01-09 21:01   ` Klaus S. Madsen
2008-01-09 21:06   ` Valdis.Kletnieks
2008-01-09 22:06     ` Rik van Riel
2008-01-09 22:19       ` Peter Staubach
2008-01-09 22:33       ` Jakob Oestergaard
2008-01-09 23:41         ` Rik van Riel
2008-01-10  0:03           ` Anton Salikhmetov
2008-01-10  8:51             ` Jakob Oestergaard
2008-01-10 10:53               ` Anton Salikhmetov
2008-01-10 15:45                 ` Rik van Riel
2008-01-10 15:56                   ` Anton Salikhmetov
2008-01-10 16:07                     ` Rik van Riel
2008-01-10 16:40                       ` Anton Salikhmetov
2008-01-10 16:52                         ` Peter Staubach
2008-01-10 16:46                       ` Peter Staubach
2008-01-10 20:48           ` Valdis.Kletnieks
2008-01-10  0:48       ` Anton Salikhmetov
2008-01-10  0:40   ` Anton Salikhmetov
2008-01-09 21:18 ` Peter Staubach

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4df4ef0c0801090332y345ccb67se98409edc65fd6bf@mail.gmail.com \
    --to=salikhmetov@gmail.com \
    --cc=joe@evalesco.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --subject='Re: [PATCH][RFC][BUG] updating the ctime and mtime time stamps in msync()' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).