Re: [PATCH 5/5] CIFS: Fix write after setting a read lock for read oplock files

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

 



2012/11/28 Jeff Layton <jlayton@xxxxxxxxxx>:
> On Wed, 28 Nov 2012 16:12:56 +0400
> Pavel Shilovsky <piastry@xxxxxxxxxxx> wrote:
>
>> 2012/11/28 Jeff Layton <jlayton@xxxxxxxxxx>:
>> > On Tue, 27 Nov 2012 18:57:22 +0400
>> > Pavel Shilovsky <piastry@xxxxxxxxxxx> wrote:
>> >
>> >> 2012/11/27 Jeff Layton <jlayton@xxxxxxxxxx>:
>> >> > On Tue, 27 Nov 2012 10:50:28 +0400
>> >> > Pavel Shilovsky <piastry@xxxxxxxxxxx> wrote:
>> >> >
>> >> >> If we have a read oplock and set a read lock in it, we can't write to the
>> >> >> locked area - so, filemap_fdatawrite may fail with a no information for a
>> >> >> userspace application even if we request a write to non-locked area. Fix
>> >> >> this by replacing it with filemap_write_and_wait call and sending non-page
>> >> >> write in a error case.
>> >> >>
>> >> >> While this may end up with two write requests to the server, we can be sure
>> >> >> that our data will be the same at the server and the page cache - the next read
>> >> >> on this file gets the valid data.
>> >> >>
>> >> >> Signed-off-by: Pavel Shilovsky <piastry@xxxxxxxxxxx>
>> >> >> ---
>> >> >>  fs/cifs/file.c |   10 ++++------
>> >> >>  1 file changed, 4 insertions(+), 6 deletions(-)
>> >> >>
>> >> >> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
>> >> >> index f8fe1bd..89efd85 100644
>> >> >> --- a/fs/cifs/file.c
>> >> >> +++ b/fs/cifs/file.c
>> >> >> @@ -2511,14 +2511,12 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
>> >> >>        */
>> >> >>       if (!cinode->clientCanCacheAll && cinode->clientCanCacheRead) {
>> >> >>               ssize_t written;
>> >> >> -             int rc;
>> >> >>
>> >> >>               written = generic_file_aio_write(iocb, iov, nr_segs, pos);
>> >> >> -             rc = filemap_fdatawrite(inode->i_mapping);
>> >> >> -             if (rc)
>> >> >> -                     return (ssize_t)rc;
>> >> >> -
>> >> >> -             return written;
>> >> >> +             /* try page write at first */
>> >> >> +             if (!filemap_write_and_wait(inode->i_mapping))
>> >> >> +                     return written;
>> >> >> +             /* page write failed - try from pos to pos+len-1 */
>> >> >>       }
>> >> >>  #endif
>> >> >>
>> >> >
>> >> > Bleh -- nasty. I guess this will work though...
>> >> >
>> >> > Wonder if there's some way to populate the cache and then just mark the
>> >> > pages clean without sending out writes? That would be a better solution
>> >> > IMO, but I guess we can live with this for now...
>> >> >
>> >> > Acked-by: Jeff Layton <jlayton@xxxxxxxxxx>
>> >>
>> >> Thanks for reviewing the patchset.
>> >>
>> >> As for this patch I have the followon patch:
>> >>
>> >> http://git.altlinux.org/people/piastry/public/?p=cifs-2.6.git;a=commitdiff;h=11673376e6840c686f0c6e51892b16ad1945887e
>> >>
>> >> that allows us to populate the page cache without making pages dirty.
>> >> I didn't have enough time to test it well (that's why I haven't posted
>> >> it yet)  - going to do it tomorrow. But you are welcome to comment the
>> >> approach.
>> >>
>> >
>> > The only thing that makes me wary here is that you're setting this flag
>> > on the inode. Could there ever be a situation where another task might
>> > be writing to this inode at the same time and needs to set them dirty?
>> >
>> > If not, then I'm not sure I see the need for a new bool in the inode.
>> > It might be simpler to just check what sort of oplock you have in
>> > write_end instead.
>> >
>> > There's also a lot of logic around what sort of locking you're doing
>> > here too. I think we ought to do the same sort of I/O regardless of
>> > whether POSIX locks are being used or not.
>> >
>>
>> There are some places where VFS code uses write_end call (through
>> pagecache_write_end) but I didn't find any place where cifs code can
>> hit it. So, I think we can assume now that cifs_write_end is called
>> only from generic_file_aio_write codepath. If so, we can be sure that
>> only on process may want to set pages dirty through cifs_write_end due
>> to i_mutex lock.
>>
>> It seems your are right and we can use clientCanCacheAll value
>> directly from cifs_write_end - will make changes. Also, I think I can
>> merge these two patches into one.
>>
>> Thanks.
>>
>
> Note though, that it matters what sort of cache= option is in force
> too. If cache=loose then you *do* want to set the page dirty.

This makes sense, thanks.

-- 
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