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:
parent
6751634d77
commit
a21ca18d4d
|
@ -478,17 +478,19 @@ 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);
|
||||||
|
|
||||||
now = current_time(ip);
|
if (!creation)
|
||||||
|
now = current_time(ip);
|
||||||
zp = ITOZ(ip);
|
zp = ITOZ(ip);
|
||||||
ASSERT3P(zp->z_dirlocks, ==, NULL);
|
ASSERT3P(zp->z_dirlocks, ==, NULL);
|
||||||
ASSERT3P(zp->z_acl_cached, ==, NULL);
|
ASSERT3P(zp->z_acl_cached, ==, 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));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue