mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
This was done entirely with mindless brute force, using
git grep -l '\<k[vmz]*alloc_objs*(.*, GFP_KERNEL)' |
xargs sed -i 's/\(alloc_objs*(.*\), GFP_KERNEL)/\1)/'
to convert the new alloc_obj() users that had a simple GFP_KERNEL
argument to just drop that argument.
Note that due to the extreme simplicity of the scripting, any slightly
more complex cases spread over multiple lines would not be triggered:
they definitely exist, but this covers the vast bulk of the cases, and
the resulting diff is also then easier to check automatically.
For the same reason the 'flex' versions will be done as a separate
conversion.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
395 lines
11 KiB
C
395 lines
11 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#include <linux/nfs4.h>
|
|
#include <linux/nfs.h>
|
|
#include <linux/sunrpc/sched.h>
|
|
#include <linux/nfs_fs.h>
|
|
#include "internal.h"
|
|
#include "nfs4_fs.h"
|
|
#include "nfs40.h"
|
|
#include "nfs4session.h"
|
|
#include "nfs4trace.h"
|
|
|
|
static void nfs40_call_sync_prepare(struct rpc_task *task, void *calldata)
|
|
{
|
|
struct nfs4_call_sync_data *data = calldata;
|
|
nfs4_setup_sequence(data->seq_server->nfs_client,
|
|
data->seq_args, data->seq_res, task);
|
|
}
|
|
|
|
static void nfs40_call_sync_done(struct rpc_task *task, void *calldata)
|
|
{
|
|
struct nfs4_call_sync_data *data = calldata;
|
|
nfs4_sequence_done(task, data->seq_res);
|
|
}
|
|
|
|
static void nfs40_sequence_free_slot(struct nfs4_sequence_res *res)
|
|
{
|
|
struct nfs4_slot *slot = res->sr_slot;
|
|
struct nfs4_slot_table *tbl;
|
|
|
|
tbl = slot->table;
|
|
spin_lock(&tbl->slot_tbl_lock);
|
|
if (!nfs41_wake_and_assign_slot(tbl, slot))
|
|
nfs4_free_slot(tbl, slot);
|
|
spin_unlock(&tbl->slot_tbl_lock);
|
|
|
|
res->sr_slot = NULL;
|
|
}
|
|
|
|
static int nfs40_sequence_done(struct rpc_task *task,
|
|
struct nfs4_sequence_res *res)
|
|
{
|
|
if (res->sr_slot != NULL)
|
|
nfs40_sequence_free_slot(res);
|
|
return 1;
|
|
}
|
|
|
|
static void nfs40_clear_delegation_stateid(struct nfs4_state *state)
|
|
{
|
|
if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL)
|
|
nfs_finish_clear_delegation_stateid(state, NULL);
|
|
}
|
|
|
|
static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
|
|
{
|
|
/* NFSv4.0 doesn't allow for delegation recovery on open expire */
|
|
nfs40_clear_delegation_stateid(state);
|
|
nfs_state_clear_open_state_flags(state);
|
|
return nfs4_open_expired(sp, state);
|
|
}
|
|
|
|
struct nfs4_renewdata {
|
|
struct nfs_client *client;
|
|
unsigned long timestamp;
|
|
};
|
|
|
|
/*
|
|
* nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
|
|
* standalone procedure for queueing an asynchronous RENEW.
|
|
*/
|
|
static void nfs4_renew_release(void *calldata)
|
|
{
|
|
struct nfs4_renewdata *data = calldata;
|
|
struct nfs_client *clp = data->client;
|
|
|
|
if (refcount_read(&clp->cl_count) > 1)
|
|
nfs4_schedule_state_renewal(clp);
|
|
nfs_put_client(clp);
|
|
kfree(data);
|
|
}
|
|
|
|
static void nfs4_renew_done(struct rpc_task *task, void *calldata)
|
|
{
|
|
struct nfs4_renewdata *data = calldata;
|
|
struct nfs_client *clp = data->client;
|
|
unsigned long timestamp = data->timestamp;
|
|
|
|
trace_nfs4_renew_async(clp, task->tk_status);
|
|
switch (task->tk_status) {
|
|
case 0:
|
|
break;
|
|
case -NFS4ERR_LEASE_MOVED:
|
|
nfs4_schedule_lease_moved_recovery(clp);
|
|
break;
|
|
default:
|
|
/* Unless we're shutting down, schedule state recovery! */
|
|
if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0)
|
|
return;
|
|
if (task->tk_status != NFS4ERR_CB_PATH_DOWN) {
|
|
nfs4_schedule_lease_recovery(clp);
|
|
return;
|
|
}
|
|
nfs4_schedule_path_down_recovery(clp);
|
|
}
|
|
do_renew_lease(clp, timestamp);
|
|
}
|
|
|
|
static const struct rpc_call_ops nfs4_renew_ops = {
|
|
.rpc_call_done = nfs4_renew_done,
|
|
.rpc_release = nfs4_renew_release,
|
|
};
|
|
|
|
static int nfs4_proc_async_renew(struct nfs_client *clp, const struct cred *cred, unsigned renew_flags)
|
|
{
|
|
struct rpc_message msg = {
|
|
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
|
|
.rpc_argp = clp,
|
|
.rpc_cred = cred,
|
|
};
|
|
struct nfs4_renewdata *data;
|
|
|
|
if (renew_flags == 0)
|
|
return 0;
|
|
if (!refcount_inc_not_zero(&clp->cl_count))
|
|
return -EIO;
|
|
data = kmalloc_obj(*data, GFP_NOFS);
|
|
if (data == NULL) {
|
|
nfs_put_client(clp);
|
|
return -ENOMEM;
|
|
}
|
|
data->client = clp;
|
|
data->timestamp = jiffies;
|
|
return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT,
|
|
&nfs4_renew_ops, data);
|
|
}
|
|
|
|
static int nfs4_proc_renew(struct nfs_client *clp, const struct cred *cred)
|
|
{
|
|
struct rpc_message msg = {
|
|
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
|
|
.rpc_argp = clp,
|
|
.rpc_cred = cred,
|
|
};
|
|
unsigned long now = jiffies;
|
|
int status;
|
|
|
|
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
|
|
if (status < 0)
|
|
return status;
|
|
do_renew_lease(clp, now);
|
|
return 0;
|
|
}
|
|
|
|
static int nfs40_test_and_free_expired_stateid(struct nfs_server *server,
|
|
nfs4_stateid *stateid,
|
|
const struct cred *cred)
|
|
{
|
|
return -NFS4ERR_BAD_STATEID;
|
|
}
|
|
|
|
/*
|
|
* This operation also signals the server that this client is
|
|
* performing migration recovery. The server can stop returning
|
|
* NFS4ERR_LEASE_MOVED to this client. A RENEW operation is
|
|
* appended to this compound to identify the client ID which is
|
|
* performing recovery.
|
|
*/
|
|
static int _nfs40_proc_get_locations(struct nfs_server *server,
|
|
struct nfs_fh *fhandle,
|
|
struct nfs4_fs_locations *locations,
|
|
struct page *page, const struct cred *cred)
|
|
{
|
|
struct rpc_clnt *clnt = server->client;
|
|
struct nfs_client *clp = server->nfs_client;
|
|
u32 bitmask[2] = {
|
|
[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
|
|
};
|
|
struct nfs4_fs_locations_arg args = {
|
|
.clientid = clp->cl_clientid,
|
|
.fh = fhandle,
|
|
.page = page,
|
|
.bitmask = bitmask,
|
|
.migration = 1, /* skip LOOKUP */
|
|
.renew = 1, /* append RENEW */
|
|
};
|
|
struct nfs4_fs_locations_res res = {
|
|
.fs_locations = locations,
|
|
.migration = 1,
|
|
.renew = 1,
|
|
};
|
|
struct rpc_message msg = {
|
|
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
|
|
.rpc_argp = &args,
|
|
.rpc_resp = &res,
|
|
.rpc_cred = cred,
|
|
};
|
|
unsigned long now = jiffies;
|
|
int status;
|
|
|
|
nfs_fattr_init(locations->fattr);
|
|
locations->server = server;
|
|
locations->nlocations = 0;
|
|
|
|
nfs4_init_sequence(clp, &args.seq_args, &res.seq_res, 0, 1);
|
|
status = nfs4_call_sync_sequence(clnt, server, &msg,
|
|
&args.seq_args, &res.seq_res);
|
|
if (status)
|
|
return status;
|
|
|
|
renew_lease(server, now);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* This operation also signals the server that this client is
|
|
* performing "lease moved" recovery. The server can stop
|
|
* returning NFS4ERR_LEASE_MOVED to this client. A RENEW operation
|
|
* is appended to this compound to identify the client ID which is
|
|
* performing recovery.
|
|
*/
|
|
static int _nfs40_proc_fsid_present(struct inode *inode, const struct cred *cred)
|
|
{
|
|
struct nfs_server *server = NFS_SERVER(inode);
|
|
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
|
|
struct rpc_clnt *clnt = server->client;
|
|
struct nfs4_fsid_present_arg args = {
|
|
.fh = NFS_FH(inode),
|
|
.clientid = clp->cl_clientid,
|
|
.renew = 1, /* append RENEW */
|
|
};
|
|
struct nfs4_fsid_present_res res = {
|
|
.renew = 1,
|
|
};
|
|
struct rpc_message msg = {
|
|
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSID_PRESENT],
|
|
.rpc_argp = &args,
|
|
.rpc_resp = &res,
|
|
.rpc_cred = cred,
|
|
};
|
|
unsigned long now = jiffies;
|
|
int status;
|
|
|
|
res.fh = nfs_alloc_fhandle();
|
|
if (res.fh == NULL)
|
|
return -ENOMEM;
|
|
|
|
nfs4_init_sequence(clp, &args.seq_args, &res.seq_res, 0, 1);
|
|
status = nfs4_call_sync_sequence(clnt, server, &msg,
|
|
&args.seq_args, &res.seq_res);
|
|
nfs_free_fhandle(res.fh);
|
|
if (status)
|
|
return status;
|
|
|
|
do_renew_lease(clp, now);
|
|
return 0;
|
|
}
|
|
|
|
struct nfs_release_lockowner_data {
|
|
struct nfs4_lock_state *lsp;
|
|
struct nfs_server *server;
|
|
struct nfs_release_lockowner_args args;
|
|
struct nfs_release_lockowner_res res;
|
|
unsigned long timestamp;
|
|
};
|
|
|
|
static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata)
|
|
{
|
|
struct nfs_release_lockowner_data *data = calldata;
|
|
struct nfs_server *server = data->server;
|
|
nfs4_setup_sequence(server->nfs_client, &data->args.seq_args,
|
|
&data->res.seq_res, task);
|
|
data->args.lock_owner.clientid = server->nfs_client->cl_clientid;
|
|
data->timestamp = jiffies;
|
|
}
|
|
|
|
static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata)
|
|
{
|
|
struct nfs_release_lockowner_data *data = calldata;
|
|
struct nfs_server *server = data->server;
|
|
|
|
nfs40_sequence_done(task, &data->res.seq_res);
|
|
|
|
switch (task->tk_status) {
|
|
case 0:
|
|
renew_lease(server, data->timestamp);
|
|
break;
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
case -NFS4ERR_EXPIRED:
|
|
nfs4_schedule_lease_recovery(server->nfs_client);
|
|
break;
|
|
case -NFS4ERR_LEASE_MOVED:
|
|
case -NFS4ERR_DELAY:
|
|
if (nfs4_async_handle_error(task, server,
|
|
NULL, NULL) == -EAGAIN)
|
|
rpc_restart_call_prepare(task);
|
|
}
|
|
}
|
|
|
|
static void nfs4_release_lockowner_release(void *calldata)
|
|
{
|
|
struct nfs_release_lockowner_data *data = calldata;
|
|
nfs4_free_lock_state(data->server, data->lsp);
|
|
kfree(calldata);
|
|
}
|
|
|
|
static const struct rpc_call_ops nfs4_release_lockowner_ops = {
|
|
.rpc_call_prepare = nfs4_release_lockowner_prepare,
|
|
.rpc_call_done = nfs4_release_lockowner_done,
|
|
.rpc_release = nfs4_release_lockowner_release,
|
|
};
|
|
|
|
static void
|
|
nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
|
|
{
|
|
struct nfs_release_lockowner_data *data;
|
|
struct nfs_client *clp = server->nfs_client;
|
|
struct rpc_message msg = {
|
|
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RELEASE_LOCKOWNER],
|
|
};
|
|
|
|
if (clp->cl_mvops->minor_version != 0)
|
|
return;
|
|
|
|
data = kmalloc_obj(*data);
|
|
if (!data)
|
|
return;
|
|
data->lsp = lsp;
|
|
data->server = server;
|
|
data->args.lock_owner.clientid = clp->cl_clientid;
|
|
data->args.lock_owner.id = lsp->ls_seqid.owner_id;
|
|
data->args.lock_owner.s_dev = server->s_dev;
|
|
|
|
msg.rpc_argp = &data->args;
|
|
msg.rpc_resp = &data->res;
|
|
nfs4_init_sequence(clp, &data->args.seq_args, &data->res.seq_res, 0, 0);
|
|
rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data);
|
|
}
|
|
|
|
static const struct rpc_call_ops nfs40_call_sync_ops = {
|
|
.rpc_call_prepare = nfs40_call_sync_prepare,
|
|
.rpc_call_done = nfs40_call_sync_done,
|
|
};
|
|
|
|
static const struct nfs4_sequence_slot_ops nfs40_sequence_slot_ops = {
|
|
.process = nfs40_sequence_done,
|
|
.done = nfs40_sequence_done,
|
|
.free_slot = nfs40_sequence_free_slot,
|
|
};
|
|
|
|
static const struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
|
|
.owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
|
|
.state_flag_bit = NFS_STATE_RECLAIM_REBOOT,
|
|
.recover_open = nfs4_open_reclaim,
|
|
.recover_lock = nfs4_lock_reclaim,
|
|
.establish_clid = nfs4_init_clientid,
|
|
.detect_trunking = nfs40_discover_server_trunking,
|
|
};
|
|
|
|
static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
|
|
.owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
|
|
.state_flag_bit = NFS_STATE_RECLAIM_NOGRACE,
|
|
.recover_open = nfs40_open_expired,
|
|
.recover_lock = nfs4_lock_expired,
|
|
.establish_clid = nfs4_init_clientid,
|
|
};
|
|
|
|
static const struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = {
|
|
.sched_state_renewal = nfs4_proc_async_renew,
|
|
.get_state_renewal_cred = nfs4_get_renew_cred,
|
|
.renew_lease = nfs4_proc_renew,
|
|
};
|
|
|
|
static const struct nfs4_mig_recovery_ops nfs40_mig_recovery_ops = {
|
|
.get_locations = _nfs40_proc_get_locations,
|
|
.fsid_present = _nfs40_proc_fsid_present,
|
|
};
|
|
|
|
const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
|
|
.minor_version = 0,
|
|
.init_caps = NFS_CAP_READDIRPLUS
|
|
| NFS_CAP_ATOMIC_OPEN
|
|
| NFS_CAP_POSIX_LOCK,
|
|
.init_client = nfs40_init_client,
|
|
.shutdown_client = nfs40_shutdown_client,
|
|
.match_stateid = nfs4_match_stateid,
|
|
.find_root_sec = nfs4_find_root_sec,
|
|
.free_lock_state = nfs4_release_lockowner,
|
|
.test_and_free_expired = nfs40_test_and_free_expired_stateid,
|
|
.alloc_seqid = nfs_alloc_seqid,
|
|
.call_sync_ops = &nfs40_call_sync_ops,
|
|
.sequence_slot_ops = &nfs40_sequence_slot_ops,
|
|
.reboot_recovery_ops = &nfs40_reboot_recovery_ops,
|
|
.nograce_recovery_ops = &nfs40_nograce_recovery_ops,
|
|
.state_renewal_ops = &nfs40_state_renewal_ops,
|
|
.mig_recovery_ops = &nfs40_mig_recovery_ops,
|
|
};
|