linux: zfs: ctldir: set [amc]time to snapshot's creation property

If looking up a snapdir inode failed, hold pool config – hold the 
snapshot – get its creation property – release it – release it, 
then use that as the [amc]time in the allocated inode. If that 
fails then fall back to current time. No performance impact since 
this is only done when allocating a new snapdir inode.
                                                       
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #15110
Closes #15117
This commit is contained in:
наб 2023-08-01 17:50:17 +02:00 committed by Brian Behlendorf
parent b3c1807d77
commit bd1eab16eb

View File

@ -478,16 +478,18 @@ zfsctl_is_snapdir(struct inode *ip)
*/ */
static struct inode * static struct inode *
zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id, zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,
const struct file_operations *fops, const struct inode_operations *ops) const struct file_operations *fops, const struct inode_operations *ops,
uint64_t creation)
{ {
inode_timespec_t now;
struct inode *ip; struct inode *ip;
znode_t *zp; znode_t *zp;
inode_timespec_t now = {.tv_sec = creation};
ip = new_inode(zfsvfs->z_sb); ip = new_inode(zfsvfs->z_sb);
if (ip == NULL) if (ip == NULL)
return (NULL); return (NULL);
if (!creation)
now = current_time(ip); now = current_time(ip);
zp = ITOZ(ip); zp = ITOZ(ip);
ASSERT3P(zp->z_dirlocks, ==, NULL); ASSERT3P(zp->z_dirlocks, ==, NULL);
@ -552,14 +554,28 @@ zfsctl_inode_lookup(zfsvfs_t *zfsvfs, uint64_t id,
const struct file_operations *fops, const struct inode_operations *ops) const struct file_operations *fops, const struct inode_operations *ops)
{ {
struct inode *ip = NULL; struct inode *ip = NULL;
uint64_t creation = 0;
dsl_dataset_t *snap_ds;
dsl_pool_t *pool;
while (ip == NULL) { while (ip == NULL) {
ip = ilookup(zfsvfs->z_sb, (unsigned long)id); ip = ilookup(zfsvfs->z_sb, (unsigned long)id);
if (ip) if (ip)
break; break;
if (id <= ZFSCTL_INO_SNAPDIRS && !creation) {
pool = dmu_objset_pool(zfsvfs->z_os);
dsl_pool_config_enter(pool, FTAG);
if (!dsl_dataset_hold_obj(pool,
ZFSCTL_INO_SNAPDIRS - id, FTAG, &snap_ds)) {
creation = dsl_get_creation(snap_ds);
dsl_dataset_rele(snap_ds, FTAG);
}
dsl_pool_config_exit(pool, FTAG);
}
/* May fail due to concurrent zfsctl_inode_alloc() */ /* May fail due to concurrent zfsctl_inode_alloc() */
ip = zfsctl_inode_alloc(zfsvfs, id, fops, ops); ip = zfsctl_inode_alloc(zfsvfs, id, fops, ops, creation);
} }
return (ip); return (ip);
@ -581,7 +597,7 @@ zfsctl_create(zfsvfs_t *zfsvfs)
ASSERT(zfsvfs->z_ctldir == NULL); ASSERT(zfsvfs->z_ctldir == NULL);
zfsvfs->z_ctldir = zfsctl_inode_alloc(zfsvfs, ZFSCTL_INO_ROOT, zfsvfs->z_ctldir = zfsctl_inode_alloc(zfsvfs, ZFSCTL_INO_ROOT,
&zpl_fops_root, &zpl_ops_root); &zpl_fops_root, &zpl_ops_root, 0);
if (zfsvfs->z_ctldir == NULL) if (zfsvfs->z_ctldir == NULL)
return (SET_ERROR(ENOENT)); return (SET_ERROR(ENOENT));