Skip to content

Commit

Permalink
NFS: Allow signal interruption of NFS4ERR_DELAYed operations
Browse files Browse the repository at this point in the history
If the server is unable to immediately execute an RPC call, and returns
an NFS4ERR_DELAY then we can assume it is safe to interrupt the operation
in order to handle ordinary signals. This allows the application to
service timer interrupts that would otherwise have to wait until the
server is again able to respond.

Signed-off-by: Trond Myklebust <[email protected]>
Signed-off-by: Anna Schumaker <[email protected]>
  • Loading branch information
trondmy authored and amschuma-ntap committed Apr 25, 2019
1 parent 33344e0 commit 0688e64
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 34 deletions.
1 change: 1 addition & 0 deletions fs/nfs/nfs4_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ struct nfs4_exception {
unsigned char delay : 1,
recovering : 1,
retry : 1;
bool interruptible;
};

struct nfs4_state_recovery_ops {
Expand Down
139 changes: 105 additions & 34 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,17 +400,32 @@ static long nfs4_update_delay(long *timeout)
return ret;
}

static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
static int nfs4_delay_killable(long *timeout)
{
int res = 0;

might_sleep();

freezable_schedule_timeout_killable_unsafe(
nfs4_update_delay(timeout));
if (fatal_signal_pending(current))
res = -ERESTARTSYS;
return res;
if (!__fatal_signal_pending(current))
return 0;
return -EINTR;
}

static int nfs4_delay_interruptible(long *timeout)
{
might_sleep();

freezable_schedule_timeout_interruptible(nfs4_update_delay(timeout));
if (!signal_pending(current))
return 0;
return __fatal_signal_pending(current) ? -EINTR :-ERESTARTSYS;
}

static int nfs4_delay(long *timeout, bool interruptible)
{
if (interruptible)
return nfs4_delay_interruptible(timeout);
return nfs4_delay_killable(timeout);
}

/* This is the error handling routine for processes that are allowed
Expand Down Expand Up @@ -546,7 +561,8 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_

ret = nfs4_do_handle_exception(server, errorcode, exception);
if (exception->delay) {
ret = nfs4_delay(server->client, &exception->timeout);
ret = nfs4_delay(&exception->timeout,
exception->interruptible);
goto out_retry;
}
if (exception->recovering) {
Expand Down Expand Up @@ -3066,7 +3082,9 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
int *opened)
{
struct nfs_server *server = NFS_SERVER(dir);
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
struct nfs4_state *res;
struct nfs4_open_createattrs c = {
.label = label,
Expand Down Expand Up @@ -3679,7 +3697,9 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f

int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = nfs4_handle_exception(server,
Expand Down Expand Up @@ -3721,7 +3741,9 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *info)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = _nfs4_lookup_root(server, fhandle, info);
Expand Down Expand Up @@ -3948,7 +3970,9 @@ static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr, struct nfs4_label *label,
struct inode *inode)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = _nfs4_proc_getattr(server, fhandle, fattr, label, inode);
Expand Down Expand Up @@ -4071,7 +4095,9 @@ static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir,
const struct qstr *name, struct nfs_fh *fhandle,
struct nfs_fattr *fattr, struct nfs4_label *label)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
struct rpc_clnt *client = *clnt;
int err;
do {
Expand Down Expand Up @@ -4175,7 +4201,9 @@ static int _nfs4_proc_lookupp(struct inode *inode,
static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle,
struct nfs_fattr *fattr, struct nfs4_label *label)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = _nfs4_proc_lookupp(inode, fhandle, fattr, label);
Expand Down Expand Up @@ -4222,7 +4250,9 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry

static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = _nfs4_proc_access(inode, entry);
Expand Down Expand Up @@ -4277,7 +4307,9 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
static int nfs4_proc_readlink(struct inode *inode, struct page *page,
unsigned int pgbase, unsigned int pglen)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = _nfs4_proc_readlink(inode, page, pgbase, pglen);
Expand Down Expand Up @@ -4353,7 +4385,9 @@ _nfs4_proc_remove(struct inode *dir, const struct qstr *name, u32 ftype)

static int nfs4_proc_remove(struct inode *dir, struct dentry *dentry)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
struct inode *inode = d_inode(dentry);
int err;

Expand All @@ -4374,7 +4408,9 @@ static int nfs4_proc_remove(struct inode *dir, struct dentry *dentry)

static int nfs4_proc_rmdir(struct inode *dir, const struct qstr *name)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;

do {
Expand Down Expand Up @@ -4533,7 +4569,9 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct

static int nfs4_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(inode),
Expand Down Expand Up @@ -4640,7 +4678,9 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
struct page *page, unsigned int len, struct iattr *sattr)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
struct nfs4_label l, *label = NULL;
int err;

Expand Down Expand Up @@ -4679,7 +4719,9 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
struct iattr *sattr)
{
struct nfs_server *server = NFS_SERVER(dir);
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
struct nfs4_label l, *label = NULL;
int err;

Expand Down Expand Up @@ -4739,7 +4781,9 @@ static int _nfs4_proc_readdir(struct dentry *dentry, const struct cred *cred,
static int nfs4_proc_readdir(struct dentry *dentry, const struct cred *cred,
u64 cookie, struct page **pages, unsigned int count, bool plus)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = _nfs4_proc_readdir(dentry, cred, cookie,
Expand Down Expand Up @@ -4790,7 +4834,9 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
struct iattr *sattr, dev_t rdev)
{
struct nfs_server *server = NFS_SERVER(dir);
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
struct nfs4_label l, *label = NULL;
int err;

Expand Down Expand Up @@ -4832,7 +4878,9 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,

static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = nfs4_handle_exception(server,
Expand Down Expand Up @@ -4863,7 +4911,9 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,

static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
unsigned long now = jiffies;
int err;

Expand Down Expand Up @@ -4925,7 +4975,9 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_pathconf *pathconf)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;

do {
Expand Down Expand Up @@ -5494,7 +5546,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu

static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
ssize_t ret;
do {
ret = __nfs4_get_acl_uncached(inode, buf, buflen);
Expand Down Expand Up @@ -5628,7 +5682,9 @@ static int _nfs4_get_security_label(struct inode *inode, void *buf,
static int nfs4_get_security_label(struct inode *inode, void *buf,
size_t buflen)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;

if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
Expand Down Expand Up @@ -6269,7 +6325,9 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock

static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;

do {
Expand Down Expand Up @@ -6833,6 +6891,7 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *
struct nfs4_exception exception = {
.state = state,
.inode = state->inode,
.interruptible = true,
};
int err;

Expand Down Expand Up @@ -7246,7 +7305,9 @@ int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
struct nfs4_fs_locations *fs_locations,
struct page *page)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = _nfs4_proc_fs_locations(client, dir, name,
Expand Down Expand Up @@ -7389,7 +7450,9 @@ int nfs4_proc_get_locations(struct inode *inode,
struct nfs_client *clp = server->nfs_client;
const struct nfs4_mig_recovery_ops *ops =
clp->cl_mvops->mig_recovery_ops;
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int status;

dprintk("%s: FSID %llx:%llx on \"%s\"\n", __func__,
Expand Down Expand Up @@ -7513,7 +7576,9 @@ int nfs4_proc_fsid_present(struct inode *inode, const struct cred *cred)
struct nfs_client *clp = server->nfs_client;
const struct nfs4_mig_recovery_ops *ops =
clp->cl_mvops->mig_recovery_ops;
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int status;

dprintk("%s: FSID %llx:%llx on \"%s\"\n", __func__,
Expand Down Expand Up @@ -7579,7 +7644,9 @@ static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct
int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name,
struct nfs4_secinfo_flavors *flavors)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = -NFS4ERR_WRONGSEC;
Expand Down Expand Up @@ -9269,7 +9336,9 @@ static int
nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
/* first try using integrity protection */
Expand Down Expand Up @@ -9436,7 +9505,9 @@ static int nfs41_test_stateid(struct nfs_server *server,
nfs4_stateid *stateid,
const struct cred *cred)
{
struct nfs4_exception exception = { };
struct nfs4_exception exception = {
.interruptible = true,
};
int err;
do {
err = _nfs41_test_stateid(server, stateid, cred);
Expand Down

0 comments on commit 0688e64

Please sign in to comment.