aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-24 08:41:41 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-24 13:07:53 -0400
commit816724e65c72a90a44fbad0ef0b59b186c85fa90 (patch)
tree421fa29aedff988e392f92780637553e275d37a0 /fs/locks.c
parent70ac4385a13f78bc478f26d317511893741b05bd (diff)
parentd384ea691fe4ea8c2dd5b9b8d9042eb181776f18 (diff)
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Conflicts: fs/nfs/inode.c fs/super.c Fix conflicts between patch 'NFS: Split fs/nfs/inode.c' and patch 'VFS: Permit filesystem to override root dentry on mount'
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c123
1 files changed, 32 insertions, 91 deletions
diff --git a/fs/locks.c b/fs/locks.c
index ab61a8b54829..1ad29c9b6252 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -703,7 +703,7 @@ EXPORT_SYMBOL(posix_test_lock);
703 * from a broken NFS client. But broken NFS clients have a lot more to 703 * from a broken NFS client. But broken NFS clients have a lot more to
704 * worry about than proper deadlock detection anyway... --okir 704 * worry about than proper deadlock detection anyway... --okir
705 */ 705 */
706int posix_locks_deadlock(struct file_lock *caller_fl, 706static int posix_locks_deadlock(struct file_lock *caller_fl,
707 struct file_lock *block_fl) 707 struct file_lock *block_fl)
708{ 708{
709 struct list_head *tmp; 709 struct list_head *tmp;
@@ -722,8 +722,6 @@ next_task:
722 return 0; 722 return 0;
723} 723}
724 724
725EXPORT_SYMBOL(posix_locks_deadlock);
726
727/* Try to create a FLOCK lock on filp. We always insert new FLOCK locks 725/* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
728 * at the head of the list, but that's secret knowledge known only to 726 * at the head of the list, but that's secret knowledge known only to
729 * flock_lock_file and posix_lock_file. 727 * flock_lock_file and posix_lock_file.
@@ -794,7 +792,8 @@ out:
794static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) 792static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
795{ 793{
796 struct file_lock *fl; 794 struct file_lock *fl;
797 struct file_lock *new_fl, *new_fl2; 795 struct file_lock *new_fl = NULL;
796 struct file_lock *new_fl2 = NULL;
798 struct file_lock *left = NULL; 797 struct file_lock *left = NULL;
799 struct file_lock *right = NULL; 798 struct file_lock *right = NULL;
800 struct file_lock **before; 799 struct file_lock **before;
@@ -803,9 +802,15 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
803 /* 802 /*
804 * We may need two file_lock structures for this operation, 803 * We may need two file_lock structures for this operation,
805 * so we get them in advance to avoid races. 804 * so we get them in advance to avoid races.
805 *
806 * In some cases we can be sure, that no new locks will be needed
806 */ 807 */
807 new_fl = locks_alloc_lock(); 808 if (!(request->fl_flags & FL_ACCESS) &&
808 new_fl2 = locks_alloc_lock(); 809 (request->fl_type != F_UNLCK ||
810 request->fl_start != 0 || request->fl_end != OFFSET_MAX)) {
811 new_fl = locks_alloc_lock();
812 new_fl2 = locks_alloc_lock();
813 }
809 814
810 lock_kernel(); 815 lock_kernel();
811 if (request->fl_type != F_UNLCK) { 816 if (request->fl_type != F_UNLCK) {
@@ -834,14 +839,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
834 if (request->fl_flags & FL_ACCESS) 839 if (request->fl_flags & FL_ACCESS)
835 goto out; 840 goto out;
836 841
837 error = -ENOLCK; /* "no luck" */
838 if (!(new_fl && new_fl2))
839 goto out;
840
841 /* 842 /*
842 * We've allocated the new locks in advance, so there are no
843 * errors possible (and no blocking operations) from here on.
844 *
845 * Find the first old lock with the same owner as the new lock. 843 * Find the first old lock with the same owner as the new lock.
846 */ 844 */
847 845
@@ -938,10 +936,25 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
938 before = &fl->fl_next; 936 before = &fl->fl_next;
939 } 937 }
940 938
939 /*
940 * The above code only modifies existing locks in case of
941 * merging or replacing. If new lock(s) need to be inserted
942 * all modifications are done bellow this, so it's safe yet to
943 * bail out.
944 */
945 error = -ENOLCK; /* "no luck" */
946 if (right && left == right && !new_fl2)
947 goto out;
948
941 error = 0; 949 error = 0;
942 if (!added) { 950 if (!added) {
943 if (request->fl_type == F_UNLCK) 951 if (request->fl_type == F_UNLCK)
944 goto out; 952 goto out;
953
954 if (!new_fl) {
955 error = -ENOLCK;
956 goto out;
957 }
945 locks_copy_lock(new_fl, request); 958 locks_copy_lock(new_fl, request);
946 locks_insert_lock(before, new_fl); 959 locks_insert_lock(before, new_fl);
947 new_fl = NULL; 960 new_fl = NULL;
@@ -1881,19 +1894,18 @@ out:
1881 */ 1894 */
1882void locks_remove_posix(struct file *filp, fl_owner_t owner) 1895void locks_remove_posix(struct file *filp, fl_owner_t owner)
1883{ 1896{
1884 struct file_lock lock, **before; 1897 struct file_lock lock;
1885 1898
1886 /* 1899 /*
1887 * If there are no locks held on this file, we don't need to call 1900 * If there are no locks held on this file, we don't need to call
1888 * posix_lock_file(). Another process could be setting a lock on this 1901 * posix_lock_file(). Another process could be setting a lock on this
1889 * file at the same time, but we wouldn't remove that lock anyway. 1902 * file at the same time, but we wouldn't remove that lock anyway.
1890 */ 1903 */
1891 before = &filp->f_dentry->d_inode->i_flock; 1904 if (!filp->f_dentry->d_inode->i_flock)
1892 if (*before == NULL)
1893 return; 1905 return;
1894 1906
1895 lock.fl_type = F_UNLCK; 1907 lock.fl_type = F_UNLCK;
1896 lock.fl_flags = FL_POSIX; 1908 lock.fl_flags = FL_POSIX | FL_CLOSE;
1897 lock.fl_start = 0; 1909 lock.fl_start = 0;
1898 lock.fl_end = OFFSET_MAX; 1910 lock.fl_end = OFFSET_MAX;
1899 lock.fl_owner = owner; 1911 lock.fl_owner = owner;
@@ -1902,25 +1914,11 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
1902 lock.fl_ops = NULL; 1914 lock.fl_ops = NULL;
1903 lock.fl_lmops = NULL; 1915 lock.fl_lmops = NULL;
1904 1916
1905 if (filp->f_op && filp->f_op->lock != NULL) { 1917 if (filp->f_op && filp->f_op->lock != NULL)
1906 filp->f_op->lock(filp, F_SETLK, &lock); 1918 filp->f_op->lock(filp, F_SETLK, &lock);
1907 goto out; 1919 else
1908 } 1920 posix_lock_file(filp, &lock);
1909 1921
1910 /* Can't use posix_lock_file here; we need to remove it no matter
1911 * which pid we have.
1912 */
1913 lock_kernel();
1914 while (*before != NULL) {
1915 struct file_lock *fl = *before;
1916 if (IS_POSIX(fl) && posix_same_owner(fl, &lock)) {
1917 locks_delete_lock(before);
1918 continue;
1919 }
1920 before = &fl->fl_next;
1921 }
1922 unlock_kernel();
1923out:
1924 if (lock.fl_ops && lock.fl_ops->fl_release_private) 1922 if (lock.fl_ops && lock.fl_ops->fl_release_private)
1925 lock.fl_ops->fl_release_private(&lock); 1923 lock.fl_ops->fl_release_private(&lock);
1926} 1924}
@@ -2206,63 +2204,6 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len)
2206 2204
2207EXPORT_SYMBOL(lock_may_write); 2205EXPORT_SYMBOL(lock_may_write);
2208 2206
2209static inline void __steal_locks(struct file *file, fl_owner_t from)
2210{
2211 struct inode *inode = file->f_dentry->d_inode;
2212 struct file_lock *fl = inode->i_flock;
2213
2214 while (fl) {
2215 if (fl->fl_file == file && fl->fl_owner == from)
2216 fl->fl_owner = current->files;
2217 fl = fl->fl_next;
2218 }
2219}
2220
2221/* When getting ready for executing a binary, we make sure that current
2222 * has a files_struct on its own. Before dropping the old files_struct,
2223 * we take over ownership of all locks for all file descriptors we own.
2224 * Note that we may accidentally steal a lock for a file that a sibling
2225 * has created since the unshare_files() call.
2226 */
2227void steal_locks(fl_owner_t from)
2228{
2229 struct files_struct *files = current->files;
2230 int i, j;
2231 struct fdtable *fdt;
2232
2233 if (from == files)
2234 return;
2235
2236 lock_kernel();
2237 j = 0;
2238
2239 /*
2240 * We are not taking a ref to the file structures, so
2241 * we need to acquire ->file_lock.
2242 */
2243 spin_lock(&files->file_lock);
2244 fdt = files_fdtable(files);
2245 for (;;) {
2246 unsigned long set;
2247 i = j * __NFDBITS;
2248 if (i >= fdt->max_fdset || i >= fdt->max_fds)
2249 break;
2250 set = fdt->open_fds->fds_bits[j++];
2251 while (set) {
2252 if (set & 1) {
2253 struct file *file = fdt->fd[i];
2254 if (file)
2255 __steal_locks(file, from);
2256 }
2257 i++;
2258 set >>= 1;
2259 }
2260 }
2261 spin_unlock(&files->file_lock);
2262 unlock_kernel();
2263}
2264EXPORT_SYMBOL(steal_locks);
2265
2266static int __init filelock_init(void) 2207static int __init filelock_init(void)
2267{ 2208{
2268 filelock_cache = kmem_cache_create("file_lock_cache", 2209 filelock_cache = kmem_cache_create("file_lock_cache",