From: Ira Weiny <ira.weiny@xxxxxxxxx> Now that the taking of LONGTERM leases is in place we can now facilitate sending a SIGBUS to process if a file truncate or hole punch is performed and they do not respond by releasing the lease. The standard file lease_break_time is used to time out the LONGTERM lease which is in place on the inode. --- fs/ext4/inode.c | 4 ++++ fs/locks.c | 13 +++++++++++-- fs/xfs/xfs_file.c | 4 ++++ include/linux/fs.h | 13 +++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index b32a57bc5d5d..bee456c8c805 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4237,6 +4237,10 @@ int ext4_break_layouts(struct inode *inode) if (WARN_ON_ONCE(!rwsem_is_locked(&ei->i_mmap_sem))) return -EINVAL; + /* Break longterm leases */ + if (dax_mapping_is_dax(inode->i_mapping)) + break_longterm(inode); + do { page = dax_layout_busy_page(inode->i_mapping); if (!page) diff --git a/fs/locks.c b/fs/locks.c index 58c6d7a411b6..c77eee081d11 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1580,6 +1580,7 @@ static void time_out_leases(struct inode *inode, struct list_head *dispose) { struct file_lock_context *ctx = inode->i_flctx; struct file_lock *fl, *tmp; + struct task_struct *tsk; lockdep_assert_held(&ctx->flc_lock); @@ -1587,8 +1588,16 @@ static void time_out_leases(struct inode *inode, struct list_head *dispose) trace_time_out_leases(inode, fl); if (past_time(fl->fl_downgrade_time)) lease_modify(fl, F_RDLCK, dispose); - if (past_time(fl->fl_break_time)) - lease_modify(fl, F_UNLCK, dispose); + if (past_time(fl->fl_break_time)) { + if (fl->fl_flags & FL_LONGTERM) { + tsk = find_task_by_vpid(fl->fl_pid); + fl->fl_break_time = 1 + jiffies + lease_break_time * HZ; + lease_modify_longterm(fl, F_UNLCK, dispose); + kill_pid(tsk->thread_pid, SIGBUS, 0); + } else { + lease_modify(fl, F_UNLCK, dispose); + } + } } } diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 1f2e2845eb76..ebd310f3ae65 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -739,6 +739,10 @@ xfs_break_dax_layouts( ASSERT(xfs_isilocked(XFS_I(inode), XFS_MMAPLOCK_EXCL)); + /* Break longterm leases */ + if (dax_mapping_is_dax(inode->i_mapping)) + break_longterm(inode); + page = dax_layout_busy_page(inode->i_mapping); if (!page) return 0; diff --git a/include/linux/fs.h b/include/linux/fs.h index be2d08080aa5..0e8b21240a71 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2459,6 +2459,14 @@ static inline int break_layout(struct inode *inode, bool wait) return 0; } +static inline int break_longterm(struct inode *inode) +{ + smp_mb(); + if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease)) + return __break_lease(inode, O_WRONLY, FL_LONGTERM); + return 0; +} + #else /* !CONFIG_FILE_LOCKING */ static inline int break_lease(struct inode *inode, unsigned int mode) { @@ -2486,6 +2494,11 @@ static inline int break_layout(struct inode *inode, bool wait) return 0; } +static inline int break_longterm(struct inode *inode, bool wait) +{ + return 0; +} + #endif /* CONFIG_FILE_LOCKING */ /* fs/open.c */ -- 2.20.1