Hello,

On Sat, 7 Nov 2026 15:52:52 Samuel Thibault wrote:

> Mmm, we should probably be able to factorize iohelp_free_iouser (user);
> by having at the exit place a if (user) iohelp_free_iouser (user); and
> make the success path set user = NULL?
>
> You'll then be able to use the simple-to-read
>
> if (!err)
>     err = do_something();
>
> if (!err)
>     err = do_something();
>
> etc.
>
> if (err)
>     {
>         errno = err
>         goto out;
>     }

I think we can factor out the error-handling code in this way.
I’ve tried to make the code in libnetfs/io_duplicate.c resemble the code in
libdiskfs/io_duplicate.c.  In libdiskfs, the refcount_ref function is called
after the mutex has been locked; perhaps we should do the same in libnetfs.

Thanks,

--
Mikhail Karpov
From db323186dcda64f5cc4535b679082d88d76b9c50 Mon Sep 17 00:00:00 2001
From: Mikhail Karpov <[email protected]>
Date: Sun, 8 Nov 2026 16:20:22 +0700
Subject: [PATCH 2/2] Added checks for netfs_make_peropen and netfs_make_protid
 return value in several place

---
 libnetfs/dir-lookup.c   | 50 +++++++++++++++++++++++----------
 libnetfs/dir-mkfile.c   | 61 +++++++++++++++++++++++++----------------
 libnetfs/fsys-getroot.c | 26 +++++++++++++++---
 libnetfs/io-duplicate.c | 22 +++++++++++----
 trans/fakeroot.c        | 45 ++++++++++++++++++++----------
 5 files changed, 141 insertions(+), 63 deletions(-)

diff --git a/libnetfs/dir-lookup.c b/libnetfs/dir-lookup.c
index faace37..b59b0d7 100644
--- a/libnetfs/dir-lookup.c
+++ b/libnetfs/dir-lookup.c
@@ -47,8 +47,9 @@ netfs_S_dir_lookup (struct protid *dircred,
   char *nextname;
   char *relpath;
   error_t err;
+  struct peropen *newpo = NULL;
   struct protid *newpi = NULL;
-  struct iouser *user;
+  struct iouser *user = NULL;
 
   if (!dircred)
     return EOPNOTSUPP;
@@ -224,18 +225,22 @@ netfs_S_dir_lookup (struct protid *dircred,
 	  err = iohelp_create_empty_iouser (&user);
 	  if (! err)
 	    {
-	      newpi = netfs_make_protid (netfs_make_peropen (dnp, 0,
-							     dircred->po),
-					 user);
+	      newpo = netfs_make_peropen (dnp, 0, dircred->po);
+	      if (! newpo)
+		err = errno;
+	    }
+
+	  if (! err)
+	    {
+	      newpi = netfs_make_protid (newpo, user);
 	      if (! newpi)
-	        {
-		  err = errno;
-		  iohelp_free_iouser (user);
-		}
+		err = errno;
 	    }
 
 	  if (! err)
 	    {
+	      user = NULL;
+	      newpo = NULL;
 
 	      dirport = ports_get_send_right (newpi);
 
@@ -301,7 +306,8 @@ netfs_S_dir_lookup (struct protid *dircred,
 		    complete_path = translator_path;
 		  else
 		    {
-			err = asprintf (&complete_path, "%s/%s", dircred->po->path,
+			err = asprintf (&complete_path, "%s/%s",
+					dircred->po->path,
 					translator_path);
 			if (err == -1)
 			  {
@@ -314,7 +320,7 @@ netfs_S_dir_lookup (struct protid *dircred,
 						      complete_path,
 						      &np->transbox);
 		  if (complete_path != translator_path)
-		    free(complete_path);
+		    free (complete_path);
 		}
 
 	      goto out;
@@ -432,15 +438,23 @@ netfs_S_dir_lookup (struct protid *dircred,
   if (err)
     goto out;
 
-  newpi = netfs_make_protid (netfs_make_peropen (np, flags, dircred->po),
-			     user);
+  newpo = netfs_make_peropen (np, flags, dircred->po);
+  if (! newpo)
+    {
+      err = errno;
+      goto out;
+    }
+
+  newpi = netfs_make_protid (newpo, user);
   if (! newpi)
     {
-      iohelp_free_iouser (user);
       err = errno;
       goto out;
     }
 
+  user = NULL;
+  newpo = NULL;
+
   mach_port_t rendezvous = MACH_PORT_NULL;
   struct flock64 lock =
     {
@@ -476,8 +490,10 @@ netfs_S_dir_lookup (struct protid *dircred,
       else
 	{
 	  newpi->po->path = NULL;
-	  int err2 = asprintf (&newpi->po->path, "%s/%s", dircred->po->path, relpath);
-	  /* If asprintf fails set path to NULL so that the if below checks errno. */
+	  int err2 = asprintf (&newpi->po->path, "%s/%s",
+			       dircred->po->path, relpath);
+	  /* If asprintf fails set path to NULL so that the if below
+	     checks errno.  */
 	  if (err2 == -1)
 	    newpi->po->path = NULL;
 	}
@@ -495,6 +511,10 @@ netfs_S_dir_lookup (struct protid *dircred,
     netfs_nrele (dnp);
   if (newpi)
     ports_port_deref (newpi);
+  if (newpo)
+    netfs_release_peropen (newpo);
+  if (user)
+    iohelp_free_iouser (user);
   free (relpath);
 
   return err;
diff --git a/libnetfs/dir-mkfile.c b/libnetfs/dir-mkfile.c
index 9036101..3549951 100644
--- a/libnetfs/dir-mkfile.c
+++ b/libnetfs/dir-mkfile.c
@@ -28,36 +28,49 @@ netfs_S_dir_mkfile (struct protid *diruser, int flags, mode_t mode,
 {
   error_t err;
   struct node *np;
-  struct iouser *user;
-  struct protid *newpi;
+  struct iouser *user = NULL;
+  struct protid *newpi = NULL;
+  struct peropen *newpo = NULL;
 
   pthread_mutex_lock (&diruser->po->np->lock);
   err = netfs_attempt_mkfile (diruser->user, diruser->po->np, mode, &np);
+  if (err)
+    return err;
 
-  if (!err)
+  /* the dir is now unlocked and NP is locked */
+  flags &= ~OPENONLY_STATE_MODES;
+  err = iohelp_dup_iouser (&user, diruser->user);
+  if (err)
+    goto out;
+
+  newpo = netfs_make_peropen (np, flags, diruser->po);
+  if (!newpo)
     {
-      /* the dir is now unlocked and NP is locked */
-      flags &= ~OPENONLY_STATE_MODES;
-      err = iohelp_dup_iouser (&user, diruser->user);
-      if (! err)
-        {
-          newpi = netfs_make_protid (netfs_make_peropen (np, flags,
-							 diruser->po),
-				     user);
-	  if (newpi)
-	    {
-	      *newfile = ports_get_right (newpi);
-	      *newfiletype = MACH_MSG_TYPE_MAKE_SEND;
-	      ports_port_deref (newpi);
-	    }
-	  else
-	    {
-	      err = errno;
-	      iohelp_free_iouser (user);
-	    }
-	}
-      netfs_nput (np);
+      err = errno;
+      goto out;
+    }
+
+  newpi = netfs_make_protid (newpo, user);
+  if (!newpi)
+    {
+      err = errno;
+      goto out;
+    }
+
+  *newfile = ports_get_right (newpi);
+  *newfiletype = MACH_MSG_TYPE_MAKE_SEND;
+  ports_port_deref (newpi);
+
+ out:
+  if (err)
+    {
+      if (user)
+	iohelp_free_iouser (user);
+
+      if (newpo)
+	netfs_release_peropen (newpo);
     }
 
+  netfs_nput (np);
   return err;
 }
diff --git a/libnetfs/fsys-getroot.c b/libnetfs/fsys-getroot.c
index fb9fef1..8c70d93 100644
--- a/libnetfs/fsys-getroot.c
+++ b/libnetfs/fsys-getroot.c
@@ -42,6 +42,7 @@ netfs_S_fsys_getroot (struct netfs_control *pt,
   error_t err;
   struct protid *newpi;
   mode_t type;
+  struct peropen *newpo = NULL;
   struct peropen peropen_context =
     {
       .root_parent = dotdot,
@@ -133,9 +134,20 @@ netfs_S_fsys_getroot (struct netfs_control *pt,
 
   flags &= ~OPENONLY_STATE_MODES;
 
-  newpi = netfs_make_protid (netfs_make_peropen (netfs_root_node, flags,
-						 &peropen_context),
-			     cred);
+  newpo = netfs_make_peropen (netfs_root_node, flags, &peropen_context);
+  if (!newpo)
+    {
+      err = errno;
+      goto out;
+    }
+
+  newpi = netfs_make_protid (newpo, cred);
+  if (!newpi)
+    {
+      err = errno;
+      goto out;
+    }
+
   mach_port_deallocate (mach_task_self (), dotdot);
 
   *do_retry = FS_RETRY_NORMAL;
@@ -146,7 +158,13 @@ netfs_S_fsys_getroot (struct netfs_control *pt,
 
  out:
   if (err)
-    iohelp_free_iouser (cred);
+    {
+      iohelp_free_iouser (cred);
+
+      if (newpo)
+	netfs_release_peropen (newpo);
+    }
+
   pthread_mutex_unlock (&netfs_root_node->lock);
   return err;
 }
diff --git a/libnetfs/io-duplicate.c b/libnetfs/io-duplicate.c
index e6ac7a1..bca0949 100644
--- a/libnetfs/io-duplicate.c
+++ b/libnetfs/io-duplicate.c
@@ -34,12 +34,24 @@ netfs_S_io_duplicate (struct protid *user,
   if (err)
     return err;
   
-  refcount_ref (&user->po->refcnt);
   pthread_mutex_lock (&user->po->np->lock);
+
+  refcount_ref (&user->po->refcnt);
   newpi = netfs_make_protid (user->po, clone);
-  *newport = ports_get_right (newpi);
+  if (newpi)
+    {
+      *newport = ports_get_right (newpi);
+      *newporttp = MACH_MSG_TYPE_MAKE_SEND;
+      ports_port_deref (newpi);
+    }
+  else
+    {
+      err = errno;
+      iohelp_free_iouser (clone);
+      refcount_deref (&user->po->refcnt);
+    }
+
   pthread_mutex_unlock (&user->po->np->lock);
-  *newporttp = MACH_MSG_TYPE_MAKE_SEND;
-  ports_port_deref (newpi);
-  return 0;
+
+  return err;
 }
diff --git a/trans/fakeroot.c b/trans/fakeroot.c
index 764d6fd..c9d8eb2 100644
--- a/trans/fakeroot.c
+++ b/trans/fakeroot.c
@@ -292,8 +292,9 @@ netfs_S_dir_lookup (struct protid *diruser,
 {
   struct node *dnp, *np;
   error_t err;
+  struct peropen *newpo = NULL;
   struct protid *newpi;
-  struct iouser *user;
+  struct iouser *user = NULL;
   mach_port_t file;
   mach_port_t idport, fsidport;
   ino_t fileno;
@@ -489,24 +490,38 @@ netfs_S_dir_lookup (struct protid *diruser,
   flags &= ~(O_CREAT|O_EXCL|O_NOLINK|O_NOTRANS|O_NONBLOCK);
 
   err = iohelp_dup_iouser (&user, diruser->user);
-  if (!err)
+  if (err)
+    goto lose;
+
+  newpo = netfs_make_peropen (np, flags, diruser->po);
+  if (!newpo)
     {
-      newpi = netfs_make_protid (netfs_make_peropen (np, flags, diruser->po),
-				 user);
-      if (! newpi)
-	{
-	  iohelp_free_iouser (user);
-	  err = errno;
-	}
-      else
-	{
-	  *retry_port = ports_get_right (newpi);
-	  *retry_port_type = MACH_MSG_TYPE_MAKE_SEND;
-	  ports_port_deref (newpi);
-	}
+      err = errno;
+      goto lose;
     }
 
+  newpi = netfs_make_protid (newpo, user);
+  if (!newpi)
+    {
+      err = errno;
+      goto lose;
+    }
+
+  *retry_port = ports_get_right (newpi);
+  *retry_port_type = MACH_MSG_TYPE_MAKE_SEND;
+  ports_port_deref (newpi);
+
+
  lose:
+  if (err)
+    {
+      if (user)
+	iohelp_free_iouser (user);
+
+      if (newpo)
+	netfs_release_peropen (newpo);
+    }
+
   if (np != NULL)
     netfs_nput (np);
   return err;
-- 
2.43.0

Reply via email to