From 16e00683dc74cf1fcdf00046b90852bee05eb94a Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 15 May 2024 18:06:03 -0500 Subject: smb3: reenable swapfiles over SMB3 mounts With the changes to folios/netfs it is now easier to reenable swapfile support over SMB3 which fixes various xfstests Reviewed-by: David Howells Suggested-by: David Howells Fixes: e1209d3a7a67 ("mm: introduce ->swap_rw and use it for reads from SWP_FS_OPS swap-space") Signed-off-by: Steve French --- fs/netfs/direct_write.c | 3 ++- fs/smb/client/file.c | 23 +++++++++++++++++++++++ include/linux/netfs.h | 2 ++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c index 608ba6416919..f516460e994e 100644 --- a/fs/netfs/direct_write.c +++ b/fs/netfs/direct_write.c @@ -27,7 +27,7 @@ static void netfs_cleanup_dio_write(struct netfs_io_request *wreq) * Perform an unbuffered write where we may have to do an RMW operation on an * encrypted file. This can also be used for direct I/O writes. */ -static ssize_t netfs_unbuffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *iter, +ssize_t netfs_unbuffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *iter, struct netfs_group *netfs_group) { struct netfs_io_request *wreq; @@ -117,6 +117,7 @@ out: netfs_put_request(wreq, false, netfs_rreq_trace_put_return); return ret; } +EXPORT_SYMBOL(netfs_unbuffered_write_iter_locked); /** * netfs_unbuffered_write_iter - Unbuffered write to a file diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index 9d38294a7e68..9d5c2440abfc 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -3189,6 +3189,28 @@ static void cifs_swap_deactivate(struct file *file) /* do we need to unpin (or unlock) the file */ } +/** + * cifs_swap_rw - SMB3 address space operation for swap I/O + * @iocb: target I/O control block + * @iter: I/O buffer + * + * Perform IO to the swap-file. This is much like direct IO. + */ +static int cifs_swap_rw(struct kiocb *iocb, struct iov_iter *iter) +{ + ssize_t ret; + + WARN_ON_ONCE(iov_iter_count(iter) != PAGE_SIZE); + + if (iov_iter_rw(iter) == READ) + ret = netfs_unbuffered_read_iter_locked(iocb, iter); + else + ret = netfs_unbuffered_write_iter_locked(iocb, iter, NULL); + if (ret < 0) + return ret; + return 0; +} + const struct address_space_operations cifs_addr_ops = { .read_folio = netfs_read_folio, .readahead = netfs_readahead, @@ -3204,6 +3226,7 @@ const struct address_space_operations cifs_addr_ops = { */ .swap_activate = cifs_swap_activate, .swap_deactivate = cifs_swap_deactivate, + .swap_rw = cifs_swap_rw, }; /* diff --git a/include/linux/netfs.h b/include/linux/netfs.h index ca56a4428043..d2d291a9cdad 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -400,6 +400,8 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, ssize_t netfs_buffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *from, struct netfs_group *netfs_group); ssize_t netfs_unbuffered_write_iter(struct kiocb *iocb, struct iov_iter *from); +ssize_t netfs_unbuffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *iter, + struct netfs_group *netfs_group); ssize_t netfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from); /* Address operations API */ -- cgit v1.2.3 From 10c623a1956e673a9268493e0dacf373ddb2f9bf Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 15 May 2024 11:03:35 -0500 Subject: cifs: update internal version number to 2.49 Signed-off-by: Steve French --- fs/smb/client/cifsfs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h index 87310f05d397..62d5fee3e5eb 100644 --- a/fs/smb/client/cifsfs.h +++ b/fs/smb/client/cifsfs.h @@ -147,6 +147,6 @@ extern const struct export_operations cifs_export_ops; #endif /* CONFIG_CIFS_NFSD_EXPORT */ /* when changing internal version - update following two lines at same time */ -#define SMB3_PRODUCT_BUILD 48 -#define CIFS_VERSION "2.48" +#define SMB3_PRODUCT_BUILD 49 +#define CIFS_VERSION "2.49" #endif /* _CIFSFS_H */ -- cgit v1.2.3 From 8a1607233566fef7fbe30416e5d3b0567d0d1fba Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 22 May 2024 09:38:48 +0100 Subject: cifs: Fix smb3_insert_range() to move the zero_point Fix smb3_insert_range() to move the zero_point over to the new EOF. Without this, generic/147 fails as reads of data beyond the old EOF point return zeroes. Fixes: 3ee1a1fc3981 ("cifs: Cut over to using netfslib") Signed-off-by: David Howells cc: Shyam Prasad N cc: Rohith Surabattula cc: Jeff Layton cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev Signed-off-by: Steve French --- fs/smb/client/smb2ops.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index ef18cd30f66c..b87b70edd0be 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -3636,6 +3636,7 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon, rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len); if (rc < 0) goto out_2; + cifsi->netfs.zero_point = new_eof; rc = smb3_zero_data(file, tcon, off, len, xid); if (rc < 0) -- cgit v1.2.3 From 93a43155127fec0f8cc942d63b76668c2f8f69fa Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 24 May 2024 15:23:36 +0100 Subject: cifs: Fix missing set of remote_i_size Occasionally, the generic/001 xfstest will fail indicating corruption in one of the copy chains when run on cifs against a server that supports FSCTL_DUPLICATE_EXTENTS_TO_FILE (eg. Samba with a share on btrfs). The problem is that the remote_i_size value isn't updated by cifs_setsize() when called by smb2_duplicate_extents(), but i_size *is*. This may cause cifs_remap_file_range() to then skip the bit after calling ->duplicate_extents() that sets sizes. Fix this by calling netfs_resize_file() in smb2_duplicate_extents() before calling cifs_setsize() to set i_size. This means we don't then need to call netfs_resize_file() upon return from ->duplicate_extents(), but we also fix the test to compare against the pre-dup inode size. [Note that this goes back before the addition of remote_i_size with the netfs_inode struct. It should probably have been setting cifsi->server_eof previously.] Fixes: cfc63fc8126a ("smb3: fix cached file size problems in duplicate extents (reflink)") Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Rohith Surabattula cc: Jeff Layton cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev Signed-off-by: Steve French --- fs/smb/client/cifsfs.c | 6 +++--- fs/smb/client/smb2ops.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index ec5b639f421a..a665aac9be9f 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -1226,7 +1226,7 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, struct cifsFileInfo *smb_file_src = src_file->private_data; struct cifsFileInfo *smb_file_target = dst_file->private_data; struct cifs_tcon *target_tcon, *src_tcon; - unsigned long long destend, fstart, fend, new_size; + unsigned long long destend, fstart, fend, old_size, new_size; unsigned int xid; int rc; @@ -1293,6 +1293,7 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, goto unlock; if (fend > target_cifsi->netfs.zero_point) target_cifsi->netfs.zero_point = fend + 1; + old_size = target_cifsi->netfs.remote_i_size; /* Discard all the folios that overlap the destination region. */ cifs_dbg(FYI, "about to discard pages %llx-%llx\n", fstart, fend); @@ -1305,9 +1306,8 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, if (target_tcon->ses->server->ops->duplicate_extents) { rc = target_tcon->ses->server->ops->duplicate_extents(xid, smb_file_src, smb_file_target, off, len, destoff); - if (rc == 0 && new_size > i_size_read(target_inode)) { + if (rc == 0 && new_size > old_size) { truncate_setsize(target_inode, new_size); - netfs_resize_file(&target_cifsi->netfs, new_size, true); fscache_resize_cookie(cifs_inode_cookie(target_inode), new_size); } diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index b87b70edd0be..4ce6c3121a7e 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -2028,6 +2028,7 @@ smb2_duplicate_extents(const unsigned int xid, * size will be queried on next revalidate, but it is important * to make sure that file's cached size is updated immediately */ + netfs_resize_file(netfs_inode(inode), dest_off + len, true); cifs_setsize(inode, dest_off + len); } rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, -- cgit v1.2.3