]> git.proxmox.com Git - mirror_zfs.git/commitdiff
FreeBSD: Add zfs_link_create() error handling master
authorAlexander Motin <mav@FreeBSD.org>
Fri, 17 May 2024 00:56:55 +0000 (20:56 -0400)
committerGitHub <noreply@github.com>
Fri, 17 May 2024 00:56:55 +0000 (17:56 -0700)
Originally Solaris didn't expect errors there, but they may happen
if we fail to add entry into ZAP.  Linux fixed it in #7421, but it
was never fully ported to FreeBSD.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Alexander Motin <mav@FreeBSD.org>
Sponsored-By: iXsystems, Inc.
Closes #13215
Closes #16138

module/os/freebsd/zfs/zfs_dir.c
module/os/freebsd/zfs/zfs_vnops_os.c
module/os/freebsd/zfs/zfs_znode.c
tests/test-runner/bin/zts-report.py.in

index 948df8e50de11a521a210af8a888e942a577e8d5..3cdb94d6cd53adc5c07ca9d821c57d0031e9ce3d 100644 (file)
@@ -543,6 +543,7 @@ zfs_rmnode(znode_t *zp)
        dataset_kstats_update_nunlinked_kstat(&zfsvfs->z_kstat, 1);
 
        zfs_znode_delete(zp, tx);
+       zfs_znode_free(zp);
 
        dmu_tx_commit(tx);
 
index d9a8c8a0d7699ce9e3ee240380024168746657c3..b9b332434bd2d9a23c618459786a870ebadef7f0 100644 (file)
@@ -1175,10 +1175,25 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
                return (error);
        }
        zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids);
+
+       error = zfs_link_create(dzp, name, zp, tx, ZNEW);
+       if (error != 0) {
+               /*
+                * Since, we failed to add the directory entry for it,
+                * delete the newly created dnode.
+                */
+               zfs_znode_delete(zp, tx);
+               VOP_UNLOCK1(ZTOV(zp));
+               zrele(zp);
+               zfs_acl_ids_free(&acl_ids);
+               dmu_tx_commit(tx);
+               getnewvnode_drop_reserve();
+               goto out;
+       }
+
        if (fuid_dirtied)
                zfs_fuid_sync(zfsvfs, tx);
 
-       (void) zfs_link_create(dzp, name, zp, tx, ZNEW);
        txtype = zfs_log_create_txtype(Z_FILE, vsecp, vap);
        zfs_log_create(zilog, tx, txtype, dzp, zp, name,
            vsecp, acl_ids.z_fuidp, vap);
@@ -1526,13 +1541,19 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
         */
        zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids);
 
-       if (fuid_dirtied)
-               zfs_fuid_sync(zfsvfs, tx);
-
        /*
         * Now put new name in parent dir.
         */
-       (void) zfs_link_create(dzp, dirname, zp, tx, ZNEW);
+       error = zfs_link_create(dzp, dirname, zp, tx, ZNEW);
+       if (error != 0) {
+               zfs_znode_delete(zp, tx);
+               VOP_UNLOCK1(ZTOV(zp));
+               zrele(zp);
+               goto out;
+       }
+
+       if (fuid_dirtied)
+               zfs_fuid_sync(zfsvfs, tx);
 
        *zpp = zp;
 
@@ -1540,6 +1561,7 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
        zfs_log_create(zilog, tx, txtype, dzp, zp, dirname, NULL,
            acl_ids.z_fuidp, vap);
 
+out:
        zfs_acl_ids_free(&acl_ids);
 
        dmu_tx_commit(tx);
@@ -1550,7 +1572,7 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
                zil_commit(zilog, 0);
 
        zfs_exit(zfsvfs, FTAG);
-       return (0);
+       return (error);
 }
 
 #if    __FreeBSD_version < 1300124
@@ -3586,10 +3608,14 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
        /*
         * Insert the new object into the directory.
         */
-       (void) zfs_link_create(dzp, name, zp, tx, ZNEW);
-
-       zfs_log_symlink(zilog, tx, txtype, dzp, zp, name, link);
-       *zpp = zp;
+       error = zfs_link_create(dzp, name, zp, tx, ZNEW);
+       if (error != 0) {
+               zfs_znode_delete(zp, tx);
+               VOP_UNLOCK1(ZTOV(zp));
+               zrele(zp);
+       } else {
+               zfs_log_symlink(zilog, tx, txtype, dzp, zp, name, link);
+       }
 
        zfs_acl_ids_free(&acl_ids);
 
@@ -3597,8 +3623,12 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
 
        getnewvnode_drop_reserve();
 
-       if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
-               zil_commit(zilog, 0);
+       if (error == 0) {
+               *zpp = zp;
+
+               if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+                       zil_commit(zilog, 0);
+       }
 
        zfs_exit(zfsvfs, FTAG);
        return (error);
index 0d4c94555c6b3b17e486c5fbc3d6f2ae42d78c24..0eea2a849416d7bbcbba1423029c1b73adf395cb 100644 (file)
@@ -1234,7 +1234,6 @@ zfs_znode_delete(znode_t *zp, dmu_tx_t *tx)
        VERIFY0(dmu_object_free(os, obj, tx));
        zfs_znode_dmu_fini(zp);
        ZFS_OBJ_HOLD_EXIT(zfsvfs, obj);
-       zfs_znode_free(zp);
 }
 
 void
index ecc50f4871526848c0eeb820f361bf6d95c8c696..5ca130931364063031dcea9b3cb845728fb65ad5 100755 (executable)
@@ -182,7 +182,6 @@ if sys.platform.startswith('freebsd'):
         'cli_root/zfs_unshare/zfs_unshare_008_pos': ['SKIP', na_reason],
         'cp_files/cp_files_002_pos': ['SKIP', na_reason],
         'link_count/link_count_001': ['SKIP', na_reason],
-        'casenorm/mixed_create_failure': ['FAIL', 13215],
         'mmap/mmap_sync_001_pos': ['SKIP', na_reason],
         'rsend/send_raw_ashift': ['SKIP', 14961],
     })