On Wed, May 14, 2025 at 04:42:11PM -0700, Ackerley Tng wrote: > enum shareability { > @@ -40,6 +47,44 @@ static struct kvm_gmem_inode_private *kvm_gmem_private(struct inode *inode) > return inode->i_mapping->i_private_data; > } > > +#ifdef CONFIG_KVM_GMEM_HUGETLB > + > +static const struct guestmem_allocator_operations * > +kvm_gmem_allocator_ops(struct inode *inode) > +{ > + return kvm_gmem_private(inode)->allocator_ops; > +} > + > +static void *kvm_gmem_allocator_private(struct inode *inode) > +{ > + return kvm_gmem_private(inode)->allocator_private; > +} > + > +static bool kvm_gmem_has_custom_allocator(struct inode *inode) > +{ + if (!kvm_gmem_private(inode)) + return NULL; > + return kvm_gmem_allocator_ops(inode) != NULL; > +} > + ... > +static void kvm_gmem_evict_inode(struct inode *inode) > +{ > + truncate_inode_pages_final_prepare(inode->i_mapping); > + > + if (kvm_gmem_has_custom_allocator(inode)) { The i_private_data of the root inode in pseudo fs is NULL. Without the two lines added above, evicting the root inode during unmount will cause NULL pointer deference. > + size_t nr_pages = inode->i_size >> PAGE_SHIFT; > + > + kvm_gmem_truncate_inode_aligned_pages(inode, 0, nr_pages); > + } else { > + truncate_inode_pages(inode->i_mapping, 0); > + } > + > + clear_inode(inode); > +} > + > static const struct super_operations kvm_gmem_super_operations = { > .statfs = simple_statfs, > + .evict_inode = kvm_gmem_evict_inode, > .destroy_inode = kvm_gmem_destroy_inode, > .free_inode = kvm_gmem_free_inode, > };