0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/fs.h>
0011 #include <linux/fcntl.h>
0012
0013 #include <cluster/masklog.h>
0014
0015 #include "ocfs2.h"
0016
0017 #include "dlmglue.h"
0018 #include "file.h"
0019 #include "inode.h"
0020 #include "locks.h"
0021
0022 static int ocfs2_do_flock(struct file *file, struct inode *inode,
0023 int cmd, struct file_lock *fl)
0024 {
0025 int ret = 0, level = 0, trylock = 0;
0026 struct ocfs2_file_private *fp = file->private_data;
0027 struct ocfs2_lock_res *lockres = &fp->fp_flock;
0028
0029 if (fl->fl_type == F_WRLCK)
0030 level = 1;
0031 if (!IS_SETLKW(cmd))
0032 trylock = 1;
0033
0034 mutex_lock(&fp->fp_mutex);
0035
0036 if (lockres->l_flags & OCFS2_LOCK_ATTACHED &&
0037 lockres->l_level > LKM_NLMODE) {
0038 int old_level = 0;
0039 struct file_lock request;
0040
0041 if (lockres->l_level == LKM_EXMODE)
0042 old_level = 1;
0043
0044 if (level == old_level)
0045 goto out;
0046
0047
0048
0049
0050
0051
0052
0053
0054 locks_init_lock(&request);
0055 request.fl_type = F_UNLCK;
0056 request.fl_flags = FL_FLOCK;
0057 locks_lock_file_wait(file, &request);
0058
0059 ocfs2_file_unlock(file);
0060 }
0061
0062 ret = ocfs2_file_lock(file, level, trylock);
0063 if (ret) {
0064 if (ret == -EAGAIN && trylock)
0065 ret = -EWOULDBLOCK;
0066 else
0067 mlog_errno(ret);
0068 goto out;
0069 }
0070
0071 ret = locks_lock_file_wait(file, fl);
0072 if (ret)
0073 ocfs2_file_unlock(file);
0074
0075 out:
0076 mutex_unlock(&fp->fp_mutex);
0077
0078 return ret;
0079 }
0080
0081 static int ocfs2_do_funlock(struct file *file, int cmd, struct file_lock *fl)
0082 {
0083 int ret;
0084 struct ocfs2_file_private *fp = file->private_data;
0085
0086 mutex_lock(&fp->fp_mutex);
0087 ocfs2_file_unlock(file);
0088 ret = locks_lock_file_wait(file, fl);
0089 mutex_unlock(&fp->fp_mutex);
0090
0091 return ret;
0092 }
0093
0094
0095
0096
0097 int ocfs2_flock(struct file *file, int cmd, struct file_lock *fl)
0098 {
0099 struct inode *inode = file->f_mapping->host;
0100 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
0101
0102 if (!(fl->fl_flags & FL_FLOCK))
0103 return -ENOLCK;
0104
0105 if ((osb->s_mount_opt & OCFS2_MOUNT_LOCALFLOCKS) ||
0106 ocfs2_mount_local(osb))
0107 return locks_lock_file_wait(file, fl);
0108
0109 if (fl->fl_type == F_UNLCK)
0110 return ocfs2_do_funlock(file, cmd, fl);
0111 else
0112 return ocfs2_do_flock(file, inode, cmd, fl);
0113 }
0114
0115 int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl)
0116 {
0117 struct inode *inode = file->f_mapping->host;
0118 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
0119
0120 if (!(fl->fl_flags & FL_POSIX))
0121 return -ENOLCK;
0122
0123 return ocfs2_plock(osb->cconn, OCFS2_I(inode)->ip_blkno, file, cmd, fl);
0124 }