Skip to content

Commit cf5c6ae

Browse files
committed
FreeBSD: Add zfs_link_create() error handling
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. Signed-off-by: Alexander Motin <[email protected]> Sponsored-By: iXsystems, Inc. Closes #13215
1 parent 21bc066 commit cf5c6ae

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

module/os/freebsd/zfs/zfs_vnops_os.c

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,10 +1175,20 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
11751175
return (error);
11761176
}
11771177
zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids);
1178+
1179+
error = zfs_link_create(dzp, name, zp, tx, ZNEW);
1180+
if (error != 0) {
1181+
VOP_UNLOCK1(ZTOV(zp));
1182+
zrele(zp);
1183+
zfs_acl_ids_free(&acl_ids);
1184+
dmu_tx_commit(tx);
1185+
getnewvnode_drop_reserve();
1186+
goto out;
1187+
}
1188+
11781189
if (fuid_dirtied)
11791190
zfs_fuid_sync(zfsvfs, tx);
11801191

1181-
(void) zfs_link_create(dzp, name, zp, tx, ZNEW);
11821192
txtype = zfs_log_create_txtype(Z_FILE, vsecp, vap);
11831193
zfs_log_create(zilog, tx, txtype, dzp, zp, name,
11841194
vsecp, acl_ids.z_fuidp, vap);
@@ -1526,20 +1536,26 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
15261536
*/
15271537
zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids);
15281538

1529-
if (fuid_dirtied)
1530-
zfs_fuid_sync(zfsvfs, tx);
1531-
15321539
/*
15331540
* Now put new name in parent dir.
15341541
*/
1535-
(void) zfs_link_create(dzp, dirname, zp, tx, ZNEW);
1542+
error = zfs_link_create(dzp, dirname, zp, tx, ZNEW);
1543+
if (error != 0) {
1544+
VOP_UNLOCK1(ZTOV(zp));
1545+
zrele(zp);
1546+
goto out;
1547+
}
1548+
1549+
if (fuid_dirtied)
1550+
zfs_fuid_sync(zfsvfs, tx);
15361551

15371552
*zpp = zp;
15381553

15391554
txtype = zfs_log_create_txtype(Z_DIR, NULL, vap);
15401555
zfs_log_create(zilog, tx, txtype, dzp, zp, dirname, NULL,
15411556
acl_ids.z_fuidp, vap);
15421557

1558+
out:
15431559
zfs_acl_ids_free(&acl_ids);
15441560

15451561
dmu_tx_commit(tx);
@@ -1550,7 +1566,7 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
15501566
zil_commit(zilog, 0);
15511567

15521568
zfs_exit(zfsvfs, FTAG);
1553-
return (0);
1569+
return (error);
15541570
}
15551571

15561572
#if __FreeBSD_version < 1300124
@@ -3586,19 +3602,26 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
35863602
/*
35873603
* Insert the new object into the directory.
35883604
*/
3589-
(void) zfs_link_create(dzp, name, zp, tx, ZNEW);
3590-
3591-
zfs_log_symlink(zilog, tx, txtype, dzp, zp, name, link);
3592-
*zpp = zp;
3605+
error = zfs_link_create(dzp, name, zp, tx, ZNEW);
3606+
if (error != 0) {
3607+
VOP_UNLOCK1(ZTOV(zp));
3608+
zrele(zp);
3609+
} else {
3610+
zfs_log_symlink(zilog, tx, txtype, dzp, zp, name, link);
3611+
}
35933612

35943613
zfs_acl_ids_free(&acl_ids);
35953614

35963615
dmu_tx_commit(tx);
35973616

35983617
getnewvnode_drop_reserve();
35993618

3600-
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
3601-
zil_commit(zilog, 0);
3619+
if (error == 0) {
3620+
*zpp = zp;
3621+
3622+
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
3623+
zil_commit(zilog, 0);
3624+
}
36023625

36033626
zfs_exit(zfsvfs, FTAG);
36043627
return (error);

tests/test-runner/bin/zts-report.py.in

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ if sys.platform.startswith('freebsd'):
182182
'cli_root/zfs_unshare/zfs_unshare_008_pos': ['SKIP', na_reason],
183183
'cp_files/cp_files_002_pos': ['SKIP', na_reason],
184184
'link_count/link_count_001': ['SKIP', na_reason],
185-
'casenorm/mixed_create_failure': ['FAIL', 13215],
186185
'mmap/mmap_sync_001_pos': ['SKIP', na_reason],
187186
'rsend/send_raw_ashift': ['SKIP', 14961],
188187
})

0 commit comments

Comments
 (0)