diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/anon_inodes.c | 34 | ||||
-rw-r--r-- | fs/bio-integrity.c | 5 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
-rw-r--r-- | fs/cifs/file.c | 24 | ||||
-rw-r--r-- | fs/cifs/transport.c | 29 | ||||
-rw-r--r-- | fs/compat.c | 121 | ||||
-rw-r--r-- | fs/compat_binfmt_elf.c | 5 | ||||
-rw-r--r-- | fs/compat_ioctl.c | 5 | ||||
-rw-r--r-- | fs/dcache.c | 4 | ||||
-rw-r--r-- | fs/efivarfs/file.c | 13 | ||||
-rw-r--r-- | fs/exec.c | 6 | ||||
-rw-r--r-- | fs/ext4/inode.c | 15 | ||||
-rw-r--r-- | fs/file.c | 47 | ||||
-rw-r--r-- | fs/file_table.c | 1 | ||||
-rw-r--r-- | fs/hfsplus/catalog.c | 41 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_fs.h | 1 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_raw.h | 6 | ||||
-rw-r--r-- | fs/hfsplus/inode.c | 9 | ||||
-rw-r--r-- | fs/mount.h | 4 | ||||
-rw-r--r-- | fs/namei.c | 31 | ||||
-rw-r--r-- | fs/namespace.c | 177 | ||||
-rw-r--r-- | fs/nfs/delegation.c | 11 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 10 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 24 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 14 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 1 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 8 | ||||
-rw-r--r-- | fs/ocfs2/stackglue.c | 4 | ||||
-rw-r--r-- | fs/open.c | 4 | ||||
-rw-r--r-- | fs/pnode.c | 26 | ||||
-rw-r--r-- | fs/pnode.h | 4 | ||||
-rw-r--r-- | fs/proc/base.c | 1 | ||||
-rw-r--r-- | fs/read_write.c | 80 |
33 files changed, 463 insertions, 304 deletions
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/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/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/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/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/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 | ||