aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-15 19:07:40 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-15 19:07:40 -0400
commit541010e4b8921cd781ff02ae68028501457045b6 (patch)
tree58bd529d4c6e69899a0aa20afa2d7f1c23326417 /fs
parente457f790d8b05977853aa238bbc667b3bb375671 (diff)
parent5e7fc436426b1f9e106f511a049de91c82ec2c53 (diff)
Merge branch 'locks' of git://linux-nfs.org/~bfields/linux
* 'locks' of git://linux-nfs.org/~bfields/linux: nfsd: remove IS_ISMNDLCK macro Rework /proc/locks via seq_files and seq_list helpers fs/locks.c: use list_for_each_entry() instead of list_for_each() NFS: clean up explicit check for mandatory locks AFS: clean up explicit check for mandatory locks 9PFS: clean up explicit check for mandatory locks GFS2: clean up explicit check for mandatory locks Cleanup macros for distinguishing mandatory locks Documentation: move locks.txt in filesystems/ locks: add warning about mandatory locking races Documentation: move mandatory locking documentation to filesystems/ locks: Fix potential OOPS in generic_setlease() Use list_first_entry in locks_wake_up_blocks locks: fix flock_lock_file() comment Memory shortage can result in inconsistent flocks state locks: kill redundant local variable locks: reverse order of posix_locks_conflict() arguments
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/vfs_file.c2
-rw-r--r--fs/afs/flock.c3
-rw-r--r--fs/gfs2/ops_file.c4
-rw-r--r--fs/locks.c192
-rw-r--r--fs/nfs/file.c3
-rw-r--r--fs/nfsd/nfs4state.c2
-rw-r--r--fs/nfsd/vfs.c13
-rw-r--r--fs/proc/proc_misc.c19
-rw-r--r--fs/read_write.c2
9 files changed, 109 insertions, 131 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 2a40c2946d0a..716691689fd5 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -105,7 +105,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
105 P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); 105 P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
106 106
107 /* No mandatory locks */ 107 /* No mandatory locks */
108 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) 108 if (__mandatory_lock(inode))
109 return -ENOLCK; 109 return -ENOLCK;
110 110
111 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { 111 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
diff --git a/fs/afs/flock.c b/fs/afs/flock.c
index af6952e39a18..210acafe4a9b 100644
--- a/fs/afs/flock.c
+++ b/fs/afs/flock.c
@@ -524,8 +524,7 @@ int afs_lock(struct file *file, int cmd, struct file_lock *fl)
524 (long long) fl->fl_start, (long long) fl->fl_end); 524 (long long) fl->fl_start, (long long) fl->fl_end);
525 525
526 /* AFS doesn't support mandatory locks */ 526 /* AFS doesn't support mandatory locks */
527 if ((vnode->vfs_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID && 527 if (__mandatory_lock(&vnode->vfs_inode) && fl->fl_type != F_UNLCK)
528 fl->fl_type != F_UNLCK)
529 return -ENOLCK; 528 return -ENOLCK;
530 529
531 if (IS_GETLK(cmd)) 530 if (IS_GETLK(cmd))
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 46a9e10ff17b..7eb4b280ac66 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -535,7 +535,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
535 535
536 if (!(fl->fl_flags & FL_POSIX)) 536 if (!(fl->fl_flags & FL_POSIX))
537 return -ENOLCK; 537 return -ENOLCK;
538 if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) 538 if (__mandatory_lock(&ip->i_inode))
539 return -ENOLCK; 539 return -ENOLCK;
540 540
541 if (sdp->sd_args.ar_localflocks) { 541 if (sdp->sd_args.ar_localflocks) {
@@ -636,7 +636,7 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl)
636 636
637 if (!(fl->fl_flags & FL_FLOCK)) 637 if (!(fl->fl_flags & FL_FLOCK))
638 return -ENOLCK; 638 return -ENOLCK;
639 if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) 639 if (__mandatory_lock(&ip->i_inode))
640 return -ENOLCK; 640 return -ENOLCK;
641 641
642 if (sdp->sd_args.ar_localflocks) 642 if (sdp->sd_args.ar_localflocks)
diff --git a/fs/locks.c b/fs/locks.c
index c795eaaf6c4c..7f9a3ea47418 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -534,7 +534,9 @@ static void locks_insert_block(struct file_lock *blocker,
534static void locks_wake_up_blocks(struct file_lock *blocker) 534static void locks_wake_up_blocks(struct file_lock *blocker)
535{ 535{
536 while (!list_empty(&blocker->fl_block)) { 536 while (!list_empty(&blocker->fl_block)) {
537 struct file_lock *waiter = list_entry(blocker->fl_block.next, 537 struct file_lock *waiter;
538
539 waiter = list_first_entry(&blocker->fl_block,
538 struct file_lock, fl_block); 540 struct file_lock, fl_block);
539 __locks_delete_block(waiter); 541 __locks_delete_block(waiter);
540 if (waiter->fl_lmops && waiter->fl_lmops->fl_notify) 542 if (waiter->fl_lmops && waiter->fl_lmops->fl_notify)
@@ -668,7 +670,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
668 for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) { 670 for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
669 if (!IS_POSIX(cfl)) 671 if (!IS_POSIX(cfl))
670 continue; 672 continue;
671 if (posix_locks_conflict(cfl, fl)) 673 if (posix_locks_conflict(fl, cfl))
672 break; 674 break;
673 } 675 }
674 if (cfl) 676 if (cfl)
@@ -698,13 +700,12 @@ EXPORT_SYMBOL(posix_test_lock);
698static int posix_locks_deadlock(struct file_lock *caller_fl, 700static int posix_locks_deadlock(struct file_lock *caller_fl,
699 struct file_lock *block_fl) 701 struct file_lock *block_fl)
700{ 702{
701 struct list_head *tmp; 703 struct file_lock *fl;
702 704
703next_task: 705next_task:
704 if (posix_same_owner(caller_fl, block_fl)) 706 if (posix_same_owner(caller_fl, block_fl))
705 return 1; 707 return 1;
706 list_for_each(tmp, &blocked_list) { 708 list_for_each_entry(fl, &blocked_list, fl_link) {
707 struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link);
708 if (posix_same_owner(fl, block_fl)) { 709 if (posix_same_owner(fl, block_fl)) {
709 fl = fl->fl_next; 710 fl = fl->fl_next;
710 block_fl = fl; 711 block_fl = fl;
@@ -715,8 +716,7 @@ next_task:
715} 716}
716 717
717/* Try to create a FLOCK lock on filp. We always insert new FLOCK locks 718/* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
718 * at the head of the list, but that's secret knowledge known only to 719 * after any leases, but before any posix locks.
719 * flock_lock_file and posix_lock_file.
720 * 720 *
721 * Note that if called with an FL_EXISTS argument, the caller may determine 721 * Note that if called with an FL_EXISTS argument, the caller may determine
722 * whether or not a lock was successfully freed by testing the return 722 * whether or not a lock was successfully freed by testing the return
@@ -733,6 +733,15 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
733 lock_kernel(); 733 lock_kernel();
734 if (request->fl_flags & FL_ACCESS) 734 if (request->fl_flags & FL_ACCESS)
735 goto find_conflict; 735 goto find_conflict;
736
737 if (request->fl_type != F_UNLCK) {
738 error = -ENOMEM;
739 new_fl = locks_alloc_lock();
740 if (new_fl == NULL)
741 goto out;
742 error = 0;
743 }
744
736 for_each_lock(inode, before) { 745 for_each_lock(inode, before) {
737 struct file_lock *fl = *before; 746 struct file_lock *fl = *before;
738 if (IS_POSIX(fl)) 747 if (IS_POSIX(fl))
@@ -754,10 +763,6 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
754 goto out; 763 goto out;
755 } 764 }
756 765
757 error = -ENOMEM;
758 new_fl = locks_alloc_lock();
759 if (new_fl == NULL)
760 goto out;
761 /* 766 /*
762 * If a higher-priority process was blocked on the old file lock, 767 * If a higher-priority process was blocked on the old file lock,
763 * give it the opportunity to lock the file. 768 * give it the opportunity to lock the file.
@@ -819,7 +824,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
819 lock_kernel(); 824 lock_kernel();
820 if (request->fl_type != F_UNLCK) { 825 if (request->fl_type != F_UNLCK) {
821 for_each_lock(inode, before) { 826 for_each_lock(inode, before) {
822 struct file_lock *fl = *before; 827 fl = *before;
823 if (!IS_POSIX(fl)) 828 if (!IS_POSIX(fl))
824 continue; 829 continue;
825 if (!posix_locks_conflict(request, fl)) 830 if (!posix_locks_conflict(request, fl))
@@ -1113,7 +1118,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
1113 * If we've been sleeping someone might have 1118 * If we've been sleeping someone might have
1114 * changed the permissions behind our back. 1119 * changed the permissions behind our back.
1115 */ 1120 */
1116 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) 1121 if (__mandatory_lock(inode))
1117 continue; 1122 continue;
1118 } 1123 }
1119 1124
@@ -1337,6 +1342,7 @@ int fcntl_getlease(struct file *filp)
1337int generic_setlease(struct file *filp, long arg, struct file_lock **flp) 1342int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1338{ 1343{
1339 struct file_lock *fl, **before, **my_before = NULL, *lease; 1344 struct file_lock *fl, **before, **my_before = NULL, *lease;
1345 struct file_lock *new_fl = NULL;
1340 struct dentry *dentry = filp->f_path.dentry; 1346 struct dentry *dentry = filp->f_path.dentry;
1341 struct inode *inode = dentry->d_inode; 1347 struct inode *inode = dentry->d_inode;
1342 int error, rdlease_count = 0, wrlease_count = 0; 1348 int error, rdlease_count = 0, wrlease_count = 0;
@@ -1363,6 +1369,11 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1363 || (atomic_read(&inode->i_count) > 1))) 1369 || (atomic_read(&inode->i_count) > 1)))
1364 goto out; 1370 goto out;
1365 1371
1372 error = -ENOMEM;
1373 new_fl = locks_alloc_lock();
1374 if (new_fl == NULL)
1375 goto out;
1376
1366 /* 1377 /*
1367 * At this point, we know that if there is an exclusive 1378 * At this point, we know that if there is an exclusive
1368 * lease on this file, then we hold it on this filp 1379 * lease on this file, then we hold it on this filp
@@ -1405,18 +1416,15 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1405 if (!leases_enable) 1416 if (!leases_enable)
1406 goto out; 1417 goto out;
1407 1418
1408 error = -ENOMEM; 1419 locks_copy_lock(new_fl, lease);
1409 fl = locks_alloc_lock(); 1420 locks_insert_lock(before, new_fl);
1410 if (fl == NULL)
1411 goto out;
1412
1413 locks_copy_lock(fl, lease);
1414 1421
1415 locks_insert_lock(before, fl); 1422 *flp = new_fl;
1423 return 0;
1416 1424
1417 *flp = fl;
1418 error = 0;
1419out: 1425out:
1426 if (new_fl != NULL)
1427 locks_free_lock(new_fl);
1420 return error; 1428 return error;
1421} 1429}
1422EXPORT_SYMBOL(generic_setlease); 1430EXPORT_SYMBOL(generic_setlease);
@@ -1752,9 +1760,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
1752 /* Don't allow mandatory locks on files that may be memory mapped 1760 /* Don't allow mandatory locks on files that may be memory mapped
1753 * and shared. 1761 * and shared.
1754 */ 1762 */
1755 if (IS_MANDLOCK(inode) && 1763 if (mandatory_lock(inode) && mapping_writably_mapped(filp->f_mapping)) {
1756 (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
1757 mapping_writably_mapped(filp->f_mapping)) {
1758 error = -EAGAIN; 1764 error = -EAGAIN;
1759 goto out; 1765 goto out;
1760 } 1766 }
@@ -1878,9 +1884,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
1878 /* Don't allow mandatory locks on files that may be memory mapped 1884 /* Don't allow mandatory locks on files that may be memory mapped
1879 * and shared. 1885 * and shared.
1880 */ 1886 */
1881 if (IS_MANDLOCK(inode) && 1887 if (mandatory_lock(inode) && mapping_writably_mapped(filp->f_mapping)) {
1882 (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
1883 mapping_writably_mapped(filp->f_mapping)) {
1884 error = -EAGAIN; 1888 error = -EAGAIN;
1885 goto out; 1889 goto out;
1886 } 1890 }
@@ -2062,138 +2066,114 @@ int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
2062 2066
2063EXPORT_SYMBOL_GPL(vfs_cancel_lock); 2067EXPORT_SYMBOL_GPL(vfs_cancel_lock);
2064 2068
2065static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx) 2069#ifdef CONFIG_PROC_FS
2070#include <linux/seq_file.h>
2071
2072static void lock_get_status(struct seq_file *f, struct file_lock *fl,
2073 int id, char *pfx)
2066{ 2074{
2067 struct inode *inode = NULL; 2075 struct inode *inode = NULL;
2068 2076
2069 if (fl->fl_file != NULL) 2077 if (fl->fl_file != NULL)
2070 inode = fl->fl_file->f_path.dentry->d_inode; 2078 inode = fl->fl_file->f_path.dentry->d_inode;
2071 2079
2072 out += sprintf(out, "%d:%s ", id, pfx); 2080 seq_printf(f, "%d:%s ", id, pfx);
2073 if (IS_POSIX(fl)) { 2081 if (IS_POSIX(fl)) {
2074 out += sprintf(out, "%6s %s ", 2082 seq_printf(f, "%6s %s ",
2075 (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ", 2083 (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ",
2076 (inode == NULL) ? "*NOINODE*" : 2084 (inode == NULL) ? "*NOINODE*" :
2077 (IS_MANDLOCK(inode) && 2085 mandatory_lock(inode) ? "MANDATORY" : "ADVISORY ");
2078 (inode->i_mode & (S_IXGRP | S_ISGID)) == S_ISGID) ?
2079 "MANDATORY" : "ADVISORY ");
2080 } else if (IS_FLOCK(fl)) { 2086 } else if (IS_FLOCK(fl)) {
2081 if (fl->fl_type & LOCK_MAND) { 2087 if (fl->fl_type & LOCK_MAND) {
2082 out += sprintf(out, "FLOCK MSNFS "); 2088 seq_printf(f, "FLOCK MSNFS ");
2083 } else { 2089 } else {
2084 out += sprintf(out, "FLOCK ADVISORY "); 2090 seq_printf(f, "FLOCK ADVISORY ");
2085 } 2091 }
2086 } else if (IS_LEASE(fl)) { 2092 } else if (IS_LEASE(fl)) {
2087 out += sprintf(out, "LEASE "); 2093 seq_printf(f, "LEASE ");
2088 if (fl->fl_type & F_INPROGRESS) 2094 if (fl->fl_type & F_INPROGRESS)
2089 out += sprintf(out, "BREAKING "); 2095 seq_printf(f, "BREAKING ");
2090 else if (fl->fl_file) 2096 else if (fl->fl_file)
2091 out += sprintf(out, "ACTIVE "); 2097 seq_printf(f, "ACTIVE ");
2092 else 2098 else
2093 out += sprintf(out, "BREAKER "); 2099 seq_printf(f, "BREAKER ");
2094 } else { 2100 } else {
2095 out += sprintf(out, "UNKNOWN UNKNOWN "); 2101 seq_printf(f, "UNKNOWN UNKNOWN ");
2096 } 2102 }
2097 if (fl->fl_type & LOCK_MAND) { 2103 if (fl->fl_type & LOCK_MAND) {
2098 out += sprintf(out, "%s ", 2104 seq_printf(f, "%s ",
2099 (fl->fl_type & LOCK_READ) 2105 (fl->fl_type & LOCK_READ)
2100 ? (fl->fl_type & LOCK_WRITE) ? "RW " : "READ " 2106 ? (fl->fl_type & LOCK_WRITE) ? "RW " : "READ "
2101 : (fl->fl_type & LOCK_WRITE) ? "WRITE" : "NONE "); 2107 : (fl->fl_type & LOCK_WRITE) ? "WRITE" : "NONE ");
2102 } else { 2108 } else {
2103 out += sprintf(out, "%s ", 2109 seq_printf(f, "%s ",
2104 (fl->fl_type & F_INPROGRESS) 2110 (fl->fl_type & F_INPROGRESS)
2105 ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ " 2111 ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ "
2106 : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ "); 2112 : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ ");
2107 } 2113 }
2108 if (inode) { 2114 if (inode) {
2109#ifdef WE_CAN_BREAK_LSLK_NOW 2115#ifdef WE_CAN_BREAK_LSLK_NOW
2110 out += sprintf(out, "%d %s:%ld ", fl->fl_pid, 2116 seq_printf(f, "%d %s:%ld ", fl->fl_pid,
2111 inode->i_sb->s_id, inode->i_ino); 2117 inode->i_sb->s_id, inode->i_ino);
2112#else 2118#else
2113 /* userspace relies on this representation of dev_t ;-( */ 2119 /* userspace relies on this representation of dev_t ;-( */
2114 out += sprintf(out, "%d %02x:%02x:%ld ", fl->fl_pid, 2120 seq_printf(f, "%d %02x:%02x:%ld ", fl->fl_pid,
2115 MAJOR(inode->i_sb->s_dev), 2121 MAJOR(inode->i_sb->s_dev),
2116 MINOR(inode->i_sb->s_dev), inode->i_ino); 2122 MINOR(inode->i_sb->s_dev), inode->i_ino);
2117#endif 2123#endif
2118 } else { 2124 } else {
2119 out += sprintf(out, "%d <none>:0 ", fl->fl_pid); 2125 seq_printf(f, "%d <none>:0 ", fl->fl_pid);
2120 } 2126 }
2121 if (IS_POSIX(fl)) { 2127 if (IS_POSIX(fl)) {
2122 if (fl->fl_end == OFFSET_MAX) 2128 if (fl->fl_end == OFFSET_MAX)
2123 out += sprintf(out, "%Ld EOF\n", fl->fl_start); 2129 seq_printf(f, "%Ld EOF\n", fl->fl_start);
2124 else 2130 else
2125 out += sprintf(out, "%Ld %Ld\n", fl->fl_start, 2131 seq_printf(f, "%Ld %Ld\n", fl->fl_start, fl->fl_end);
2126 fl->fl_end);
2127 } else { 2132 } else {
2128 out += sprintf(out, "0 EOF\n"); 2133 seq_printf(f, "0 EOF\n");
2129 } 2134 }
2130} 2135}
2131 2136
2132static void move_lock_status(char **p, off_t* pos, off_t offset) 2137static int locks_show(struct seq_file *f, void *v)
2133{ 2138{
2134 int len; 2139 struct file_lock *fl, *bfl;
2135 len = strlen(*p); 2140
2136 if(*pos >= offset) { 2141 fl = list_entry(v, struct file_lock, fl_link);
2137 /* the complete line is valid */ 2142
2138 *p += len; 2143 lock_get_status(f, fl, (long)f->private, "");
2139 *pos += len; 2144
2140 return; 2145 list_for_each_entry(bfl, &fl->fl_block, fl_block)
2141 } 2146 lock_get_status(f, bfl, (long)f->private, " ->");
2142 if(*pos+len > offset) { 2147
2143 /* use the second part of the line */ 2148 f->private++;
2144 int i = offset-*pos; 2149 return 0;
2145 memmove(*p,*p+i,len-i);
2146 *p += len-i;
2147 *pos += len;
2148 return;
2149 }
2150 /* discard the complete line */
2151 *pos += len;
2152} 2150}
2153 2151
2154/** 2152static void *locks_start(struct seq_file *f, loff_t *pos)
2155 * get_locks_status - reports lock usage in /proc/locks 2153{
2156 * @buffer: address in userspace to write into 2154 lock_kernel();
2157 * @start: ? 2155 f->private = (void *)1;
2158 * @offset: how far we are through the buffer 2156 return seq_list_start(&file_lock_list, *pos);
2159 * @length: how much to read 2157}
2160 */
2161 2158
2162int get_locks_status(char *buffer, char **start, off_t offset, int length) 2159static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
2163{ 2160{
2164 struct list_head *tmp; 2161 return seq_list_next(v, &file_lock_list, pos);
2165 char *q = buffer; 2162}
2166 off_t pos = 0;
2167 int i = 0;
2168 2163
2169 lock_kernel(); 2164static void locks_stop(struct seq_file *f, void *v)
2170 list_for_each(tmp, &file_lock_list) { 2165{
2171 struct list_head *btmp;
2172 struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link);
2173 lock_get_status(q, fl, ++i, "");
2174 move_lock_status(&q, &pos, offset);
2175
2176 if(pos >= offset+length)
2177 goto done;
2178
2179 list_for_each(btmp, &fl->fl_block) {
2180 struct file_lock *bfl = list_entry(btmp,
2181 struct file_lock, fl_block);
2182 lock_get_status(q, bfl, i, " ->");
2183 move_lock_status(&q, &pos, offset);
2184
2185 if(pos >= offset+length)
2186 goto done;
2187 }
2188 }
2189done:
2190 unlock_kernel(); 2166 unlock_kernel();
2191 *start = buffer;
2192 if(q-buffer < length)
2193 return (q-buffer);
2194 return length;
2195} 2167}
2196 2168
2169struct seq_operations locks_seq_operations = {
2170 .start = locks_start,
2171 .next = locks_next,
2172 .stop = locks_stop,
2173 .show = locks_show,
2174};
2175#endif
2176
2197/** 2177/**
2198 * lock_may_read - checks that the region is free of locks 2178 * lock_may_read - checks that the region is free of locks
2199 * @inode: the inode that is being read 2179 * @inode: the inode that is being read
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index c664bb921425..08c7c7387fce 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -577,8 +577,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
577 nfs_inc_stats(inode, NFSIOS_VFSLOCK); 577 nfs_inc_stats(inode, NFSIOS_VFSLOCK);
578 578
579 /* No mandatory locks over NFS */ 579 /* No mandatory locks over NFS */
580 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID && 580 if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
581 fl->fl_type != F_UNLCK)
582 return -ENOLCK; 581 return -ENOLCK;
583 582
584 if (IS_GETLK(cmd)) 583 if (IS_GETLK(cmd))
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6f182d25793d..31673cd251c3 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2035,7 +2035,7 @@ static inline int
2035io_during_grace_disallowed(struct inode *inode, int flags) 2035io_during_grace_disallowed(struct inode *inode, int flags)
2036{ 2036{
2037 return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE)) 2037 return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE))
2038 && MANDATORY_LOCK(inode); 2038 && mandatory_lock(inode);
2039} 2039}
2040 2040
2041/* 2041/*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index cec78c82b1f9..2a8d665b134b 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -61,12 +61,6 @@
61#define NFSDDBG_FACILITY NFSDDBG_FILEOP 61#define NFSDDBG_FACILITY NFSDDBG_FILEOP
62 62
63 63
64/* We must ignore files (but only files) which might have mandatory
65 * locks on them because there is no way to know if the accesser has
66 * the lock.
67 */
68#define IS_ISMNDLK(i) (S_ISREG((i)->i_mode) && MANDATORY_LOCK(i))
69
70/* 64/*
71 * This is a cache of readahead params that help us choose the proper 65 * This is a cache of readahead params that help us choose the proper
72 * readahead strategy. Initially, we set all readahead parameters to 0 66 * readahead strategy. Initially, we set all readahead parameters to 0
@@ -689,7 +683,12 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
689 err = nfserr_perm; 683 err = nfserr_perm;
690 if (IS_APPEND(inode) && (access & MAY_WRITE)) 684 if (IS_APPEND(inode) && (access & MAY_WRITE))
691 goto out; 685 goto out;
692 if (IS_ISMNDLK(inode)) 686 /*
687 * We must ignore files (but only files) which might have mandatory
688 * locks on them because there is no way to know if the accesser has
689 * the lock.
690 */
691 if (S_ISREG((inode)->i_mode) && mandatory_lock(inode))
693 goto out; 692 goto out;
694 693
695 if (!inode->i_fop) 694 if (!inode->i_fop)
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index b872a01ad3af..0071939c0095 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -66,7 +66,6 @@ extern int get_stram_list(char *);
66extern int get_filesystem_list(char *); 66extern int get_filesystem_list(char *);
67extern int get_exec_domain_list(char *); 67extern int get_exec_domain_list(char *);
68extern int get_dma_list(char *); 68extern int get_dma_list(char *);
69extern int get_locks_status (char *, char **, off_t, int);
70 69
71static int proc_calc_metrics(char *page, char **start, off_t off, 70static int proc_calc_metrics(char *page, char **start, off_t off,
72 int count, int *eof, int len) 71 int count, int *eof, int len)
@@ -624,16 +623,18 @@ static int cmdline_read_proc(char *page, char **start, off_t off,
624 return proc_calc_metrics(page, start, off, count, eof, len); 623 return proc_calc_metrics(page, start, off, count, eof, len);
625} 624}
626 625
627static int locks_read_proc(char *page, char **start, off_t off, 626static int locks_open(struct inode *inode, struct file *filp)
628 int count, int *eof, void *data)
629{ 627{
630 int len = get_locks_status(page, start, off, count); 628 return seq_open(filp, &locks_seq_operations);
631
632 if (len < count)
633 *eof = 1;
634 return len;
635} 629}
636 630
631static const struct file_operations proc_locks_operations = {
632 .open = locks_open,
633 .read = seq_read,
634 .llseek = seq_lseek,
635 .release = seq_release,
636};
637
637static int execdomains_read_proc(char *page, char **start, off_t off, 638static int execdomains_read_proc(char *page, char **start, off_t off,
638 int count, int *eof, void *data) 639 int count, int *eof, void *data)
639{ 640{
@@ -691,7 +692,6 @@ void __init proc_misc_init(void)
691#endif 692#endif
692 {"filesystems", filesystems_read_proc}, 693 {"filesystems", filesystems_read_proc},
693 {"cmdline", cmdline_read_proc}, 694 {"cmdline", cmdline_read_proc},
694 {"locks", locks_read_proc},
695 {"execdomains", execdomains_read_proc}, 695 {"execdomains", execdomains_read_proc},
696 {NULL,} 696 {NULL,}
697 }; 697 };
@@ -709,6 +709,7 @@ void __init proc_misc_init(void)
709 entry->proc_fops = &proc_kmsg_operations; 709 entry->proc_fops = &proc_kmsg_operations;
710 } 710 }
711#endif 711#endif
712 create_seq_entry("locks", 0, &proc_locks_operations);
712 create_seq_entry("devices", 0, &proc_devinfo_operations); 713 create_seq_entry("devices", 0, &proc_devinfo_operations);
713 create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); 714 create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
714#ifdef CONFIG_BLOCK 715#ifdef CONFIG_BLOCK
diff --git a/fs/read_write.c b/fs/read_write.c
index 507ddff48a9a..124693e8d3fa 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -205,7 +205,7 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
205 if (unlikely((pos < 0) || (loff_t) (pos + count) < 0)) 205 if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
206 goto Einval; 206 goto Einval;
207 207
208 if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) { 208 if (unlikely(inode->i_flock && mandatory_lock(inode))) {
209 int retval = locks_mandatory_area( 209 int retval = locks_mandatory_area(
210 read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, 210 read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
211 inode, file, pos, count); 211 inode, file, pos, count);