153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh/* -*- mode: c; c-basic-offset: 8; -*- 253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * vim: noexpandtab sw=8 ts=8 sts=0: 353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * 453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * locks.c 553fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * 653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * Userspace file locking support 753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * 853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * Copyright (C) 2007 Oracle. All rights reserved. 953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * 1053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * This program is free software; you can redistribute it and/or 1153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * modify it under the terms of the GNU General Public 1253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * License as published by the Free Software Foundation; either 1353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * version 2 of the License, or (at your option) any later version. 1453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * 1553fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * This program is distributed in the hope that it will be useful, 1653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * but WITHOUT ANY WARRANTY; without even the implied warranty of 1753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * General Public License for more details. 1953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * 2053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * You should have received a copy of the GNU General Public 2153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * License along with this program; if not, write to the 2253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 2353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * Boston, MA 021110-1307, USA. 2453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh */ 2553fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 2653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh#include <linux/fs.h> 2753da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh#include <linux/fcntl.h> 2853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 2953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh#include <cluster/masklog.h> 3053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 3153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh#include "ocfs2.h" 3253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 3353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh#include "dlmglue.h" 3453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh#include "file.h" 3553da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh#include "inode.h" 3653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh#include "locks.h" 3753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 3853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fashehstatic int ocfs2_do_flock(struct file *file, struct inode *inode, 3953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh int cmd, struct file_lock *fl) 4053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh{ 4153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh int ret = 0, level = 0, trylock = 0; 4253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh struct ocfs2_file_private *fp = file->private_data; 4353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh struct ocfs2_lock_res *lockres = &fp->fp_flock; 4453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 4553fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh if (fl->fl_type == F_WRLCK) 4653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh level = 1; 4753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh if (!IS_SETLKW(cmd)) 4853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh trylock = 1; 4953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 5053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh mutex_lock(&fp->fp_mutex); 5153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 5253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh if (lockres->l_flags & OCFS2_LOCK_ATTACHED && 5353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh lockres->l_level > LKM_NLMODE) { 5453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh int old_level = 0; 5553fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 5653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh if (lockres->l_level == LKM_EXMODE) 5753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh old_level = 1; 5853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 5953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh if (level == old_level) 6053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh goto out; 6153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 6253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh /* 6353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * Converting an existing lock is not guaranteed to be 6453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * atomic, so we can get away with simply unlocking 6553fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * here and allowing the lock code to try at the new 6653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * level. 6753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh */ 6853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 6953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh flock_lock_file_wait(file, 7053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh &(struct file_lock){.fl_type = F_UNLCK}); 7153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 7253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh ocfs2_file_unlock(file); 7353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh } 7453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 7553fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh ret = ocfs2_file_lock(file, level, trylock); 7653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh if (ret) { 7753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh if (ret == -EAGAIN && trylock) 7853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh ret = -EWOULDBLOCK; 7953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh else 8053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh mlog_errno(ret); 8153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh goto out; 8253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh } 8353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 8453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh ret = flock_lock_file_wait(file, fl); 85e228f6439862359f9b26f9d62634e4fce180b54aWengang Wang if (ret) 86e228f6439862359f9b26f9d62634e4fce180b54aWengang Wang ocfs2_file_unlock(file); 8753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 8853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fashehout: 8953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh mutex_unlock(&fp->fp_mutex); 9053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 9153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh return ret; 9253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh} 9353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 9453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fashehstatic int ocfs2_do_funlock(struct file *file, int cmd, struct file_lock *fl) 9553fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh{ 9653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh int ret; 9753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh struct ocfs2_file_private *fp = file->private_data; 9853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 9953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh mutex_lock(&fp->fp_mutex); 10053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh ocfs2_file_unlock(file); 10153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh ret = flock_lock_file_wait(file, fl); 10253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh mutex_unlock(&fp->fp_mutex); 10353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 10453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh return ret; 10553fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh} 10653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 10753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh/* 10853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh * Overall flow of ocfs2_flock() was influenced by gfs2_flock(). 10953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh */ 11053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fashehint ocfs2_flock(struct file *file, int cmd, struct file_lock *fl) 11153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh{ 11253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh struct inode *inode = file->f_mapping->host; 11353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 11453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 11553fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh if (!(fl->fl_flags & FL_FLOCK)) 11653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh return -ENOLCK; 11753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh if (__mandatory_lock(inode)) 11853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh return -ENOLCK; 11953fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 12053fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh if ((osb->s_mount_opt & OCFS2_MOUNT_LOCALFLOCKS) || 12153fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh ocfs2_mount_local(osb)) 12253fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh return flock_lock_file_wait(file, fl); 12353fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh 12453fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh if (fl->fl_type == F_UNLCK) 12553fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh return ocfs2_do_funlock(file, cmd, fl); 12653fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh else 12753fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh return ocfs2_do_flock(file, inode, cmd, fl); 12853fc622b9e829c8e632e45ef8c14f054388759c1Mark Fasheh} 12953da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh 13053da4939f349d4edd283b043219221ca5b78e4d4Mark Fashehint ocfs2_lock(struct file *file, int cmd, struct file_lock *fl) 13153da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh{ 13253da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh struct inode *inode = file->f_mapping->host; 13353da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 13453da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh 13553da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh if (!(fl->fl_flags & FL_POSIX)) 13653da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh return -ENOLCK; 137ee860b6a650360c91f5d5f9a94262aad9be90015Sachin Prabhu if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) 13853da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh return -ENOLCK; 13953da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh 14053da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh return ocfs2_plock(osb->cconn, OCFS2_I(inode)->ip_blkno, file, cmd, fl); 14153da4939f349d4edd283b043219221ca5b78e4d4Mark Fasheh} 142