Re: [PATCH 03/15] cifs: fix handling of signing with writepages (try #5)

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

 



The patch does seem to change one behavior.

If CIFSSMBWrite2 writes data, but less than requested
(bytes written < bytes_to_write) this may change the file size but the
(local copy of eof?) eof won't be updated in that case (as it was
before)

On Wed, Sep 22, 2010 at 4:23 PM, Jeff Layton <jlayton@xxxxxxxxxx> wrote:
> Get a reference to the file early so we can eventually base the decision
> about signing on the correct tcon. If that doesn't work for some reason,
> then fall back to generic_writepages. That's just as likely to fail, but
> it simplifies the error handling.
>
> In truth, I'm not sure how that could occur anyway, so maybe a NULL
> open_file here ought to be a BUG()?
>
> After that, we drop the reference to the open_file and then we re-get
> one prior to each WriteAndX call. This helps ensure that the filehandle
> isn't held open any longer than necessary and that open files are
> reclaimed prior to each write call.
>
> Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
> ---
>  fs/cifs/file.c |   70 ++++++++++++++++++++++++++++++-------------------------
>  1 files changed, 38 insertions(+), 32 deletions(-)
>
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index 84979fc..e099b50 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -1353,6 +1353,15 @@ static int cifs_writepages(struct address_space *mapping,
>        int scanned = 0;
>        int xid, long_op;
>
> +       /*
> +        * BB: Is this meaningful for a non-block-device file system?
> +        * If it is, we should test it again after we do I/O
> +        */
> +       if (wbc->nonblocking && bdi_write_congested(bdi)) {
> +               wbc->encountered_congestion = 1;
> +               return 0;
> +       }
> +
>        cifs_sb = CIFS_SB(mapping->host->i_sb);
>
>        /*
> @@ -1362,26 +1371,28 @@ static int cifs_writepages(struct address_space *mapping,
>        if (cifs_sb->wsize < PAGE_CACHE_SIZE)
>                return generic_writepages(mapping, wbc);
>
> -       if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
> -               if (cifs_sb->tcon->ses->server->secMode &
> -                               (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
> -                       if (!experimEnabled)
> -                               return generic_writepages(mapping, wbc);
> -
>        iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
>        if (iov == NULL)
>                return generic_writepages(mapping, wbc);
>
> -
>        /*
> -        * BB: Is this meaningful for a non-block-device file system?
> -        * If it is, we should test it again after we do I/O
> +        * if there's no open file, then this is likely to fail too,
> +        * but it'll at least handle the return. Maybe it should be
> +        * a BUG() instead?
>         */
> -       if (wbc->nonblocking && bdi_write_congested(bdi)) {
> -               wbc->encountered_congestion = 1;
> +       open_file = find_writable_file(CIFS_I(mapping->host));
> +       if (!open_file) {
>                kfree(iov);
> -               return 0;
> +               return generic_writepages(mapping, wbc);
> +       }
> +
> +       tcon = open_file->tcon;
> +       if (!experimEnabled && tcon->ses->server->secMode &
> +                       (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
> +               cifsFileInfo_put(open_file);
> +               return generic_writepages(mapping, wbc);
>        }
> +       cifsFileInfo_put(open_file);
>
>        xid = GetXid();
>
> @@ -1486,38 +1497,33 @@ retry:
>                                break;
>                }
>                if (n_iov) {
> -                       /* Search for a writable handle every time we call
> -                        * CIFSSMBWrite2.  We can't rely on the last handle
> -                        * we used to still be valid
> -                        */
>                        open_file = find_writable_file(CIFS_I(mapping->host));
>                        if (!open_file) {
>                                cERROR(1, "No writable handles for inode");
>                                rc = -EBADF;
>                        } else {
> -                               tcon = open_file->tcon;
>                                long_op = cifs_write_timeout(cifsi, offset);
> -                               rc = CIFSSMBWrite2(xid, tcon,
> -                                                  open_file->netfid,
> +                               rc = CIFSSMBWrite2(xid, tcon, open_file->netfid,
>                                                   bytes_to_write, offset,
>                                                   &bytes_written, iov, n_iov,
>                                                   long_op);
>                                cifsFileInfo_put(open_file);
> -                               cifs_update_eof(cifsi, offset, bytes_written);
> +                       }
>
> -                               if (rc || bytes_written < bytes_to_write) {
> -                                       cERROR(1, "Write2 ret %d, wrote %d",
> -                                                 rc, bytes_written);
> -                                       /* BB what if continued retry is
> -                                          requested via mount flags? */
> -                                       if (rc == -ENOSPC)
> -                                               set_bit(AS_ENOSPC, &mapping->flags);
> -                                       else
> -                                               set_bit(AS_EIO, &mapping->flags);
> -                               } else {
> -                                       cifs_stats_bytes_written(tcon, bytes_written);
> -                               }
> +                       if (rc || bytes_written < bytes_to_write) {
> +                               cERROR(1, "Write2 ret %d, wrote %d",
> +                                         rc, bytes_written);
> +                               /* BB what if continued retry is
> +                                  requested via mount flags? */
> +                               if (rc == -ENOSPC)
> +                                       set_bit(AS_ENOSPC, &mapping->flags);
> +                               else
> +                                       set_bit(AS_EIO, &mapping->flags);
> +                       } else {
> +                               cifs_update_eof(cifsi, offset, bytes_written);
> +                               cifs_stats_bytes_written(tcon, bytes_written);
>                        }
> +
>                        for (i = 0; i < n_iov; i++) {
>                                page = pvec.pages[first + i];
>                                /* Should we also set page error on
> --
> 1.7.3
>
>



-- 
Thanks,

Steve
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux