aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c82
1 files changed, 54 insertions, 28 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index a901c6901bce..89509b5a090e 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -36,6 +36,7 @@
36#include <linux/bit_spinlock.h> 36#include <linux/bit_spinlock.h>
37#include <linux/rculist_bl.h> 37#include <linux/rculist_bl.h>
38#include <linux/prefetch.h> 38#include <linux/prefetch.h>
39#include <linux/ratelimit.h>
39#include "internal.h" 40#include "internal.h"
40 41
41/* 42/*
@@ -2383,8 +2384,16 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
2383 actual = __d_unalias(inode, dentry, alias); 2384 actual = __d_unalias(inode, dentry, alias);
2384 } 2385 }
2385 write_sequnlock(&rename_lock); 2386 write_sequnlock(&rename_lock);
2386 if (IS_ERR(actual)) 2387 if (IS_ERR(actual)) {
2388 if (PTR_ERR(actual) == -ELOOP)
2389 pr_warn_ratelimited(
2390 "VFS: Lookup of '%s' in %s %s"
2391 " would have caused loop\n",
2392 dentry->d_name.name,
2393 inode->i_sb->s_type->name,
2394 inode->i_sb->s_id);
2387 dput(alias); 2395 dput(alias);
2396 }
2388 goto out_nolock; 2397 goto out_nolock;
2389 } 2398 }
2390 } 2399 }
@@ -2430,16 +2439,14 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name)
2430/** 2439/**
2431 * prepend_path - Prepend path string to a buffer 2440 * prepend_path - Prepend path string to a buffer
2432 * @path: the dentry/vfsmount to report 2441 * @path: the dentry/vfsmount to report
2433 * @root: root vfsmnt/dentry (may be modified by this function) 2442 * @root: root vfsmnt/dentry
2434 * @buffer: pointer to the end of the buffer 2443 * @buffer: pointer to the end of the buffer
2435 * @buflen: pointer to buffer length 2444 * @buflen: pointer to buffer length
2436 * 2445 *
2437 * Caller holds the rename_lock. 2446 * Caller holds the rename_lock.
2438 *
2439 * If path is not reachable from the supplied root, then the value of
2440 * root is changed (without modifying refcounts).
2441 */ 2447 */
2442static int prepend_path(const struct path *path, struct path *root, 2448static int prepend_path(const struct path *path,
2449 const struct path *root,
2443 char **buffer, int *buflen) 2450 char **buffer, int *buflen)
2444{ 2451{
2445 struct dentry *dentry = path->dentry; 2452 struct dentry *dentry = path->dentry;
@@ -2474,10 +2481,10 @@ static int prepend_path(const struct path *path, struct path *root,
2474 dentry = parent; 2481 dentry = parent;
2475 } 2482 }
2476 2483
2477out:
2478 if (!error && !slash) 2484 if (!error && !slash)
2479 error = prepend(buffer, buflen, "/", 1); 2485 error = prepend(buffer, buflen, "/", 1);
2480 2486
2487out:
2481 br_read_unlock(vfsmount_lock); 2488 br_read_unlock(vfsmount_lock);
2482 return error; 2489 return error;
2483 2490
@@ -2491,15 +2498,17 @@ global_root:
2491 WARN(1, "Root dentry has weird name <%.*s>\n", 2498 WARN(1, "Root dentry has weird name <%.*s>\n",
2492 (int) dentry->d_name.len, dentry->d_name.name); 2499 (int) dentry->d_name.len, dentry->d_name.name);
2493 } 2500 }
2494 root->mnt = vfsmnt; 2501 if (!slash)
2495 root->dentry = dentry; 2502 error = prepend(buffer, buflen, "/", 1);
2503 if (!error)
2504 error = vfsmnt->mnt_ns ? 1 : 2;
2496 goto out; 2505 goto out;
2497} 2506}
2498 2507
2499/** 2508/**
2500 * __d_path - return the path of a dentry 2509 * __d_path - return the path of a dentry
2501 * @path: the dentry/vfsmount to report 2510 * @path: the dentry/vfsmount to report
2502 * @root: root vfsmnt/dentry (may be modified by this function) 2511 * @root: root vfsmnt/dentry
2503 * @buf: buffer to return value in 2512 * @buf: buffer to return value in
2504 * @buflen: buffer length 2513 * @buflen: buffer length
2505 * 2514 *
@@ -2510,10 +2519,10 @@ global_root:
2510 * 2519 *
2511 * "buflen" should be positive. 2520 * "buflen" should be positive.
2512 * 2521 *
2513 * If path is not reachable from the supplied root, then the value of 2522 * If the path is not reachable from the supplied root, return %NULL.
2514 * root is changed (without modifying refcounts).
2515 */ 2523 */
2516char *__d_path(const struct path *path, struct path *root, 2524char *__d_path(const struct path *path,
2525 const struct path *root,
2517 char *buf, int buflen) 2526 char *buf, int buflen)
2518{ 2527{
2519 char *res = buf + buflen; 2528 char *res = buf + buflen;
@@ -2524,7 +2533,28 @@ char *__d_path(const struct path *path, struct path *root,
2524 error = prepend_path(path, root, &res, &buflen); 2533 error = prepend_path(path, root, &res, &buflen);
2525 write_sequnlock(&rename_lock); 2534 write_sequnlock(&rename_lock);
2526 2535
2527 if (error) 2536 if (error < 0)
2537 return ERR_PTR(error);
2538 if (error > 0)
2539 return NULL;
2540 return res;
2541}
2542
2543char *d_absolute_path(const struct path *path,
2544 char *buf, int buflen)
2545{
2546 struct path root = {};
2547 char *res = buf + buflen;
2548 int error;
2549
2550 prepend(&res, &buflen, "\0", 1);
2551 write_seqlock(&rename_lock);
2552 error = prepend_path(path, &root, &res, &buflen);
2553 write_sequnlock(&rename_lock);
2554
2555 if (error > 1)
2556 error = -EINVAL;
2557 if (error < 0)
2528 return ERR_PTR(error); 2558 return ERR_PTR(error);
2529 return res; 2559 return res;
2530} 2560}
@@ -2532,8 +2562,9 @@ char *__d_path(const struct path *path, struct path *root,
2532/* 2562/*
2533 * same as __d_path but appends "(deleted)" for unlinked files. 2563 * same as __d_path but appends "(deleted)" for unlinked files.
2534 */ 2564 */
2535static int path_with_deleted(const struct path *path, struct path *root, 2565static int path_with_deleted(const struct path *path,
2536 char **buf, int *buflen) 2566 const struct path *root,
2567 char **buf, int *buflen)
2537{ 2568{
2538 prepend(buf, buflen, "\0", 1); 2569 prepend(buf, buflen, "\0", 1);
2539 if (d_unlinked(path->dentry)) { 2570 if (d_unlinked(path->dentry)) {
@@ -2570,7 +2601,6 @@ char *d_path(const struct path *path, char *buf, int buflen)
2570{ 2601{
2571 char *res = buf + buflen; 2602 char *res = buf + buflen;
2572 struct path root; 2603 struct path root;
2573 struct path tmp;
2574 int error; 2604 int error;
2575 2605
2576 /* 2606 /*
@@ -2585,9 +2615,8 @@ char *d_path(const struct path *path, char *buf, int buflen)
2585 2615
2586 get_fs_root(current->fs, &root); 2616 get_fs_root(current->fs, &root);
2587 write_seqlock(&rename_lock); 2617 write_seqlock(&rename_lock);
2588 tmp = root; 2618 error = path_with_deleted(path, &root, &res, &buflen);
2589 error = path_with_deleted(path, &tmp, &res, &buflen); 2619 if (error < 0)
2590 if (error)
2591 res = ERR_PTR(error); 2620 res = ERR_PTR(error);
2592 write_sequnlock(&rename_lock); 2621 write_sequnlock(&rename_lock);
2593 path_put(&root); 2622 path_put(&root);
@@ -2608,7 +2637,6 @@ char *d_path_with_unreachable(const struct path *path, char *buf, int buflen)
2608{ 2637{
2609 char *res = buf + buflen; 2638 char *res = buf + buflen;
2610 struct path root; 2639 struct path root;
2611 struct path tmp;
2612 int error; 2640 int error;
2613 2641
2614 if (path->dentry->d_op && path->dentry->d_op->d_dname) 2642 if (path->dentry->d_op && path->dentry->d_op->d_dname)
@@ -2616,9 +2644,8 @@ char *d_path_with_unreachable(const struct path *path, char *buf, int buflen)
2616 2644
2617 get_fs_root(current->fs, &root); 2645 get_fs_root(current->fs, &root);
2618 write_seqlock(&rename_lock); 2646 write_seqlock(&rename_lock);
2619 tmp = root; 2647 error = path_with_deleted(path, &root, &res, &buflen);
2620 error = path_with_deleted(path, &tmp, &res, &buflen); 2648 if (error > 0)
2621 if (!error && !path_equal(&tmp, &root))
2622 error = prepend_unreachable(&res, &buflen); 2649 error = prepend_unreachable(&res, &buflen);
2623 write_sequnlock(&rename_lock); 2650 write_sequnlock(&rename_lock);
2624 path_put(&root); 2651 path_put(&root);
@@ -2749,19 +2776,18 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
2749 write_seqlock(&rename_lock); 2776 write_seqlock(&rename_lock);
2750 if (!d_unlinked(pwd.dentry)) { 2777 if (!d_unlinked(pwd.dentry)) {
2751 unsigned long len; 2778 unsigned long len;
2752 struct path tmp = root;
2753 char *cwd = page + PAGE_SIZE; 2779 char *cwd = page + PAGE_SIZE;
2754 int buflen = PAGE_SIZE; 2780 int buflen = PAGE_SIZE;
2755 2781
2756 prepend(&cwd, &buflen, "\0", 1); 2782 prepend(&cwd, &buflen, "\0", 1);
2757 error = prepend_path(&pwd, &tmp, &cwd, &buflen); 2783 error = prepend_path(&pwd, &root, &cwd, &buflen);
2758 write_sequnlock(&rename_lock); 2784 write_sequnlock(&rename_lock);
2759 2785
2760 if (error) 2786 if (error < 0)
2761 goto out; 2787 goto out;
2762 2788
2763 /* Unreachable from current root */ 2789 /* Unreachable from current root */
2764 if (!path_equal(&tmp, &root)) { 2790 if (error > 0) {
2765 error = prepend_unreachable(&cwd, &buflen); 2791 error = prepend_unreachable(&cwd, &buflen);
2766 if (error) 2792 if (error)
2767 goto out; 2793 goto out;