diff options
| author | John W. Linville <linville@tuxdriver.com> | 2006-03-15 17:02:08 -0500 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2006-03-15 17:02:08 -0500 |
| commit | dd288e7d75b9041f79fecae77d61cfa345da7266 (patch) | |
| tree | 85ff1d1ea0fe1d6eae0b6819422d5c6c05f862cd /fs | |
| parent | 30dcbf29cc6d92d70fa262e79e84011fe6913bed (diff) | |
| parent | 72df16f109b73be37977a26d342e9103e8851cb6 (diff) | |
Merge branch 'upstream-fixes'
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/buffer.c | 6 | ||||
| -rw-r--r-- | fs/direct-io.c | 21 | ||||
| -rw-r--r-- | fs/jfs/jfs_dmap.c | 7 | ||||
| -rw-r--r-- | fs/jfs/jfs_imap.c | 6 | ||||
| -rw-r--r-- | fs/lockd/clntproc.c | 9 | ||||
| -rw-r--r-- | fs/namespace.c | 5 | ||||
| -rw-r--r-- | fs/nfs/direct.c | 10 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 2 |
8 files changed, 40 insertions, 26 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 62cfd17dc5fe..a9b399402007 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -3060,6 +3060,7 @@ int buffer_migrate_page(struct page *newpage, struct page *page) | |||
| 3060 | { | 3060 | { |
| 3061 | struct address_space *mapping = page->mapping; | 3061 | struct address_space *mapping = page->mapping; |
| 3062 | struct buffer_head *bh, *head; | 3062 | struct buffer_head *bh, *head; |
| 3063 | int rc; | ||
| 3063 | 3064 | ||
| 3064 | if (!mapping) | 3065 | if (!mapping) |
| 3065 | return -EAGAIN; | 3066 | return -EAGAIN; |
| @@ -3069,8 +3070,9 @@ int buffer_migrate_page(struct page *newpage, struct page *page) | |||
| 3069 | 3070 | ||
| 3070 | head = page_buffers(page); | 3071 | head = page_buffers(page); |
| 3071 | 3072 | ||
| 3072 | if (migrate_page_remove_references(newpage, page, 3)) | 3073 | rc = migrate_page_remove_references(newpage, page, 3); |
| 3073 | return -EAGAIN; | 3074 | if (rc) |
| 3075 | return rc; | ||
| 3074 | 3076 | ||
| 3075 | bh = head; | 3077 | bh = head; |
| 3076 | do { | 3078 | do { |
diff --git a/fs/direct-io.c b/fs/direct-io.c index 848044af7e16..27f3e787faca 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
| @@ -1155,15 +1155,16 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, | |||
| 1155 | * For writes, i_mutex is not held on entry; it is never taken. | 1155 | * For writes, i_mutex is not held on entry; it is never taken. |
| 1156 | * | 1156 | * |
| 1157 | * DIO_LOCKING (simple locking for regular files) | 1157 | * DIO_LOCKING (simple locking for regular files) |
| 1158 | * For writes we are called under i_mutex and return with i_mutex held, even though | 1158 | * For writes we are called under i_mutex and return with i_mutex held, even |
| 1159 | * it is internally dropped. | 1159 | * though it is internally dropped. |
| 1160 | * For reads, i_mutex is not held on entry, but it is taken and dropped before | 1160 | * For reads, i_mutex is not held on entry, but it is taken and dropped before |
| 1161 | * returning. | 1161 | * returning. |
| 1162 | * | 1162 | * |
| 1163 | * DIO_OWN_LOCKING (filesystem provides synchronisation and handling of | 1163 | * DIO_OWN_LOCKING (filesystem provides synchronisation and handling of |
| 1164 | * uninitialised data, allowing parallel direct readers and writers) | 1164 | * uninitialised data, allowing parallel direct readers and writers) |
| 1165 | * For writes we are called without i_mutex, return without it, never touch it. | 1165 | * For writes we are called without i_mutex, return without it, never touch it. |
| 1166 | * For reads, i_mutex is held on entry and will be released before returning. | 1166 | * For reads we are called under i_mutex and return with i_mutex held, even |
| 1167 | * though it may be internally dropped. | ||
| 1167 | * | 1168 | * |
| 1168 | * Additional i_alloc_sem locking requirements described inline below. | 1169 | * Additional i_alloc_sem locking requirements described inline below. |
| 1169 | */ | 1170 | */ |
| @@ -1182,7 +1183,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | |||
| 1182 | ssize_t retval = -EINVAL; | 1183 | ssize_t retval = -EINVAL; |
| 1183 | loff_t end = offset; | 1184 | loff_t end = offset; |
| 1184 | struct dio *dio; | 1185 | struct dio *dio; |
| 1185 | int reader_with_isem = (rw == READ && dio_lock_type == DIO_OWN_LOCKING); | 1186 | int release_i_mutex = 0; |
| 1187 | int acquire_i_mutex = 0; | ||
| 1186 | 1188 | ||
| 1187 | if (rw & WRITE) | 1189 | if (rw & WRITE) |
| 1188 | current->flags |= PF_SYNCWRITE; | 1190 | current->flags |= PF_SYNCWRITE; |
| @@ -1225,7 +1227,6 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | |||
| 1225 | * writers need to grab i_alloc_sem only (i_mutex is already held) | 1227 | * writers need to grab i_alloc_sem only (i_mutex is already held) |
| 1226 | * For regular files using DIO_OWN_LOCKING, | 1228 | * For regular files using DIO_OWN_LOCKING, |
| 1227 | * neither readers nor writers take any locks here | 1229 | * neither readers nor writers take any locks here |
| 1228 | * (i_mutex is already held and release for writers here) | ||
| 1229 | */ | 1230 | */ |
| 1230 | dio->lock_type = dio_lock_type; | 1231 | dio->lock_type = dio_lock_type; |
| 1231 | if (dio_lock_type != DIO_NO_LOCKING) { | 1232 | if (dio_lock_type != DIO_NO_LOCKING) { |
| @@ -1236,7 +1237,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | |||
| 1236 | mapping = iocb->ki_filp->f_mapping; | 1237 | mapping = iocb->ki_filp->f_mapping; |
| 1237 | if (dio_lock_type != DIO_OWN_LOCKING) { | 1238 | if (dio_lock_type != DIO_OWN_LOCKING) { |
| 1238 | mutex_lock(&inode->i_mutex); | 1239 | mutex_lock(&inode->i_mutex); |
| 1239 | reader_with_isem = 1; | 1240 | release_i_mutex = 1; |
| 1240 | } | 1241 | } |
| 1241 | 1242 | ||
| 1242 | retval = filemap_write_and_wait_range(mapping, offset, | 1243 | retval = filemap_write_and_wait_range(mapping, offset, |
| @@ -1248,7 +1249,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | |||
| 1248 | 1249 | ||
| 1249 | if (dio_lock_type == DIO_OWN_LOCKING) { | 1250 | if (dio_lock_type == DIO_OWN_LOCKING) { |
| 1250 | mutex_unlock(&inode->i_mutex); | 1251 | mutex_unlock(&inode->i_mutex); |
| 1251 | reader_with_isem = 0; | 1252 | acquire_i_mutex = 1; |
| 1252 | } | 1253 | } |
| 1253 | } | 1254 | } |
| 1254 | 1255 | ||
| @@ -1269,11 +1270,13 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | |||
| 1269 | nr_segs, blkbits, get_blocks, end_io, dio); | 1270 | nr_segs, blkbits, get_blocks, end_io, dio); |
| 1270 | 1271 | ||
| 1271 | if (rw == READ && dio_lock_type == DIO_LOCKING) | 1272 | if (rw == READ && dio_lock_type == DIO_LOCKING) |
| 1272 | reader_with_isem = 0; | 1273 | release_i_mutex = 0; |
| 1273 | 1274 | ||
| 1274 | out: | 1275 | out: |
| 1275 | if (reader_with_isem) | 1276 | if (release_i_mutex) |
| 1276 | mutex_unlock(&inode->i_mutex); | 1277 | mutex_unlock(&inode->i_mutex); |
| 1278 | else if (acquire_i_mutex) | ||
| 1279 | mutex_lock(&inode->i_mutex); | ||
| 1277 | if (rw & WRITE) | 1280 | if (rw & WRITE) |
| 1278 | current->flags &= ~PF_SYNCWRITE; | 1281 | current->flags &= ~PF_SYNCWRITE; |
| 1279 | return retval; | 1282 | return retval; |
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 2967b7393415..79b5404db100 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c | |||
| @@ -532,10 +532,10 @@ dbUpdatePMap(struct inode *ipbmap, | |||
| 532 | 532 | ||
| 533 | lastlblkno = lblkno; | 533 | lastlblkno = lblkno; |
| 534 | 534 | ||
| 535 | LOGSYNC_LOCK(log, flags); | ||
| 535 | if (mp->lsn != 0) { | 536 | if (mp->lsn != 0) { |
| 536 | /* inherit older/smaller lsn */ | 537 | /* inherit older/smaller lsn */ |
| 537 | logdiff(diffp, mp->lsn, log); | 538 | logdiff(diffp, mp->lsn, log); |
| 538 | LOGSYNC_LOCK(log, flags); | ||
| 539 | if (difft < diffp) { | 539 | if (difft < diffp) { |
| 540 | mp->lsn = lsn; | 540 | mp->lsn = lsn; |
| 541 | 541 | ||
| @@ -548,20 +548,17 @@ dbUpdatePMap(struct inode *ipbmap, | |||
| 548 | logdiff(diffp, mp->clsn, log); | 548 | logdiff(diffp, mp->clsn, log); |
| 549 | if (difft > diffp) | 549 | if (difft > diffp) |
| 550 | mp->clsn = tblk->clsn; | 550 | mp->clsn = tblk->clsn; |
| 551 | LOGSYNC_UNLOCK(log, flags); | ||
| 552 | } else { | 551 | } else { |
| 553 | mp->log = log; | 552 | mp->log = log; |
| 554 | mp->lsn = lsn; | 553 | mp->lsn = lsn; |
| 555 | 554 | ||
| 556 | /* insert bp after tblock in logsync list */ | 555 | /* insert bp after tblock in logsync list */ |
| 557 | LOGSYNC_LOCK(log, flags); | ||
| 558 | |||
| 559 | log->count++; | 556 | log->count++; |
| 560 | list_add(&mp->synclist, &tblk->synclist); | 557 | list_add(&mp->synclist, &tblk->synclist); |
| 561 | 558 | ||
| 562 | mp->clsn = tblk->clsn; | 559 | mp->clsn = tblk->clsn; |
| 563 | LOGSYNC_UNLOCK(log, flags); | ||
| 564 | } | 560 | } |
| 561 | LOGSYNC_UNLOCK(log, flags); | ||
| 565 | } | 562 | } |
| 566 | 563 | ||
| 567 | /* write the last buffer. */ | 564 | /* write the last buffer. */ |
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 31b4aa13dd4b..4efa0d0eec39 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c | |||
| @@ -2844,11 +2844,11 @@ diUpdatePMap(struct inode *ipimap, | |||
| 2844 | */ | 2844 | */ |
| 2845 | lsn = tblk->lsn; | 2845 | lsn = tblk->lsn; |
| 2846 | log = JFS_SBI(tblk->sb)->log; | 2846 | log = JFS_SBI(tblk->sb)->log; |
| 2847 | LOGSYNC_LOCK(log, flags); | ||
| 2847 | if (mp->lsn != 0) { | 2848 | if (mp->lsn != 0) { |
| 2848 | /* inherit older/smaller lsn */ | 2849 | /* inherit older/smaller lsn */ |
| 2849 | logdiff(difft, lsn, log); | 2850 | logdiff(difft, lsn, log); |
| 2850 | logdiff(diffp, mp->lsn, log); | 2851 | logdiff(diffp, mp->lsn, log); |
| 2851 | LOGSYNC_LOCK(log, flags); | ||
| 2852 | if (difft < diffp) { | 2852 | if (difft < diffp) { |
| 2853 | mp->lsn = lsn; | 2853 | mp->lsn = lsn; |
| 2854 | /* move mp after tblock in logsync list */ | 2854 | /* move mp after tblock in logsync list */ |
| @@ -2860,17 +2860,15 @@ diUpdatePMap(struct inode *ipimap, | |||
| 2860 | logdiff(diffp, mp->clsn, log); | 2860 | logdiff(diffp, mp->clsn, log); |
| 2861 | if (difft > diffp) | 2861 | if (difft > diffp) |
| 2862 | mp->clsn = tblk->clsn; | 2862 | mp->clsn = tblk->clsn; |
| 2863 | LOGSYNC_UNLOCK(log, flags); | ||
| 2864 | } else { | 2863 | } else { |
| 2865 | mp->log = log; | 2864 | mp->log = log; |
| 2866 | mp->lsn = lsn; | 2865 | mp->lsn = lsn; |
| 2867 | /* insert mp after tblock in logsync list */ | 2866 | /* insert mp after tblock in logsync list */ |
| 2868 | LOGSYNC_LOCK(log, flags); | ||
| 2869 | log->count++; | 2867 | log->count++; |
| 2870 | list_add(&mp->synclist, &tblk->synclist); | 2868 | list_add(&mp->synclist, &tblk->synclist); |
| 2871 | mp->clsn = tblk->clsn; | 2869 | mp->clsn = tblk->clsn; |
| 2872 | LOGSYNC_UNLOCK(log, flags); | ||
| 2873 | } | 2870 | } |
| 2871 | LOGSYNC_UNLOCK(log, flags); | ||
| 2874 | write_metapage(mp); | 2872 | write_metapage(mp); |
| 2875 | return (0); | 2873 | return (0); |
| 2876 | } | 2874 | } |
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 220058d8616d..970b6a6aa337 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
| @@ -662,12 +662,18 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) | |||
| 662 | * reclaimed while we're stuck in the unlock call. */ | 662 | * reclaimed while we're stuck in the unlock call. */ |
| 663 | fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED; | 663 | fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED; |
| 664 | 664 | ||
| 665 | /* | ||
| 666 | * Note: the server is supposed to either grant us the unlock | ||
| 667 | * request, or to deny it with NLM_LCK_DENIED_GRACE_PERIOD. In either | ||
| 668 | * case, we want to unlock. | ||
| 669 | */ | ||
| 670 | do_vfs_lock(fl); | ||
| 671 | |||
| 665 | if (req->a_flags & RPC_TASK_ASYNC) { | 672 | if (req->a_flags & RPC_TASK_ASYNC) { |
| 666 | status = nlmclnt_async_call(req, NLMPROC_UNLOCK, | 673 | status = nlmclnt_async_call(req, NLMPROC_UNLOCK, |
| 667 | &nlmclnt_unlock_ops); | 674 | &nlmclnt_unlock_ops); |
| 668 | /* Hrmf... Do the unlock early since locks_remove_posix() | 675 | /* Hrmf... Do the unlock early since locks_remove_posix() |
| 669 | * really expects us to free the lock synchronously */ | 676 | * really expects us to free the lock synchronously */ |
| 670 | do_vfs_lock(fl); | ||
| 671 | if (status < 0) { | 677 | if (status < 0) { |
| 672 | nlmclnt_release_lockargs(req); | 678 | nlmclnt_release_lockargs(req); |
| 673 | kfree(req); | 679 | kfree(req); |
| @@ -680,7 +686,6 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) | |||
| 680 | if (status < 0) | 686 | if (status < 0) |
| 681 | return status; | 687 | return status; |
| 682 | 688 | ||
| 683 | do_vfs_lock(fl); | ||
| 684 | if (resp->status == NLM_LCK_GRANTED) | 689 | if (resp->status == NLM_LCK_GRANTED) |
| 685 | return 0; | 690 | return 0; |
| 686 | 691 | ||
diff --git a/fs/namespace.c b/fs/namespace.c index 058a44865beb..39c81a8d6316 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -1338,7 +1338,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) | |||
| 1338 | 1338 | ||
| 1339 | new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL); | 1339 | new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL); |
| 1340 | if (!new_ns) | 1340 | if (!new_ns) |
| 1341 | goto out; | 1341 | return NULL; |
| 1342 | 1342 | ||
| 1343 | atomic_set(&new_ns->count, 1); | 1343 | atomic_set(&new_ns->count, 1); |
| 1344 | INIT_LIST_HEAD(&new_ns->list); | 1344 | INIT_LIST_HEAD(&new_ns->list); |
| @@ -1352,7 +1352,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) | |||
| 1352 | if (!new_ns->root) { | 1352 | if (!new_ns->root) { |
| 1353 | up_write(&namespace_sem); | 1353 | up_write(&namespace_sem); |
| 1354 | kfree(new_ns); | 1354 | kfree(new_ns); |
| 1355 | goto out; | 1355 | return NULL; |
| 1356 | } | 1356 | } |
| 1357 | spin_lock(&vfsmount_lock); | 1357 | spin_lock(&vfsmount_lock); |
| 1358 | list_add_tail(&new_ns->list, &new_ns->root->mnt_list); | 1358 | list_add_tail(&new_ns->list, &new_ns->root->mnt_list); |
| @@ -1393,7 +1393,6 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) | |||
| 1393 | if (altrootmnt) | 1393 | if (altrootmnt) |
| 1394 | mntput(altrootmnt); | 1394 | mntput(altrootmnt); |
| 1395 | 1395 | ||
| 1396 | out: | ||
| 1397 | return new_ns; | 1396 | return new_ns; |
| 1398 | } | 1397 | } |
| 1399 | 1398 | ||
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 04ab2fc360e7..4e9b3a1b36c5 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
| @@ -57,6 +57,7 @@ | |||
| 57 | #define NFSDBG_FACILITY NFSDBG_VFS | 57 | #define NFSDBG_FACILITY NFSDBG_VFS |
| 58 | #define MAX_DIRECTIO_SIZE (4096UL << PAGE_SHIFT) | 58 | #define MAX_DIRECTIO_SIZE (4096UL << PAGE_SHIFT) |
| 59 | 59 | ||
| 60 | static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty); | ||
| 60 | static kmem_cache_t *nfs_direct_cachep; | 61 | static kmem_cache_t *nfs_direct_cachep; |
| 61 | 62 | ||
| 62 | /* | 63 | /* |
| @@ -107,6 +108,15 @@ nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, | |||
| 107 | page_count, (rw == READ), 0, | 108 | page_count, (rw == READ), 0, |
| 108 | *pages, NULL); | 109 | *pages, NULL); |
| 109 | up_read(¤t->mm->mmap_sem); | 110 | up_read(¤t->mm->mmap_sem); |
| 111 | /* | ||
| 112 | * If we got fewer pages than expected from get_user_pages(), | ||
| 113 | * the user buffer runs off the end of a mapping; return EFAULT. | ||
| 114 | */ | ||
| 115 | if (result >= 0 && result < page_count) { | ||
| 116 | nfs_free_user_pages(*pages, result, 0); | ||
| 117 | *pages = NULL; | ||
| 118 | result = -EFAULT; | ||
| 119 | } | ||
| 110 | } | 120 | } |
| 111 | return result; | 121 | return result; |
| 112 | } | 122 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 984ca3454d04..f8c0066e02e1 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -1430,7 +1430,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 1430 | if (status == 0) | 1430 | if (status == 0) |
| 1431 | status = nfs4_do_fsinfo(server, fhandle, info); | 1431 | status = nfs4_do_fsinfo(server, fhandle, info); |
| 1432 | out: | 1432 | out: |
| 1433 | return status; | 1433 | return nfs4_map_errors(status); |
| 1434 | } | 1434 | } |
| 1435 | 1435 | ||
| 1436 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 1436 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
