aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c192
1 files changed, 86 insertions, 106 deletions
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