]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
NFS: Decrement refcounts if allocating nfs_free_stateid_data fails
authorAnna Schumaker <anna.schumaker@hammerspace.com>
Tue, 30 Jun 2026 19:39:45 +0000 (15:39 -0400)
committerAnna Schumaker <anna.schumaker@hammerspace.com>
Mon, 20 Jul 2026 15:04:04 +0000 (11:04 -0400)
I noticed that we were immediately exiting this function if the
allocation fails, leaving the client and server object refcounts bumped.
Fix this by creating a common exit point to clean up dangling
references.

Fixes: 576acc259146 ("nfs4: take a reference on the nfs_client when running FREE_STATEID")
Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
fs/nfs/nfs4proc.c

index 71b6ab863b395453f8a663d6739280db42819a32..7d98e9a98580ebde1df9c8985be89eeb0f389c22 100644 (file)
@@ -10403,21 +10403,22 @@ static int nfs41_free_stateid(struct nfs_server *server,
        struct nfs_free_stateid_data *data;
        struct rpc_task *task;
        struct nfs_client *clp = server->nfs_client;
+       int ret = -EIO;
 
        if (!refcount_inc_not_zero(&clp->cl_count))
-               return -EIO;
-       if (!nfs_sb_active(server->super)) {
-               nfs_put_client(clp);
-               return -EIO;
-       }
+               return ret;
+       if (!nfs_sb_active(server->super))
+               goto out_put_clp;
 
        nfs4_state_protect(clp, NFS_SP4_MACH_CRED_STATEID,
                &task_setup.rpc_client, &msg);
 
        dprintk("NFS call  free_stateid %p\n", stateid);
        data = kmalloc_obj(*data);
-       if (!data)
-               return -ENOMEM;
+       if (!data) {
+               ret = -ENOMEM;
+               goto out_put_server;
+       }
        data->server = server;
        nfs4_stateid_copy(&data->args.stateid, stateid);
 
@@ -10433,6 +10434,11 @@ static int nfs41_free_stateid(struct nfs_server *server,
        rpc_put_task(task);
        stateid->type = NFS4_FREED_STATEID_TYPE;
        return 0;
+out_put_server:
+       nfs_sb_deactive(server->super);
+out_put_clp:
+       nfs_put_client(clp);
+       return ret;
 }
 
 static void