Skip to content

Commit c6abce5

Browse files
adamdmosstonyhutter
authored andcommitted
Linux: always check or verify return of igrab()
zhold() wraps igrab() on Linux, and igrab() may fail when the inode is in the process of being deleted. This means zhold() must only be called when a reference exists and therefore it cannot be deleted. This is the case for all existing consumers so add a VERIFY and a comment explaining this requirement. Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Adam Moss <[email protected]> Closes openzfs#11704
1 parent 7a4b636 commit c6abce5

File tree

4 files changed

+16
-4
lines changed

4 files changed

+16
-4
lines changed

include/os/linux/zfs/sys/zfs_znode_impl.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,13 @@ extern "C" {
7373
#define zn_has_cached_data(zp) ((zp)->z_is_mapped)
7474
#define zn_rlimit_fsize(zp, uio, td) (0)
7575

76-
#define zhold(zp) igrab(ZTOI((zp)))
76+
/*
77+
* zhold() wraps igrab() on Linux, and igrab() may fail when the
78+
* inode is in the process of being deleted. As zhold() must only be
79+
* called when a ref already exists - so the inode cannot be
80+
* mid-deletion - we VERIFY() this.
81+
*/
82+
#define zhold(zp) VERIFY3P(igrab(ZTOI((zp))), !=, NULL)
7783
#define zrele(zp) iput(ZTOI((zp)))
7884

7985
/* Called on entry to each ZFS inode and vfs operation. */

module/os/linux/zfs/zfs_ctldir.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,8 @@ struct inode *
590590
zfsctl_root(znode_t *zp)
591591
{
592592
ASSERT(zfs_has_ctldir(zp));
593-
igrab(ZTOZSB(zp)->z_ctldir);
593+
/* Must have an existing ref, so igrab() cannot return NULL */
594+
VERIFY3P(igrab(ZTOZSB(zp)->z_ctldir), !=, NULL);
594595
return (ZTOZSB(zp)->z_ctldir);
595596
}
596597

module/os/linux/zfs/zfs_vfsops.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1734,7 +1734,11 @@ zfs_vget(struct super_block *sb, struct inode **ipp, fid_t *fidp)
17341734
VERIFY(zfsctl_root_lookup(*ipp, "snapshot", ipp,
17351735
0, kcred, NULL, NULL) == 0);
17361736
} else {
1737-
igrab(*ipp);
1737+
/*
1738+
* Must have an existing ref, so igrab()
1739+
* cannot return NULL
1740+
*/
1741+
VERIFY3P(igrab(*ipp), !=, NULL);
17381742
}
17391743
ZFS_EXIT(zfsvfs);
17401744
return (0);

module/os/linux/zfs/zpl_inode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,8 @@ zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
639639

640640
crhold(cr);
641641
ip->i_ctime = current_time(ip);
642-
igrab(ip); /* Use ihold() if available */
642+
/* Must have an existing ref, so igrab() cannot return NULL */
643+
VERIFY3P(igrab(ip), !=, NULL);
643644

644645
cookie = spl_fstrans_mark();
645646
error = -zfs_link(ITOZ(dir), ITOZ(ip), dname(dentry), cr, 0);

0 commit comments

Comments
 (0)