Re: [PATCH v1 8/8] cifs: convert cifs_iovec_write to use async writes

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

 



2012/2/21 Jeff Layton <jlayton@xxxxxxxxxx>:
> On Tue, 21 Feb 2012 12:06:49 +0400
> Pavel Shilovsky <piastryyy@xxxxxxxxx> wrote:
>
>> 2012/2/3 Jeff Layton <jlayton@xxxxxxxxxx>:
>> > Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
>> > ---
>> >  fs/cifs/cifsproto.h |    2 +
>> >  fs/cifs/cifssmb.c   |    4 +-
>> >  fs/cifs/file.c      |  191 ++++++++++++++++++++++++++++++++-------------------
>> >  3 files changed, 126 insertions(+), 71 deletions(-)
>> >
>> > diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
>> > index bceadc5..a131ded 100644
>> > --- a/fs/cifs/cifsproto.h
>> > +++ b/fs/cifs/cifsproto.h
>> > @@ -473,6 +473,8 @@ int cifs_async_readv(struct cifs_readdata *rdata);
>> >  /* asynchronous write support */
>> >  struct cifs_writedata {
>> >        struct kref                     refcount;
>> > +       struct list_head                list;
>> > +       struct completion               done;
>> >        enum writeback_sync_modes       sync_mode;
>> >        struct work_struct              work;
>> >        struct cifsFileInfo             *cfile;
>> > diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
>> > index 113b5af..6e93c9e 100644
>> > --- a/fs/cifs/cifssmb.c
>> > +++ b/fs/cifs/cifssmb.c
>> > @@ -2034,8 +2034,10 @@ cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
>> >        wdata = kzalloc(sizeof(*wdata) +
>> >                        sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
>> >        if (wdata != NULL) {
>> > -               INIT_WORK(&wdata->work, complete);
>> >                kref_init(&wdata->refcount);
>> > +               INIT_LIST_HEAD(&wdata->list);
>> > +               init_completion(&wdata->done);
>> > +               INIT_WORK(&wdata->work, complete);
>> >        }
>> >        return wdata;
>> >  }
>> > diff --git a/fs/cifs/file.c b/fs/cifs/file.c
>> > index c7e47a2..ef25fc5 100644
>> > --- a/fs/cifs/file.c
>> > +++ b/fs/cifs/file.c
>> > @@ -2057,23 +2057,55 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
>> >        return num_pages;
>> >  }
>> >
>> > +static void
>> > +cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
>> > +{
>> > +       int i;
>> > +       size_t bytes = wdata->bytes;
>> > +
>> > +       /* marshal up the pages into iov array */
>> > +       for (i = 0; i < wdata->nr_pages; i++) {
>> > +               iov[i + 1].iov_len = min(bytes, PAGE_SIZE);
>> > +               iov[i + 1].iov_base = kmap(wdata->pages[i]);
>> > +               bytes -= iov[i + 1].iov_len;
>> > +       }
>> > +}
>> > +
>> > +static void
>> > +cifs_uncached_writev_complete(struct work_struct *work)
>> > +{
>> > +       int i;
>> > +       struct cifs_writedata *wdata = container_of(work,
>> > +                                       struct cifs_writedata, work);
>> > +
>> > +       complete(&wdata->done);
>> > +
>> > +       if (wdata->result != -EAGAIN) {
>> > +               for (i = 0; i < wdata->nr_pages; i++)
>> > +                       put_page(wdata->pages[i]);
>> > +       }
>> > +
>> > +       kref_put(&wdata->refcount, cifs_writedata_release);
>> > +}
>> > +
>> >  static ssize_t
>> >  cifs_iovec_write(struct file *file, const struct iovec *iov,
>> >                 unsigned long nr_segs, loff_t *poffset)
>> >  {
>> > -       unsigned int written;
>> > -       unsigned long num_pages, npages, i;
>> > +       unsigned long nr_pages, i;
>> >        size_t copied, len, cur_len;
>> >        ssize_t total_written = 0;
>> > -       struct kvec *to_send;
>> > -       struct page **pages;
>> > +       loff_t offset = *poffset;
>> >        struct iov_iter it;
>> > -       struct inode *inode;
>> > +       struct inode *inode = file->f_path.dentry->d_inode;
>> > +       struct cifsInodeInfo *cifsi = CIFS_I(inode);
>> >        struct cifsFileInfo *open_file;
>> >        struct cifs_tcon *tcon;
>> >        struct cifs_sb_info *cifs_sb;
>> > -       int xid, rc;
>> > -       __u32 pid;
>> > +       struct cifs_writedata *wdata, *tmp;
>> > +       struct list_head wdata_list;
>> > +       int rc;
>> > +       pid_t pid;
>> >
>> >        len = iov_length(iov, nr_segs);
>> >        if (!len)
>> > @@ -2083,103 +2115,122 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
>> >        if (rc)
>> >                return rc;
>> >
>> > +       INIT_LIST_HEAD(&wdata_list);
>> >        cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
>> > -       num_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
>> > -
>> > -       pages = kmalloc(sizeof(struct pages *)*num_pages, GFP_KERNEL);
>> > -       if (!pages)
>> > -               return -ENOMEM;
>> > -
>> > -       to_send = kmalloc(sizeof(struct kvec)*(num_pages + 1), GFP_KERNEL);
>> > -       if (!to_send) {
>> > -               kfree(pages);
>> > -               return -ENOMEM;
>> > -       }
>> > -
>> > -       rc = cifs_write_allocate_pages(pages, num_pages);
>> > -       if (rc) {
>> > -               kfree(pages);
>> > -               kfree(to_send);
>> > -               return rc;
>> > -       }
>> > -
>> > -       xid = GetXid();
>> >        open_file = file->private_data;
>> > +       tcon = tlink_tcon(open_file->tlink);
>> >
>> >        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
>> >                pid = open_file->pid;
>> >        else
>> >                pid = current->tgid;
>> >
>> > -       tcon = tlink_tcon(open_file->tlink);
>> > -       inode = file->f_path.dentry->d_inode;
>> > -
>> >        iov_iter_init(&it, iov, nr_segs, len, 0);
>> > -       npages = num_pages;
>> > -
>> >        do {
>> > -               size_t save_len = cur_len;
>> > -               for (i = 0; i < npages; i++) {
>> > -                       copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE);
>> > -                       copied = iov_iter_copy_from_user(pages[i], &it, 0,
>> > -                                                        copied);
>> > +               size_t save_len;
>> > +
>> > +               nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
>> > +               wdata = cifs_writedata_alloc(nr_pages,
>> > +                                            cifs_uncached_writev_complete);
>> > +               if (!wdata) {
>> > +                       rc = -ENOMEM;
>> > +                       break;
>> > +               }
>> > +
>> > +               rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
>> > +               if (rc) {
>> > +                       kfree(wdata);
>> > +                       break;
>> > +               }
>> > +
>> > +               save_len = cur_len;
>> > +               for (i = 0; i < nr_pages; i++) {
>> > +                       copied = min_t(const size_t, cur_len, PAGE_SIZE);
>> > +                       copied = iov_iter_copy_from_user(wdata->pages[i], &it,
>> > +                                                        0, copied);
>> >                        cur_len -= copied;
>> >                        iov_iter_advance(&it, copied);
>> > -                       to_send[i+1].iov_base = kmap(pages[i]);
>> > -                       to_send[i+1].iov_len = copied;
>> >                }
>> > -
>> >                cur_len = save_len - cur_len;
>> >
>> > +               wdata->sync_mode = WB_SYNC_ALL;
>> > +               wdata->nr_pages = nr_pages;
>> > +               wdata->offset = (__u64)offset;
>> > +               wdata->cfile = cifsFileInfo_get(open_file);
>> > +               wdata->pid = pid;
>> > +               wdata->bytes = cur_len;
>> > +               wdata->marshal_iov = cifs_uncached_marshal_iov;
>> >                do {
>> >                        if (open_file->invalidHandle) {
>> >                                rc = cifs_reopen_file(open_file, false);
>> >                                if (rc != 0)
>> >                                        break;
>> >                        }
>>
>> When we reopen a file, we do it with the current pid, but in
>> cfile->pid leaves with the old value (and pid variable too).Should we
>> do reopen with cfile->pid to save the original state of the file (now
>> we don't restore locks, if we do it - it will be the problem)?
>>
>
> Yes, that does sound like something that should be fixed. That said, we
> have a lot of problems in the code that handles open files, and that's
> just one of them. At this point, I'm not going to fix that in this
> patchset since it's an existing bug and unrelated to what I'm changing
> here. It certainly wouldn't hurt to fix that at some point though.
>

I agree - this doesn't related to the patch, it simply pointed me to
this existing problem.

-- 
Best regards,
Pavel Shilovsky.
--
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