Skip to content

Commit d15209f

Browse files
tuxokotonyhutter
authored andcommitted
Fix zfs_get_data access to files with wrong generation
If TX_WRITE is create on a file, and the file is later deleted and a new directory is created on the same object id, it is possible that when zil_commit happens, zfs_get_data will be called on the new directory. This may result in panic as it tries to do range lock. This patch fixes this issue by record the generation number during zfs_log_write, so zfs_get_data can check if the object is valid. Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Chunwei Chen <[email protected]> Closes openzfs#10593 Closes openzfs#11682
1 parent 5649456 commit d15209f

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

module/zfs/zfs_vnops.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,8 @@ static void zfs_get_done(zgd_t *zgd, int error);
739739
* Get data to generate a TX_WRITE intent log record.
740740
*/
741741
int
742-
zfs_get_data(void *arg, lr_write_t *lr, char *buf, struct lwb *lwb, zio_t *zio)
742+
zfs_get_data(void *arg, uint64_t gen, lr_write_t *lr, char *buf,
743+
struct lwb *lwb, zio_t *zio)
743744
{
744745
zfsvfs_t *zfsvfs = arg;
745746
objset_t *os = zfsvfs->z_os;
@@ -750,6 +751,7 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, struct lwb *lwb, zio_t *zio)
750751
dmu_buf_t *db;
751752
zgd_t *zgd;
752753
int error = 0;
754+
uint64_t zp_gen;
753755

754756
ASSERT3P(lwb, !=, NULL);
755757
ASSERT3P(zio, !=, NULL);
@@ -768,6 +770,16 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, struct lwb *lwb, zio_t *zio)
768770
zfs_zrele_async(zp);
769771
return (SET_ERROR(ENOENT));
770772
}
773+
/* check if generation number matches */
774+
if (sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), &zp_gen,
775+
sizeof (zp_gen)) != 0) {
776+
zfs_zrele_async(zp);
777+
return (SET_ERROR(EIO));
778+
}
779+
if (zp_gen != gen) {
780+
zfs_zrele_async(zp);
781+
return (SET_ERROR(ENOENT));
782+
}
771783

772784
zgd = (zgd_t *)kmem_zalloc(sizeof (zgd_t), KM_SLEEP);
773785
zgd->zgd_lwb = lwb;

0 commit comments

Comments
 (0)