On Wed, Oct 24, 2018 at 7:09 AM Jeff Layton <jlayton@xxxxxxxxxx> wrote: > > On Tue, 2018-10-23 at 12:50 -0400, Olga Kornievskaia wrote: > > On Mon, Oct 22, 2018 at 7:23 PM Jeff Layton <jlayton@xxxxxxxxxx> wrote: > > > > > > On Mon, 2018-10-22 at 14:32 -0400, Olga Kornievskaia wrote: > > > > On Sun, Oct 21, 2018 at 10:29 AM Jeff Layton <jlayton@xxxxxxxxxx> wrote: > > > > > > > > > > On Fri, 2018-10-19 at 11:29 -0400, Olga Kornievskaia wrote: > > > > > > From: Anna Schumaker <Anna.Schumaker@xxxxxxxxxx> > > > > > > > > > > > > Signed-off-by: Anna Schumaker <Anna.Schumaker@xxxxxxxxxx> > > > > > > --- > > > > > > fs/read_write.c | 3 +++ > > > > > > 1 file changed, 3 insertions(+) > > > > > > > > > > > > diff --git a/fs/read_write.c b/fs/read_write.c > > > > > > index 39b4a21..c60790f 100644 > > > > > > --- a/fs/read_write.c > > > > > > +++ b/fs/read_write.c > > > > > > @@ -1570,6 +1570,9 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, > > > > > > if (unlikely(ret)) > > > > > > return ret; > > > > > > > > > > > > + if (pos_in >= i_size_read(inode_in)) > > > > > > + return -EINVAL; > > > > > > + > > > > > > if (!(file_in->f_mode & FMODE_READ) || > > > > > > !(file_out->f_mode & FMODE_WRITE) || > > > > > > (file_out->f_flags & O_APPEND)) > > > > > > > > > > The patch description could use a bit more fleshing-out. The > > > > > copy_file_range manpage says: > > > > > > > > > > EINVAL Requested range extends beyond the end of the source file; or the flags argument is not 0. > > > > > > > > > > So I guess this is intended to satisfy that requirement? > > > > > > > > I agree the description of the patch is poor. It sort of falls under > > > > the the man page's description of range beyond the end of the source > > > > file. But in NFSv4.2, there is an explicit wording for the validity of > > > > the input parameters and having an input source offset that's beyond > > > > the end of the file is what this patch is attempting to check. > > > > > > > > > > Side note: > > > > > > One has to wonder why they decided to make that an -EINVAL condition? > > > > To me that sounds like a correct use of -EINVAL error to check for > > invalid arguments. > > > > You can argue that since there were no bytes to copy then returning 0 > > would be an appropriate "size" of the copy. However, I would argue how > > would a caller distinguish this 0 size which really means don't try to > > copy more vs another case when copy_file_range() returned less byte > > (0) and so that caller should loop to get the rest. > > > > I don't know -- it seems to run contrary to how read(2) and write(2) That's because copy_file_range is not just read/write but also lseek. I think of it as doing lseek(to source offset)->read()->lseek(to dst offset)->write. and lseek() does return EINVAL when position is beyond the end of the file. > work with an EOF condition. I don't see why the implementation wouldn't > want to just copy what you can up to the EOF of the source file. Maybe I > need to go back and review the discussion from when the syscall was > merged... > > > > The system call returns ssize_t. Why not just return a fewer number of > > > bytes in that situation? > > > > > > In fact, the RETURN VALUE section of the manpage says: > > > > > > Upon successful completion, copy_file_range() will return the number of > > > bytes copied between files. This could be less than the length origi‐ > > > nally requested. > > > > > > Under what conditions would that occur that do not include the file > > > being shorter than the range you wanted to copy? > > > > > > I wonder if we ought to lobby to get that changed. > > > > Do you mean ask NFSv4.2 spec to be changed? I thought that's stuff is > > "written in stone". > > > > No, I meant the copy_file_range spec (such as it is). I guess the v4.2 > spec has this though: > > If the source offset or the source offset plus count is greater than > the size of the source file, the operation MUST fail with > NFS4ERR_INVAL. > > I wonder if you'd be better off not trying to enforce this on the client > and simply let the server return NFS4ERR_INVAL if we're beyond EOF on > the source? That way it doesn't matter whether the client's attr cache > is up to date or not. > > > > > > > > > If so, > > > > > i_size_read is just going to return whatever is in inode->isize. > > > > > Could a copy_file_range call end up getting issued to copy from a file > > > > > that is already open on a range that it doesn't know about yet? i.e. > > > > > where the inode cache has not yet been updated. > > > > > > > > I thought that with NFSv4 cache consistency, the inode->isize is > > > > accurate. If previous open had a read delegation, any modification on > > > > a server would trigger a CB_RECALL and the open for the copy offload > > > > would retrieve the latest size. In case of no delegations, the open > > > > retrieves the latest size and the call to copy_file_range() would have > > > > an update size. > > > > > > > > It seems like that could on network filesystems (like NFS). Would this > > > > > be better handled in ->copy_file_range instead, where the driver could > > > > > make a better determination of the file size? > > > > > > > > I'm not opposed to moving the size check into the NFS's copy_file_size > > > > (again in my opinion NFS attribute cache has the same file size as the > > > > inode's size). I think the thought was that such check should be done > > > > at the VFS layer as oppose to doing it by each of the file systems. > > > > > > > > > > > > > > The attribute cache is not revalidated before the i_size is fetched with > > > i_size_read. You're just reading what happens to be in the in-memory > > > inode structure. So both clients have the file open already, and neither > > > has a delegation: > > > > > > client 1: fetches attributes from file and sees a size of 1000 > > > client 2: writes 20 bytes at offset 1000 > > > client 1: calls copy file range to copy 1020 bytes starting at offset 0 > > > > > > If client1 didn't get an attribute update before the copy_file_range > > > call came in, then it would still think the size was 1000 and fail the > > > operation. It may even be many seconds before client1 sees the updated > > > size. > > > > > > You could argue that we're not using locking here so you're just subject > > > to normal open-to-close cache coherency behavior, but that's rather "not > > > nice". > > > > Yes I would argue that locking needs to be used. In case your > > describing it is impossible to get an accurate file size. Even if the > > client issues a GETATTR there is nothing prevents another client from > > changing it right after that GETATTR was already replied to. > > > > What nfscopy application does is it opens then file and then locks it > > (as suggested by the spec), then calls the copy_file_range() system > > call. You can argue (if we didn't get a delegation) that a file might > > have been changed between the reply to the OPEN and the LOCK operation > > and therefore, we should send another GETATTR just in case. To guard > > against that, I can add a getattr call though I think it's an overkill > > specially since linux server always grants us a read delegation. > > > > The spec does say you might need to lock the files but they don't say > you SHOULD, only that servers need to be able to deal with lock > stateids. hat said, you have a good point. We're not violating anything > by not revalidating the cache beforehand. Maybe we don't need to do this > after all. > > Personally, I think this would be best enforced by the NFS server. Just > fire off the COPY request as-is and let the server vet the lengths. > > Side note: a delegation is never guaranteed. knfsd won't grant one if > the inode falls afoul of the bloom filter, for instance, and that can > easily happen if (for example) there is a hash collision between > different inodes. I could push the checking validity of the arguments to the server (but to me it sounds lame: a failure will require a network roundtrip). But one can argue the server needs to check the validity of the arguments anyway (as it can't rely on the client to play nice). I still think the check should be done in both places (client and server). And I feel like VFS is the right place to do so (as this check implements what the man page states). But I don't feel strongly about dropping the patch all together (I'll add a patch to the server). > > > I think we probably ought to also push this check down into the > > > filesystem operations as well, and have copy_file_range ensure that the > > > attribute cache is updated. We're dealing with copy offload here so > > > doing an extra GETATTR beforehand shouldn't be terribly costly. > > > -- > > > Jeff Layton <jlayton@xxxxxxxxxx> > > -- > Jeff Layton <jlayton@xxxxxxxxxx> >