diff options
| author | David Vrabel <david.vrabel@citrix.com> | 2014-04-07 08:52:12 -0400 |
|---|---|---|
| committer | David Vrabel <david.vrabel@citrix.com> | 2014-04-07 08:52:12 -0400 |
| commit | 2c5cb2770392fb9c5d8518688c8bc61986d70dc6 (patch) | |
| tree | b19210e709de6ee0d22b67ef605a569500cf1a18 /fs | |
| parent | cd979883b9ede90643e019f33cb317933eb867b4 (diff) | |
| parent | 683b6c6f82a60fabf47012581c2cfbf1b037ab95 (diff) | |
Merge commit '683b6c6f82a60fabf47012581c2cfbf1b037ab95' into stable/for-linus-3.15
This merge of the irq-core-for-linus branch broke the ARM build when
Xen is enabled.
Conflicts:
drivers/xen/events/events_base.c
Diffstat (limited to 'fs')
59 files changed, 607 insertions, 380 deletions
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 6621f8008122..be75b500005d 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
| @@ -75,6 +75,7 @@ struct afs_call { | |||
| 75 | const struct afs_call_type *type; /* type of call */ | 75 | const struct afs_call_type *type; /* type of call */ |
| 76 | const struct afs_wait_mode *wait_mode; /* completion wait mode */ | 76 | const struct afs_wait_mode *wait_mode; /* completion wait mode */ |
| 77 | wait_queue_head_t waitq; /* processes awaiting completion */ | 77 | wait_queue_head_t waitq; /* processes awaiting completion */ |
| 78 | work_func_t async_workfn; | ||
| 78 | struct work_struct async_work; /* asynchronous work processor */ | 79 | struct work_struct async_work; /* asynchronous work processor */ |
| 79 | struct work_struct work; /* actual work processor */ | 80 | struct work_struct work; /* actual work processor */ |
| 80 | struct sk_buff_head rx_queue; /* received packets */ | 81 | struct sk_buff_head rx_queue; /* received packets */ |
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 8ad8c2a0703a..ef943df73b8c 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c | |||
| @@ -644,7 +644,7 @@ static void afs_process_async_call(struct work_struct *work) | |||
| 644 | 644 | ||
| 645 | /* we can't just delete the call because the work item may be | 645 | /* we can't just delete the call because the work item may be |
| 646 | * queued */ | 646 | * queued */ |
| 647 | PREPARE_WORK(&call->async_work, afs_delete_async_call); | 647 | call->async_workfn = afs_delete_async_call; |
| 648 | queue_work(afs_async_calls, &call->async_work); | 648 | queue_work(afs_async_calls, &call->async_work); |
| 649 | } | 649 | } |
| 650 | 650 | ||
| @@ -663,6 +663,13 @@ void afs_transfer_reply(struct afs_call *call, struct sk_buff *skb) | |||
| 663 | call->reply_size += len; | 663 | call->reply_size += len; |
| 664 | } | 664 | } |
| 665 | 665 | ||
| 666 | static void afs_async_workfn(struct work_struct *work) | ||
| 667 | { | ||
| 668 | struct afs_call *call = container_of(work, struct afs_call, async_work); | ||
| 669 | |||
| 670 | call->async_workfn(work); | ||
| 671 | } | ||
| 672 | |||
| 666 | /* | 673 | /* |
| 667 | * accept the backlog of incoming calls | 674 | * accept the backlog of incoming calls |
| 668 | */ | 675 | */ |
| @@ -685,7 +692,8 @@ static void afs_collect_incoming_call(struct work_struct *work) | |||
| 685 | return; | 692 | return; |
| 686 | } | 693 | } |
| 687 | 694 | ||
| 688 | INIT_WORK(&call->async_work, afs_process_async_call); | 695 | call->async_workfn = afs_process_async_call; |
| 696 | INIT_WORK(&call->async_work, afs_async_workfn); | ||
| 689 | call->wait_mode = &afs_async_incoming_call; | 697 | call->wait_mode = &afs_async_incoming_call; |
| 690 | call->type = &afs_RXCMxxxx; | 698 | call->type = &afs_RXCMxxxx; |
| 691 | init_waitqueue_head(&call->waitq); | 699 | init_waitqueue_head(&call->waitq); |
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 24084732b1d0..80ef38c73e5a 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c | |||
| @@ -41,19 +41,8 @@ static const struct dentry_operations anon_inodefs_dentry_operations = { | |||
| 41 | static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type, | 41 | static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type, |
| 42 | int flags, const char *dev_name, void *data) | 42 | int flags, const char *dev_name, void *data) |
| 43 | { | 43 | { |
| 44 | struct dentry *root; | 44 | return mount_pseudo(fs_type, "anon_inode:", NULL, |
| 45 | root = mount_pseudo(fs_type, "anon_inode:", NULL, | ||
| 46 | &anon_inodefs_dentry_operations, ANON_INODE_FS_MAGIC); | 45 | &anon_inodefs_dentry_operations, ANON_INODE_FS_MAGIC); |
| 47 | if (!IS_ERR(root)) { | ||
| 48 | struct super_block *s = root->d_sb; | ||
| 49 | anon_inode_inode = alloc_anon_inode(s); | ||
| 50 | if (IS_ERR(anon_inode_inode)) { | ||
| 51 | dput(root); | ||
| 52 | deactivate_locked_super(s); | ||
| 53 | root = ERR_CAST(anon_inode_inode); | ||
| 54 | } | ||
| 55 | } | ||
| 56 | return root; | ||
| 57 | } | 46 | } |
| 58 | 47 | ||
| 59 | static struct file_system_type anon_inode_fs_type = { | 48 | static struct file_system_type anon_inode_fs_type = { |
| @@ -175,22 +164,15 @@ EXPORT_SYMBOL_GPL(anon_inode_getfd); | |||
| 175 | 164 | ||
| 176 | static int __init anon_inode_init(void) | 165 | static int __init anon_inode_init(void) |
| 177 | { | 166 | { |
| 178 | int error; | ||
| 179 | |||
| 180 | error = register_filesystem(&anon_inode_fs_type); | ||
| 181 | if (error) | ||
| 182 | goto err_exit; | ||
| 183 | anon_inode_mnt = kern_mount(&anon_inode_fs_type); | 167 | anon_inode_mnt = kern_mount(&anon_inode_fs_type); |
| 184 | if (IS_ERR(anon_inode_mnt)) { | 168 | if (IS_ERR(anon_inode_mnt)) |
| 185 | error = PTR_ERR(anon_inode_mnt); | 169 | panic("anon_inode_init() kernel mount failed (%ld)\n", PTR_ERR(anon_inode_mnt)); |
| 186 | goto err_unregister_filesystem; | ||
| 187 | } | ||
| 188 | return 0; | ||
| 189 | 170 | ||
| 190 | err_unregister_filesystem: | 171 | anon_inode_inode = alloc_anon_inode(anon_inode_mnt->mnt_sb); |
| 191 | unregister_filesystem(&anon_inode_fs_type); | 172 | if (IS_ERR(anon_inode_inode)) |
| 192 | err_exit: | 173 | panic("anon_inode_init() inode allocation failed (%ld)\n", PTR_ERR(anon_inode_inode)); |
| 193 | panic(KERN_ERR "anon_inode_init() failed (%d)\n", error); | 174 | |
| 175 | return 0; | ||
| 194 | } | 176 | } |
| 195 | 177 | ||
| 196 | fs_initcall(anon_inode_init); | 178 | fs_initcall(anon_inode_init); |
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 0129b78a6908..4f70f383132c 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c | |||
| @@ -458,11 +458,10 @@ static int bio_integrity_verify(struct bio *bio) | |||
| 458 | struct blk_integrity_exchg bix; | 458 | struct blk_integrity_exchg bix; |
| 459 | struct bio_vec *bv; | 459 | struct bio_vec *bv; |
| 460 | sector_t sector = bio->bi_integrity->bip_iter.bi_sector; | 460 | sector_t sector = bio->bi_integrity->bip_iter.bi_sector; |
| 461 | unsigned int sectors, total, ret; | 461 | unsigned int sectors, ret = 0; |
| 462 | void *prot_buf = bio->bi_integrity->bip_buf; | 462 | void *prot_buf = bio->bi_integrity->bip_buf; |
| 463 | int i; | 463 | int i; |
| 464 | 464 | ||
| 465 | ret = total = 0; | ||
| 466 | bix.disk_name = bio->bi_bdev->bd_disk->disk_name; | 465 | bix.disk_name = bio->bi_bdev->bd_disk->disk_name; |
| 467 | bix.sector_size = bi->sector_size; | 466 | bix.sector_size = bi->sector_size; |
| 468 | 467 | ||
| @@ -484,8 +483,6 @@ static int bio_integrity_verify(struct bio *bio) | |||
| 484 | sectors = bv->bv_len / bi->sector_size; | 483 | sectors = bv->bv_len / bi->sector_size; |
| 485 | sector += sectors; | 484 | sector += sectors; |
| 486 | prot_buf += sectors * bi->tuple_size; | 485 | prot_buf += sectors * bi->tuple_size; |
| 487 | total += sectors * bi->tuple_size; | ||
| 488 | BUG_ON(total > bio->bi_integrity->bip_iter.bi_size); | ||
| 489 | 486 | ||
| 490 | kunmap_atomic(kaddr); | 487 | kunmap_atomic(kaddr); |
| 491 | } | 488 | } |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index cf32f0393369..c0f3718b77a8 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -513,7 +513,7 @@ struct cifs_mnt_data { | |||
| 513 | static inline unsigned int | 513 | static inline unsigned int |
| 514 | get_rfc1002_length(void *buf) | 514 | get_rfc1002_length(void *buf) |
| 515 | { | 515 | { |
| 516 | return be32_to_cpu(*((__be32 *)buf)); | 516 | return be32_to_cpu(*((__be32 *)buf)) & 0xffffff; |
| 517 | } | 517 | } |
| 518 | 518 | ||
| 519 | static inline void | 519 | static inline void |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 53c15074bb36..834fce759d80 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -2579,31 +2579,19 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov, | |||
| 2579 | struct cifsInodeInfo *cinode = CIFS_I(inode); | 2579 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
| 2580 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; | 2580 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; |
| 2581 | ssize_t rc = -EACCES; | 2581 | ssize_t rc = -EACCES; |
| 2582 | loff_t lock_pos = pos; | ||
| 2582 | 2583 | ||
| 2583 | BUG_ON(iocb->ki_pos != pos); | 2584 | if (file->f_flags & O_APPEND) |
| 2584 | 2585 | lock_pos = i_size_read(inode); | |
| 2585 | /* | 2586 | /* |
| 2586 | * We need to hold the sem to be sure nobody modifies lock list | 2587 | * We need to hold the sem to be sure nobody modifies lock list |
| 2587 | * with a brlock that prevents writing. | 2588 | * with a brlock that prevents writing. |
| 2588 | */ | 2589 | */ |
| 2589 | down_read(&cinode->lock_sem); | 2590 | down_read(&cinode->lock_sem); |
| 2590 | if (!cifs_find_lock_conflict(cfile, pos, iov_length(iov, nr_segs), | 2591 | if (!cifs_find_lock_conflict(cfile, lock_pos, iov_length(iov, nr_segs), |
| 2591 | server->vals->exclusive_lock_type, NULL, | 2592 | server->vals->exclusive_lock_type, NULL, |
| 2592 | CIFS_WRITE_OP)) { | 2593 | CIFS_WRITE_OP)) |
| 2593 | mutex_lock(&inode->i_mutex); | 2594 | rc = generic_file_aio_write(iocb, iov, nr_segs, pos); |
| 2594 | rc = __generic_file_aio_write(iocb, iov, nr_segs, | ||
| 2595 | &iocb->ki_pos); | ||
| 2596 | mutex_unlock(&inode->i_mutex); | ||
| 2597 | } | ||
| 2598 | |||
| 2599 | if (rc > 0) { | ||
| 2600 | ssize_t err; | ||
| 2601 | |||
| 2602 | err = generic_write_sync(file, iocb->ki_pos - rc, rc); | ||
| 2603 | if (err < 0) | ||
| 2604 | rc = err; | ||
| 2605 | } | ||
| 2606 | |||
| 2607 | up_read(&cinode->lock_sem); | 2595 | up_read(&cinode->lock_sem); |
| 2608 | return rc; | 2596 | return rc; |
| 2609 | } | 2597 | } |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index b37570952846..18cd5650a5fc 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
| @@ -270,6 +270,26 @@ cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx, | |||
| 270 | iov->iov_len = rqst->rq_pagesz; | 270 | iov->iov_len = rqst->rq_pagesz; |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | static unsigned long | ||
| 274 | rqst_len(struct smb_rqst *rqst) | ||
| 275 | { | ||
| 276 | unsigned int i; | ||
| 277 | struct kvec *iov = rqst->rq_iov; | ||
| 278 | unsigned long buflen = 0; | ||
| 279 | |||
| 280 | /* total up iov array first */ | ||
| 281 | for (i = 0; i < rqst->rq_nvec; i++) | ||
| 282 | buflen += iov[i].iov_len; | ||
| 283 | |||
| 284 | /* add in the page array if there is one */ | ||
| 285 | if (rqst->rq_npages) { | ||
| 286 | buflen += rqst->rq_pagesz * (rqst->rq_npages - 1); | ||
| 287 | buflen += rqst->rq_tailsz; | ||
| 288 | } | ||
| 289 | |||
| 290 | return buflen; | ||
| 291 | } | ||
| 292 | |||
| 273 | static int | 293 | static int |
| 274 | smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) | 294 | smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) |
| 275 | { | 295 | { |
| @@ -277,6 +297,7 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) | |||
| 277 | struct kvec *iov = rqst->rq_iov; | 297 | struct kvec *iov = rqst->rq_iov; |
| 278 | int n_vec = rqst->rq_nvec; | 298 | int n_vec = rqst->rq_nvec; |
| 279 | unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base); | 299 | unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base); |
| 300 | unsigned long send_length; | ||
| 280 | unsigned int i; | 301 | unsigned int i; |
| 281 | size_t total_len = 0, sent; | 302 | size_t total_len = 0, sent; |
| 282 | struct socket *ssocket = server->ssocket; | 303 | struct socket *ssocket = server->ssocket; |
| @@ -285,6 +306,14 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) | |||
| 285 | if (ssocket == NULL) | 306 | if (ssocket == NULL) |
| 286 | return -ENOTSOCK; | 307 | return -ENOTSOCK; |
| 287 | 308 | ||
| 309 | /* sanity check send length */ | ||
| 310 | send_length = rqst_len(rqst); | ||
| 311 | if (send_length != smb_buf_length + 4) { | ||
| 312 | WARN(1, "Send length mismatch(send_length=%lu smb_buf_length=%u)\n", | ||
| 313 | send_length, smb_buf_length); | ||
| 314 | return -EIO; | ||
| 315 | } | ||
| 316 | |||
| 288 | cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length); | 317 | cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length); |
| 289 | dump_smb(iov[0].iov_base, iov[0].iov_len); | 318 | dump_smb(iov[0].iov_base, iov[0].iov_len); |
| 290 | 319 | ||
diff --git a/fs/compat.c b/fs/compat.c index 6af20de2c1a3..19252b97f0cc 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
| @@ -72,8 +72,8 @@ int compat_printk(const char *fmt, ...) | |||
| 72 | * Not all architectures have sys_utime, so implement this in terms | 72 | * Not all architectures have sys_utime, so implement this in terms |
| 73 | * of sys_utimes. | 73 | * of sys_utimes. |
| 74 | */ | 74 | */ |
| 75 | asmlinkage long compat_sys_utime(const char __user *filename, | 75 | COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, |
| 76 | struct compat_utimbuf __user *t) | 76 | struct compat_utimbuf __user *, t) |
| 77 | { | 77 | { |
| 78 | struct timespec tv[2]; | 78 | struct timespec tv[2]; |
| 79 | 79 | ||
| @@ -87,7 +87,7 @@ asmlinkage long compat_sys_utime(const char __user *filename, | |||
| 87 | return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0); | 87 | return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filename, struct compat_timespec __user *t, int flags) | 90 | COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags) |
| 91 | { | 91 | { |
| 92 | struct timespec tv[2]; | 92 | struct timespec tv[2]; |
| 93 | 93 | ||
| @@ -102,7 +102,7 @@ asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filena | |||
| 102 | return do_utimes(dfd, filename, t ? tv : NULL, flags); | 102 | return do_utimes(dfd, filename, t ? tv : NULL, flags); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filename, struct compat_timeval __user *t) | 105 | COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t) |
| 106 | { | 106 | { |
| 107 | struct timespec tv[2]; | 107 | struct timespec tv[2]; |
| 108 | 108 | ||
| @@ -121,7 +121,7 @@ asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filena | |||
| 121 | return do_utimes(dfd, filename, t ? tv : NULL, 0); | 121 | return do_utimes(dfd, filename, t ? tv : NULL, 0); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | asmlinkage long compat_sys_utimes(const char __user *filename, struct compat_timeval __user *t) | 124 | COMPAT_SYSCALL_DEFINE2(utimes, const char __user *, filename, struct compat_timeval __user *, t) |
| 125 | { | 125 | { |
| 126 | return compat_sys_futimesat(AT_FDCWD, filename, t); | 126 | return compat_sys_futimesat(AT_FDCWD, filename, t); |
| 127 | } | 127 | } |
| @@ -159,8 +159,8 @@ static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf) | |||
| 159 | return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; | 159 | return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | asmlinkage long compat_sys_newstat(const char __user * filename, | 162 | COMPAT_SYSCALL_DEFINE2(newstat, const char __user *, filename, |
| 163 | struct compat_stat __user *statbuf) | 163 | struct compat_stat __user *, statbuf) |
| 164 | { | 164 | { |
| 165 | struct kstat stat; | 165 | struct kstat stat; |
| 166 | int error; | 166 | int error; |
| @@ -171,8 +171,8 @@ asmlinkage long compat_sys_newstat(const char __user * filename, | |||
| 171 | return cp_compat_stat(&stat, statbuf); | 171 | return cp_compat_stat(&stat, statbuf); |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | asmlinkage long compat_sys_newlstat(const char __user * filename, | 174 | COMPAT_SYSCALL_DEFINE2(newlstat, const char __user *, filename, |
| 175 | struct compat_stat __user *statbuf) | 175 | struct compat_stat __user *, statbuf) |
| 176 | { | 176 | { |
| 177 | struct kstat stat; | 177 | struct kstat stat; |
| 178 | int error; | 178 | int error; |
| @@ -184,9 +184,9 @@ asmlinkage long compat_sys_newlstat(const char __user * filename, | |||
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | #ifndef __ARCH_WANT_STAT64 | 186 | #ifndef __ARCH_WANT_STAT64 |
| 187 | asmlinkage long compat_sys_newfstatat(unsigned int dfd, | 187 | COMPAT_SYSCALL_DEFINE4(newfstatat, unsigned int, dfd, |
| 188 | const char __user *filename, | 188 | const char __user *, filename, |
| 189 | struct compat_stat __user *statbuf, int flag) | 189 | struct compat_stat __user *, statbuf, int, flag) |
| 190 | { | 190 | { |
| 191 | struct kstat stat; | 191 | struct kstat stat; |
| 192 | int error; | 192 | int error; |
| @@ -198,8 +198,8 @@ asmlinkage long compat_sys_newfstatat(unsigned int dfd, | |||
| 198 | } | 198 | } |
| 199 | #endif | 199 | #endif |
| 200 | 200 | ||
| 201 | asmlinkage long compat_sys_newfstat(unsigned int fd, | 201 | COMPAT_SYSCALL_DEFINE2(newfstat, unsigned int, fd, |
| 202 | struct compat_stat __user * statbuf) | 202 | struct compat_stat __user *, statbuf) |
| 203 | { | 203 | { |
| 204 | struct kstat stat; | 204 | struct kstat stat; |
| 205 | int error = vfs_fstat(fd, &stat); | 205 | int error = vfs_fstat(fd, &stat); |
| @@ -247,7 +247,7 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs * | |||
| 247 | * The following statfs calls are copies of code from fs/statfs.c and | 247 | * The following statfs calls are copies of code from fs/statfs.c and |
| 248 | * should be checked against those from time to time | 248 | * should be checked against those from time to time |
| 249 | */ | 249 | */ |
| 250 | asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf) | 250 | COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf) |
| 251 | { | 251 | { |
| 252 | struct kstatfs tmp; | 252 | struct kstatfs tmp; |
| 253 | int error = user_statfs(pathname, &tmp); | 253 | int error = user_statfs(pathname, &tmp); |
| @@ -256,7 +256,7 @@ asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_sta | |||
| 256 | return error; | 256 | return error; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf) | 259 | COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf) |
| 260 | { | 260 | { |
| 261 | struct kstatfs tmp; | 261 | struct kstatfs tmp; |
| 262 | int error = fd_statfs(fd, &tmp); | 262 | int error = fd_statfs(fd, &tmp); |
| @@ -298,7 +298,7 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat | |||
| 298 | return 0; | 298 | return 0; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf) | 301 | COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf) |
| 302 | { | 302 | { |
| 303 | struct kstatfs tmp; | 303 | struct kstatfs tmp; |
| 304 | int error; | 304 | int error; |
| @@ -312,7 +312,7 @@ asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t s | |||
| 312 | return error; | 312 | return error; |
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf) | 315 | COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf) |
| 316 | { | 316 | { |
| 317 | struct kstatfs tmp; | 317 | struct kstatfs tmp; |
| 318 | int error; | 318 | int error; |
| @@ -331,7 +331,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c | |||
| 331 | * Given how simple this syscall is that apporach is more maintainable | 331 | * Given how simple this syscall is that apporach is more maintainable |
| 332 | * than the various conversion hacks. | 332 | * than the various conversion hacks. |
| 333 | */ | 333 | */ |
| 334 | asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u) | 334 | COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u) |
| 335 | { | 335 | { |
| 336 | struct compat_ustat tmp; | 336 | struct compat_ustat tmp; |
| 337 | struct kstatfs sbuf; | 337 | struct kstatfs sbuf; |
| @@ -399,8 +399,8 @@ static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *u | |||
| 399 | } | 399 | } |
| 400 | #endif | 400 | #endif |
| 401 | 401 | ||
| 402 | asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, | 402 | COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, |
| 403 | unsigned long arg) | 403 | compat_ulong_t, arg) |
| 404 | { | 404 | { |
| 405 | mm_segment_t old_fs; | 405 | mm_segment_t old_fs; |
| 406 | struct flock f; | 406 | struct flock f; |
| @@ -468,16 +468,15 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, | |||
| 468 | return ret; | 468 | return ret; |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd, | 471 | COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, |
| 472 | unsigned long arg) | 472 | compat_ulong_t, arg) |
| 473 | { | 473 | { |
| 474 | if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64)) | 474 | if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64)) |
| 475 | return -EINVAL; | 475 | return -EINVAL; |
| 476 | return compat_sys_fcntl64(fd, cmd, arg); | 476 | return compat_sys_fcntl64(fd, cmd, arg); |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | asmlinkage long | 479 | COMPAT_SYSCALL_DEFINE2(io_setup, unsigned, nr_reqs, u32 __user *, ctx32p) |
| 480 | compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p) | ||
| 481 | { | 480 | { |
| 482 | long ret; | 481 | long ret; |
| 483 | aio_context_t ctx64; | 482 | aio_context_t ctx64; |
| @@ -496,32 +495,24 @@ compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p) | |||
| 496 | return ret; | 495 | return ret; |
| 497 | } | 496 | } |
| 498 | 497 | ||
| 499 | asmlinkage long | 498 | COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id, |
| 500 | compat_sys_io_getevents(aio_context_t ctx_id, | 499 | compat_long_t, min_nr, |
| 501 | unsigned long min_nr, | 500 | compat_long_t, nr, |
| 502 | unsigned long nr, | 501 | struct io_event __user *, events, |
| 503 | struct io_event __user *events, | 502 | struct compat_timespec __user *, timeout) |
| 504 | struct compat_timespec __user *timeout) | ||
| 505 | { | 503 | { |
| 506 | long ret; | ||
| 507 | struct timespec t; | 504 | struct timespec t; |
| 508 | struct timespec __user *ut = NULL; | 505 | struct timespec __user *ut = NULL; |
| 509 | 506 | ||
| 510 | ret = -EFAULT; | ||
| 511 | if (unlikely(!access_ok(VERIFY_WRITE, events, | ||
| 512 | nr * sizeof(struct io_event)))) | ||
| 513 | goto out; | ||
| 514 | if (timeout) { | 507 | if (timeout) { |
| 515 | if (get_compat_timespec(&t, timeout)) | 508 | if (get_compat_timespec(&t, timeout)) |
| 516 | goto out; | 509 | return -EFAULT; |
| 517 | 510 | ||
| 518 | ut = compat_alloc_user_space(sizeof(*ut)); | 511 | ut = compat_alloc_user_space(sizeof(*ut)); |
| 519 | if (copy_to_user(ut, &t, sizeof(t)) ) | 512 | if (copy_to_user(ut, &t, sizeof(t)) ) |
| 520 | goto out; | 513 | return -EFAULT; |
| 521 | } | 514 | } |
| 522 | ret = sys_io_getevents(ctx_id, min_nr, nr, events, ut); | 515 | return sys_io_getevents(ctx_id, min_nr, nr, events, ut); |
| 523 | out: | ||
| 524 | return ret; | ||
| 525 | } | 516 | } |
| 526 | 517 | ||
| 527 | /* A write operation does a read from user space and vice versa */ | 518 | /* A write operation does a read from user space and vice versa */ |
| @@ -617,8 +608,8 @@ copy_iocb(long nr, u32 __user *ptr32, struct iocb __user * __user *ptr64) | |||
| 617 | 608 | ||
| 618 | #define MAX_AIO_SUBMITS (PAGE_SIZE/sizeof(struct iocb *)) | 609 | #define MAX_AIO_SUBMITS (PAGE_SIZE/sizeof(struct iocb *)) |
| 619 | 610 | ||
| 620 | asmlinkage long | 611 | COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, |
| 621 | compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 __user *iocb) | 612 | int, nr, u32 __user *, iocb) |
| 622 | { | 613 | { |
| 623 | struct iocb __user * __user *iocb64; | 614 | struct iocb __user * __user *iocb64; |
| 624 | long ret; | 615 | long ret; |
| @@ -770,10 +761,10 @@ static int do_nfs4_super_data_conv(void *raw_data) | |||
| 770 | #define NCPFS_NAME "ncpfs" | 761 | #define NCPFS_NAME "ncpfs" |
| 771 | #define NFS4_NAME "nfs4" | 762 | #define NFS4_NAME "nfs4" |
| 772 | 763 | ||
| 773 | asmlinkage long compat_sys_mount(const char __user * dev_name, | 764 | COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name, |
| 774 | const char __user * dir_name, | 765 | const char __user *, dir_name, |
| 775 | const char __user * type, unsigned long flags, | 766 | const char __user *, type, compat_ulong_t, flags, |
| 776 | const void __user * data) | 767 | const void __user *, data) |
| 777 | { | 768 | { |
| 778 | char *kernel_type; | 769 | char *kernel_type; |
| 779 | unsigned long data_page; | 770 | unsigned long data_page; |
| @@ -869,8 +860,8 @@ efault: | |||
| 869 | return -EFAULT; | 860 | return -EFAULT; |
| 870 | } | 861 | } |
| 871 | 862 | ||
| 872 | asmlinkage long compat_sys_old_readdir(unsigned int fd, | 863 | COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd, |
| 873 | struct compat_old_linux_dirent __user *dirent, unsigned int count) | 864 | struct compat_old_linux_dirent __user *, dirent, unsigned int, count) |
| 874 | { | 865 | { |
| 875 | int error; | 866 | int error; |
| 876 | struct fd f = fdget(fd); | 867 | struct fd f = fdget(fd); |
| @@ -948,8 +939,8 @@ efault: | |||
| 948 | return -EFAULT; | 939 | return -EFAULT; |
| 949 | } | 940 | } |
| 950 | 941 | ||
| 951 | asmlinkage long compat_sys_getdents(unsigned int fd, | 942 | COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd, |
| 952 | struct compat_linux_dirent __user *dirent, unsigned int count) | 943 | struct compat_linux_dirent __user *, dirent, unsigned int, count) |
| 953 | { | 944 | { |
| 954 | struct fd f; | 945 | struct fd f; |
| 955 | struct compat_linux_dirent __user * lastdirent; | 946 | struct compat_linux_dirent __user * lastdirent; |
| @@ -981,7 +972,7 @@ asmlinkage long compat_sys_getdents(unsigned int fd, | |||
| 981 | return error; | 972 | return error; |
| 982 | } | 973 | } |
| 983 | 974 | ||
| 984 | #ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64 | 975 | #ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64 |
| 985 | 976 | ||
| 986 | struct compat_getdents_callback64 { | 977 | struct compat_getdents_callback64 { |
| 987 | struct dir_context ctx; | 978 | struct dir_context ctx; |
| @@ -1033,8 +1024,8 @@ efault: | |||
| 1033 | return -EFAULT; | 1024 | return -EFAULT; |
| 1034 | } | 1025 | } |
| 1035 | 1026 | ||
| 1036 | asmlinkage long compat_sys_getdents64(unsigned int fd, | 1027 | COMPAT_SYSCALL_DEFINE3(getdents64, unsigned int, fd, |
| 1037 | struct linux_dirent64 __user * dirent, unsigned int count) | 1028 | struct linux_dirent64 __user *, dirent, unsigned int, count) |
| 1038 | { | 1029 | { |
| 1039 | struct fd f; | 1030 | struct fd f; |
| 1040 | struct linux_dirent64 __user * lastdirent; | 1031 | struct linux_dirent64 __user * lastdirent; |
| @@ -1066,7 +1057,7 @@ asmlinkage long compat_sys_getdents64(unsigned int fd, | |||
| 1066 | fdput(f); | 1057 | fdput(f); |
| 1067 | return error; | 1058 | return error; |
| 1068 | } | 1059 | } |
| 1069 | #endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */ | 1060 | #endif /* __ARCH_WANT_COMPAT_SYS_GETDENTS64 */ |
| 1070 | 1061 | ||
| 1071 | /* | 1062 | /* |
| 1072 | * Exactly like fs/open.c:sys_open(), except that it doesn't set the | 1063 | * Exactly like fs/open.c:sys_open(), except that it doesn't set the |
| @@ -1287,9 +1278,9 @@ out_nofds: | |||
| 1287 | return ret; | 1278 | return ret; |
| 1288 | } | 1279 | } |
| 1289 | 1280 | ||
| 1290 | asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, | 1281 | COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp, |
| 1291 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, | 1282 | compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, |
| 1292 | struct compat_timeval __user *tvp) | 1283 | struct compat_timeval __user *, tvp) |
| 1293 | { | 1284 | { |
| 1294 | struct timespec end_time, *to = NULL; | 1285 | struct timespec end_time, *to = NULL; |
| 1295 | struct compat_timeval tv; | 1286 | struct compat_timeval tv; |
| @@ -1320,7 +1311,7 @@ struct compat_sel_arg_struct { | |||
| 1320 | compat_uptr_t tvp; | 1311 | compat_uptr_t tvp; |
| 1321 | }; | 1312 | }; |
| 1322 | 1313 | ||
| 1323 | asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg) | 1314 | COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg) |
| 1324 | { | 1315 | { |
| 1325 | struct compat_sel_arg_struct a; | 1316 | struct compat_sel_arg_struct a; |
| 1326 | 1317 | ||
| @@ -1381,9 +1372,9 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, | |||
| 1381 | return ret; | 1372 | return ret; |
| 1382 | } | 1373 | } |
| 1383 | 1374 | ||
| 1384 | asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp, | 1375 | COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp, |
| 1385 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, | 1376 | compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, |
| 1386 | struct compat_timespec __user *tsp, void __user *sig) | 1377 | struct compat_timespec __user *, tsp, void __user *, sig) |
| 1387 | { | 1378 | { |
| 1388 | compat_size_t sigsetsize = 0; | 1379 | compat_size_t sigsetsize = 0; |
| 1389 | compat_uptr_t up = 0; | 1380 | compat_uptr_t up = 0; |
| @@ -1400,9 +1391,9 @@ asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp, | |||
| 1400 | sigsetsize); | 1391 | sigsetsize); |
| 1401 | } | 1392 | } |
| 1402 | 1393 | ||
| 1403 | asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, | 1394 | COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, |
| 1404 | unsigned int nfds, struct compat_timespec __user *tsp, | 1395 | unsigned int, nfds, struct compat_timespec __user *, tsp, |
| 1405 | const compat_sigset_t __user *sigmask, compat_size_t sigsetsize) | 1396 | const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize) |
| 1406 | { | 1397 | { |
| 1407 | compat_sigset_t ss32; | 1398 | compat_sigset_t ss32; |
| 1408 | sigset_t ksigmask, sigsaved; | 1399 | sigset_t ksigmask, sigsaved; |
diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c index a81147e2e4ef..4d24d17bcfc1 100644 --- a/fs/compat_binfmt_elf.c +++ b/fs/compat_binfmt_elf.c | |||
| @@ -88,6 +88,11 @@ static void cputime_to_compat_timeval(const cputime_t cputime, | |||
| 88 | #define ELF_HWCAP COMPAT_ELF_HWCAP | 88 | #define ELF_HWCAP COMPAT_ELF_HWCAP |
| 89 | #endif | 89 | #endif |
| 90 | 90 | ||
| 91 | #ifdef COMPAT_ELF_HWCAP2 | ||
| 92 | #undef ELF_HWCAP2 | ||
| 93 | #define ELF_HWCAP2 COMPAT_ELF_HWCAP2 | ||
| 94 | #endif | ||
| 95 | |||
| 91 | #ifdef COMPAT_ARCH_DLINFO | 96 | #ifdef COMPAT_ARCH_DLINFO |
| 92 | #undef ARCH_DLINFO | 97 | #undef ARCH_DLINFO |
| 93 | #define ARCH_DLINFO COMPAT_ARCH_DLINFO | 98 | #define ARCH_DLINFO COMPAT_ARCH_DLINFO |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 3881610b6438..e82289047272 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
| @@ -1538,9 +1538,10 @@ static int compat_ioctl_check_table(unsigned int xcmd) | |||
| 1538 | return ioctl_pointer[i] == xcmd; | 1538 | return ioctl_pointer[i] == xcmd; |
| 1539 | } | 1539 | } |
| 1540 | 1540 | ||
| 1541 | asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, | 1541 | COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, |
| 1542 | unsigned long arg) | 1542 | compat_ulong_t, arg32) |
| 1543 | { | 1543 | { |
| 1544 | unsigned long arg = arg32; | ||
| 1544 | struct fd f = fdget(fd); | 1545 | struct fd f = fdget(fd); |
| 1545 | int error = -EBADF; | 1546 | int error = -EBADF; |
| 1546 | if (!f.file) | 1547 | if (!f.file) |
diff --git a/fs/dcache.c b/fs/dcache.c index 265e0ce9769c..ca02c13a84aa 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -2833,9 +2833,9 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name) | |||
| 2833 | u32 dlen = ACCESS_ONCE(name->len); | 2833 | u32 dlen = ACCESS_ONCE(name->len); |
| 2834 | char *p; | 2834 | char *p; |
| 2835 | 2835 | ||
| 2836 | if (*buflen < dlen + 1) | ||
| 2837 | return -ENAMETOOLONG; | ||
| 2838 | *buflen -= dlen + 1; | 2836 | *buflen -= dlen + 1; |
| 2837 | if (*buflen < 0) | ||
| 2838 | return -ENAMETOOLONG; | ||
| 2839 | p = *buffer -= dlen + 1; | 2839 | p = *buffer -= dlen + 1; |
| 2840 | *p++ = '/'; | 2840 | *p++ = '/'; |
| 2841 | while (dlen--) { | 2841 | while (dlen--) { |
diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c index 8dd524f32284..cdb2971192a5 100644 --- a/fs/efivarfs/file.c +++ b/fs/efivarfs/file.c | |||
| @@ -21,7 +21,7 @@ static ssize_t efivarfs_file_write(struct file *file, | |||
| 21 | u32 attributes; | 21 | u32 attributes; |
| 22 | struct inode *inode = file->f_mapping->host; | 22 | struct inode *inode = file->f_mapping->host; |
| 23 | unsigned long datasize = count - sizeof(attributes); | 23 | unsigned long datasize = count - sizeof(attributes); |
| 24 | ssize_t bytes = 0; | 24 | ssize_t bytes; |
| 25 | bool set = false; | 25 | bool set = false; |
| 26 | 26 | ||
| 27 | if (count < sizeof(attributes)) | 27 | if (count < sizeof(attributes)) |
| @@ -33,14 +33,9 @@ static ssize_t efivarfs_file_write(struct file *file, | |||
| 33 | if (attributes & ~(EFI_VARIABLE_MASK)) | 33 | if (attributes & ~(EFI_VARIABLE_MASK)) |
| 34 | return -EINVAL; | 34 | return -EINVAL; |
| 35 | 35 | ||
| 36 | data = kmalloc(datasize, GFP_KERNEL); | 36 | data = memdup_user(userbuf + sizeof(attributes), datasize); |
| 37 | if (!data) | 37 | if (IS_ERR(data)) |
| 38 | return -ENOMEM; | 38 | return PTR_ERR(data); |
| 39 | |||
| 40 | if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { | ||
| 41 | bytes = -EFAULT; | ||
| 42 | goto out; | ||
| 43 | } | ||
| 44 | 39 | ||
| 45 | bytes = efivar_entry_set_get_size(var, attributes, &datasize, | 40 | bytes = efivar_entry_set_get_size(var, attributes, &datasize, |
| 46 | data, &set); | 41 | data, &set); |
| @@ -1619,9 +1619,9 @@ SYSCALL_DEFINE3(execve, | |||
| 1619 | return do_execve(getname(filename), argv, envp); | 1619 | return do_execve(getname(filename), argv, envp); |
| 1620 | } | 1620 | } |
| 1621 | #ifdef CONFIG_COMPAT | 1621 | #ifdef CONFIG_COMPAT |
| 1622 | asmlinkage long compat_sys_execve(const char __user * filename, | 1622 | COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename, |
| 1623 | const compat_uptr_t __user * argv, | 1623 | const compat_uptr_t __user *, argv, |
| 1624 | const compat_uptr_t __user * envp) | 1624 | const compat_uptr_t __user *, envp) |
| 1625 | { | 1625 | { |
| 1626 | return compat_do_execve(getname(filename), argv, envp); | 1626 | return compat_do_execve(getname(filename), argv, envp); |
| 1627 | } | 1627 | } |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 6e39895a91b8..24bfd7ff3049 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
| 39 | #include <linux/ratelimit.h> | 39 | #include <linux/ratelimit.h> |
| 40 | #include <linux/aio.h> | 40 | #include <linux/aio.h> |
| 41 | #include <linux/bitops.h> | ||
| 41 | 42 | ||
| 42 | #include "ext4_jbd2.h" | 43 | #include "ext4_jbd2.h" |
| 43 | #include "xattr.h" | 44 | #include "xattr.h" |
| @@ -3921,18 +3922,20 @@ int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc) | |||
| 3921 | void ext4_set_inode_flags(struct inode *inode) | 3922 | void ext4_set_inode_flags(struct inode *inode) |
| 3922 | { | 3923 | { |
| 3923 | unsigned int flags = EXT4_I(inode)->i_flags; | 3924 | unsigned int flags = EXT4_I(inode)->i_flags; |
| 3925 | unsigned int new_fl = 0; | ||
| 3924 | 3926 | ||
| 3925 | inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); | ||
| 3926 | if (flags & EXT4_SYNC_FL) | 3927 | if (flags & EXT4_SYNC_FL) |
| 3927 | inode->i_flags |= S_SYNC; | 3928 | new_fl |= S_SYNC; |
| 3928 | if (flags & EXT4_APPEND_FL) | 3929 | if (flags & EXT4_APPEND_FL) |
| 3929 | inode->i_flags |= S_APPEND; | 3930 | new_fl |= S_APPEND; |
| 3930 | if (flags & EXT4_IMMUTABLE_FL) | 3931 | if (flags & EXT4_IMMUTABLE_FL) |
| 3931 | inode->i_flags |= S_IMMUTABLE; | 3932 | new_fl |= S_IMMUTABLE; |
| 3932 | if (flags & EXT4_NOATIME_FL) | 3933 | if (flags & EXT4_NOATIME_FL) |
| 3933 | inode->i_flags |= S_NOATIME; | 3934 | new_fl |= S_NOATIME; |
| 3934 | if (flags & EXT4_DIRSYNC_FL) | 3935 | if (flags & EXT4_DIRSYNC_FL) |
| 3935 | inode->i_flags |= S_DIRSYNC; | 3936 | new_fl |= S_DIRSYNC; |
| 3937 | set_mask_bits(&inode->i_flags, | ||
| 3938 | S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC, new_fl); | ||
| 3936 | } | 3939 | } |
| 3937 | 3940 | ||
| 3938 | /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */ | 3941 | /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */ |
| @@ -497,7 +497,7 @@ repeat: | |||
| 497 | error = fd; | 497 | error = fd; |
| 498 | #if 1 | 498 | #if 1 |
| 499 | /* Sanity check */ | 499 | /* Sanity check */ |
| 500 | if (rcu_dereference_raw(fdt->fd[fd]) != NULL) { | 500 | if (rcu_access_pointer(fdt->fd[fd]) != NULL) { |
| 501 | printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd); | 501 | printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd); |
| 502 | rcu_assign_pointer(fdt->fd[fd], NULL); | 502 | rcu_assign_pointer(fdt->fd[fd], NULL); |
| 503 | } | 503 | } |
| @@ -683,35 +683,54 @@ EXPORT_SYMBOL(fget_raw); | |||
| 683 | * The fput_needed flag returned by fget_light should be passed to the | 683 | * The fput_needed flag returned by fget_light should be passed to the |
| 684 | * corresponding fput_light. | 684 | * corresponding fput_light. |
| 685 | */ | 685 | */ |
| 686 | struct file *__fget_light(unsigned int fd, fmode_t mask, int *fput_needed) | 686 | static unsigned long __fget_light(unsigned int fd, fmode_t mask) |
| 687 | { | 687 | { |
| 688 | struct files_struct *files = current->files; | 688 | struct files_struct *files = current->files; |
| 689 | struct file *file; | 689 | struct file *file; |
| 690 | 690 | ||
| 691 | *fput_needed = 0; | ||
| 692 | if (atomic_read(&files->count) == 1) { | 691 | if (atomic_read(&files->count) == 1) { |
| 693 | file = __fcheck_files(files, fd); | 692 | file = __fcheck_files(files, fd); |
| 694 | if (file && (file->f_mode & mask)) | 693 | if (!file || unlikely(file->f_mode & mask)) |
| 695 | file = NULL; | 694 | return 0; |
| 695 | return (unsigned long)file; | ||
| 696 | } else { | 696 | } else { |
| 697 | file = __fget(fd, mask); | 697 | file = __fget(fd, mask); |
| 698 | if (file) | 698 | if (!file) |
| 699 | *fput_needed = 1; | 699 | return 0; |
| 700 | return FDPUT_FPUT | (unsigned long)file; | ||
| 700 | } | 701 | } |
| 701 | |||
| 702 | return file; | ||
| 703 | } | 702 | } |
| 704 | struct file *fget_light(unsigned int fd, int *fput_needed) | 703 | unsigned long __fdget(unsigned int fd) |
| 705 | { | 704 | { |
| 706 | return __fget_light(fd, FMODE_PATH, fput_needed); | 705 | return __fget_light(fd, FMODE_PATH); |
| 707 | } | 706 | } |
| 708 | EXPORT_SYMBOL(fget_light); | 707 | EXPORT_SYMBOL(__fdget); |
| 709 | 708 | ||
| 710 | struct file *fget_raw_light(unsigned int fd, int *fput_needed) | 709 | unsigned long __fdget_raw(unsigned int fd) |
| 711 | { | 710 | { |
| 712 | return __fget_light(fd, 0, fput_needed); | 711 | return __fget_light(fd, 0); |
| 713 | } | 712 | } |
| 714 | 713 | ||
| 714 | unsigned long __fdget_pos(unsigned int fd) | ||
| 715 | { | ||
| 716 | unsigned long v = __fdget(fd); | ||
| 717 | struct file *file = (struct file *)(v & ~3); | ||
| 718 | |||
| 719 | if (file && (file->f_mode & FMODE_ATOMIC_POS)) { | ||
| 720 | if (file_count(file) > 1) { | ||
| 721 | v |= FDPUT_POS_UNLOCK; | ||
| 722 | mutex_lock(&file->f_pos_lock); | ||
| 723 | } | ||
| 724 | } | ||
| 725 | return v; | ||
| 726 | } | ||
| 727 | |||
| 728 | /* | ||
| 729 | * We only lock f_pos if we have threads or if the file might be | ||
| 730 | * shared with another process. In both cases we'll have an elevated | ||
| 731 | * file count (done either by fdget() or by fork()). | ||
| 732 | */ | ||
| 733 | |||
| 715 | void set_close_on_exec(unsigned int fd, int flag) | 734 | void set_close_on_exec(unsigned int fd, int flag) |
| 716 | { | 735 | { |
| 717 | struct files_struct *files = current->files; | 736 | struct files_struct *files = current->files; |
diff --git a/fs/file_table.c b/fs/file_table.c index 5fff9030be34..5b24008ea4f6 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
| @@ -135,6 +135,7 @@ struct file *get_empty_filp(void) | |||
| 135 | atomic_long_set(&f->f_count, 1); | 135 | atomic_long_set(&f->f_count, 1); |
| 136 | rwlock_init(&f->f_owner.lock); | 136 | rwlock_init(&f->f_owner.lock); |
| 137 | spin_lock_init(&f->f_lock); | 137 | spin_lock_init(&f->f_lock); |
| 138 | mutex_init(&f->f_pos_lock); | ||
| 138 | eventpoll_init_file(f); | 139 | eventpoll_init_file(f); |
| 139 | /* f->f_version: 0 */ | 140 | /* f->f_version: 0 */ |
| 140 | return f; | 141 | return f; |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index e0259a163f98..d754e3cf99a8 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -40,18 +40,13 @@ | |||
| 40 | struct wb_writeback_work { | 40 | struct wb_writeback_work { |
| 41 | long nr_pages; | 41 | long nr_pages; |
| 42 | struct super_block *sb; | 42 | struct super_block *sb; |
| 43 | /* | 43 | unsigned long *older_than_this; |
| 44 | * Write only inodes dirtied before this time. Don't forget to set | ||
| 45 | * older_than_this_is_set when you set this. | ||
| 46 | */ | ||
| 47 | unsigned long older_than_this; | ||
| 48 | enum writeback_sync_modes sync_mode; | 44 | enum writeback_sync_modes sync_mode; |
| 49 | unsigned int tagged_writepages:1; | 45 | unsigned int tagged_writepages:1; |
| 50 | unsigned int for_kupdate:1; | 46 | unsigned int for_kupdate:1; |
| 51 | unsigned int range_cyclic:1; | 47 | unsigned int range_cyclic:1; |
| 52 | unsigned int for_background:1; | 48 | unsigned int for_background:1; |
| 53 | unsigned int for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ | 49 | unsigned int for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ |
| 54 | unsigned int older_than_this_is_set:1; | ||
| 55 | enum wb_reason reason; /* why was writeback initiated? */ | 50 | enum wb_reason reason; /* why was writeback initiated? */ |
| 56 | 51 | ||
| 57 | struct list_head list; /* pending work list */ | 52 | struct list_head list; /* pending work list */ |
| @@ -252,10 +247,10 @@ static int move_expired_inodes(struct list_head *delaying_queue, | |||
| 252 | int do_sb_sort = 0; | 247 | int do_sb_sort = 0; |
| 253 | int moved = 0; | 248 | int moved = 0; |
| 254 | 249 | ||
| 255 | WARN_ON_ONCE(!work->older_than_this_is_set); | ||
| 256 | while (!list_empty(delaying_queue)) { | 250 | while (!list_empty(delaying_queue)) { |
| 257 | inode = wb_inode(delaying_queue->prev); | 251 | inode = wb_inode(delaying_queue->prev); |
| 258 | if (inode_dirtied_after(inode, work->older_than_this)) | 252 | if (work->older_than_this && |
| 253 | inode_dirtied_after(inode, *work->older_than_this)) | ||
| 259 | break; | 254 | break; |
| 260 | list_move(&inode->i_wb_list, &tmp); | 255 | list_move(&inode->i_wb_list, &tmp); |
| 261 | moved++; | 256 | moved++; |
| @@ -742,8 +737,6 @@ static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, | |||
| 742 | .sync_mode = WB_SYNC_NONE, | 737 | .sync_mode = WB_SYNC_NONE, |
| 743 | .range_cyclic = 1, | 738 | .range_cyclic = 1, |
| 744 | .reason = reason, | 739 | .reason = reason, |
| 745 | .older_than_this = jiffies, | ||
| 746 | .older_than_this_is_set = 1, | ||
| 747 | }; | 740 | }; |
| 748 | 741 | ||
| 749 | spin_lock(&wb->list_lock); | 742 | spin_lock(&wb->list_lock); |
| @@ -802,13 +795,12 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
| 802 | { | 795 | { |
| 803 | unsigned long wb_start = jiffies; | 796 | unsigned long wb_start = jiffies; |
| 804 | long nr_pages = work->nr_pages; | 797 | long nr_pages = work->nr_pages; |
| 798 | unsigned long oldest_jif; | ||
| 805 | struct inode *inode; | 799 | struct inode *inode; |
| 806 | long progress; | 800 | long progress; |
| 807 | 801 | ||
| 808 | if (!work->older_than_this_is_set) { | 802 | oldest_jif = jiffies; |
| 809 | work->older_than_this = jiffies; | 803 | work->older_than_this = &oldest_jif; |
| 810 | work->older_than_this_is_set = 1; | ||
| 811 | } | ||
| 812 | 804 | ||
| 813 | spin_lock(&wb->list_lock); | 805 | spin_lock(&wb->list_lock); |
| 814 | for (;;) { | 806 | for (;;) { |
| @@ -842,10 +834,10 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
| 842 | * safe. | 834 | * safe. |
| 843 | */ | 835 | */ |
| 844 | if (work->for_kupdate) { | 836 | if (work->for_kupdate) { |
| 845 | work->older_than_this = jiffies - | 837 | oldest_jif = jiffies - |
| 846 | msecs_to_jiffies(dirty_expire_interval * 10); | 838 | msecs_to_jiffies(dirty_expire_interval * 10); |
| 847 | } else if (work->for_background) | 839 | } else if (work->for_background) |
| 848 | work->older_than_this = jiffies; | 840 | oldest_jif = jiffies; |
| 849 | 841 | ||
| 850 | trace_writeback_start(wb->bdi, work); | 842 | trace_writeback_start(wb->bdi, work); |
| 851 | if (list_empty(&wb->b_io)) | 843 | if (list_empty(&wb->b_io)) |
| @@ -1357,21 +1349,18 @@ EXPORT_SYMBOL(try_to_writeback_inodes_sb); | |||
| 1357 | 1349 | ||
| 1358 | /** | 1350 | /** |
| 1359 | * sync_inodes_sb - sync sb inode pages | 1351 | * sync_inodes_sb - sync sb inode pages |
| 1360 | * @sb: the superblock | 1352 | * @sb: the superblock |
| 1361 | * @older_than_this: timestamp | ||
| 1362 | * | 1353 | * |
| 1363 | * This function writes and waits on any dirty inode belonging to this | 1354 | * This function writes and waits on any dirty inode belonging to this |
| 1364 | * superblock that has been dirtied before given timestamp. | 1355 | * super_block. |
| 1365 | */ | 1356 | */ |
| 1366 | void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this) | 1357 | void sync_inodes_sb(struct super_block *sb) |
| 1367 | { | 1358 | { |
| 1368 | DECLARE_COMPLETION_ONSTACK(done); | 1359 | DECLARE_COMPLETION_ONSTACK(done); |
| 1369 | struct wb_writeback_work work = { | 1360 | struct wb_writeback_work work = { |
| 1370 | .sb = sb, | 1361 | .sb = sb, |
| 1371 | .sync_mode = WB_SYNC_ALL, | 1362 | .sync_mode = WB_SYNC_ALL, |
| 1372 | .nr_pages = LONG_MAX, | 1363 | .nr_pages = LONG_MAX, |
| 1373 | .older_than_this = older_than_this, | ||
| 1374 | .older_than_this_is_set = 1, | ||
| 1375 | .range_cyclic = 0, | 1364 | .range_cyclic = 0, |
| 1376 | .done = &done, | 1365 | .done = &done, |
| 1377 | .reason = WB_REASON_SYNC, | 1366 | .reason = WB_REASON_SYNC, |
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index 968ce411db53..32602c667b4a 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c | |||
| @@ -103,6 +103,8 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, | |||
| 103 | folder = &entry->folder; | 103 | folder = &entry->folder; |
| 104 | memset(folder, 0, sizeof(*folder)); | 104 | memset(folder, 0, sizeof(*folder)); |
| 105 | folder->type = cpu_to_be16(HFSPLUS_FOLDER); | 105 | folder->type = cpu_to_be16(HFSPLUS_FOLDER); |
| 106 | if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) | ||
| 107 | folder->flags |= cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT); | ||
| 106 | folder->id = cpu_to_be32(inode->i_ino); | 108 | folder->id = cpu_to_be32(inode->i_ino); |
| 107 | HFSPLUS_I(inode)->create_date = | 109 | HFSPLUS_I(inode)->create_date = |
| 108 | folder->create_date = | 110 | folder->create_date = |
| @@ -203,6 +205,36 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid, | |||
| 203 | return hfs_brec_find(fd, hfs_find_rec_by_key); | 205 | return hfs_brec_find(fd, hfs_find_rec_by_key); |
| 204 | } | 206 | } |
| 205 | 207 | ||
| 208 | static void hfsplus_subfolders_inc(struct inode *dir) | ||
| 209 | { | ||
| 210 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); | ||
| 211 | |||
| 212 | if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) { | ||
| 213 | /* | ||
| 214 | * Increment subfolder count. Note, the value is only meaningful | ||
| 215 | * for folders with HFSPLUS_HAS_FOLDER_COUNT flag set. | ||
| 216 | */ | ||
| 217 | HFSPLUS_I(dir)->subfolders++; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | static void hfsplus_subfolders_dec(struct inode *dir) | ||
| 222 | { | ||
| 223 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); | ||
| 224 | |||
| 225 | if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) { | ||
| 226 | /* | ||
| 227 | * Decrement subfolder count. Note, the value is only meaningful | ||
| 228 | * for folders with HFSPLUS_HAS_FOLDER_COUNT flag set. | ||
| 229 | * | ||
| 230 | * Check for zero. Some subfolders may have been created | ||
| 231 | * by an implementation ignorant of this counter. | ||
| 232 | */ | ||
| 233 | if (HFSPLUS_I(dir)->subfolders) | ||
| 234 | HFSPLUS_I(dir)->subfolders--; | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 206 | int hfsplus_create_cat(u32 cnid, struct inode *dir, | 238 | int hfsplus_create_cat(u32 cnid, struct inode *dir, |
| 207 | struct qstr *str, struct inode *inode) | 239 | struct qstr *str, struct inode *inode) |
| 208 | { | 240 | { |
| @@ -247,6 +279,8 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir, | |||
| 247 | goto err1; | 279 | goto err1; |
| 248 | 280 | ||
| 249 | dir->i_size++; | 281 | dir->i_size++; |
| 282 | if (S_ISDIR(inode->i_mode)) | ||
| 283 | hfsplus_subfolders_inc(dir); | ||
| 250 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 284 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
| 251 | hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY); | 285 | hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY); |
| 252 | 286 | ||
| @@ -336,6 +370,8 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) | |||
| 336 | goto out; | 370 | goto out; |
| 337 | 371 | ||
| 338 | dir->i_size--; | 372 | dir->i_size--; |
| 373 | if (type == HFSPLUS_FOLDER) | ||
| 374 | hfsplus_subfolders_dec(dir); | ||
| 339 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 375 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
| 340 | hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY); | 376 | hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY); |
| 341 | 377 | ||
| @@ -380,6 +416,7 @@ int hfsplus_rename_cat(u32 cnid, | |||
| 380 | 416 | ||
| 381 | hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset, | 417 | hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset, |
| 382 | src_fd.entrylength); | 418 | src_fd.entrylength); |
| 419 | type = be16_to_cpu(entry.type); | ||
| 383 | 420 | ||
| 384 | /* create new dir entry with the data from the old entry */ | 421 | /* create new dir entry with the data from the old entry */ |
| 385 | hfsplus_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name); | 422 | hfsplus_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name); |
| @@ -394,6 +431,8 @@ int hfsplus_rename_cat(u32 cnid, | |||
| 394 | if (err) | 431 | if (err) |
| 395 | goto out; | 432 | goto out; |
| 396 | dst_dir->i_size++; | 433 | dst_dir->i_size++; |
| 434 | if (type == HFSPLUS_FOLDER) | ||
| 435 | hfsplus_subfolders_inc(dst_dir); | ||
| 397 | dst_dir->i_mtime = dst_dir->i_ctime = CURRENT_TIME_SEC; | 436 | dst_dir->i_mtime = dst_dir->i_ctime = CURRENT_TIME_SEC; |
| 398 | 437 | ||
| 399 | /* finally remove the old entry */ | 438 | /* finally remove the old entry */ |
| @@ -405,6 +444,8 @@ int hfsplus_rename_cat(u32 cnid, | |||
| 405 | if (err) | 444 | if (err) |
| 406 | goto out; | 445 | goto out; |
| 407 | src_dir->i_size--; | 446 | src_dir->i_size--; |
| 447 | if (type == HFSPLUS_FOLDER) | ||
| 448 | hfsplus_subfolders_dec(src_dir); | ||
| 408 | src_dir->i_mtime = src_dir->i_ctime = CURRENT_TIME_SEC; | 449 | src_dir->i_mtime = src_dir->i_ctime = CURRENT_TIME_SEC; |
| 409 | 450 | ||
| 410 | /* remove old thread entry */ | 451 | /* remove old thread entry */ |
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 08846425b67f..62d571eb69ba 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
| @@ -242,6 +242,7 @@ struct hfsplus_inode_info { | |||
| 242 | */ | 242 | */ |
| 243 | sector_t fs_blocks; | 243 | sector_t fs_blocks; |
| 244 | u8 userflags; /* BSD user file flags */ | 244 | u8 userflags; /* BSD user file flags */ |
| 245 | u32 subfolders; /* Subfolder count (HFSX only) */ | ||
| 245 | struct list_head open_dir_list; | 246 | struct list_head open_dir_list; |
| 246 | loff_t phys_size; | 247 | loff_t phys_size; |
| 247 | 248 | ||
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h index 8ffb3a8ffe75..5a126828d85e 100644 --- a/fs/hfsplus/hfsplus_raw.h +++ b/fs/hfsplus/hfsplus_raw.h | |||
| @@ -261,7 +261,7 @@ struct hfsplus_cat_folder { | |||
| 261 | struct DInfo user_info; | 261 | struct DInfo user_info; |
| 262 | struct DXInfo finder_info; | 262 | struct DXInfo finder_info; |
| 263 | __be32 text_encoding; | 263 | __be32 text_encoding; |
| 264 | u32 reserved; | 264 | __be32 subfolders; /* Subfolder count in HFSX. Reserved in HFS+. */ |
| 265 | } __packed; | 265 | } __packed; |
| 266 | 266 | ||
| 267 | /* HFS file info (stolen from hfs.h) */ | 267 | /* HFS file info (stolen from hfs.h) */ |
| @@ -301,11 +301,13 @@ struct hfsplus_cat_file { | |||
| 301 | struct hfsplus_fork_raw rsrc_fork; | 301 | struct hfsplus_fork_raw rsrc_fork; |
| 302 | } __packed; | 302 | } __packed; |
| 303 | 303 | ||
| 304 | /* File attribute bits */ | 304 | /* File and folder flag bits */ |
| 305 | #define HFSPLUS_FILE_LOCKED 0x0001 | 305 | #define HFSPLUS_FILE_LOCKED 0x0001 |
| 306 | #define HFSPLUS_FILE_THREAD_EXISTS 0x0002 | 306 | #define HFSPLUS_FILE_THREAD_EXISTS 0x0002 |
| 307 | #define HFSPLUS_XATTR_EXISTS 0x0004 | 307 | #define HFSPLUS_XATTR_EXISTS 0x0004 |
| 308 | #define HFSPLUS_ACL_EXISTS 0x0008 | 308 | #define HFSPLUS_ACL_EXISTS 0x0008 |
| 309 | #define HFSPLUS_HAS_FOLDER_COUNT 0x0010 /* Folder has subfolder count | ||
| 310 | * (HFSX only) */ | ||
| 309 | 311 | ||
| 310 | /* HFS+ catalog thread (part of a cat_entry) */ | 312 | /* HFS+ catalog thread (part of a cat_entry) */ |
| 311 | struct hfsplus_cat_thread { | 313 | struct hfsplus_cat_thread { |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index fa929f325f87..a4f45bd88a63 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
| @@ -375,6 +375,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode) | |||
| 375 | hip->extent_state = 0; | 375 | hip->extent_state = 0; |
| 376 | hip->flags = 0; | 376 | hip->flags = 0; |
| 377 | hip->userflags = 0; | 377 | hip->userflags = 0; |
| 378 | hip->subfolders = 0; | ||
| 378 | memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec)); | 379 | memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec)); |
| 379 | memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); | 380 | memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); |
| 380 | hip->alloc_blocks = 0; | 381 | hip->alloc_blocks = 0; |
| @@ -494,6 +495,10 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | |||
| 494 | inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date); | 495 | inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date); |
| 495 | HFSPLUS_I(inode)->create_date = folder->create_date; | 496 | HFSPLUS_I(inode)->create_date = folder->create_date; |
| 496 | HFSPLUS_I(inode)->fs_blocks = 0; | 497 | HFSPLUS_I(inode)->fs_blocks = 0; |
| 498 | if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) { | ||
| 499 | HFSPLUS_I(inode)->subfolders = | ||
| 500 | be32_to_cpu(folder->subfolders); | ||
| 501 | } | ||
| 497 | inode->i_op = &hfsplus_dir_inode_operations; | 502 | inode->i_op = &hfsplus_dir_inode_operations; |
| 498 | inode->i_fop = &hfsplus_dir_operations; | 503 | inode->i_fop = &hfsplus_dir_operations; |
| 499 | } else if (type == HFSPLUS_FILE) { | 504 | } else if (type == HFSPLUS_FILE) { |
| @@ -566,6 +571,10 @@ int hfsplus_cat_write_inode(struct inode *inode) | |||
| 566 | folder->content_mod_date = hfsp_ut2mt(inode->i_mtime); | 571 | folder->content_mod_date = hfsp_ut2mt(inode->i_mtime); |
| 567 | folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); | 572 | folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); |
| 568 | folder->valence = cpu_to_be32(inode->i_size - 2); | 573 | folder->valence = cpu_to_be32(inode->i_size - 2); |
| 574 | if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) { | ||
| 575 | folder->subfolders = | ||
| 576 | cpu_to_be32(HFSPLUS_I(inode)->subfolders); | ||
| 577 | } | ||
| 569 | hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, | 578 | hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, |
| 570 | sizeof(struct hfsplus_cat_folder)); | 579 | sizeof(struct hfsplus_cat_folder)); |
| 571 | } else if (HFSPLUS_IS_RSRC(inode)) { | 580 | } else if (HFSPLUS_IS_RSRC(inode)) { |
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index 968eab5bc1f5..68537e8b7a09 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c | |||
| @@ -75,7 +75,7 @@ int hfsplus_parse_options_remount(char *input, int *force) | |||
| 75 | int token; | 75 | int token; |
| 76 | 76 | ||
| 77 | if (!input) | 77 | if (!input) |
| 78 | return 0; | 78 | return 1; |
| 79 | 79 | ||
| 80 | while ((p = strsep(&input, ",")) != NULL) { | 80 | while ((p = strsep(&input, ",")) != NULL) { |
| 81 | if (!*p) | 81 | if (!*p) |
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c index 0d6ce895a9ee..0f4152defe7b 100644 --- a/fs/kernfs/mount.c +++ b/fs/kernfs/mount.c | |||
| @@ -94,6 +94,7 @@ const void *kernfs_super_ns(struct super_block *sb) | |||
| 94 | * @fs_type: file_system_type of the fs being mounted | 94 | * @fs_type: file_system_type of the fs being mounted |
| 95 | * @flags: mount flags specified for the mount | 95 | * @flags: mount flags specified for the mount |
| 96 | * @root: kernfs_root of the hierarchy being mounted | 96 | * @root: kernfs_root of the hierarchy being mounted |
| 97 | * @new_sb_created: tell the caller if we allocated a new superblock | ||
| 97 | * @ns: optional namespace tag of the mount | 98 | * @ns: optional namespace tag of the mount |
| 98 | * | 99 | * |
| 99 | * This is to be called from each kernfs user's file_system_type->mount() | 100 | * This is to be called from each kernfs user's file_system_type->mount() |
| @@ -104,7 +105,8 @@ const void *kernfs_super_ns(struct super_block *sb) | |||
| 104 | * The return value can be passed to the vfs layer verbatim. | 105 | * The return value can be passed to the vfs layer verbatim. |
| 105 | */ | 106 | */ |
| 106 | struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags, | 107 | struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags, |
| 107 | struct kernfs_root *root, const void *ns) | 108 | struct kernfs_root *root, bool *new_sb_created, |
| 109 | const void *ns) | ||
| 108 | { | 110 | { |
| 109 | struct super_block *sb; | 111 | struct super_block *sb; |
| 110 | struct kernfs_super_info *info; | 112 | struct kernfs_super_info *info; |
| @@ -122,6 +124,10 @@ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags, | |||
| 122 | kfree(info); | 124 | kfree(info); |
| 123 | if (IS_ERR(sb)) | 125 | if (IS_ERR(sb)) |
| 124 | return ERR_CAST(sb); | 126 | return ERR_CAST(sb); |
| 127 | |||
| 128 | if (new_sb_created) | ||
| 129 | *new_sb_created = !sb->s_root; | ||
| 130 | |||
| 125 | if (!sb->s_root) { | 131 | if (!sb->s_root) { |
| 126 | error = kernfs_fill_super(sb); | 132 | error = kernfs_fill_super(sb); |
| 127 | if (error) { | 133 | if (error) { |
diff --git a/fs/mount.h b/fs/mount.h index a17458ca6f29..b29e42f05f34 100644 --- a/fs/mount.h +++ b/fs/mount.h | |||
| @@ -19,13 +19,13 @@ struct mnt_pcp { | |||
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | struct mountpoint { | 21 | struct mountpoint { |
| 22 | struct list_head m_hash; | 22 | struct hlist_node m_hash; |
| 23 | struct dentry *m_dentry; | 23 | struct dentry *m_dentry; |
| 24 | int m_count; | 24 | int m_count; |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | struct mount { | 27 | struct mount { |
| 28 | struct list_head mnt_hash; | 28 | struct hlist_node mnt_hash; |
| 29 | struct mount *mnt_parent; | 29 | struct mount *mnt_parent; |
| 30 | struct dentry *mnt_mountpoint; | 30 | struct dentry *mnt_mountpoint; |
| 31 | struct vfsmount mnt; | 31 | struct vfsmount mnt; |
diff --git a/fs/namei.c b/fs/namei.c index 385f7817bfcc..4b491b431990 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -1109,7 +1109,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
| 1109 | return false; | 1109 | return false; |
| 1110 | 1110 | ||
| 1111 | if (!d_mountpoint(path->dentry)) | 1111 | if (!d_mountpoint(path->dentry)) |
| 1112 | break; | 1112 | return true; |
| 1113 | 1113 | ||
| 1114 | mounted = __lookup_mnt(path->mnt, path->dentry); | 1114 | mounted = __lookup_mnt(path->mnt, path->dentry); |
| 1115 | if (!mounted) | 1115 | if (!mounted) |
| @@ -1125,20 +1125,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
| 1125 | */ | 1125 | */ |
| 1126 | *inode = path->dentry->d_inode; | 1126 | *inode = path->dentry->d_inode; |
| 1127 | } | 1127 | } |
| 1128 | return true; | 1128 | return read_seqretry(&mount_lock, nd->m_seq); |
| 1129 | } | ||
| 1130 | |||
| 1131 | static void follow_mount_rcu(struct nameidata *nd) | ||
| 1132 | { | ||
| 1133 | while (d_mountpoint(nd->path.dentry)) { | ||
| 1134 | struct mount *mounted; | ||
| 1135 | mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry); | ||
| 1136 | if (!mounted) | ||
| 1137 | break; | ||
| 1138 | nd->path.mnt = &mounted->mnt; | ||
| 1139 | nd->path.dentry = mounted->mnt.mnt_root; | ||
| 1140 | nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); | ||
| 1141 | } | ||
| 1142 | } | 1129 | } |
| 1143 | 1130 | ||
| 1144 | static int follow_dotdot_rcu(struct nameidata *nd) | 1131 | static int follow_dotdot_rcu(struct nameidata *nd) |
| @@ -1166,7 +1153,17 @@ static int follow_dotdot_rcu(struct nameidata *nd) | |||
| 1166 | break; | 1153 | break; |
| 1167 | nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); | 1154 | nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); |
| 1168 | } | 1155 | } |
| 1169 | follow_mount_rcu(nd); | 1156 | while (d_mountpoint(nd->path.dentry)) { |
| 1157 | struct mount *mounted; | ||
| 1158 | mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry); | ||
| 1159 | if (!mounted) | ||
| 1160 | break; | ||
| 1161 | nd->path.mnt = &mounted->mnt; | ||
| 1162 | nd->path.dentry = mounted->mnt.mnt_root; | ||
| 1163 | nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); | ||
| 1164 | if (!read_seqretry(&mount_lock, nd->m_seq)) | ||
| 1165 | goto failed; | ||
| 1166 | } | ||
| 1170 | nd->inode = nd->path.dentry->d_inode; | 1167 | nd->inode = nd->path.dentry->d_inode; |
| 1171 | return 0; | 1168 | return 0; |
| 1172 | 1169 | ||
| @@ -1884,7 +1881,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
| 1884 | 1881 | ||
| 1885 | nd->path = f.file->f_path; | 1882 | nd->path = f.file->f_path; |
| 1886 | if (flags & LOOKUP_RCU) { | 1883 | if (flags & LOOKUP_RCU) { |
| 1887 | if (f.need_put) | 1884 | if (f.flags & FDPUT_FPUT) |
| 1888 | *fp = f.file; | 1885 | *fp = f.file; |
| 1889 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); | 1886 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); |
| 1890 | rcu_read_lock(); | 1887 | rcu_read_lock(); |
diff --git a/fs/namespace.c b/fs/namespace.c index 22e536705c45..2ffc5a2905d4 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -23,11 +23,34 @@ | |||
| 23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
| 24 | #include <linux/proc_ns.h> | 24 | #include <linux/proc_ns.h> |
| 25 | #include <linux/magic.h> | 25 | #include <linux/magic.h> |
| 26 | #include <linux/bootmem.h> | ||
| 26 | #include "pnode.h" | 27 | #include "pnode.h" |
| 27 | #include "internal.h" | 28 | #include "internal.h" |
| 28 | 29 | ||
| 29 | #define HASH_SHIFT ilog2(PAGE_SIZE / sizeof(struct list_head)) | 30 | static unsigned int m_hash_mask __read_mostly; |
| 30 | #define HASH_SIZE (1UL << HASH_SHIFT) | 31 | static unsigned int m_hash_shift __read_mostly; |
| 32 | static unsigned int mp_hash_mask __read_mostly; | ||
| 33 | static unsigned int mp_hash_shift __read_mostly; | ||
| 34 | |||
| 35 | static __initdata unsigned long mhash_entries; | ||
| 36 | static int __init set_mhash_entries(char *str) | ||
| 37 | { | ||
| 38 | if (!str) | ||
| 39 | return 0; | ||
| 40 | mhash_entries = simple_strtoul(str, &str, 0); | ||
| 41 | return 1; | ||
| 42 | } | ||
| 43 | __setup("mhash_entries=", set_mhash_entries); | ||
| 44 | |||
| 45 | static __initdata unsigned long mphash_entries; | ||
| 46 | static int __init set_mphash_entries(char *str) | ||
| 47 | { | ||
| 48 | if (!str) | ||
| 49 | return 0; | ||
| 50 | mphash_entries = simple_strtoul(str, &str, 0); | ||
| 51 | return 1; | ||
| 52 | } | ||
| 53 | __setup("mphash_entries=", set_mphash_entries); | ||
| 31 | 54 | ||
| 32 | static int event; | 55 | static int event; |
| 33 | static DEFINE_IDA(mnt_id_ida); | 56 | static DEFINE_IDA(mnt_id_ida); |
| @@ -36,8 +59,8 @@ static DEFINE_SPINLOCK(mnt_id_lock); | |||
| 36 | static int mnt_id_start = 0; | 59 | static int mnt_id_start = 0; |
| 37 | static int mnt_group_start = 1; | 60 | static int mnt_group_start = 1; |
| 38 | 61 | ||
| 39 | static struct list_head *mount_hashtable __read_mostly; | 62 | static struct hlist_head *mount_hashtable __read_mostly; |
| 40 | static struct list_head *mountpoint_hashtable __read_mostly; | 63 | static struct hlist_head *mountpoint_hashtable __read_mostly; |
| 41 | static struct kmem_cache *mnt_cache __read_mostly; | 64 | static struct kmem_cache *mnt_cache __read_mostly; |
| 42 | static DECLARE_RWSEM(namespace_sem); | 65 | static DECLARE_RWSEM(namespace_sem); |
| 43 | 66 | ||
| @@ -55,12 +78,19 @@ EXPORT_SYMBOL_GPL(fs_kobj); | |||
| 55 | */ | 78 | */ |
| 56 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock); | 79 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock); |
| 57 | 80 | ||
| 58 | static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) | 81 | static inline struct hlist_head *m_hash(struct vfsmount *mnt, struct dentry *dentry) |
| 59 | { | 82 | { |
| 60 | unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES); | 83 | unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES); |
| 61 | tmp += ((unsigned long)dentry / L1_CACHE_BYTES); | 84 | tmp += ((unsigned long)dentry / L1_CACHE_BYTES); |
| 62 | tmp = tmp + (tmp >> HASH_SHIFT); | 85 | tmp = tmp + (tmp >> m_hash_shift); |
| 63 | return tmp & (HASH_SIZE - 1); | 86 | return &mount_hashtable[tmp & m_hash_mask]; |
| 87 | } | ||
| 88 | |||
| 89 | static inline struct hlist_head *mp_hash(struct dentry *dentry) | ||
| 90 | { | ||
| 91 | unsigned long tmp = ((unsigned long)dentry / L1_CACHE_BYTES); | ||
| 92 | tmp = tmp + (tmp >> mp_hash_shift); | ||
| 93 | return &mountpoint_hashtable[tmp & mp_hash_mask]; | ||
| 64 | } | 94 | } |
| 65 | 95 | ||
| 66 | /* | 96 | /* |
| @@ -187,7 +217,7 @@ static struct mount *alloc_vfsmnt(const char *name) | |||
| 187 | mnt->mnt_writers = 0; | 217 | mnt->mnt_writers = 0; |
| 188 | #endif | 218 | #endif |
| 189 | 219 | ||
| 190 | INIT_LIST_HEAD(&mnt->mnt_hash); | 220 | INIT_HLIST_NODE(&mnt->mnt_hash); |
| 191 | INIT_LIST_HEAD(&mnt->mnt_child); | 221 | INIT_LIST_HEAD(&mnt->mnt_child); |
| 192 | INIT_LIST_HEAD(&mnt->mnt_mounts); | 222 | INIT_LIST_HEAD(&mnt->mnt_mounts); |
| 193 | INIT_LIST_HEAD(&mnt->mnt_list); | 223 | INIT_LIST_HEAD(&mnt->mnt_list); |
| @@ -575,10 +605,10 @@ bool legitimize_mnt(struct vfsmount *bastard, unsigned seq) | |||
| 575 | */ | 605 | */ |
| 576 | struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) | 606 | struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) |
| 577 | { | 607 | { |
| 578 | struct list_head *head = mount_hashtable + hash(mnt, dentry); | 608 | struct hlist_head *head = m_hash(mnt, dentry); |
| 579 | struct mount *p; | 609 | struct mount *p; |
| 580 | 610 | ||
| 581 | list_for_each_entry_rcu(p, head, mnt_hash) | 611 | hlist_for_each_entry_rcu(p, head, mnt_hash) |
| 582 | if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry) | 612 | if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry) |
| 583 | return p; | 613 | return p; |
| 584 | return NULL; | 614 | return NULL; |
| @@ -590,13 +620,17 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) | |||
| 590 | */ | 620 | */ |
| 591 | struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry) | 621 | struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry) |
| 592 | { | 622 | { |
| 593 | struct list_head *head = mount_hashtable + hash(mnt, dentry); | 623 | struct mount *p, *res; |
| 594 | struct mount *p; | 624 | res = p = __lookup_mnt(mnt, dentry); |
| 595 | 625 | if (!p) | |
| 596 | list_for_each_entry_reverse(p, head, mnt_hash) | 626 | goto out; |
| 597 | if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry) | 627 | hlist_for_each_entry_continue(p, mnt_hash) { |
| 598 | return p; | 628 | if (&p->mnt_parent->mnt != mnt || p->mnt_mountpoint != dentry) |
| 599 | return NULL; | 629 | break; |
| 630 | res = p; | ||
| 631 | } | ||
| 632 | out: | ||
| 633 | return res; | ||
| 600 | } | 634 | } |
| 601 | 635 | ||
| 602 | /* | 636 | /* |
| @@ -633,11 +667,11 @@ struct vfsmount *lookup_mnt(struct path *path) | |||
| 633 | 667 | ||
| 634 | static struct mountpoint *new_mountpoint(struct dentry *dentry) | 668 | static struct mountpoint *new_mountpoint(struct dentry *dentry) |
| 635 | { | 669 | { |
| 636 | struct list_head *chain = mountpoint_hashtable + hash(NULL, dentry); | 670 | struct hlist_head *chain = mp_hash(dentry); |
| 637 | struct mountpoint *mp; | 671 | struct mountpoint *mp; |
| 638 | int ret; | 672 | int ret; |
| 639 | 673 | ||
| 640 | list_for_each_entry(mp, chain, m_hash) { | 674 | hlist_for_each_entry(mp, chain, m_hash) { |
| 641 | if (mp->m_dentry == dentry) { | 675 | if (mp->m_dentry == dentry) { |
| 642 | /* might be worth a WARN_ON() */ | 676 | /* might be worth a WARN_ON() */ |
| 643 | if (d_unlinked(dentry)) | 677 | if (d_unlinked(dentry)) |
| @@ -659,7 +693,7 @@ static struct mountpoint *new_mountpoint(struct dentry *dentry) | |||
| 659 | 693 | ||
| 660 | mp->m_dentry = dentry; | 694 | mp->m_dentry = dentry; |
| 661 | mp->m_count = 1; | 695 | mp->m_count = 1; |
| 662 | list_add(&mp->m_hash, chain); | 696 | hlist_add_head(&mp->m_hash, chain); |
| 663 | return mp; | 697 | return mp; |
| 664 | } | 698 | } |
| 665 | 699 | ||
| @@ -670,7 +704,7 @@ static void put_mountpoint(struct mountpoint *mp) | |||
| 670 | spin_lock(&dentry->d_lock); | 704 | spin_lock(&dentry->d_lock); |
| 671 | dentry->d_flags &= ~DCACHE_MOUNTED; | 705 | dentry->d_flags &= ~DCACHE_MOUNTED; |
| 672 | spin_unlock(&dentry->d_lock); | 706 | spin_unlock(&dentry->d_lock); |
| 673 | list_del(&mp->m_hash); | 707 | hlist_del(&mp->m_hash); |
| 674 | kfree(mp); | 708 | kfree(mp); |
| 675 | } | 709 | } |
| 676 | } | 710 | } |
| @@ -712,7 +746,7 @@ static void detach_mnt(struct mount *mnt, struct path *old_path) | |||
| 712 | mnt->mnt_parent = mnt; | 746 | mnt->mnt_parent = mnt; |
| 713 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; | 747 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; |
| 714 | list_del_init(&mnt->mnt_child); | 748 | list_del_init(&mnt->mnt_child); |
| 715 | list_del_init(&mnt->mnt_hash); | 749 | hlist_del_init_rcu(&mnt->mnt_hash); |
| 716 | put_mountpoint(mnt->mnt_mp); | 750 | put_mountpoint(mnt->mnt_mp); |
| 717 | mnt->mnt_mp = NULL; | 751 | mnt->mnt_mp = NULL; |
| 718 | } | 752 | } |
| @@ -739,15 +773,14 @@ static void attach_mnt(struct mount *mnt, | |||
| 739 | struct mountpoint *mp) | 773 | struct mountpoint *mp) |
| 740 | { | 774 | { |
| 741 | mnt_set_mountpoint(parent, mp, mnt); | 775 | mnt_set_mountpoint(parent, mp, mnt); |
| 742 | list_add_tail(&mnt->mnt_hash, mount_hashtable + | 776 | hlist_add_head_rcu(&mnt->mnt_hash, m_hash(&parent->mnt, mp->m_dentry)); |
| 743 | hash(&parent->mnt, mp->m_dentry)); | ||
| 744 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); | 777 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); |
| 745 | } | 778 | } |
| 746 | 779 | ||
| 747 | /* | 780 | /* |
| 748 | * vfsmount lock must be held for write | 781 | * vfsmount lock must be held for write |
| 749 | */ | 782 | */ |
| 750 | static void commit_tree(struct mount *mnt) | 783 | static void commit_tree(struct mount *mnt, struct mount *shadows) |
| 751 | { | 784 | { |
| 752 | struct mount *parent = mnt->mnt_parent; | 785 | struct mount *parent = mnt->mnt_parent; |
| 753 | struct mount *m; | 786 | struct mount *m; |
| @@ -762,8 +795,11 @@ static void commit_tree(struct mount *mnt) | |||
| 762 | 795 | ||
| 763 | list_splice(&head, n->list.prev); | 796 | list_splice(&head, n->list.prev); |
| 764 | 797 | ||
| 765 | list_add_tail(&mnt->mnt_hash, mount_hashtable + | 798 | if (shadows) |
| 766 | hash(&parent->mnt, mnt->mnt_mountpoint)); | 799 | hlist_add_after_rcu(&shadows->mnt_hash, &mnt->mnt_hash); |
| 800 | else | ||
| 801 | hlist_add_head_rcu(&mnt->mnt_hash, | ||
| 802 | m_hash(&parent->mnt, mnt->mnt_mountpoint)); | ||
| 767 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); | 803 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); |
| 768 | touch_mnt_namespace(n); | 804 | touch_mnt_namespace(n); |
| 769 | } | 805 | } |
| @@ -1153,26 +1189,28 @@ int may_umount(struct vfsmount *mnt) | |||
| 1153 | 1189 | ||
| 1154 | EXPORT_SYMBOL(may_umount); | 1190 | EXPORT_SYMBOL(may_umount); |
| 1155 | 1191 | ||
| 1156 | static LIST_HEAD(unmounted); /* protected by namespace_sem */ | 1192 | static HLIST_HEAD(unmounted); /* protected by namespace_sem */ |
| 1157 | 1193 | ||
| 1158 | static void namespace_unlock(void) | 1194 | static void namespace_unlock(void) |
| 1159 | { | 1195 | { |
| 1160 | struct mount *mnt; | 1196 | struct mount *mnt; |
| 1161 | LIST_HEAD(head); | 1197 | struct hlist_head head = unmounted; |
| 1162 | 1198 | ||
| 1163 | if (likely(list_empty(&unmounted))) { | 1199 | if (likely(hlist_empty(&head))) { |
| 1164 | up_write(&namespace_sem); | 1200 | up_write(&namespace_sem); |
| 1165 | return; | 1201 | return; |
| 1166 | } | 1202 | } |
| 1167 | 1203 | ||
| 1168 | list_splice_init(&unmounted, &head); | 1204 | head.first->pprev = &head.first; |
| 1205 | INIT_HLIST_HEAD(&unmounted); | ||
| 1206 | |||
| 1169 | up_write(&namespace_sem); | 1207 | up_write(&namespace_sem); |
| 1170 | 1208 | ||
| 1171 | synchronize_rcu(); | 1209 | synchronize_rcu(); |
| 1172 | 1210 | ||
| 1173 | while (!list_empty(&head)) { | 1211 | while (!hlist_empty(&head)) { |
| 1174 | mnt = list_first_entry(&head, struct mount, mnt_hash); | 1212 | mnt = hlist_entry(head.first, struct mount, mnt_hash); |
| 1175 | list_del_init(&mnt->mnt_hash); | 1213 | hlist_del_init(&mnt->mnt_hash); |
| 1176 | if (mnt->mnt_ex_mountpoint.mnt) | 1214 | if (mnt->mnt_ex_mountpoint.mnt) |
| 1177 | path_put(&mnt->mnt_ex_mountpoint); | 1215 | path_put(&mnt->mnt_ex_mountpoint); |
| 1178 | mntput(&mnt->mnt); | 1216 | mntput(&mnt->mnt); |
| @@ -1193,16 +1231,19 @@ static inline void namespace_lock(void) | |||
| 1193 | */ | 1231 | */ |
| 1194 | void umount_tree(struct mount *mnt, int how) | 1232 | void umount_tree(struct mount *mnt, int how) |
| 1195 | { | 1233 | { |
| 1196 | LIST_HEAD(tmp_list); | 1234 | HLIST_HEAD(tmp_list); |
| 1197 | struct mount *p; | 1235 | struct mount *p; |
| 1236 | struct mount *last = NULL; | ||
| 1198 | 1237 | ||
| 1199 | for (p = mnt; p; p = next_mnt(p, mnt)) | 1238 | for (p = mnt; p; p = next_mnt(p, mnt)) { |
| 1200 | list_move(&p->mnt_hash, &tmp_list); | 1239 | hlist_del_init_rcu(&p->mnt_hash); |
| 1240 | hlist_add_head(&p->mnt_hash, &tmp_list); | ||
| 1241 | } | ||
| 1201 | 1242 | ||
| 1202 | if (how) | 1243 | if (how) |
| 1203 | propagate_umount(&tmp_list); | 1244 | propagate_umount(&tmp_list); |
| 1204 | 1245 | ||
| 1205 | list_for_each_entry(p, &tmp_list, mnt_hash) { | 1246 | hlist_for_each_entry(p, &tmp_list, mnt_hash) { |
| 1206 | list_del_init(&p->mnt_expire); | 1247 | list_del_init(&p->mnt_expire); |
| 1207 | list_del_init(&p->mnt_list); | 1248 | list_del_init(&p->mnt_list); |
| 1208 | __touch_mnt_namespace(p->mnt_ns); | 1249 | __touch_mnt_namespace(p->mnt_ns); |
| @@ -1220,8 +1261,13 @@ void umount_tree(struct mount *mnt, int how) | |||
| 1220 | p->mnt_mp = NULL; | 1261 | p->mnt_mp = NULL; |
| 1221 | } | 1262 | } |
| 1222 | change_mnt_propagation(p, MS_PRIVATE); | 1263 | change_mnt_propagation(p, MS_PRIVATE); |
| 1264 | last = p; | ||
| 1265 | } | ||
| 1266 | if (last) { | ||
| 1267 | last->mnt_hash.next = unmounted.first; | ||
| 1268 | unmounted.first = tmp_list.first; | ||
| 1269 | unmounted.first->pprev = &unmounted.first; | ||
| 1223 | } | 1270 | } |
| 1224 | list_splice(&tmp_list, &unmounted); | ||
| 1225 | } | 1271 | } |
| 1226 | 1272 | ||
| 1227 | static void shrink_submounts(struct mount *mnt); | 1273 | static void shrink_submounts(struct mount *mnt); |
| @@ -1605,24 +1651,23 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
| 1605 | struct mountpoint *dest_mp, | 1651 | struct mountpoint *dest_mp, |
| 1606 | struct path *parent_path) | 1652 | struct path *parent_path) |
| 1607 | { | 1653 | { |
| 1608 | LIST_HEAD(tree_list); | 1654 | HLIST_HEAD(tree_list); |
| 1609 | struct mount *child, *p; | 1655 | struct mount *child, *p; |
| 1656 | struct hlist_node *n; | ||
| 1610 | int err; | 1657 | int err; |
| 1611 | 1658 | ||
| 1612 | if (IS_MNT_SHARED(dest_mnt)) { | 1659 | if (IS_MNT_SHARED(dest_mnt)) { |
| 1613 | err = invent_group_ids(source_mnt, true); | 1660 | err = invent_group_ids(source_mnt, true); |
| 1614 | if (err) | 1661 | if (err) |
| 1615 | goto out; | 1662 | goto out; |
| 1616 | } | 1663 | err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list); |
| 1617 | err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list); | 1664 | if (err) |
| 1618 | if (err) | 1665 | goto out_cleanup_ids; |
| 1619 | goto out_cleanup_ids; | 1666 | lock_mount_hash(); |
| 1620 | |||
| 1621 | lock_mount_hash(); | ||
| 1622 | |||
| 1623 | if (IS_MNT_SHARED(dest_mnt)) { | ||
| 1624 | for (p = source_mnt; p; p = next_mnt(p, source_mnt)) | 1667 | for (p = source_mnt; p; p = next_mnt(p, source_mnt)) |
| 1625 | set_mnt_shared(p); | 1668 | set_mnt_shared(p); |
| 1669 | } else { | ||
| 1670 | lock_mount_hash(); | ||
| 1626 | } | 1671 | } |
| 1627 | if (parent_path) { | 1672 | if (parent_path) { |
| 1628 | detach_mnt(source_mnt, parent_path); | 1673 | detach_mnt(source_mnt, parent_path); |
| @@ -1630,20 +1675,22 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
| 1630 | touch_mnt_namespace(source_mnt->mnt_ns); | 1675 | touch_mnt_namespace(source_mnt->mnt_ns); |
| 1631 | } else { | 1676 | } else { |
| 1632 | mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt); | 1677 | mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt); |
| 1633 | commit_tree(source_mnt); | 1678 | commit_tree(source_mnt, NULL); |
| 1634 | } | 1679 | } |
| 1635 | 1680 | ||
| 1636 | list_for_each_entry_safe(child, p, &tree_list, mnt_hash) { | 1681 | hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) { |
| 1637 | list_del_init(&child->mnt_hash); | 1682 | struct mount *q; |
| 1638 | commit_tree(child); | 1683 | hlist_del_init(&child->mnt_hash); |
| 1684 | q = __lookup_mnt_last(&child->mnt_parent->mnt, | ||
| 1685 | child->mnt_mountpoint); | ||
| 1686 | commit_tree(child, q); | ||
| 1639 | } | 1687 | } |
| 1640 | unlock_mount_hash(); | 1688 | unlock_mount_hash(); |
| 1641 | 1689 | ||
| 1642 | return 0; | 1690 | return 0; |
| 1643 | 1691 | ||
| 1644 | out_cleanup_ids: | 1692 | out_cleanup_ids: |
| 1645 | if (IS_MNT_SHARED(dest_mnt)) | 1693 | cleanup_group_ids(source_mnt, NULL); |
| 1646 | cleanup_group_ids(source_mnt, NULL); | ||
| 1647 | out: | 1694 | out: |
| 1648 | return err; | 1695 | return err; |
| 1649 | } | 1696 | } |
| @@ -2777,18 +2824,24 @@ void __init mnt_init(void) | |||
| 2777 | mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount), | 2824 | mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount), |
| 2778 | 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); | 2825 | 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); |
| 2779 | 2826 | ||
| 2780 | mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC); | 2827 | mount_hashtable = alloc_large_system_hash("Mount-cache", |
| 2781 | mountpoint_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC); | 2828 | sizeof(struct hlist_head), |
| 2829 | mhash_entries, 19, | ||
| 2830 | 0, | ||
| 2831 | &m_hash_shift, &m_hash_mask, 0, 0); | ||
| 2832 | mountpoint_hashtable = alloc_large_system_hash("Mountpoint-cache", | ||
| 2833 | sizeof(struct hlist_head), | ||
| 2834 | mphash_entries, 19, | ||
| 2835 | 0, | ||
| 2836 | &mp_hash_shift, &mp_hash_mask, 0, 0); | ||
| 2782 | 2837 | ||
| 2783 | if (!mount_hashtable || !mountpoint_hashtable) | 2838 | if (!mount_hashtable || !mountpoint_hashtable) |
| 2784 | panic("Failed to allocate mount hash table\n"); | 2839 | panic("Failed to allocate mount hash table\n"); |
| 2785 | 2840 | ||
| 2786 | printk(KERN_INFO "Mount-cache hash table entries: %lu\n", HASH_SIZE); | 2841 | for (u = 0; u <= m_hash_mask; u++) |
| 2787 | 2842 | INIT_HLIST_HEAD(&mount_hashtable[u]); | |
| 2788 | for (u = 0; u < HASH_SIZE; u++) | 2843 | for (u = 0; u <= mp_hash_mask; u++) |
| 2789 | INIT_LIST_HEAD(&mount_hashtable[u]); | 2844 | INIT_HLIST_HEAD(&mountpoint_hashtable[u]); |
| 2790 | for (u = 0; u < HASH_SIZE; u++) | ||
| 2791 | INIT_LIST_HEAD(&mountpoint_hashtable[u]); | ||
| 2792 | 2845 | ||
| 2793 | kernfs_init(); | 2846 | kernfs_init(); |
| 2794 | 2847 | ||
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index ef792f29f831..5d8ccecf5f5c 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
| @@ -659,16 +659,19 @@ int nfs_async_inode_return_delegation(struct inode *inode, | |||
| 659 | 659 | ||
| 660 | rcu_read_lock(); | 660 | rcu_read_lock(); |
| 661 | delegation = rcu_dereference(NFS_I(inode)->delegation); | 661 | delegation = rcu_dereference(NFS_I(inode)->delegation); |
| 662 | if (delegation == NULL) | ||
| 663 | goto out_enoent; | ||
| 662 | 664 | ||
| 663 | if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid)) { | 665 | if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid)) |
| 664 | rcu_read_unlock(); | 666 | goto out_enoent; |
| 665 | return -ENOENT; | ||
| 666 | } | ||
| 667 | nfs_mark_return_delegation(server, delegation); | 667 | nfs_mark_return_delegation(server, delegation); |
| 668 | rcu_read_unlock(); | 668 | rcu_read_unlock(); |
| 669 | 669 | ||
| 670 | nfs_delegation_run_state_manager(clp); | 670 | nfs_delegation_run_state_manager(clp); |
| 671 | return 0; | 671 | return 0; |
| 672 | out_enoent: | ||
| 673 | rcu_read_unlock(); | ||
| 674 | return -ENOENT; | ||
| 672 | } | 675 | } |
| 673 | 676 | ||
| 674 | static struct inode * | 677 | static struct inode * |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 12c8132ad408..b9a35c05b60f 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
| @@ -324,8 +324,9 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data) | |||
| 324 | &rdata->res.seq_res, | 324 | &rdata->res.seq_res, |
| 325 | task)) | 325 | task)) |
| 326 | return; | 326 | return; |
| 327 | nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context, | 327 | if (nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context, |
| 328 | rdata->args.lock_context, FMODE_READ); | 328 | rdata->args.lock_context, FMODE_READ) == -EIO) |
| 329 | rpc_exit(task, -EIO); /* lost lock, terminate I/O */ | ||
| 329 | } | 330 | } |
| 330 | 331 | ||
| 331 | static void filelayout_read_call_done(struct rpc_task *task, void *data) | 332 | static void filelayout_read_call_done(struct rpc_task *task, void *data) |
| @@ -435,8 +436,9 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data) | |||
| 435 | &wdata->res.seq_res, | 436 | &wdata->res.seq_res, |
| 436 | task)) | 437 | task)) |
| 437 | return; | 438 | return; |
| 438 | nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context, | 439 | if (nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context, |
| 439 | wdata->args.lock_context, FMODE_WRITE); | 440 | wdata->args.lock_context, FMODE_WRITE) == -EIO) |
| 441 | rpc_exit(task, -EIO); /* lost lock, terminate I/O */ | ||
| 440 | } | 442 | } |
| 441 | 443 | ||
| 442 | static void filelayout_write_call_done(struct rpc_task *task, void *data) | 444 | static void filelayout_write_call_done(struct rpc_task *task, void *data) |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 2da6a698b8f7..450bfedbe2f4 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -2398,13 +2398,16 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
| 2398 | 2398 | ||
| 2399 | if (nfs4_copy_delegation_stateid(&arg.stateid, inode, fmode)) { | 2399 | if (nfs4_copy_delegation_stateid(&arg.stateid, inode, fmode)) { |
| 2400 | /* Use that stateid */ | 2400 | /* Use that stateid */ |
| 2401 | } else if (truncate && state != NULL && nfs4_valid_open_stateid(state)) { | 2401 | } else if (truncate && state != NULL) { |
| 2402 | struct nfs_lockowner lockowner = { | 2402 | struct nfs_lockowner lockowner = { |
| 2403 | .l_owner = current->files, | 2403 | .l_owner = current->files, |
| 2404 | .l_pid = current->tgid, | 2404 | .l_pid = current->tgid, |
| 2405 | }; | 2405 | }; |
| 2406 | nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE, | 2406 | if (!nfs4_valid_open_stateid(state)) |
| 2407 | &lockowner); | 2407 | return -EBADF; |
| 2408 | if (nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE, | ||
| 2409 | &lockowner) == -EIO) | ||
| 2410 | return -EBADF; | ||
| 2408 | } else | 2411 | } else |
| 2409 | nfs4_stateid_copy(&arg.stateid, &zero_stateid); | 2412 | nfs4_stateid_copy(&arg.stateid, &zero_stateid); |
| 2410 | 2413 | ||
| @@ -4011,8 +4014,9 @@ static bool nfs4_stateid_is_current(nfs4_stateid *stateid, | |||
| 4011 | { | 4014 | { |
| 4012 | nfs4_stateid current_stateid; | 4015 | nfs4_stateid current_stateid; |
| 4013 | 4016 | ||
| 4014 | if (nfs4_set_rw_stateid(¤t_stateid, ctx, l_ctx, fmode)) | 4017 | /* If the current stateid represents a lost lock, then exit */ |
| 4015 | return false; | 4018 | if (nfs4_set_rw_stateid(¤t_stateid, ctx, l_ctx, fmode) == -EIO) |
| 4019 | return true; | ||
| 4016 | return nfs4_stateid_match(stateid, ¤t_stateid); | 4020 | return nfs4_stateid_match(stateid, ¤t_stateid); |
| 4017 | } | 4021 | } |
| 4018 | 4022 | ||
| @@ -5828,8 +5832,7 @@ struct nfs_release_lockowner_data { | |||
| 5828 | struct nfs4_lock_state *lsp; | 5832 | struct nfs4_lock_state *lsp; |
| 5829 | struct nfs_server *server; | 5833 | struct nfs_server *server; |
| 5830 | struct nfs_release_lockowner_args args; | 5834 | struct nfs_release_lockowner_args args; |
| 5831 | struct nfs4_sequence_args seq_args; | 5835 | struct nfs_release_lockowner_res res; |
| 5832 | struct nfs4_sequence_res seq_res; | ||
| 5833 | unsigned long timestamp; | 5836 | unsigned long timestamp; |
| 5834 | }; | 5837 | }; |
| 5835 | 5838 | ||
| @@ -5837,7 +5840,7 @@ static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata | |||
| 5837 | { | 5840 | { |
| 5838 | struct nfs_release_lockowner_data *data = calldata; | 5841 | struct nfs_release_lockowner_data *data = calldata; |
| 5839 | nfs40_setup_sequence(data->server, | 5842 | nfs40_setup_sequence(data->server, |
| 5840 | &data->seq_args, &data->seq_res, task); | 5843 | &data->args.seq_args, &data->res.seq_res, task); |
| 5841 | data->timestamp = jiffies; | 5844 | data->timestamp = jiffies; |
| 5842 | } | 5845 | } |
| 5843 | 5846 | ||
| @@ -5846,7 +5849,7 @@ static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata) | |||
| 5846 | struct nfs_release_lockowner_data *data = calldata; | 5849 | struct nfs_release_lockowner_data *data = calldata; |
| 5847 | struct nfs_server *server = data->server; | 5850 | struct nfs_server *server = data->server; |
| 5848 | 5851 | ||
| 5849 | nfs40_sequence_done(task, &data->seq_res); | 5852 | nfs40_sequence_done(task, &data->res.seq_res); |
| 5850 | 5853 | ||
| 5851 | switch (task->tk_status) { | 5854 | switch (task->tk_status) { |
| 5852 | case 0: | 5855 | case 0: |
| @@ -5887,7 +5890,6 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st | |||
| 5887 | data = kmalloc(sizeof(*data), GFP_NOFS); | 5890 | data = kmalloc(sizeof(*data), GFP_NOFS); |
| 5888 | if (!data) | 5891 | if (!data) |
| 5889 | return -ENOMEM; | 5892 | return -ENOMEM; |
| 5890 | nfs4_init_sequence(&data->seq_args, &data->seq_res, 0); | ||
| 5891 | data->lsp = lsp; | 5893 | data->lsp = lsp; |
| 5892 | data->server = server; | 5894 | data->server = server; |
| 5893 | data->args.lock_owner.clientid = server->nfs_client->cl_clientid; | 5895 | data->args.lock_owner.clientid = server->nfs_client->cl_clientid; |
| @@ -5895,6 +5897,8 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st | |||
| 5895 | data->args.lock_owner.s_dev = server->s_dev; | 5897 | data->args.lock_owner.s_dev = server->s_dev; |
| 5896 | 5898 | ||
| 5897 | msg.rpc_argp = &data->args; | 5899 | msg.rpc_argp = &data->args; |
| 5900 | msg.rpc_resp = &data->res; | ||
| 5901 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); | ||
| 5898 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data); | 5902 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data); |
| 5899 | return 0; | 5903 | return 0; |
| 5900 | } | 5904 | } |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index e1a47217c05e..0deb32105ccf 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -974,9 +974,6 @@ static int nfs4_copy_lock_stateid(nfs4_stateid *dst, | |||
| 974 | else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) { | 974 | else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) { |
| 975 | nfs4_stateid_copy(dst, &lsp->ls_stateid); | 975 | nfs4_stateid_copy(dst, &lsp->ls_stateid); |
| 976 | ret = 0; | 976 | ret = 0; |
| 977 | smp_rmb(); | ||
| 978 | if (!list_empty(&lsp->ls_seqid.list)) | ||
| 979 | ret = -EWOULDBLOCK; | ||
| 980 | } | 977 | } |
| 981 | spin_unlock(&state->state_lock); | 978 | spin_unlock(&state->state_lock); |
| 982 | nfs4_put_lock_state(lsp); | 979 | nfs4_put_lock_state(lsp); |
| @@ -984,10 +981,9 @@ out: | |||
| 984 | return ret; | 981 | return ret; |
| 985 | } | 982 | } |
| 986 | 983 | ||
| 987 | static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) | 984 | static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) |
| 988 | { | 985 | { |
| 989 | const nfs4_stateid *src; | 986 | const nfs4_stateid *src; |
| 990 | int ret; | ||
| 991 | int seq; | 987 | int seq; |
| 992 | 988 | ||
| 993 | do { | 989 | do { |
| @@ -996,12 +992,7 @@ static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) | |||
| 996 | if (test_bit(NFS_OPEN_STATE, &state->flags)) | 992 | if (test_bit(NFS_OPEN_STATE, &state->flags)) |
| 997 | src = &state->open_stateid; | 993 | src = &state->open_stateid; |
| 998 | nfs4_stateid_copy(dst, src); | 994 | nfs4_stateid_copy(dst, src); |
| 999 | ret = 0; | ||
| 1000 | smp_rmb(); | ||
| 1001 | if (!list_empty(&state->owner->so_seqid.list)) | ||
| 1002 | ret = -EWOULDBLOCK; | ||
| 1003 | } while (read_seqretry(&state->seqlock, seq)); | 995 | } while (read_seqretry(&state->seqlock, seq)); |
| 1004 | return ret; | ||
| 1005 | } | 996 | } |
| 1006 | 997 | ||
| 1007 | /* | 998 | /* |
| @@ -1026,7 +1017,8 @@ int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, | |||
| 1026 | * choose to use. | 1017 | * choose to use. |
| 1027 | */ | 1018 | */ |
| 1028 | goto out; | 1019 | goto out; |
| 1029 | ret = nfs4_copy_open_stateid(dst, state); | 1020 | nfs4_copy_open_stateid(dst, state); |
| 1021 | ret = 0; | ||
| 1030 | out: | 1022 | out: |
| 1031 | if (nfs_server_capable(state->inode, NFS_CAP_STATEID_NFSV41)) | 1023 | if (nfs_server_capable(state->inode, NFS_CAP_STATEID_NFSV41)) |
| 1032 | dst->seqid = 0; | 1024 | dst->seqid = 0; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 017d3cb5e99b..6d7be3f80356 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -449,6 +449,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
| 449 | fh_lock(fhp); | 449 | fh_lock(fhp); |
| 450 | host_err = notify_change(dentry, iap, NULL); | 450 | host_err = notify_change(dentry, iap, NULL); |
| 451 | fh_unlock(fhp); | 451 | fh_unlock(fhp); |
| 452 | err = nfserrno(host_err); | ||
| 452 | 453 | ||
| 453 | out_put_write_access: | 454 | out_put_write_access: |
| 454 | if (size_change) | 455 | if (size_change) |
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 0b9ff4395e6a..abc8cbcfe90e 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c | |||
| @@ -86,7 +86,7 @@ static int dnotify_handle_event(struct fsnotify_group *group, | |||
| 86 | struct fsnotify_mark *inode_mark, | 86 | struct fsnotify_mark *inode_mark, |
| 87 | struct fsnotify_mark *vfsmount_mark, | 87 | struct fsnotify_mark *vfsmount_mark, |
| 88 | u32 mask, void *data, int data_type, | 88 | u32 mask, void *data, int data_type, |
| 89 | const unsigned char *file_name) | 89 | const unsigned char *file_name, u32 cookie) |
| 90 | { | 90 | { |
| 91 | struct dnotify_mark *dn_mark; | 91 | struct dnotify_mark *dn_mark; |
| 92 | struct dnotify_struct *dn; | 92 | struct dnotify_struct *dn; |
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 0e792f5e3147..dc638f786d5c 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
| @@ -147,7 +147,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, | |||
| 147 | struct fsnotify_mark *inode_mark, | 147 | struct fsnotify_mark *inode_mark, |
| 148 | struct fsnotify_mark *fanotify_mark, | 148 | struct fsnotify_mark *fanotify_mark, |
| 149 | u32 mask, void *data, int data_type, | 149 | u32 mask, void *data, int data_type, |
| 150 | const unsigned char *file_name) | 150 | const unsigned char *file_name, u32 cookie) |
| 151 | { | 151 | { |
| 152 | int ret = 0; | 152 | int ret = 0; |
| 153 | struct fanotify_event_info *event; | 153 | struct fanotify_event_info *event; |
| @@ -192,10 +192,12 @@ static int fanotify_handle_event(struct fsnotify_group *group, | |||
| 192 | 192 | ||
| 193 | ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge); | 193 | ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge); |
| 194 | if (ret) { | 194 | if (ret) { |
| 195 | BUG_ON(mask & FAN_ALL_PERM_EVENTS); | 195 | /* Permission events shouldn't be merged */ |
| 196 | BUG_ON(ret == 1 && mask & FAN_ALL_PERM_EVENTS); | ||
| 196 | /* Our event wasn't used in the end. Free it. */ | 197 | /* Our event wasn't used in the end. Free it. */ |
| 197 | fsnotify_destroy_event(group, fsn_event); | 198 | fsnotify_destroy_event(group, fsn_event); |
| 198 | ret = 0; | 199 | |
| 200 | return 0; | ||
| 199 | } | 201 | } |
| 200 | 202 | ||
| 201 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | 203 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS |
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index b6175fa11bf8..287a22c04149 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
| @@ -698,6 +698,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
| 698 | struct fsnotify_group *group; | 698 | struct fsnotify_group *group; |
| 699 | int f_flags, fd; | 699 | int f_flags, fd; |
| 700 | struct user_struct *user; | 700 | struct user_struct *user; |
| 701 | struct fanotify_event_info *oevent; | ||
| 701 | 702 | ||
| 702 | pr_debug("%s: flags=%d event_f_flags=%d\n", | 703 | pr_debug("%s: flags=%d event_f_flags=%d\n", |
| 703 | __func__, flags, event_f_flags); | 704 | __func__, flags, event_f_flags); |
| @@ -730,8 +731,20 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
| 730 | group->fanotify_data.user = user; | 731 | group->fanotify_data.user = user; |
| 731 | atomic_inc(&user->fanotify_listeners); | 732 | atomic_inc(&user->fanotify_listeners); |
| 732 | 733 | ||
| 734 | oevent = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL); | ||
| 735 | if (unlikely(!oevent)) { | ||
| 736 | fd = -ENOMEM; | ||
| 737 | goto out_destroy_group; | ||
| 738 | } | ||
| 739 | group->overflow_event = &oevent->fse; | ||
| 740 | fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW); | ||
| 741 | oevent->tgid = get_pid(task_tgid(current)); | ||
| 742 | oevent->path.mnt = NULL; | ||
| 743 | oevent->path.dentry = NULL; | ||
| 744 | |||
| 733 | group->fanotify_data.f_flags = event_f_flags; | 745 | group->fanotify_data.f_flags = event_f_flags; |
| 734 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | 746 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS |
| 747 | oevent->response = 0; | ||
| 735 | mutex_init(&group->fanotify_data.access_mutex); | 748 | mutex_init(&group->fanotify_data.access_mutex); |
| 736 | init_waitqueue_head(&group->fanotify_data.access_waitq); | 749 | init_waitqueue_head(&group->fanotify_data.access_waitq); |
| 737 | INIT_LIST_HEAD(&group->fanotify_data.access_list); | 750 | INIT_LIST_HEAD(&group->fanotify_data.access_list); |
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 1d4e1ea2f37c..9d3e9c50066a 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
| @@ -179,7 +179,7 @@ static int send_to_group(struct inode *to_tell, | |||
| 179 | 179 | ||
| 180 | return group->ops->handle_event(group, to_tell, inode_mark, | 180 | return group->ops->handle_event(group, to_tell, inode_mark, |
| 181 | vfsmount_mark, mask, data, data_is, | 181 | vfsmount_mark, mask, data, data_is, |
| 182 | file_name); | 182 | file_name, cookie); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | /* | 185 | /* |
diff --git a/fs/notify/group.c b/fs/notify/group.c index ee674fe2cec7..ad1995980456 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c | |||
| @@ -55,6 +55,13 @@ void fsnotify_destroy_group(struct fsnotify_group *group) | |||
| 55 | /* clear the notification queue of all events */ | 55 | /* clear the notification queue of all events */ |
| 56 | fsnotify_flush_notify(group); | 56 | fsnotify_flush_notify(group); |
| 57 | 57 | ||
| 58 | /* | ||
| 59 | * Destroy overflow event (we cannot use fsnotify_destroy_event() as | ||
| 60 | * that deliberately ignores overflow events. | ||
| 61 | */ | ||
| 62 | if (group->overflow_event) | ||
| 63 | group->ops->free_event(group->overflow_event); | ||
| 64 | |||
| 58 | fsnotify_put_group(group); | 65 | fsnotify_put_group(group); |
| 59 | } | 66 | } |
| 60 | 67 | ||
| @@ -99,7 +106,6 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) | |||
| 99 | INIT_LIST_HEAD(&group->marks_list); | 106 | INIT_LIST_HEAD(&group->marks_list); |
| 100 | 107 | ||
| 101 | group->ops = ops; | 108 | group->ops = ops; |
| 102 | fsnotify_init_event(&group->overflow_event, NULL, FS_Q_OVERFLOW); | ||
| 103 | 109 | ||
| 104 | return group; | 110 | return group; |
| 105 | } | 111 | } |
diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h index 485eef3f4407..ed855ef6f077 100644 --- a/fs/notify/inotify/inotify.h +++ b/fs/notify/inotify/inotify.h | |||
| @@ -27,6 +27,6 @@ extern int inotify_handle_event(struct fsnotify_group *group, | |||
| 27 | struct fsnotify_mark *inode_mark, | 27 | struct fsnotify_mark *inode_mark, |
| 28 | struct fsnotify_mark *vfsmount_mark, | 28 | struct fsnotify_mark *vfsmount_mark, |
| 29 | u32 mask, void *data, int data_type, | 29 | u32 mask, void *data, int data_type, |
| 30 | const unsigned char *file_name); | 30 | const unsigned char *file_name, u32 cookie); |
| 31 | 31 | ||
| 32 | extern const struct fsnotify_ops inotify_fsnotify_ops; | 32 | extern const struct fsnotify_ops inotify_fsnotify_ops; |
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index d5ee56348bb8..43ab1e1a07a2 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c | |||
| @@ -67,7 +67,7 @@ int inotify_handle_event(struct fsnotify_group *group, | |||
| 67 | struct fsnotify_mark *inode_mark, | 67 | struct fsnotify_mark *inode_mark, |
| 68 | struct fsnotify_mark *vfsmount_mark, | 68 | struct fsnotify_mark *vfsmount_mark, |
| 69 | u32 mask, void *data, int data_type, | 69 | u32 mask, void *data, int data_type, |
| 70 | const unsigned char *file_name) | 70 | const unsigned char *file_name, u32 cookie) |
| 71 | { | 71 | { |
| 72 | struct inotify_inode_mark *i_mark; | 72 | struct inotify_inode_mark *i_mark; |
| 73 | struct inotify_event_info *event; | 73 | struct inotify_event_info *event; |
| @@ -103,6 +103,7 @@ int inotify_handle_event(struct fsnotify_group *group, | |||
| 103 | fsn_event = &event->fse; | 103 | fsn_event = &event->fse; |
| 104 | fsnotify_init_event(fsn_event, inode, mask); | 104 | fsnotify_init_event(fsn_event, inode, mask); |
| 105 | event->wd = i_mark->wd; | 105 | event->wd = i_mark->wd; |
| 106 | event->sync_cookie = cookie; | ||
| 106 | event->name_len = len; | 107 | event->name_len = len; |
| 107 | if (len) | 108 | if (len) |
| 108 | strcpy(event->name, file_name); | 109 | strcpy(event->name, file_name); |
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 497395c8274b..78a2ca3966c3 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
| @@ -495,7 +495,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, | |||
| 495 | 495 | ||
| 496 | /* Queue ignore event for the watch */ | 496 | /* Queue ignore event for the watch */ |
| 497 | inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED, | 497 | inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED, |
| 498 | NULL, FSNOTIFY_EVENT_NONE, NULL); | 498 | NULL, FSNOTIFY_EVENT_NONE, NULL, 0); |
| 499 | 499 | ||
| 500 | i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); | 500 | i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); |
| 501 | /* remove this mark from the idr */ | 501 | /* remove this mark from the idr */ |
| @@ -633,11 +633,23 @@ static int inotify_update_watch(struct fsnotify_group *group, struct inode *inod | |||
| 633 | static struct fsnotify_group *inotify_new_group(unsigned int max_events) | 633 | static struct fsnotify_group *inotify_new_group(unsigned int max_events) |
| 634 | { | 634 | { |
| 635 | struct fsnotify_group *group; | 635 | struct fsnotify_group *group; |
| 636 | struct inotify_event_info *oevent; | ||
| 636 | 637 | ||
| 637 | group = fsnotify_alloc_group(&inotify_fsnotify_ops); | 638 | group = fsnotify_alloc_group(&inotify_fsnotify_ops); |
| 638 | if (IS_ERR(group)) | 639 | if (IS_ERR(group)) |
| 639 | return group; | 640 | return group; |
| 640 | 641 | ||
| 642 | oevent = kmalloc(sizeof(struct inotify_event_info), GFP_KERNEL); | ||
| 643 | if (unlikely(!oevent)) { | ||
| 644 | fsnotify_destroy_group(group); | ||
| 645 | return ERR_PTR(-ENOMEM); | ||
| 646 | } | ||
| 647 | group->overflow_event = &oevent->fse; | ||
| 648 | fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW); | ||
| 649 | oevent->wd = -1; | ||
| 650 | oevent->sync_cookie = 0; | ||
| 651 | oevent->name_len = 0; | ||
| 652 | |||
| 641 | group->max_events = max_events; | 653 | group->max_events = max_events; |
| 642 | 654 | ||
| 643 | spin_lock_init(&group->inotify_data.idr_lock); | 655 | spin_lock_init(&group->inotify_data.idr_lock); |
diff --git a/fs/notify/notification.c b/fs/notify/notification.c index 18b3c4427dca..1e58402171a5 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c | |||
| @@ -80,7 +80,8 @@ void fsnotify_destroy_event(struct fsnotify_group *group, | |||
| 80 | /* | 80 | /* |
| 81 | * Add an event to the group notification queue. The group can later pull this | 81 | * Add an event to the group notification queue. The group can later pull this |
| 82 | * event off the queue to deal with. The function returns 0 if the event was | 82 | * event off the queue to deal with. The function returns 0 if the event was |
| 83 | * added to the queue, 1 if the event was merged with some other queued event. | 83 | * added to the queue, 1 if the event was merged with some other queued event, |
| 84 | * 2 if the queue of events has overflown. | ||
| 84 | */ | 85 | */ |
| 85 | int fsnotify_add_notify_event(struct fsnotify_group *group, | 86 | int fsnotify_add_notify_event(struct fsnotify_group *group, |
| 86 | struct fsnotify_event *event, | 87 | struct fsnotify_event *event, |
| @@ -95,10 +96,14 @@ int fsnotify_add_notify_event(struct fsnotify_group *group, | |||
| 95 | mutex_lock(&group->notification_mutex); | 96 | mutex_lock(&group->notification_mutex); |
| 96 | 97 | ||
| 97 | if (group->q_len >= group->max_events) { | 98 | if (group->q_len >= group->max_events) { |
| 99 | ret = 2; | ||
| 98 | /* Queue overflow event only if it isn't already queued */ | 100 | /* Queue overflow event only if it isn't already queued */ |
| 99 | if (list_empty(&group->overflow_event.list)) | 101 | if (!list_empty(&group->overflow_event->list)) { |
| 100 | event = &group->overflow_event; | 102 | mutex_unlock(&group->notification_mutex); |
| 101 | ret = 1; | 103 | return ret; |
| 104 | } | ||
| 105 | event = group->overflow_event; | ||
| 106 | goto queue; | ||
| 102 | } | 107 | } |
| 103 | 108 | ||
| 104 | if (!list_empty(list) && merge) { | 109 | if (!list_empty(list) && merge) { |
| @@ -109,6 +114,7 @@ int fsnotify_add_notify_event(struct fsnotify_group *group, | |||
| 109 | } | 114 | } |
| 110 | } | 115 | } |
| 111 | 116 | ||
| 117 | queue: | ||
| 112 | group->q_len++; | 118 | group->q_len++; |
| 113 | list_add_tail(&event->list, list); | 119 | list_add_tail(&event->list, list); |
| 114 | mutex_unlock(&group->notification_mutex); | 120 | mutex_unlock(&group->notification_mutex); |
| @@ -132,7 +138,11 @@ struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group *group | |||
| 132 | 138 | ||
| 133 | event = list_first_entry(&group->notification_list, | 139 | event = list_first_entry(&group->notification_list, |
| 134 | struct fsnotify_event, list); | 140 | struct fsnotify_event, list); |
| 135 | list_del(&event->list); | 141 | /* |
| 142 | * We need to init list head for the case of overflow event so that | ||
| 143 | * check in fsnotify_add_notify_events() works | ||
| 144 | */ | ||
| 145 | list_del_init(&event->list); | ||
| 136 | group->q_len--; | 146 | group->q_len--; |
| 137 | 147 | ||
| 138 | return event; | 148 | return event; |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 8450262bcf2a..51632c40e896 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -2393,8 +2393,8 @@ out_dio: | |||
| 2393 | 2393 | ||
| 2394 | if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || | 2394 | if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || |
| 2395 | ((file->f_flags & O_DIRECT) && !direct_io)) { | 2395 | ((file->f_flags & O_DIRECT) && !direct_io)) { |
| 2396 | ret = filemap_fdatawrite_range(file->f_mapping, pos, | 2396 | ret = filemap_fdatawrite_range(file->f_mapping, *ppos, |
| 2397 | pos + count - 1); | 2397 | *ppos + count - 1); |
| 2398 | if (ret < 0) | 2398 | if (ret < 0) |
| 2399 | written = ret; | 2399 | written = ret; |
| 2400 | 2400 | ||
| @@ -2407,8 +2407,8 @@ out_dio: | |||
| 2407 | } | 2407 | } |
| 2408 | 2408 | ||
| 2409 | if (!ret) | 2409 | if (!ret) |
| 2410 | ret = filemap_fdatawait_range(file->f_mapping, pos, | 2410 | ret = filemap_fdatawait_range(file->f_mapping, *ppos, |
| 2411 | pos + count - 1); | 2411 | *ppos + count - 1); |
| 2412 | } | 2412 | } |
| 2413 | 2413 | ||
| 2414 | /* | 2414 | /* |
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index aaa50611ec66..d7b5108789e2 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c | |||
| @@ -717,6 +717,12 @@ static int ocfs2_release_dquot(struct dquot *dquot) | |||
| 717 | */ | 717 | */ |
| 718 | if (status < 0) | 718 | if (status < 0) |
| 719 | mlog_errno(status); | 719 | mlog_errno(status); |
| 720 | /* | ||
| 721 | * Clear dq_off so that we search for the structure in quota file next | ||
| 722 | * time we acquire it. The structure might be deleted and reallocated | ||
| 723 | * elsewhere by another node while our dquot structure is on freelist. | ||
| 724 | */ | ||
| 725 | dquot->dq_off = 0; | ||
| 720 | clear_bit(DQ_ACTIVE_B, &dquot->dq_flags); | 726 | clear_bit(DQ_ACTIVE_B, &dquot->dq_flags); |
| 721 | out_trans: | 727 | out_trans: |
| 722 | ocfs2_commit_trans(osb, handle); | 728 | ocfs2_commit_trans(osb, handle); |
| @@ -756,16 +762,17 @@ static int ocfs2_acquire_dquot(struct dquot *dquot) | |||
| 756 | status = ocfs2_lock_global_qf(info, 1); | 762 | status = ocfs2_lock_global_qf(info, 1); |
| 757 | if (status < 0) | 763 | if (status < 0) |
| 758 | goto out; | 764 | goto out; |
| 759 | if (!test_bit(DQ_READ_B, &dquot->dq_flags)) { | 765 | status = ocfs2_qinfo_lock(info, 0); |
| 760 | status = ocfs2_qinfo_lock(info, 0); | 766 | if (status < 0) |
| 761 | if (status < 0) | 767 | goto out_dq; |
| 762 | goto out_dq; | 768 | /* |
| 763 | status = qtree_read_dquot(&info->dqi_gi, dquot); | 769 | * We always want to read dquot structure from disk because we don't |
| 764 | ocfs2_qinfo_unlock(info, 0); | 770 | * know what happened with it while it was on freelist. |
| 765 | if (status < 0) | 771 | */ |
| 766 | goto out_dq; | 772 | status = qtree_read_dquot(&info->dqi_gi, dquot); |
| 767 | } | 773 | ocfs2_qinfo_unlock(info, 0); |
| 768 | set_bit(DQ_READ_B, &dquot->dq_flags); | 774 | if (status < 0) |
| 775 | goto out_dq; | ||
| 769 | 776 | ||
| 770 | OCFS2_DQUOT(dquot)->dq_use_count++; | 777 | OCFS2_DQUOT(dquot)->dq_use_count++; |
| 771 | OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace; | 778 | OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace; |
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 2e4344be3b96..2001862bf2b1 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c | |||
| @@ -1303,10 +1303,6 @@ int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot) | |||
| 1303 | ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh); | 1303 | ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh); |
| 1304 | 1304 | ||
| 1305 | out: | 1305 | out: |
| 1306 | /* Clear the read bit so that next time someone uses this | ||
| 1307 | * dquot he reads fresh info from disk and allocates local | ||
| 1308 | * dquot structure */ | ||
| 1309 | clear_bit(DQ_READ_B, &dquot->dq_flags); | ||
| 1310 | return status; | 1306 | return status; |
| 1311 | } | 1307 | } |
| 1312 | 1308 | ||
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index 1324e6600e57..ca5ce14cbddc 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c | |||
| @@ -346,7 +346,9 @@ int ocfs2_cluster_connect(const char *stack_name, | |||
| 346 | 346 | ||
| 347 | strlcpy(new_conn->cc_name, group, GROUP_NAME_MAX + 1); | 347 | strlcpy(new_conn->cc_name, group, GROUP_NAME_MAX + 1); |
| 348 | new_conn->cc_namelen = grouplen; | 348 | new_conn->cc_namelen = grouplen; |
| 349 | strlcpy(new_conn->cc_cluster_name, cluster_name, CLUSTER_NAME_MAX + 1); | 349 | if (cluster_name_len) |
| 350 | strlcpy(new_conn->cc_cluster_name, cluster_name, | ||
| 351 | CLUSTER_NAME_MAX + 1); | ||
| 350 | new_conn->cc_cluster_name_len = cluster_name_len; | 352 | new_conn->cc_cluster_name_len = cluster_name_len; |
| 351 | new_conn->cc_recovery_handler = recovery_handler; | 353 | new_conn->cc_recovery_handler = recovery_handler; |
| 352 | new_conn->cc_recovery_data = recovery_data; | 354 | new_conn->cc_recovery_data = recovery_data; |
| @@ -705,6 +705,10 @@ static int do_dentry_open(struct file *f, | |||
| 705 | return 0; | 705 | return 0; |
| 706 | } | 706 | } |
| 707 | 707 | ||
| 708 | /* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */ | ||
| 709 | if (S_ISREG(inode->i_mode)) | ||
| 710 | f->f_mode |= FMODE_ATOMIC_POS; | ||
| 711 | |||
| 708 | f->f_op = fops_get(inode->i_fop); | 712 | f->f_op = fops_get(inode->i_fop); |
| 709 | if (unlikely(WARN_ON(!f->f_op))) { | 713 | if (unlikely(WARN_ON(!f->f_op))) { |
| 710 | error = -ENODEV; | 714 | error = -ENODEV; |
diff --git a/fs/pnode.c b/fs/pnode.c index c7221bb19801..88396df725b4 100644 --- a/fs/pnode.c +++ b/fs/pnode.c | |||
| @@ -220,14 +220,14 @@ static struct mount *get_source(struct mount *dest, | |||
| 220 | * @tree_list : list of heads of trees to be attached. | 220 | * @tree_list : list of heads of trees to be attached. |
| 221 | */ | 221 | */ |
| 222 | int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp, | 222 | int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp, |
| 223 | struct mount *source_mnt, struct list_head *tree_list) | 223 | struct mount *source_mnt, struct hlist_head *tree_list) |
| 224 | { | 224 | { |
| 225 | struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns; | 225 | struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns; |
| 226 | struct mount *m, *child; | 226 | struct mount *m, *child; |
| 227 | int ret = 0; | 227 | int ret = 0; |
| 228 | struct mount *prev_dest_mnt = dest_mnt; | 228 | struct mount *prev_dest_mnt = dest_mnt; |
| 229 | struct mount *prev_src_mnt = source_mnt; | 229 | struct mount *prev_src_mnt = source_mnt; |
| 230 | LIST_HEAD(tmp_list); | 230 | HLIST_HEAD(tmp_list); |
| 231 | 231 | ||
| 232 | for (m = propagation_next(dest_mnt, dest_mnt); m; | 232 | for (m = propagation_next(dest_mnt, dest_mnt); m; |
| 233 | m = propagation_next(m, dest_mnt)) { | 233 | m = propagation_next(m, dest_mnt)) { |
| @@ -246,27 +246,29 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp, | |||
| 246 | child = copy_tree(source, source->mnt.mnt_root, type); | 246 | child = copy_tree(source, source->mnt.mnt_root, type); |
| 247 | if (IS_ERR(child)) { | 247 | if (IS_ERR(child)) { |
| 248 | ret = PTR_ERR(child); | 248 | ret = PTR_ERR(child); |
| 249 | list_splice(tree_list, tmp_list.prev); | 249 | tmp_list = *tree_list; |
| 250 | tmp_list.first->pprev = &tmp_list.first; | ||
| 251 | INIT_HLIST_HEAD(tree_list); | ||
| 250 | goto out; | 252 | goto out; |
| 251 | } | 253 | } |
| 252 | 254 | ||
| 253 | if (is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) { | 255 | if (is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) { |
| 254 | mnt_set_mountpoint(m, dest_mp, child); | 256 | mnt_set_mountpoint(m, dest_mp, child); |
| 255 | list_add_tail(&child->mnt_hash, tree_list); | 257 | hlist_add_head(&child->mnt_hash, tree_list); |
| 256 | } else { | 258 | } else { |
| 257 | /* | 259 | /* |
| 258 | * This can happen if the parent mount was bind mounted | 260 | * This can happen if the parent mount was bind mounted |
| 259 | * on some subdirectory of a shared/slave mount. | 261 | * on some subdirectory of a shared/slave mount. |
| 260 | */ | 262 | */ |
| 261 | list_add_tail(&child->mnt_hash, &tmp_list); | 263 | hlist_add_head(&child->mnt_hash, &tmp_list); |
| 262 | } | 264 | } |
| 263 | prev_dest_mnt = m; | 265 | prev_dest_mnt = m; |
| 264 | prev_src_mnt = child; | 266 | prev_src_mnt = child; |
| 265 | } | 267 | } |
| 266 | out: | 268 | out: |
| 267 | lock_mount_hash(); | 269 | lock_mount_hash(); |
| 268 | while (!list_empty(&tmp_list)) { | 270 | while (!hlist_empty(&tmp_list)) { |
| 269 | child = list_first_entry(&tmp_list, struct mount, mnt_hash); | 271 | child = hlist_entry(tmp_list.first, struct mount, mnt_hash); |
| 270 | umount_tree(child, 0); | 272 | umount_tree(child, 0); |
| 271 | } | 273 | } |
| 272 | unlock_mount_hash(); | 274 | unlock_mount_hash(); |
| @@ -338,8 +340,10 @@ static void __propagate_umount(struct mount *mnt) | |||
| 338 | * umount the child only if the child has no | 340 | * umount the child only if the child has no |
| 339 | * other children | 341 | * other children |
| 340 | */ | 342 | */ |
| 341 | if (child && list_empty(&child->mnt_mounts)) | 343 | if (child && list_empty(&child->mnt_mounts)) { |
| 342 | list_move_tail(&child->mnt_hash, &mnt->mnt_hash); | 344 | hlist_del_init_rcu(&child->mnt_hash); |
| 345 | hlist_add_before_rcu(&child->mnt_hash, &mnt->mnt_hash); | ||
| 346 | } | ||
| 343 | } | 347 | } |
| 344 | } | 348 | } |
| 345 | 349 | ||
| @@ -350,11 +354,11 @@ static void __propagate_umount(struct mount *mnt) | |||
| 350 | * | 354 | * |
| 351 | * vfsmount lock must be held for write | 355 | * vfsmount lock must be held for write |
| 352 | */ | 356 | */ |
| 353 | int propagate_umount(struct list_head *list) | 357 | int propagate_umount(struct hlist_head *list) |
| 354 | { | 358 | { |
| 355 | struct mount *mnt; | 359 | struct mount *mnt; |
| 356 | 360 | ||
| 357 | list_for_each_entry(mnt, list, mnt_hash) | 361 | hlist_for_each_entry(mnt, list, mnt_hash) |
| 358 | __propagate_umount(mnt); | 362 | __propagate_umount(mnt); |
| 359 | return 0; | 363 | return 0; |
| 360 | } | 364 | } |
diff --git a/fs/pnode.h b/fs/pnode.h index 59e7eda1851e..fc28a27fa892 100644 --- a/fs/pnode.h +++ b/fs/pnode.h | |||
| @@ -36,8 +36,8 @@ static inline void set_mnt_shared(struct mount *mnt) | |||
| 36 | 36 | ||
| 37 | void change_mnt_propagation(struct mount *, int); | 37 | void change_mnt_propagation(struct mount *, int); |
| 38 | int propagate_mnt(struct mount *, struct mountpoint *, struct mount *, | 38 | int propagate_mnt(struct mount *, struct mountpoint *, struct mount *, |
| 39 | struct list_head *); | 39 | struct hlist_head *); |
| 40 | int propagate_umount(struct list_head *); | 40 | int propagate_umount(struct hlist_head *); |
| 41 | int propagate_mount_busy(struct mount *, int); | 41 | int propagate_mount_busy(struct mount *, int); |
| 42 | void mnt_release_group_id(struct mount *); | 42 | void mnt_release_group_id(struct mount *); |
| 43 | int get_dominating_id(struct mount *mnt, const struct path *root); | 43 | int get_dominating_id(struct mount *mnt, const struct path *root); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 51507065263b..b9760628e1fd 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -1824,6 +1824,7 @@ static int proc_map_files_get_link(struct dentry *dentry, struct path *path) | |||
| 1824 | if (rc) | 1824 | if (rc) |
| 1825 | goto out_mmput; | 1825 | goto out_mmput; |
| 1826 | 1826 | ||
| 1827 | rc = -ENOENT; | ||
| 1827 | down_read(&mm->mmap_sem); | 1828 | down_read(&mm->mmap_sem); |
| 1828 | vma = find_exact_vma(mm, vm_start, vm_end); | 1829 | vma = find_exact_vma(mm, vm_start, vm_end); |
| 1829 | if (vma && vma->vm_file) { | 1830 | if (vma && vma->vm_file) { |
diff --git a/fs/proc/page.c b/fs/proc/page.c index 02174a610315..e647c55275d9 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c | |||
| @@ -121,9 +121,8 @@ u64 stable_page_flags(struct page *page) | |||
| 121 | * just checks PG_head/PG_tail, so we need to check PageLRU/PageAnon | 121 | * just checks PG_head/PG_tail, so we need to check PageLRU/PageAnon |
| 122 | * to make sure a given page is a thp, not a non-huge compound page. | 122 | * to make sure a given page is a thp, not a non-huge compound page. |
| 123 | */ | 123 | */ |
| 124 | else if (PageTransCompound(page) && | 124 | else if (PageTransCompound(page) && (PageLRU(compound_head(page)) || |
| 125 | (PageLRU(compound_trans_head(page)) || | 125 | PageAnon(compound_head(page)))) |
| 126 | PageAnon(compound_trans_head(page)))) | ||
| 127 | u |= 1 << KPF_THP; | 126 | u |= 1 << KPF_THP; |
| 128 | 127 | ||
| 129 | /* | 128 | /* |
diff --git a/fs/proc/stat.c b/fs/proc/stat.c index 6f599c62f0cc..9d231e9e5f0e 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
| 10 | #include <linux/time.h> | 10 | #include <linux/time.h> |
| 11 | #include <linux/irqnr.h> | 11 | #include <linux/irqnr.h> |
| 12 | #include <asm/cputime.h> | 12 | #include <linux/cputime.h> |
| 13 | #include <linux/tick.h> | 13 | #include <linux/tick.h> |
| 14 | 14 | ||
| 15 | #ifndef arch_irq_stat_cpu | 15 | #ifndef arch_irq_stat_cpu |
diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c index 7141b8d0ca9e..33de567c25af 100644 --- a/fs/proc/uptime.c +++ b/fs/proc/uptime.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #include <linux/seq_file.h> | 5 | #include <linux/seq_file.h> |
| 6 | #include <linux/time.h> | 6 | #include <linux/time.h> |
| 7 | #include <linux/kernel_stat.h> | 7 | #include <linux/kernel_stat.h> |
| 8 | #include <asm/cputime.h> | 8 | #include <linux/cputime.h> |
| 9 | 9 | ||
| 10 | static int uptime_proc_show(struct seq_file *m, void *v) | 10 | static int uptime_proc_show(struct seq_file *m, void *v) |
| 11 | { | 11 | { |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 831d49a4111f..cfc8dcc16043 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
| @@ -581,9 +581,17 @@ int dquot_scan_active(struct super_block *sb, | |||
| 581 | dqstats_inc(DQST_LOOKUPS); | 581 | dqstats_inc(DQST_LOOKUPS); |
| 582 | dqput(old_dquot); | 582 | dqput(old_dquot); |
| 583 | old_dquot = dquot; | 583 | old_dquot = dquot; |
| 584 | ret = fn(dquot, priv); | 584 | /* |
| 585 | if (ret < 0) | 585 | * ->release_dquot() can be racing with us. Our reference |
| 586 | goto out; | 586 | * protects us from new calls to it so just wait for any |
| 587 | * outstanding call and recheck the DQ_ACTIVE_B after that. | ||
| 588 | */ | ||
| 589 | wait_on_dquot(dquot); | ||
| 590 | if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { | ||
| 591 | ret = fn(dquot, priv); | ||
| 592 | if (ret < 0) | ||
| 593 | goto out; | ||
| 594 | } | ||
| 587 | spin_lock(&dq_list_lock); | 595 | spin_lock(&dq_list_lock); |
| 588 | /* We are safe to continue now because our dquot could not | 596 | /* We are safe to continue now because our dquot could not |
| 589 | * be moved out of the inuse list while we hold the reference */ | 597 | * be moved out of the inuse list while we hold the reference */ |
diff --git a/fs/read_write.c b/fs/read_write.c index edc5746a902a..31c6efa43183 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -264,10 +264,22 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int whence) | |||
| 264 | } | 264 | } |
| 265 | EXPORT_SYMBOL(vfs_llseek); | 265 | EXPORT_SYMBOL(vfs_llseek); |
| 266 | 266 | ||
| 267 | static inline struct fd fdget_pos(int fd) | ||
| 268 | { | ||
| 269 | return __to_fd(__fdget_pos(fd)); | ||
| 270 | } | ||
| 271 | |||
| 272 | static inline void fdput_pos(struct fd f) | ||
| 273 | { | ||
| 274 | if (f.flags & FDPUT_POS_UNLOCK) | ||
| 275 | mutex_unlock(&f.file->f_pos_lock); | ||
| 276 | fdput(f); | ||
| 277 | } | ||
| 278 | |||
| 267 | SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence) | 279 | SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence) |
| 268 | { | 280 | { |
| 269 | off_t retval; | 281 | off_t retval; |
| 270 | struct fd f = fdget(fd); | 282 | struct fd f = fdget_pos(fd); |
| 271 | if (!f.file) | 283 | if (!f.file) |
| 272 | return -EBADF; | 284 | return -EBADF; |
| 273 | 285 | ||
| @@ -278,7 +290,7 @@ SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence) | |||
| 278 | if (res != (loff_t)retval) | 290 | if (res != (loff_t)retval) |
| 279 | retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ | 291 | retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ |
| 280 | } | 292 | } |
| 281 | fdput(f); | 293 | fdput_pos(f); |
| 282 | return retval; | 294 | return retval; |
| 283 | } | 295 | } |
| 284 | 296 | ||
| @@ -295,7 +307,7 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, | |||
| 295 | unsigned int, whence) | 307 | unsigned int, whence) |
| 296 | { | 308 | { |
| 297 | int retval; | 309 | int retval; |
| 298 | struct fd f = fdget(fd); | 310 | struct fd f = fdget_pos(fd); |
| 299 | loff_t offset; | 311 | loff_t offset; |
| 300 | 312 | ||
| 301 | if (!f.file) | 313 | if (!f.file) |
| @@ -315,7 +327,7 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, | |||
| 315 | retval = 0; | 327 | retval = 0; |
| 316 | } | 328 | } |
| 317 | out_putf: | 329 | out_putf: |
| 318 | fdput(f); | 330 | fdput_pos(f); |
| 319 | return retval; | 331 | return retval; |
| 320 | } | 332 | } |
| 321 | #endif | 333 | #endif |
| @@ -498,7 +510,7 @@ static inline void file_pos_write(struct file *file, loff_t pos) | |||
| 498 | 510 | ||
| 499 | SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) | 511 | SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) |
| 500 | { | 512 | { |
| 501 | struct fd f = fdget(fd); | 513 | struct fd f = fdget_pos(fd); |
| 502 | ssize_t ret = -EBADF; | 514 | ssize_t ret = -EBADF; |
| 503 | 515 | ||
| 504 | if (f.file) { | 516 | if (f.file) { |
| @@ -506,7 +518,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) | |||
| 506 | ret = vfs_read(f.file, buf, count, &pos); | 518 | ret = vfs_read(f.file, buf, count, &pos); |
| 507 | if (ret >= 0) | 519 | if (ret >= 0) |
| 508 | file_pos_write(f.file, pos); | 520 | file_pos_write(f.file, pos); |
| 509 | fdput(f); | 521 | fdput_pos(f); |
| 510 | } | 522 | } |
| 511 | return ret; | 523 | return ret; |
| 512 | } | 524 | } |
| @@ -514,7 +526,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) | |||
| 514 | SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, | 526 | SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, |
| 515 | size_t, count) | 527 | size_t, count) |
| 516 | { | 528 | { |
| 517 | struct fd f = fdget(fd); | 529 | struct fd f = fdget_pos(fd); |
| 518 | ssize_t ret = -EBADF; | 530 | ssize_t ret = -EBADF; |
| 519 | 531 | ||
| 520 | if (f.file) { | 532 | if (f.file) { |
| @@ -522,7 +534,7 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, | |||
| 522 | ret = vfs_write(f.file, buf, count, &pos); | 534 | ret = vfs_write(f.file, buf, count, &pos); |
| 523 | if (ret >= 0) | 535 | if (ret >= 0) |
| 524 | file_pos_write(f.file, pos); | 536 | file_pos_write(f.file, pos); |
| 525 | fdput(f); | 537 | fdput_pos(f); |
| 526 | } | 538 | } |
| 527 | 539 | ||
| 528 | return ret; | 540 | return ret; |
| @@ -797,7 +809,7 @@ EXPORT_SYMBOL(vfs_writev); | |||
| 797 | SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | 809 | SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, |
| 798 | unsigned long, vlen) | 810 | unsigned long, vlen) |
| 799 | { | 811 | { |
| 800 | struct fd f = fdget(fd); | 812 | struct fd f = fdget_pos(fd); |
| 801 | ssize_t ret = -EBADF; | 813 | ssize_t ret = -EBADF; |
| 802 | 814 | ||
| 803 | if (f.file) { | 815 | if (f.file) { |
| @@ -805,7 +817,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | |||
| 805 | ret = vfs_readv(f.file, vec, vlen, &pos); | 817 | ret = vfs_readv(f.file, vec, vlen, &pos); |
| 806 | if (ret >= 0) | 818 | if (ret >= 0) |
| 807 | file_pos_write(f.file, pos); | 819 | file_pos_write(f.file, pos); |
| 808 | fdput(f); | 820 | fdput_pos(f); |
| 809 | } | 821 | } |
| 810 | 822 | ||
| 811 | if (ret > 0) | 823 | if (ret > 0) |
| @@ -817,7 +829,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | |||
| 817 | SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | 829 | SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, |
| 818 | unsigned long, vlen) | 830 | unsigned long, vlen) |
| 819 | { | 831 | { |
| 820 | struct fd f = fdget(fd); | 832 | struct fd f = fdget_pos(fd); |
| 821 | ssize_t ret = -EBADF; | 833 | ssize_t ret = -EBADF; |
| 822 | 834 | ||
| 823 | if (f.file) { | 835 | if (f.file) { |
| @@ -825,7 +837,7 @@ SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | |||
| 825 | ret = vfs_writev(f.file, vec, vlen, &pos); | 837 | ret = vfs_writev(f.file, vec, vlen, &pos); |
| 826 | if (ret >= 0) | 838 | if (ret >= 0) |
| 827 | file_pos_write(f.file, pos); | 839 | file_pos_write(f.file, pos); |
| 828 | fdput(f); | 840 | fdput_pos(f); |
| 829 | } | 841 | } |
| 830 | 842 | ||
| 831 | if (ret > 0) | 843 | if (ret > 0) |
| @@ -968,7 +980,7 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, | |||
| 968 | const struct compat_iovec __user *,vec, | 980 | const struct compat_iovec __user *,vec, |
| 969 | compat_ulong_t, vlen) | 981 | compat_ulong_t, vlen) |
| 970 | { | 982 | { |
| 971 | struct fd f = fdget(fd); | 983 | struct fd f = fdget_pos(fd); |
| 972 | ssize_t ret; | 984 | ssize_t ret; |
| 973 | loff_t pos; | 985 | loff_t pos; |
| 974 | 986 | ||
| @@ -978,13 +990,13 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, | |||
| 978 | ret = compat_readv(f.file, vec, vlen, &pos); | 990 | ret = compat_readv(f.file, vec, vlen, &pos); |
| 979 | if (ret >= 0) | 991 | if (ret >= 0) |
| 980 | f.file->f_pos = pos; | 992 | f.file->f_pos = pos; |
| 981 | fdput(f); | 993 | fdput_pos(f); |
| 982 | return ret; | 994 | return ret; |
| 983 | } | 995 | } |
| 984 | 996 | ||
| 985 | COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd, | 997 | static long __compat_sys_preadv64(unsigned long fd, |
| 986 | const struct compat_iovec __user *,vec, | 998 | const struct compat_iovec __user *vec, |
| 987 | unsigned long, vlen, loff_t, pos) | 999 | unsigned long vlen, loff_t pos) |
| 988 | { | 1000 | { |
| 989 | struct fd f; | 1001 | struct fd f; |
| 990 | ssize_t ret; | 1002 | ssize_t ret; |
| @@ -1001,12 +1013,22 @@ COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd, | |||
| 1001 | return ret; | 1013 | return ret; |
| 1002 | } | 1014 | } |
| 1003 | 1015 | ||
| 1016 | #ifdef __ARCH_WANT_COMPAT_SYS_PREADV64 | ||
| 1017 | COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd, | ||
| 1018 | const struct compat_iovec __user *,vec, | ||
| 1019 | unsigned long, vlen, loff_t, pos) | ||
| 1020 | { | ||
| 1021 | return __compat_sys_preadv64(fd, vec, vlen, pos); | ||
| 1022 | } | ||
| 1023 | #endif | ||
| 1024 | |||
| 1004 | COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd, | 1025 | COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd, |
| 1005 | const struct compat_iovec __user *,vec, | 1026 | const struct compat_iovec __user *,vec, |
| 1006 | compat_ulong_t, vlen, u32, pos_low, u32, pos_high) | 1027 | compat_ulong_t, vlen, u32, pos_low, u32, pos_high) |
| 1007 | { | 1028 | { |
| 1008 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | 1029 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; |
| 1009 | return compat_sys_preadv64(fd, vec, vlen, pos); | 1030 | |
| 1031 | return __compat_sys_preadv64(fd, vec, vlen, pos); | ||
| 1010 | } | 1032 | } |
| 1011 | 1033 | ||
| 1012 | static size_t compat_writev(struct file *file, | 1034 | static size_t compat_writev(struct file *file, |
| @@ -1035,7 +1057,7 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, | |||
| 1035 | const struct compat_iovec __user *, vec, | 1057 | const struct compat_iovec __user *, vec, |
| 1036 | compat_ulong_t, vlen) | 1058 | compat_ulong_t, vlen) |
| 1037 | { | 1059 | { |
| 1038 | struct fd f = fdget(fd); | 1060 | struct fd f = fdget_pos(fd); |
| 1039 | ssize_t ret; | 1061 | ssize_t ret; |
| 1040 | loff_t pos; | 1062 | loff_t pos; |
| 1041 | 1063 | ||
| @@ -1045,13 +1067,13 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, | |||
| 1045 | ret = compat_writev(f.file, vec, vlen, &pos); | 1067 | ret = compat_writev(f.file, vec, vlen, &pos); |
| 1046 | if (ret >= 0) | 1068 | if (ret >= 0) |
| 1047 | f.file->f_pos = pos; | 1069 | f.file->f_pos = pos; |
| 1048 | fdput(f); | 1070 | fdput_pos(f); |
| 1049 | return ret; | 1071 | return ret; |
| 1050 | } | 1072 | } |
| 1051 | 1073 | ||
| 1052 | COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd, | 1074 | static long __compat_sys_pwritev64(unsigned long fd, |
| 1053 | const struct compat_iovec __user *,vec, | 1075 | const struct compat_iovec __user *vec, |
| 1054 | unsigned long, vlen, loff_t, pos) | 1076 | unsigned long vlen, loff_t pos) |
| 1055 | { | 1077 | { |
| 1056 | struct fd f; | 1078 | struct fd f; |
| 1057 | ssize_t ret; | 1079 | ssize_t ret; |
| @@ -1068,12 +1090,22 @@ COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd, | |||
| 1068 | return ret; | 1090 | return ret; |
| 1069 | } | 1091 | } |
| 1070 | 1092 | ||
| 1093 | #ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64 | ||
| 1094 | COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd, | ||
| 1095 | const struct compat_iovec __user *,vec, | ||
| 1096 | unsigned long, vlen, loff_t, pos) | ||
| 1097 | { | ||
| 1098 | return __compat_sys_pwritev64(fd, vec, vlen, pos); | ||
| 1099 | } | ||
| 1100 | #endif | ||
| 1101 | |||
| 1071 | COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd, | 1102 | COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd, |
| 1072 | const struct compat_iovec __user *,vec, | 1103 | const struct compat_iovec __user *,vec, |
| 1073 | compat_ulong_t, vlen, u32, pos_low, u32, pos_high) | 1104 | compat_ulong_t, vlen, u32, pos_low, u32, pos_high) |
| 1074 | { | 1105 | { |
| 1075 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | 1106 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; |
| 1076 | return compat_sys_pwritev64(fd, vec, vlen, pos); | 1107 | |
| 1108 | return __compat_sys_pwritev64(fd, vec, vlen, pos); | ||
| 1077 | } | 1109 | } |
| 1078 | #endif | 1110 | #endif |
| 1079 | 1111 | ||
| @@ -27,11 +27,10 @@ | |||
| 27 | * wait == 1 case since in that case write_inode() functions do | 27 | * wait == 1 case since in that case write_inode() functions do |
| 28 | * sync_dirty_buffer() and thus effectively write one block at a time. | 28 | * sync_dirty_buffer() and thus effectively write one block at a time. |
| 29 | */ | 29 | */ |
| 30 | static int __sync_filesystem(struct super_block *sb, int wait, | 30 | static int __sync_filesystem(struct super_block *sb, int wait) |
| 31 | unsigned long start) | ||
| 32 | { | 31 | { |
| 33 | if (wait) | 32 | if (wait) |
| 34 | sync_inodes_sb(sb, start); | 33 | sync_inodes_sb(sb); |
| 35 | else | 34 | else |
| 36 | writeback_inodes_sb(sb, WB_REASON_SYNC); | 35 | writeback_inodes_sb(sb, WB_REASON_SYNC); |
| 37 | 36 | ||
| @@ -48,7 +47,6 @@ static int __sync_filesystem(struct super_block *sb, int wait, | |||
| 48 | int sync_filesystem(struct super_block *sb) | 47 | int sync_filesystem(struct super_block *sb) |
| 49 | { | 48 | { |
| 50 | int ret; | 49 | int ret; |
| 51 | unsigned long start = jiffies; | ||
| 52 | 50 | ||
| 53 | /* | 51 | /* |
| 54 | * We need to be protected against the filesystem going from | 52 | * We need to be protected against the filesystem going from |
| @@ -62,17 +60,17 @@ int sync_filesystem(struct super_block *sb) | |||
| 62 | if (sb->s_flags & MS_RDONLY) | 60 | if (sb->s_flags & MS_RDONLY) |
| 63 | return 0; | 61 | return 0; |
| 64 | 62 | ||
| 65 | ret = __sync_filesystem(sb, 0, start); | 63 | ret = __sync_filesystem(sb, 0); |
| 66 | if (ret < 0) | 64 | if (ret < 0) |
| 67 | return ret; | 65 | return ret; |
| 68 | return __sync_filesystem(sb, 1, start); | 66 | return __sync_filesystem(sb, 1); |
| 69 | } | 67 | } |
| 70 | EXPORT_SYMBOL_GPL(sync_filesystem); | 68 | EXPORT_SYMBOL_GPL(sync_filesystem); |
| 71 | 69 | ||
| 72 | static void sync_inodes_one_sb(struct super_block *sb, void *arg) | 70 | static void sync_inodes_one_sb(struct super_block *sb, void *arg) |
| 73 | { | 71 | { |
| 74 | if (!(sb->s_flags & MS_RDONLY)) | 72 | if (!(sb->s_flags & MS_RDONLY)) |
| 75 | sync_inodes_sb(sb, *((unsigned long *)arg)); | 73 | sync_inodes_sb(sb); |
| 76 | } | 74 | } |
| 77 | 75 | ||
| 78 | static void sync_fs_one_sb(struct super_block *sb, void *arg) | 76 | static void sync_fs_one_sb(struct super_block *sb, void *arg) |
| @@ -104,10 +102,9 @@ static void fdatawait_one_bdev(struct block_device *bdev, void *arg) | |||
| 104 | SYSCALL_DEFINE0(sync) | 102 | SYSCALL_DEFINE0(sync) |
| 105 | { | 103 | { |
| 106 | int nowait = 0, wait = 1; | 104 | int nowait = 0, wait = 1; |
| 107 | unsigned long start = jiffies; | ||
| 108 | 105 | ||
| 109 | wakeup_flusher_threads(0, WB_REASON_SYNC); | 106 | wakeup_flusher_threads(0, WB_REASON_SYNC); |
| 110 | iterate_supers(sync_inodes_one_sb, &start); | 107 | iterate_supers(sync_inodes_one_sb, NULL); |
| 111 | iterate_supers(sync_fs_one_sb, &nowait); | 108 | iterate_supers(sync_fs_one_sb, &nowait); |
| 112 | iterate_supers(sync_fs_one_sb, &wait); | 109 | iterate_supers(sync_fs_one_sb, &wait); |
| 113 | iterate_bdevs(fdatawrite_one_bdev, NULL); | 110 | iterate_bdevs(fdatawrite_one_bdev, NULL); |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 6211230814fd..3eaf5c6622eb 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
| @@ -27,6 +27,7 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, | |||
| 27 | { | 27 | { |
| 28 | struct dentry *root; | 28 | struct dentry *root; |
| 29 | void *ns; | 29 | void *ns; |
| 30 | bool new_sb; | ||
| 30 | 31 | ||
| 31 | if (!(flags & MS_KERNMOUNT)) { | 32 | if (!(flags & MS_KERNMOUNT)) { |
| 32 | if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type)) | 33 | if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type)) |
| @@ -37,8 +38,8 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, | |||
| 37 | } | 38 | } |
| 38 | 39 | ||
| 39 | ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET); | 40 | ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET); |
| 40 | root = kernfs_mount_ns(fs_type, flags, sysfs_root, ns); | 41 | root = kernfs_mount_ns(fs_type, flags, sysfs_root, &new_sb, ns); |
| 41 | if (IS_ERR(root)) | 42 | if (IS_ERR(root) || !new_sb) |
| 42 | kobj_ns_drop(KOBJ_NS_TYPE_NET, ns); | 43 | kobj_ns_drop(KOBJ_NS_TYPE_NET, ns); |
| 43 | return root; | 44 | return root; |
| 44 | } | 45 | } |
diff --git a/fs/timerfd.c b/fs/timerfd.c index 929312180dd0..0013142c0475 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c | |||
| @@ -317,6 +317,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) | |||
| 317 | (clockid != CLOCK_MONOTONIC && | 317 | (clockid != CLOCK_MONOTONIC && |
| 318 | clockid != CLOCK_REALTIME && | 318 | clockid != CLOCK_REALTIME && |
| 319 | clockid != CLOCK_REALTIME_ALARM && | 319 | clockid != CLOCK_REALTIME_ALARM && |
| 320 | clockid != CLOCK_BOOTTIME && | ||
| 320 | clockid != CLOCK_BOOTTIME_ALARM)) | 321 | clockid != CLOCK_BOOTTIME_ALARM)) |
| 321 | return -EINVAL; | 322 | return -EINVAL; |
| 322 | 323 | ||
diff --git a/fs/udf/file.c b/fs/udf/file.c index c02a27a19c6d..1037637957c7 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
| @@ -144,6 +144,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 144 | size_t count = iocb->ki_nbytes; | 144 | size_t count = iocb->ki_nbytes; |
| 145 | struct udf_inode_info *iinfo = UDF_I(inode); | 145 | struct udf_inode_info *iinfo = UDF_I(inode); |
| 146 | 146 | ||
| 147 | mutex_lock(&inode->i_mutex); | ||
| 147 | down_write(&iinfo->i_data_sem); | 148 | down_write(&iinfo->i_data_sem); |
| 148 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | 149 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { |
| 149 | if (file->f_flags & O_APPEND) | 150 | if (file->f_flags & O_APPEND) |
| @@ -156,6 +157,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 156 | pos + count)) { | 157 | pos + count)) { |
| 157 | err = udf_expand_file_adinicb(inode); | 158 | err = udf_expand_file_adinicb(inode); |
| 158 | if (err) { | 159 | if (err) { |
| 160 | mutex_unlock(&inode->i_mutex); | ||
| 159 | udf_debug("udf_expand_adinicb: err=%d\n", err); | 161 | udf_debug("udf_expand_adinicb: err=%d\n", err); |
| 160 | return err; | 162 | return err; |
| 161 | } | 163 | } |
| @@ -169,9 +171,17 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 169 | } else | 171 | } else |
| 170 | up_write(&iinfo->i_data_sem); | 172 | up_write(&iinfo->i_data_sem); |
| 171 | 173 | ||
| 172 | retval = generic_file_aio_write(iocb, iov, nr_segs, ppos); | 174 | retval = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); |
| 173 | if (retval > 0) | 175 | mutex_unlock(&inode->i_mutex); |
| 176 | |||
| 177 | if (retval > 0) { | ||
| 178 | ssize_t err; | ||
| 179 | |||
| 174 | mark_inode_dirty(inode); | 180 | mark_inode_dirty(inode); |
| 181 | err = generic_write_sync(file, iocb->ki_pos - retval, retval); | ||
| 182 | if (err < 0) | ||
| 183 | retval = err; | ||
| 184 | } | ||
| 175 | 185 | ||
| 176 | return retval; | 186 | return retval; |
| 177 | } | 187 | } |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 062b7925bca0..982ce05c87ed 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
| @@ -265,6 +265,7 @@ int udf_expand_file_adinicb(struct inode *inode) | |||
| 265 | .nr_to_write = 1, | 265 | .nr_to_write = 1, |
| 266 | }; | 266 | }; |
| 267 | 267 | ||
| 268 | WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); | ||
| 268 | if (!iinfo->i_lenAlloc) { | 269 | if (!iinfo->i_lenAlloc) { |
| 269 | if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) | 270 | if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) |
| 270 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT; | 271 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT; |
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index f317488263dd..d971f4932b5d 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
| @@ -913,7 +913,7 @@ xfs_flush_inodes( | |||
| 913 | struct super_block *sb = mp->m_super; | 913 | struct super_block *sb = mp->m_super; |
| 914 | 914 | ||
| 915 | if (down_read_trylock(&sb->s_umount)) { | 915 | if (down_read_trylock(&sb->s_umount)) { |
| 916 | sync_inodes_sb(sb, jiffies); | 916 | sync_inodes_sb(sb); |
| 917 | up_read(&sb->s_umount); | 917 | up_read(&sb->s_umount); |
| 918 | } | 918 | } |
| 919 | } | 919 | } |
