diff options
Diffstat (limited to 'fs/locks.c')
| -rw-r--r-- | fs/locks.c | 61 | 
1 files changed, 37 insertions, 24 deletions
diff --git a/fs/locks.c b/fs/locks.c index 90ec67108b22..22c5b4aa4961 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -138,6 +138,11 @@  #define IS_LEASE(fl)	(fl->fl_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT))  #define IS_OFDLCK(fl)	(fl->fl_flags & FL_OFDLCK) +static inline bool is_remote_lock(struct file *filp) +{ +	return likely(!(filp->f_path.dentry->d_sb->s_flags & MS_NOREMOTELOCK)); +} +  static bool lease_breaking(struct file_lock *fl)  {  	return fl->fl_flags & (FL_UNLOCK_PENDING | FL_DOWNGRADE_PENDING); @@ -806,7 +811,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)  {  	struct file_lock *cfl;  	struct file_lock_context *ctx; -	struct inode *inode = file_inode(filp); +	struct inode *inode = locks_inode(filp);  	ctx = smp_load_acquire(&inode->i_flctx);  	if (!ctx || list_empty_careful(&ctx->flc_posix)) { @@ -1211,7 +1216,7 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request,  int posix_lock_file(struct file *filp, struct file_lock *fl,  			struct file_lock *conflock)  { -	return posix_lock_inode(file_inode(filp), fl, conflock); +	return posix_lock_inode(locks_inode(filp), fl, conflock);  }  EXPORT_SYMBOL(posix_lock_file); @@ -1251,7 +1256,7 @@ static int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)  int locks_mandatory_locked(struct file *file)  {  	int ret; -	struct inode *inode = file_inode(file); +	struct inode *inode = locks_inode(file);  	struct file_lock_context *ctx;  	struct file_lock *fl; @@ -1564,7 +1569,7 @@ void lease_get_mtime(struct inode *inode, struct timespec *time)  	}  	if (has_lease) -		*time = current_fs_time(inode->i_sb); +		*time = current_time(inode);  	else  		*time = inode->i_mtime;  } @@ -1597,15 +1602,16 @@ EXPORT_SYMBOL(lease_get_mtime);  int fcntl_getlease(struct file *filp)  {  	struct file_lock *fl; -	struct inode *inode = file_inode(filp); +	struct inode *inode = locks_inode(filp);  	struct file_lock_context *ctx;  	int type = F_UNLCK;  	LIST_HEAD(dispose);  	ctx = smp_load_acquire(&inode->i_flctx);  	if (ctx && !list_empty_careful(&ctx->flc_lease)) { +		percpu_down_read_preempt_disable(&file_rwsem);  		spin_lock(&ctx->flc_lock); -		time_out_leases(file_inode(filp), &dispose); +		time_out_leases(inode, &dispose);  		list_for_each_entry(fl, &ctx->flc_lease, fl_list) {  			if (fl->fl_file != filp)  				continue; @@ -1613,6 +1619,8 @@ int fcntl_getlease(struct file *filp)  			break;  		}  		spin_unlock(&ctx->flc_lock); +		percpu_up_read_preempt_enable(&file_rwsem); +  		locks_dispose_list(&dispose);  	}  	return type; @@ -1638,7 +1646,8 @@ check_conflicting_open(const struct dentry *dentry, const long arg, int flags)  	if (flags & FL_LAYOUT)  		return 0; -	if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) +	if ((arg == F_RDLCK) && +	    (atomic_read(&d_real_inode(dentry)->i_writecount) > 0))  		return -EAGAIN;  	if ((arg == F_WRLCK) && ((d_count(dentry) > 1) || @@ -1653,7 +1662,7 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr  {  	struct file_lock *fl, *my_fl = NULL, *lease;  	struct dentry *dentry = filp->f_path.dentry; -	struct inode *inode = file_inode(filp); +	struct inode *inode = dentry->d_inode;  	struct file_lock_context *ctx;  	bool is_deleg = (*flp)->fl_flags & FL_DELEG;  	int error; @@ -1769,7 +1778,7 @@ static int generic_delete_lease(struct file *filp, void *owner)  {  	int error = -EAGAIN;  	struct file_lock *fl, *victim = NULL; -	struct inode *inode = file_inode(filp); +	struct inode *inode = locks_inode(filp);  	struct file_lock_context *ctx;  	LIST_HEAD(dispose); @@ -1811,7 +1820,7 @@ static int generic_delete_lease(struct file *filp, void *owner)  int generic_setlease(struct file *filp, long arg, struct file_lock **flp,  			void **priv)  { -	struct inode *inode = file_inode(filp); +	struct inode *inode = locks_inode(filp);  	int error;  	if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE)) @@ -1859,7 +1868,7 @@ EXPORT_SYMBOL(generic_setlease);  int  vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)  { -	if (filp->f_op->setlease) +	if (filp->f_op->setlease && is_remote_lock(filp))  		return filp->f_op->setlease(filp, arg, lease, priv);  	else  		return generic_setlease(filp, arg, lease, priv); @@ -2008,7 +2017,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)  	if (error)  		goto out_free; -	if (f.file->f_op->flock) +	if (f.file->f_op->flock && is_remote_lock(f.file))  		error = f.file->f_op->flock(f.file,  					  (can_sleep) ? F_SETLKW : F_SETLK,  					  lock); @@ -2034,7 +2043,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)   */  int vfs_test_lock(struct file *filp, struct file_lock *fl)  { -	if (filp->f_op->lock) +	if (filp->f_op->lock && is_remote_lock(filp))  		return filp->f_op->lock(filp, F_GETLK, fl);  	posix_test_lock(filp, fl);  	return 0; @@ -2158,7 +2167,7 @@ out:   */  int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)  { -	if (filp->f_op->lock) +	if (filp->f_op->lock && is_remote_lock(filp))  		return filp->f_op->lock(filp, cmd, fl);  	else  		return posix_lock_file(filp, fl, conf); @@ -2220,7 +2229,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,  	if (file_lock == NULL)  		return -ENOLCK; -	inode = file_inode(filp); +	inode = locks_inode(filp);  	/*  	 * This might block, so we do it before checking the inode. @@ -2372,7 +2381,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,  	if (copy_from_user(&flock, l, sizeof(flock)))  		goto out; -	inode = file_inode(filp); +	inode = locks_inode(filp);  	/* Don't allow mandatory locks on files that may be memory mapped  	 * and shared. @@ -2455,6 +2464,7 @@ out:  void locks_remove_posix(struct file *filp, fl_owner_t owner)  {  	int error; +	struct inode *inode = locks_inode(filp);  	struct file_lock lock;  	struct file_lock_context *ctx; @@ -2463,7 +2473,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)  	 * posix_lock_file().  Another process could be setting a lock on this  	 * file at the same time, but we wouldn't remove that lock anyway.  	 */ -	ctx =  smp_load_acquire(&file_inode(filp)->i_flctx); +	ctx =  smp_load_acquire(&inode->i_flctx);  	if (!ctx || list_empty(&ctx->flc_posix))  		return; @@ -2481,7 +2491,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)  	if (lock.fl_ops && lock.fl_ops->fl_release_private)  		lock.fl_ops->fl_release_private(&lock); -	trace_locks_remove_posix(file_inode(filp), &lock, error); +	trace_locks_remove_posix(inode, &lock, error);  }  EXPORT_SYMBOL(locks_remove_posix); @@ -2498,12 +2508,12 @@ locks_remove_flock(struct file *filp, struct file_lock_context *flctx)  		.fl_type = F_UNLCK,  		.fl_end = OFFSET_MAX,  	}; -	struct inode *inode = file_inode(filp); +	struct inode *inode = locks_inode(filp);  	if (list_empty(&flctx->flc_flock))  		return; -	if (filp->f_op->flock) +	if (filp->f_op->flock && is_remote_lock(filp))  		filp->f_op->flock(filp, F_SETLKW, &fl);  	else  		flock_lock_inode(inode, &fl); @@ -2522,11 +2532,14 @@ locks_remove_lease(struct file *filp, struct file_lock_context *ctx)  	if (list_empty(&ctx->flc_lease))  		return; +	percpu_down_read_preempt_disable(&file_rwsem);  	spin_lock(&ctx->flc_lock);  	list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list)  		if (filp == fl->fl_file)  			lease_modify(fl, F_UNLCK, &dispose);  	spin_unlock(&ctx->flc_lock); +	percpu_up_read_preempt_enable(&file_rwsem); +  	locks_dispose_list(&dispose);  } @@ -2537,7 +2550,7 @@ void locks_remove_file(struct file *filp)  {  	struct file_lock_context *ctx; -	ctx = smp_load_acquire(&file_inode(filp)->i_flctx); +	ctx = smp_load_acquire(&locks_inode(filp)->i_flctx);  	if (!ctx)  		return; @@ -2581,7 +2594,7 @@ EXPORT_SYMBOL(posix_unblock_lock);   */  int vfs_cancel_lock(struct file *filp, struct file_lock *fl)  { -	if (filp->f_op->lock) +	if (filp->f_op->lock && is_remote_lock(filp))  		return filp->f_op->lock(filp, F_CANCELLK, fl);  	return 0;  } @@ -2620,7 +2633,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,  		fl_pid = fl->fl_pid;  	if (fl->fl_file != NULL) -		inode = file_inode(fl->fl_file); +		inode = locks_inode(fl->fl_file);  	seq_printf(f, "%lld:%s ", id, pfx);  	if (IS_POSIX(fl)) { @@ -2726,7 +2739,7 @@ static void __show_fd_locks(struct seq_file *f,  void show_fd_locks(struct seq_file *f,  		  struct file *filp, struct files_struct *files)  { -	struct inode *inode = file_inode(filp); +	struct inode *inode = locks_inode(filp);  	struct file_lock_context *ctx;  	int id = 0;  |