forked from Minki/linux
NFS client updates for Linux 5.18
Highlights include: Features: - Switch NFS to use readahead instead of the obsolete readpages. - Readdir fixes to improve cacheability of large directories when there are multiple readers and writers. - Readdir performance improvements when doing a seekdir() immediately after opening the directory (common when re-exporting NFS). - NFS swap improvements from Neil Brown. - Loosen up memory allocation to permit direct reclaim and write back in cases where there is no danger of deadlocking the writeback code or NFS swap. - Avoid sillyrename when the NFSv4 server claims to support the necessary features to recover the unlinked but open file after reboot. Bugfixes: - Patch from Olga to add a mount option to control NFSv4.1 session trunking discovery, and default it to being off. - Fix a lockup in nfs_do_recoalesce(). - Two fixes for list iterator variables being used when pointing to the list head. - Fix a kernel memory scribble when reading from a non-socket transport in /sys/kernel/sunrpc. - Fix a race where reconnecting to a server could leave the TCP socket stuck forever in the connecting state. - Patch from Neil to fix a shutdown race which can leave the SUNRPC transport timer primed after we free the struct xprt itself. - Patch from Xin Xiong to fix reference count leaks in the NFSv4.2 copy offload. - Sunrpc patch from Olga to avoid resending a task on an offlined transport. Cleanups: - Patches from Dave Wysochanski to clean up the fscache code -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEESQctxSBg8JpV8KqEZwvnipYKAPIFAmJDLLUACgkQZwvnipYK APJZ5Q/9FH5S38RcUOxpFS+XaVdmxltJTMQv9Bz5mcyljq6PwRjTn73Qs7MfBQfD k90O9Pn/EXgQpFWNW4o/saQGLAO1MbVaesdNNF92Le9NziMz7lr95fsFXOqpg9EQ rEVOImWinv/N0+P0yv5tgjx6Fheu70L4dnwsxepnmtv2R1VjXOVchK7WjsV+9qey Xvn15OzhtVCGhRvvKfmGuGW+2I0D29tRNn2X0Pi+LjxAEQ0We/rcsJeGDMGYtbeC 2U4ADk7KB0kJq04WYCH8k8tTrljL3PUONzO6QP1lltmAZ0FOwXf/AjyaD3SML2Xu A1yc2bEn3/S6wCQ3BiMxoE7UCSewg/ZyQD7B9GjZ/nWYNXREhLKvtVZt+ULTCA6o UKAI2vlEHljzQI2YfbVVZFyL8KCZqi+BFcJ/H/dtFKNazIkiefkaF+703Pflazis HjhA5G6IT0Pk6qZ6OBp+Z/4kCDYZYXXi9ysiNuMPWCiYEfZzt7ocUjm44uRAi+vR Qpf0V01Rg4iplTj3YFXqb9TwxrudzC7AcQ7hbLJia0kD/8djG+aGZs3SJWeO+VuE Xa41oxAx9jqOSRvSKPvj7nbexrwn8PtQI2NtDRqjPXlg6+Jbk23u8lIEVhsCH877 xoMUHtTKLyqECskzRN4nh7qoBD3QfiLuI74aDcPtGEuXzU1+Ox8= =jeGt -----END PGP SIGNATURE----- Merge tag 'nfs-for-5.18-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs Pull NFS client updates from Trond Myklebust: "Highlights include: Features: - Switch NFS to use readahead instead of the obsolete readpages. - Readdir fixes to improve cacheability of large directories when there are multiple readers and writers. - Readdir performance improvements when doing a seekdir() immediately after opening the directory (common when re-exporting NFS). - NFS swap improvements from Neil Brown. - Loosen up memory allocation to permit direct reclaim and write back in cases where there is no danger of deadlocking the writeback code or NFS swap. - Avoid sillyrename when the NFSv4 server claims to support the necessary features to recover the unlinked but open file after reboot. Bugfixes: - Patch from Olga to add a mount option to control NFSv4.1 session trunking discovery, and default it to being off. - Fix a lockup in nfs_do_recoalesce(). - Two fixes for list iterator variables being used when pointing to the list head. - Fix a kernel memory scribble when reading from a non-socket transport in /sys/kernel/sunrpc. - Fix a race where reconnecting to a server could leave the TCP socket stuck forever in the connecting state. - Patch from Neil to fix a shutdown race which can leave the SUNRPC transport timer primed after we free the struct xprt itself. - Patch from Xin Xiong to fix reference count leaks in the NFSv4.2 copy offload. - Sunrpc patch from Olga to avoid resending a task on an offlined transport. Cleanups: - Patches from Dave Wysochanski to clean up the fscache code" * tag 'nfs-for-5.18-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (91 commits) NFSv4/pNFS: Fix another issue with a list iterator pointing to the head NFS: Don't loop forever in nfs_do_recoalesce() SUNRPC: Don't return error values in sysfs read of closed files SUNRPC: Do not dereference non-socket transports in sysfs NFSv4.1: don't retry BIND_CONN_TO_SESSION on session error SUNRPC don't resend a task on an offlined transport NFS: replace usage of found with dedicated list iterator variable SUNRPC: avoid race between mod_timer() and del_timer_sync() pNFS/files: Ensure pNFS allocation modes are consistent with nfsiod pNFS/flexfiles: Ensure pNFS allocation modes are consistent with nfsiod NFSv4/pnfs: Ensure pNFS allocation modes are consistent with nfsiod NFS: Avoid writeback threads getting stuck in mempool_alloc() NFS: nfsiod should not block forever in mempool_alloc() SUNRPC: Make the rpciod and xprtiod slab allocation modes consistent SUNRPC: Fix unx_lookup_cred() allocation NFS: Fix memory allocation in rpc_alloc_task() NFS: Fix memory allocation in rpc_malloc() SUNRPC: Improve accuracy of socket ENOBUFS determination SUNRPC: Replace internal use of SOCKWQ_ASYNC_NOSPACE SUNRPC: Fix socket waits for write buffer space ...
This commit is contained in:
commit
965181d7ef
@ -4,6 +4,10 @@ config NFS_FS
|
||||
depends on INET && FILE_LOCKING && MULTIUSER
|
||||
select LOCKD
|
||||
select SUNRPC
|
||||
select CRYPTO
|
||||
select CRYPTO_HASH
|
||||
select XXHASH
|
||||
select CRYPTO_XXHASH
|
||||
select NFS_ACL_SUPPORT if NFS_V3_ACL
|
||||
help
|
||||
Choose Y here if you want to access files residing on other
|
||||
|
@ -358,12 +358,11 @@ __be32 nfs4_callback_devicenotify(void *argp, void *resp,
|
||||
struct cb_process_state *cps)
|
||||
{
|
||||
struct cb_devicenotifyargs *args = argp;
|
||||
const struct pnfs_layoutdriver_type *ld = NULL;
|
||||
uint32_t i;
|
||||
__be32 res = 0;
|
||||
struct nfs_client *clp = cps->clp;
|
||||
struct nfs_server *server = NULL;
|
||||
|
||||
if (!clp) {
|
||||
if (!cps->clp) {
|
||||
res = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION);
|
||||
goto out;
|
||||
}
|
||||
@ -371,23 +370,15 @@ __be32 nfs4_callback_devicenotify(void *argp, void *resp,
|
||||
for (i = 0; i < args->ndevs; i++) {
|
||||
struct cb_devicenotifyitem *dev = &args->devs[i];
|
||||
|
||||
if (!server ||
|
||||
server->pnfs_curr_ld->id != dev->cbd_layout_type) {
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
|
||||
if (server->pnfs_curr_ld &&
|
||||
server->pnfs_curr_ld->id == dev->cbd_layout_type) {
|
||||
rcu_read_unlock();
|
||||
goto found;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
continue;
|
||||
if (!ld || ld->id != dev->cbd_layout_type) {
|
||||
pnfs_put_layoutdriver(ld);
|
||||
ld = pnfs_find_layoutdriver(dev->cbd_layout_type);
|
||||
if (!ld)
|
||||
continue;
|
||||
}
|
||||
|
||||
found:
|
||||
nfs4_delete_deviceid(server->pnfs_curr_ld, clp, &dev->cbd_dev_id);
|
||||
nfs4_delete_deviceid(ld, cps->clp, &dev->cbd_dev_id);
|
||||
}
|
||||
|
||||
pnfs_put_layoutdriver(ld);
|
||||
out:
|
||||
kfree(args->devs);
|
||||
return res;
|
||||
@ -710,7 +701,7 @@ __be32 nfs4_callback_offload(void *data, void *dummy,
|
||||
struct nfs4_copy_state *copy, *tmp_copy;
|
||||
bool found = false;
|
||||
|
||||
copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS);
|
||||
copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_KERNEL);
|
||||
if (!copy)
|
||||
return htonl(NFS4ERR_SERVERFAULT);
|
||||
|
||||
|
@ -271,10 +271,6 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
|
||||
n = ntohl(*p++);
|
||||
if (n == 0)
|
||||
goto out;
|
||||
if (n > ULONG_MAX / sizeof(*args->devs)) {
|
||||
status = htonl(NFS4ERR_BADXDR);
|
||||
goto out;
|
||||
}
|
||||
|
||||
args->devs = kmalloc_array(n, sizeof(*args->devs), GFP_KERNEL);
|
||||
if (!args->devs) {
|
||||
|
@ -857,7 +857,8 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
|
||||
}
|
||||
|
||||
if (clp->rpc_ops->discover_trunking != NULL &&
|
||||
(server->caps & NFS_CAP_FS_LOCATIONS)) {
|
||||
(server->caps & NFS_CAP_FS_LOCATIONS &&
|
||||
(server->flags & NFS_MOUNT_TRUNK_DISCOVERY))) {
|
||||
error = clp->rpc_ops->discover_trunking(server, mntfh);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
@ -439,7 +439,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
|
||||
struct nfs_delegation *freeme = NULL;
|
||||
int status = 0;
|
||||
|
||||
delegation = kmalloc(sizeof(*delegation), GFP_NOFS);
|
||||
delegation = kmalloc(sizeof(*delegation), GFP_KERNEL_ACCOUNT);
|
||||
if (delegation == NULL)
|
||||
return -ENOMEM;
|
||||
nfs4_stateid_copy(&delegation->stateid, stateid);
|
||||
|
628
fs/nfs/dir.c
628
fs/nfs/dir.c
File diff suppressed because it is too large
Load Diff
@ -173,8 +173,8 @@ ssize_t nfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
||||
VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE);
|
||||
|
||||
if (iov_iter_rw(iter) == READ)
|
||||
return nfs_file_direct_read(iocb, iter);
|
||||
return nfs_file_direct_write(iocb, iter);
|
||||
return nfs_file_direct_read(iocb, iter, true);
|
||||
return nfs_file_direct_write(iocb, iter, true);
|
||||
}
|
||||
|
||||
static void nfs_direct_release_pages(struct page **pages, unsigned int npages)
|
||||
@ -425,6 +425,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
|
||||
* nfs_file_direct_read - file direct read operation for NFS files
|
||||
* @iocb: target I/O control block
|
||||
* @iter: vector of user buffers into which to read data
|
||||
* @swap: flag indicating this is swap IO, not O_DIRECT IO
|
||||
*
|
||||
* We use this function for direct reads instead of calling
|
||||
* generic_file_aio_read() in order to avoid gfar's check to see if
|
||||
@ -440,7 +441,8 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
|
||||
* client must read the updated atime from the server back into its
|
||||
* cache.
|
||||
*/
|
||||
ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter)
|
||||
ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
|
||||
bool swap)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct address_space *mapping = file->f_mapping;
|
||||
@ -482,12 +484,14 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter)
|
||||
if (iter_is_iovec(iter))
|
||||
dreq->flags = NFS_ODIRECT_SHOULD_DIRTY;
|
||||
|
||||
nfs_start_io_direct(inode);
|
||||
if (!swap)
|
||||
nfs_start_io_direct(inode);
|
||||
|
||||
NFS_I(inode)->read_io += count;
|
||||
requested = nfs_direct_read_schedule_iovec(dreq, iter, iocb->ki_pos);
|
||||
|
||||
nfs_end_io_direct(inode);
|
||||
if (!swap)
|
||||
nfs_end_io_direct(inode);
|
||||
|
||||
if (requested > 0) {
|
||||
result = nfs_direct_wait(dreq);
|
||||
@ -790,7 +794,7 @@ static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = {
|
||||
*/
|
||||
static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
|
||||
struct iov_iter *iter,
|
||||
loff_t pos)
|
||||
loff_t pos, int ioflags)
|
||||
{
|
||||
struct nfs_pageio_descriptor desc;
|
||||
struct inode *inode = dreq->inode;
|
||||
@ -798,7 +802,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
|
||||
size_t requested_bytes = 0;
|
||||
size_t wsize = max_t(size_t, NFS_SERVER(inode)->wsize, PAGE_SIZE);
|
||||
|
||||
nfs_pageio_init_write(&desc, inode, FLUSH_COND_STABLE, false,
|
||||
nfs_pageio_init_write(&desc, inode, ioflags, false,
|
||||
&nfs_direct_write_completion_ops);
|
||||
desc.pg_dreq = dreq;
|
||||
get_dreq(dreq);
|
||||
@ -876,6 +880,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
|
||||
* nfs_file_direct_write - file direct write operation for NFS files
|
||||
* @iocb: target I/O control block
|
||||
* @iter: vector of user buffers from which to write data
|
||||
* @swap: flag indicating this is swap IO, not O_DIRECT IO
|
||||
*
|
||||
* We use this function for direct writes instead of calling
|
||||
* generic_file_aio_write() in order to avoid taking the inode
|
||||
@ -892,7 +897,8 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
|
||||
* Note that O_APPEND is not supported for NFS direct writes, as there
|
||||
* is no atomic O_APPEND write facility in the NFS protocol.
|
||||
*/
|
||||
ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter)
|
||||
ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
|
||||
bool swap)
|
||||
{
|
||||
ssize_t result, requested;
|
||||
size_t count;
|
||||
@ -906,7 +912,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter)
|
||||
dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n",
|
||||
file, iov_iter_count(iter), (long long) iocb->ki_pos);
|
||||
|
||||
result = generic_write_checks(iocb, iter);
|
||||
if (swap)
|
||||
/* bypass generic checks */
|
||||
result = iov_iter_count(iter);
|
||||
else
|
||||
result = generic_write_checks(iocb, iter);
|
||||
if (result <= 0)
|
||||
return result;
|
||||
count = result;
|
||||
@ -937,17 +947,23 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter)
|
||||
dreq->iocb = iocb;
|
||||
pnfs_init_ds_commit_info_ops(&dreq->ds_cinfo, inode);
|
||||
|
||||
nfs_start_io_direct(inode);
|
||||
if (swap) {
|
||||
requested = nfs_direct_write_schedule_iovec(dreq, iter, pos,
|
||||
FLUSH_STABLE);
|
||||
} else {
|
||||
nfs_start_io_direct(inode);
|
||||
|
||||
requested = nfs_direct_write_schedule_iovec(dreq, iter, pos);
|
||||
requested = nfs_direct_write_schedule_iovec(dreq, iter, pos,
|
||||
FLUSH_COND_STABLE);
|
||||
|
||||
if (mapping->nrpages) {
|
||||
invalidate_inode_pages2_range(mapping,
|
||||
pos >> PAGE_SHIFT, end);
|
||||
if (mapping->nrpages) {
|
||||
invalidate_inode_pages2_range(mapping,
|
||||
pos >> PAGE_SHIFT, end);
|
||||
}
|
||||
|
||||
nfs_end_io_direct(inode);
|
||||
}
|
||||
|
||||
nfs_end_io_direct(inode);
|
||||
|
||||
if (requested > 0) {
|
||||
result = nfs_direct_wait(dreq);
|
||||
if (result > 0) {
|
||||
|
@ -44,11 +44,6 @@
|
||||
|
||||
static const struct vm_operations_struct nfs_file_vm_ops;
|
||||
|
||||
/* Hack for future NFS swap support */
|
||||
#ifndef IS_SWAPFILE
|
||||
# define IS_SWAPFILE(inode) (0)
|
||||
#endif
|
||||
|
||||
int nfs_check_flags(int flags)
|
||||
{
|
||||
if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT))
|
||||
@ -162,7 +157,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
|
||||
ssize_t result;
|
||||
|
||||
if (iocb->ki_flags & IOCB_DIRECT)
|
||||
return nfs_file_direct_read(iocb, to);
|
||||
return nfs_file_direct_read(iocb, to, false);
|
||||
|
||||
dprintk("NFS: read(%pD2, %zu@%lu)\n",
|
||||
iocb->ki_filp,
|
||||
@ -488,8 +483,9 @@ static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file,
|
||||
{
|
||||
unsigned long blocks;
|
||||
long long isize;
|
||||
struct rpc_clnt *clnt = NFS_CLIENT(file->f_mapping->host);
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct rpc_clnt *clnt = NFS_CLIENT(inode);
|
||||
struct nfs_client *cl = NFS_SERVER(inode)->nfs_client;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
blocks = inode->i_blocks;
|
||||
@ -502,19 +498,27 @@ static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file,
|
||||
|
||||
*span = sis->pages;
|
||||
|
||||
|
||||
if (cl->rpc_ops->enable_swap)
|
||||
cl->rpc_ops->enable_swap(inode);
|
||||
|
||||
return rpc_clnt_swap_activate(clnt);
|
||||
}
|
||||
|
||||
static void nfs_swap_deactivate(struct file *file)
|
||||
{
|
||||
struct rpc_clnt *clnt = NFS_CLIENT(file->f_mapping->host);
|
||||
struct inode *inode = file_inode(file);
|
||||
struct rpc_clnt *clnt = NFS_CLIENT(inode);
|
||||
struct nfs_client *cl = NFS_SERVER(inode)->nfs_client;
|
||||
|
||||
rpc_clnt_swap_deactivate(clnt);
|
||||
if (cl->rpc_ops->disable_swap)
|
||||
cl->rpc_ops->disable_swap(file_inode(file));
|
||||
}
|
||||
|
||||
const struct address_space_operations nfs_file_aops = {
|
||||
.readpage = nfs_readpage,
|
||||
.readpages = nfs_readpages,
|
||||
.readahead = nfs_readahead,
|
||||
.dirty_folio = filemap_dirty_folio,
|
||||
.writepage = nfs_writepage,
|
||||
.writepages = nfs_writepages,
|
||||
@ -619,7 +623,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
|
||||
return result;
|
||||
|
||||
if (iocb->ki_flags & IOCB_DIRECT)
|
||||
return nfs_file_direct_write(iocb, from);
|
||||
return nfs_file_direct_write(iocb, from, false);
|
||||
|
||||
dprintk("NFS: write(%pD2, %zu@%Ld)\n",
|
||||
file, iov_iter_count(from), (long long) iocb->ki_pos);
|
||||
|
@ -1075,7 +1075,7 @@ filelayout_setup_ds_info(struct pnfs_ds_commit_info *fl_cinfo,
|
||||
unsigned int size = (fl->stripe_type == STRIPE_SPARSE) ?
|
||||
fl->dsaddr->ds_num : fl->dsaddr->stripe_count;
|
||||
|
||||
new = pnfs_alloc_commit_array(size, GFP_NOIO);
|
||||
new = pnfs_alloc_commit_array(size, nfs_io_gfp_mask());
|
||||
if (new) {
|
||||
spin_lock(&inode->i_lock);
|
||||
array = pnfs_add_commit_array(fl_cinfo, new, lseg);
|
||||
|
@ -663,7 +663,7 @@ nfs4_ff_layout_stat_io_start_read(struct inode *inode,
|
||||
spin_unlock(&mirror->lock);
|
||||
|
||||
if (report)
|
||||
pnfs_report_layoutstat(inode, GFP_KERNEL);
|
||||
pnfs_report_layoutstat(inode, nfs_io_gfp_mask());
|
||||
}
|
||||
|
||||
static void
|
||||
@ -694,7 +694,7 @@ nfs4_ff_layout_stat_io_start_write(struct inode *inode,
|
||||
spin_unlock(&mirror->lock);
|
||||
|
||||
if (report)
|
||||
pnfs_report_layoutstat(inode, GFP_NOIO);
|
||||
pnfs_report_layoutstat(inode, nfs_io_gfp_mask());
|
||||
}
|
||||
|
||||
static void
|
||||
@ -806,13 +806,10 @@ ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio,
|
||||
bool strict_iomode)
|
||||
{
|
||||
pnfs_put_lseg(pgio->pg_lseg);
|
||||
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
|
||||
nfs_req_openctx(req),
|
||||
req_offset(req),
|
||||
req->wb_bytes,
|
||||
IOMODE_READ,
|
||||
strict_iomode,
|
||||
GFP_KERNEL);
|
||||
pgio->pg_lseg =
|
||||
pnfs_update_layout(pgio->pg_inode, nfs_req_openctx(req),
|
||||
req_offset(req), req->wb_bytes, IOMODE_READ,
|
||||
strict_iomode, nfs_io_gfp_mask());
|
||||
if (IS_ERR(pgio->pg_lseg)) {
|
||||
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
|
||||
pgio->pg_lseg = NULL;
|
||||
@ -894,13 +891,10 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
|
||||
retry:
|
||||
ff_layout_pg_check_layout(pgio, req);
|
||||
if (!pgio->pg_lseg) {
|
||||
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
|
||||
nfs_req_openctx(req),
|
||||
req_offset(req),
|
||||
req->wb_bytes,
|
||||
IOMODE_RW,
|
||||
false,
|
||||
GFP_NOFS);
|
||||
pgio->pg_lseg =
|
||||
pnfs_update_layout(pgio->pg_inode, nfs_req_openctx(req),
|
||||
req_offset(req), req->wb_bytes,
|
||||
IOMODE_RW, false, nfs_io_gfp_mask());
|
||||
if (IS_ERR(pgio->pg_lseg)) {
|
||||
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
|
||||
pgio->pg_lseg = NULL;
|
||||
@ -953,13 +947,10 @@ ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio,
|
||||
struct nfs_page *req)
|
||||
{
|
||||
if (!pgio->pg_lseg) {
|
||||
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
|
||||
nfs_req_openctx(req),
|
||||
req_offset(req),
|
||||
req->wb_bytes,
|
||||
IOMODE_RW,
|
||||
false,
|
||||
GFP_NOFS);
|
||||
pgio->pg_lseg =
|
||||
pnfs_update_layout(pgio->pg_inode, nfs_req_openctx(req),
|
||||
req_offset(req), req->wb_bytes,
|
||||
IOMODE_RW, false, nfs_io_gfp_mask());
|
||||
if (IS_ERR(pgio->pg_lseg)) {
|
||||
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
|
||||
pgio->pg_lseg = NULL;
|
||||
@ -1258,7 +1249,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg,
|
||||
mirror = FF_LAYOUT_COMP(lseg, idx);
|
||||
err = ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout),
|
||||
mirror, offset, length, status, opnum,
|
||||
GFP_NOIO);
|
||||
nfs_io_gfp_mask());
|
||||
|
||||
switch (status) {
|
||||
case NFS4ERR_DELAY:
|
||||
@ -1973,7 +1964,8 @@ ff_layout_setup_ds_info(struct pnfs_ds_commit_info *fl_cinfo,
|
||||
struct inode *inode = lseg->pls_layout->plh_inode;
|
||||
struct pnfs_commit_array *array, *new;
|
||||
|
||||
new = pnfs_alloc_commit_array(flseg->mirror_array_cnt, GFP_NOIO);
|
||||
new = pnfs_alloc_commit_array(flseg->mirror_array_cnt,
|
||||
nfs_io_gfp_mask());
|
||||
if (new) {
|
||||
spin_lock(&inode->i_lock);
|
||||
array = pnfs_add_commit_array(fl_cinfo, new, lseg);
|
||||
@ -2152,10 +2144,10 @@ ff_layout_prepare_layoutreturn(struct nfs4_layoutreturn_args *args)
|
||||
struct nfs4_flexfile_layoutreturn_args *ff_args;
|
||||
struct nfs4_flexfile_layout *ff_layout = FF_LAYOUT_FROM_HDR(args->layout);
|
||||
|
||||
ff_args = kmalloc(sizeof(*ff_args), GFP_KERNEL);
|
||||
ff_args = kmalloc(sizeof(*ff_args), nfs_io_gfp_mask());
|
||||
if (!ff_args)
|
||||
goto out_nomem;
|
||||
ff_args->pages[0] = alloc_page(GFP_KERNEL);
|
||||
ff_args->pages[0] = alloc_page(nfs_io_gfp_mask());
|
||||
if (!ff_args->pages[0])
|
||||
goto out_nomem_free;
|
||||
|
||||
@ -2192,8 +2184,8 @@ ff_layout_send_layouterror(struct pnfs_layout_segment *lseg)
|
||||
if (list_empty(&head))
|
||||
return;
|
||||
|
||||
errors = kmalloc_array(NFS42_LAYOUTERROR_MAX,
|
||||
sizeof(*errors), GFP_NOFS);
|
||||
errors = kmalloc_array(NFS42_LAYOUTERROR_MAX, sizeof(*errors),
|
||||
nfs_io_gfp_mask());
|
||||
if (errors != NULL) {
|
||||
const struct nfs4_ff_layout_ds_err *pos;
|
||||
size_t n = 0;
|
||||
@ -2444,7 +2436,8 @@ ff_layout_prepare_layoutstats(struct nfs42_layoutstat_args *args)
|
||||
const int dev_count = PNFS_LAYOUTSTATS_MAXDEV;
|
||||
|
||||
/* For now, send at most PNFS_LAYOUTSTATS_MAXDEV statistics */
|
||||
args->devinfo = kmalloc_array(dev_count, sizeof(*args->devinfo), GFP_NOIO);
|
||||
args->devinfo = kmalloc_array(dev_count, sizeof(*args->devinfo),
|
||||
nfs_io_gfp_mask());
|
||||
if (!args->devinfo)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -80,6 +80,7 @@ enum nfs_param {
|
||||
Opt_source,
|
||||
Opt_tcp,
|
||||
Opt_timeo,
|
||||
Opt_trunkdiscovery,
|
||||
Opt_udp,
|
||||
Opt_v,
|
||||
Opt_vers,
|
||||
@ -180,6 +181,7 @@ static const struct fs_parameter_spec nfs_fs_parameters[] = {
|
||||
fsparam_string("source", Opt_source),
|
||||
fsparam_flag ("tcp", Opt_tcp),
|
||||
fsparam_u32 ("timeo", Opt_timeo),
|
||||
fsparam_flag_no("trunkdiscovery", Opt_trunkdiscovery),
|
||||
fsparam_flag ("udp", Opt_udp),
|
||||
fsparam_flag ("v2", Opt_v),
|
||||
fsparam_flag ("v3", Opt_v),
|
||||
@ -529,6 +531,12 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
|
||||
else
|
||||
ctx->flags &= ~NFS_MOUNT_NOCTO;
|
||||
break;
|
||||
case Opt_trunkdiscovery:
|
||||
if (result.negated)
|
||||
ctx->flags &= ~NFS_MOUNT_TRUNK_DISCOVERY;
|
||||
else
|
||||
ctx->flags |= NFS_MOUNT_TRUNK_DISCOVERY;
|
||||
break;
|
||||
case Opt_ac:
|
||||
if (result.negated)
|
||||
ctx->flags |= NFS_MOUNT_NOAC;
|
||||
|
@ -19,8 +19,7 @@
|
||||
#include "internal.h"
|
||||
#include "iostat.h"
|
||||
#include "fscache.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_FSCACHE
|
||||
#include "nfstrace.h"
|
||||
|
||||
#define NFS_MAX_KEY_LEN 1000
|
||||
|
||||
@ -128,8 +127,6 @@ int nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int u
|
||||
vcookie = fscache_acquire_volume(key,
|
||||
NULL, /* preferred_cache */
|
||||
NULL, 0 /* coherency_data */);
|
||||
dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n",
|
||||
nfss, vcookie);
|
||||
if (IS_ERR(vcookie)) {
|
||||
if (vcookie != ERR_PTR(-EBUSY)) {
|
||||
kfree(key);
|
||||
@ -152,9 +149,6 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
|
||||
{
|
||||
struct nfs_server *nfss = NFS_SB(sb);
|
||||
|
||||
dfprintk(FSCACHE, "NFS: releasing superblock cookie (0x%p/0x%p)\n",
|
||||
nfss, nfss->fscache);
|
||||
|
||||
fscache_relinquish_volume(nfss->fscache, NULL, false);
|
||||
nfss->fscache = NULL;
|
||||
kfree(nfss->fscache_uniq);
|
||||
@ -173,7 +167,7 @@ void nfs_fscache_init_inode(struct inode *inode)
|
||||
if (!(nfss->fscache && S_ISREG(inode->i_mode)))
|
||||
return;
|
||||
|
||||
nfs_fscache_update_auxdata(&auxdata, nfsi);
|
||||
nfs_fscache_update_auxdata(&auxdata, inode);
|
||||
|
||||
nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache,
|
||||
0,
|
||||
@ -181,7 +175,7 @@ void nfs_fscache_init_inode(struct inode *inode)
|
||||
nfsi->fh.size,
|
||||
&auxdata, /* aux_data */
|
||||
sizeof(auxdata),
|
||||
i_size_read(&nfsi->vfs_inode));
|
||||
i_size_read(inode));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -192,8 +186,6 @@ void nfs_fscache_clear_inode(struct inode *inode)
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
struct fscache_cookie *cookie = nfs_i_fscache(inode);
|
||||
|
||||
dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie);
|
||||
|
||||
fscache_relinquish_cookie(cookie, false);
|
||||
nfsi->fscache = NULL;
|
||||
}
|
||||
@ -220,7 +212,6 @@ void nfs_fscache_clear_inode(struct inode *inode)
|
||||
void nfs_fscache_open_file(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct nfs_fscache_inode_auxdata auxdata;
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
struct fscache_cookie *cookie = nfs_i_fscache(inode);
|
||||
bool open_for_write = inode_is_open_for_write(inode);
|
||||
|
||||
@ -229,8 +220,7 @@ void nfs_fscache_open_file(struct inode *inode, struct file *filp)
|
||||
|
||||
fscache_use_cookie(cookie, open_for_write);
|
||||
if (open_for_write) {
|
||||
dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi);
|
||||
nfs_fscache_update_auxdata(&auxdata, nfsi);
|
||||
nfs_fscache_update_auxdata(&auxdata, inode);
|
||||
fscache_invalidate(cookie, &auxdata, i_size_read(inode),
|
||||
FSCACHE_INVAL_DIO_WRITE);
|
||||
}
|
||||
@ -240,11 +230,10 @@ EXPORT_SYMBOL_GPL(nfs_fscache_open_file);
|
||||
void nfs_fscache_release_file(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct nfs_fscache_inode_auxdata auxdata;
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
struct fscache_cookie *cookie = nfs_i_fscache(inode);
|
||||
|
||||
if (fscache_cookie_valid(cookie)) {
|
||||
nfs_fscache_update_auxdata(&auxdata, nfsi);
|
||||
nfs_fscache_update_auxdata(&auxdata, inode);
|
||||
fscache_unuse_cookie(cookie, &auxdata, NULL);
|
||||
}
|
||||
}
|
||||
@ -319,58 +308,50 @@ static int fscache_fallback_write_page(struct inode *inode, struct page *page,
|
||||
/*
|
||||
* Retrieve a page from fscache
|
||||
*/
|
||||
int __nfs_readpage_from_fscache(struct inode *inode, struct page *page)
|
||||
int __nfs_fscache_read_page(struct inode *inode, struct page *page)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dfprintk(FSCACHE,
|
||||
"NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n",
|
||||
nfs_i_fscache(inode), page, page->index, page->flags, inode);
|
||||
|
||||
trace_nfs_fscache_read_page(inode, page);
|
||||
if (PageChecked(page)) {
|
||||
dfprintk(FSCACHE, "NFS: readpage_from_fscache: PageChecked\n");
|
||||
ClearPageChecked(page);
|
||||
return 1;
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fscache_fallback_read_page(inode, page);
|
||||
if (ret < 0) {
|
||||
nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL);
|
||||
dfprintk(FSCACHE,
|
||||
"NFS: readpage_from_fscache failed %d\n", ret);
|
||||
SetPageChecked(page);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Read completed synchronously */
|
||||
dfprintk(FSCACHE, "NFS: readpage_from_fscache: read successful\n");
|
||||
nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_OK);
|
||||
SetPageUptodate(page);
|
||||
return 0;
|
||||
ret = 0;
|
||||
out:
|
||||
trace_nfs_fscache_read_page_exit(inode, page, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store a newly fetched page in fscache. We can be certain there's no page
|
||||
* stored in the cache as yet otherwise we would've read it from there.
|
||||
*/
|
||||
void __nfs_readpage_to_fscache(struct inode *inode, struct page *page)
|
||||
void __nfs_fscache_write_page(struct inode *inode, struct page *page)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dfprintk(FSCACHE,
|
||||
"NFS: readpage_to_fscache(fsc:%p/p:%p(i:%lx f:%lx))\n",
|
||||
nfs_i_fscache(inode), page, page->index, page->flags);
|
||||
trace_nfs_fscache_write_page(inode, page);
|
||||
|
||||
ret = fscache_fallback_write_page(inode, page, true);
|
||||
|
||||
dfprintk(FSCACHE,
|
||||
"NFS: readpage_to_fscache: p:%p(i:%lu f:%lx) ret %d\n",
|
||||
page, page->index, page->flags, ret);
|
||||
|
||||
if (ret != 0) {
|
||||
nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_WRITTEN_FAIL);
|
||||
nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_UNCACHED);
|
||||
} else {
|
||||
nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_WRITTEN_OK);
|
||||
}
|
||||
trace_nfs_fscache_write_page_exit(inode, page, ret);
|
||||
}
|
||||
|
@ -45,10 +45,8 @@ extern void nfs_fscache_clear_inode(struct inode *);
|
||||
extern void nfs_fscache_open_file(struct inode *, struct file *);
|
||||
extern void nfs_fscache_release_file(struct inode *, struct file *);
|
||||
|
||||
extern int __nfs_readpage_from_fscache(struct inode *, struct page *);
|
||||
extern void __nfs_read_completion_to_fscache(struct nfs_pgio_header *hdr,
|
||||
unsigned long bytes);
|
||||
extern void __nfs_readpage_to_fscache(struct inode *, struct page *);
|
||||
extern int __nfs_fscache_read_page(struct inode *, struct page *);
|
||||
extern void __nfs_fscache_write_page(struct inode *, struct page *);
|
||||
|
||||
static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp)
|
||||
{
|
||||
@ -66,11 +64,10 @@ static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp)
|
||||
/*
|
||||
* Retrieve a page from an inode data storage object.
|
||||
*/
|
||||
static inline int nfs_readpage_from_fscache(struct inode *inode,
|
||||
struct page *page)
|
||||
static inline int nfs_fscache_read_page(struct inode *inode, struct page *page)
|
||||
{
|
||||
if (NFS_I(inode)->fscache)
|
||||
return __nfs_readpage_from_fscache(inode, page);
|
||||
if (nfs_i_fscache(inode))
|
||||
return __nfs_fscache_read_page(inode, page);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
@ -78,24 +75,24 @@ static inline int nfs_readpage_from_fscache(struct inode *inode,
|
||||
* Store a page newly fetched from the server in an inode data storage object
|
||||
* in the cache.
|
||||
*/
|
||||
static inline void nfs_readpage_to_fscache(struct inode *inode,
|
||||
static inline void nfs_fscache_write_page(struct inode *inode,
|
||||
struct page *page)
|
||||
{
|
||||
if (NFS_I(inode)->fscache)
|
||||
__nfs_readpage_to_fscache(inode, page);
|
||||
if (nfs_i_fscache(inode))
|
||||
__nfs_fscache_write_page(inode, page);
|
||||
}
|
||||
|
||||
static inline void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata *auxdata,
|
||||
struct nfs_inode *nfsi)
|
||||
struct inode *inode)
|
||||
{
|
||||
memset(auxdata, 0, sizeof(*auxdata));
|
||||
auxdata->mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec;
|
||||
auxdata->mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
|
||||
auxdata->ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec;
|
||||
auxdata->ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
|
||||
auxdata->mtime_sec = inode->i_mtime.tv_sec;
|
||||
auxdata->mtime_nsec = inode->i_mtime.tv_nsec;
|
||||
auxdata->ctime_sec = inode->i_ctime.tv_sec;
|
||||
auxdata->ctime_nsec = inode->i_ctime.tv_nsec;
|
||||
|
||||
if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
|
||||
auxdata->change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
|
||||
if (NFS_SERVER(inode)->nfs_client->rpc_ops->version == 4)
|
||||
auxdata->change_attr = inode_peek_iversion_raw(inode);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -107,9 +104,9 @@ static inline void nfs_fscache_invalidate(struct inode *inode, int flags)
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
|
||||
if (nfsi->fscache) {
|
||||
nfs_fscache_update_auxdata(&auxdata, nfsi);
|
||||
nfs_fscache_update_auxdata(&auxdata, inode);
|
||||
fscache_invalidate(nfsi->fscache, &auxdata,
|
||||
i_size_read(&nfsi->vfs_inode), flags);
|
||||
i_size_read(inode), flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,15 +133,11 @@ static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp)
|
||||
{
|
||||
return 1; /* True: may release page */
|
||||
}
|
||||
static inline int nfs_readpage_from_fscache(struct inode *inode,
|
||||
struct page *page)
|
||||
static inline int nfs_fscache_read_page(struct inode *inode, struct page *page)
|
||||
{
|
||||
return -ENOBUFS;
|
||||
}
|
||||
static inline void nfs_readpage_to_fscache(struct inode *inode,
|
||||
struct page *page) {}
|
||||
|
||||
|
||||
static inline void nfs_fscache_write_page(struct inode *inode, struct page *page) {}
|
||||
static inline void nfs_fscache_invalidate(struct inode *inode, int flags) {}
|
||||
|
||||
static inline const char *nfs_server_fscache_state(struct nfs_server *server)
|
||||
|
@ -203,14 +203,13 @@ void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
|
||||
NFS_INO_INVALID_OTHER |
|
||||
NFS_INO_INVALID_XATTR);
|
||||
flags &= ~(NFS_INO_INVALID_CHANGE | NFS_INO_INVALID_SIZE);
|
||||
} else if (flags & NFS_INO_REVAL_PAGECACHE)
|
||||
flags |= NFS_INO_INVALID_CHANGE | NFS_INO_INVALID_SIZE;
|
||||
}
|
||||
|
||||
if (!nfs_has_xattr_cache(nfsi))
|
||||
flags &= ~NFS_INO_INVALID_XATTR;
|
||||
if (flags & NFS_INO_INVALID_DATA)
|
||||
nfs_fscache_invalidate(inode, 0);
|
||||
flags &= ~(NFS_INO_REVAL_PAGECACHE | NFS_INO_REVAL_FORCED);
|
||||
flags &= ~NFS_INO_REVAL_FORCED;
|
||||
|
||||
nfsi->cache_validity |= flags;
|
||||
|
||||
@ -236,19 +235,17 @@ static void nfs_zap_caches_locked(struct inode *inode)
|
||||
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
|
||||
nfsi->attrtimeo_timestamp = jiffies;
|
||||
|
||||
if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) {
|
||||
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR
|
||||
| NFS_INO_INVALID_DATA
|
||||
| NFS_INO_INVALID_ACCESS
|
||||
| NFS_INO_INVALID_ACL
|
||||
| NFS_INO_INVALID_XATTR
|
||||
| NFS_INO_REVAL_PAGECACHE);
|
||||
} else
|
||||
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR
|
||||
| NFS_INO_INVALID_ACCESS
|
||||
| NFS_INO_INVALID_ACL
|
||||
| NFS_INO_INVALID_XATTR
|
||||
| NFS_INO_REVAL_PAGECACHE);
|
||||
if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
|
||||
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR |
|
||||
NFS_INO_INVALID_DATA |
|
||||
NFS_INO_INVALID_ACCESS |
|
||||
NFS_INO_INVALID_ACL |
|
||||
NFS_INO_INVALID_XATTR);
|
||||
else
|
||||
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR |
|
||||
NFS_INO_INVALID_ACCESS |
|
||||
NFS_INO_INVALID_ACL |
|
||||
NFS_INO_INVALID_XATTR);
|
||||
nfs_zap_label_cache_locked(nfsi);
|
||||
}
|
||||
|
||||
@ -564,8 +561,6 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
|
||||
inode->i_gid = fattr->gid;
|
||||
else if (fattr_supported & NFS_ATTR_FATTR_GROUP)
|
||||
nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
|
||||
if (nfs_server_capable(inode, NFS_CAP_XATTR))
|
||||
nfs_set_cache_invalid(inode, NFS_INO_INVALID_XATTR);
|
||||
if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
|
||||
inode->i_blocks = fattr->du.nfs2.blocks;
|
||||
else if (fattr_supported & NFS_ATTR_FATTR_BLOCKS_USED &&
|
||||
@ -785,26 +780,32 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_setattr_update_inode);
|
||||
|
||||
/*
|
||||
* Don't request help from readdirplus if the file is being written to,
|
||||
* or if attribute caching is turned off
|
||||
*/
|
||||
static bool nfs_getattr_readdirplus_enable(const struct inode *inode)
|
||||
{
|
||||
return nfs_server_capable(inode, NFS_CAP_READDIRPLUS) &&
|
||||
!nfs_have_writebacks(inode) && NFS_MAXATTRTIMEO(inode) > 5 * HZ;
|
||||
}
|
||||
|
||||
static void nfs_readdirplus_parent_cache_miss(struct dentry *dentry)
|
||||
{
|
||||
struct dentry *parent;
|
||||
|
||||
if (!nfs_server_capable(d_inode(dentry), NFS_CAP_READDIRPLUS))
|
||||
return;
|
||||
parent = dget_parent(dentry);
|
||||
nfs_force_use_readdirplus(d_inode(parent));
|
||||
dput(parent);
|
||||
if (!IS_ROOT(dentry)) {
|
||||
struct dentry *parent = dget_parent(dentry);
|
||||
nfs_readdir_record_entry_cache_miss(d_inode(parent));
|
||||
dput(parent);
|
||||
}
|
||||
}
|
||||
|
||||
static void nfs_readdirplus_parent_cache_hit(struct dentry *dentry)
|
||||
{
|
||||
struct dentry *parent;
|
||||
|
||||
if (!nfs_server_capable(d_inode(dentry), NFS_CAP_READDIRPLUS))
|
||||
return;
|
||||
parent = dget_parent(dentry);
|
||||
nfs_advise_use_readdirplus(d_inode(parent));
|
||||
dput(parent);
|
||||
if (!IS_ROOT(dentry)) {
|
||||
struct dentry *parent = dget_parent(dentry);
|
||||
nfs_readdir_record_entry_cache_hit(d_inode(parent));
|
||||
dput(parent);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 nfs_get_valid_attrmask(struct inode *inode)
|
||||
@ -840,6 +841,7 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
|
||||
int err = 0;
|
||||
bool force_sync = query_flags & AT_STATX_FORCE_SYNC;
|
||||
bool do_update = false;
|
||||
bool readdirplus_enabled = nfs_getattr_readdirplus_enable(inode);
|
||||
|
||||
trace_nfs_getattr_enter(inode);
|
||||
|
||||
@ -848,7 +850,8 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
|
||||
STATX_INO | STATX_SIZE | STATX_BLOCKS;
|
||||
|
||||
if ((query_flags & AT_STATX_DONT_SYNC) && !force_sync) {
|
||||
nfs_readdirplus_parent_cache_hit(path->dentry);
|
||||
if (readdirplus_enabled)
|
||||
nfs_readdirplus_parent_cache_hit(path->dentry);
|
||||
goto out_no_revalidate;
|
||||
}
|
||||
|
||||
@ -898,15 +901,12 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
|
||||
do_update |= cache_validity & NFS_INO_INVALID_BLOCKS;
|
||||
|
||||
if (do_update) {
|
||||
/* Update the attribute cache */
|
||||
if (!(server->flags & NFS_MOUNT_NOAC))
|
||||
if (readdirplus_enabled)
|
||||
nfs_readdirplus_parent_cache_miss(path->dentry);
|
||||
else
|
||||
nfs_readdirplus_parent_cache_hit(path->dentry);
|
||||
err = __nfs_revalidate_inode(server, inode);
|
||||
if (err)
|
||||
goto out;
|
||||
} else
|
||||
} else if (readdirplus_enabled)
|
||||
nfs_readdirplus_parent_cache_hit(path->dentry);
|
||||
out_no_revalidate:
|
||||
/* Only return attributes that were revalidated. */
|
||||
@ -952,7 +952,7 @@ struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx)
|
||||
res = __nfs_find_lock_context(ctx);
|
||||
rcu_read_unlock();
|
||||
if (res == NULL) {
|
||||
new = kmalloc(sizeof(*new), GFP_KERNEL);
|
||||
new = kmalloc(sizeof(*new), GFP_KERNEL_ACCOUNT);
|
||||
if (new == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
nfs_init_lock_context(new);
|
||||
@ -1030,7 +1030,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry,
|
||||
{
|
||||
struct nfs_open_context *ctx;
|
||||
|
||||
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT);
|
||||
if (!ctx)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
nfs_sb_active(dentry->d_sb);
|
||||
@ -1583,7 +1583,7 @@ struct nfs_fattr *nfs_alloc_fattr(void)
|
||||
{
|
||||
struct nfs_fattr *fattr;
|
||||
|
||||
fattr = kmalloc(sizeof(*fattr), GFP_NOFS);
|
||||
fattr = kmalloc(sizeof(*fattr), GFP_KERNEL);
|
||||
if (fattr != NULL) {
|
||||
nfs_fattr_init(fattr);
|
||||
fattr->label = NULL;
|
||||
@ -1599,7 +1599,7 @@ struct nfs_fattr *nfs_alloc_fattr_with_label(struct nfs_server *server)
|
||||
if (!fattr)
|
||||
return NULL;
|
||||
|
||||
fattr->label = nfs4_label_alloc(server, GFP_NOFS);
|
||||
fattr->label = nfs4_label_alloc(server, GFP_KERNEL);
|
||||
if (IS_ERR(fattr->label)) {
|
||||
kfree(fattr);
|
||||
return NULL;
|
||||
@ -1613,7 +1613,7 @@ struct nfs_fh *nfs_alloc_fhandle(void)
|
||||
{
|
||||
struct nfs_fh *fh;
|
||||
|
||||
fh = kmalloc(sizeof(struct nfs_fh), GFP_NOFS);
|
||||
fh = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL);
|
||||
if (fh != NULL)
|
||||
fh->size = 0;
|
||||
return fh;
|
||||
|
@ -366,8 +366,8 @@ extern struct nfs_client *nfs_init_client(struct nfs_client *clp,
|
||||
const struct nfs_client_initdata *);
|
||||
|
||||
/* dir.c */
|
||||
extern void nfs_advise_use_readdirplus(struct inode *dir);
|
||||
extern void nfs_force_use_readdirplus(struct inode *dir);
|
||||
extern void nfs_readdir_record_entry_cache_hit(struct inode *dir);
|
||||
extern void nfs_readdir_record_entry_cache_miss(struct inode *dir);
|
||||
extern unsigned long nfs_access_cache_count(struct shrinker *shrink,
|
||||
struct shrink_control *sc);
|
||||
extern unsigned long nfs_access_cache_scan(struct shrinker *shrink,
|
||||
@ -388,6 +388,20 @@ int nfs_mknod(struct user_namespace *, struct inode *, struct dentry *, umode_t,
|
||||
int nfs_rename(struct user_namespace *, struct inode *, struct dentry *,
|
||||
struct inode *, struct dentry *, unsigned int);
|
||||
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
static inline __u32 nfs_access_xattr_mask(const struct nfs_server *server)
|
||||
{
|
||||
if (!(server->caps & NFS_CAP_XATTR))
|
||||
return 0;
|
||||
return NFS4_ACCESS_XAREAD | NFS4_ACCESS_XAWRITE | NFS4_ACCESS_XALIST;
|
||||
}
|
||||
#else
|
||||
static inline __u32 nfs_access_xattr_mask(const struct nfs_server *server)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* file.c */
|
||||
int nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync);
|
||||
loff_t nfs_file_llseek(struct file *, loff_t, int);
|
||||
@ -573,6 +587,13 @@ nfs_write_match_verf(const struct nfs_writeverf *verf,
|
||||
!nfs_write_verifier_cmp(&req->wb_verf, &verf->verifier);
|
||||
}
|
||||
|
||||
static inline gfp_t nfs_io_gfp_mask(void)
|
||||
{
|
||||
if (current->flags & PF_WQ_WORKER)
|
||||
return GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN;
|
||||
return GFP_KERNEL;
|
||||
}
|
||||
|
||||
/* unlink.c */
|
||||
extern struct rpc_task *
|
||||
nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
|
||||
|
@ -949,13 +949,12 @@ int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
|
||||
|
||||
error = decode_filename_inline(xdr, &entry->name, &entry->len);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
return -EAGAIN;
|
||||
|
||||
/*
|
||||
* The type (size and byte order) of nfscookie isn't defined in
|
||||
* RFC 1094. This implementation assumes that it's an XDR uint32.
|
||||
*/
|
||||
entry->prev_cookie = entry->cookie;
|
||||
p = xdr_inline_decode(xdr, 4);
|
||||
if (unlikely(!p))
|
||||
return -EAGAIN;
|
||||
|
@ -1261,6 +1261,8 @@ static void nfs3_xdr_enc_readdir3args(struct rpc_rqst *req,
|
||||
static void encode_readdirplus3args(struct xdr_stream *xdr,
|
||||
const struct nfs3_readdirargs *args)
|
||||
{
|
||||
uint32_t dircount = args->count;
|
||||
uint32_t maxcount = args->count;
|
||||
__be32 *p;
|
||||
|
||||
encode_nfs_fh3(xdr, args->fh);
|
||||
@ -1273,9 +1275,8 @@ static void encode_readdirplus3args(struct xdr_stream *xdr,
|
||||
* readdirplus: need dircount + buffer size.
|
||||
* We just make sure we make dircount big enough
|
||||
*/
|
||||
*p++ = cpu_to_be32(args->count >> 3);
|
||||
|
||||
*p = cpu_to_be32(args->count);
|
||||
*p++ = cpu_to_be32(dircount);
|
||||
*p = cpu_to_be32(maxcount);
|
||||
}
|
||||
|
||||
static void nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req,
|
||||
@ -1967,7 +1968,6 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
|
||||
bool plus)
|
||||
{
|
||||
struct user_namespace *userns = rpc_userns(entry->server->client);
|
||||
struct nfs_entry old = *entry;
|
||||
__be32 *p;
|
||||
int error;
|
||||
u64 new_cookie;
|
||||
@ -1987,15 +1987,15 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
|
||||
|
||||
error = decode_fileid3(xdr, &entry->ino);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
return -EAGAIN;
|
||||
|
||||
error = decode_inline_filename3(xdr, &entry->name, &entry->len);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
return -EAGAIN;
|
||||
|
||||
error = decode_cookie3(xdr, &new_cookie);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
return -EAGAIN;
|
||||
|
||||
entry->d_type = DT_UNKNOWN;
|
||||
|
||||
@ -2003,7 +2003,7 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
|
||||
entry->fattr->valid = 0;
|
||||
error = decode_post_op_attr(xdr, entry->fattr, userns);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
return -EAGAIN;
|
||||
if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
|
||||
entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
|
||||
|
||||
@ -2018,24 +2018,15 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
|
||||
return -EAGAIN;
|
||||
if (*p != xdr_zero) {
|
||||
error = decode_nfs_fh3(xdr, entry->fh);
|
||||
if (unlikely(error)) {
|
||||
if (error == -E2BIG)
|
||||
goto out_truncated;
|
||||
return error;
|
||||
}
|
||||
if (unlikely(error))
|
||||
return -EAGAIN;
|
||||
} else
|
||||
zero_nfs_fh3(entry->fh);
|
||||
}
|
||||
|
||||
entry->prev_cookie = entry->cookie;
|
||||
entry->cookie = new_cookie;
|
||||
|
||||
return 0;
|
||||
|
||||
out_truncated:
|
||||
dprintk("NFS: directory entry contains invalid file handle\n");
|
||||
*entry = old;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2228,6 +2219,7 @@ static int decode_fsinfo3resok(struct xdr_stream *xdr,
|
||||
/* ignore properties */
|
||||
result->lease_time = 0;
|
||||
result->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED;
|
||||
result->xattr_support = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -175,28 +175,27 @@ static int handle_async_copy(struct nfs42_copy_res *res,
|
||||
nfs4_stateid *src_stateid,
|
||||
bool *restart)
|
||||
{
|
||||
struct nfs4_copy_state *copy, *tmp_copy;
|
||||
struct nfs4_copy_state *copy, *tmp_copy = NULL, *iter;
|
||||
int status = NFS4_OK;
|
||||
bool found_pending = false;
|
||||
struct nfs_open_context *dst_ctx = nfs_file_open_context(dst);
|
||||
struct nfs_open_context *src_ctx = nfs_file_open_context(src);
|
||||
|
||||
copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS);
|
||||
copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_KERNEL);
|
||||
if (!copy)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock(&dst_server->nfs_client->cl_lock);
|
||||
list_for_each_entry(tmp_copy,
|
||||
list_for_each_entry(iter,
|
||||
&dst_server->nfs_client->pending_cb_stateids,
|
||||
copies) {
|
||||
if (memcmp(&res->write_res.stateid, &tmp_copy->stateid,
|
||||
if (memcmp(&res->write_res.stateid, &iter->stateid,
|
||||
NFS4_STATEID_SIZE))
|
||||
continue;
|
||||
found_pending = true;
|
||||
list_del(&tmp_copy->copies);
|
||||
tmp_copy = iter;
|
||||
list_del(&iter->copies);
|
||||
break;
|
||||
}
|
||||
if (found_pending) {
|
||||
if (tmp_copy) {
|
||||
spin_unlock(&dst_server->nfs_client->cl_lock);
|
||||
kfree(copy);
|
||||
copy = tmp_copy;
|
||||
@ -254,7 +253,7 @@ static int process_copy_commit(struct file *dst, loff_t pos_dst,
|
||||
struct nfs_commitres cres;
|
||||
int status = -ENOMEM;
|
||||
|
||||
cres.verf = kzalloc(sizeof(struct nfs_writeverf), GFP_NOFS);
|
||||
cres.verf = kzalloc(sizeof(struct nfs_writeverf), GFP_KERNEL);
|
||||
if (!cres.verf)
|
||||
goto out;
|
||||
|
||||
@ -357,7 +356,7 @@ static ssize_t _nfs42_proc_copy(struct file *src,
|
||||
res->commit_res.verf = NULL;
|
||||
if (args->sync) {
|
||||
res->commit_res.verf =
|
||||
kzalloc(sizeof(struct nfs_writeverf), GFP_NOFS);
|
||||
kzalloc(sizeof(struct nfs_writeverf), GFP_KERNEL);
|
||||
if (!res->commit_res.verf)
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -552,7 +551,7 @@ static int nfs42_do_offload_cancel_async(struct file *dst,
|
||||
if (!(dst_server->caps & NFS_CAP_OFFLOAD_CANCEL))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
data = kzalloc(sizeof(struct nfs42_offloadcancel_data), GFP_NOFS);
|
||||
data = kzalloc(sizeof(struct nfs42_offloadcancel_data), GFP_KERNEL);
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -591,8 +590,10 @@ static int _nfs42_proc_copy_notify(struct file *src, struct file *dst,
|
||||
|
||||
ctx = get_nfs_open_context(nfs_file_open_context(src));
|
||||
l_ctx = nfs_get_lock_context(ctx);
|
||||
if (IS_ERR(l_ctx))
|
||||
return PTR_ERR(l_ctx);
|
||||
if (IS_ERR(l_ctx)) {
|
||||
status = PTR_ERR(l_ctx);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = nfs4_set_rw_stateid(&args->cna_src_stateid, ctx, l_ctx,
|
||||
FMODE_READ);
|
||||
@ -600,7 +601,7 @@ static int _nfs42_proc_copy_notify(struct file *src, struct file *dst,
|
||||
if (status) {
|
||||
if (status == -EAGAIN)
|
||||
status = -NFS4ERR_BAD_STATEID;
|
||||
return status;
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = nfs4_call_sync(src_server->client, src_server, &msg,
|
||||
@ -609,6 +610,7 @@ static int _nfs42_proc_copy_notify(struct file *src, struct file *dst,
|
||||
if (status == -ENOTSUPP)
|
||||
src_server->caps &= ~NFS_CAP_COPY_NOTIFY;
|
||||
|
||||
out:
|
||||
put_nfs_open_context(nfs_file_open_context(src));
|
||||
return status;
|
||||
}
|
||||
@ -626,7 +628,7 @@ int nfs42_proc_copy_notify(struct file *src, struct file *dst,
|
||||
if (!(src_server->caps & NFS_CAP_COPY_NOTIFY))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
args = kzalloc(sizeof(struct nfs42_copy_notify_args), GFP_NOFS);
|
||||
args = kzalloc(sizeof(struct nfs42_copy_notify_args), GFP_KERNEL);
|
||||
if (args == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1014,7 +1016,7 @@ int nfs42_proc_layouterror(struct pnfs_layout_segment *lseg,
|
||||
return -EOPNOTSUPP;
|
||||
if (n > NFS42_LAYOUTERROR_MAX)
|
||||
return -EINVAL;
|
||||
data = nfs42_alloc_layouterror_data(lseg, GFP_NOFS);
|
||||
data = nfs42_alloc_layouterror_data(lseg, nfs_io_gfp_mask());
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < n; i++) {
|
||||
|
@ -199,7 +199,7 @@ nfs4_xattr_alloc_entry(const char *name, const void *value,
|
||||
flags = NFS4_XATTR_ENTRY_EXTVAL;
|
||||
}
|
||||
|
||||
buf = kmalloc(alloclen, GFP_KERNEL_ACCOUNT | GFP_NOFS);
|
||||
buf = kmalloc(alloclen, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
entry = (struct nfs4_xattr_entry *)buf;
|
||||
@ -213,7 +213,7 @@ nfs4_xattr_alloc_entry(const char *name, const void *value,
|
||||
|
||||
|
||||
if (flags & NFS4_XATTR_ENTRY_EXTVAL) {
|
||||
valp = kvmalloc(len, GFP_KERNEL_ACCOUNT | GFP_NOFS);
|
||||
valp = kvmalloc(len, GFP_KERNEL);
|
||||
if (valp == NULL) {
|
||||
kfree(buf);
|
||||
return NULL;
|
||||
@ -289,8 +289,7 @@ nfs4_xattr_alloc_cache(void)
|
||||
{
|
||||
struct nfs4_xattr_cache *cache;
|
||||
|
||||
cache = kmem_cache_alloc(nfs4_xattr_cache_cachep,
|
||||
GFP_KERNEL_ACCOUNT | GFP_NOFS);
|
||||
cache = kmem_cache_alloc(nfs4_xattr_cache_cachep, GFP_KERNEL);
|
||||
if (cache == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -42,6 +42,7 @@ enum nfs4_client_state {
|
||||
NFS4CLNT_LEASE_MOVED,
|
||||
NFS4CLNT_DELEGATION_EXPIRED,
|
||||
NFS4CLNT_RUN_MANAGER,
|
||||
NFS4CLNT_MANAGER_AVAILABLE,
|
||||
NFS4CLNT_RECALL_RUNNING,
|
||||
NFS4CLNT_RECALL_ANY_LAYOUT_READ,
|
||||
NFS4CLNT_RECALL_ANY_LAYOUT_RW,
|
||||
|
@ -165,7 +165,7 @@ retry:
|
||||
if (sync)
|
||||
return -EOPNOTSUPP;
|
||||
cn_resp = kzalloc(sizeof(struct nfs42_copy_notify_res),
|
||||
GFP_NOFS);
|
||||
GFP_KERNEL);
|
||||
if (unlikely(cn_resp == NULL))
|
||||
return -ENOMEM;
|
||||
|
||||
@ -180,8 +180,8 @@ retry:
|
||||
ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count,
|
||||
nss, cnrs, sync);
|
||||
out:
|
||||
if (!nfs42_files_from_same_server(file_in, file_out))
|
||||
kfree(cn_resp);
|
||||
kfree(cn_resp);
|
||||
|
||||
if (ret == -EAGAIN)
|
||||
goto retry;
|
||||
return ret;
|
||||
@ -339,7 +339,7 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
|
||||
|
||||
res = ERR_PTR(-ENOMEM);
|
||||
len = strlen(SSC_READ_NAME_BODY) + 16;
|
||||
read_name = kzalloc(len, GFP_NOFS);
|
||||
read_name = kzalloc(len, GFP_KERNEL);
|
||||
if (read_name == NULL)
|
||||
goto out;
|
||||
snprintf(read_name, len, SSC_READ_NAME_BODY, read_name_gen++);
|
||||
|
@ -1392,13 +1392,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
|
||||
case NFS4_OPEN_CLAIM_FH:
|
||||
p->o_arg.access = NFS4_ACCESS_READ | NFS4_ACCESS_MODIFY |
|
||||
NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE |
|
||||
NFS4_ACCESS_EXECUTE;
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
if (!(server->caps & NFS_CAP_XATTR))
|
||||
break;
|
||||
p->o_arg.access |= NFS4_ACCESS_XAREAD | NFS4_ACCESS_XAWRITE |
|
||||
NFS4_ACCESS_XALIST;
|
||||
#endif
|
||||
NFS4_ACCESS_EXECUTE |
|
||||
nfs_access_xattr_mask(server);
|
||||
}
|
||||
p->o_arg.clientid = server->nfs_client->cl_clientid;
|
||||
p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
|
||||
@ -3050,6 +3045,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
|
||||
set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
|
||||
if (opendata->o_res.rflags & NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK)
|
||||
set_bit(NFS_STATE_MAY_NOTIFY_LOCK, &state->flags);
|
||||
if (opendata->o_res.rflags & NFS4_OPEN_RESULT_PRESERVE_UNLINKED)
|
||||
set_bit(NFS_INO_PRESERVE_UNLINKED, &NFS_I(state->inode)->flags);
|
||||
|
||||
dentry = opendata->dentry;
|
||||
if (d_really_is_negative(dentry)) {
|
||||
@ -5904,7 +5901,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
|
||||
buflen = server->rsize;
|
||||
|
||||
npages = DIV_ROUND_UP(buflen, PAGE_SIZE) + 1;
|
||||
pages = kmalloc_array(npages, sizeof(struct page *), GFP_NOFS);
|
||||
pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
|
||||
if (!pages)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -6609,7 +6606,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
|
||||
};
|
||||
int status = 0;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_NOFS);
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -6797,7 +6794,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
|
||||
struct nfs4_state *state = lsp->ls_state;
|
||||
struct inode *inode = state->inode;
|
||||
|
||||
p = kzalloc(sizeof(*p), GFP_NOFS);
|
||||
p = kzalloc(sizeof(*p), GFP_KERNEL);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
p->arg.fh = NFS_FH(inode);
|
||||
@ -7202,8 +7199,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
|
||||
task_setup_data.flags |= RPC_TASK_MOVEABLE;
|
||||
|
||||
data = nfs4_alloc_lockdata(fl, nfs_file_open_context(fl->fl_file),
|
||||
fl->fl_u.nfs4_fl.owner,
|
||||
recovery_type == NFS_LOCK_NEW ? GFP_KERNEL : GFP_NOFS);
|
||||
fl->fl_u.nfs4_fl.owner, GFP_KERNEL);
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
if (IS_SETLKW(cmd))
|
||||
@ -7626,7 +7622,7 @@ nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
|
||||
if (server->nfs_client->cl_mvops->minor_version != 0)
|
||||
return;
|
||||
|
||||
data = kmalloc(sizeof(*data), GFP_NOFS);
|
||||
data = kmalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return;
|
||||
data->lsp = lsp;
|
||||
@ -8012,6 +8008,18 @@ static int _nfs41_proc_get_locations(struct nfs_server *server,
|
||||
.rpc_resp = &res,
|
||||
.rpc_cred = cred,
|
||||
};
|
||||
struct nfs4_call_sync_data data = {
|
||||
.seq_server = server,
|
||||
.seq_args = &args.seq_args,
|
||||
.seq_res = &res.seq_res,
|
||||
};
|
||||
struct rpc_task_setup task_setup_data = {
|
||||
.rpc_client = clnt,
|
||||
.rpc_message = &msg,
|
||||
.callback_ops = server->nfs_client->cl_mvops->call_sync_ops,
|
||||
.callback_data = &data,
|
||||
.flags = RPC_TASK_NO_ROUND_ROBIN,
|
||||
};
|
||||
int status;
|
||||
|
||||
nfs_fattr_init(&locations->fattr);
|
||||
@ -8019,8 +8027,7 @@ static int _nfs41_proc_get_locations(struct nfs_server *server,
|
||||
locations->nlocations = 0;
|
||||
|
||||
nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 1);
|
||||
status = nfs4_call_sync_sequence(clnt, server, &msg,
|
||||
&args.seq_args, &res.seq_res);
|
||||
status = nfs4_call_sync_custom(&task_setup_data);
|
||||
if (status == NFS4_OK &&
|
||||
res.seq_res.sr_status_flags & SEQ4_STATUS_LEASE_MOVED)
|
||||
status = -NFS4ERR_LEASE_MOVED;
|
||||
@ -8333,6 +8340,7 @@ nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata)
|
||||
case -NFS4ERR_DEADSESSION:
|
||||
nfs4_schedule_session_recovery(clp->cl_session,
|
||||
task->tk_status);
|
||||
return;
|
||||
}
|
||||
if (args->dir == NFS4_CDFC4_FORE_OR_BOTH &&
|
||||
res->dir != NFS4_CDFS4_BOTH) {
|
||||
@ -9291,7 +9299,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
|
||||
goto out_err;
|
||||
|
||||
ret = ERR_PTR(-ENOMEM);
|
||||
calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
|
||||
calldata = kzalloc(sizeof(*calldata), GFP_KERNEL);
|
||||
if (calldata == NULL)
|
||||
goto out_put_clp;
|
||||
nfs4_init_sequence(&calldata->args, &calldata->res, 0, is_privileged);
|
||||
@ -10222,7 +10230,7 @@ static int nfs41_free_stateid(struct nfs_server *server,
|
||||
&task_setup.rpc_client, &msg);
|
||||
|
||||
dprintk("NFS call free_stateid %p\n", stateid);
|
||||
data = kmalloc(sizeof(*data), GFP_NOFS);
|
||||
data = kmalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
data->server = server;
|
||||
@ -10461,6 +10469,24 @@ static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
|
||||
return error + error2 + error3;
|
||||
}
|
||||
|
||||
static void nfs4_enable_swap(struct inode *inode)
|
||||
{
|
||||
/* The state manager thread must always be running.
|
||||
* It will notice the client is a swapper, and stay put.
|
||||
*/
|
||||
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
|
||||
|
||||
nfs4_schedule_state_manager(clp);
|
||||
}
|
||||
|
||||
static void nfs4_disable_swap(struct inode *inode)
|
||||
{
|
||||
/* The state manager thread will now exit once it is
|
||||
* woken.
|
||||
*/
|
||||
wake_up_var(&NFS_SERVER(inode)->nfs_client->cl_state);
|
||||
}
|
||||
|
||||
static const struct inode_operations nfs4_dir_inode_operations = {
|
||||
.create = nfs_create,
|
||||
.lookup = nfs_lookup,
|
||||
@ -10538,6 +10564,8 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
|
||||
.create_server = nfs4_create_server,
|
||||
.clone_server = nfs_clone_server,
|
||||
.discover_trunking = nfs4_discover_trunking,
|
||||
.enable_swap = nfs4_enable_swap,
|
||||
.disable_swap = nfs4_disable_swap,
|
||||
};
|
||||
|
||||
static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/sched/mm.h>
|
||||
|
||||
#include <linux/sunrpc/clnt.h>
|
||||
|
||||
@ -666,7 +667,7 @@ nfs4_alloc_open_state(void)
|
||||
{
|
||||
struct nfs4_state *state;
|
||||
|
||||
state = kzalloc(sizeof(*state), GFP_NOFS);
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL_ACCOUNT);
|
||||
if (!state)
|
||||
return NULL;
|
||||
refcount_set(&state->count, 1);
|
||||
@ -820,7 +821,7 @@ static void __nfs4_close(struct nfs4_state *state,
|
||||
|
||||
void nfs4_close_state(struct nfs4_state *state, fmode_t fmode)
|
||||
{
|
||||
__nfs4_close(state, fmode, GFP_NOFS, 0);
|
||||
__nfs4_close(state, fmode, GFP_KERNEL, 0);
|
||||
}
|
||||
|
||||
void nfs4_close_sync(struct nfs4_state *state, fmode_t fmode)
|
||||
@ -869,14 +870,15 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
|
||||
struct nfs4_lock_state *lsp;
|
||||
struct nfs_server *server = state->owner->so_server;
|
||||
|
||||
lsp = kzalloc(sizeof(*lsp), GFP_NOFS);
|
||||
lsp = kzalloc(sizeof(*lsp), GFP_KERNEL_ACCOUNT);
|
||||
if (lsp == NULL)
|
||||
return NULL;
|
||||
nfs4_init_seqid_counter(&lsp->ls_seqid);
|
||||
refcount_set(&lsp->ls_count, 1);
|
||||
lsp->ls_state = state;
|
||||
lsp->ls_owner = fl_owner;
|
||||
lsp->ls_seqid.owner_id = ida_simple_get(&server->lockowner_id, 0, 0, GFP_NOFS);
|
||||
lsp->ls_seqid.owner_id = ida_simple_get(&server->lockowner_id,
|
||||
0, 0, GFP_KERNEL_ACCOUNT);
|
||||
if (lsp->ls_seqid.owner_id < 0)
|
||||
goto out_free;
|
||||
INIT_LIST_HEAD(&lsp->ls_locks);
|
||||
@ -1205,10 +1207,17 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
|
||||
{
|
||||
struct task_struct *task;
|
||||
char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1];
|
||||
struct rpc_clnt *cl = clp->cl_rpcclient;
|
||||
|
||||
while (cl != cl->cl_parent)
|
||||
cl = cl->cl_parent;
|
||||
|
||||
set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
|
||||
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
|
||||
if (test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) != 0) {
|
||||
wake_up_var(&clp->cl_state);
|
||||
return;
|
||||
}
|
||||
set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
|
||||
__module_get(THIS_MODULE);
|
||||
refcount_inc(&clp->cl_count);
|
||||
|
||||
@ -1224,6 +1233,7 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
|
||||
printk(KERN_ERR "%s: kthread_run: %ld\n",
|
||||
__func__, PTR_ERR(task));
|
||||
nfs4_clear_state_manager_bit(clp);
|
||||
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
|
||||
nfs_put_client(clp);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
@ -2560,9 +2570,17 @@ static void nfs4_layoutreturn_any_run(struct nfs_client *clp)
|
||||
|
||||
static void nfs4_state_manager(struct nfs_client *clp)
|
||||
{
|
||||
unsigned int memflags;
|
||||
int status = 0;
|
||||
const char *section = "", *section_sep = "";
|
||||
|
||||
/*
|
||||
* State recovery can deadlock if the direct reclaim code tries
|
||||
* start NFS writeback. So ensure memory allocations are all
|
||||
* GFP_NOFS.
|
||||
*/
|
||||
memflags = memalloc_nofs_save();
|
||||
|
||||
/* Ensure exclusive access to NFSv4 state */
|
||||
do {
|
||||
trace_nfs4_state_mgr(clp);
|
||||
@ -2657,6 +2675,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
||||
clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
|
||||
}
|
||||
|
||||
memalloc_nofs_restore(memflags);
|
||||
nfs4_end_drain_session(clp);
|
||||
nfs4_clear_state_manager_bit(clp);
|
||||
|
||||
@ -2669,11 +2688,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
||||
clear_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state);
|
||||
}
|
||||
|
||||
/* Did we race with an attempt to give us more work? */
|
||||
if (!test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state))
|
||||
return;
|
||||
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
|
||||
return;
|
||||
return;
|
||||
|
||||
} while (refcount_read(&clp->cl_count) > 1 && !signalled());
|
||||
goto out_drain;
|
||||
|
||||
@ -2686,6 +2702,7 @@ out_error:
|
||||
clp->cl_hostname, -status);
|
||||
ssleep(1);
|
||||
out_drain:
|
||||
memalloc_nofs_restore(memflags);
|
||||
nfs4_end_drain_session(clp);
|
||||
nfs4_clear_state_manager_bit(clp);
|
||||
}
|
||||
@ -2693,9 +2710,31 @@ out_drain:
|
||||
static int nfs4_run_state_manager(void *ptr)
|
||||
{
|
||||
struct nfs_client *clp = ptr;
|
||||
struct rpc_clnt *cl = clp->cl_rpcclient;
|
||||
|
||||
while (cl != cl->cl_parent)
|
||||
cl = cl->cl_parent;
|
||||
|
||||
allow_signal(SIGKILL);
|
||||
again:
|
||||
set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
|
||||
nfs4_state_manager(clp);
|
||||
if (atomic_read(&cl->cl_swapper)) {
|
||||
wait_var_event_interruptible(&clp->cl_state,
|
||||
test_bit(NFS4CLNT_RUN_MANAGER,
|
||||
&clp->cl_state));
|
||||
if (atomic_read(&cl->cl_swapper) &&
|
||||
test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state))
|
||||
goto again;
|
||||
/* Either no longer a swapper, or were signalled */
|
||||
}
|
||||
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
|
||||
|
||||
if (refcount_read(&clp->cl_count) > 1 && !signalled() &&
|
||||
test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) &&
|
||||
!test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state))
|
||||
goto again;
|
||||
|
||||
nfs_put_client(clp);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1605,7 +1605,8 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
|
||||
FATTR4_WORD0_RDATTR_ERROR,
|
||||
FATTR4_WORD1_MOUNTED_ON_FILEID,
|
||||
};
|
||||
uint32_t dircount = readdir->count >> 1;
|
||||
uint32_t dircount = readdir->count;
|
||||
uint32_t maxcount = readdir->count;
|
||||
__be32 *p, verf[2];
|
||||
uint32_t attrlen = 0;
|
||||
unsigned int i;
|
||||
@ -1618,7 +1619,6 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
|
||||
FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
|
||||
FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
|
||||
attrs[2] |= FATTR4_WORD2_SECURITY_LABEL;
|
||||
dircount >>= 1;
|
||||
}
|
||||
/* Use mounted_on_fileid only if the server supports it */
|
||||
if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID))
|
||||
@ -1634,7 +1634,7 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
|
||||
encode_nfs4_verifier(xdr, &readdir->verifier);
|
||||
p = reserve_space(xdr, 12 + (attrlen << 2));
|
||||
*p++ = cpu_to_be32(dircount);
|
||||
*p++ = cpu_to_be32(readdir->count);
|
||||
*p++ = cpu_to_be32(maxcount);
|
||||
*p++ = cpu_to_be32(attrlen);
|
||||
for (i = 0; i < attrlen; i++)
|
||||
*p++ = cpu_to_be32(attrs[i]);
|
||||
@ -7508,7 +7508,6 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
|
||||
if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE)
|
||||
entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
|
||||
|
||||
entry->prev_cookie = entry->cookie;
|
||||
entry->cookie = new_cookie;
|
||||
|
||||
return 0;
|
||||
|
@ -21,7 +21,6 @@
|
||||
{ NFS_INO_INVALID_ATIME, "INVALID_ATIME" }, \
|
||||
{ NFS_INO_INVALID_ACCESS, "INVALID_ACCESS" }, \
|
||||
{ NFS_INO_INVALID_ACL, "INVALID_ACL" }, \
|
||||
{ NFS_INO_REVAL_PAGECACHE, "REVAL_PAGECACHE" }, \
|
||||
{ NFS_INO_REVAL_FORCED, "REVAL_FORCED" }, \
|
||||
{ NFS_INO_INVALID_LABEL, "INVALID_LABEL" }, \
|
||||
{ NFS_INO_INVALID_CHANGE, "INVALID_CHANGE" }, \
|
||||
@ -37,7 +36,6 @@
|
||||
|
||||
#define nfs_show_nfsi_flags(v) \
|
||||
__print_flags(v, "|", \
|
||||
{ BIT(NFS_INO_ADVISE_RDPLUS), "ADVISE_RDPLUS" }, \
|
||||
{ BIT(NFS_INO_STALE), "STALE" }, \
|
||||
{ BIT(NFS_INO_ACL_LRU_SET), "ACL_LRU_SET" }, \
|
||||
{ BIT(NFS_INO_INVALIDATING), "INVALIDATING" }, \
|
||||
@ -162,6 +160,9 @@ DEFINE_NFS_INODE_EVENT(nfs_fsync_enter);
|
||||
DEFINE_NFS_INODE_EVENT_DONE(nfs_fsync_exit);
|
||||
DEFINE_NFS_INODE_EVENT(nfs_access_enter);
|
||||
DEFINE_NFS_INODE_EVENT_DONE(nfs_set_cache_invalid);
|
||||
DEFINE_NFS_INODE_EVENT(nfs_readdir_force_readdirplus);
|
||||
DEFINE_NFS_INODE_EVENT_DONE(nfs_readdir_cache_fill_done);
|
||||
DEFINE_NFS_INODE_EVENT_DONE(nfs_readdir_uncached_done);
|
||||
|
||||
TRACE_EVENT(nfs_access_exit,
|
||||
TP_PROTO(
|
||||
@ -273,6 +274,122 @@ DEFINE_NFS_UPDATE_SIZE_EVENT(wcc);
|
||||
DEFINE_NFS_UPDATE_SIZE_EVENT(update);
|
||||
DEFINE_NFS_UPDATE_SIZE_EVENT(grow);
|
||||
|
||||
DECLARE_EVENT_CLASS(nfs_inode_range_event,
|
||||
TP_PROTO(
|
||||
const struct inode *inode,
|
||||
loff_t range_start,
|
||||
loff_t range_end
|
||||
),
|
||||
|
||||
TP_ARGS(inode, range_start, range_end),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(u32, fhandle)
|
||||
__field(u64, fileid)
|
||||
__field(u64, version)
|
||||
__field(loff_t, range_start)
|
||||
__field(loff_t, range_end)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
const struct nfs_inode *nfsi = NFS_I(inode);
|
||||
|
||||
__entry->dev = inode->i_sb->s_dev;
|
||||
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
|
||||
__entry->fileid = nfsi->fileid;
|
||||
__entry->version = inode_peek_iversion_raw(inode);
|
||||
__entry->range_start = range_start;
|
||||
__entry->range_end = range_end;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"fileid=%02x:%02x:%llu fhandle=0x%08x version=%llu "
|
||||
"range=[%lld, %lld]",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
(unsigned long long)__entry->fileid,
|
||||
__entry->fhandle, __entry->version,
|
||||
__entry->range_start, __entry->range_end
|
||||
)
|
||||
);
|
||||
|
||||
#define DEFINE_NFS_INODE_RANGE_EVENT(name) \
|
||||
DEFINE_EVENT(nfs_inode_range_event, name, \
|
||||
TP_PROTO( \
|
||||
const struct inode *inode, \
|
||||
loff_t range_start, \
|
||||
loff_t range_end \
|
||||
), \
|
||||
TP_ARGS(inode, range_start, range_end))
|
||||
|
||||
DEFINE_NFS_INODE_RANGE_EVENT(nfs_readdir_invalidate_cache_range);
|
||||
|
||||
DECLARE_EVENT_CLASS(nfs_readdir_event,
|
||||
TP_PROTO(
|
||||
const struct file *file,
|
||||
const __be32 *verifier,
|
||||
u64 cookie,
|
||||
pgoff_t page_index,
|
||||
unsigned int dtsize
|
||||
),
|
||||
|
||||
TP_ARGS(file, verifier, cookie, page_index, dtsize),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(u32, fhandle)
|
||||
__field(u64, fileid)
|
||||
__field(u64, version)
|
||||
__array(char, verifier, NFS4_VERIFIER_SIZE)
|
||||
__field(u64, cookie)
|
||||
__field(pgoff_t, index)
|
||||
__field(unsigned int, dtsize)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
const struct inode *dir = file_inode(file);
|
||||
const struct nfs_inode *nfsi = NFS_I(dir);
|
||||
|
||||
__entry->dev = dir->i_sb->s_dev;
|
||||
__entry->fileid = nfsi->fileid;
|
||||
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
|
||||
__entry->version = inode_peek_iversion_raw(dir);
|
||||
if (cookie != 0)
|
||||
memcpy(__entry->verifier, verifier,
|
||||
NFS4_VERIFIER_SIZE);
|
||||
else
|
||||
memset(__entry->verifier, 0,
|
||||
NFS4_VERIFIER_SIZE);
|
||||
__entry->cookie = cookie;
|
||||
__entry->index = page_index;
|
||||
__entry->dtsize = dtsize;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"fileid=%02x:%02x:%llu fhandle=0x%08x version=%llu "
|
||||
"cookie=%s:0x%llx cache_index=%lu dtsize=%u",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
(unsigned long long)__entry->fileid, __entry->fhandle,
|
||||
__entry->version, show_nfs4_verifier(__entry->verifier),
|
||||
(unsigned long long)__entry->cookie, __entry->index,
|
||||
__entry->dtsize
|
||||
)
|
||||
);
|
||||
|
||||
#define DEFINE_NFS_READDIR_EVENT(name) \
|
||||
DEFINE_EVENT(nfs_readdir_event, name, \
|
||||
TP_PROTO( \
|
||||
const struct file *file, \
|
||||
const __be32 *verifier, \
|
||||
u64 cookie, \
|
||||
pgoff_t page_index, \
|
||||
unsigned int dtsize \
|
||||
), \
|
||||
TP_ARGS(file, verifier, cookie, page_index, dtsize))
|
||||
|
||||
DEFINE_NFS_READDIR_EVENT(nfs_readdir_cache_fill);
|
||||
DEFINE_NFS_READDIR_EVENT(nfs_readdir_uncached);
|
||||
|
||||
DECLARE_EVENT_CLASS(nfs_lookup_event,
|
||||
TP_PROTO(
|
||||
const struct inode *dir,
|
||||
@ -366,6 +483,9 @@ DEFINE_NFS_LOOKUP_EVENT(nfs_lookup_enter);
|
||||
DEFINE_NFS_LOOKUP_EVENT_DONE(nfs_lookup_exit);
|
||||
DEFINE_NFS_LOOKUP_EVENT(nfs_lookup_revalidate_enter);
|
||||
DEFINE_NFS_LOOKUP_EVENT_DONE(nfs_lookup_revalidate_exit);
|
||||
DEFINE_NFS_LOOKUP_EVENT(nfs_readdir_lookup);
|
||||
DEFINE_NFS_LOOKUP_EVENT(nfs_readdir_lookup_revalidate_failed);
|
||||
DEFINE_NFS_LOOKUP_EVENT_DONE(nfs_readdir_lookup_revalidate);
|
||||
|
||||
TRACE_EVENT(nfs_atomic_open_enter,
|
||||
TP_PROTO(
|
||||
@ -889,11 +1009,11 @@ TRACE_EVENT(nfs_aop_readpage_done,
|
||||
TRACE_EVENT(nfs_aop_readahead,
|
||||
TP_PROTO(
|
||||
const struct inode *inode,
|
||||
struct page *page,
|
||||
loff_t pos,
|
||||
unsigned int nr_pages
|
||||
),
|
||||
|
||||
TP_ARGS(inode, page, nr_pages),
|
||||
TP_ARGS(inode, pos, nr_pages),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
@ -911,7 +1031,7 @@ TRACE_EVENT(nfs_aop_readahead,
|
||||
__entry->fileid = nfsi->fileid;
|
||||
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
|
||||
__entry->version = inode_peek_iversion_raw(inode);
|
||||
__entry->offset = page_index(page) << PAGE_SHIFT;
|
||||
__entry->offset = pos;
|
||||
__entry->nr_pages = nr_pages;
|
||||
),
|
||||
|
||||
@ -1095,6 +1215,97 @@ TRACE_EVENT(nfs_readpage_short,
|
||||
)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(nfs_fscache_page_event,
|
||||
TP_PROTO(
|
||||
const struct inode *inode,
|
||||
struct page *page
|
||||
),
|
||||
|
||||
TP_ARGS(inode, page),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(u32, fhandle)
|
||||
__field(u64, fileid)
|
||||
__field(loff_t, offset)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
const struct nfs_inode *nfsi = NFS_I(inode);
|
||||
const struct nfs_fh *fh = &nfsi->fh;
|
||||
|
||||
__entry->offset = page_index(page) << PAGE_SHIFT;
|
||||
__entry->dev = inode->i_sb->s_dev;
|
||||
__entry->fileid = nfsi->fileid;
|
||||
__entry->fhandle = nfs_fhandle_hash(fh);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"fileid=%02x:%02x:%llu fhandle=0x%08x "
|
||||
"offset=%lld",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
(unsigned long long)__entry->fileid,
|
||||
__entry->fhandle,
|
||||
(long long)__entry->offset
|
||||
)
|
||||
);
|
||||
DECLARE_EVENT_CLASS(nfs_fscache_page_event_done,
|
||||
TP_PROTO(
|
||||
const struct inode *inode,
|
||||
struct page *page,
|
||||
int error
|
||||
),
|
||||
|
||||
TP_ARGS(inode, page, error),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(int, error)
|
||||
__field(dev_t, dev)
|
||||
__field(u32, fhandle)
|
||||
__field(u64, fileid)
|
||||
__field(loff_t, offset)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
const struct nfs_inode *nfsi = NFS_I(inode);
|
||||
const struct nfs_fh *fh = &nfsi->fh;
|
||||
|
||||
__entry->offset = page_index(page) << PAGE_SHIFT;
|
||||
__entry->dev = inode->i_sb->s_dev;
|
||||
__entry->fileid = nfsi->fileid;
|
||||
__entry->fhandle = nfs_fhandle_hash(fh);
|
||||
__entry->error = error;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"fileid=%02x:%02x:%llu fhandle=0x%08x "
|
||||
"offset=%lld error=%d",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
(unsigned long long)__entry->fileid,
|
||||
__entry->fhandle,
|
||||
(long long)__entry->offset, __entry->error
|
||||
)
|
||||
);
|
||||
#define DEFINE_NFS_FSCACHE_PAGE_EVENT(name) \
|
||||
DEFINE_EVENT(nfs_fscache_page_event, name, \
|
||||
TP_PROTO( \
|
||||
const struct inode *inode, \
|
||||
struct page *page \
|
||||
), \
|
||||
TP_ARGS(inode, page))
|
||||
#define DEFINE_NFS_FSCACHE_PAGE_EVENT_DONE(name) \
|
||||
DEFINE_EVENT(nfs_fscache_page_event_done, name, \
|
||||
TP_PROTO( \
|
||||
const struct inode *inode, \
|
||||
struct page *page, \
|
||||
int error \
|
||||
), \
|
||||
TP_ARGS(inode, page, error))
|
||||
DEFINE_NFS_FSCACHE_PAGE_EVENT(nfs_fscache_read_page);
|
||||
DEFINE_NFS_FSCACHE_PAGE_EVENT_DONE(nfs_fscache_read_page_exit);
|
||||
DEFINE_NFS_FSCACHE_PAGE_EVENT(nfs_fscache_write_page);
|
||||
DEFINE_NFS_FSCACHE_PAGE_EVENT_DONE(nfs_fscache_write_page_exit);
|
||||
|
||||
TRACE_EVENT(nfs_pgio_error,
|
||||
TP_PROTO(
|
||||
const struct nfs_pgio_header *hdr,
|
||||
|
@ -90,10 +90,10 @@ void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos)
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct nfs_page *
|
||||
nfs_page_alloc(void)
|
||||
static inline struct nfs_page *nfs_page_alloc(void)
|
||||
{
|
||||
struct nfs_page *p = kmem_cache_zalloc(nfs_page_cachep, GFP_KERNEL);
|
||||
struct nfs_page *p =
|
||||
kmem_cache_zalloc(nfs_page_cachep, nfs_io_gfp_mask());
|
||||
if (p)
|
||||
INIT_LIST_HEAD(&p->wb_list);
|
||||
return p;
|
||||
@ -892,7 +892,7 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
|
||||
struct nfs_commit_info cinfo;
|
||||
struct nfs_page_array *pg_array = &hdr->page_array;
|
||||
unsigned int pagecount, pageused;
|
||||
gfp_t gfp_flags = GFP_KERNEL;
|
||||
gfp_t gfp_flags = nfs_io_gfp_mask();
|
||||
|
||||
pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count);
|
||||
pg_array->npages = pagecount;
|
||||
@ -979,7 +979,7 @@ nfs_pageio_alloc_mirrors(struct nfs_pageio_descriptor *desc,
|
||||
desc->pg_mirrors_dynamic = NULL;
|
||||
if (mirror_count == 1)
|
||||
return desc->pg_mirrors_static;
|
||||
ret = kmalloc_array(mirror_count, sizeof(*ret), GFP_KERNEL);
|
||||
ret = kmalloc_array(mirror_count, sizeof(*ret), nfs_io_gfp_mask());
|
||||
if (ret != NULL) {
|
||||
for (i = 0; i < mirror_count; i++)
|
||||
nfs_pageio_mirror_init(&ret[i], desc->pg_bsize);
|
||||
@ -1218,6 +1218,7 @@ static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc)
|
||||
|
||||
do {
|
||||
list_splice_init(&mirror->pg_list, &head);
|
||||
mirror->pg_recoalesce = 0;
|
||||
|
||||
while (!list_empty(&head)) {
|
||||
struct nfs_page *req;
|
||||
|
@ -92,6 +92,17 @@ find_pnfs_driver(u32 id)
|
||||
return local;
|
||||
}
|
||||
|
||||
const struct pnfs_layoutdriver_type *pnfs_find_layoutdriver(u32 id)
|
||||
{
|
||||
return find_pnfs_driver(id);
|
||||
}
|
||||
|
||||
void pnfs_put_layoutdriver(const struct pnfs_layoutdriver_type *ld)
|
||||
{
|
||||
if (ld)
|
||||
module_put(ld->owner);
|
||||
}
|
||||
|
||||
void
|
||||
unset_pnfs_layoutdriver(struct nfs_server *nfss)
|
||||
{
|
||||
@ -1233,7 +1244,7 @@ pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo,
|
||||
int status = 0;
|
||||
|
||||
*pcred = NULL;
|
||||
lrp = kzalloc(sizeof(*lrp), GFP_NOFS);
|
||||
lrp = kzalloc(sizeof(*lrp), nfs_io_gfp_mask());
|
||||
if (unlikely(lrp == NULL)) {
|
||||
status = -ENOMEM;
|
||||
spin_lock(&ino->i_lock);
|
||||
@ -2206,7 +2217,7 @@ _pnfs_grab_empty_layout(struct inode *ino, struct nfs_open_context *ctx)
|
||||
struct pnfs_layout_hdr *lo;
|
||||
|
||||
spin_lock(&ino->i_lock);
|
||||
lo = pnfs_find_alloc_layout(ino, ctx, GFP_KERNEL);
|
||||
lo = pnfs_find_alloc_layout(ino, ctx, nfs_io_gfp_mask());
|
||||
if (!lo)
|
||||
goto out_unlock;
|
||||
if (!test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags))
|
||||
@ -2249,8 +2260,8 @@ static void _lgopen_prepare_attached(struct nfs4_opendata *data,
|
||||
lo = _pnfs_grab_empty_layout(ino, ctx);
|
||||
if (!lo)
|
||||
return;
|
||||
lgp = pnfs_alloc_init_layoutget_args(ino, ctx, ¤t_stateid,
|
||||
&rng, GFP_KERNEL);
|
||||
lgp = pnfs_alloc_init_layoutget_args(ino, ctx, ¤t_stateid, &rng,
|
||||
nfs_io_gfp_mask());
|
||||
if (!lgp) {
|
||||
pnfs_clear_first_layoutget(lo);
|
||||
nfs_layoutget_end(lo);
|
||||
@ -2275,8 +2286,8 @@ static void _lgopen_prepare_floating(struct nfs4_opendata *data,
|
||||
};
|
||||
struct nfs4_layoutget *lgp;
|
||||
|
||||
lgp = pnfs_alloc_init_layoutget_args(ino, ctx, ¤t_stateid,
|
||||
&rng, GFP_KERNEL);
|
||||
lgp = pnfs_alloc_init_layoutget_args(ino, ctx, ¤t_stateid, &rng,
|
||||
nfs_io_gfp_mask());
|
||||
if (!lgp)
|
||||
return;
|
||||
data->lgp = lgp;
|
||||
@ -2691,13 +2702,11 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r
|
||||
else
|
||||
rd_size = nfs_dreq_bytes_left(pgio->pg_dreq);
|
||||
|
||||
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
|
||||
nfs_req_openctx(req),
|
||||
req_offset(req),
|
||||
rd_size,
|
||||
IOMODE_READ,
|
||||
false,
|
||||
GFP_KERNEL);
|
||||
pgio->pg_lseg =
|
||||
pnfs_update_layout(pgio->pg_inode, nfs_req_openctx(req),
|
||||
req_offset(req), rd_size,
|
||||
IOMODE_READ, false,
|
||||
nfs_io_gfp_mask());
|
||||
if (IS_ERR(pgio->pg_lseg)) {
|
||||
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
|
||||
pgio->pg_lseg = NULL;
|
||||
@ -2718,13 +2727,10 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
|
||||
pnfs_generic_pg_check_layout(pgio);
|
||||
pnfs_generic_pg_check_range(pgio, req);
|
||||
if (pgio->pg_lseg == NULL) {
|
||||
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
|
||||
nfs_req_openctx(req),
|
||||
req_offset(req),
|
||||
wb_size,
|
||||
IOMODE_RW,
|
||||
false,
|
||||
GFP_KERNEL);
|
||||
pgio->pg_lseg =
|
||||
pnfs_update_layout(pgio->pg_inode, nfs_req_openctx(req),
|
||||
req_offset(req), wb_size, IOMODE_RW,
|
||||
false, nfs_io_gfp_mask());
|
||||
if (IS_ERR(pgio->pg_lseg)) {
|
||||
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
|
||||
pgio->pg_lseg = NULL;
|
||||
@ -3183,7 +3189,7 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
|
||||
|
||||
status = -ENOMEM;
|
||||
/* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */
|
||||
data = kzalloc(sizeof(*data), GFP_NOFS);
|
||||
data = kzalloc(sizeof(*data), nfs_io_gfp_mask());
|
||||
if (!data)
|
||||
goto clear_layoutcommitting;
|
||||
|
||||
@ -3250,7 +3256,7 @@ struct nfs4_threshold *pnfs_mdsthreshold_alloc(void)
|
||||
{
|
||||
struct nfs4_threshold *thp;
|
||||
|
||||
thp = kzalloc(sizeof(*thp), GFP_NOFS);
|
||||
thp = kzalloc(sizeof(*thp), nfs_io_gfp_mask());
|
||||
if (!thp) {
|
||||
dprintk("%s mdsthreshold allocation failed\n", __func__);
|
||||
return NULL;
|
||||
|
@ -234,6 +234,8 @@ struct pnfs_devicelist {
|
||||
|
||||
extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
|
||||
extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
|
||||
extern const struct pnfs_layoutdriver_type *pnfs_find_layoutdriver(u32 id);
|
||||
extern void pnfs_put_layoutdriver(const struct pnfs_layoutdriver_type *ld);
|
||||
|
||||
/* nfs4proc.c */
|
||||
extern size_t max_response_pages(struct nfs_server *server);
|
||||
|
@ -419,7 +419,7 @@ static struct nfs_commit_data *
|
||||
pnfs_bucket_fetch_commitdata(struct pnfs_commit_bucket *bucket,
|
||||
struct nfs_commit_info *cinfo)
|
||||
{
|
||||
struct nfs_commit_data *data = nfs_commitdata_alloc(false);
|
||||
struct nfs_commit_data *data = nfs_commitdata_alloc();
|
||||
|
||||
if (!data)
|
||||
return NULL;
|
||||
@ -515,7 +515,11 @@ pnfs_generic_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
|
||||
unsigned int nreq = 0;
|
||||
|
||||
if (!list_empty(mds_pages)) {
|
||||
data = nfs_commitdata_alloc(true);
|
||||
data = nfs_commitdata_alloc();
|
||||
if (!data) {
|
||||
nfs_retry_commit(mds_pages, NULL, cinfo, -1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
data->ds_commit_index = -1;
|
||||
list_splice_init(mds_pages, &data->pages);
|
||||
list_add_tail(&data->list, &list);
|
||||
|
@ -92,6 +92,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||
info->maxfilesize = 0x7FFFFFFF;
|
||||
info->lease_time = 0;
|
||||
info->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED;
|
||||
info->xattr_support = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ static void nfs_readpage_release(struct nfs_page *req, int error)
|
||||
struct address_space *mapping = page_file_mapping(page);
|
||||
|
||||
if (PageUptodate(page))
|
||||
nfs_readpage_to_fscache(inode, page);
|
||||
nfs_fscache_write_page(inode, page);
|
||||
else if (!PageError(page) && !PagePrivate(page))
|
||||
generic_error_remove_page(mapping, page);
|
||||
unlock_page(page);
|
||||
@ -194,10 +194,6 @@ static void nfs_initiate_read(struct nfs_pgio_header *hdr,
|
||||
const struct nfs_rpc_ops *rpc_ops,
|
||||
struct rpc_task_setup *task_setup_data, int how)
|
||||
{
|
||||
struct inode *inode = hdr->inode;
|
||||
int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0;
|
||||
|
||||
task_setup_data->flags |= swap_flags;
|
||||
rpc_ops->read_setup(hdr, msg);
|
||||
trace_nfs_initiate_read(hdr);
|
||||
}
|
||||
@ -290,9 +286,8 @@ static void nfs_readpage_result(struct rpc_task *task,
|
||||
}
|
||||
|
||||
static int
|
||||
readpage_async_filler(void *data, struct page *page)
|
||||
readpage_async_filler(struct nfs_readdesc *desc, struct page *page)
|
||||
{
|
||||
struct nfs_readdesc *desc = data;
|
||||
struct inode *inode = page_file_mapping(page)->host;
|
||||
unsigned int rsize = NFS_SERVER(inode)->rsize;
|
||||
struct nfs_page *new;
|
||||
@ -306,7 +301,7 @@ readpage_async_filler(void *data, struct page *page)
|
||||
aligned_len = min_t(unsigned int, ALIGN(len, rsize), PAGE_SIZE);
|
||||
|
||||
if (!IS_SYNC(page->mapping->host)) {
|
||||
error = nfs_readpage_from_fscache(page->mapping->host, page);
|
||||
error = nfs_fscache_read_page(page->mapping->host, page);
|
||||
if (error == 0)
|
||||
goto out_unlock;
|
||||
}
|
||||
@ -397,14 +392,16 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int nfs_readpages(struct file *file, struct address_space *mapping,
|
||||
struct list_head *pages, unsigned nr_pages)
|
||||
void nfs_readahead(struct readahead_control *ractl)
|
||||
{
|
||||
unsigned int nr_pages = readahead_count(ractl);
|
||||
struct file *file = ractl->file;
|
||||
struct nfs_readdesc desc;
|
||||
struct inode *inode = mapping->host;
|
||||
struct inode *inode = ractl->mapping->host;
|
||||
struct page *page;
|
||||
int ret;
|
||||
|
||||
trace_nfs_aop_readahead(inode, lru_to_page(pages), nr_pages);
|
||||
trace_nfs_aop_readahead(inode, readahead_pos(ractl), nr_pages);
|
||||
nfs_inc_stats(inode, NFSIOS_VFSREADPAGES);
|
||||
|
||||
ret = -ESTALE;
|
||||
@ -422,14 +419,18 @@ int nfs_readpages(struct file *file, struct address_space *mapping,
|
||||
nfs_pageio_init_read(&desc.pgio, inode, false,
|
||||
&nfs_async_read_completion_ops);
|
||||
|
||||
ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
|
||||
while ((page = readahead_page(ractl)) != NULL) {
|
||||
ret = readpage_async_filler(&desc, page);
|
||||
put_page(page);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
nfs_pageio_complete_read(&desc.pgio);
|
||||
|
||||
put_nfs_open_context(desc.ctx);
|
||||
out:
|
||||
trace_nfs_aop_readahead_done(inode, nr_pages, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __init nfs_init_readpagecache(void)
|
||||
|
@ -70,27 +70,17 @@ static mempool_t *nfs_wdata_mempool;
|
||||
static struct kmem_cache *nfs_cdata_cachep;
|
||||
static mempool_t *nfs_commit_mempool;
|
||||
|
||||
struct nfs_commit_data *nfs_commitdata_alloc(bool never_fail)
|
||||
struct nfs_commit_data *nfs_commitdata_alloc(void)
|
||||
{
|
||||
struct nfs_commit_data *p;
|
||||
|
||||
if (never_fail)
|
||||
p = mempool_alloc(nfs_commit_mempool, GFP_NOIO);
|
||||
else {
|
||||
/* It is OK to do some reclaim, not no safe to wait
|
||||
* for anything to be returned to the pool.
|
||||
* mempool_alloc() cannot handle that particular combination,
|
||||
* so we need two separate attempts.
|
||||
*/
|
||||
p = kmem_cache_zalloc(nfs_cdata_cachep, nfs_io_gfp_mask());
|
||||
if (!p) {
|
||||
p = mempool_alloc(nfs_commit_mempool, GFP_NOWAIT);
|
||||
if (!p)
|
||||
p = kmem_cache_alloc(nfs_cdata_cachep, GFP_NOIO |
|
||||
__GFP_NOWARN | __GFP_NORETRY);
|
||||
if (!p)
|
||||
return NULL;
|
||||
memset(p, 0, sizeof(*p));
|
||||
}
|
||||
|
||||
memset(p, 0, sizeof(*p));
|
||||
INIT_LIST_HEAD(&p->pages);
|
||||
return p;
|
||||
}
|
||||
@ -104,9 +94,15 @@ EXPORT_SYMBOL_GPL(nfs_commit_free);
|
||||
|
||||
static struct nfs_pgio_header *nfs_writehdr_alloc(void)
|
||||
{
|
||||
struct nfs_pgio_header *p = mempool_alloc(nfs_wdata_mempool, GFP_KERNEL);
|
||||
struct nfs_pgio_header *p;
|
||||
|
||||
memset(p, 0, sizeof(*p));
|
||||
p = kmem_cache_zalloc(nfs_wdata_cachep, nfs_io_gfp_mask());
|
||||
if (!p) {
|
||||
p = mempool_alloc(nfs_wdata_mempool, GFP_NOWAIT);
|
||||
if (!p)
|
||||
return NULL;
|
||||
memset(p, 0, sizeof(*p));
|
||||
}
|
||||
p->rw_mode = FMODE_WRITE;
|
||||
return p;
|
||||
}
|
||||
@ -306,7 +302,7 @@ static void nfs_set_pageerror(struct address_space *mapping)
|
||||
/* Force file size revalidation */
|
||||
spin_lock(&inode->i_lock);
|
||||
nfs_set_cache_invalid(inode, NFS_INO_REVAL_FORCED |
|
||||
NFS_INO_REVAL_PAGECACHE |
|
||||
NFS_INO_INVALID_CHANGE |
|
||||
NFS_INO_INVALID_SIZE);
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
@ -316,7 +312,10 @@ static void nfs_mapping_set_error(struct page *page, int error)
|
||||
struct address_space *mapping = page_file_mapping(page);
|
||||
|
||||
SetPageError(page);
|
||||
mapping_set_error(mapping, error);
|
||||
filemap_set_wb_err(mapping, error);
|
||||
if (mapping->host)
|
||||
errseq_set(&mapping->host->i_sb->s_wb_err,
|
||||
error == -ENOSPC ? -ENOSPC : -EIO);
|
||||
nfs_set_pageerror(mapping);
|
||||
}
|
||||
|
||||
@ -1417,6 +1416,8 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
|
||||
{
|
||||
int priority = flush_task_priority(how);
|
||||
|
||||
if (IS_SWAPFILE(hdr->inode))
|
||||
task_setup_data->flags |= RPC_TASK_SWAPPER;
|
||||
task_setup_data->priority = priority;
|
||||
rpc_ops->write_setup(hdr, msg, &task_setup_data->rpc_client);
|
||||
trace_nfs_initiate_write(hdr);
|
||||
@ -1829,7 +1830,11 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how,
|
||||
if (list_empty(head))
|
||||
return 0;
|
||||
|
||||
data = nfs_commitdata_alloc(true);
|
||||
data = nfs_commitdata_alloc();
|
||||
if (!data) {
|
||||
nfs_retry_commit(head, NULL, cinfo, -1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Set up the argument struct */
|
||||
nfs_init_commit(data, head, NULL, cinfo);
|
||||
|
@ -45,11 +45,6 @@
|
||||
*/
|
||||
#define NFS_MAX_TRANSPORTS 16
|
||||
|
||||
/*
|
||||
* These are the default flags for swap requests
|
||||
*/
|
||||
#define NFS_RPC_SWAPFLAGS (RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS)
|
||||
|
||||
/*
|
||||
* Size of the NFS directory verifier
|
||||
*/
|
||||
@ -101,13 +96,17 @@ struct nfs_open_context {
|
||||
|
||||
struct nfs_open_dir_context {
|
||||
struct list_head list;
|
||||
atomic_t cache_hits;
|
||||
atomic_t cache_misses;
|
||||
unsigned long attr_gencount;
|
||||
__be32 verf[NFS_DIR_VERIFIER_SIZE];
|
||||
__u64 dir_cookie;
|
||||
__u64 dup_cookie;
|
||||
__u64 last_cookie;
|
||||
pgoff_t page_index;
|
||||
signed char duped;
|
||||
unsigned int dtsize;
|
||||
bool force_clear;
|
||||
bool eof;
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -247,7 +246,6 @@ struct nfs4_copy_state {
|
||||
#define NFS_INO_INVALID_ATIME BIT(2) /* cached atime is invalid */
|
||||
#define NFS_INO_INVALID_ACCESS BIT(3) /* cached access cred invalid */
|
||||
#define NFS_INO_INVALID_ACL BIT(4) /* cached acls are invalid */
|
||||
#define NFS_INO_REVAL_PAGECACHE BIT(5) /* must revalidate pagecache */
|
||||
#define NFS_INO_REVAL_FORCED BIT(6) /* force revalidation ignoring a delegation */
|
||||
#define NFS_INO_INVALID_LABEL BIT(7) /* cached label is invalid */
|
||||
#define NFS_INO_INVALID_CHANGE BIT(8) /* cached change is invalid */
|
||||
@ -273,12 +271,11 @@ struct nfs4_copy_state {
|
||||
/*
|
||||
* Bit offsets in flags field
|
||||
*/
|
||||
#define NFS_INO_ADVISE_RDPLUS (0) /* advise readdirplus */
|
||||
#define NFS_INO_STALE (1) /* possible stale inode */
|
||||
#define NFS_INO_ACL_LRU_SET (2) /* Inode is on the LRU list */
|
||||
#define NFS_INO_INVALIDATING (3) /* inode is being invalidated */
|
||||
#define NFS_INO_PRESERVE_UNLINKED (4) /* preserve file if removed while open */
|
||||
#define NFS_INO_FSCACHE (5) /* inode can be cached by FS-Cache */
|
||||
#define NFS_INO_FORCE_READDIR (7) /* force readdirplus */
|
||||
#define NFS_INO_LAYOUTCOMMIT (9) /* layoutcommit required */
|
||||
#define NFS_INO_LAYOUTCOMMITTING (10) /* layoutcommit inflight */
|
||||
#define NFS_INO_LAYOUTSTATS (11) /* layoutstats inflight */
|
||||
@ -355,17 +352,15 @@ static inline void nfs_mark_for_revalidate(struct inode *inode)
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE
|
||||
| NFS_INO_INVALID_ACCESS
|
||||
| NFS_INO_INVALID_ACL
|
||||
| NFS_INO_INVALID_CHANGE
|
||||
| NFS_INO_INVALID_CTIME;
|
||||
nfsi->cache_validity |= NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL |
|
||||
NFS_INO_INVALID_CHANGE | NFS_INO_INVALID_CTIME |
|
||||
NFS_INO_INVALID_SIZE;
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
nfsi->cache_validity |= NFS_INO_INVALID_DATA;
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
|
||||
static inline int nfs_server_capable(struct inode *inode, int cap)
|
||||
static inline int nfs_server_capable(const struct inode *inode, int cap)
|
||||
{
|
||||
return NFS_SERVER(inode)->caps & cap;
|
||||
}
|
||||
@ -513,10 +508,10 @@ static inline const struct cred *nfs_file_cred(struct file *file)
|
||||
* linux/fs/nfs/direct.c
|
||||
*/
|
||||
extern ssize_t nfs_direct_IO(struct kiocb *, struct iov_iter *);
|
||||
extern ssize_t nfs_file_direct_read(struct kiocb *iocb,
|
||||
struct iov_iter *iter);
|
||||
extern ssize_t nfs_file_direct_write(struct kiocb *iocb,
|
||||
struct iov_iter *iter);
|
||||
ssize_t nfs_file_direct_read(struct kiocb *iocb,
|
||||
struct iov_iter *iter, bool swap);
|
||||
ssize_t nfs_file_direct_write(struct kiocb *iocb,
|
||||
struct iov_iter *iter, bool swap);
|
||||
|
||||
/*
|
||||
* linux/fs/nfs/dir.c
|
||||
@ -585,24 +580,22 @@ extern int nfs_wb_all(struct inode *inode);
|
||||
extern int nfs_wb_page(struct inode *inode, struct page *page);
|
||||
int nfs_wb_folio_cancel(struct inode *inode, struct folio *folio);
|
||||
extern int nfs_commit_inode(struct inode *, int);
|
||||
extern struct nfs_commit_data *nfs_commitdata_alloc(bool never_fail);
|
||||
extern struct nfs_commit_data *nfs_commitdata_alloc(void);
|
||||
extern void nfs_commit_free(struct nfs_commit_data *data);
|
||||
bool nfs_commit_end(struct nfs_mds_commit_info *cinfo);
|
||||
|
||||
static inline int
|
||||
nfs_have_writebacks(struct inode *inode)
|
||||
static inline bool nfs_have_writebacks(const struct inode *inode)
|
||||
{
|
||||
if (S_ISREG(inode->i_mode))
|
||||
return atomic_long_read(&NFS_I(inode)->nrequests) != 0;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* linux/fs/nfs/read.c
|
||||
*/
|
||||
extern int nfs_readpage(struct file *, struct page *);
|
||||
extern int nfs_readpages(struct file *, struct address_space *,
|
||||
struct list_head *, unsigned);
|
||||
void nfs_readahead(struct readahead_control *);
|
||||
|
||||
/*
|
||||
* inline functions
|
||||
|
@ -152,6 +152,7 @@ struct nfs_server {
|
||||
#define NFS_MOUNT_SOFTREVAL 0x800000
|
||||
#define NFS_MOUNT_WRITE_EAGER 0x01000000
|
||||
#define NFS_MOUNT_WRITE_WAIT 0x02000000
|
||||
#define NFS_MOUNT_TRUNK_DISCOVERY 0x04000000
|
||||
|
||||
unsigned int fattr_valid; /* Valid attributes */
|
||||
unsigned int caps; /* server capabilities */
|
||||
|
@ -745,8 +745,7 @@ struct nfs_auth_info {
|
||||
*/
|
||||
struct nfs_entry {
|
||||
__u64 ino;
|
||||
__u64 cookie,
|
||||
prev_cookie;
|
||||
__u64 cookie;
|
||||
const char * name;
|
||||
unsigned int len;
|
||||
int eof;
|
||||
@ -1798,6 +1797,8 @@ struct nfs_rpc_ops {
|
||||
struct nfs_server *(*clone_server)(struct nfs_server *, struct nfs_fh *,
|
||||
struct nfs_fattr *, rpc_authflavor_t);
|
||||
int (*discover_trunking)(struct nfs_server *, struct nfs_fh *);
|
||||
void (*enable_swap)(struct inode *inode);
|
||||
void (*disable_swap)(struct inode *inode);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -99,6 +99,7 @@ struct rpc_auth_create_args {
|
||||
|
||||
/* Flags for rpcauth_lookupcred() */
|
||||
#define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */
|
||||
#define RPCAUTH_LOOKUP_ASYNC 0x02 /* Don't block waiting for memory */
|
||||
|
||||
/*
|
||||
* Client authentication ops
|
||||
|
@ -124,7 +124,6 @@ struct rpc_task_setup {
|
||||
#define RPC_TASK_MOVEABLE 0x0004 /* nfs4.1+ rpc tasks */
|
||||
#define RPC_TASK_NULLCREDS 0x0010 /* Use AUTH_NULL credential */
|
||||
#define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */
|
||||
#define RPC_TASK_ROOTCREDS 0x0040 /* force root creds */
|
||||
#define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */
|
||||
#define RPC_TASK_NO_ROUND_ROBIN 0x0100 /* send requests on "main" xprt */
|
||||
#define RPC_TASK_SOFT 0x0200 /* Use soft timeouts */
|
||||
@ -263,6 +262,7 @@ void rpc_destroy_mempool(void);
|
||||
extern struct workqueue_struct *rpciod_workqueue;
|
||||
extern struct workqueue_struct *xprtiod_workqueue;
|
||||
void rpc_prepare_task(struct rpc_task *task);
|
||||
gfp_t rpc_task_gfp_mask(void);
|
||||
|
||||
static inline int rpc_wait_for_completion_task(struct rpc_task *task)
|
||||
{
|
||||
|
@ -139,6 +139,9 @@ struct rpc_xprt_ops {
|
||||
void (*rpcbind)(struct rpc_task *task);
|
||||
void (*set_port)(struct rpc_xprt *xprt, unsigned short port);
|
||||
void (*connect)(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
int (*get_srcaddr)(struct rpc_xprt *xprt, char *buf,
|
||||
size_t buflen);
|
||||
unsigned short (*get_srcport)(struct rpc_xprt *xprt);
|
||||
int (*buf_alloc)(struct rpc_task *task);
|
||||
void (*buf_free)(struct rpc_task *task);
|
||||
void (*prepare_request)(struct rpc_rqst *req);
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
int init_socket_xprt(void);
|
||||
void cleanup_socket_xprt(void);
|
||||
unsigned short get_srcport(struct rpc_xprt *);
|
||||
|
||||
#define RPC_MIN_RESVPORT (1U)
|
||||
#define RPC_MAX_RESVPORT (65535U)
|
||||
@ -89,5 +88,7 @@ struct sock_xprt {
|
||||
#define XPRT_SOCK_WAKE_WRITE (5)
|
||||
#define XPRT_SOCK_WAKE_PENDING (6)
|
||||
#define XPRT_SOCK_WAKE_DISCONNECT (7)
|
||||
#define XPRT_SOCK_CONNECT_SENT (8)
|
||||
#define XPRT_SOCK_NOSPACE (9)
|
||||
|
||||
#endif /* _LINUX_SUNRPC_XPRTSOCK_H */
|
||||
|
@ -311,7 +311,6 @@ TRACE_EVENT(rpc_request,
|
||||
{ RPC_TASK_MOVEABLE, "MOVEABLE" }, \
|
||||
{ RPC_TASK_NULLCREDS, "NULLCREDS" }, \
|
||||
{ RPC_CALL_MAJORSEEN, "MAJORSEEN" }, \
|
||||
{ RPC_TASK_ROOTCREDS, "ROOTCREDS" }, \
|
||||
{ RPC_TASK_DYNAMIC, "DYNAMIC" }, \
|
||||
{ RPC_TASK_NO_ROUND_ROBIN, "NO_ROUND_ROBIN" }, \
|
||||
{ RPC_TASK_SOFT, "SOFT" }, \
|
||||
|
@ -45,6 +45,7 @@
|
||||
|
||||
#define NFS4_OPEN_RESULT_CONFIRM 0x0002
|
||||
#define NFS4_OPEN_RESULT_LOCKTYPE_POSIX 0x0004
|
||||
#define NFS4_OPEN_RESULT_PRESERVE_UNLINKED 0x0008
|
||||
#define NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK 0x0020
|
||||
|
||||
#define NFS4_SHARE_ACCESS_MASK 0x000F
|
||||
|
@ -52,7 +52,7 @@
|
||||
#define NFSDBG_CALLBACK 0x0100
|
||||
#define NFSDBG_CLIENT 0x0200
|
||||
#define NFSDBG_MOUNT 0x0400
|
||||
#define NFSDBG_FSCACHE 0x0800
|
||||
#define NFSDBG_FSCACHE 0x0800 /* unused */
|
||||
#define NFSDBG_PNFS 0x1000
|
||||
#define NFSDBG_PNFS_LD 0x2000
|
||||
#define NFSDBG_STATE 0x4000
|
||||
|
@ -615,6 +615,8 @@ rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags)
|
||||
};
|
||||
struct rpc_cred *ret;
|
||||
|
||||
if (RPC_IS_ASYNC(task))
|
||||
lookupflags |= RPCAUTH_LOOKUP_ASYNC;
|
||||
ret = auth->au_ops->lookup_cred(auth, &acred, lookupflags);
|
||||
put_cred(acred.cred);
|
||||
return ret;
|
||||
@ -631,6 +633,8 @@ rpcauth_bind_machine_cred(struct rpc_task *task, int lookupflags)
|
||||
|
||||
if (!acred.principal)
|
||||
return NULL;
|
||||
if (RPC_IS_ASYNC(task))
|
||||
lookupflags |= RPCAUTH_LOOKUP_ASYNC;
|
||||
return auth->au_ops->lookup_cred(auth, &acred, lookupflags);
|
||||
}
|
||||
|
||||
@ -654,7 +658,7 @@ rpcauth_bindcred(struct rpc_task *task, const struct cred *cred, int flags)
|
||||
};
|
||||
|
||||
if (flags & RPC_TASK_ASYNC)
|
||||
lookupflags |= RPCAUTH_LOOKUP_NEW;
|
||||
lookupflags |= RPCAUTH_LOOKUP_NEW | RPCAUTH_LOOKUP_ASYNC;
|
||||
if (task->tk_op_cred)
|
||||
/* Task must use exactly this rpc_cred */
|
||||
new = get_rpccred(task->tk_op_cred);
|
||||
@ -666,7 +670,7 @@ rpcauth_bindcred(struct rpc_task *task, const struct cred *cred, int flags)
|
||||
/* If machine cred couldn't be bound, try a root cred */
|
||||
if (new)
|
||||
;
|
||||
else if (cred == &machine_cred || (flags & RPC_TASK_ROOTCREDS))
|
||||
else if (cred == &machine_cred)
|
||||
new = rpcauth_bind_root_cred(task, lookupflags);
|
||||
else if (flags & RPC_TASK_NULLCREDS)
|
||||
new = authnull_ops.lookup_cred(NULL, NULL, 0);
|
||||
|
@ -146,7 +146,7 @@ gss_alloc_context(void)
|
||||
{
|
||||
struct gss_cl_ctx *ctx;
|
||||
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_NOFS);
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (ctx != NULL) {
|
||||
ctx->gc_proc = RPC_GSS_PROC_DATA;
|
||||
ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */
|
||||
@ -209,7 +209,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
|
||||
p = ERR_PTR(-EFAULT);
|
||||
goto err;
|
||||
}
|
||||
ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx, NULL, GFP_NOFS);
|
||||
ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx, NULL, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
trace_rpcgss_import_ctx(ret);
|
||||
p = ERR_PTR(ret);
|
||||
@ -511,7 +511,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
|
||||
int vers;
|
||||
int err = -ENOMEM;
|
||||
|
||||
gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS);
|
||||
gss_msg = kzalloc(sizeof(*gss_msg), GFP_KERNEL);
|
||||
if (gss_msg == NULL)
|
||||
goto err;
|
||||
vers = get_pipe_version(gss_auth->net);
|
||||
@ -527,7 +527,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
|
||||
gss_msg->auth = gss_auth;
|
||||
kref_get(&gss_auth->kref);
|
||||
if (service_name) {
|
||||
gss_msg->service_name = kstrdup_const(service_name, GFP_NOFS);
|
||||
gss_msg->service_name = kstrdup_const(service_name, GFP_KERNEL);
|
||||
if (!gss_msg->service_name) {
|
||||
err = -ENOMEM;
|
||||
goto err_put_pipe_version;
|
||||
@ -703,7 +703,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
|
||||
if (mlen > MSG_BUF_MAXSIZE)
|
||||
goto out;
|
||||
err = -ENOMEM;
|
||||
buf = kmalloc(mlen, GFP_NOFS);
|
||||
buf = kmalloc(mlen, GFP_KERNEL);
|
||||
if (!buf)
|
||||
goto out;
|
||||
|
||||
@ -1220,7 +1220,7 @@ gss_dup_cred(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
|
||||
struct gss_cred *new;
|
||||
|
||||
/* Make a copy of the cred so that we can reference count it */
|
||||
new = kzalloc(sizeof(*gss_cred), GFP_NOFS);
|
||||
new = kzalloc(sizeof(*gss_cred), GFP_KERNEL);
|
||||
if (new) {
|
||||
struct auth_cred acred = {
|
||||
.cred = gss_cred->gc_base.cr_cred,
|
||||
@ -1343,7 +1343,11 @@ gss_hash_cred(struct auth_cred *acred, unsigned int hashbits)
|
||||
static struct rpc_cred *
|
||||
gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
|
||||
{
|
||||
return rpcauth_lookup_credcache(auth, acred, flags, GFP_NOFS);
|
||||
gfp_t gfp = GFP_KERNEL;
|
||||
|
||||
if (flags & RPCAUTH_LOOKUP_ASYNC)
|
||||
gfp = GFP_NOWAIT | __GFP_NOWARN;
|
||||
return rpcauth_lookup_credcache(auth, acred, flags, gfp);
|
||||
}
|
||||
|
||||
static struct rpc_cred *
|
||||
@ -1669,7 +1673,7 @@ gss_validate(struct rpc_task *task, struct xdr_stream *xdr)
|
||||
if (!p)
|
||||
goto validate_failed;
|
||||
|
||||
seq = kmalloc(4, GFP_NOFS);
|
||||
seq = kmalloc(4, GFP_KERNEL);
|
||||
if (!seq)
|
||||
goto validate_failed;
|
||||
*seq = cpu_to_be32(task->tk_rqstp->rq_seqno);
|
||||
@ -1779,11 +1783,11 @@ alloc_enc_pages(struct rpc_rqst *rqstp)
|
||||
rqstp->rq_enc_pages
|
||||
= kmalloc_array(rqstp->rq_enc_pages_num,
|
||||
sizeof(struct page *),
|
||||
GFP_NOFS);
|
||||
GFP_KERNEL);
|
||||
if (!rqstp->rq_enc_pages)
|
||||
goto out;
|
||||
for (i=0; i < rqstp->rq_enc_pages_num; i++) {
|
||||
rqstp->rq_enc_pages[i] = alloc_page(GFP_NOFS);
|
||||
rqstp->rq_enc_pages[i] = alloc_page(GFP_KERNEL);
|
||||
if (rqstp->rq_enc_pages[i] == NULL)
|
||||
goto out_free;
|
||||
}
|
||||
@ -1987,7 +1991,7 @@ gss_unwrap_resp_integ(struct rpc_task *task, struct rpc_cred *cred,
|
||||
if (offset + len > rcv_buf->len)
|
||||
goto unwrap_failed;
|
||||
mic.len = len;
|
||||
mic.data = kmalloc(len, GFP_NOFS);
|
||||
mic.data = kmalloc(len, GFP_KERNEL);
|
||||
if (!mic.data)
|
||||
goto unwrap_failed;
|
||||
if (read_bytes_from_xdr_buf(rcv_buf, offset, mic.data, mic.len))
|
||||
|
@ -35,7 +35,7 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest)
|
||||
if (unlikely(q > end || q < p))
|
||||
return ERR_PTR(-EFAULT);
|
||||
if (len) {
|
||||
dest->data = kmemdup(p, len, GFP_NOFS);
|
||||
dest->data = kmemdup(p, len, GFP_KERNEL);
|
||||
if (unlikely(dest->data == NULL))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
} else
|
||||
|
@ -161,7 +161,7 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS);
|
||||
checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_KERNEL);
|
||||
if (checksumdata == NULL)
|
||||
return GSS_S_FAILURE;
|
||||
|
||||
@ -169,7 +169,7 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
if (IS_ERR(tfm))
|
||||
goto out_free_cksum;
|
||||
|
||||
req = ahash_request_alloc(tfm, GFP_NOFS);
|
||||
req = ahash_request_alloc(tfm, GFP_KERNEL);
|
||||
if (!req)
|
||||
goto out_free_ahash;
|
||||
|
||||
@ -257,7 +257,7 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS);
|
||||
checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_KERNEL);
|
||||
if (!checksumdata)
|
||||
return GSS_S_FAILURE;
|
||||
|
||||
@ -265,7 +265,7 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
if (IS_ERR(tfm))
|
||||
goto out_free_cksum;
|
||||
|
||||
req = ahash_request_alloc(tfm, GFP_NOFS);
|
||||
req = ahash_request_alloc(tfm, GFP_KERNEL);
|
||||
if (!req)
|
||||
goto out_free_ahash;
|
||||
|
||||
@ -554,7 +554,7 @@ gss_krb5_cts_crypt(struct crypto_sync_skcipher *cipher, struct xdr_buf *buf,
|
||||
WARN_ON(0);
|
||||
return -ENOMEM;
|
||||
}
|
||||
data = kmalloc(GSS_KRB5_MAX_BLOCKSIZE * 2, GFP_NOFS);
|
||||
data = kmalloc(GSS_KRB5_MAX_BLOCKSIZE * 2, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -49,7 +49,7 @@ krb5_make_seq_num(struct krb5_ctx *kctx,
|
||||
unsigned char *plain;
|
||||
s32 code;
|
||||
|
||||
plain = kmalloc(8, GFP_NOFS);
|
||||
plain = kmalloc(8, GFP_KERNEL);
|
||||
if (!plain)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -80,7 +80,7 @@ krb5_get_seq_num(struct krb5_ctx *kctx,
|
||||
|
||||
dprintk("RPC: krb5_get_seq_num:\n");
|
||||
|
||||
plain = kmalloc(8, GFP_NOFS);
|
||||
plain = kmalloc(8, GFP_KERNEL);
|
||||
if (!plain)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -409,7 +409,7 @@ static u32
|
||||
gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset,
|
||||
struct xdr_buf *buf, struct page **pages)
|
||||
{
|
||||
u8 *ptr, *plainhdr;
|
||||
u8 *ptr;
|
||||
time64_t now;
|
||||
u8 flags = 0x00;
|
||||
__be16 *be16ptr;
|
||||
@ -426,7 +426,7 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset,
|
||||
return GSS_S_FAILURE;
|
||||
|
||||
/* construct gss token header */
|
||||
ptr = plainhdr = buf->head[0].iov_base + offset;
|
||||
ptr = buf->head[0].iov_base + offset;
|
||||
*ptr++ = (unsigned char) ((KG2_TOK_WRAP>>8) & 0xff);
|
||||
*ptr++ = (unsigned char) (KG2_TOK_WRAP & 0xff);
|
||||
|
||||
|
@ -40,11 +40,19 @@ unx_destroy(struct rpc_auth *auth)
|
||||
/*
|
||||
* Lookup AUTH_UNIX creds for current process
|
||||
*/
|
||||
static struct rpc_cred *
|
||||
unx_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
|
||||
static struct rpc_cred *unx_lookup_cred(struct rpc_auth *auth,
|
||||
struct auth_cred *acred, int flags)
|
||||
{
|
||||
struct rpc_cred *ret = mempool_alloc(unix_pool, GFP_NOFS);
|
||||
struct rpc_cred *ret;
|
||||
|
||||
ret = kmalloc(sizeof(*ret), rpc_task_gfp_mask());
|
||||
if (!ret) {
|
||||
if (!(flags & RPCAUTH_LOOKUP_ASYNC))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
ret = mempool_alloc(unix_pool, GFP_NOWAIT);
|
||||
if (!ret)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
rpcauth_init_cred(ret, acred, auth, &unix_credops);
|
||||
ret->cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
|
||||
return ret;
|
||||
|
@ -75,9 +75,9 @@ static int xprt_alloc_xdr_buf(struct xdr_buf *buf, gfp_t gfp_flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
struct rpc_rqst *xprt_alloc_bc_req(struct rpc_xprt *xprt, gfp_t gfp_flags)
|
||||
static struct rpc_rqst *xprt_alloc_bc_req(struct rpc_xprt *xprt)
|
||||
{
|
||||
gfp_t gfp_flags = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN;
|
||||
struct rpc_rqst *req;
|
||||
|
||||
/* Pre-allocate one backchannel rpc_rqst */
|
||||
@ -154,7 +154,7 @@ int xprt_setup_bc(struct rpc_xprt *xprt, unsigned int min_reqs)
|
||||
INIT_LIST_HEAD(&tmp_list);
|
||||
for (i = 0; i < min_reqs; i++) {
|
||||
/* Pre-allocate one backchannel rpc_rqst */
|
||||
req = xprt_alloc_bc_req(xprt, GFP_KERNEL);
|
||||
req = xprt_alloc_bc_req(xprt);
|
||||
if (req == NULL) {
|
||||
printk(KERN_ERR "Failed to create bc rpc_rqst\n");
|
||||
goto out_free;
|
||||
@ -343,7 +343,7 @@ found:
|
||||
break;
|
||||
} else if (req)
|
||||
break;
|
||||
new = xprt_alloc_bc_req(xprt, GFP_KERNEL);
|
||||
new = xprt_alloc_bc_req(xprt);
|
||||
} while (new);
|
||||
return req;
|
||||
}
|
||||
|
@ -1065,7 +1065,9 @@ rpc_task_get_next_xprt(struct rpc_clnt *clnt)
|
||||
static
|
||||
void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
|
||||
{
|
||||
if (task->tk_xprt)
|
||||
if (task->tk_xprt &&
|
||||
!(test_bit(XPRT_OFFLINE, &task->tk_xprt->state) &&
|
||||
(task->tk_flags & RPC_TASK_MOVEABLE)))
|
||||
return;
|
||||
if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN)
|
||||
task->tk_xprt = rpc_task_get_first_xprt(clnt);
|
||||
@ -1085,8 +1087,6 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
|
||||
task->tk_flags |= RPC_TASK_TIMEOUT;
|
||||
if (clnt->cl_noretranstimeo)
|
||||
task->tk_flags |= RPC_TASK_NO_RETRANS_TIMEOUT;
|
||||
if (atomic_read(&clnt->cl_swapper))
|
||||
task->tk_flags |= RPC_TASK_SWAPPER;
|
||||
/* Add to the client's list of all tasks */
|
||||
spin_lock(&clnt->cl_lock);
|
||||
list_add_tail(&task->tk_task, &clnt->cl_tasks);
|
||||
@ -1745,6 +1745,9 @@ call_refreshresult(struct rpc_task *task)
|
||||
task->tk_cred_retry--;
|
||||
trace_rpc_retry_refresh_status(task);
|
||||
return;
|
||||
case -ENOMEM:
|
||||
rpc_delay(task, HZ >> 4);
|
||||
return;
|
||||
}
|
||||
trace_rpc_refresh_status(task);
|
||||
rpc_call_rpcerror(task, status);
|
||||
@ -2793,7 +2796,7 @@ int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data = kmalloc(sizeof(*data), GFP_NOFS);
|
||||
data = kmalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
data->xps = xprt_switch_get(xps);
|
||||
@ -3068,6 +3071,8 @@ rpc_clnt_swap_activate_callback(struct rpc_clnt *clnt,
|
||||
int
|
||||
rpc_clnt_swap_activate(struct rpc_clnt *clnt)
|
||||
{
|
||||
while (clnt != clnt->cl_parent)
|
||||
clnt = clnt->cl_parent;
|
||||
if (atomic_inc_return(&clnt->cl_swapper) == 1)
|
||||
return rpc_clnt_iterate_for_each_xprt(clnt,
|
||||
rpc_clnt_swap_activate_callback, NULL);
|
||||
|
@ -714,7 +714,7 @@ void rpcb_getport_async(struct rpc_task *task)
|
||||
goto bailout_nofree;
|
||||
}
|
||||
|
||||
map = kzalloc(sizeof(struct rpcbind_args), GFP_NOFS);
|
||||
map = kzalloc(sizeof(struct rpcbind_args), rpc_task_gfp_mask());
|
||||
if (!map) {
|
||||
status = -ENOMEM;
|
||||
goto bailout_release_client;
|
||||
@ -730,7 +730,7 @@ void rpcb_getport_async(struct rpc_task *task)
|
||||
case RPCBVERS_4:
|
||||
case RPCBVERS_3:
|
||||
map->r_netid = xprt->address_strings[RPC_DISPLAY_NETID];
|
||||
map->r_addr = rpc_sockaddr2uaddr(sap, GFP_NOFS);
|
||||
map->r_addr = rpc_sockaddr2uaddr(sap, rpc_task_gfp_mask());
|
||||
if (!map->r_addr) {
|
||||
status = -ENOMEM;
|
||||
goto bailout_free_args;
|
||||
|
@ -57,6 +57,13 @@ struct workqueue_struct *rpciod_workqueue __read_mostly;
|
||||
struct workqueue_struct *xprtiod_workqueue __read_mostly;
|
||||
EXPORT_SYMBOL_GPL(xprtiod_workqueue);
|
||||
|
||||
gfp_t rpc_task_gfp_mask(void)
|
||||
{
|
||||
if (current->flags & PF_WQ_WORKER)
|
||||
return GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN;
|
||||
return GFP_KERNEL;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
rpc_task_timeout(const struct rpc_task *task)
|
||||
{
|
||||
@ -186,11 +193,6 @@ static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue,
|
||||
|
||||
/*
|
||||
* Add new request to wait queue.
|
||||
*
|
||||
* Swapper tasks always get inserted at the head of the queue.
|
||||
* This should avoid many nasty memory deadlocks and hopefully
|
||||
* improve overall performance.
|
||||
* Everyone else gets appended to the queue to ensure proper FIFO behavior.
|
||||
*/
|
||||
static void __rpc_add_wait_queue(struct rpc_wait_queue *queue,
|
||||
struct rpc_task *task,
|
||||
@ -199,8 +201,6 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue,
|
||||
INIT_LIST_HEAD(&task->u.tk_wait.timer_list);
|
||||
if (RPC_IS_PRIORITY(queue))
|
||||
__rpc_add_wait_queue_priority(queue, task, queue_priority);
|
||||
else if (RPC_IS_SWAPPER(task))
|
||||
list_add(&task->u.tk_wait.list, &queue->tasks[0]);
|
||||
else
|
||||
list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);
|
||||
task->tk_waitqueue = queue;
|
||||
@ -876,6 +876,15 @@ void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata)
|
||||
ops->rpc_release(calldata);
|
||||
}
|
||||
|
||||
static bool xprt_needs_memalloc(struct rpc_xprt *xprt, struct rpc_task *tk)
|
||||
{
|
||||
if (!xprt)
|
||||
return false;
|
||||
if (!atomic_read(&xprt->swapper))
|
||||
return false;
|
||||
return test_bit(XPRT_LOCKED, &xprt->state) && xprt->snd_task == tk;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the RPC `scheduler' (or rather, the finite state machine).
|
||||
*/
|
||||
@ -884,6 +893,7 @@ static void __rpc_execute(struct rpc_task *task)
|
||||
struct rpc_wait_queue *queue;
|
||||
int task_is_async = RPC_IS_ASYNC(task);
|
||||
int status = 0;
|
||||
unsigned long pflags = current->flags;
|
||||
|
||||
WARN_ON_ONCE(RPC_IS_QUEUED(task));
|
||||
if (RPC_IS_QUEUED(task))
|
||||
@ -906,6 +916,10 @@ static void __rpc_execute(struct rpc_task *task)
|
||||
}
|
||||
if (!do_action)
|
||||
break;
|
||||
if (RPC_IS_SWAPPER(task) ||
|
||||
xprt_needs_memalloc(task->tk_xprt, task))
|
||||
current->flags |= PF_MEMALLOC;
|
||||
|
||||
trace_rpc_task_run_action(task, do_action);
|
||||
do_action(task);
|
||||
|
||||
@ -943,7 +957,7 @@ static void __rpc_execute(struct rpc_task *task)
|
||||
rpc_clear_running(task);
|
||||
spin_unlock(&queue->lock);
|
||||
if (task_is_async)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
/* sync task: sleep here */
|
||||
trace_rpc_task_sync_sleep(task, task->tk_action);
|
||||
@ -967,6 +981,8 @@ static void __rpc_execute(struct rpc_task *task)
|
||||
|
||||
/* Release all resources associated with the task */
|
||||
rpc_release_task(task);
|
||||
out:
|
||||
current_restore_flags(pflags, PF_MEMALLOC);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1021,15 +1037,15 @@ int rpc_malloc(struct rpc_task *task)
|
||||
struct rpc_rqst *rqst = task->tk_rqstp;
|
||||
size_t size = rqst->rq_callsize + rqst->rq_rcvsize;
|
||||
struct rpc_buffer *buf;
|
||||
gfp_t gfp = GFP_NOFS;
|
||||
|
||||
if (RPC_IS_SWAPPER(task))
|
||||
gfp = __GFP_MEMALLOC | GFP_NOWAIT | __GFP_NOWARN;
|
||||
gfp_t gfp = rpc_task_gfp_mask();
|
||||
|
||||
size += sizeof(struct rpc_buffer);
|
||||
if (size <= RPC_BUFFER_MAXSIZE)
|
||||
buf = mempool_alloc(rpc_buffer_mempool, gfp);
|
||||
else
|
||||
if (size <= RPC_BUFFER_MAXSIZE) {
|
||||
buf = kmem_cache_alloc(rpc_buffer_slabp, gfp);
|
||||
/* Reach for the mempool if dynamic allocation fails */
|
||||
if (!buf && RPC_IS_ASYNC(task))
|
||||
buf = mempool_alloc(rpc_buffer_mempool, GFP_NOWAIT);
|
||||
} else
|
||||
buf = kmalloc(size, gfp);
|
||||
|
||||
if (!buf)
|
||||
@ -1092,10 +1108,14 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta
|
||||
rpc_init_task_statistics(task);
|
||||
}
|
||||
|
||||
static struct rpc_task *
|
||||
rpc_alloc_task(void)
|
||||
static struct rpc_task *rpc_alloc_task(void)
|
||||
{
|
||||
return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS);
|
||||
struct rpc_task *task;
|
||||
|
||||
task = kmem_cache_alloc(rpc_task_slabp, rpc_task_gfp_mask());
|
||||
if (task)
|
||||
return task;
|
||||
return mempool_alloc(rpc_task_mempool, GFP_NOWAIT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/sunrpc/msg_prot.h>
|
||||
#include <linux/sunrpc/sched.h>
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
@ -222,7 +223,7 @@ static int xprt_send_pagedata(struct socket *sock, struct msghdr *msg,
|
||||
{
|
||||
int err;
|
||||
|
||||
err = xdr_alloc_bvec(xdr, GFP_KERNEL);
|
||||
err = xdr_alloc_bvec(xdr, rpc_task_gfp_mask());
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -93,11 +93,14 @@ static ssize_t rpc_sysfs_xprt_dstaddr_show(struct kobject *kobj,
|
||||
struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
|
||||
ssize_t ret;
|
||||
|
||||
if (!xprt)
|
||||
return 0;
|
||||
if (!xprt) {
|
||||
ret = sprintf(buf, "<closed>\n");
|
||||
goto out;
|
||||
}
|
||||
ret = sprintf(buf, "%s\n", xprt->address_strings[RPC_DISPLAY_ADDR]);
|
||||
xprt_put(xprt);
|
||||
return ret + 1;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj,
|
||||
@ -105,41 +108,45 @@ static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj,
|
||||
char *buf)
|
||||
{
|
||||
struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
|
||||
struct sockaddr_storage saddr;
|
||||
struct sock_xprt *sock;
|
||||
ssize_t ret = -1;
|
||||
|
||||
if (!xprt || !xprt_connected(xprt)) {
|
||||
xprt_put(xprt);
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
sock = container_of(xprt, struct sock_xprt, xprt);
|
||||
mutex_lock(&sock->recv_mutex);
|
||||
if (sock->sock == NULL ||
|
||||
kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0)
|
||||
goto out;
|
||||
|
||||
ret = sprintf(buf, "%pISc\n", &saddr);
|
||||
out:
|
||||
mutex_unlock(&sock->recv_mutex);
|
||||
xprt_put(xprt);
|
||||
return ret + 1;
|
||||
}
|
||||
|
||||
static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
|
||||
size_t buflen = PAGE_SIZE;
|
||||
ssize_t ret;
|
||||
|
||||
if (!xprt || !xprt_connected(xprt)) {
|
||||
xprt_put(xprt);
|
||||
return -ENOTCONN;
|
||||
ret = sprintf(buf, "<closed>\n");
|
||||
} else if (xprt->ops->get_srcaddr) {
|
||||
ret = xprt->ops->get_srcaddr(xprt, buf, buflen);
|
||||
if (ret > 0) {
|
||||
if (ret < buflen - 1) {
|
||||
buf[ret] = '\n';
|
||||
ret++;
|
||||
buf[ret] = '\0';
|
||||
}
|
||||
} else
|
||||
ret = sprintf(buf, "<closed>\n");
|
||||
} else
|
||||
ret = sprintf(buf, "<not a socket>\n");
|
||||
xprt_put(xprt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
|
||||
unsigned short srcport = 0;
|
||||
size_t buflen = PAGE_SIZE;
|
||||
ssize_t ret;
|
||||
|
||||
if (!xprt || !xprt_connected(xprt)) {
|
||||
ret = sprintf(buf, "<closed>\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = sprintf(buf, "last_used=%lu\ncur_cong=%lu\ncong_win=%lu\n"
|
||||
if (xprt->ops->get_srcport)
|
||||
srcport = xprt->ops->get_srcport(xprt);
|
||||
|
||||
ret = snprintf(buf, buflen,
|
||||
"last_used=%lu\ncur_cong=%lu\ncong_win=%lu\n"
|
||||
"max_num_slots=%u\nmin_num_slots=%u\nnum_reqs=%u\n"
|
||||
"binding_q_len=%u\nsending_q_len=%u\npending_q_len=%u\n"
|
||||
"backlog_q_len=%u\nmain_xprt=%d\nsrc_port=%u\n"
|
||||
@ -147,14 +154,12 @@ static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj,
|
||||
xprt->last_used, xprt->cong, xprt->cwnd, xprt->max_reqs,
|
||||
xprt->min_reqs, xprt->num_reqs, xprt->binding.qlen,
|
||||
xprt->sending.qlen, xprt->pending.qlen,
|
||||
xprt->backlog.qlen, xprt->main,
|
||||
(xprt->xprt_class->ident == XPRT_TRANSPORT_TCP) ?
|
||||
get_srcport(xprt) : 0,
|
||||
xprt->backlog.qlen, xprt->main, srcport,
|
||||
atomic_long_read(&xprt->queuelen),
|
||||
(xprt->xprt_class->ident == XPRT_TRANSPORT_TCP) ?
|
||||
xprt->address_strings[RPC_DISPLAY_PORT] : "0");
|
||||
xprt->address_strings[RPC_DISPLAY_PORT]);
|
||||
out:
|
||||
xprt_put(xprt);
|
||||
return ret + 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj,
|
||||
@ -166,10 +171,7 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj,
|
||||
int locked, connected, connecting, close_wait, bound, binding,
|
||||
closing, congested, cwnd_wait, write_space, offline, remove;
|
||||
|
||||
if (!xprt)
|
||||
return 0;
|
||||
|
||||
if (!xprt->state) {
|
||||
if (!(xprt && xprt->state)) {
|
||||
ret = sprintf(buf, "state=CLOSED\n");
|
||||
} else {
|
||||
locked = test_bit(XPRT_LOCKED, &xprt->state);
|
||||
@ -201,7 +203,7 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj,
|
||||
}
|
||||
|
||||
xprt_put(xprt);
|
||||
return ret + 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj,
|
||||
@ -220,7 +222,7 @@ static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj,
|
||||
xprt_switch->xps_nunique_destaddr_xprts,
|
||||
atomic_long_read(&xprt_switch->xps_queuelen));
|
||||
xprt_switch_put(xprt_switch);
|
||||
return ret + 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj,
|
||||
|
@ -1354,17 +1354,6 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
|
||||
INIT_LIST_HEAD(&req->rq_xmit2);
|
||||
goto out;
|
||||
}
|
||||
} else if (RPC_IS_SWAPPER(task)) {
|
||||
list_for_each_entry(pos, &xprt->xmit_queue, rq_xmit) {
|
||||
if (pos->rq_cong || pos->rq_bytes_sent)
|
||||
continue;
|
||||
if (RPC_IS_SWAPPER(pos->rq_task))
|
||||
continue;
|
||||
/* Note: req is added _before_ pos */
|
||||
list_add_tail(&req->rq_xmit, &pos->rq_xmit);
|
||||
INIT_LIST_HEAD(&req->rq_xmit2);
|
||||
goto out;
|
||||
}
|
||||
} else if (!req->rq_seqno) {
|
||||
list_for_each_entry(pos, &xprt->xmit_queue, rq_xmit) {
|
||||
if (pos->rq_task->tk_owner != task->tk_owner)
|
||||
@ -1503,6 +1492,9 @@ bool xprt_prepare_transmit(struct rpc_task *task)
|
||||
return false;
|
||||
|
||||
}
|
||||
if (atomic_read(&xprt->swapper))
|
||||
/* This will be clear in __rpc_execute */
|
||||
current->flags |= PF_MEMALLOC;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1692,7 +1684,7 @@ static struct rpc_rqst *xprt_dynamic_alloc_slot(struct rpc_xprt *xprt)
|
||||
goto out;
|
||||
++xprt->num_reqs;
|
||||
spin_unlock(&xprt->reserve_lock);
|
||||
req = kzalloc(sizeof(struct rpc_rqst), GFP_NOFS);
|
||||
req = kzalloc(sizeof(*req), rpc_task_gfp_mask());
|
||||
spin_lock(&xprt->reserve_lock);
|
||||
if (req != NULL)
|
||||
goto out;
|
||||
@ -2112,7 +2104,14 @@ static void xprt_destroy(struct rpc_xprt *xprt)
|
||||
*/
|
||||
wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE);
|
||||
|
||||
/*
|
||||
* xprt_schedule_autodisconnect() can run after XPRT_LOCKED
|
||||
* is cleared. We use ->transport_lock to ensure the mod_timer()
|
||||
* can only run *before* del_time_sync(), never after.
|
||||
*/
|
||||
spin_lock(&xprt->transport_lock);
|
||||
del_timer_sync(&xprt->timer);
|
||||
spin_unlock(&xprt->transport_lock);
|
||||
|
||||
/*
|
||||
* Destroy sockets etc from the system workqueue so they can
|
||||
|
@ -130,7 +130,7 @@ int frwr_mr_init(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr *mr)
|
||||
if (IS_ERR(frmr))
|
||||
goto out_mr_err;
|
||||
|
||||
sg = kmalloc_array(depth, sizeof(*sg), GFP_NOFS);
|
||||
sg = kmalloc_array(depth, sizeof(*sg), GFP_KERNEL);
|
||||
if (!sg)
|
||||
goto out_list_err;
|
||||
|
||||
|
@ -235,8 +235,11 @@ xprt_rdma_connect_worker(struct work_struct *work)
|
||||
struct rpcrdma_xprt *r_xprt = container_of(work, struct rpcrdma_xprt,
|
||||
rx_connect_worker.work);
|
||||
struct rpc_xprt *xprt = &r_xprt->rx_xprt;
|
||||
unsigned int pflags = current->flags;
|
||||
int rc;
|
||||
|
||||
if (atomic_read(&xprt->swapper))
|
||||
current->flags |= PF_MEMALLOC;
|
||||
rc = rpcrdma_xprt_connect(r_xprt);
|
||||
xprt_clear_connecting(xprt);
|
||||
if (!rc) {
|
||||
@ -250,6 +253,7 @@ xprt_rdma_connect_worker(struct work_struct *work)
|
||||
rpcrdma_xprt_disconnect(r_xprt);
|
||||
xprt_unlock_connect(xprt, r_xprt);
|
||||
xprt_wake_pending_tasks(xprt, rc);
|
||||
current_restore_flags(pflags, PF_MEMALLOC);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -517,7 +521,7 @@ xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
|
||||
return;
|
||||
|
||||
out_sleep:
|
||||
task->tk_status = -EAGAIN;
|
||||
task->tk_status = -ENOMEM;
|
||||
xprt_add_backlog(xprt, task);
|
||||
}
|
||||
|
||||
@ -570,8 +574,8 @@ xprt_rdma_allocate(struct rpc_task *task)
|
||||
gfp_t flags;
|
||||
|
||||
flags = RPCRDMA_DEF_GFP;
|
||||
if (RPC_IS_SWAPPER(task))
|
||||
flags = __GFP_MEMALLOC | GFP_NOWAIT | __GFP_NOWARN;
|
||||
if (RPC_IS_ASYNC(task))
|
||||
flags = GFP_NOWAIT | __GFP_NOWARN;
|
||||
|
||||
if (!rpcrdma_check_regbuf(r_xprt, req->rl_sendbuf, rqst->rq_callsize,
|
||||
flags))
|
||||
|
@ -373,7 +373,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
|
||||
struct rpcrdma_ep *ep;
|
||||
int rc;
|
||||
|
||||
ep = kzalloc(sizeof(*ep), GFP_NOFS);
|
||||
ep = kzalloc(sizeof(*ep), GFP_KERNEL);
|
||||
if (!ep)
|
||||
return -ENOTCONN;
|
||||
ep->re_xprt = &r_xprt->rx_xprt;
|
||||
@ -746,7 +746,7 @@ rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt)
|
||||
struct rpcrdma_mr *mr;
|
||||
int rc;
|
||||
|
||||
mr = kzalloc(sizeof(*mr), GFP_NOFS);
|
||||
mr = kzalloc(sizeof(*mr), GFP_KERNEL);
|
||||
if (!mr)
|
||||
break;
|
||||
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include "sunrpc.h"
|
||||
|
||||
static void xs_close(struct rpc_xprt *xprt);
|
||||
static void xs_set_srcport(struct sock_xprt *transport, struct socket *sock);
|
||||
static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
|
||||
struct socket *sock);
|
||||
|
||||
@ -427,9 +428,9 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
|
||||
offset += want;
|
||||
}
|
||||
|
||||
want = xs_alloc_sparse_pages(buf,
|
||||
min_t(size_t, count - offset, buf->page_len),
|
||||
GFP_KERNEL);
|
||||
want = xs_alloc_sparse_pages(
|
||||
buf, min_t(size_t, count - offset, buf->page_len),
|
||||
GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
|
||||
if (seek < want) {
|
||||
ret = xs_read_bvec(sock, msg, flags, buf->bvec,
|
||||
xdr_buf_pagecount(buf),
|
||||
@ -763,12 +764,12 @@ xs_stream_start_connect(struct sock_xprt *transport)
|
||||
/**
|
||||
* xs_nospace - handle transmit was incomplete
|
||||
* @req: pointer to RPC request
|
||||
* @transport: pointer to struct sock_xprt
|
||||
*
|
||||
*/
|
||||
static int xs_nospace(struct rpc_rqst *req)
|
||||
static int xs_nospace(struct rpc_rqst *req, struct sock_xprt *transport)
|
||||
{
|
||||
struct rpc_xprt *xprt = req->rq_xprt;
|
||||
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
|
||||
struct rpc_xprt *xprt = &transport->xprt;
|
||||
struct sock *sk = transport->inet;
|
||||
int ret = -EAGAIN;
|
||||
|
||||
@ -780,24 +781,44 @@ static int xs_nospace(struct rpc_rqst *req)
|
||||
/* Don't race with disconnect */
|
||||
if (xprt_connected(xprt)) {
|
||||
/* wait for more buffer space */
|
||||
set_bit(XPRT_SOCK_NOSPACE, &transport->sock_state);
|
||||
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
|
||||
sk->sk_write_pending++;
|
||||
xprt_wait_for_buffer_space(xprt);
|
||||
} else
|
||||
ret = -ENOTCONN;
|
||||
|
||||
spin_unlock(&xprt->transport_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Race breaker in case memory is freed before above code is called */
|
||||
if (ret == -EAGAIN) {
|
||||
struct socket_wq *wq;
|
||||
static int xs_sock_nospace(struct rpc_rqst *req)
|
||||
{
|
||||
struct sock_xprt *transport =
|
||||
container_of(req->rq_xprt, struct sock_xprt, xprt);
|
||||
struct sock *sk = transport->inet;
|
||||
int ret = -EAGAIN;
|
||||
|
||||
rcu_read_lock();
|
||||
wq = rcu_dereference(sk->sk_wq);
|
||||
set_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags);
|
||||
rcu_read_unlock();
|
||||
lock_sock(sk);
|
||||
if (!sock_writeable(sk))
|
||||
ret = xs_nospace(req, transport);
|
||||
release_sock(sk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sk->sk_write_space(sk);
|
||||
}
|
||||
static int xs_stream_nospace(struct rpc_rqst *req, bool vm_wait)
|
||||
{
|
||||
struct sock_xprt *transport =
|
||||
container_of(req->rq_xprt, struct sock_xprt, xprt);
|
||||
struct sock *sk = transport->inet;
|
||||
int ret = -EAGAIN;
|
||||
|
||||
if (vm_wait)
|
||||
return -ENOBUFS;
|
||||
lock_sock(sk);
|
||||
if (!sk_stream_memory_free(sk))
|
||||
ret = xs_nospace(req, transport);
|
||||
release_sock(sk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -805,7 +826,8 @@ static void
|
||||
xs_stream_prepare_request(struct rpc_rqst *req)
|
||||
{
|
||||
xdr_free_bvec(&req->rq_rcv_buf);
|
||||
req->rq_task->tk_status = xdr_alloc_bvec(&req->rq_rcv_buf, GFP_KERNEL);
|
||||
req->rq_task->tk_status = xdr_alloc_bvec(
|
||||
&req->rq_rcv_buf, GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -851,6 +873,7 @@ static int xs_local_send_request(struct rpc_rqst *req)
|
||||
struct msghdr msg = {
|
||||
.msg_flags = XS_SENDMSG_FLAGS,
|
||||
};
|
||||
bool vm_wait;
|
||||
unsigned int sent;
|
||||
int status;
|
||||
|
||||
@ -863,15 +886,14 @@ static int xs_local_send_request(struct rpc_rqst *req)
|
||||
xs_pktdump("packet data:",
|
||||
req->rq_svec->iov_base, req->rq_svec->iov_len);
|
||||
|
||||
vm_wait = sk_stream_is_writeable(transport->inet) ? true : false;
|
||||
|
||||
req->rq_xtime = ktime_get();
|
||||
status = xprt_sock_sendmsg(transport->sock, &msg, xdr,
|
||||
transport->xmit.offset, rm, &sent);
|
||||
dprintk("RPC: %s(%u) = %d\n",
|
||||
__func__, xdr->len - transport->xmit.offset, status);
|
||||
|
||||
if (status == -EAGAIN && sock_writeable(transport->inet))
|
||||
status = -ENOBUFS;
|
||||
|
||||
if (likely(sent > 0) || status == 0) {
|
||||
transport->xmit.offset += sent;
|
||||
req->rq_bytes_sent = transport->xmit.offset;
|
||||
@ -881,13 +903,12 @@ static int xs_local_send_request(struct rpc_rqst *req)
|
||||
return 0;
|
||||
}
|
||||
status = -EAGAIN;
|
||||
vm_wait = false;
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case -ENOBUFS:
|
||||
break;
|
||||
case -EAGAIN:
|
||||
status = xs_nospace(req);
|
||||
status = xs_stream_nospace(req, vm_wait);
|
||||
break;
|
||||
default:
|
||||
dprintk("RPC: sendmsg returned unrecognized error %d\n",
|
||||
@ -963,7 +984,7 @@ process_status:
|
||||
/* Should we call xs_close() here? */
|
||||
break;
|
||||
case -EAGAIN:
|
||||
status = xs_nospace(req);
|
||||
status = xs_sock_nospace(req);
|
||||
break;
|
||||
case -ENETUNREACH:
|
||||
case -ENOBUFS:
|
||||
@ -1005,7 +1026,7 @@ static int xs_tcp_send_request(struct rpc_rqst *req)
|
||||
struct msghdr msg = {
|
||||
.msg_flags = XS_SENDMSG_FLAGS,
|
||||
};
|
||||
bool vm_wait = false;
|
||||
bool vm_wait;
|
||||
unsigned int sent;
|
||||
int status;
|
||||
|
||||
@ -1025,12 +1046,17 @@ static int xs_tcp_send_request(struct rpc_rqst *req)
|
||||
if (test_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state))
|
||||
xs_tcp_set_socket_timeouts(xprt, transport->sock);
|
||||
|
||||
xs_set_srcport(transport, transport->sock);
|
||||
|
||||
/* Continue transmitting the packet/record. We must be careful
|
||||
* to cope with writespace callbacks arriving _after_ we have
|
||||
* called sendmsg(). */
|
||||
req->rq_xtime = ktime_get();
|
||||
tcp_sock_set_cork(transport->inet, true);
|
||||
while (1) {
|
||||
|
||||
vm_wait = sk_stream_is_writeable(transport->inet) ? true : false;
|
||||
|
||||
do {
|
||||
status = xprt_sock_sendmsg(transport->sock, &msg, xdr,
|
||||
transport->xmit.offset, rm, &sent);
|
||||
|
||||
@ -1051,31 +1077,10 @@ static int xs_tcp_send_request(struct rpc_rqst *req)
|
||||
|
||||
WARN_ON_ONCE(sent == 0 && status == 0);
|
||||
|
||||
if (status == -EAGAIN ) {
|
||||
/*
|
||||
* Return EAGAIN if we're sure we're hitting the
|
||||
* socket send buffer limits.
|
||||
*/
|
||||
if (test_bit(SOCK_NOSPACE, &transport->sock->flags))
|
||||
break;
|
||||
/*
|
||||
* Did we hit a memory allocation failure?
|
||||
*/
|
||||
if (sent == 0) {
|
||||
status = -ENOBUFS;
|
||||
if (vm_wait)
|
||||
break;
|
||||
/* Retry, knowing now that we're below the
|
||||
* socket send buffer limit
|
||||
*/
|
||||
vm_wait = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (status < 0)
|
||||
break;
|
||||
vm_wait = false;
|
||||
}
|
||||
if (sent > 0)
|
||||
vm_wait = false;
|
||||
|
||||
} while (status == 0);
|
||||
|
||||
switch (status) {
|
||||
case -ENOTSOCK:
|
||||
@ -1083,7 +1088,7 @@ static int xs_tcp_send_request(struct rpc_rqst *req)
|
||||
/* Should we call xs_close() here? */
|
||||
break;
|
||||
case -EAGAIN:
|
||||
status = xs_nospace(req);
|
||||
status = xs_stream_nospace(req, vm_wait);
|
||||
break;
|
||||
case -ECONNRESET:
|
||||
case -ECONNREFUSED:
|
||||
@ -1124,6 +1129,7 @@ static void xs_sock_reset_state_flags(struct rpc_xprt *xprt)
|
||||
clear_bit(XPRT_SOCK_WAKE_ERROR, &transport->sock_state);
|
||||
clear_bit(XPRT_SOCK_WAKE_WRITE, &transport->sock_state);
|
||||
clear_bit(XPRT_SOCK_WAKE_DISCONNECT, &transport->sock_state);
|
||||
clear_bit(XPRT_SOCK_NOSPACE, &transport->sock_state);
|
||||
}
|
||||
|
||||
static void xs_run_error_worker(struct sock_xprt *transport, unsigned int nr)
|
||||
@ -1470,7 +1476,6 @@ static void xs_tcp_state_change(struct sock *sk)
|
||||
|
||||
static void xs_write_space(struct sock *sk)
|
||||
{
|
||||
struct socket_wq *wq;
|
||||
struct sock_xprt *transport;
|
||||
struct rpc_xprt *xprt;
|
||||
|
||||
@ -1481,15 +1486,10 @@ static void xs_write_space(struct sock *sk)
|
||||
if (unlikely(!(xprt = xprt_from_sock(sk))))
|
||||
return;
|
||||
transport = container_of(xprt, struct sock_xprt, xprt);
|
||||
rcu_read_lock();
|
||||
wq = rcu_dereference(sk->sk_wq);
|
||||
if (!wq || test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags) == 0)
|
||||
goto out;
|
||||
|
||||
if (!test_and_clear_bit(XPRT_SOCK_NOSPACE, &transport->sock_state))
|
||||
return;
|
||||
xs_run_error_worker(transport, XPRT_SOCK_WAKE_WRITE);
|
||||
sk->sk_write_pending--;
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1638,7 +1638,7 @@ static int xs_get_srcport(struct sock_xprt *transport)
|
||||
return port;
|
||||
}
|
||||
|
||||
unsigned short get_srcport(struct rpc_xprt *xprt)
|
||||
static unsigned short xs_sock_srcport(struct rpc_xprt *xprt)
|
||||
{
|
||||
struct sock_xprt *sock = container_of(xprt, struct sock_xprt, xprt);
|
||||
unsigned short ret = 0;
|
||||
@ -1648,7 +1648,25 @@ unsigned short get_srcport(struct rpc_xprt *xprt)
|
||||
mutex_unlock(&sock->recv_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(get_srcport);
|
||||
|
||||
static int xs_sock_srcaddr(struct rpc_xprt *xprt, char *buf, size_t buflen)
|
||||
{
|
||||
struct sock_xprt *sock = container_of(xprt, struct sock_xprt, xprt);
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_storage st;
|
||||
} saddr;
|
||||
int ret = -ENOTCONN;
|
||||
|
||||
mutex_lock(&sock->recv_mutex);
|
||||
if (sock->sock) {
|
||||
ret = kernel_getsockname(sock->sock, &saddr.sa);
|
||||
if (ret >= 0)
|
||||
ret = snprintf(buf, buflen, "%pISc", &saddr.sa);
|
||||
}
|
||||
mutex_unlock(&sock->recv_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned short xs_next_srcport(struct sock_xprt *transport, unsigned short port)
|
||||
{
|
||||
@ -1830,7 +1848,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,
|
||||
sk->sk_user_data = xprt;
|
||||
sk->sk_data_ready = xs_data_ready;
|
||||
sk->sk_write_space = xs_udp_write_space;
|
||||
sock_set_flag(sk, SOCK_FASYNC);
|
||||
sk->sk_error_report = xs_error_report;
|
||||
|
||||
xprt_clear_connected(xprt);
|
||||
@ -1936,9 +1953,9 @@ static void xs_local_connect(struct rpc_xprt *xprt, struct rpc_task *task)
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUNRPC_SWAP)
|
||||
/*
|
||||
* Note that this should be called with XPRT_LOCKED held (or when we otherwise
|
||||
* know that we have exclusive access to the socket), to guard against
|
||||
* races with xs_reset_transport.
|
||||
* Note that this should be called with XPRT_LOCKED held, or recv_mutex
|
||||
* held, or when we otherwise know that we have exclusive access to the
|
||||
* socket, to guard against races with xs_reset_transport.
|
||||
*/
|
||||
static void xs_set_memalloc(struct rpc_xprt *xprt)
|
||||
{
|
||||
@ -1967,13 +1984,11 @@ xs_enable_swap(struct rpc_xprt *xprt)
|
||||
{
|
||||
struct sock_xprt *xs = container_of(xprt, struct sock_xprt, xprt);
|
||||
|
||||
if (atomic_inc_return(&xprt->swapper) != 1)
|
||||
return 0;
|
||||
if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE))
|
||||
return -ERESTARTSYS;
|
||||
if (xs->inet)
|
||||
mutex_lock(&xs->recv_mutex);
|
||||
if (atomic_inc_return(&xprt->swapper) == 1 &&
|
||||
xs->inet)
|
||||
sk_set_memalloc(xs->inet);
|
||||
xprt_release_xprt(xprt, NULL);
|
||||
mutex_unlock(&xs->recv_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1989,13 +2004,11 @@ xs_disable_swap(struct rpc_xprt *xprt)
|
||||
{
|
||||
struct sock_xprt *xs = container_of(xprt, struct sock_xprt, xprt);
|
||||
|
||||
if (!atomic_dec_and_test(&xprt->swapper))
|
||||
return;
|
||||
if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE))
|
||||
return;
|
||||
if (xs->inet)
|
||||
mutex_lock(&xs->recv_mutex);
|
||||
if (atomic_dec_and_test(&xprt->swapper) &&
|
||||
xs->inet)
|
||||
sk_clear_memalloc(xs->inet);
|
||||
xprt_release_xprt(xprt, NULL);
|
||||
mutex_unlock(&xs->recv_mutex);
|
||||
}
|
||||
#else
|
||||
static void xs_set_memalloc(struct rpc_xprt *xprt)
|
||||
@ -2028,7 +2041,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
|
||||
sk->sk_user_data = xprt;
|
||||
sk->sk_data_ready = xs_data_ready;
|
||||
sk->sk_write_space = xs_udp_write_space;
|
||||
sock_set_flag(sk, SOCK_FASYNC);
|
||||
|
||||
xprt_set_connected(xprt);
|
||||
|
||||
@ -2052,7 +2064,10 @@ static void xs_udp_setup_socket(struct work_struct *work)
|
||||
struct rpc_xprt *xprt = &transport->xprt;
|
||||
struct socket *sock;
|
||||
int status = -EIO;
|
||||
unsigned int pflags = current->flags;
|
||||
|
||||
if (atomic_read(&xprt->swapper))
|
||||
current->flags |= PF_MEMALLOC;
|
||||
sock = xs_create_sock(xprt, transport,
|
||||
xs_addr(xprt)->sa_family, SOCK_DGRAM,
|
||||
IPPROTO_UDP, false);
|
||||
@ -2072,6 +2087,7 @@ out:
|
||||
xprt_clear_connecting(xprt);
|
||||
xprt_unlock_connect(xprt, transport);
|
||||
xprt_wake_pending_tasks(xprt, status);
|
||||
current_restore_flags(pflags, PF_MEMALLOC);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2191,7 +2207,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
|
||||
sk->sk_data_ready = xs_data_ready;
|
||||
sk->sk_state_change = xs_tcp_state_change;
|
||||
sk->sk_write_space = xs_tcp_write_space;
|
||||
sock_set_flag(sk, SOCK_FASYNC);
|
||||
sk->sk_error_report = xs_error_report;
|
||||
|
||||
/* socket options */
|
||||
@ -2231,11 +2246,19 @@ static void xs_tcp_setup_socket(struct work_struct *work)
|
||||
struct socket *sock = transport->sock;
|
||||
struct rpc_xprt *xprt = &transport->xprt;
|
||||
int status;
|
||||
unsigned int pflags = current->flags;
|
||||
|
||||
if (!sock) {
|
||||
sock = xs_create_sock(xprt, transport,
|
||||
xs_addr(xprt)->sa_family, SOCK_STREAM,
|
||||
IPPROTO_TCP, true);
|
||||
if (atomic_read(&xprt->swapper))
|
||||
current->flags |= PF_MEMALLOC;
|
||||
|
||||
if (xprt_connected(xprt))
|
||||
goto out;
|
||||
if (test_and_clear_bit(XPRT_SOCK_CONNECT_SENT,
|
||||
&transport->sock_state) ||
|
||||
!sock) {
|
||||
xs_reset_transport(transport);
|
||||
sock = xs_create_sock(xprt, transport, xs_addr(xprt)->sa_family,
|
||||
SOCK_STREAM, IPPROTO_TCP, true);
|
||||
if (IS_ERR(sock)) {
|
||||
xprt_wake_pending_tasks(xprt, PTR_ERR(sock));
|
||||
goto out;
|
||||
@ -2255,10 +2278,9 @@ static void xs_tcp_setup_socket(struct work_struct *work)
|
||||
sock->sk->sk_state);
|
||||
switch (status) {
|
||||
case 0:
|
||||
xs_set_srcport(transport, sock);
|
||||
fallthrough;
|
||||
case -EINPROGRESS:
|
||||
/* SYN_SENT! */
|
||||
set_bit(XPRT_SOCK_CONNECT_SENT, &transport->sock_state);
|
||||
if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
|
||||
xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
|
||||
fallthrough;
|
||||
@ -2296,6 +2318,7 @@ out:
|
||||
xprt_clear_connecting(xprt);
|
||||
out_unlock:
|
||||
xprt_unlock_connect(xprt, transport);
|
||||
current_restore_flags(pflags, PF_MEMALLOC);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2319,13 +2342,9 @@ static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
|
||||
|
||||
WARN_ON_ONCE(!xprt_lock_connect(xprt, task, transport));
|
||||
|
||||
if (transport->sock != NULL && !xprt_connecting(xprt)) {
|
||||
if (transport->sock != NULL) {
|
||||
dprintk("RPC: xs_connect delayed xprt %p for %lu "
|
||||
"seconds\n",
|
||||
xprt, xprt->reestablish_timeout / HZ);
|
||||
|
||||
/* Start by resetting any existing state */
|
||||
xs_reset_transport(transport);
|
||||
"seconds\n", xprt, xprt->reestablish_timeout / HZ);
|
||||
|
||||
delay = xprt_reconnect_delay(xprt);
|
||||
xprt_reconnect_backoff(xprt, XS_TCP_INIT_REEST_TO);
|
||||
@ -2487,7 +2506,7 @@ static int bc_malloc(struct rpc_task *task)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
page = alloc_page(GFP_KERNEL);
|
||||
page = alloc_page(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -2621,6 +2640,8 @@ static const struct rpc_xprt_ops xs_udp_ops = {
|
||||
.rpcbind = rpcb_getport_async,
|
||||
.set_port = xs_set_port,
|
||||
.connect = xs_connect,
|
||||
.get_srcaddr = xs_sock_srcaddr,
|
||||
.get_srcport = xs_sock_srcport,
|
||||
.buf_alloc = rpc_malloc,
|
||||
.buf_free = rpc_free,
|
||||
.send_request = xs_udp_send_request,
|
||||
@ -2643,6 +2664,8 @@ static const struct rpc_xprt_ops xs_tcp_ops = {
|
||||
.rpcbind = rpcb_getport_async,
|
||||
.set_port = xs_set_port,
|
||||
.connect = xs_connect,
|
||||
.get_srcaddr = xs_sock_srcaddr,
|
||||
.get_srcport = xs_sock_srcport,
|
||||
.buf_alloc = rpc_malloc,
|
||||
.buf_free = rpc_free,
|
||||
.prepare_request = xs_stream_prepare_request,
|
||||
|
Loading…
Reference in New Issue
Block a user