aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/Kconfig1
-rw-r--r--fs/fcntl.c66
-rw-r--r--fs/lockd/svc.c11
-rw-r--r--fs/lockd/svclock.c6
-rw-r--r--fs/lockd/svcsubs.c9
-rw-r--r--fs/locks.c57
-rw-r--r--fs/nfs/Kconfig1
-rw-r--r--fs/nfsd/Kconfig1
-rw-r--r--fs/nfsd/nfs4state.c26
-rw-r--r--include/linux/fs.h6
10 files changed, 114 insertions, 70 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index b5e582bd769d..97673c955484 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -53,7 +53,6 @@ config EXPORTFS
53config FILE_LOCKING 53config FILE_LOCKING
54 bool "Enable POSIX file locking API" if EMBEDDED 54 bool "Enable POSIX file locking API" if EMBEDDED
55 default y 55 default y
56 select BKL # while lockd still uses it.
57 help 56 help
58 This option enables standard file locking support, required 57 This option enables standard file locking support, required
59 for filesystems like NFS and for the flock() system 58 for filesystems like NFS and for the flock() system
diff --git a/fs/fcntl.c b/fs/fcntl.c
index f8cc34f542c3..dcdbc6f5c33b 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -640,7 +640,7 @@ static void fasync_free_rcu(struct rcu_head *head)
640 * match the state "is the filp on a fasync list". 640 * match the state "is the filp on a fasync list".
641 * 641 *
642 */ 642 */
643static int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp) 643int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp)
644{ 644{
645 struct fasync_struct *fa, **fp; 645 struct fasync_struct *fa, **fp;
646 int result = 0; 646 int result = 0;
@@ -666,21 +666,28 @@ static int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp)
666 return result; 666 return result;
667} 667}
668 668
669struct fasync_struct *fasync_alloc(void)
670{
671 return kmem_cache_alloc(fasync_cache, GFP_KERNEL);
672}
673
669/* 674/*
670 * Add a fasync entry. Return negative on error, positive if 675 * NOTE! This can be used only for unused fasync entries:
671 * added, and zero if did nothing but change an existing one. 676 * entries that actually got inserted on the fasync list
672 * 677 * need to be released by rcu - see fasync_remove_entry.
673 * NOTE! It is very important that the FASYNC flag always
674 * match the state "is the filp on a fasync list".
675 */ 678 */
676static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fapp) 679void fasync_free(struct fasync_struct *new)
677{ 680{
678 struct fasync_struct *new, *fa, **fp; 681 kmem_cache_free(fasync_cache, new);
679 int result = 0; 682}
680 683
681 new = kmem_cache_alloc(fasync_cache, GFP_KERNEL); 684/*
682 if (!new) 685 * Insert a new entry into the fasync list. Return the pointer to the
683 return -ENOMEM; 686 * old one if we didn't use the new one.
687 */
688struct fasync_struct *fasync_insert_entry(int fd, struct file *filp, struct fasync_struct **fapp, struct fasync_struct *new)
689{
690 struct fasync_struct *fa, **fp;
684 691
685 spin_lock(&filp->f_lock); 692 spin_lock(&filp->f_lock);
686 spin_lock(&fasync_lock); 693 spin_lock(&fasync_lock);
@@ -691,8 +698,6 @@ static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fa
691 spin_lock_irq(&fa->fa_lock); 698 spin_lock_irq(&fa->fa_lock);
692 fa->fa_fd = fd; 699 fa->fa_fd = fd;
693 spin_unlock_irq(&fa->fa_lock); 700 spin_unlock_irq(&fa->fa_lock);
694
695 kmem_cache_free(fasync_cache, new);
696 goto out; 701 goto out;
697 } 702 }
698 703
@@ -702,13 +707,42 @@ static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fa
702 new->fa_fd = fd; 707 new->fa_fd = fd;
703 new->fa_next = *fapp; 708 new->fa_next = *fapp;
704 rcu_assign_pointer(*fapp, new); 709 rcu_assign_pointer(*fapp, new);
705 result = 1;
706 filp->f_flags |= FASYNC; 710 filp->f_flags |= FASYNC;
707 711
708out: 712out:
709 spin_unlock(&fasync_lock); 713 spin_unlock(&fasync_lock);
710 spin_unlock(&filp->f_lock); 714 spin_unlock(&filp->f_lock);
711 return result; 715 return fa;
716}
717
718/*
719 * Add a fasync entry. Return negative on error, positive if
720 * added, and zero if did nothing but change an existing one.
721 *
722 * NOTE! It is very important that the FASYNC flag always
723 * match the state "is the filp on a fasync list".
724 */
725static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fapp)
726{
727 struct fasync_struct *new;
728
729 new = fasync_alloc();
730 if (!new)
731 return -ENOMEM;
732
733 /*
734 * fasync_insert_entry() returns the old (update) entry if
735 * it existed.
736 *
737 * So free the (unused) new entry and return 0 to let the
738 * caller know that we didn't add any new fasync entries.
739 */
740 if (fasync_insert_entry(fd, filp, fapp, new)) {
741 fasync_free(new);
742 return 0;
743 }
744
745 return 1;
712} 746}
713 747
714/* 748/*
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index b13aabc12298..abfff9d7979d 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -22,7 +22,6 @@
22#include <linux/in.h> 22#include <linux/in.h>
23#include <linux/uio.h> 23#include <linux/uio.h>
24#include <linux/smp.h> 24#include <linux/smp.h>
25#include <linux/smp_lock.h>
26#include <linux/mutex.h> 25#include <linux/mutex.h>
27#include <linux/kthread.h> 26#include <linux/kthread.h>
28#include <linux/freezer.h> 27#include <linux/freezer.h>
@@ -130,15 +129,6 @@ lockd(void *vrqstp)
130 129
131 dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n"); 130 dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
132 131
133 /*
134 * FIXME: it would be nice if lockd didn't spend its entire life
135 * running under the BKL. At the very least, it would be good to
136 * have someone clarify what it's intended to protect here. I've
137 * seen some handwavy posts about posix locking needing to be
138 * done under the BKL, but it's far from clear.
139 */
140 lock_kernel();
141
142 if (!nlm_timeout) 132 if (!nlm_timeout)
143 nlm_timeout = LOCKD_DFLT_TIMEO; 133 nlm_timeout = LOCKD_DFLT_TIMEO;
144 nlmsvc_timeout = nlm_timeout * HZ; 134 nlmsvc_timeout = nlm_timeout * HZ;
@@ -195,7 +185,6 @@ lockd(void *vrqstp)
195 if (nlmsvc_ops) 185 if (nlmsvc_ops)
196 nlmsvc_invalidate_all(); 186 nlmsvc_invalidate_all();
197 nlm_shutdown_hosts(); 187 nlm_shutdown_hosts();
198 unlock_kernel();
199 return 0; 188 return 0;
200} 189}
201 190
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 6f1ef000975a..c462d346acbd 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -700,14 +700,16 @@ nlmsvc_notify_blocked(struct file_lock *fl)
700 struct nlm_block *block; 700 struct nlm_block *block;
701 701
702 dprintk("lockd: VFS unblock notification for block %p\n", fl); 702 dprintk("lockd: VFS unblock notification for block %p\n", fl);
703 spin_lock(&nlm_blocked_lock);
703 list_for_each_entry(block, &nlm_blocked, b_list) { 704 list_for_each_entry(block, &nlm_blocked, b_list) {
704 if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { 705 if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
705 nlmsvc_insert_block(block, 0); 706 nlmsvc_insert_block_locked(block, 0);
707 spin_unlock(&nlm_blocked_lock);
706 svc_wake_up(block->b_daemon); 708 svc_wake_up(block->b_daemon);
707 return; 709 return;
708 } 710 }
709 } 711 }
710 712 spin_unlock(&nlm_blocked_lock);
711 printk(KERN_WARNING "lockd: notification for unknown block!\n"); 713 printk(KERN_WARNING "lockd: notification for unknown block!\n");
712} 714}
713 715
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index d0ef94cfb3da..1ca0679c80bf 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -170,6 +170,7 @@ nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file,
170 170
171again: 171again:
172 file->f_locks = 0; 172 file->f_locks = 0;
173 lock_flocks(); /* protects i_flock list */
173 for (fl = inode->i_flock; fl; fl = fl->fl_next) { 174 for (fl = inode->i_flock; fl; fl = fl->fl_next) {
174 if (fl->fl_lmops != &nlmsvc_lock_operations) 175 if (fl->fl_lmops != &nlmsvc_lock_operations)
175 continue; 176 continue;
@@ -181,6 +182,7 @@ again:
181 if (match(lockhost, host)) { 182 if (match(lockhost, host)) {
182 struct file_lock lock = *fl; 183 struct file_lock lock = *fl;
183 184
185 unlock_flocks();
184 lock.fl_type = F_UNLCK; 186 lock.fl_type = F_UNLCK;
185 lock.fl_start = 0; 187 lock.fl_start = 0;
186 lock.fl_end = OFFSET_MAX; 188 lock.fl_end = OFFSET_MAX;
@@ -192,6 +194,7 @@ again:
192 goto again; 194 goto again;
193 } 195 }
194 } 196 }
197 unlock_flocks();
195 198
196 return 0; 199 return 0;
197} 200}
@@ -226,10 +229,14 @@ nlm_file_inuse(struct nlm_file *file)
226 if (file->f_count || !list_empty(&file->f_blocks) || file->f_shares) 229 if (file->f_count || !list_empty(&file->f_blocks) || file->f_shares)
227 return 1; 230 return 1;
228 231
232 lock_flocks();
229 for (fl = inode->i_flock; fl; fl = fl->fl_next) { 233 for (fl = inode->i_flock; fl; fl = fl->fl_next) {
230 if (fl->fl_lmops == &nlmsvc_lock_operations) 234 if (fl->fl_lmops == &nlmsvc_lock_operations) {
235 unlock_flocks();
231 return 1; 236 return 1;
237 }
232 } 238 }
239 unlock_flocks();
233 file->f_locks = 0; 240 file->f_locks = 0;
234 return 0; 241 return 0;
235} 242}
diff --git a/fs/locks.c b/fs/locks.c
index 4de3a2666810..50ec15927aab 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -142,6 +142,7 @@ int lease_break_time = 45;
142 142
143static LIST_HEAD(file_lock_list); 143static LIST_HEAD(file_lock_list);
144static LIST_HEAD(blocked_list); 144static LIST_HEAD(blocked_list);
145static DEFINE_SPINLOCK(file_lock_lock);
145 146
146/* 147/*
147 * Protects the two list heads above, plus the inode->i_flock list 148 * Protects the two list heads above, plus the inode->i_flock list
@@ -149,23 +150,24 @@ static LIST_HEAD(blocked_list);
149 */ 150 */
150void lock_flocks(void) 151void lock_flocks(void)
151{ 152{
152 lock_kernel(); 153 spin_lock(&file_lock_lock);
153} 154}
154EXPORT_SYMBOL_GPL(lock_flocks); 155EXPORT_SYMBOL_GPL(lock_flocks);
155 156
156void unlock_flocks(void) 157void unlock_flocks(void)
157{ 158{
158 unlock_kernel(); 159 spin_unlock(&file_lock_lock);
159} 160}
160EXPORT_SYMBOL_GPL(unlock_flocks); 161EXPORT_SYMBOL_GPL(unlock_flocks);
161 162
162static struct kmem_cache *filelock_cache __read_mostly; 163static struct kmem_cache *filelock_cache __read_mostly;
163 164
164/* Allocate an empty lock structure. */ 165/* Allocate an empty lock structure. */
165static struct file_lock *locks_alloc_lock(void) 166struct file_lock *locks_alloc_lock(void)
166{ 167{
167 return kmem_cache_alloc(filelock_cache, GFP_KERNEL); 168 return kmem_cache_alloc(filelock_cache, GFP_KERNEL);
168} 169}
170EXPORT_SYMBOL_GPL(locks_alloc_lock);
169 171
170void locks_release_private(struct file_lock *fl) 172void locks_release_private(struct file_lock *fl)
171{ 173{
@@ -1365,7 +1367,6 @@ int fcntl_getlease(struct file *filp)
1365int generic_setlease(struct file *filp, long arg, struct file_lock **flp) 1367int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1366{ 1368{
1367 struct file_lock *fl, **before, **my_before = NULL, *lease; 1369 struct file_lock *fl, **before, **my_before = NULL, *lease;
1368 struct file_lock *new_fl = NULL;
1369 struct dentry *dentry = filp->f_path.dentry; 1370 struct dentry *dentry = filp->f_path.dentry;
1370 struct inode *inode = dentry->d_inode; 1371 struct inode *inode = dentry->d_inode;
1371 int error, rdlease_count = 0, wrlease_count = 0; 1372 int error, rdlease_count = 0, wrlease_count = 0;
@@ -1385,11 +1386,6 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1385 lease = *flp; 1386 lease = *flp;
1386 1387
1387 if (arg != F_UNLCK) { 1388 if (arg != F_UNLCK) {
1388 error = -ENOMEM;
1389 new_fl = locks_alloc_lock();
1390 if (new_fl == NULL)
1391 goto out;
1392
1393 error = -EAGAIN; 1389 error = -EAGAIN;
1394 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) 1390 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
1395 goto out; 1391 goto out;
@@ -1434,7 +1430,6 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1434 goto out; 1430 goto out;
1435 } 1431 }
1436 1432
1437 error = 0;
1438 if (arg == F_UNLCK) 1433 if (arg == F_UNLCK)
1439 goto out; 1434 goto out;
1440 1435
@@ -1442,15 +1437,11 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1442 if (!leases_enable) 1437 if (!leases_enable)
1443 goto out; 1438 goto out;
1444 1439
1445 locks_copy_lock(new_fl, lease); 1440 locks_insert_lock(before, lease);
1446 locks_insert_lock(before, new_fl);
1447
1448 *flp = new_fl;
1449 return 0; 1441 return 0;
1450 1442
1451out: 1443out:
1452 if (new_fl != NULL) 1444 locks_free_lock(lease);
1453 locks_free_lock(new_fl);
1454 return error; 1445 return error;
1455} 1446}
1456EXPORT_SYMBOL(generic_setlease); 1447EXPORT_SYMBOL(generic_setlease);
@@ -1514,26 +1505,38 @@ EXPORT_SYMBOL_GPL(vfs_setlease);
1514 */ 1505 */
1515int fcntl_setlease(unsigned int fd, struct file *filp, long arg) 1506int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
1516{ 1507{
1517 struct file_lock fl, *flp = &fl; 1508 struct file_lock *fl;
1509 struct fasync_struct *new;
1518 struct inode *inode = filp->f_path.dentry->d_inode; 1510 struct inode *inode = filp->f_path.dentry->d_inode;
1519 int error; 1511 int error;
1520 1512
1521 locks_init_lock(&fl); 1513 fl = lease_alloc(filp, arg);
1522 error = lease_init(filp, arg, &fl); 1514 if (IS_ERR(fl))
1523 if (error) 1515 return PTR_ERR(fl);
1524 return error;
1525 1516
1517 new = fasync_alloc();
1518 if (!new) {
1519 locks_free_lock(fl);
1520 return -ENOMEM;
1521 }
1526 lock_flocks(); 1522 lock_flocks();
1527 1523 error = __vfs_setlease(filp, arg, &fl);
1528 error = __vfs_setlease(filp, arg, &flp);
1529 if (error || arg == F_UNLCK) 1524 if (error || arg == F_UNLCK)
1530 goto out_unlock; 1525 goto out_unlock;
1531 1526
1532 error = fasync_helper(fd, filp, 1, &flp->fl_fasync); 1527 /*
1528 * fasync_insert_entry() returns the old entry if any.
1529 * If there was no old entry, then it used 'new' and
1530 * inserted it into the fasync list. Clear new so that
1531 * we don't release it here.
1532 */
1533 if (!fasync_insert_entry(fd, filp, &fl->fl_fasync, new))
1534 new = NULL;
1535
1533 if (error < 0) { 1536 if (error < 0) {
1534 /* remove lease just inserted by setlease */ 1537 /* remove lease just inserted by setlease */
1535 flp->fl_type = F_UNLCK | F_INPROGRESS; 1538 fl->fl_type = F_UNLCK | F_INPROGRESS;
1536 flp->fl_break_time = jiffies - 10; 1539 fl->fl_break_time = jiffies - 10;
1537 time_out_leases(inode); 1540 time_out_leases(inode);
1538 goto out_unlock; 1541 goto out_unlock;
1539 } 1542 }
@@ -1541,6 +1544,8 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
1541 error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); 1544 error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
1542out_unlock: 1545out_unlock:
1543 unlock_flocks(); 1546 unlock_flocks();
1547 if (new)
1548 fasync_free(new);
1544 return error; 1549 return error;
1545} 1550}
1546 1551
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index fd667652c502..ba306658a6db 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -1,7 +1,6 @@
1config NFS_FS 1config NFS_FS
2 tristate "NFS client support" 2 tristate "NFS client support"
3 depends on INET && FILE_LOCKING 3 depends on INET && FILE_LOCKING
4 depends on BKL # fix as soon as lockd is done
5 select LOCKD 4 select LOCKD
6 select SUNRPC 5 select SUNRPC
7 select NFS_ACL_SUPPORT if NFS_V3_ACL 6 select NFS_ACL_SUPPORT if NFS_V3_ACL
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index 31a78fce4732..18b3e8975fe0 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -2,7 +2,6 @@ config NFSD
2 tristate "NFS server support" 2 tristate "NFS server support"
3 depends on INET 3 depends on INET
4 depends on FILE_LOCKING 4 depends on FILE_LOCKING
5 depends on BKL # fix as soon as lockd is done
6 select LOCKD 5 select LOCKD
7 select SUNRPC 6 select SUNRPC
8 select EXPORTFS 7 select EXPORTFS
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9019e8ec9dc8..56347e0ac88d 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2614,7 +2614,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
2614 struct nfs4_delegation *dp; 2614 struct nfs4_delegation *dp;
2615 struct nfs4_stateowner *sop = stp->st_stateowner; 2615 struct nfs4_stateowner *sop = stp->st_stateowner;
2616 int cb_up = atomic_read(&sop->so_client->cl_cb_set); 2616 int cb_up = atomic_read(&sop->so_client->cl_cb_set);
2617 struct file_lock fl, *flp = &fl; 2617 struct file_lock *fl;
2618 int status, flag = 0; 2618 int status, flag = 0;
2619 2619
2620 flag = NFS4_OPEN_DELEGATE_NONE; 2620 flag = NFS4_OPEN_DELEGATE_NONE;
@@ -2648,20 +2648,24 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
2648 flag = NFS4_OPEN_DELEGATE_NONE; 2648 flag = NFS4_OPEN_DELEGATE_NONE;
2649 goto out; 2649 goto out;
2650 } 2650 }
2651 locks_init_lock(&fl); 2651 status = -ENOMEM;
2652 fl.fl_lmops = &nfsd_lease_mng_ops; 2652 fl = locks_alloc_lock();
2653 fl.fl_flags = FL_LEASE; 2653 if (!fl)
2654 fl.fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK; 2654 goto out;
2655 fl.fl_end = OFFSET_MAX; 2655 locks_init_lock(fl);
2656 fl.fl_owner = (fl_owner_t)dp; 2656 fl->fl_lmops = &nfsd_lease_mng_ops;
2657 fl.fl_file = find_readable_file(stp->st_file); 2657 fl->fl_flags = FL_LEASE;
2658 BUG_ON(!fl.fl_file); 2658 fl->fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK;
2659 fl.fl_pid = current->tgid; 2659 fl->fl_end = OFFSET_MAX;
2660 fl->fl_owner = (fl_owner_t)dp;
2661 fl->fl_file = find_readable_file(stp->st_file);
2662 BUG_ON(!fl->fl_file);
2663 fl->fl_pid = current->tgid;
2660 2664
2661 /* vfs_setlease checks to see if delegation should be handed out. 2665 /* vfs_setlease checks to see if delegation should be handed out.
2662 * the lock_manager callbacks fl_mylease and fl_change are used 2666 * the lock_manager callbacks fl_mylease and fl_change are used
2663 */ 2667 */
2664 if ((status = vfs_setlease(fl.fl_file, fl.fl_type, &flp))) { 2668 if ((status = vfs_setlease(fl->fl_file, fl->fl_type, &fl))) {
2665 dprintk("NFSD: setlease failed [%d], no delegation\n", status); 2669 dprintk("NFSD: setlease failed [%d], no delegation\n", status);
2666 unhash_delegation(dp); 2670 unhash_delegation(dp);
2667 flag = NFS4_OPEN_DELEGATE_NONE; 2671 flag = NFS4_OPEN_DELEGATE_NONE;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 240eb1d4f876..b2a6009cba10 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1122,6 +1122,7 @@ extern int fcntl_getlease(struct file *filp);
1122 1122
1123/* fs/locks.c */ 1123/* fs/locks.c */
1124extern void locks_init_lock(struct file_lock *); 1124extern void locks_init_lock(struct file_lock *);
1125extern struct file_lock * locks_alloc_lock(void);
1125extern void locks_copy_lock(struct file_lock *, struct file_lock *); 1126extern void locks_copy_lock(struct file_lock *, struct file_lock *);
1126extern void __locks_copy_lock(struct file_lock *, const struct file_lock *); 1127extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
1127extern void locks_remove_posix(struct file *, fl_owner_t); 1128extern void locks_remove_posix(struct file *, fl_owner_t);
@@ -1310,6 +1311,11 @@ struct fasync_struct {
1310 1311
1311/* SMP safe fasync helpers: */ 1312/* SMP safe fasync helpers: */
1312extern int fasync_helper(int, struct file *, int, struct fasync_struct **); 1313extern int fasync_helper(int, struct file *, int, struct fasync_struct **);
1314extern struct fasync_struct *fasync_insert_entry(int, struct file *, struct fasync_struct **, struct fasync_struct *);
1315extern int fasync_remove_entry(struct file *, struct fasync_struct **);
1316extern struct fasync_struct *fasync_alloc(void);
1317extern void fasync_free(struct fasync_struct *);
1318
1313/* can be called from interrupts */ 1319/* can be called from interrupts */
1314extern void kill_fasync(struct fasync_struct **, int, int); 1320extern void kill_fasync(struct fasync_struct **, int, int);
1315 1321