aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c106
1 files changed, 60 insertions, 46 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 909eab8fb1d0..56f996e98bbc 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -139,10 +139,7 @@ int lease_break_time = 45;
139#define for_each_lock(inode, lockp) \ 139#define for_each_lock(inode, lockp) \
140 for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next) 140 for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next)
141 141
142LIST_HEAD(file_lock_list); 142static LIST_HEAD(file_lock_list);
143
144EXPORT_SYMBOL(file_lock_list);
145
146static LIST_HEAD(blocked_list); 143static LIST_HEAD(blocked_list);
147 144
148static kmem_cache_t *filelock_cache; 145static kmem_cache_t *filelock_cache;
@@ -153,6 +150,21 @@ static struct file_lock *locks_alloc_lock(void)
153 return kmem_cache_alloc(filelock_cache, SLAB_KERNEL); 150 return kmem_cache_alloc(filelock_cache, SLAB_KERNEL);
154} 151}
155 152
153static void locks_release_private(struct file_lock *fl)
154{
155 if (fl->fl_ops) {
156 if (fl->fl_ops->fl_release_private)
157 fl->fl_ops->fl_release_private(fl);
158 fl->fl_ops = NULL;
159 }
160 if (fl->fl_lmops) {
161 if (fl->fl_lmops->fl_release_private)
162 fl->fl_lmops->fl_release_private(fl);
163 fl->fl_lmops = NULL;
164 }
165
166}
167
156/* Free a lock which is not in use. */ 168/* Free a lock which is not in use. */
157static void locks_free_lock(struct file_lock *fl) 169static void locks_free_lock(struct file_lock *fl)
158{ 170{
@@ -169,18 +181,7 @@ static void locks_free_lock(struct file_lock *fl)
169 if (!list_empty(&fl->fl_link)) 181 if (!list_empty(&fl->fl_link))
170 panic("Attempting to free lock on active lock list"); 182 panic("Attempting to free lock on active lock list");
171 183
172 if (fl->fl_ops) { 184 locks_release_private(fl);
173 if (fl->fl_ops->fl_release_private)
174 fl->fl_ops->fl_release_private(fl);
175 fl->fl_ops = NULL;
176 }
177
178 if (fl->fl_lmops) {
179 if (fl->fl_lmops->fl_release_private)
180 fl->fl_lmops->fl_release_private(fl);
181 fl->fl_lmops = NULL;
182 }
183
184 kmem_cache_free(filelock_cache, fl); 185 kmem_cache_free(filelock_cache, fl);
185} 186}
186 187
@@ -218,24 +219,46 @@ static void init_once(void *foo, kmem_cache_t *cache, unsigned long flags)
218 locks_init_lock(lock); 219 locks_init_lock(lock);
219} 220}
220 221
222static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
223{
224 if (fl->fl_ops) {
225 if (fl->fl_ops->fl_copy_lock)
226 fl->fl_ops->fl_copy_lock(new, fl);
227 new->fl_ops = fl->fl_ops;
228 }
229 if (fl->fl_lmops) {
230 if (fl->fl_lmops->fl_copy_lock)
231 fl->fl_lmops->fl_copy_lock(new, fl);
232 new->fl_lmops = fl->fl_lmops;
233 }
234}
235
221/* 236/*
222 * Initialize a new lock from an existing file_lock structure. 237 * Initialize a new lock from an existing file_lock structure.
223 */ 238 */
224void locks_copy_lock(struct file_lock *new, struct file_lock *fl) 239static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
225{ 240{
226 new->fl_owner = fl->fl_owner; 241 new->fl_owner = fl->fl_owner;
227 new->fl_pid = fl->fl_pid; 242 new->fl_pid = fl->fl_pid;
228 new->fl_file = fl->fl_file; 243 new->fl_file = NULL;
229 new->fl_flags = fl->fl_flags; 244 new->fl_flags = fl->fl_flags;
230 new->fl_type = fl->fl_type; 245 new->fl_type = fl->fl_type;
231 new->fl_start = fl->fl_start; 246 new->fl_start = fl->fl_start;
232 new->fl_end = fl->fl_end; 247 new->fl_end = fl->fl_end;
248 new->fl_ops = NULL;
249 new->fl_lmops = NULL;
250}
251
252void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
253{
254 locks_release_private(new);
255
256 __locks_copy_lock(new, fl);
257 new->fl_file = fl->fl_file;
233 new->fl_ops = fl->fl_ops; 258 new->fl_ops = fl->fl_ops;
234 new->fl_lmops = fl->fl_lmops; 259 new->fl_lmops = fl->fl_lmops;
235 if (fl->fl_ops && fl->fl_ops->fl_copy_lock) 260
236 fl->fl_ops->fl_copy_lock(new, fl); 261 locks_copy_private(new, fl);
237 if (fl->fl_lmops && fl->fl_lmops->fl_copy_lock)
238 fl->fl_lmops->fl_copy_lock(new, fl);
239} 262}
240 263
241EXPORT_SYMBOL(locks_copy_lock); 264EXPORT_SYMBOL(locks_copy_lock);
@@ -654,8 +677,9 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w
654 return result; 677 return result;
655} 678}
656 679
657struct file_lock * 680int
658posix_test_lock(struct file *filp, struct file_lock *fl) 681posix_test_lock(struct file *filp, struct file_lock *fl,
682 struct file_lock *conflock)
659{ 683{
660 struct file_lock *cfl; 684 struct file_lock *cfl;
661 685
@@ -666,9 +690,13 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
666 if (posix_locks_conflict(cfl, fl)) 690 if (posix_locks_conflict(cfl, fl))
667 break; 691 break;
668 } 692 }
693 if (cfl) {
694 __locks_copy_lock(conflock, cfl);
695 unlock_kernel();
696 return 1;
697 }
669 unlock_kernel(); 698 unlock_kernel();
670 699 return 0;
671 return (cfl);
672} 700}
673 701
674EXPORT_SYMBOL(posix_test_lock); 702EXPORT_SYMBOL(posix_test_lock);
@@ -904,7 +932,8 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request)
904 fl->fl_start = request->fl_start; 932 fl->fl_start = request->fl_start;
905 fl->fl_end = request->fl_end; 933 fl->fl_end = request->fl_end;
906 fl->fl_type = request->fl_type; 934 fl->fl_type = request->fl_type;
907 fl->fl_u = request->fl_u; 935 locks_release_private(fl);
936 locks_copy_private(fl, request);
908 request = fl; 937 request = fl;
909 added = 1; 938 added = 1;
910 } 939 }
@@ -1544,7 +1573,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
1544 */ 1573 */
1545int fcntl_getlk(struct file *filp, struct flock __user *l) 1574int fcntl_getlk(struct file *filp, struct flock __user *l)
1546{ 1575{
1547 struct file_lock *fl, file_lock; 1576 struct file_lock *fl, cfl, file_lock;
1548 struct flock flock; 1577 struct flock flock;
1549 int error; 1578 int error;
1550 1579
@@ -1568,7 +1597,7 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
1568 else 1597 else
1569 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); 1598 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
1570 } else { 1599 } else {
1571 fl = posix_test_lock(filp, &file_lock); 1600 fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
1572 } 1601 }
1573 1602
1574 flock.l_type = F_UNLCK; 1603 flock.l_type = F_UNLCK;
@@ -1698,7 +1727,7 @@ out:
1698 */ 1727 */
1699int fcntl_getlk64(struct file *filp, struct flock64 __user *l) 1728int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
1700{ 1729{
1701 struct file_lock *fl, file_lock; 1730 struct file_lock *fl, cfl, file_lock;
1702 struct flock64 flock; 1731 struct flock64 flock;
1703 int error; 1732 int error;
1704 1733
@@ -1722,7 +1751,7 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
1722 else 1751 else
1723 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); 1752 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
1724 } else { 1753 } else {
1725 fl = posix_test_lock(filp, &file_lock); 1754 fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
1726 } 1755 }
1727 1756
1728 flock.l_type = F_UNLCK; 1757 flock.l_type = F_UNLCK;
@@ -1936,21 +1965,6 @@ void locks_remove_flock(struct file *filp)
1936} 1965}
1937 1966
1938/** 1967/**
1939 * posix_block_lock - blocks waiting for a file lock
1940 * @blocker: the lock which is blocking
1941 * @waiter: the lock which conflicts and has to wait
1942 *
1943 * lockd needs to block waiting for locks.
1944 */
1945void
1946posix_block_lock(struct file_lock *blocker, struct file_lock *waiter)
1947{
1948 locks_insert_block(blocker, waiter);
1949}
1950
1951EXPORT_SYMBOL(posix_block_lock);
1952
1953/**
1954 * posix_unblock_lock - stop waiting for a file lock 1968 * posix_unblock_lock - stop waiting for a file lock
1955 * @filp: how the file was opened 1969 * @filp: how the file was opened
1956 * @waiter: the lock which was waiting 1970 * @waiter: the lock which was waiting