f7e33bdbd6
We added CONFIG_MANDATORY_FILE_LOCKING in 2015, and soon after turned it off in Fedora and RHEL8. Several other distros have followed suit. I've heard of one problem in all that time: Someone migrated from an older distro that supported "-o mand" to one that didn't, and the host had a fstab entry with "mand" in it which broke on reboot. They didn't actually _use_ mandatory locking so they just removed the mount option and moved on. This patch rips out mandatory locking support wholesale from the kernel, along with the Kconfig option and the Documentation file. It also changes the mount code to ignore the "mand" mount option instead of erroring out, and to throw a big, ugly warning. Signed-off-by: Jeff Layton <jlayton@kernel.org>
125 lines
2.6 KiB
C
125 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* locks.c
|
|
*
|
|
* Userspace file locking support
|
|
*
|
|
* Copyright (C) 2007 Oracle. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/fs.h>
|
|
#include <linux/fcntl.h>
|
|
|
|
#include <cluster/masklog.h>
|
|
|
|
#include "ocfs2.h"
|
|
|
|
#include "dlmglue.h"
|
|
#include "file.h"
|
|
#include "inode.h"
|
|
#include "locks.h"
|
|
|
|
static int ocfs2_do_flock(struct file *file, struct inode *inode,
|
|
int cmd, struct file_lock *fl)
|
|
{
|
|
int ret = 0, level = 0, trylock = 0;
|
|
struct ocfs2_file_private *fp = file->private_data;
|
|
struct ocfs2_lock_res *lockres = &fp->fp_flock;
|
|
|
|
if (fl->fl_type == F_WRLCK)
|
|
level = 1;
|
|
if (!IS_SETLKW(cmd))
|
|
trylock = 1;
|
|
|
|
mutex_lock(&fp->fp_mutex);
|
|
|
|
if (lockres->l_flags & OCFS2_LOCK_ATTACHED &&
|
|
lockres->l_level > LKM_NLMODE) {
|
|
int old_level = 0;
|
|
struct file_lock request;
|
|
|
|
if (lockres->l_level == LKM_EXMODE)
|
|
old_level = 1;
|
|
|
|
if (level == old_level)
|
|
goto out;
|
|
|
|
/*
|
|
* Converting an existing lock is not guaranteed to be
|
|
* atomic, so we can get away with simply unlocking
|
|
* here and allowing the lock code to try at the new
|
|
* level.
|
|
*/
|
|
|
|
locks_init_lock(&request);
|
|
request.fl_type = F_UNLCK;
|
|
request.fl_flags = FL_FLOCK;
|
|
locks_lock_file_wait(file, &request);
|
|
|
|
ocfs2_file_unlock(file);
|
|
}
|
|
|
|
ret = ocfs2_file_lock(file, level, trylock);
|
|
if (ret) {
|
|
if (ret == -EAGAIN && trylock)
|
|
ret = -EWOULDBLOCK;
|
|
else
|
|
mlog_errno(ret);
|
|
goto out;
|
|
}
|
|
|
|
ret = locks_lock_file_wait(file, fl);
|
|
if (ret)
|
|
ocfs2_file_unlock(file);
|
|
|
|
out:
|
|
mutex_unlock(&fp->fp_mutex);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int ocfs2_do_funlock(struct file *file, int cmd, struct file_lock *fl)
|
|
{
|
|
int ret;
|
|
struct ocfs2_file_private *fp = file->private_data;
|
|
|
|
mutex_lock(&fp->fp_mutex);
|
|
ocfs2_file_unlock(file);
|
|
ret = locks_lock_file_wait(file, fl);
|
|
mutex_unlock(&fp->fp_mutex);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Overall flow of ocfs2_flock() was influenced by gfs2_flock().
|
|
*/
|
|
int ocfs2_flock(struct file *file, int cmd, struct file_lock *fl)
|
|
{
|
|
struct inode *inode = file->f_mapping->host;
|
|
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
|
|
|
if (!(fl->fl_flags & FL_FLOCK))
|
|
return -ENOLCK;
|
|
|
|
if ((osb->s_mount_opt & OCFS2_MOUNT_LOCALFLOCKS) ||
|
|
ocfs2_mount_local(osb))
|
|
return locks_lock_file_wait(file, fl);
|
|
|
|
if (fl->fl_type == F_UNLCK)
|
|
return ocfs2_do_funlock(file, cmd, fl);
|
|
else
|
|
return ocfs2_do_flock(file, inode, cmd, fl);
|
|
}
|
|
|
|
int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl)
|
|
{
|
|
struct inode *inode = file->f_mapping->host;
|
|
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
|
|
|
if (!(fl->fl_flags & FL_POSIX))
|
|
return -ENOLCK;
|
|
|
|
return ocfs2_plock(osb->cconn, OCFS2_I(inode)->ip_blkno, file, cmd, fl);
|
|
}
|