For a CB_NOTIFY operation, we need to stop processing the callback
if an allocation fails. Change the ->prepare callback operation to
return true if processing should continue, and false otherwise.

Signed-off-by: Jeff Layton <[email protected]>
---
 fs/nfsd/nfs4callback.c | 5 ++++-
 fs/nfsd/nfs4layouts.c  | 3 ++-
 fs/nfsd/nfs4state.c    | 6 ++++--
 fs/nfsd/state.h        | 6 +++---
 4 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 50827405468d..25bbf5b8814d 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -1715,7 +1715,10 @@ nfsd4_run_cb_work(struct work_struct *work)
 
        if (!test_and_clear_bit(NFSD4_CALLBACK_REQUEUE, &cb->cb_flags)) {
                if (cb->cb_ops && cb->cb_ops->prepare)
-                       cb->cb_ops->prepare(cb);
+                       if (!cb->cb_ops->prepare(cb)) {
+                               nfsd41_destroy_cb(cb);
+                               return;
+                       }
        }
 
        cb->cb_msg.rpc_cred = clp->cl_cb_cred;
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c
index c550b83f4432..8974e3d85d75 100644
--- a/fs/nfsd/nfs4layouts.c
+++ b/fs/nfsd/nfs4layouts.c
@@ -654,7 +654,7 @@ nfsd4_cb_layout_fail(struct nfs4_layout_stateid *ls, struct 
nfsd_file *file)
        }
 }
 
-static void
+static bool
 nfsd4_cb_layout_prepare(struct nfsd4_callback *cb)
 {
        struct nfs4_layout_stateid *ls =
@@ -663,6 +663,7 @@ nfsd4_cb_layout_prepare(struct nfsd4_callback *cb)
        mutex_lock(&ls->ls_mutex);
        nfs4_inc_and_copy_stateid(&ls->ls_recall_sid, &ls->ls_stid);
        mutex_unlock(&ls->ls_mutex);
+       return true;
 }
 
 static int
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6adce94e9fdb..c0046fc3c1b1 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -357,12 +357,13 @@ remove_blocked_locks(struct nfs4_lockowner *lo)
        }
 }
 
-static void
+static bool
 nfsd4_cb_notify_lock_prepare(struct nfsd4_callback *cb)
 {
        struct nfsd4_blocked_lock       *nbl = container_of(cb,
                                                struct nfsd4_blocked_lock, 
nbl_cb);
        locks_delete_block(&nbl->nbl_lock);
+       return true;
 }
 
 static int
@@ -5553,7 +5554,7 @@ bool nfsd_wait_for_delegreturn(struct svc_rqst *rqstp, 
struct inode *inode)
        return timeo > 0;
 }
 
-static void nfsd4_cb_recall_prepare(struct nfsd4_callback *cb)
+static bool nfsd4_cb_recall_prepare(struct nfsd4_callback *cb)
 {
        struct nfs4_delegation *dp = cb_to_delegation(cb);
        struct nfsd_net *nn = net_generic(dp->dl_stid.sc_client->net,
@@ -5574,6 +5575,7 @@ static void nfsd4_cb_recall_prepare(struct nfsd4_callback 
*cb)
                list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru);
        }
        spin_unlock(&nn->deleg_lock);
+       return true;
 }
 
 static int nfsd4_cb_recall_done(struct nfsd4_callback *cb,
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 811c148f36fc..7d2afe7dcc3e 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -98,9 +98,9 @@ struct nfsd4_callback {
 };
 
 struct nfsd4_callback_ops {
-       void (*prepare)(struct nfsd4_callback *);
-       int (*done)(struct nfsd4_callback *, struct rpc_task *);
-       void (*release)(struct nfsd4_callback *);
+       bool (*prepare)(struct nfsd4_callback *cb);
+       int (*done)(struct nfsd4_callback *cb, struct rpc_task *task);
+       void (*release)(struct nfsd4_callback *cb);
        uint32_t opcode;
 };
 

-- 
2.53.0


Reply via email to