diff options
-rw-r--r-- | fs/netfs/direct_write.c | 3 | ||||
-rw-r--r-- | fs/smb/client/cifsfs.c | 6 | ||||
-rw-r--r-- | fs/smb/client/cifsfs.h | 4 | ||||
-rw-r--r-- | fs/smb/client/file.c | 23 | ||||
-rw-r--r-- | fs/smb/client/smb2ops.c | 2 | ||||
-rw-r--r-- | include/linux/netfs.h | 2 |
6 files changed, 34 insertions, 6 deletions
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/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/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 */ 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/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index ef18cd30f66c..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, @@ -3636,6 +3637,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) 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 */ |