Set UFS/FFS file type to snapshot before changing its block pointers.

A UFS/FFS snapshot file is identified with the SF_SNAPSHOT
flag to identify it as a snapshot. This flag needs to be
set before setting some of its block pointers to the special
values BLK_SNAP and BLK_NOCOPY. If the snapshot creation fails
and we call VOP_REMOVE(), the SF_SNAPSHOT flag will let the
remove routine know that the special block pointer values need
to be rolled back before attempting deletion of the file.

Also ensure that an fsck is required after setting superblock
values in the ffs_checkcgintegrity() routine.

Reported-by:  Peter Holm
Tested-by:    Peter Holm
MFC-after:    1 week
Sponsored-by: The FreeBSD Foundation
This commit is contained in:
Kirk McKusick 2023-08-12 11:20:08 -07:00
parent b1a39c31a3
commit 220427da0e
2 changed files with 10 additions and 6 deletions

View file

@ -3130,6 +3130,7 @@ ffs_checkcgintegrity(struct fs *fs,
fs->fs_cstotal.cs_nifree -= fs->fs_cs(fs, cg).cs_nifree;
fs->fs_cs(fs, cg).cs_nifree = 0;
fs->fs_maxcluster[cg] = 0;
fs->fs_flags |= FS_NEEDSFSCK;
fs->fs_fmod = 1;
}

View file

@ -368,6 +368,15 @@ ffs_snapshot(struct mount *mp, char *snapfile)
goto out;
}
}
/*
* Change inode to snapshot type file. Before setting its block
* pointers to BLK_SNAP and BLK_NOCOPY in cgaccount, we have to
* set its type to SF_SNAPSHOT so that VOP_REMOVE will know that
* they need to be rolled back before attempting deletion.
*/
ip->i_flags |= SF_SNAPSHOT;
DIP_SET(ip, i_flags, ip->i_flags);
UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE);
/*
* Copy all the cylinder group maps. Although the
* filesystem is still active, we hope that only a few
@ -393,12 +402,6 @@ ffs_snapshot(struct mount *mp, char *snapfile)
if (error)
goto out;
}
/*
* Change inode to snapshot type file.
*/
ip->i_flags |= SF_SNAPSHOT;
DIP_SET(ip, i_flags, ip->i_flags);
UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE);
/*
* Ensure that the snapshot is completely on disk.
* Since we have marked it as a snapshot it is safe to