mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-01-27 10:24:22 +03:00
Fix zil_commit() NULL dereference
Update the current code to ensure inodes are never dirtied if they are part of a read-only file system or snapshot. If they do somehow get dirtied an attempt will make made to write them to disk. In the case of snapshots, which don't have a ZIL, this will result in a NULL dereference in zil_commit(). Signed-off-by: Richard Yao <ryao@gentoo.org> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #2405
This commit is contained in:
parent
a5778ea242
commit
1e8db77102
@ -337,6 +337,7 @@ extern void zfs_znode_dmu_fini(znode_t *);
|
|||||||
extern int zfs_inode_alloc(struct super_block *, struct inode **ip);
|
extern int zfs_inode_alloc(struct super_block *, struct inode **ip);
|
||||||
extern void zfs_inode_destroy(struct inode *);
|
extern void zfs_inode_destroy(struct inode *);
|
||||||
extern void zfs_inode_update(znode_t *);
|
extern void zfs_inode_update(znode_t *);
|
||||||
|
extern void zfs_mark_inode_dirty(struct inode *);
|
||||||
|
|
||||||
extern void zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
|
extern void zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
|
||||||
znode_t *dzp, znode_t *zp, char *name, vsecattr_t *, zfs_fuid_info_t *,
|
znode_t *dzp, znode_t *zp, char *name, vsecattr_t *, zfs_fuid_info_t *,
|
||||||
|
@ -3965,7 +3965,8 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc)
|
|||||||
* writepages() normally handles the entire commit for
|
* writepages() normally handles the entire commit for
|
||||||
* performance reasons.
|
* performance reasons.
|
||||||
*/
|
*/
|
||||||
zil_commit(zsb->z_log, zp->z_id);
|
if (zsb->z_log != NULL)
|
||||||
|
zil_commit(zsb->z_log, zp->z_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZFS_EXIT(zsb);
|
ZFS_EXIT(zsb);
|
||||||
|
@ -511,6 +511,21 @@ zfs_inode_update(znode_t *zp)
|
|||||||
spin_unlock(&ip->i_lock);
|
spin_unlock(&ip->i_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Safely mark an inode dirty. Inodes which are part of a read-only
|
||||||
|
* file system or snapshot may not be dirtied.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
zfs_mark_inode_dirty(struct inode *ip)
|
||||||
|
{
|
||||||
|
zfs_sb_t *zsb = ITOZSB(ip);
|
||||||
|
|
||||||
|
if (zfs_is_readonly(zsb) || dmu_objset_is_snapshot(zsb->z_os))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mark_inode_dirty(ip);
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t empty_xattr;
|
static uint64_t empty_xattr;
|
||||||
static uint64_t pad[4];
|
static uint64_t pad[4];
|
||||||
static zfs_acl_phys_t acl_phys;
|
static zfs_acl_phys_t acl_phys;
|
||||||
|
@ -55,7 +55,7 @@ zpl_release(struct inode *ip, struct file *filp)
|
|||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (ITOZ(ip)->z_atime_dirty)
|
if (ITOZ(ip)->z_atime_dirty)
|
||||||
mark_inode_dirty(ip);
|
zfs_mark_inode_dirty(ip);
|
||||||
|
|
||||||
crhold(cr);
|
crhold(cr);
|
||||||
error = -zfs_close(ip, filp->f_flags, cr);
|
error = -zfs_close(ip, filp->f_flags, cr);
|
||||||
@ -445,7 +445,8 @@ zpl_writepages(struct address_space *mapping, struct writeback_control *wbc)
|
|||||||
if (sync_mode != wbc->sync_mode) {
|
if (sync_mode != wbc->sync_mode) {
|
||||||
ZFS_ENTER(zsb);
|
ZFS_ENTER(zsb);
|
||||||
ZFS_VERIFY_ZP(zp);
|
ZFS_VERIFY_ZP(zp);
|
||||||
zil_commit(zsb->z_log, zp->z_id);
|
if (zsb->z_log != NULL)
|
||||||
|
zil_commit(zsb->z_log, zp->z_id);
|
||||||
ZFS_EXIT(zsb);
|
ZFS_EXIT(zsb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -751,7 +751,7 @@ zpl_set_acl(struct inode *ip, int type, struct posix_acl *acl)
|
|||||||
if (ip->i_mode != mode) {
|
if (ip->i_mode != mode) {
|
||||||
ip->i_mode = mode;
|
ip->i_mode = mode;
|
||||||
ip->i_ctime = current_fs_time(sb);
|
ip->i_ctime = current_fs_time(sb);
|
||||||
mark_inode_dirty(ip);
|
zfs_mark_inode_dirty(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
@ -909,7 +909,7 @@ zpl_init_acl(struct inode *ip, struct inode *dir)
|
|||||||
if (!acl) {
|
if (!acl) {
|
||||||
ip->i_mode &= ~current_umask();
|
ip->i_mode &= ~current_umask();
|
||||||
ip->i_ctime = current_fs_time(ITOZSB(ip)->z_sb);
|
ip->i_ctime = current_fs_time(ITOZSB(ip)->z_sb);
|
||||||
mark_inode_dirty(ip);
|
zfs_mark_inode_dirty(ip);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -927,7 +927,7 @@ zpl_init_acl(struct inode *ip, struct inode *dir)
|
|||||||
error = __posix_acl_create(&acl, GFP_KERNEL, &mode);
|
error = __posix_acl_create(&acl, GFP_KERNEL, &mode);
|
||||||
if (error >= 0) {
|
if (error >= 0) {
|
||||||
ip->i_mode = mode;
|
ip->i_mode = mode;
|
||||||
mark_inode_dirty(ip);
|
zfs_mark_inode_dirty(ip);
|
||||||
if (error > 0)
|
if (error > 0)
|
||||||
error = zpl_set_acl(ip, ACL_TYPE_ACCESS, acl);
|
error = zpl_set_acl(ip, ACL_TYPE_ACCESS, acl);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user