qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Fam Zheng <famz@redhat.com>
To: Max Reitz <mreitz@redhat.com>
Cc: qemu-block@nongnu.org, Kevin Wolf <kwolf@redhat.com>,
	qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 2/3] block/file-posix: File locking during creation
Date: Thu, 3 May 2018 14:45:52 +0800	[thread overview]
Message-ID: <20180503064552.GJ15438@lemon.usersys.redhat.com> (raw)
In-Reply-To: <9801ca35-b050-d482-f482-f1364bf07e1c@redhat.com>

On Sat, 04/28 13:03, Max Reitz wrote:
> On 2018-04-27 08:22, Fam Zheng wrote:
> > On Sat, 04/21 00:09, Max Reitz wrote:
> >> When creating a file, we should take the WRITE and RESIZE permissions.
> >> We do not need either for the creation itself, but we do need them for
> >> clearing and resizing it.  So we can take the proper permissions by
> >> replacing O_TRUNC with an explicit truncation to 0, and by taking the
> >> appropriate file locks between those two steps.
> >>
> >> Signed-off-by: Max Reitz <mreitz@redhat.com>
> >> ---
> >>  block/file-posix.c | 41 +++++++++++++++++++++++++++++++++++++++--
> >>  1 file changed, 39 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/block/file-posix.c b/block/file-posix.c
> >> index c98a4a1556..ed7932d6e8 100644
> >> --- a/block/file-posix.c
> >> +++ b/block/file-posix.c
> >> @@ -1992,6 +1992,7 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
> >>  {
> >>      BlockdevCreateOptionsFile *file_opts;
> >>      int fd;
> >> +    int perm, shared;
> >>      int result = 0;
> >>  
> >>      /* Validate options and set default values */
> >> @@ -2006,14 +2007,48 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
> >>      }
> >>  
> >>      /* Create file */
> >> -    fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
> >> -                   0644);
> >> +    fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_BINARY, 0644);
> >>      if (fd < 0) {
> >>          result = -errno;
> >>          error_setg_errno(errp, -result, "Could not create file");
> >>          goto out;
> >>      }
> >>  
> >> +    /* Take permissions: We want to discard everything, so we need
> >> +     * BLK_PERM_WRITE; and truncation to the desired size requires
> >> +     * BLK_PERM_RESIZE.
> >> +     * On the other hand, we cannot share the RESIZE permission
> >> +     * because we promise that after this function, the file has the
> >> +     * size given in the options.  If someone else were to resize it
> >> +     * concurrently, we could not guarantee that. */
> > 
> > Strictly speaking, we do close(fd) before this function returns so the lock is
> > lost and race can happen.
> 
> Right, but then creation from the perspective of file-posix is over.  We
> are going to reopen the file for formatting, but that is just a normal
> bdrv_open() so it will automatically be locked, no?

After this function close() but before the following bdrv_open(), another
process can sneak in and steal the lock. So we cannot guarantee the RESIZE lock
does what we really want.

Fam

> 
> >> +    perm = BLK_PERM_WRITE | BLK_PERM_RESIZE;
> >> +    shared = BLK_PERM_ALL & ~BLK_PERM_RESIZE;
> >> +
> >> +    /* Step one: Take locks in shared mode */
> >> +    result = raw_apply_lock_bytes(fd, perm, shared, false, errp);
> >> +    if (result < 0) {
> >> +        goto out_close;
> >> +    }
> >> +
> >> +    /* Step two: Try to get them exclusively */
> >> +    result = raw_check_lock_bytes(fd, perm, shared, errp);
> >> +    if (result < 0) {
> >> +        goto out_close;
> >> +    }
> >> +
> >> +    /* Step three: Downgrade them to shared again, and keep
> >> +     *             them that way until we are done */
> >> +    result = raw_apply_lock_bytes(fd, perm, shared, true, errp);
> > 
> > You comment it as "downgrade to shared" but what this actually does in addition
> > to step one is to "unlock" unneeded bytes which we haven't locked anyway. So I'm
> > confused why we need this stop. IIUC no downgrading is necessary after step one
> > and step two: only necessary shared locks are acquired in step one, and step two
> > is read-only op (F_OFD_GETLK).
> 
> Oops.  For some reason I thought raw_check_lock_bytes() would take the
> locks exclusively.  Yes, then we don't need this third step.
> 
> Thanks for reviewing!
> 
> Max
> 
> >> +    if (result < 0) {
> >> +        goto out_close;
> >> +    }
> >> +
> >> +    /* Clear the file by truncating it to 0 */
> >> +    result = raw_regular_truncate(fd, 0, PREALLOC_MODE_OFF, errp);
> >> +    if (result < 0) {
> >> +        goto out_close;
> >> +    }
> >> +
> >>      if (file_opts->nocow) {
> >>  #ifdef __linux__
> >>          /* Set NOCOW flag to solve performance issue on fs like btrfs.
> >> @@ -2029,6 +2064,8 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
> >>  #endif
> >>      }
> >>  
> >> +    /* Resize and potentially preallocate the file to the desired
> >> +     * final size */
> >>      result = raw_regular_truncate(fd, file_opts->size, file_opts->preallocation,
> >>                                    errp);
> >>      if (result < 0) {
> >> -- 
> >> 2.14.3
> >>
> >>
> > 
> > Fam
> > 
> 
> 

  reply	other threads:[~2018-05-03  6:46 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-20 22:09 [Qemu-devel] [PATCH 0/3] block/file-posix: File locking during creation Max Reitz
2018-04-20 22:09 ` [Qemu-devel] [PATCH 1/3] block/file-posix: Pass FD to locking helpers Max Reitz
2018-04-27  6:24   ` Fam Zheng
2018-04-20 22:09 ` [Qemu-devel] [PATCH 2/3] block/file-posix: File locking during creation Max Reitz
2018-04-27  6:22   ` Fam Zheng
2018-04-28 11:03     ` Max Reitz
2018-05-03  6:45       ` Fam Zheng [this message]
2018-05-04 13:45         ` Max Reitz
2018-05-07  7:23           ` Fam Zheng
2018-04-20 22:09 ` [Qemu-devel] [PATCH 3/3] iotests: Add creation test to 153 Max Reitz
2018-04-27  6:24   ` Fam Zheng
2018-04-23 13:19 ` [Qemu-devel] [Qemu-block] [PATCH 0/3] block/file-posix: File locking during creation Alberto Garcia
2018-04-23 15:56   ` Max Reitz

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=20180503064552.GJ15438@lemon.usersys.redhat.com \
    --to=famz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).