mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 13:19:56 -04:00
Merge tag 'nfs-for-7.2-2' of git://git.linux-nfs.org/projects/anna/linux-nfs
Pull NFS client fixes from Anna Schumaker:
- SUNRPC:
- Release lower rpc_clnt if killed waiting for XPRT_LOCKED
- Pin upper rpc_clnt across the TLS connect_worker
- NFS:
- Include MAY_WRITE in open permission mask for O_TRUNC
- Charge unstable writes by request size, not folio size
* tag 'nfs-for-7.2-2' of git://git.linux-nfs.org/projects/anna/linux-nfs:
NFS: Charge unstable writes by request size, not folio size
NFSv4: include MAY_WRITE in open permission mask for O_TRUNC
SUNRPC: pin upper rpc_clnt across the TLS connect_worker
SUNRPC: release lower rpc_clnt if killed waiting for XPRT_LOCKED
This commit is contained in:
@@ -3346,6 +3346,8 @@ static int nfs_open_permission_mask(int openflags)
|
||||
mask |= MAY_READ;
|
||||
if ((openflags & O_ACCMODE) != O_RDONLY)
|
||||
mask |= MAY_WRITE;
|
||||
if (openflags & O_TRUNC)
|
||||
mask |= MAY_WRITE;
|
||||
}
|
||||
|
||||
return mask;
|
||||
|
||||
@@ -851,17 +851,19 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize)
|
||||
}
|
||||
|
||||
/*
|
||||
* Record the page as unstable (an extra writeback period) and mark its
|
||||
* inode as dirty.
|
||||
* Record the request's range as unstable (an extra writeback period) and
|
||||
* mark its inode as dirty.
|
||||
*/
|
||||
static inline void nfs_folio_mark_unstable(struct folio *folio,
|
||||
static inline void nfs_folio_mark_unstable(struct nfs_page *req,
|
||||
struct nfs_commit_info *cinfo)
|
||||
{
|
||||
struct folio *folio = nfs_page_to_folio(req);
|
||||
|
||||
if (folio && !cinfo->dreq) {
|
||||
struct inode *inode = folio->mapping->host;
|
||||
long nr = folio_nr_pages(folio);
|
||||
long nr = DIV_ROUND_UP(req->wb_bytes, PAGE_SIZE);
|
||||
|
||||
/* This page is really still in write-back - just that the
|
||||
/* This range is really still in write-back - just that the
|
||||
* writeback is happening on the server now.
|
||||
*/
|
||||
node_stat_mod_folio(folio, NR_WRITEBACK, nr);
|
||||
|
||||
@@ -1199,7 +1199,7 @@ pnfs_layout_mark_request_commit(struct nfs_page *req,
|
||||
|
||||
nfs_request_add_commit_list_locked(req, list, cinfo);
|
||||
mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
|
||||
nfs_folio_mark_unstable(nfs_page_to_folio(req), cinfo);
|
||||
nfs_folio_mark_unstable(req, cinfo);
|
||||
return;
|
||||
out_resched:
|
||||
mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
|
||||
|
||||
@@ -807,7 +807,7 @@ nfs_request_add_commit_list(struct nfs_page *req, struct nfs_commit_info *cinfo)
|
||||
mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
|
||||
nfs_request_add_commit_list_locked(req, &cinfo->mds->list, cinfo);
|
||||
mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
|
||||
nfs_folio_mark_unstable(nfs_page_to_folio(req), cinfo);
|
||||
nfs_folio_mark_unstable(req, cinfo);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_request_add_commit_list);
|
||||
|
||||
@@ -866,10 +866,12 @@ nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
|
||||
nfs_request_add_commit_list(req, cinfo);
|
||||
}
|
||||
|
||||
static void nfs_folio_clear_commit(struct folio *folio)
|
||||
static void nfs_folio_clear_commit(struct nfs_page *req)
|
||||
{
|
||||
struct folio *folio = nfs_page_to_folio(req);
|
||||
|
||||
if (folio) {
|
||||
long nr = folio_nr_pages(folio);
|
||||
long nr = DIV_ROUND_UP(req->wb_bytes, PAGE_SIZE);
|
||||
|
||||
node_stat_mod_folio(folio, NR_WRITEBACK, -nr);
|
||||
bdi_wb_stat_mod(folio->mapping->host, WB_WRITEBACK, -nr);
|
||||
@@ -889,7 +891,7 @@ static void nfs_clear_request_commit(struct nfs_commit_info *cinfo,
|
||||
nfs_request_remove_commit_list(req, cinfo);
|
||||
}
|
||||
mutex_unlock(&NFS_I(inode)->commit_mutex);
|
||||
nfs_folio_clear_commit(nfs_page_to_folio(req));
|
||||
nfs_folio_clear_commit(req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1741,7 +1743,7 @@ void nfs_retry_commit(struct list_head *page_list,
|
||||
req = nfs_list_entry(page_list->next);
|
||||
nfs_list_remove_request(req);
|
||||
nfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx);
|
||||
nfs_folio_clear_commit(nfs_page_to_folio(req));
|
||||
nfs_folio_clear_commit(req);
|
||||
nfs_unlock_and_release_request(req);
|
||||
}
|
||||
}
|
||||
@@ -1813,7 +1815,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
|
||||
req = nfs_list_entry(data->pages.next);
|
||||
nfs_list_remove_request(req);
|
||||
folio = nfs_page_to_folio(req);
|
||||
nfs_folio_clear_commit(folio);
|
||||
nfs_folio_clear_commit(req);
|
||||
|
||||
dprintk("NFS: commit (%s/%llu %d@%lld)",
|
||||
nfs_req_openctx(req)->dentry->d_sb->s_id,
|
||||
|
||||
@@ -190,6 +190,7 @@ int rpc_switch_client_transport(struct rpc_clnt *,
|
||||
const struct rpc_timeout *);
|
||||
|
||||
void rpc_shutdown_client(struct rpc_clnt *);
|
||||
void rpc_hold_client(struct rpc_clnt *);
|
||||
void rpc_release_client(struct rpc_clnt *);
|
||||
void rpc_task_release_transport(struct rpc_task *);
|
||||
void rpc_task_release_client(struct rpc_task *);
|
||||
|
||||
@@ -1026,8 +1026,23 @@ rpc_free_auth(struct rpc_clnt *clnt)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release reference to the RPC client
|
||||
/**
|
||||
* rpc_hold_client - acquire a reference on an rpc_clnt
|
||||
* @clnt: rpc_clnt to pin
|
||||
*
|
||||
* Pairs with rpc_release_client().
|
||||
*/
|
||||
void rpc_hold_client(struct rpc_clnt *clnt)
|
||||
{
|
||||
refcount_inc(&clnt->cl_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpc_release_client - release a reference on an rpc_clnt
|
||||
* @clnt: rpc_clnt to release
|
||||
*
|
||||
* Pairs with rpc_hold_client(). The rpc_clnt's resources are
|
||||
* freed once its reference count drops to zero.
|
||||
*/
|
||||
void
|
||||
rpc_release_client(struct rpc_clnt *clnt)
|
||||
|
||||
@@ -2734,8 +2734,11 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
|
||||
lower_xprt = rcu_dereference(lower_clnt->cl_xprt);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (wait_on_bit_lock(&lower_xprt->state, XPRT_LOCKED, TASK_KILLABLE))
|
||||
if (wait_on_bit_lock(&lower_xprt->state, XPRT_LOCKED, TASK_KILLABLE)) {
|
||||
/* XPRT_LOCKED was never acquired. */
|
||||
rpc_shutdown_client(lower_clnt);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
status = xs_tls_handshake_sync(lower_xprt, &upper_xprt->xprtsec);
|
||||
if (status) {
|
||||
@@ -2758,6 +2761,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
|
||||
out_unlock:
|
||||
current_restore_flags(pflags, PF_MEMALLOC);
|
||||
upper_transport->clnt = NULL;
|
||||
rpc_release_client(upper_clnt);
|
||||
xprt_unlock_connect(upper_xprt, upper_transport);
|
||||
return;
|
||||
|
||||
@@ -2805,7 +2809,15 @@ static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
|
||||
} else
|
||||
dprintk("RPC: xs_connect scheduled xprt %p\n", xprt);
|
||||
|
||||
transport->clnt = task->tk_client;
|
||||
/*
|
||||
* Only the TLS connect_worker reads transport->clnt; pinning
|
||||
* the upper rpc_clnt unconditionally would form a cycle with
|
||||
* cl_xprt and prevent xprt destruction.
|
||||
*/
|
||||
if (xprt->xprtsec.policy != RPC_XPRTSEC_NONE) {
|
||||
rpc_hold_client(task->tk_client);
|
||||
transport->clnt = task->tk_client;
|
||||
}
|
||||
queue_delayed_work(xprtiod_workqueue,
|
||||
&transport->connect_worker,
|
||||
delay);
|
||||
|
||||
Reference in New Issue
Block a user