diff --git a/[refs] b/[refs] index 751255ae31fe..9dedc5df26d5 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 4e0641a7ad98fca5646a6be17605bc80f6c4ebde +refs/heads/master: f475ae957db66650db66916c62604ac27409d884 diff --git a/trunk/fs/locks.c b/trunk/fs/locks.c index 1ad29c9b6252..50cb0a2b74d9 100644 --- a/trunk/fs/locks.c +++ b/trunk/fs/locks.c @@ -725,6 +725,10 @@ static int posix_locks_deadlock(struct file_lock *caller_fl, /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks * at the head of the list, but that's secret knowledge known only to * flock_lock_file and posix_lock_file. + * + * Note that if called with an FL_EXISTS argument, the caller may determine + * whether or not a lock was successfully freed by testing the return + * value for -ENOENT. */ static int flock_lock_file(struct file *filp, struct file_lock *request) { @@ -750,8 +754,11 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) break; } - if (request->fl_type == F_UNLCK) + if (request->fl_type == F_UNLCK) { + if ((request->fl_flags & FL_EXISTS) && !found) + error = -ENOENT; goto out; + } error = -ENOMEM; new_fl = locks_alloc_lock(); @@ -948,8 +955,11 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request error = 0; if (!added) { - if (request->fl_type == F_UNLCK) + if (request->fl_type == F_UNLCK) { + if (request->fl_flags & FL_EXISTS) + error = -ENOENT; goto out; + } if (!new_fl) { error = -ENOLCK; @@ -996,6 +1006,10 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request * Add a POSIX style lock to a file. * We merge adjacent & overlapping locks whenever possible. * POSIX locks are sorted by owner task, then by starting address + * + * Note that if called with an FL_EXISTS argument, the caller may determine + * whether or not a lock was successfully freed by testing the return + * value for -ENOENT. */ int posix_lock_file(struct file *filp, struct file_lock *fl) { diff --git a/trunk/fs/nfs/dir.c b/trunk/fs/nfs/dir.c index e7ffb4deb3e5..3ddda6f7ecc2 100644 --- a/trunk/fs/nfs/dir.c +++ b/trunk/fs/nfs/dir.c @@ -690,9 +690,7 @@ int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) goto out_force; /* This is an open(2) */ if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 && - !(server->flags & NFS_MOUNT_NOCTO) && - (S_ISREG(inode->i_mode) || - S_ISDIR(inode->i_mode))) + !(server->flags & NFS_MOUNT_NOCTO)) goto out_force; } return nfs_revalidate_inode(server, inode); diff --git a/trunk/fs/nfs/write.c b/trunk/fs/nfs/write.c index 86bac6a5008e..bca5734ca9fb 100644 --- a/trunk/fs/nfs/write.c +++ b/trunk/fs/nfs/write.c @@ -578,7 +578,7 @@ static int nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, un return ret; } -static void nfs_cancel_dirty_list(struct list_head *head) +static void nfs_cancel_requests(struct list_head *head) { struct nfs_page *req; while(!list_empty(head)) { @@ -589,19 +589,6 @@ static void nfs_cancel_dirty_list(struct list_head *head) } } -static void nfs_cancel_commit_list(struct list_head *head) -{ - struct nfs_page *req; - - while(!list_empty(head)) { - req = nfs_list_entry(head->next); - nfs_list_remove_request(req); - nfs_inode_remove_request(req); - nfs_clear_page_writeback(req); - dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); - } -} - /* * nfs_scan_dirty - Scan an inode for dirty requests * @inode: NFS inode to scan @@ -1394,7 +1381,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) nfs_list_remove_request(req); nfs_mark_request_commit(req); nfs_clear_page_writeback(req); - dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); } return -ENOMEM; } @@ -1513,7 +1499,7 @@ int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start, if (pages != 0) { spin_unlock(&nfsi->req_lock); if (how & FLUSH_INVALIDATE) - nfs_cancel_dirty_list(&head); + nfs_cancel_requests(&head); else ret = nfs_flush_list(inode, &head, pages, how); spin_lock(&nfsi->req_lock); @@ -1526,7 +1512,7 @@ int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start, break; if (how & FLUSH_INVALIDATE) { spin_unlock(&nfsi->req_lock); - nfs_cancel_commit_list(&head); + nfs_cancel_requests(&head); spin_lock(&nfsi->req_lock); continue; } diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 134b32068246..43aef9b230fd 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -716,6 +716,7 @@ extern spinlock_t files_lock; #define FL_POSIX 1 #define FL_FLOCK 2 #define FL_ACCESS 8 /* not trying to lock, just looking */ +#define FL_EXISTS 16 /* when unlocking, test for existence */ #define FL_LEASE 32 /* lease held on this file */ #define FL_CLOSE 64 /* unlock on close */ #define FL_SLEEP 128 /* A blocking lock */ diff --git a/trunk/net/sunrpc/xdr.c b/trunk/net/sunrpc/xdr.c index 6ac45103a272..49174f0d0a3e 100644 --- a/trunk/net/sunrpc/xdr.c +++ b/trunk/net/sunrpc/xdr.c @@ -191,6 +191,7 @@ _shift_data_right_pages(struct page **pages, size_t pgto_base, do { /* Are any pointers crossing a page boundary? */ if (pgto_base == 0) { + flush_dcache_page(*pgto); pgto_base = PAGE_CACHE_SIZE; pgto--; } @@ -210,11 +211,11 @@ _shift_data_right_pages(struct page **pages, size_t pgto_base, vto = kmap_atomic(*pgto, KM_USER0); vfrom = kmap_atomic(*pgfrom, KM_USER1); memmove(vto + pgto_base, vfrom + pgfrom_base, copy); - flush_dcache_page(*pgto); kunmap_atomic(vfrom, KM_USER1); kunmap_atomic(vto, KM_USER0); } while ((len -= copy) != 0); + flush_dcache_page(*pgto); } /*