Merge branch 'cifs-netfs' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull cifs netfs updates from David Howells: This ports cifs over to use the netfs library. * 'cifs-netfs' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: cifs: Enable large folio support cifs: Remove some code that's no longer used, part 3 cifs: Remove some code that's no longer used, part 2 cifs: Remove some code that's no longer used, part 1 cifs: Cut over to using netfslib cifs: Implement netfslib hooks cifs: Make add_credits_and_wake_if() clear deducted credits cifs: Add mempools for cifs_io_request and cifs_io_subrequest structs cifs: Set zero_point in the copy_file_range() and remap_file_range() cifs: Move cifs_loose_read_iter() and cifs_file_write_iter() to file.c cifs: Replace the writedata replay bool with a netfs sreq flag cifs: Make wait_mtu_credits take size_t args cifs: Use more fields from netfs_io_subrequest cifs: Replace cifs_writedata with a wrapper around netfs_io_subrequest cifs: Replace cifs_readdata with a wrapper around netfs_io_subrequest cifs: Use alternative invalidation to using launder_folio Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
commit
e2bc9f6cfb
@ -405,6 +405,9 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
|
||||
} while (iov_iter_count(iter));
|
||||
|
||||
out:
|
||||
if (likely(written) && ctx->ops->post_modify)
|
||||
ctx->ops->post_modify(inode);
|
||||
|
||||
if (unlikely(wreq)) {
|
||||
ret2 = netfs_end_writethrough(wreq, &wbc, writethrough);
|
||||
wbc_detach_inode(&wbc);
|
||||
@ -521,6 +524,7 @@ vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_gr
|
||||
struct folio *folio = page_folio(vmf->page);
|
||||
struct file *file = vmf->vma->vm_file;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct netfs_inode *ictx = netfs_inode(inode);
|
||||
vm_fault_t ret = VM_FAULT_RETRY;
|
||||
int err;
|
||||
|
||||
@ -567,6 +571,8 @@ vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_gr
|
||||
trace_netfs_folio(folio, netfs_folio_trace_mkwrite);
|
||||
netfs_set_group(folio, netfs_group);
|
||||
file_update_time(file);
|
||||
if (ictx->ops->post_modify)
|
||||
ictx->ops->post_modify(inode);
|
||||
ret = VM_FAULT_LOCKED;
|
||||
out:
|
||||
sb_end_pagefault(inode->i_sb);
|
||||
|
@ -213,8 +213,13 @@ static void netfs_rreq_assess_dio(struct netfs_io_request *rreq)
|
||||
unsigned int i;
|
||||
size_t transferred = 0;
|
||||
|
||||
for (i = 0; i < rreq->direct_bv_count; i++)
|
||||
for (i = 0; i < rreq->direct_bv_count; i++) {
|
||||
flush_dcache_page(rreq->direct_bv[i].bv_page);
|
||||
// TODO: cifs marks pages in the destination buffer
|
||||
// dirty under some circumstances after a read. Do we
|
||||
// need to do that too?
|
||||
set_page_dirty(rreq->direct_bv[i].bv_page);
|
||||
}
|
||||
|
||||
list_for_each_entry(subreq, &rreq->subrequests, rreq_link) {
|
||||
if (subreq->error || subreq->transferred == 0)
|
||||
|
@ -2,6 +2,7 @@
|
||||
config CIFS
|
||||
tristate "SMB3 and CIFS support (advanced network filesystem)"
|
||||
depends on INET
|
||||
select NETFS_SUPPORT
|
||||
select NLS
|
||||
select NLS_UCS2_UTILS
|
||||
select CRYPTO
|
||||
|
@ -371,9 +371,13 @@ static struct kmem_cache *cifs_inode_cachep;
|
||||
static struct kmem_cache *cifs_req_cachep;
|
||||
static struct kmem_cache *cifs_mid_cachep;
|
||||
static struct kmem_cache *cifs_sm_req_cachep;
|
||||
static struct kmem_cache *cifs_io_request_cachep;
|
||||
static struct kmem_cache *cifs_io_subrequest_cachep;
|
||||
mempool_t *cifs_sm_req_poolp;
|
||||
mempool_t *cifs_req_poolp;
|
||||
mempool_t *cifs_mid_poolp;
|
||||
mempool_t cifs_io_request_pool;
|
||||
mempool_t cifs_io_subrequest_pool;
|
||||
|
||||
static struct inode *
|
||||
cifs_alloc_inode(struct super_block *sb)
|
||||
@ -986,61 +990,6 @@ out:
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
|
||||
{
|
||||
ssize_t rc;
|
||||
struct inode *inode = file_inode(iocb->ki_filp);
|
||||
|
||||
if (iocb->ki_flags & IOCB_DIRECT)
|
||||
return cifs_user_readv(iocb, iter);
|
||||
|
||||
rc = cifs_revalidate_mapping(inode);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return generic_file_read_iter(iocb, iter);
|
||||
}
|
||||
|
||||
static ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
struct inode *inode = file_inode(iocb->ki_filp);
|
||||
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
||||
ssize_t written;
|
||||
int rc;
|
||||
|
||||
if (iocb->ki_filp->f_flags & O_DIRECT) {
|
||||
written = cifs_user_writev(iocb, from);
|
||||
if (written > 0 && CIFS_CACHE_READ(cinode)) {
|
||||
cifs_zap_mapping(inode);
|
||||
cifs_dbg(FYI,
|
||||
"Set no oplock for inode=%p after a write operation\n",
|
||||
inode);
|
||||
cinode->oplock = 0;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
written = cifs_get_writer(cinode);
|
||||
if (written)
|
||||
return written;
|
||||
|
||||
written = generic_file_write_iter(iocb, from);
|
||||
|
||||
if (CIFS_CACHE_WRITE(CIFS_I(inode)))
|
||||
goto out;
|
||||
|
||||
rc = filemap_fdatawrite(inode->i_mapping);
|
||||
if (rc)
|
||||
cifs_dbg(FYI, "cifs_file_write_iter: %d rc on %p inode\n",
|
||||
rc, inode);
|
||||
|
||||
out:
|
||||
cifs_put_writer(cinode);
|
||||
return written;
|
||||
}
|
||||
|
||||
static loff_t cifs_llseek(struct file *file, loff_t offset, int whence)
|
||||
{
|
||||
struct cifsFileInfo *cfile = file->private_data;
|
||||
@ -1342,6 +1291,8 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
|
||||
rc = cifs_flush_folio(target_inode, destend, &fstart, &fend, false);
|
||||
if (rc)
|
||||
goto unlock;
|
||||
if (fend > target_cifsi->netfs.zero_point)
|
||||
target_cifsi->netfs.zero_point = fend + 1;
|
||||
|
||||
/* Discard all the folios that overlap the destination region. */
|
||||
cifs_dbg(FYI, "about to discard pages %llx-%llx\n", fstart, fend);
|
||||
@ -1360,6 +1311,8 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
|
||||
fscache_resize_cookie(cifs_inode_cookie(target_inode),
|
||||
new_size);
|
||||
}
|
||||
if (rc == 0 && new_size > target_cifsi->netfs.zero_point)
|
||||
target_cifsi->netfs.zero_point = new_size;
|
||||
}
|
||||
|
||||
/* force revalidate of size and timestamps of target file now
|
||||
@ -1451,6 +1404,8 @@ ssize_t cifs_file_copychunk_range(unsigned int xid,
|
||||
rc = cifs_flush_folio(target_inode, destend, &fstart, &fend, false);
|
||||
if (rc)
|
||||
goto unlock;
|
||||
if (fend > target_cifsi->netfs.zero_point)
|
||||
target_cifsi->netfs.zero_point = fend + 1;
|
||||
|
||||
/* Discard all the folios that overlap the destination region. */
|
||||
truncate_inode_pages_range(&target_inode->i_data, fstart, fend);
|
||||
@ -1567,8 +1522,8 @@ const struct file_operations cifs_file_strict_ops = {
|
||||
};
|
||||
|
||||
const struct file_operations cifs_file_direct_ops = {
|
||||
.read_iter = cifs_direct_readv,
|
||||
.write_iter = cifs_direct_writev,
|
||||
.read_iter = netfs_unbuffered_read_iter,
|
||||
.write_iter = netfs_file_write_iter,
|
||||
.open = cifs_open,
|
||||
.release = cifs_close,
|
||||
.lock = cifs_lock,
|
||||
@ -1623,8 +1578,8 @@ const struct file_operations cifs_file_strict_nobrl_ops = {
|
||||
};
|
||||
|
||||
const struct file_operations cifs_file_direct_nobrl_ops = {
|
||||
.read_iter = cifs_direct_readv,
|
||||
.write_iter = cifs_direct_writev,
|
||||
.read_iter = netfs_unbuffered_read_iter,
|
||||
.write_iter = netfs_file_write_iter,
|
||||
.open = cifs_open,
|
||||
.release = cifs_close,
|
||||
.fsync = cifs_fsync,
|
||||
@ -1799,6 +1754,48 @@ static void destroy_mids(void)
|
||||
kmem_cache_destroy(cifs_mid_cachep);
|
||||
}
|
||||
|
||||
static int cifs_init_netfs(void)
|
||||
{
|
||||
cifs_io_request_cachep =
|
||||
kmem_cache_create("cifs_io_request",
|
||||
sizeof(struct cifs_io_request), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (!cifs_io_request_cachep)
|
||||
goto nomem_req;
|
||||
|
||||
if (mempool_init_slab_pool(&cifs_io_request_pool, 100, cifs_io_request_cachep) < 0)
|
||||
goto nomem_reqpool;
|
||||
|
||||
cifs_io_subrequest_cachep =
|
||||
kmem_cache_create("cifs_io_subrequest",
|
||||
sizeof(struct cifs_io_subrequest), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (!cifs_io_subrequest_cachep)
|
||||
goto nomem_subreq;
|
||||
|
||||
if (mempool_init_slab_pool(&cifs_io_subrequest_pool, 100, cifs_io_subrequest_cachep) < 0)
|
||||
goto nomem_subreqpool;
|
||||
|
||||
return 0;
|
||||
|
||||
nomem_subreqpool:
|
||||
kmem_cache_destroy(cifs_io_subrequest_cachep);
|
||||
nomem_subreq:
|
||||
mempool_destroy(&cifs_io_request_pool);
|
||||
nomem_reqpool:
|
||||
kmem_cache_destroy(cifs_io_request_cachep);
|
||||
nomem_req:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void cifs_destroy_netfs(void)
|
||||
{
|
||||
mempool_destroy(&cifs_io_subrequest_pool);
|
||||
kmem_cache_destroy(cifs_io_subrequest_cachep);
|
||||
mempool_destroy(&cifs_io_request_pool);
|
||||
kmem_cache_destroy(cifs_io_request_cachep);
|
||||
}
|
||||
|
||||
static int __init
|
||||
init_cifs(void)
|
||||
{
|
||||
@ -1903,10 +1900,14 @@ init_cifs(void)
|
||||
if (rc)
|
||||
goto out_destroy_deferredclose_wq;
|
||||
|
||||
rc = init_mids();
|
||||
rc = cifs_init_netfs();
|
||||
if (rc)
|
||||
goto out_destroy_inodecache;
|
||||
|
||||
rc = init_mids();
|
||||
if (rc)
|
||||
goto out_destroy_netfs;
|
||||
|
||||
rc = cifs_init_request_bufs();
|
||||
if (rc)
|
||||
goto out_destroy_mids;
|
||||
@ -1961,6 +1962,8 @@ out_destroy_request_bufs:
|
||||
cifs_destroy_request_bufs();
|
||||
out_destroy_mids:
|
||||
destroy_mids();
|
||||
out_destroy_netfs:
|
||||
cifs_destroy_netfs();
|
||||
out_destroy_inodecache:
|
||||
cifs_destroy_inodecache();
|
||||
out_destroy_deferredclose_wq:
|
||||
@ -1999,6 +2002,7 @@ exit_cifs(void)
|
||||
#endif
|
||||
cifs_destroy_request_bufs();
|
||||
destroy_mids();
|
||||
cifs_destroy_netfs();
|
||||
cifs_destroy_inodecache();
|
||||
destroy_workqueue(deferredclose_wq);
|
||||
destroy_workqueue(cifsoplockd_wq);
|
||||
|
@ -69,7 +69,6 @@ extern int cifs_revalidate_file_attr(struct file *filp);
|
||||
extern int cifs_revalidate_dentry_attr(struct dentry *);
|
||||
extern int cifs_revalidate_file(struct file *filp);
|
||||
extern int cifs_revalidate_dentry(struct dentry *);
|
||||
extern int cifs_invalidate_mapping(struct inode *inode);
|
||||
extern int cifs_revalidate_mapping(struct inode *inode);
|
||||
extern int cifs_zap_mapping(struct inode *inode);
|
||||
extern int cifs_getattr(struct mnt_idmap *, const struct path *,
|
||||
@ -85,6 +84,7 @@ extern const struct inode_operations cifs_namespace_inode_operations;
|
||||
|
||||
|
||||
/* Functions related to files and directories */
|
||||
extern const struct netfs_request_ops cifs_req_ops;
|
||||
extern const struct file_operations cifs_file_ops;
|
||||
extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
|
||||
extern const struct file_operations cifs_file_strict_ops; /* if strictio mnt */
|
||||
@ -94,12 +94,10 @@ extern const struct file_operations cifs_file_strict_nobrl_ops;
|
||||
extern int cifs_open(struct inode *inode, struct file *file);
|
||||
extern int cifs_close(struct inode *inode, struct file *file);
|
||||
extern int cifs_closedir(struct inode *inode, struct file *file);
|
||||
extern ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to);
|
||||
extern ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to);
|
||||
extern ssize_t cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to);
|
||||
extern ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from);
|
||||
extern ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from);
|
||||
extern ssize_t cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from);
|
||||
ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from);
|
||||
ssize_t cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter);
|
||||
extern int cifs_flock(struct file *pfile, int cmd, struct file_lock *plock);
|
||||
extern int cifs_lock(struct file *, int, struct file_lock *);
|
||||
extern int cifs_fsync(struct file *, loff_t, loff_t, int);
|
||||
@ -110,9 +108,6 @@ extern int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma);
|
||||
extern const struct file_operations cifs_dir_ops;
|
||||
extern int cifs_dir_open(struct inode *inode, struct file *file);
|
||||
extern int cifs_readdir(struct file *file, struct dir_context *ctx);
|
||||
extern void cifs_pages_written_back(struct inode *inode, loff_t start, unsigned int len);
|
||||
extern void cifs_pages_write_failed(struct inode *inode, loff_t start, unsigned int len);
|
||||
extern void cifs_pages_write_redirty(struct inode *inode, loff_t start, unsigned int len);
|
||||
|
||||
/* Functions related to dir entries */
|
||||
extern const struct dentry_operations cifs_dentry_ops;
|
||||
|
@ -268,8 +268,7 @@ struct dfs_info3_param;
|
||||
struct cifs_fattr;
|
||||
struct smb3_fs_context;
|
||||
struct cifs_fid;
|
||||
struct cifs_readdata;
|
||||
struct cifs_writedata;
|
||||
struct cifs_io_subrequest;
|
||||
struct cifs_io_parms;
|
||||
struct cifs_search_info;
|
||||
struct cifsInodeInfo;
|
||||
@ -450,10 +449,9 @@ struct smb_version_operations {
|
||||
/* send a flush request to the server */
|
||||
int (*flush)(const unsigned int, struct cifs_tcon *, struct cifs_fid *);
|
||||
/* async read from the server */
|
||||
int (*async_readv)(struct cifs_readdata *);
|
||||
int (*async_readv)(struct cifs_io_subrequest *);
|
||||
/* async write to the server */
|
||||
int (*async_writev)(struct cifs_writedata *,
|
||||
void (*release)(struct kref *));
|
||||
void (*async_writev)(struct cifs_io_subrequest *);
|
||||
/* sync read from the server */
|
||||
int (*sync_read)(const unsigned int, struct cifs_fid *,
|
||||
struct cifs_io_parms *, unsigned int *, char **,
|
||||
@ -548,8 +546,8 @@ struct smb_version_operations {
|
||||
/* writepages retry size */
|
||||
unsigned int (*wp_retry_size)(struct inode *);
|
||||
/* get mtu credits */
|
||||
int (*wait_mtu_credits)(struct TCP_Server_Info *, unsigned int,
|
||||
unsigned int *, struct cifs_credits *);
|
||||
int (*wait_mtu_credits)(struct TCP_Server_Info *, size_t,
|
||||
size_t *, struct cifs_credits *);
|
||||
/* adjust previously taken mtu credits to request size */
|
||||
int (*adjust_credits)(struct TCP_Server_Info *server,
|
||||
struct cifs_credits *credits,
|
||||
@ -883,11 +881,12 @@ add_credits(struct TCP_Server_Info *server, const struct cifs_credits *credits,
|
||||
|
||||
static inline void
|
||||
add_credits_and_wake_if(struct TCP_Server_Info *server,
|
||||
const struct cifs_credits *credits, const int optype)
|
||||
struct cifs_credits *credits, const int optype)
|
||||
{
|
||||
if (credits->value) {
|
||||
server->ops->add_credits(server, credits, optype);
|
||||
wake_up(&server->request_q);
|
||||
credits->value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1492,21 +1491,24 @@ struct cifs_aio_ctx {
|
||||
bool direct_io;
|
||||
};
|
||||
|
||||
/* asynchronous read support */
|
||||
struct cifs_readdata {
|
||||
struct kref refcount;
|
||||
struct list_head list;
|
||||
struct completion done;
|
||||
struct cifs_io_request {
|
||||
struct netfs_io_request rreq;
|
||||
struct cifsFileInfo *cfile;
|
||||
struct address_space *mapping;
|
||||
struct cifs_aio_ctx *ctx;
|
||||
__u64 offset;
|
||||
};
|
||||
|
||||
/* asynchronous read support */
|
||||
struct cifs_io_subrequest {
|
||||
union {
|
||||
struct netfs_io_subrequest subreq;
|
||||
struct netfs_io_request *rreq;
|
||||
struct cifs_io_request *req;
|
||||
};
|
||||
ssize_t got_bytes;
|
||||
unsigned int bytes;
|
||||
pid_t pid;
|
||||
unsigned int xid;
|
||||
int result;
|
||||
struct work_struct work;
|
||||
struct iov_iter iter;
|
||||
bool have_xid;
|
||||
bool replay;
|
||||
struct kvec iov[2];
|
||||
struct TCP_Server_Info *server;
|
||||
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||
@ -1515,29 +1517,6 @@ struct cifs_readdata {
|
||||
struct cifs_credits credits;
|
||||
};
|
||||
|
||||
/* asynchronous write support */
|
||||
struct cifs_writedata {
|
||||
struct kref refcount;
|
||||
struct list_head list;
|
||||
struct completion done;
|
||||
enum writeback_sync_modes sync_mode;
|
||||
struct work_struct work;
|
||||
struct cifsFileInfo *cfile;
|
||||
struct cifs_aio_ctx *ctx;
|
||||
struct iov_iter iter;
|
||||
struct bio_vec *bv;
|
||||
__u64 offset;
|
||||
pid_t pid;
|
||||
unsigned int bytes;
|
||||
int result;
|
||||
struct TCP_Server_Info *server;
|
||||
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||
struct smbd_mr *mr;
|
||||
#endif
|
||||
struct cifs_credits credits;
|
||||
bool replay;
|
||||
};
|
||||
|
||||
/*
|
||||
* Take a reference on the file private data. Must be called with
|
||||
* cfile->file_info_lock held.
|
||||
@ -2115,6 +2094,8 @@ extern __u32 cifs_lock_secret;
|
||||
extern mempool_t *cifs_sm_req_poolp;
|
||||
extern mempool_t *cifs_req_poolp;
|
||||
extern mempool_t *cifs_mid_poolp;
|
||||
extern mempool_t cifs_io_request_pool;
|
||||
extern mempool_t cifs_io_subrequest_pool;
|
||||
|
||||
/* Operations for different SMB versions */
|
||||
#define SMB1_VERSION_STRING "1.0"
|
||||
|
@ -121,7 +121,7 @@ extern struct mid_q_entry *cifs_setup_async_request(struct TCP_Server_Info *,
|
||||
extern int cifs_check_receive(struct mid_q_entry *mid,
|
||||
struct TCP_Server_Info *server, bool log_error);
|
||||
extern int cifs_wait_mtu_credits(struct TCP_Server_Info *server,
|
||||
unsigned int size, unsigned int *num,
|
||||
size_t size, size_t *num,
|
||||
struct cifs_credits *credits);
|
||||
extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
|
||||
struct kvec *, int /* nvec to send */,
|
||||
@ -148,6 +148,8 @@ extern bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 eof,
|
||||
bool from_readdir);
|
||||
extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
|
||||
unsigned int bytes_written);
|
||||
void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t result,
|
||||
bool was_async);
|
||||
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int);
|
||||
extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
|
||||
int flags,
|
||||
@ -599,15 +601,11 @@ void __cifs_put_smb_ses(struct cifs_ses *ses);
|
||||
extern struct cifs_ses *
|
||||
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx);
|
||||
|
||||
void cifs_readdata_release(struct kref *refcount);
|
||||
int cifs_async_readv(struct cifs_readdata *rdata);
|
||||
int cifs_async_readv(struct cifs_io_subrequest *rdata);
|
||||
int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid);
|
||||
|
||||
int cifs_async_writev(struct cifs_writedata *wdata,
|
||||
void (*release)(struct kref *kref));
|
||||
void cifs_async_writev(struct cifs_io_subrequest *wdata);
|
||||
void cifs_writev_complete(struct work_struct *work);
|
||||
struct cifs_writedata *cifs_writedata_alloc(work_func_t complete);
|
||||
void cifs_writedata_release(struct kref *refcount);
|
||||
int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
const unsigned char *path, char *pbuf,
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <linux/swap.h>
|
||||
#include <linux/task_io_accounting_ops.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/netfs.h>
|
||||
#include <trace/events/netfs.h>
|
||||
#include "cifspdu.h"
|
||||
#include "cifsfs.h"
|
||||
#include "cifsglob.h"
|
||||
@ -1262,18 +1264,17 @@ openRetry:
|
||||
static void
|
||||
cifs_readv_callback(struct mid_q_entry *mid)
|
||||
{
|
||||
struct cifs_readdata *rdata = mid->callback_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
|
||||
struct cifs_io_subrequest *rdata = mid->callback_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
struct smb_rqst rqst = { .rq_iov = rdata->iov,
|
||||
.rq_nvec = 2,
|
||||
.rq_iter_size = iov_iter_count(&rdata->iter),
|
||||
.rq_iter = rdata->iter };
|
||||
.rq_iter = rdata->subreq.io_iter };
|
||||
struct cifs_credits credits = { .value = 1, .instance = 0 };
|
||||
|
||||
cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
|
||||
cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu\n",
|
||||
__func__, mid->mid, mid->mid_state, rdata->result,
|
||||
rdata->bytes);
|
||||
rdata->subreq.len);
|
||||
|
||||
switch (mid->mid_state) {
|
||||
case MID_RESPONSE_RECEIVED:
|
||||
@ -1305,30 +1306,36 @@ cifs_readv_callback(struct mid_q_entry *mid)
|
||||
rdata->result = -EIO;
|
||||
}
|
||||
|
||||
queue_work(cifsiod_wq, &rdata->work);
|
||||
if (rdata->result == 0 || rdata->result == -EAGAIN)
|
||||
iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes);
|
||||
rdata->credits.value = 0;
|
||||
netfs_subreq_terminated(&rdata->subreq,
|
||||
(rdata->result == 0 || rdata->result == -EAGAIN) ?
|
||||
rdata->got_bytes : rdata->result,
|
||||
false);
|
||||
release_mid(mid);
|
||||
add_credits(server, &credits, 0);
|
||||
}
|
||||
|
||||
/* cifs_async_readv - send an async write, and set up mid to handle result */
|
||||
int
|
||||
cifs_async_readv(struct cifs_readdata *rdata)
|
||||
cifs_async_readv(struct cifs_io_subrequest *rdata)
|
||||
{
|
||||
int rc;
|
||||
READ_REQ *smb = NULL;
|
||||
int wct;
|
||||
struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
|
||||
struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
|
||||
struct smb_rqst rqst = { .rq_iov = rdata->iov,
|
||||
.rq_nvec = 2 };
|
||||
|
||||
cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
|
||||
__func__, rdata->offset, rdata->bytes);
|
||||
cifs_dbg(FYI, "%s: offset=%llu bytes=%zu\n",
|
||||
__func__, rdata->subreq.start, rdata->subreq.len);
|
||||
|
||||
if (tcon->ses->capabilities & CAP_LARGE_FILES)
|
||||
wct = 12;
|
||||
else {
|
||||
wct = 10; /* old style read */
|
||||
if ((rdata->offset >> 32) > 0) {
|
||||
if ((rdata->subreq.start >> 32) > 0) {
|
||||
/* can not handle this big offset for old */
|
||||
return -EIO;
|
||||
}
|
||||
@ -1342,13 +1349,13 @@ cifs_async_readv(struct cifs_readdata *rdata)
|
||||
smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
|
||||
|
||||
smb->AndXCommand = 0xFF; /* none */
|
||||
smb->Fid = rdata->cfile->fid.netfid;
|
||||
smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
|
||||
smb->Fid = rdata->req->cfile->fid.netfid;
|
||||
smb->OffsetLow = cpu_to_le32(rdata->subreq.start & 0xFFFFFFFF);
|
||||
if (wct == 12)
|
||||
smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
|
||||
smb->OffsetHigh = cpu_to_le32(rdata->subreq.start >> 32);
|
||||
smb->Remaining = 0;
|
||||
smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
|
||||
smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
|
||||
smb->MaxCount = cpu_to_le16(rdata->subreq.len & 0xFFFF);
|
||||
smb->MaxCountHigh = cpu_to_le32(rdata->subreq.len >> 16);
|
||||
if (wct == 12)
|
||||
smb->ByteCount = 0;
|
||||
else {
|
||||
@ -1364,15 +1371,11 @@ cifs_async_readv(struct cifs_readdata *rdata)
|
||||
rdata->iov[1].iov_base = (char *)smb + 4;
|
||||
rdata->iov[1].iov_len = get_rfc1002_length(smb);
|
||||
|
||||
kref_get(&rdata->refcount);
|
||||
rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
|
||||
cifs_readv_callback, NULL, rdata, 0, NULL);
|
||||
|
||||
if (rc == 0)
|
||||
cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
|
||||
else
|
||||
kref_put(&rdata->refcount, cifs_readdata_release);
|
||||
|
||||
cifs_small_buf_release(smb);
|
||||
return rc;
|
||||
}
|
||||
@ -1615,16 +1618,17 @@ CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
|
||||
static void
|
||||
cifs_writev_callback(struct mid_q_entry *mid)
|
||||
{
|
||||
struct cifs_writedata *wdata = mid->callback_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
|
||||
unsigned int written;
|
||||
struct cifs_io_subrequest *wdata = mid->callback_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
|
||||
WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
|
||||
struct cifs_credits credits = { .value = 1, .instance = 0 };
|
||||
ssize_t result;
|
||||
size_t written;
|
||||
|
||||
switch (mid->mid_state) {
|
||||
case MID_RESPONSE_RECEIVED:
|
||||
wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
|
||||
if (wdata->result != 0)
|
||||
result = cifs_check_receive(mid, tcon->ses->server, 0);
|
||||
if (result != 0)
|
||||
break;
|
||||
|
||||
written = le16_to_cpu(smb->CountHigh);
|
||||
@ -1636,37 +1640,37 @@ cifs_writev_callback(struct mid_q_entry *mid)
|
||||
* client. OS/2 servers are known to set incorrect
|
||||
* CountHigh values.
|
||||
*/
|
||||
if (written > wdata->bytes)
|
||||
if (written > wdata->subreq.len)
|
||||
written &= 0xFFFF;
|
||||
|
||||
if (written < wdata->bytes)
|
||||
wdata->result = -ENOSPC;
|
||||
if (written < wdata->subreq.len)
|
||||
result = -ENOSPC;
|
||||
else
|
||||
wdata->bytes = written;
|
||||
result = written;
|
||||
break;
|
||||
case MID_REQUEST_SUBMITTED:
|
||||
case MID_RETRY_NEEDED:
|
||||
wdata->result = -EAGAIN;
|
||||
result = -EAGAIN;
|
||||
break;
|
||||
default:
|
||||
wdata->result = -EIO;
|
||||
result = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
queue_work(cifsiod_wq, &wdata->work);
|
||||
wdata->credits.value = 0;
|
||||
cifs_write_subrequest_terminated(wdata, result, true);
|
||||
release_mid(mid);
|
||||
add_credits(tcon->ses->server, &credits, 0);
|
||||
}
|
||||
|
||||
/* cifs_async_writev - send an async write, and set up mid to handle result */
|
||||
int
|
||||
cifs_async_writev(struct cifs_writedata *wdata,
|
||||
void (*release)(struct kref *kref))
|
||||
void
|
||||
cifs_async_writev(struct cifs_io_subrequest *wdata)
|
||||
{
|
||||
int rc = -EACCES;
|
||||
WRITE_REQ *smb = NULL;
|
||||
int wct;
|
||||
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
|
||||
struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
|
||||
struct kvec iov[2];
|
||||
struct smb_rqst rqst = { };
|
||||
|
||||
@ -1674,9 +1678,10 @@ cifs_async_writev(struct cifs_writedata *wdata,
|
||||
wct = 14;
|
||||
} else {
|
||||
wct = 12;
|
||||
if (wdata->offset >> 32 > 0) {
|
||||
if (wdata->subreq.start >> 32 > 0) {
|
||||
/* can not handle big offset for old srv */
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1688,10 +1693,10 @@ cifs_async_writev(struct cifs_writedata *wdata,
|
||||
smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
|
||||
|
||||
smb->AndXCommand = 0xFF; /* none */
|
||||
smb->Fid = wdata->cfile->fid.netfid;
|
||||
smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
|
||||
smb->Fid = wdata->req->cfile->fid.netfid;
|
||||
smb->OffsetLow = cpu_to_le32(wdata->subreq.start & 0xFFFFFFFF);
|
||||
if (wct == 14)
|
||||
smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
|
||||
smb->OffsetHigh = cpu_to_le32(wdata->subreq.start >> 32);
|
||||
smb->Reserved = 0xFFFFFFFF;
|
||||
smb->WriteMode = 0;
|
||||
smb->Remaining = 0;
|
||||
@ -1707,39 +1712,40 @@ cifs_async_writev(struct cifs_writedata *wdata,
|
||||
|
||||
rqst.rq_iov = iov;
|
||||
rqst.rq_nvec = 2;
|
||||
rqst.rq_iter = wdata->iter;
|
||||
rqst.rq_iter_size = iov_iter_count(&wdata->iter);
|
||||
rqst.rq_iter = wdata->subreq.io_iter;
|
||||
rqst.rq_iter_size = iov_iter_count(&wdata->subreq.io_iter);
|
||||
|
||||
cifs_dbg(FYI, "async write at %llu %u bytes\n",
|
||||
wdata->offset, wdata->bytes);
|
||||
cifs_dbg(FYI, "async write at %llu %zu bytes\n",
|
||||
wdata->subreq.start, wdata->subreq.len);
|
||||
|
||||
smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
|
||||
smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
|
||||
smb->DataLengthLow = cpu_to_le16(wdata->subreq.len & 0xFFFF);
|
||||
smb->DataLengthHigh = cpu_to_le16(wdata->subreq.len >> 16);
|
||||
|
||||
if (wct == 14) {
|
||||
inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
|
||||
put_bcc(wdata->bytes + 1, &smb->hdr);
|
||||
inc_rfc1001_len(&smb->hdr, wdata->subreq.len + 1);
|
||||
put_bcc(wdata->subreq.len + 1, &smb->hdr);
|
||||
} else {
|
||||
/* wct == 12 */
|
||||
struct smb_com_writex_req *smbw =
|
||||
(struct smb_com_writex_req *)smb;
|
||||
inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
|
||||
put_bcc(wdata->bytes + 5, &smbw->hdr);
|
||||
inc_rfc1001_len(&smbw->hdr, wdata->subreq.len + 5);
|
||||
put_bcc(wdata->subreq.len + 5, &smbw->hdr);
|
||||
iov[1].iov_len += 4; /* pad bigger by four bytes */
|
||||
}
|
||||
|
||||
kref_get(&wdata->refcount);
|
||||
rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
|
||||
cifs_writev_callback, NULL, wdata, 0, NULL);
|
||||
|
||||
/* Can't touch wdata if rc == 0 */
|
||||
if (rc == 0)
|
||||
cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
|
||||
else
|
||||
kref_put(&wdata->refcount, release);
|
||||
|
||||
async_writev_out:
|
||||
cifs_small_buf_release(smb);
|
||||
return rc;
|
||||
out:
|
||||
if (rc) {
|
||||
add_credits_and_wake_if(wdata->server, &wdata->credits, 0);
|
||||
cifs_write_subrequest_terminated(wdata, rc, false);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
2754
fs/smb/client/file.c
2754
fs/smb/client/file.c
File diff suppressed because it is too large
Load Diff
@ -170,112 +170,3 @@ void cifs_fscache_release_inode_cookie(struct inode *inode)
|
||||
cifsi->netfs.cache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fallback page reading interface.
|
||||
*/
|
||||
static int fscache_fallback_read_page(struct inode *inode, struct page *page)
|
||||
{
|
||||
struct netfs_cache_resources cres;
|
||||
struct fscache_cookie *cookie = cifs_inode_cookie(inode);
|
||||
struct iov_iter iter;
|
||||
struct bio_vec bvec;
|
||||
int ret;
|
||||
|
||||
memset(&cres, 0, sizeof(cres));
|
||||
bvec_set_page(&bvec, page, PAGE_SIZE, 0);
|
||||
iov_iter_bvec(&iter, ITER_DEST, &bvec, 1, PAGE_SIZE);
|
||||
|
||||
ret = fscache_begin_read_operation(&cres, cookie);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = fscache_read(&cres, page_offset(page), &iter, NETFS_READ_HOLE_FAIL,
|
||||
NULL, NULL);
|
||||
fscache_end_operation(&cres);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fallback page writing interface.
|
||||
*/
|
||||
static int fscache_fallback_write_pages(struct inode *inode, loff_t start, size_t len,
|
||||
bool no_space_allocated_yet)
|
||||
{
|
||||
struct netfs_cache_resources cres;
|
||||
struct fscache_cookie *cookie = cifs_inode_cookie(inode);
|
||||
struct iov_iter iter;
|
||||
int ret;
|
||||
|
||||
memset(&cres, 0, sizeof(cres));
|
||||
iov_iter_xarray(&iter, ITER_SOURCE, &inode->i_mapping->i_pages, start, len);
|
||||
|
||||
ret = fscache_begin_write_operation(&cres, cookie);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cres.ops->prepare_write(&cres, &start, &len, len, i_size_read(inode),
|
||||
no_space_allocated_yet);
|
||||
if (ret == 0)
|
||||
ret = fscache_write(&cres, start, &iter, NULL, NULL);
|
||||
fscache_end_operation(&cres);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve a page from FS-Cache
|
||||
*/
|
||||
int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
|
||||
{
|
||||
int ret;
|
||||
|
||||
cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n",
|
||||
__func__, cifs_inode_cookie(inode), page, inode);
|
||||
|
||||
ret = fscache_fallback_read_page(inode, page);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Read completed synchronously */
|
||||
SetPageUptodate(page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __cifs_readahead_to_fscache(struct inode *inode, loff_t pos, size_t len)
|
||||
{
|
||||
cifs_dbg(FYI, "%s: (fsc: %p, p: %llx, l: %zx, i: %p)\n",
|
||||
__func__, cifs_inode_cookie(inode), pos, len, inode);
|
||||
|
||||
fscache_fallback_write_pages(inode, pos, len, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Query the cache occupancy.
|
||||
*/
|
||||
int __cifs_fscache_query_occupancy(struct inode *inode,
|
||||
pgoff_t first, unsigned int nr_pages,
|
||||
pgoff_t *_data_first,
|
||||
unsigned int *_data_nr_pages)
|
||||
{
|
||||
struct netfs_cache_resources cres;
|
||||
struct fscache_cookie *cookie = cifs_inode_cookie(inode);
|
||||
loff_t start, data_start;
|
||||
size_t len, data_len;
|
||||
int ret;
|
||||
|
||||
ret = fscache_begin_read_operation(&cres, cookie);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
start = first * PAGE_SIZE;
|
||||
len = nr_pages * PAGE_SIZE;
|
||||
ret = cres.ops->query_occupancy(&cres, start, len, PAGE_SIZE,
|
||||
&data_start, &data_len);
|
||||
if (ret == 0) {
|
||||
*_data_first = data_start / PAGE_SIZE;
|
||||
*_data_nr_pages = len / PAGE_SIZE;
|
||||
}
|
||||
|
||||
fscache_end_operation(&cres);
|
||||
return ret;
|
||||
}
|
||||
|
@ -74,41 +74,6 @@ static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags
|
||||
i_size_read(inode), flags);
|
||||
}
|
||||
|
||||
extern int __cifs_fscache_query_occupancy(struct inode *inode,
|
||||
pgoff_t first, unsigned int nr_pages,
|
||||
pgoff_t *_data_first,
|
||||
unsigned int *_data_nr_pages);
|
||||
|
||||
static inline int cifs_fscache_query_occupancy(struct inode *inode,
|
||||
pgoff_t first, unsigned int nr_pages,
|
||||
pgoff_t *_data_first,
|
||||
unsigned int *_data_nr_pages)
|
||||
{
|
||||
if (!cifs_inode_cookie(inode))
|
||||
return -ENOBUFS;
|
||||
return __cifs_fscache_query_occupancy(inode, first, nr_pages,
|
||||
_data_first, _data_nr_pages);
|
||||
}
|
||||
|
||||
extern int __cifs_readpage_from_fscache(struct inode *pinode, struct page *ppage);
|
||||
extern void __cifs_readahead_to_fscache(struct inode *pinode, loff_t pos, size_t len);
|
||||
|
||||
|
||||
static inline int cifs_readpage_from_fscache(struct inode *inode,
|
||||
struct page *page)
|
||||
{
|
||||
if (cifs_inode_cookie(inode))
|
||||
return __cifs_readpage_from_fscache(inode, page);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
static inline void cifs_readahead_to_fscache(struct inode *inode,
|
||||
loff_t pos, size_t len)
|
||||
{
|
||||
if (cifs_inode_cookie(inode))
|
||||
__cifs_readahead_to_fscache(inode, pos, len);
|
||||
}
|
||||
|
||||
static inline bool cifs_fscache_enabled(struct inode *inode)
|
||||
{
|
||||
return fscache_cookie_enabled(cifs_inode_cookie(inode));
|
||||
@ -131,25 +96,6 @@ static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { re
|
||||
static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) {}
|
||||
static inline bool cifs_fscache_enabled(struct inode *inode) { return false; }
|
||||
|
||||
static inline int cifs_fscache_query_occupancy(struct inode *inode,
|
||||
pgoff_t first, unsigned int nr_pages,
|
||||
pgoff_t *_data_first,
|
||||
unsigned int *_data_nr_pages)
|
||||
{
|
||||
*_data_first = ULONG_MAX;
|
||||
*_data_nr_pages = 0;
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
static inline int
|
||||
cifs_readpage_from_fscache(struct inode *inode, struct page *page)
|
||||
{
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
static inline
|
||||
void cifs_readahead_to_fscache(struct inode *inode, loff_t pos, size_t len) {}
|
||||
|
||||
#endif /* CONFIG_CIFS_FSCACHE */
|
||||
|
||||
#endif /* _CIFS_FSCACHE_H */
|
||||
|
@ -28,14 +28,29 @@
|
||||
#include "cached_dir.h"
|
||||
#include "reparse.h"
|
||||
|
||||
/*
|
||||
* Set parameters for the netfs library
|
||||
*/
|
||||
static void cifs_set_netfs_context(struct inode *inode)
|
||||
{
|
||||
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
|
||||
netfs_inode_init(&cifs_i->netfs, &cifs_req_ops, true);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
|
||||
__set_bit(NETFS_ICTX_WRITETHROUGH, &cifs_i->netfs.flags);
|
||||
}
|
||||
|
||||
static void cifs_set_ops(struct inode *inode)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct netfs_inode *ictx = netfs_inode(inode);
|
||||
|
||||
switch (inode->i_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
inode->i_op = &cifs_file_inode_ops;
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
set_bit(NETFS_ICTX_UNBUFFERED, &ictx->flags);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop = &cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
@ -57,6 +72,7 @@ static void cifs_set_ops(struct inode *inode)
|
||||
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
inode->i_data.a_ops = &cifs_addr_ops;
|
||||
mapping_set_large_folios(inode->i_mapping);
|
||||
break;
|
||||
case S_IFDIR:
|
||||
if (IS_AUTOMOUNT(inode)) {
|
||||
@ -221,8 +237,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
|
||||
|
||||
if (fattr->cf_flags & CIFS_FATTR_JUNCTION)
|
||||
inode->i_flags |= S_AUTOMOUNT;
|
||||
if (inode->i_state & I_NEW)
|
||||
if (inode->i_state & I_NEW) {
|
||||
cifs_set_netfs_context(inode);
|
||||
cifs_set_ops(inode);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2431,24 +2449,6 @@ cifs_dentry_needs_reval(struct dentry *dentry)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Zap the cache. Called when invalid_mapping flag is set.
|
||||
*/
|
||||
int
|
||||
cifs_invalidate_mapping(struct inode *inode)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
|
||||
rc = invalidate_inode_pages2(inode->i_mapping);
|
||||
if (rc)
|
||||
cifs_dbg(VFS, "%s: invalidate inode %p failed with rc %d\n",
|
||||
__func__, inode, rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
|
||||
*
|
||||
@ -2485,9 +2485,12 @@ cifs_revalidate_mapping(struct inode *inode)
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
|
||||
goto skip_invalidate;
|
||||
|
||||
rc = cifs_invalidate_mapping(inode);
|
||||
if (rc)
|
||||
rc = filemap_invalidate_inode(inode, true, 0, LLONG_MAX);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: invalidate inode %p failed with rc %d\n",
|
||||
__func__, inode, rc);
|
||||
set_bit(CIFS_INO_INVALID_MAPPING, flags);
|
||||
}
|
||||
}
|
||||
|
||||
skip_invalidate:
|
||||
|
@ -217,8 +217,8 @@ smb2_get_credits(struct mid_q_entry *mid)
|
||||
}
|
||||
|
||||
static int
|
||||
smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
|
||||
unsigned int *num, struct cifs_credits *credits)
|
||||
smb2_wait_mtu_credits(struct TCP_Server_Info *server, size_t size,
|
||||
size_t *num, struct cifs_credits *credits)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned int scredits, in_flight;
|
||||
@ -4490,7 +4490,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
||||
unsigned int cur_off;
|
||||
unsigned int cur_page_idx;
|
||||
unsigned int pad_len;
|
||||
struct cifs_readdata *rdata = mid->callback_data;
|
||||
struct cifs_io_subrequest *rdata = mid->callback_data;
|
||||
struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
|
||||
int length;
|
||||
bool use_rdma_mr = false;
|
||||
@ -4592,7 +4592,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
||||
|
||||
/* Copy the data to the output I/O iterator. */
|
||||
rdata->result = cifs_copy_pages_to_iter(pages, pages_len,
|
||||
cur_off, &rdata->iter);
|
||||
cur_off, &rdata->subreq.io_iter);
|
||||
if (rdata->result != 0) {
|
||||
if (is_offloaded)
|
||||
mid->mid_state = MID_RESPONSE_MALFORMED;
|
||||
@ -4606,7 +4606,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
||||
/* read response payload is in buf */
|
||||
WARN_ONCE(pages && !xa_empty(pages),
|
||||
"read data can be either in buf or in pages");
|
||||
length = copy_to_iter(buf + data_offset, data_len, &rdata->iter);
|
||||
length = copy_to_iter(buf + data_offset, data_len, &rdata->subreq.io_iter);
|
||||
if (length < 0)
|
||||
return length;
|
||||
rdata->got_bytes = data_len;
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <linux/uuid.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <linux/netfs.h>
|
||||
#include <trace/events/netfs.h>
|
||||
#include "cifsglob.h"
|
||||
#include "cifsacl.h"
|
||||
#include "cifsproto.h"
|
||||
@ -4391,7 +4393,7 @@ static inline bool smb3_use_rdma_offload(struct cifs_io_parms *io_parms)
|
||||
*/
|
||||
static int
|
||||
smb2_new_read_req(void **buf, unsigned int *total_len,
|
||||
struct cifs_io_parms *io_parms, struct cifs_readdata *rdata,
|
||||
struct cifs_io_parms *io_parms, struct cifs_io_subrequest *rdata,
|
||||
unsigned int remaining_bytes, int request_type)
|
||||
{
|
||||
int rc = -EACCES;
|
||||
@ -4419,10 +4421,12 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
|
||||
req->Length = cpu_to_le32(io_parms->length);
|
||||
req->Offset = cpu_to_le64(io_parms->offset);
|
||||
|
||||
trace_smb3_read_enter(0 /* xid */,
|
||||
io_parms->persistent_fid,
|
||||
io_parms->tcon->tid, io_parms->tcon->ses->Suid,
|
||||
io_parms->offset, io_parms->length);
|
||||
trace_smb3_read_enter(rdata ? rdata->rreq->debug_id : 0,
|
||||
rdata ? rdata->subreq.debug_index : 0,
|
||||
rdata ? rdata->xid : 0,
|
||||
io_parms->persistent_fid,
|
||||
io_parms->tcon->tid, io_parms->tcon->ses->Suid,
|
||||
io_parms->offset, io_parms->length);
|
||||
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||
/*
|
||||
* If we want to do a RDMA write, fill in and append
|
||||
@ -4432,7 +4436,7 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
|
||||
struct smbd_buffer_descriptor_v1 *v1;
|
||||
bool need_invalidate = server->dialect == SMB30_PROT_ID;
|
||||
|
||||
rdata->mr = smbd_register_mr(server->smbd_conn, &rdata->iter,
|
||||
rdata->mr = smbd_register_mr(server->smbd_conn, &rdata->subreq.io_iter,
|
||||
true, need_invalidate);
|
||||
if (!rdata->mr)
|
||||
return -EAGAIN;
|
||||
@ -4483,8 +4487,8 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
|
||||
static void
|
||||
smb2_readv_callback(struct mid_q_entry *mid)
|
||||
{
|
||||
struct cifs_readdata *rdata = mid->callback_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
|
||||
struct cifs_io_subrequest *rdata = mid->callback_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
|
||||
struct TCP_Server_Info *server = rdata->server;
|
||||
struct smb2_hdr *shdr =
|
||||
(struct smb2_hdr *)rdata->iov[0].iov_base;
|
||||
@ -4492,17 +4496,17 @@ smb2_readv_callback(struct mid_q_entry *mid)
|
||||
struct smb_rqst rqst = { .rq_iov = &rdata->iov[1], .rq_nvec = 1 };
|
||||
|
||||
if (rdata->got_bytes) {
|
||||
rqst.rq_iter = rdata->iter;
|
||||
rqst.rq_iter_size = iov_iter_count(&rdata->iter);
|
||||
rqst.rq_iter = rdata->subreq.io_iter;
|
||||
rqst.rq_iter_size = iov_iter_count(&rdata->subreq.io_iter);
|
||||
}
|
||||
|
||||
WARN_ONCE(rdata->server != mid->server,
|
||||
"rdata server %p != mid server %p",
|
||||
rdata->server, mid->server);
|
||||
|
||||
cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
|
||||
cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu\n",
|
||||
__func__, mid->mid, mid->mid_state, rdata->result,
|
||||
rdata->bytes);
|
||||
rdata->subreq.len);
|
||||
|
||||
switch (mid->mid_state) {
|
||||
case MID_RESPONSE_RECEIVED:
|
||||
@ -4512,7 +4516,6 @@ smb2_readv_callback(struct mid_q_entry *mid)
|
||||
if (server->sign && !mid->decrypted) {
|
||||
int rc;
|
||||
|
||||
iov_iter_revert(&rqst.rq_iter, rdata->got_bytes);
|
||||
iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes);
|
||||
rc = smb2_verify_signature(&rqst, server);
|
||||
if (rc)
|
||||
@ -4553,24 +4556,40 @@ smb2_readv_callback(struct mid_q_entry *mid)
|
||||
#endif
|
||||
if (rdata->result && rdata->result != -ENODATA) {
|
||||
cifs_stats_fail_inc(tcon, SMB2_READ_HE);
|
||||
trace_smb3_read_err(0 /* xid */,
|
||||
rdata->cfile->fid.persistent_fid,
|
||||
tcon->tid, tcon->ses->Suid, rdata->offset,
|
||||
rdata->bytes, rdata->result);
|
||||
trace_smb3_read_err(rdata->rreq->debug_id,
|
||||
rdata->subreq.debug_index,
|
||||
rdata->xid,
|
||||
rdata->req->cfile->fid.persistent_fid,
|
||||
tcon->tid, tcon->ses->Suid, rdata->subreq.start,
|
||||
rdata->subreq.len, rdata->result);
|
||||
} else
|
||||
trace_smb3_read_done(0 /* xid */,
|
||||
rdata->cfile->fid.persistent_fid,
|
||||
trace_smb3_read_done(rdata->rreq->debug_id,
|
||||
rdata->subreq.debug_index,
|
||||
rdata->xid,
|
||||
rdata->req->cfile->fid.persistent_fid,
|
||||
tcon->tid, tcon->ses->Suid,
|
||||
rdata->offset, rdata->got_bytes);
|
||||
rdata->subreq.start, rdata->got_bytes);
|
||||
|
||||
queue_work(cifsiod_wq, &rdata->work);
|
||||
if (rdata->result == -ENODATA) {
|
||||
/* We may have got an EOF error because fallocate
|
||||
* failed to enlarge the file.
|
||||
*/
|
||||
if (rdata->subreq.start < rdata->subreq.rreq->i_size)
|
||||
rdata->result = 0;
|
||||
}
|
||||
if (rdata->result == 0 || rdata->result == -EAGAIN)
|
||||
iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes);
|
||||
rdata->credits.value = 0;
|
||||
netfs_subreq_terminated(&rdata->subreq,
|
||||
(rdata->result == 0 || rdata->result == -EAGAIN) ?
|
||||
rdata->got_bytes : rdata->result, true);
|
||||
release_mid(mid);
|
||||
add_credits(server, &credits, 0);
|
||||
}
|
||||
|
||||
/* smb2_async_readv - send an async read, and set up mid to handle result */
|
||||
int
|
||||
smb2_async_readv(struct cifs_readdata *rdata)
|
||||
smb2_async_readv(struct cifs_io_subrequest *rdata)
|
||||
{
|
||||
int rc, flags = 0;
|
||||
char *buf;
|
||||
@ -4579,22 +4598,22 @@ smb2_async_readv(struct cifs_readdata *rdata)
|
||||
struct smb_rqst rqst = { .rq_iov = rdata->iov,
|
||||
.rq_nvec = 1 };
|
||||
struct TCP_Server_Info *server;
|
||||
struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
|
||||
struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
|
||||
unsigned int total_len;
|
||||
int credit_request;
|
||||
|
||||
cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
|
||||
__func__, rdata->offset, rdata->bytes);
|
||||
cifs_dbg(FYI, "%s: offset=%llu bytes=%zu\n",
|
||||
__func__, rdata->subreq.start, rdata->subreq.len);
|
||||
|
||||
if (!rdata->server)
|
||||
rdata->server = cifs_pick_channel(tcon->ses);
|
||||
|
||||
io_parms.tcon = tlink_tcon(rdata->cfile->tlink);
|
||||
io_parms.tcon = tlink_tcon(rdata->req->cfile->tlink);
|
||||
io_parms.server = server = rdata->server;
|
||||
io_parms.offset = rdata->offset;
|
||||
io_parms.length = rdata->bytes;
|
||||
io_parms.persistent_fid = rdata->cfile->fid.persistent_fid;
|
||||
io_parms.volatile_fid = rdata->cfile->fid.volatile_fid;
|
||||
io_parms.offset = rdata->subreq.start;
|
||||
io_parms.length = rdata->subreq.len;
|
||||
io_parms.persistent_fid = rdata->req->cfile->fid.persistent_fid;
|
||||
io_parms.volatile_fid = rdata->req->cfile->fid.volatile_fid;
|
||||
io_parms.pid = rdata->pid;
|
||||
|
||||
rc = smb2_new_read_req(
|
||||
@ -4611,7 +4630,7 @@ smb2_async_readv(struct cifs_readdata *rdata)
|
||||
shdr = (struct smb2_hdr *)buf;
|
||||
|
||||
if (rdata->credits.value > 0) {
|
||||
shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
|
||||
shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->subreq.len,
|
||||
SMB2_MAX_BUFFER_SIZE));
|
||||
credit_request = le16_to_cpu(shdr->CreditCharge) + 8;
|
||||
if (server->credits >= server->max_credits)
|
||||
@ -4621,22 +4640,22 @@ smb2_async_readv(struct cifs_readdata *rdata)
|
||||
min_t(int, server->max_credits -
|
||||
server->credits, credit_request));
|
||||
|
||||
rc = adjust_credits(server, &rdata->credits, rdata->bytes);
|
||||
rc = adjust_credits(server, &rdata->credits, rdata->subreq.len);
|
||||
if (rc)
|
||||
goto async_readv_out;
|
||||
|
||||
flags |= CIFS_HAS_CREDITS;
|
||||
}
|
||||
|
||||
kref_get(&rdata->refcount);
|
||||
rc = cifs_call_async(server, &rqst,
|
||||
cifs_readv_receive, smb2_readv_callback,
|
||||
smb3_handle_read_data, rdata, flags,
|
||||
&rdata->credits);
|
||||
if (rc) {
|
||||
kref_put(&rdata->refcount, cifs_readdata_release);
|
||||
cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
|
||||
trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
|
||||
trace_smb3_read_err(rdata->rreq->debug_id,
|
||||
rdata->subreq.debug_index,
|
||||
rdata->xid, io_parms.persistent_fid,
|
||||
io_parms.tcon->tid,
|
||||
io_parms.tcon->ses->Suid,
|
||||
io_parms.offset, io_parms.length, rc);
|
||||
@ -4687,22 +4706,23 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
|
||||
if (rc != -ENODATA) {
|
||||
cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
|
||||
cifs_dbg(VFS, "Send error in read = %d\n", rc);
|
||||
trace_smb3_read_err(xid,
|
||||
trace_smb3_read_err(0, 0, xid,
|
||||
req->PersistentFileId,
|
||||
io_parms->tcon->tid, ses->Suid,
|
||||
io_parms->offset, io_parms->length,
|
||||
rc);
|
||||
} else
|
||||
trace_smb3_read_done(xid, req->PersistentFileId, io_parms->tcon->tid,
|
||||
trace_smb3_read_done(0, 0, xid,
|
||||
req->PersistentFileId, io_parms->tcon->tid,
|
||||
ses->Suid, io_parms->offset, 0);
|
||||
free_rsp_buf(resp_buftype, rsp_iov.iov_base);
|
||||
cifs_small_buf_release(req);
|
||||
return rc == -ENODATA ? 0 : rc;
|
||||
} else
|
||||
trace_smb3_read_done(xid,
|
||||
req->PersistentFileId,
|
||||
io_parms->tcon->tid, ses->Suid,
|
||||
io_parms->offset, io_parms->length);
|
||||
trace_smb3_read_done(0, 0, xid,
|
||||
req->PersistentFileId,
|
||||
io_parms->tcon->tid, ses->Suid,
|
||||
io_parms->offset, io_parms->length);
|
||||
|
||||
cifs_small_buf_release(req);
|
||||
|
||||
@ -4735,12 +4755,13 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
|
||||
static void
|
||||
smb2_writev_callback(struct mid_q_entry *mid)
|
||||
{
|
||||
struct cifs_writedata *wdata = mid->callback_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
|
||||
struct cifs_io_subrequest *wdata = mid->callback_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
|
||||
struct TCP_Server_Info *server = wdata->server;
|
||||
unsigned int written;
|
||||
struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
|
||||
struct cifs_credits credits = { .value = 0, .instance = 0 };
|
||||
ssize_t result = 0;
|
||||
size_t written;
|
||||
|
||||
WARN_ONCE(wdata->server != mid->server,
|
||||
"wdata server %p != mid server %p",
|
||||
@ -4750,8 +4771,8 @@ smb2_writev_callback(struct mid_q_entry *mid)
|
||||
case MID_RESPONSE_RECEIVED:
|
||||
credits.value = le16_to_cpu(rsp->hdr.CreditRequest);
|
||||
credits.instance = server->reconnect_instance;
|
||||
wdata->result = smb2_check_receive(mid, server, 0);
|
||||
if (wdata->result != 0)
|
||||
result = smb2_check_receive(mid, server, 0);
|
||||
if (result != 0)
|
||||
break;
|
||||
|
||||
written = le32_to_cpu(rsp->DataLength);
|
||||
@ -4761,24 +4782,25 @@ smb2_writev_callback(struct mid_q_entry *mid)
|
||||
* client. OS/2 servers are known to set incorrect
|
||||
* CountHigh values.
|
||||
*/
|
||||
if (written > wdata->bytes)
|
||||
if (written > wdata->subreq.len)
|
||||
written &= 0xFFFF;
|
||||
|
||||
if (written < wdata->bytes)
|
||||
if (written < wdata->subreq.len)
|
||||
wdata->result = -ENOSPC;
|
||||
else
|
||||
wdata->bytes = written;
|
||||
wdata->subreq.len = written;
|
||||
iov_iter_advance(&wdata->subreq.io_iter, written);
|
||||
break;
|
||||
case MID_REQUEST_SUBMITTED:
|
||||
case MID_RETRY_NEEDED:
|
||||
wdata->result = -EAGAIN;
|
||||
result = -EAGAIN;
|
||||
break;
|
||||
case MID_RESPONSE_MALFORMED:
|
||||
credits.value = le16_to_cpu(rsp->hdr.CreditRequest);
|
||||
credits.instance = server->reconnect_instance;
|
||||
fallthrough;
|
||||
default:
|
||||
wdata->result = -EIO;
|
||||
result = -EIO;
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||
@ -4794,44 +4816,44 @@ smb2_writev_callback(struct mid_q_entry *mid)
|
||||
wdata->mr = NULL;
|
||||
}
|
||||
#endif
|
||||
if (wdata->result) {
|
||||
if (result) {
|
||||
cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
|
||||
trace_smb3_write_err(0 /* no xid */,
|
||||
wdata->cfile->fid.persistent_fid,
|
||||
tcon->tid, tcon->ses->Suid, wdata->offset,
|
||||
wdata->bytes, wdata->result);
|
||||
trace_smb3_write_err(wdata->xid,
|
||||
wdata->req->cfile->fid.persistent_fid,
|
||||
tcon->tid, tcon->ses->Suid, wdata->subreq.start,
|
||||
wdata->subreq.len, wdata->result);
|
||||
if (wdata->result == -ENOSPC)
|
||||
pr_warn_once("Out of space writing to %s\n",
|
||||
tcon->tree_name);
|
||||
} else
|
||||
trace_smb3_write_done(0 /* no xid */,
|
||||
wdata->cfile->fid.persistent_fid,
|
||||
wdata->req->cfile->fid.persistent_fid,
|
||||
tcon->tid, tcon->ses->Suid,
|
||||
wdata->offset, wdata->bytes);
|
||||
wdata->subreq.start, wdata->subreq.len);
|
||||
|
||||
queue_work(cifsiod_wq, &wdata->work);
|
||||
wdata->credits.value = 0;
|
||||
cifs_write_subrequest_terminated(wdata, result ?: written, true);
|
||||
release_mid(mid);
|
||||
add_credits(server, &credits, 0);
|
||||
}
|
||||
|
||||
/* smb2_async_writev - send an async write, and set up mid to handle result */
|
||||
int
|
||||
smb2_async_writev(struct cifs_writedata *wdata,
|
||||
void (*release)(struct kref *kref))
|
||||
void
|
||||
smb2_async_writev(struct cifs_io_subrequest *wdata)
|
||||
{
|
||||
int rc = -EACCES, flags = 0;
|
||||
struct smb2_write_req *req = NULL;
|
||||
struct smb2_hdr *shdr;
|
||||
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
|
||||
struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
|
||||
struct TCP_Server_Info *server = wdata->server;
|
||||
struct kvec iov[1];
|
||||
struct smb_rqst rqst = { };
|
||||
unsigned int total_len;
|
||||
unsigned int total_len, xid = wdata->xid;
|
||||
struct cifs_io_parms _io_parms;
|
||||
struct cifs_io_parms *io_parms = NULL;
|
||||
int credit_request;
|
||||
|
||||
if (!wdata->server || wdata->replay)
|
||||
if (!wdata->server || test_bit(NETFS_SREQ_RETRYING, &wdata->subreq.flags))
|
||||
server = wdata->server = cifs_pick_channel(tcon->ses);
|
||||
|
||||
/*
|
||||
@ -4841,10 +4863,10 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
||||
_io_parms = (struct cifs_io_parms) {
|
||||
.tcon = tcon,
|
||||
.server = server,
|
||||
.offset = wdata->offset,
|
||||
.length = wdata->bytes,
|
||||
.persistent_fid = wdata->cfile->fid.persistent_fid,
|
||||
.volatile_fid = wdata->cfile->fid.volatile_fid,
|
||||
.offset = wdata->subreq.start,
|
||||
.length = wdata->subreq.len,
|
||||
.persistent_fid = wdata->req->cfile->fid.persistent_fid,
|
||||
.volatile_fid = wdata->req->cfile->fid.volatile_fid,
|
||||
.pid = wdata->pid,
|
||||
};
|
||||
io_parms = &_io_parms;
|
||||
@ -4852,7 +4874,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
||||
rc = smb2_plain_req_init(SMB2_WRITE, tcon, server,
|
||||
(void **) &req, &total_len);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto out;
|
||||
|
||||
if (smb3_encryption_required(tcon))
|
||||
flags |= CIFS_TRANSFORM_REQ;
|
||||
@ -4870,7 +4892,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
||||
offsetof(struct smb2_write_req, Buffer));
|
||||
req->RemainingBytes = 0;
|
||||
|
||||
trace_smb3_write_enter(0 /* xid */,
|
||||
trace_smb3_write_enter(wdata->xid,
|
||||
io_parms->persistent_fid,
|
||||
io_parms->tcon->tid,
|
||||
io_parms->tcon->ses->Suid,
|
||||
@ -4884,10 +4906,10 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
||||
*/
|
||||
if (smb3_use_rdma_offload(io_parms)) {
|
||||
struct smbd_buffer_descriptor_v1 *v1;
|
||||
size_t data_size = iov_iter_count(&wdata->iter);
|
||||
size_t data_size = iov_iter_count(&wdata->subreq.io_iter);
|
||||
bool need_invalidate = server->dialect == SMB30_PROT_ID;
|
||||
|
||||
wdata->mr = smbd_register_mr(server->smbd_conn, &wdata->iter,
|
||||
wdata->mr = smbd_register_mr(server->smbd_conn, &wdata->subreq.io_iter,
|
||||
false, need_invalidate);
|
||||
if (!wdata->mr) {
|
||||
rc = -EAGAIN;
|
||||
@ -4914,9 +4936,9 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
||||
|
||||
rqst.rq_iov = iov;
|
||||
rqst.rq_nvec = 1;
|
||||
rqst.rq_iter = wdata->iter;
|
||||
rqst.rq_iter = wdata->subreq.io_iter;
|
||||
rqst.rq_iter_size = iov_iter_count(&rqst.rq_iter);
|
||||
if (wdata->replay)
|
||||
if (test_bit(NETFS_SREQ_RETRYING, &wdata->subreq.flags))
|
||||
smb2_set_replay(server, &rqst);
|
||||
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||
if (wdata->mr)
|
||||
@ -4934,7 +4956,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
||||
#endif
|
||||
|
||||
if (wdata->credits.value > 0) {
|
||||
shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
|
||||
shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->subreq.len,
|
||||
SMB2_MAX_BUFFER_SIZE));
|
||||
credit_request = le16_to_cpu(shdr->CreditCharge) + 8;
|
||||
if (server->credits >= server->max_credits)
|
||||
@ -4951,25 +4973,27 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
||||
flags |= CIFS_HAS_CREDITS;
|
||||
}
|
||||
|
||||
kref_get(&wdata->refcount);
|
||||
rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL,
|
||||
wdata, flags, &wdata->credits);
|
||||
|
||||
/* Can't touch wdata if rc == 0 */
|
||||
if (rc) {
|
||||
trace_smb3_write_err(0 /* no xid */,
|
||||
trace_smb3_write_err(xid,
|
||||
io_parms->persistent_fid,
|
||||
io_parms->tcon->tid,
|
||||
io_parms->tcon->ses->Suid,
|
||||
io_parms->offset,
|
||||
io_parms->length,
|
||||
rc);
|
||||
kref_put(&wdata->refcount, release);
|
||||
cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
|
||||
}
|
||||
|
||||
async_writev_out:
|
||||
cifs_small_buf_release(req);
|
||||
return rc;
|
||||
out:
|
||||
if (rc) {
|
||||
add_credits_and_wake_if(wdata->server, &wdata->credits, 0);
|
||||
cifs_write_subrequest_terminated(wdata, rc, true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -210,11 +210,10 @@ extern int SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_fid, u64 volatile_fid,
|
||||
__le64 *uniqueid);
|
||||
extern int smb2_async_readv(struct cifs_readdata *rdata);
|
||||
extern int smb2_async_readv(struct cifs_io_subrequest *rdata);
|
||||
extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
|
||||
unsigned int *nbytes, char **buf, int *buf_type);
|
||||
extern int smb2_async_writev(struct cifs_writedata *wdata,
|
||||
void (*release)(struct kref *kref));
|
||||
extern void smb2_async_writev(struct cifs_io_subrequest *wdata);
|
||||
extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
|
||||
unsigned int *nbytes, struct kvec *iov, int n_vec);
|
||||
extern int SMB2_echo(struct TCP_Server_Info *server);
|
||||
|
@ -85,6 +85,62 @@ smb3_tcon_ref_traces;
|
||||
|
||||
/* For logging errors in read or write */
|
||||
DECLARE_EVENT_CLASS(smb3_rw_err_class,
|
||||
TP_PROTO(unsigned int rreq_debug_id,
|
||||
unsigned int rreq_debug_index,
|
||||
unsigned int xid,
|
||||
__u64 fid,
|
||||
__u32 tid,
|
||||
__u64 sesid,
|
||||
__u64 offset,
|
||||
__u32 len,
|
||||
int rc),
|
||||
TP_ARGS(rreq_debug_id, rreq_debug_index,
|
||||
xid, fid, tid, sesid, offset, len, rc),
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, rreq_debug_id)
|
||||
__field(unsigned int, rreq_debug_index)
|
||||
__field(unsigned int, xid)
|
||||
__field(__u64, fid)
|
||||
__field(__u32, tid)
|
||||
__field(__u64, sesid)
|
||||
__field(__u64, offset)
|
||||
__field(__u32, len)
|
||||
__field(int, rc)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->rreq_debug_id = rreq_debug_id;
|
||||
__entry->rreq_debug_index = rreq_debug_index;
|
||||
__entry->xid = xid;
|
||||
__entry->fid = fid;
|
||||
__entry->tid = tid;
|
||||
__entry->sesid = sesid;
|
||||
__entry->offset = offset;
|
||||
__entry->len = len;
|
||||
__entry->rc = rc;
|
||||
),
|
||||
TP_printk("\tR=%08x[%x] xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x rc=%d",
|
||||
__entry->rreq_debug_id, __entry->rreq_debug_index,
|
||||
__entry->xid, __entry->sesid, __entry->tid, __entry->fid,
|
||||
__entry->offset, __entry->len, __entry->rc)
|
||||
)
|
||||
|
||||
#define DEFINE_SMB3_RW_ERR_EVENT(name) \
|
||||
DEFINE_EVENT(smb3_rw_err_class, smb3_##name, \
|
||||
TP_PROTO(unsigned int rreq_debug_id, \
|
||||
unsigned int rreq_debug_index, \
|
||||
unsigned int xid, \
|
||||
__u64 fid, \
|
||||
__u32 tid, \
|
||||
__u64 sesid, \
|
||||
__u64 offset, \
|
||||
__u32 len, \
|
||||
int rc), \
|
||||
TP_ARGS(rreq_debug_id, rreq_debug_index, xid, fid, tid, sesid, offset, len, rc))
|
||||
|
||||
DEFINE_SMB3_RW_ERR_EVENT(read_err);
|
||||
|
||||
/* For logging errors in other file I/O ops */
|
||||
DECLARE_EVENT_CLASS(smb3_other_err_class,
|
||||
TP_PROTO(unsigned int xid,
|
||||
__u64 fid,
|
||||
__u32 tid,
|
||||
@ -116,8 +172,8 @@ DECLARE_EVENT_CLASS(smb3_rw_err_class,
|
||||
__entry->offset, __entry->len, __entry->rc)
|
||||
)
|
||||
|
||||
#define DEFINE_SMB3_RW_ERR_EVENT(name) \
|
||||
DEFINE_EVENT(smb3_rw_err_class, smb3_##name, \
|
||||
#define DEFINE_SMB3_OTHER_ERR_EVENT(name) \
|
||||
DEFINE_EVENT(smb3_other_err_class, smb3_##name, \
|
||||
TP_PROTO(unsigned int xid, \
|
||||
__u64 fid, \
|
||||
__u32 tid, \
|
||||
@ -127,15 +183,67 @@ DEFINE_EVENT(smb3_rw_err_class, smb3_##name, \
|
||||
int rc), \
|
||||
TP_ARGS(xid, fid, tid, sesid, offset, len, rc))
|
||||
|
||||
DEFINE_SMB3_RW_ERR_EVENT(write_err);
|
||||
DEFINE_SMB3_RW_ERR_EVENT(read_err);
|
||||
DEFINE_SMB3_RW_ERR_EVENT(query_dir_err);
|
||||
DEFINE_SMB3_RW_ERR_EVENT(zero_err);
|
||||
DEFINE_SMB3_RW_ERR_EVENT(falloc_err);
|
||||
DEFINE_SMB3_OTHER_ERR_EVENT(write_err);
|
||||
DEFINE_SMB3_OTHER_ERR_EVENT(query_dir_err);
|
||||
DEFINE_SMB3_OTHER_ERR_EVENT(zero_err);
|
||||
DEFINE_SMB3_OTHER_ERR_EVENT(falloc_err);
|
||||
|
||||
|
||||
/* For logging successful read or write */
|
||||
DECLARE_EVENT_CLASS(smb3_rw_done_class,
|
||||
TP_PROTO(unsigned int rreq_debug_id,
|
||||
unsigned int rreq_debug_index,
|
||||
unsigned int xid,
|
||||
__u64 fid,
|
||||
__u32 tid,
|
||||
__u64 sesid,
|
||||
__u64 offset,
|
||||
__u32 len),
|
||||
TP_ARGS(rreq_debug_id, rreq_debug_index,
|
||||
xid, fid, tid, sesid, offset, len),
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, rreq_debug_id)
|
||||
__field(unsigned int, rreq_debug_index)
|
||||
__field(unsigned int, xid)
|
||||
__field(__u64, fid)
|
||||
__field(__u32, tid)
|
||||
__field(__u64, sesid)
|
||||
__field(__u64, offset)
|
||||
__field(__u32, len)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->rreq_debug_id = rreq_debug_id;
|
||||
__entry->rreq_debug_index = rreq_debug_index;
|
||||
__entry->xid = xid;
|
||||
__entry->fid = fid;
|
||||
__entry->tid = tid;
|
||||
__entry->sesid = sesid;
|
||||
__entry->offset = offset;
|
||||
__entry->len = len;
|
||||
),
|
||||
TP_printk("R=%08x[%x] xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x",
|
||||
__entry->rreq_debug_id, __entry->rreq_debug_index,
|
||||
__entry->xid, __entry->sesid, __entry->tid, __entry->fid,
|
||||
__entry->offset, __entry->len)
|
||||
)
|
||||
|
||||
#define DEFINE_SMB3_RW_DONE_EVENT(name) \
|
||||
DEFINE_EVENT(smb3_rw_done_class, smb3_##name, \
|
||||
TP_PROTO(unsigned int rreq_debug_id, \
|
||||
unsigned int rreq_debug_index, \
|
||||
unsigned int xid, \
|
||||
__u64 fid, \
|
||||
__u32 tid, \
|
||||
__u64 sesid, \
|
||||
__u64 offset, \
|
||||
__u32 len), \
|
||||
TP_ARGS(rreq_debug_id, rreq_debug_index, xid, fid, tid, sesid, offset, len))
|
||||
|
||||
DEFINE_SMB3_RW_DONE_EVENT(read_enter);
|
||||
DEFINE_SMB3_RW_DONE_EVENT(read_done);
|
||||
|
||||
/* For logging successful other op */
|
||||
DECLARE_EVENT_CLASS(smb3_other_done_class,
|
||||
TP_PROTO(unsigned int xid,
|
||||
__u64 fid,
|
||||
__u32 tid,
|
||||
@ -164,8 +272,8 @@ DECLARE_EVENT_CLASS(smb3_rw_done_class,
|
||||
__entry->offset, __entry->len)
|
||||
)
|
||||
|
||||
#define DEFINE_SMB3_RW_DONE_EVENT(name) \
|
||||
DEFINE_EVENT(smb3_rw_done_class, smb3_##name, \
|
||||
#define DEFINE_SMB3_OTHER_DONE_EVENT(name) \
|
||||
DEFINE_EVENT(smb3_other_done_class, smb3_##name, \
|
||||
TP_PROTO(unsigned int xid, \
|
||||
__u64 fid, \
|
||||
__u32 tid, \
|
||||
@ -174,16 +282,14 @@ DEFINE_EVENT(smb3_rw_done_class, smb3_##name, \
|
||||
__u32 len), \
|
||||
TP_ARGS(xid, fid, tid, sesid, offset, len))
|
||||
|
||||
DEFINE_SMB3_RW_DONE_EVENT(write_enter);
|
||||
DEFINE_SMB3_RW_DONE_EVENT(read_enter);
|
||||
DEFINE_SMB3_RW_DONE_EVENT(query_dir_enter);
|
||||
DEFINE_SMB3_RW_DONE_EVENT(zero_enter);
|
||||
DEFINE_SMB3_RW_DONE_EVENT(falloc_enter);
|
||||
DEFINE_SMB3_RW_DONE_EVENT(write_done);
|
||||
DEFINE_SMB3_RW_DONE_EVENT(read_done);
|
||||
DEFINE_SMB3_RW_DONE_EVENT(query_dir_done);
|
||||
DEFINE_SMB3_RW_DONE_EVENT(zero_done);
|
||||
DEFINE_SMB3_RW_DONE_EVENT(falloc_done);
|
||||
DEFINE_SMB3_OTHER_DONE_EVENT(write_enter);
|
||||
DEFINE_SMB3_OTHER_DONE_EVENT(query_dir_enter);
|
||||
DEFINE_SMB3_OTHER_DONE_EVENT(zero_enter);
|
||||
DEFINE_SMB3_OTHER_DONE_EVENT(falloc_enter);
|
||||
DEFINE_SMB3_OTHER_DONE_EVENT(write_done);
|
||||
DEFINE_SMB3_OTHER_DONE_EVENT(query_dir_done);
|
||||
DEFINE_SMB3_OTHER_DONE_EVENT(zero_done);
|
||||
DEFINE_SMB3_OTHER_DONE_EVENT(falloc_done);
|
||||
|
||||
/* For logging successful set EOF (truncate) */
|
||||
DECLARE_EVENT_CLASS(smb3_eof_class,
|
||||
|
@ -691,8 +691,8 @@ wait_for_compound_request(struct TCP_Server_Info *server, int num,
|
||||
}
|
||||
|
||||
int
|
||||
cifs_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
|
||||
unsigned int *num, struct cifs_credits *credits)
|
||||
cifs_wait_mtu_credits(struct TCP_Server_Info *server, size_t size,
|
||||
size_t *num, struct cifs_credits *credits)
|
||||
{
|
||||
*num = size;
|
||||
credits->value = 0;
|
||||
@ -1692,7 +1692,7 @@ __cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
||||
static int
|
||||
cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
{
|
||||
struct cifs_readdata *rdata = mid->callback_data;
|
||||
struct cifs_io_subrequest *rdata = mid->callback_data;
|
||||
|
||||
return __cifs_readv_discard(server, mid, rdata->result);
|
||||
}
|
||||
@ -1702,13 +1702,13 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
{
|
||||
int length, len;
|
||||
unsigned int data_offset, data_len;
|
||||
struct cifs_readdata *rdata = mid->callback_data;
|
||||
struct cifs_io_subrequest *rdata = mid->callback_data;
|
||||
char *buf = server->smallbuf;
|
||||
unsigned int buflen = server->pdu_size + HEADER_PREAMBLE_SIZE(server);
|
||||
bool use_rdma_mr = false;
|
||||
|
||||
cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
|
||||
__func__, mid->mid, rdata->offset, rdata->bytes);
|
||||
cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%zu\n",
|
||||
__func__, mid->mid, rdata->subreq.start, rdata->subreq.len);
|
||||
|
||||
/*
|
||||
* read the rest of READ_RSP header (sans Data array), or whatever we
|
||||
@ -1813,8 +1813,11 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
length = data_len; /* An RDMA read is already done. */
|
||||
else
|
||||
#endif
|
||||
length = cifs_read_iter_from_socket(server, &rdata->iter,
|
||||
{
|
||||
length = cifs_read_iter_from_socket(server, &rdata->subreq.io_iter,
|
||||
data_len);
|
||||
iov_iter_revert(&rdata->subreq.io_iter, data_len);
|
||||
}
|
||||
if (length > 0)
|
||||
rdata->got_bytes += length;
|
||||
server->total_read += length;
|
||||
|
@ -302,6 +302,7 @@ struct netfs_request_ops {
|
||||
|
||||
/* Modification handling */
|
||||
void (*update_i_size)(struct inode *inode, loff_t i_size);
|
||||
void (*post_modify)(struct inode *inode);
|
||||
|
||||
/* Write request handling */
|
||||
void (*begin_writeback)(struct netfs_io_request *wreq);
|
||||
|
@ -112,6 +112,7 @@
|
||||
#define netfs_sreq_ref_traces \
|
||||
EM(netfs_sreq_trace_get_copy_to_cache, "GET COPY2C ") \
|
||||
EM(netfs_sreq_trace_get_resubmit, "GET RESUBMIT") \
|
||||
EM(netfs_sreq_trace_get_submit, "GET SUBMIT") \
|
||||
EM(netfs_sreq_trace_get_short_read, "GET SHORTRD") \
|
||||
EM(netfs_sreq_trace_new, "NEW ") \
|
||||
EM(netfs_sreq_trace_put_cancel, "PUT CANCEL ") \
|
||||
|
Loading…
x
Reference in New Issue
Block a user