We don't always undo the link increases in error cases.
Added logic the undo the changes to link count if an
error occurred in those cases.
---
libdiskfs/dir-rename.c | 12 ++++++++++--
libdiskfs/dir-renamed.c | 29 +++++++++++++++++++++++++++--
2 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/libdiskfs/dir-rename.c b/libdiskfs/dir-rename.c
index c8bb0dad..7953132b 100644
--- a/libdiskfs/dir-rename.c
+++ b/libdiskfs/dir-rename.c
@@ -188,12 +188,20 @@ diskfs_S_dir_rename (struct protid *fromcred,
diskfs_node_update (tdp, 1);
pthread_mutex_unlock (&tdp->lock);
- pthread_mutex_unlock (&fnp->lock);
if (err)
{
- diskfs_nrele (fnp);
+ if (fnp->dn_stat.st_nlink > 0)
+ {
+ fnp->dn_stat.st_nlink--;
+ fnp->dn_set_ctime = 1;
+ if (diskfs_synchronous)
+ diskfs_node_update (fnp, 1);
+ }
+ diskfs_drop_dirstat (tdp, ds);
+ diskfs_nput (fnp);
return err;
}
+ pthread_mutex_unlock (&fnp->lock);
/* We now hold no locks */
diff --git a/libdiskfs/dir-renamed.c b/libdiskfs/dir-renamed.c
index 1f3f3de4..532ff998 100644
--- a/libdiskfs/dir-renamed.c
+++ b/libdiskfs/dir-renamed.c
@@ -159,6 +159,13 @@ diskfs_rename_dir (struct node *fdp, struct node *fnp,
const char *fromname,
assert_backtrace (err != ENOENT);
if (err)
{
+ if (tdp->dn_stat.st_nlink > 0)
+ {
+ tdp->dn_stat.st_nlink--;
+ tdp->dn_set_ctime = 1;
+ if (diskfs_synchronous)
+ diskfs_node_update (tdp, 1);
+ }
diskfs_drop_dirstat (fnp, tmpds);
goto out;
}
@@ -168,7 +175,16 @@ diskfs_rename_dir (struct node *fdp, struct node *fnp,
const char *fromname,
if (diskfs_synchronous)
diskfs_file_update (fnp, 1);
if (err)
- goto out;
+ {
+ if (tdp->dn_stat.st_nlink > 0)
+ {
+ tdp->dn_stat.st_nlink--;
+ tdp->dn_set_ctime = 1;
+ if (diskfs_synchronous)
+ diskfs_node_update (tdp, 1);
+ }
+ goto out;
+ }
fdp->dn_stat.st_nlink--;
fdp->dn_set_ctime = 1;
@@ -213,7 +229,16 @@ diskfs_rename_dir (struct node *fdp, struct node *fnp,
const char *fromname,
}
if (err)
- goto out;
+ {
+ if (fnp->dn_stat.st_nlink > 0)
+ {
+ fnp->dn_stat.st_nlink--;
+ fnp->dn_set_ctime = 1;
+ if (diskfs_synchronous)
+ diskfs_node_update (fnp, 1);
+ }
+ goto out;
+ }
/* 4: Remove the entry in fdp. */
ds = buf;
--
2.52.0