diff options
author | Ingo Molnar <mingo@elte.hu> | 2012-03-13 11:26:52 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2012-03-13 11:26:52 -0400 |
commit | 47258cf3c4aa5d56e678bafe0dd0d03ddd980b88 (patch) | |
tree | 4856f0fb1185ba97f320a7ed6fb63bf136708a42 /fs | |
parent | c308b56b5398779cd3da0f62ab26b0453494c3d4 (diff) | |
parent | fde7d9049e55ab85a390be7f415d74c9f62dd0f9 (diff) |
Merge tag 'v3.3-rc7' into sched/core
Merge reason: merge back final fixes, prepare for the merge window.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/aio.c | 24 | ||||
-rw-r--r-- | fs/binfmt_aout.c | 14 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 2 | ||||
-rw-r--r-- | fs/btrfs/backref.c | 8 | ||||
-rw-r--r-- | fs/btrfs/reada.c | 2 | ||||
-rw-r--r-- | fs/cifs/dir.c | 20 | ||||
-rw-r--r-- | fs/cifs/inode.c | 28 | ||||
-rw-r--r-- | fs/dcache.c | 33 | ||||
-rw-r--r-- | fs/exec.c | 18 | ||||
-rw-r--r-- | fs/namei.c | 66 |
10 files changed, 138 insertions, 77 deletions
@@ -228,12 +228,6 @@ static void __put_ioctx(struct kioctx *ctx) | |||
228 | call_rcu(&ctx->rcu_head, ctx_rcu_free); | 228 | call_rcu(&ctx->rcu_head, ctx_rcu_free); |
229 | } | 229 | } |
230 | 230 | ||
231 | static inline void get_ioctx(struct kioctx *kioctx) | ||
232 | { | ||
233 | BUG_ON(atomic_read(&kioctx->users) <= 0); | ||
234 | atomic_inc(&kioctx->users); | ||
235 | } | ||
236 | |||
237 | static inline int try_get_ioctx(struct kioctx *kioctx) | 231 | static inline int try_get_ioctx(struct kioctx *kioctx) |
238 | { | 232 | { |
239 | return atomic_inc_not_zero(&kioctx->users); | 233 | return atomic_inc_not_zero(&kioctx->users); |
@@ -273,7 +267,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) | |||
273 | mm = ctx->mm = current->mm; | 267 | mm = ctx->mm = current->mm; |
274 | atomic_inc(&mm->mm_count); | 268 | atomic_inc(&mm->mm_count); |
275 | 269 | ||
276 | atomic_set(&ctx->users, 1); | 270 | atomic_set(&ctx->users, 2); |
277 | spin_lock_init(&ctx->ctx_lock); | 271 | spin_lock_init(&ctx->ctx_lock); |
278 | spin_lock_init(&ctx->ring_info.ring_lock); | 272 | spin_lock_init(&ctx->ring_info.ring_lock); |
279 | init_waitqueue_head(&ctx->wait); | 273 | init_waitqueue_head(&ctx->wait); |
@@ -490,6 +484,8 @@ static void kiocb_batch_free(struct kioctx *ctx, struct kiocb_batch *batch) | |||
490 | kmem_cache_free(kiocb_cachep, req); | 484 | kmem_cache_free(kiocb_cachep, req); |
491 | ctx->reqs_active--; | 485 | ctx->reqs_active--; |
492 | } | 486 | } |
487 | if (unlikely(!ctx->reqs_active && ctx->dead)) | ||
488 | wake_up_all(&ctx->wait); | ||
493 | spin_unlock_irq(&ctx->ctx_lock); | 489 | spin_unlock_irq(&ctx->ctx_lock); |
494 | } | 490 | } |
495 | 491 | ||
@@ -607,11 +603,16 @@ static void aio_fput_routine(struct work_struct *data) | |||
607 | fput(req->ki_filp); | 603 | fput(req->ki_filp); |
608 | 604 | ||
609 | /* Link the iocb into the context's free list */ | 605 | /* Link the iocb into the context's free list */ |
606 | rcu_read_lock(); | ||
610 | spin_lock_irq(&ctx->ctx_lock); | 607 | spin_lock_irq(&ctx->ctx_lock); |
611 | really_put_req(ctx, req); | 608 | really_put_req(ctx, req); |
609 | /* | ||
610 | * at that point ctx might've been killed, but actual | ||
611 | * freeing is RCU'd | ||
612 | */ | ||
612 | spin_unlock_irq(&ctx->ctx_lock); | 613 | spin_unlock_irq(&ctx->ctx_lock); |
614 | rcu_read_unlock(); | ||
613 | 615 | ||
614 | put_ioctx(ctx); | ||
615 | spin_lock_irq(&fput_lock); | 616 | spin_lock_irq(&fput_lock); |
616 | } | 617 | } |
617 | spin_unlock_irq(&fput_lock); | 618 | spin_unlock_irq(&fput_lock); |
@@ -642,7 +643,6 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) | |||
642 | * this function will be executed w/out any aio kthread wakeup. | 643 | * this function will be executed w/out any aio kthread wakeup. |
643 | */ | 644 | */ |
644 | if (unlikely(!fput_atomic(req->ki_filp))) { | 645 | if (unlikely(!fput_atomic(req->ki_filp))) { |
645 | get_ioctx(ctx); | ||
646 | spin_lock(&fput_lock); | 646 | spin_lock(&fput_lock); |
647 | list_add(&req->ki_list, &fput_head); | 647 | list_add(&req->ki_list, &fput_head); |
648 | spin_unlock(&fput_lock); | 648 | spin_unlock(&fput_lock); |
@@ -1336,10 +1336,10 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp) | |||
1336 | ret = PTR_ERR(ioctx); | 1336 | ret = PTR_ERR(ioctx); |
1337 | if (!IS_ERR(ioctx)) { | 1337 | if (!IS_ERR(ioctx)) { |
1338 | ret = put_user(ioctx->user_id, ctxp); | 1338 | ret = put_user(ioctx->user_id, ctxp); |
1339 | if (!ret) | 1339 | if (!ret) { |
1340 | put_ioctx(ioctx); | ||
1340 | return 0; | 1341 | return 0; |
1341 | 1342 | } | |
1342 | get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */ | ||
1343 | io_destroy(ioctx); | 1343 | io_destroy(ioctx); |
1344 | } | 1344 | } |
1345 | 1345 | ||
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index a6395bdb26ae..1ff94054d35a 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c | |||
@@ -259,6 +259,13 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
259 | current->mm->free_area_cache = current->mm->mmap_base; | 259 | current->mm->free_area_cache = current->mm->mmap_base; |
260 | current->mm->cached_hole_size = 0; | 260 | current->mm->cached_hole_size = 0; |
261 | 261 | ||
262 | retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); | ||
263 | if (retval < 0) { | ||
264 | /* Someone check-me: is this error path enough? */ | ||
265 | send_sig(SIGKILL, current, 0); | ||
266 | return retval; | ||
267 | } | ||
268 | |||
262 | install_exec_creds(bprm); | 269 | install_exec_creds(bprm); |
263 | current->flags &= ~PF_FORKNOEXEC; | 270 | current->flags &= ~PF_FORKNOEXEC; |
264 | 271 | ||
@@ -352,13 +359,6 @@ beyond_if: | |||
352 | return retval; | 359 | return retval; |
353 | } | 360 | } |
354 | 361 | ||
355 | retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); | ||
356 | if (retval < 0) { | ||
357 | /* Someone check-me: is this error path enough? */ | ||
358 | send_sig(SIGKILL, current, 0); | ||
359 | return retval; | ||
360 | } | ||
361 | |||
362 | current->mm->start_stack = | 362 | current->mm->start_stack = |
363 | (unsigned long) create_aout_tables((char __user *) bprm->p, bprm); | 363 | (unsigned long) create_aout_tables((char __user *) bprm->p, bprm); |
364 | #ifdef __alpha__ | 364 | #ifdef __alpha__ |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index bcb884e2d613..07d096c49920 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1421,7 +1421,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, | |||
1421 | for (i = 1; i < view->n; ++i) { | 1421 | for (i = 1; i < view->n; ++i) { |
1422 | const struct user_regset *regset = &view->regsets[i]; | 1422 | const struct user_regset *regset = &view->regsets[i]; |
1423 | do_thread_regset_writeback(t->task, regset); | 1423 | do_thread_regset_writeback(t->task, regset); |
1424 | if (regset->core_note_type && | 1424 | if (regset->core_note_type && regset->get && |
1425 | (!regset->active || regset->active(t->task, regset))) { | 1425 | (!regset->active || regset->active(t->task, regset))) { |
1426 | int ret; | 1426 | int ret; |
1427 | size_t size = regset->n * regset->size; | 1427 | size_t size = regset->n * regset->size; |
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 98f6bf10bbd4..0436c12da8c2 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -583,7 +583,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, | |||
583 | struct btrfs_path *path; | 583 | struct btrfs_path *path; |
584 | struct btrfs_key info_key = { 0 }; | 584 | struct btrfs_key info_key = { 0 }; |
585 | struct btrfs_delayed_ref_root *delayed_refs = NULL; | 585 | struct btrfs_delayed_ref_root *delayed_refs = NULL; |
586 | struct btrfs_delayed_ref_head *head = NULL; | 586 | struct btrfs_delayed_ref_head *head; |
587 | int info_level = 0; | 587 | int info_level = 0; |
588 | int ret; | 588 | int ret; |
589 | struct list_head prefs_delayed; | 589 | struct list_head prefs_delayed; |
@@ -607,6 +607,8 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, | |||
607 | * at a specified point in time | 607 | * at a specified point in time |
608 | */ | 608 | */ |
609 | again: | 609 | again: |
610 | head = NULL; | ||
611 | |||
610 | ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0); | 612 | ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0); |
611 | if (ret < 0) | 613 | if (ret < 0) |
612 | goto out; | 614 | goto out; |
@@ -635,8 +637,10 @@ again: | |||
635 | goto again; | 637 | goto again; |
636 | } | 638 | } |
637 | ret = __add_delayed_refs(head, seq, &info_key, &prefs_delayed); | 639 | ret = __add_delayed_refs(head, seq, &info_key, &prefs_delayed); |
638 | if (ret) | 640 | if (ret) { |
641 | spin_unlock(&delayed_refs->lock); | ||
639 | goto out; | 642 | goto out; |
643 | } | ||
640 | } | 644 | } |
641 | spin_unlock(&delayed_refs->lock); | 645 | spin_unlock(&delayed_refs->lock); |
642 | 646 | ||
diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c index 2373b39a132b..22db04550f6a 100644 --- a/fs/btrfs/reada.c +++ b/fs/btrfs/reada.c | |||
@@ -305,7 +305,7 @@ again: | |||
305 | 305 | ||
306 | spin_lock(&fs_info->reada_lock); | 306 | spin_lock(&fs_info->reada_lock); |
307 | ret = radix_tree_insert(&dev->reada_zones, | 307 | ret = radix_tree_insert(&dev->reada_zones, |
308 | (unsigned long)zone->end >> PAGE_CACHE_SHIFT, | 308 | (unsigned long)(zone->end >> PAGE_CACHE_SHIFT), |
309 | zone); | 309 | zone); |
310 | spin_unlock(&fs_info->reada_lock); | 310 | spin_unlock(&fs_info->reada_lock); |
311 | 311 | ||
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 63a196b97d50..bc7e24420ac0 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -584,10 +584,26 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
584 | * If either that or op not supported returned, follow | 584 | * If either that or op not supported returned, follow |
585 | * the normal lookup. | 585 | * the normal lookup. |
586 | */ | 586 | */ |
587 | if ((rc == 0) || (rc == -ENOENT)) | 587 | switch (rc) { |
588 | case 0: | ||
589 | /* | ||
590 | * The server may allow us to open things like | ||
591 | * FIFOs, but the client isn't set up to deal | ||
592 | * with that. If it's not a regular file, just | ||
593 | * close it and proceed as if it were a normal | ||
594 | * lookup. | ||
595 | */ | ||
596 | if (newInode && !S_ISREG(newInode->i_mode)) { | ||
597 | CIFSSMBClose(xid, pTcon, fileHandle); | ||
598 | break; | ||
599 | } | ||
600 | case -ENOENT: | ||
588 | posix_open = true; | 601 | posix_open = true; |
589 | else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP)) | 602 | case -EOPNOTSUPP: |
603 | break; | ||
604 | default: | ||
590 | pTcon->broken_posix_open = true; | 605 | pTcon->broken_posix_open = true; |
606 | } | ||
591 | } | 607 | } |
592 | if (!posix_open) | 608 | if (!posix_open) |
593 | rc = cifs_get_inode_info_unix(&newInode, full_path, | 609 | rc = cifs_get_inode_info_unix(&newInode, full_path, |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index a5f54b7d9822..745da3d0653e 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -534,6 +534,11 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | |||
534 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | 534 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { |
535 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | 535 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; |
536 | fattr->cf_dtype = DT_DIR; | 536 | fattr->cf_dtype = DT_DIR; |
537 | /* | ||
538 | * Server can return wrong NumberOfLinks value for directories | ||
539 | * when Unix extensions are disabled - fake it. | ||
540 | */ | ||
541 | fattr->cf_nlink = 2; | ||
537 | } else { | 542 | } else { |
538 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; | 543 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; |
539 | fattr->cf_dtype = DT_REG; | 544 | fattr->cf_dtype = DT_REG; |
@@ -541,9 +546,9 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | |||
541 | /* clear write bits if ATTR_READONLY is set */ | 546 | /* clear write bits if ATTR_READONLY is set */ |
542 | if (fattr->cf_cifsattrs & ATTR_READONLY) | 547 | if (fattr->cf_cifsattrs & ATTR_READONLY) |
543 | fattr->cf_mode &= ~(S_IWUGO); | 548 | fattr->cf_mode &= ~(S_IWUGO); |
544 | } | ||
545 | 549 | ||
546 | fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); | 550 | fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); |
551 | } | ||
547 | 552 | ||
548 | fattr->cf_uid = cifs_sb->mnt_uid; | 553 | fattr->cf_uid = cifs_sb->mnt_uid; |
549 | fattr->cf_gid = cifs_sb->mnt_gid; | 554 | fattr->cf_gid = cifs_sb->mnt_gid; |
@@ -1322,7 +1327,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) | |||
1322 | } | 1327 | } |
1323 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need | 1328 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need |
1324 | to set uid/gid */ | 1329 | to set uid/gid */ |
1325 | inc_nlink(inode); | ||
1326 | 1330 | ||
1327 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); | 1331 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); |
1328 | cifs_fill_uniqueid(inode->i_sb, &fattr); | 1332 | cifs_fill_uniqueid(inode->i_sb, &fattr); |
@@ -1355,7 +1359,6 @@ mkdir_retry_old: | |||
1355 | d_drop(direntry); | 1359 | d_drop(direntry); |
1356 | } else { | 1360 | } else { |
1357 | mkdir_get_info: | 1361 | mkdir_get_info: |
1358 | inc_nlink(inode); | ||
1359 | if (pTcon->unix_ext) | 1362 | if (pTcon->unix_ext) |
1360 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 1363 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
1361 | inode->i_sb, xid); | 1364 | inode->i_sb, xid); |
@@ -1436,6 +1439,11 @@ mkdir_get_info: | |||
1436 | } | 1439 | } |
1437 | } | 1440 | } |
1438 | mkdir_out: | 1441 | mkdir_out: |
1442 | /* | ||
1443 | * Force revalidate to get parent dir info when needed since cached | ||
1444 | * attributes are invalid now. | ||
1445 | */ | ||
1446 | CIFS_I(inode)->time = 0; | ||
1439 | kfree(full_path); | 1447 | kfree(full_path); |
1440 | FreeXid(xid); | 1448 | FreeXid(xid); |
1441 | cifs_put_tlink(tlink); | 1449 | cifs_put_tlink(tlink); |
@@ -1475,7 +1483,6 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1475 | cifs_put_tlink(tlink); | 1483 | cifs_put_tlink(tlink); |
1476 | 1484 | ||
1477 | if (!rc) { | 1485 | if (!rc) { |
1478 | drop_nlink(inode); | ||
1479 | spin_lock(&direntry->d_inode->i_lock); | 1486 | spin_lock(&direntry->d_inode->i_lock); |
1480 | i_size_write(direntry->d_inode, 0); | 1487 | i_size_write(direntry->d_inode, 0); |
1481 | clear_nlink(direntry->d_inode); | 1488 | clear_nlink(direntry->d_inode); |
@@ -1483,12 +1490,15 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1483 | } | 1490 | } |
1484 | 1491 | ||
1485 | cifsInode = CIFS_I(direntry->d_inode); | 1492 | cifsInode = CIFS_I(direntry->d_inode); |
1486 | cifsInode->time = 0; /* force revalidate to go get info when | 1493 | /* force revalidate to go get info when needed */ |
1487 | needed */ | 1494 | cifsInode->time = 0; |
1488 | 1495 | ||
1489 | cifsInode = CIFS_I(inode); | 1496 | cifsInode = CIFS_I(inode); |
1490 | cifsInode->time = 0; /* force revalidate to get parent dir info | 1497 | /* |
1491 | since cached search results now invalid */ | 1498 | * Force revalidate to get parent dir info when needed since cached |
1499 | * attributes are invalid now. | ||
1500 | */ | ||
1501 | cifsInode->time = 0; | ||
1492 | 1502 | ||
1493 | direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = | 1503 | direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = |
1494 | current_fs_time(inode->i_sb); | 1504 | current_fs_time(inode->i_sb); |
diff --git a/fs/dcache.c b/fs/dcache.c index fe19ac13f75f..bcbdb33fcc20 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -104,7 +104,7 @@ static unsigned int d_hash_shift __read_mostly; | |||
104 | 104 | ||
105 | static struct hlist_bl_head *dentry_hashtable __read_mostly; | 105 | static struct hlist_bl_head *dentry_hashtable __read_mostly; |
106 | 106 | ||
107 | static inline struct hlist_bl_head *d_hash(struct dentry *parent, | 107 | static inline struct hlist_bl_head *d_hash(const struct dentry *parent, |
108 | unsigned long hash) | 108 | unsigned long hash) |
109 | { | 109 | { |
110 | hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES; | 110 | hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES; |
@@ -137,6 +137,26 @@ int proc_nr_dentry(ctl_table *table, int write, void __user *buffer, | |||
137 | } | 137 | } |
138 | #endif | 138 | #endif |
139 | 139 | ||
140 | /* | ||
141 | * Compare 2 name strings, return 0 if they match, otherwise non-zero. | ||
142 | * The strings are both count bytes long, and count is non-zero. | ||
143 | */ | ||
144 | static inline int dentry_cmp(const unsigned char *cs, size_t scount, | ||
145 | const unsigned char *ct, size_t tcount) | ||
146 | { | ||
147 | if (scount != tcount) | ||
148 | return 1; | ||
149 | |||
150 | do { | ||
151 | if (*cs != *ct) | ||
152 | return 1; | ||
153 | cs++; | ||
154 | ct++; | ||
155 | tcount--; | ||
156 | } while (tcount); | ||
157 | return 0; | ||
158 | } | ||
159 | |||
140 | static void __d_free(struct rcu_head *head) | 160 | static void __d_free(struct rcu_head *head) |
141 | { | 161 | { |
142 | struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); | 162 | struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); |
@@ -1717,8 +1737,9 @@ EXPORT_SYMBOL(d_add_ci); | |||
1717 | * child is looked up. Thus, an interlocking stepping of sequence lock checks | 1737 | * child is looked up. Thus, an interlocking stepping of sequence lock checks |
1718 | * is formed, giving integrity down the path walk. | 1738 | * is formed, giving integrity down the path walk. |
1719 | */ | 1739 | */ |
1720 | struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, | 1740 | struct dentry *__d_lookup_rcu(const struct dentry *parent, |
1721 | unsigned *seq, struct inode **inode) | 1741 | const struct qstr *name, |
1742 | unsigned *seqp, struct inode **inode) | ||
1722 | { | 1743 | { |
1723 | unsigned int len = name->len; | 1744 | unsigned int len = name->len; |
1724 | unsigned int hash = name->hash; | 1745 | unsigned int hash = name->hash; |
@@ -1748,6 +1769,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, | |||
1748 | * See Documentation/filesystems/path-lookup.txt for more details. | 1769 | * See Documentation/filesystems/path-lookup.txt for more details. |
1749 | */ | 1770 | */ |
1750 | hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { | 1771 | hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { |
1772 | unsigned seq; | ||
1751 | struct inode *i; | 1773 | struct inode *i; |
1752 | const char *tname; | 1774 | const char *tname; |
1753 | int tlen; | 1775 | int tlen; |
@@ -1756,7 +1778,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, | |||
1756 | continue; | 1778 | continue; |
1757 | 1779 | ||
1758 | seqretry: | 1780 | seqretry: |
1759 | *seq = read_seqcount_begin(&dentry->d_seq); | 1781 | seq = read_seqcount_begin(&dentry->d_seq); |
1760 | if (dentry->d_parent != parent) | 1782 | if (dentry->d_parent != parent) |
1761 | continue; | 1783 | continue; |
1762 | if (d_unhashed(dentry)) | 1784 | if (d_unhashed(dentry)) |
@@ -1771,7 +1793,7 @@ seqretry: | |||
1771 | * edge of memory when walking. If we could load this | 1793 | * edge of memory when walking. If we could load this |
1772 | * atomically some other way, we could drop this check. | 1794 | * atomically some other way, we could drop this check. |
1773 | */ | 1795 | */ |
1774 | if (read_seqcount_retry(&dentry->d_seq, *seq)) | 1796 | if (read_seqcount_retry(&dentry->d_seq, seq)) |
1775 | goto seqretry; | 1797 | goto seqretry; |
1776 | if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) { | 1798 | if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) { |
1777 | if (parent->d_op->d_compare(parent, *inode, | 1799 | if (parent->d_op->d_compare(parent, *inode, |
@@ -1788,6 +1810,7 @@ seqretry: | |||
1788 | * order to do anything useful with the returned dentry | 1810 | * order to do anything useful with the returned dentry |
1789 | * anyway. | 1811 | * anyway. |
1790 | */ | 1812 | */ |
1813 | *seqp = seq; | ||
1791 | *inode = i; | 1814 | *inode = i; |
1792 | return dentry; | 1815 | return dentry; |
1793 | } | 1816 | } |
@@ -1915,7 +1915,6 @@ static int coredump_wait(int exit_code, struct core_state *core_state) | |||
1915 | { | 1915 | { |
1916 | struct task_struct *tsk = current; | 1916 | struct task_struct *tsk = current; |
1917 | struct mm_struct *mm = tsk->mm; | 1917 | struct mm_struct *mm = tsk->mm; |
1918 | struct completion *vfork_done; | ||
1919 | int core_waiters = -EBUSY; | 1918 | int core_waiters = -EBUSY; |
1920 | 1919 | ||
1921 | init_completion(&core_state->startup); | 1920 | init_completion(&core_state->startup); |
@@ -1927,22 +1926,9 @@ static int coredump_wait(int exit_code, struct core_state *core_state) | |||
1927 | core_waiters = zap_threads(tsk, mm, core_state, exit_code); | 1926 | core_waiters = zap_threads(tsk, mm, core_state, exit_code); |
1928 | up_write(&mm->mmap_sem); | 1927 | up_write(&mm->mmap_sem); |
1929 | 1928 | ||
1930 | if (unlikely(core_waiters < 0)) | 1929 | if (core_waiters > 0) |
1931 | goto fail; | ||
1932 | |||
1933 | /* | ||
1934 | * Make sure nobody is waiting for us to release the VM, | ||
1935 | * otherwise we can deadlock when we wait on each other | ||
1936 | */ | ||
1937 | vfork_done = tsk->vfork_done; | ||
1938 | if (vfork_done) { | ||
1939 | tsk->vfork_done = NULL; | ||
1940 | complete(vfork_done); | ||
1941 | } | ||
1942 | |||
1943 | if (core_waiters) | ||
1944 | wait_for_completion(&core_state->startup); | 1930 | wait_for_completion(&core_state->startup); |
1945 | fail: | 1931 | |
1946 | return core_waiters; | 1932 | return core_waiters; |
1947 | } | 1933 | } |
1948 | 1934 | ||
diff --git a/fs/namei.c b/fs/namei.c index a780ea515c47..e2ba62820a0f 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1374,6 +1374,34 @@ static inline int can_lookup(struct inode *inode) | |||
1374 | return 1; | 1374 | return 1; |
1375 | } | 1375 | } |
1376 | 1376 | ||
1377 | unsigned int full_name_hash(const unsigned char *name, unsigned int len) | ||
1378 | { | ||
1379 | unsigned long hash = init_name_hash(); | ||
1380 | while (len--) | ||
1381 | hash = partial_name_hash(*name++, hash); | ||
1382 | return end_name_hash(hash); | ||
1383 | } | ||
1384 | EXPORT_SYMBOL(full_name_hash); | ||
1385 | |||
1386 | /* | ||
1387 | * We know there's a real path component here of at least | ||
1388 | * one character. | ||
1389 | */ | ||
1390 | static inline unsigned long hash_name(const char *name, unsigned int *hashp) | ||
1391 | { | ||
1392 | unsigned long hash = init_name_hash(); | ||
1393 | unsigned long len = 0, c; | ||
1394 | |||
1395 | c = (unsigned char)*name; | ||
1396 | do { | ||
1397 | len++; | ||
1398 | hash = partial_name_hash(c, hash); | ||
1399 | c = (unsigned char)name[len]; | ||
1400 | } while (c && c != '/'); | ||
1401 | *hashp = end_name_hash(hash); | ||
1402 | return len; | ||
1403 | } | ||
1404 | |||
1377 | /* | 1405 | /* |
1378 | * Name resolution. | 1406 | * Name resolution. |
1379 | * This is the basic name resolution function, turning a pathname into | 1407 | * This is the basic name resolution function, turning a pathname into |
@@ -1394,31 +1422,22 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1394 | 1422 | ||
1395 | /* At this point we know we have a real path component. */ | 1423 | /* At this point we know we have a real path component. */ |
1396 | for(;;) { | 1424 | for(;;) { |
1397 | unsigned long hash; | ||
1398 | struct qstr this; | 1425 | struct qstr this; |
1399 | unsigned int c; | 1426 | long len; |
1400 | int type; | 1427 | int type; |
1401 | 1428 | ||
1402 | err = may_lookup(nd); | 1429 | err = may_lookup(nd); |
1403 | if (err) | 1430 | if (err) |
1404 | break; | 1431 | break; |
1405 | 1432 | ||
1433 | len = hash_name(name, &this.hash); | ||
1406 | this.name = name; | 1434 | this.name = name; |
1407 | c = *(const unsigned char *)name; | 1435 | this.len = len; |
1408 | |||
1409 | hash = init_name_hash(); | ||
1410 | do { | ||
1411 | name++; | ||
1412 | hash = partial_name_hash(c, hash); | ||
1413 | c = *(const unsigned char *)name; | ||
1414 | } while (c && (c != '/')); | ||
1415 | this.len = name - (const char *) this.name; | ||
1416 | this.hash = end_name_hash(hash); | ||
1417 | 1436 | ||
1418 | type = LAST_NORM; | 1437 | type = LAST_NORM; |
1419 | if (this.name[0] == '.') switch (this.len) { | 1438 | if (name[0] == '.') switch (len) { |
1420 | case 2: | 1439 | case 2: |
1421 | if (this.name[1] == '.') { | 1440 | if (name[1] == '.') { |
1422 | type = LAST_DOTDOT; | 1441 | type = LAST_DOTDOT; |
1423 | nd->flags |= LOOKUP_JUMPED; | 1442 | nd->flags |= LOOKUP_JUMPED; |
1424 | } | 1443 | } |
@@ -1437,12 +1456,18 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1437 | } | 1456 | } |
1438 | } | 1457 | } |
1439 | 1458 | ||
1440 | /* remove trailing slashes? */ | 1459 | if (!name[len]) |
1441 | if (!c) | ||
1442 | goto last_component; | 1460 | goto last_component; |
1443 | while (*++name == '/'); | 1461 | /* |
1444 | if (!*name) | 1462 | * If it wasn't NUL, we know it was '/'. Skip that |
1463 | * slash, and continue until no more slashes. | ||
1464 | */ | ||
1465 | do { | ||
1466 | len++; | ||
1467 | } while (unlikely(name[len] == '/')); | ||
1468 | if (!name[len]) | ||
1445 | goto last_component; | 1469 | goto last_component; |
1470 | name += len; | ||
1446 | 1471 | ||
1447 | err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW); | 1472 | err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW); |
1448 | if (err < 0) | 1473 | if (err < 0) |
@@ -1775,24 +1800,21 @@ static struct dentry *lookup_hash(struct nameidata *nd) | |||
1775 | struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | 1800 | struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) |
1776 | { | 1801 | { |
1777 | struct qstr this; | 1802 | struct qstr this; |
1778 | unsigned long hash; | ||
1779 | unsigned int c; | 1803 | unsigned int c; |
1780 | 1804 | ||
1781 | WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex)); | 1805 | WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex)); |
1782 | 1806 | ||
1783 | this.name = name; | 1807 | this.name = name; |
1784 | this.len = len; | 1808 | this.len = len; |
1809 | this.hash = full_name_hash(name, len); | ||
1785 | if (!len) | 1810 | if (!len) |
1786 | return ERR_PTR(-EACCES); | 1811 | return ERR_PTR(-EACCES); |
1787 | 1812 | ||
1788 | hash = init_name_hash(); | ||
1789 | while (len--) { | 1813 | while (len--) { |
1790 | c = *(const unsigned char *)name++; | 1814 | c = *(const unsigned char *)name++; |
1791 | if (c == '/' || c == '\0') | 1815 | if (c == '/' || c == '\0') |
1792 | return ERR_PTR(-EACCES); | 1816 | return ERR_PTR(-EACCES); |
1793 | hash = partial_name_hash(c, hash); | ||
1794 | } | 1817 | } |
1795 | this.hash = end_name_hash(hash); | ||
1796 | /* | 1818 | /* |
1797 | * See if the low-level filesystem might want | 1819 | * See if the low-level filesystem might want |
1798 | * to use its own hash.. | 1820 | * to use its own hash.. |