[linux-cifs-client] Re: [PATCH] cifs: Convert cifs to new aops.

Steve French smfrench at gmail.com
Wed Sep 24 19:34:44 GMT 2008


I have reviewed the patch and merged into cifs-2.6.git tree.

Will do some additional testing (with fsx and other test tools) while
at SDC plugfest this week.

On Wed, Sep 24, 2008 at 12:54 PM, Christoph Hellwig <hch at infradead.org> wrote:
> Might be worth Ccing Nick as he's started on finishing the last aops
> conversions again at Kernel Summit.
>
> On Wed, Sep 24, 2008 at 01:39:13PM -0400, Jeff Layton wrote:
>> This patch is based on the one originally posted by Nick Piggin. His
>> patch was very close, but had a couple of small bugs. Nick's original
>> comments follow:
>>
>> ---------------[snip]--------------
>>
>> This is another relatively naive conversion. Always do the read upfront
>> when the page is not uptodate (unless we're in the writethrough path).
>>
>> Fix an uninitialized data exposure where SetPageUptodate was called
>> before the page was uptodate.
>>
>> SetPageUptodate and switch to writeback mode in the case that the full
>> page was dirtied.
>>
>> Signed-off-by: Jeff Layton <jlayton at redhat.com>
>> Reviewed-by: Badari Pulavarty <pbadari at us.ibm.com>
>> Acked-by: Dave Kleikamp <shaggy at linux.vnet.ibm.com>
>> Cc: Steve French <smfrench at gmail.com>
>> Cc: Nick Piggin <npiggin at suse.de>
>> ---
>>  fs/cifs/file.c |  120 +++++++++++++++++++++++++++----------------------------
>>  1 files changed, 59 insertions(+), 61 deletions(-)
>>
>> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
>> index d39e852..c4a8a06 100644
>> --- a/fs/cifs/file.c
>> +++ b/fs/cifs/file.c
>> @@ -107,7 +107,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
>>
>>       /* want handles we can use to read with first
>>          in the list so we do not have to walk the
>> -        list to search for one in prepare_write */
>> +        list to search for one in write_begin */
>>       if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
>>               list_add_tail(&pCifsFile->flist,
>>                             &pCifsInode->openFileList);
>> @@ -915,7 +915,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
>>  }
>>
>>  static ssize_t cifs_write(struct file *file, const char *write_data,
>> -     size_t write_size, loff_t *poffset)
>> +                       size_t write_size, loff_t *poffset)
>>  {
>>       int rc = 0;
>>       unsigned int bytes_written = 0;
>> @@ -1455,49 +1455,52 @@ static int cifs_writepage(struct page *page, struct writeback_control *wbc)
>>       return rc;
>>  }
>>
>> -static int cifs_commit_write(struct file *file, struct page *page,
>> -     unsigned offset, unsigned to)
>> +static int cifs_write_end(struct file *file, struct address_space *mapping,
>> +                     loff_t pos, unsigned len, unsigned copied,
>> +                     struct page *page, void *fsdata)
>>  {
>> -     int xid;
>> -     int rc = 0;
>> -     struct inode *inode = page->mapping->host;
>> -     loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
>> -     char *page_data;
>> +     int rc;
>> +     struct inode *inode = mapping->host;
>>
>> -     xid = GetXid();
>> -     cFYI(1, ("commit write for page %p up to position %lld for %d",
>> -              page, position, to));
>> -     spin_lock(&inode->i_lock);
>> -     if (position > inode->i_size)
>> -             i_size_write(inode, position);
>> +     cFYI(1, ("write_end for page %p from pos %lld with %d bytes",
>> +              page, pos, copied));
>> +
>> +     if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
>> +             SetPageUptodate(page);
>>
>> -     spin_unlock(&inode->i_lock);
>>       if (!PageUptodate(page)) {
>> -             position =  ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
>> -             /* can not rely on (or let) writepage write this data */
>> -             if (to < offset) {
>> -                     cFYI(1, ("Illegal offsets, can not copy from %d to %d",
>> -                             offset, to));
>> -                     FreeXid(xid);
>> -                     return rc;
>> -             }
>> +             char *page_data;
>> +             unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
>> +             int xid;
>> +
>> +             xid = GetXid();
>>               /* this is probably better than directly calling
>>                  partialpage_write since in this function the file handle is
>>                  known which we might as well leverage */
>>               /* BB check if anything else missing out of ppw
>>                  such as updating last write time */
>>               page_data = kmap(page);
>> -             rc = cifs_write(file, page_data + offset, to-offset,
>> -                             &position);
>> -             if (rc > 0)
>> -                     rc = 0;
>> -             /* else if (rc < 0) should we set writebehind rc? */
>> +             rc = cifs_write(file, page_data + offset, copied, &pos);
>> +             /* if (rc < 0) should we set writebehind rc? */
>>               kunmap(page);
>> +
>> +             FreeXid(xid);
>>       } else {
>> +             rc = copied;
>> +             pos += copied;
>>               set_page_dirty(page);
>>       }
>>
>> -     FreeXid(xid);
>> +     if (rc > 0) {
>> +             spin_lock(&inode->i_lock);
>> +             if (pos > inode->i_size)
>> +                     i_size_write(inode, pos);
>> +             spin_unlock(&inode->i_lock);
>> +     }
>> +
>> +     unlock_page(page);
>> +     page_cache_release(page);
>> +
>>       return rc;
>>  }
>>
>> @@ -2043,49 +2046,44 @@ bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
>>               return true;
>>  }
>>
>> -static int cifs_prepare_write(struct file *file, struct page *page,
>> -     unsigned from, unsigned to)
>> +static int cifs_write_begin(struct file *file, struct address_space *mapping,
>> +                     loff_t pos, unsigned len, unsigned flags,
>> +                     struct page **pagep, void **fsdata)
>>  {
>> -     int rc = 0;
>> -     loff_t i_size;
>> -     loff_t offset;
>> +     pgoff_t index = pos >> PAGE_CACHE_SHIFT;
>> +     loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
>> +
>> +     cFYI(1, ("write_begin from %lld len %d", (long long)pos, len));
>> +
>> +     *pagep = __grab_cache_page(mapping, index);
>> +     if (!*pagep)
>> +             return -ENOMEM;
>>
>> -     cFYI(1, ("prepare write for page %p from %d to %d", page, from, to));
>> -     if (PageUptodate(page))
>> +     if (PageUptodate(*pagep))
>>               return 0;
>>
>>       /* If we are writing a full page it will be up to date,
>>          no need to read from the server */
>> -     if ((to == PAGE_CACHE_SIZE) && (from == 0)) {
>> -             SetPageUptodate(page);
>> +     if (len == PAGE_CACHE_SIZE && flags & AOP_FLAG_UNINTERRUPTIBLE)
>>               return 0;
>> -     }
>>
>> -     offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
>> -     i_size = i_size_read(page->mapping->host);
>> +     if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
>> +             int rc;
>>
>> -     if ((offset >= i_size) ||
>> -         ((from == 0) && (offset + to) >= i_size)) {
>> -             /*
>> -              * We don't need to read data beyond the end of the file.
>> -              * zero it, and set the page uptodate
>> -              */
>> -             simple_prepare_write(file, page, from, to);
>> -             SetPageUptodate(page);
>> -     } else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
>>               /* might as well read a page, it is fast enough */
>> -             rc = cifs_readpage_worker(file, page, &offset);
>> +             rc = cifs_readpage_worker(file, *pagep, &offset);
>> +
>> +             /* we do not need to pass errors back
>> +                e.g. if we do not have read access to the file
>> +                because cifs_write_end will attempt synchronous writes
>> +                -- shaggy */
>>       } else {
>>               /* we could try using another file handle if there is one -
>>                  but how would we lock it to prevent close of that handle
>>                  racing with this read? In any case
>> -                this will be written out by commit_write so is fine */
>> +                this will be written out by write_end so is fine */
>>       }
>>
>> -     /* we do not need to pass errors back
>> -        e.g. if we do not have read access to the file
>> -        because cifs_commit_write will do the right thing.  -- shaggy */
>> -
>>       return 0;
>>  }
>>
>> @@ -2094,8 +2092,8 @@ const struct address_space_operations cifs_addr_ops = {
>>       .readpages = cifs_readpages,
>>       .writepage = cifs_writepage,
>>       .writepages = cifs_writepages,
>> -     .prepare_write = cifs_prepare_write,
>> -     .commit_write = cifs_commit_write,
>> +     .write_begin = cifs_write_begin,
>> +     .write_end = cifs_write_end,
>>       .set_page_dirty = __set_page_dirty_nobuffers,
>>       /* .sync_page = cifs_sync_page, */
>>       /* .direct_IO = */
>> @@ -2110,8 +2108,8 @@ const struct address_space_operations cifs_addr_ops_smallbuf = {
>>       .readpage = cifs_readpage,
>>       .writepage = cifs_writepage,
>>       .writepages = cifs_writepages,
>> -     .prepare_write = cifs_prepare_write,
>> -     .commit_write = cifs_commit_write,
>> +     .write_begin = cifs_write_begin,
>> +     .write_end = cifs_write_end,
>>       .set_page_dirty = __set_page_dirty_nobuffers,
>>       /* .sync_page = cifs_sync_page, */
>>       /* .direct_IO = */
>> --
>> 1.5.5.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
> ---end quoted text---
>



-- 
Thanks,

Steve


More information about the linux-cifs-client mailing list