diff options
| -rw-r--r-- | fs/nfs/internal.h | 5 | ||||
| -rw-r--r-- | fs/nfs/namespace.c | 19 | ||||
| -rw-r--r-- | fs/nfs/nfs4namespace.c | 3 | ||||
| -rw-r--r-- | fs/nfs/super.c | 2 |
4 files changed, 20 insertions, 9 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 59b133c5d652..a54fe51c1dfb 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -353,8 +353,9 @@ extern void nfs_sb_active(struct super_block *sb); | |||
| 353 | extern void nfs_sb_deactive(struct super_block *sb); | 353 | extern void nfs_sb_deactive(struct super_block *sb); |
| 354 | 354 | ||
| 355 | /* namespace.c */ | 355 | /* namespace.c */ |
| 356 | #define NFS_PATH_CANONICAL 1 | ||
| 356 | extern char *nfs_path(char **p, struct dentry *dentry, | 357 | extern char *nfs_path(char **p, struct dentry *dentry, |
| 357 | char *buffer, ssize_t buflen); | 358 | char *buffer, ssize_t buflen, unsigned flags); |
| 358 | extern struct vfsmount *nfs_d_automount(struct path *path); | 359 | extern struct vfsmount *nfs_d_automount(struct path *path); |
| 359 | struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *, | 360 | struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *, |
| 360 | struct nfs_fh *, struct nfs_fattr *); | 361 | struct nfs_fh *, struct nfs_fattr *); |
| @@ -498,7 +499,7 @@ static inline char *nfs_devname(struct dentry *dentry, | |||
| 498 | char *buffer, ssize_t buflen) | 499 | char *buffer, ssize_t buflen) |
| 499 | { | 500 | { |
| 500 | char *dummy; | 501 | char *dummy; |
| 501 | return nfs_path(&dummy, dentry, buffer, buflen); | 502 | return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL); |
| 502 | } | 503 | } |
| 503 | 504 | ||
| 504 | /* | 505 | /* |
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 655925373b91..dd057bc6b65b 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
| @@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; | |||
| 33 | * @dentry - pointer to dentry | 33 | * @dentry - pointer to dentry |
| 34 | * @buffer - result buffer | 34 | * @buffer - result buffer |
| 35 | * @buflen - length of buffer | 35 | * @buflen - length of buffer |
| 36 | * @flags - options (see below) | ||
| 36 | * | 37 | * |
| 37 | * Helper function for constructing the server pathname | 38 | * Helper function for constructing the server pathname |
| 38 | * by arbitrary hashed dentry. | 39 | * by arbitrary hashed dentry. |
| @@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; | |||
| 40 | * This is mainly for use in figuring out the path on the | 41 | * This is mainly for use in figuring out the path on the |
| 41 | * server side when automounting on top of an existing partition | 42 | * server side when automounting on top of an existing partition |
| 42 | * and in generating /proc/mounts and friends. | 43 | * and in generating /proc/mounts and friends. |
| 44 | * | ||
| 45 | * Supported flags: | ||
| 46 | * NFS_PATH_CANONICAL: ensure there is exactly one slash after | ||
| 47 | * the original device (export) name | ||
| 48 | * (if unset, the original name is returned verbatim) | ||
| 43 | */ | 49 | */ |
| 44 | char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) | 50 | char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen, |
| 51 | unsigned flags) | ||
| 45 | { | 52 | { |
| 46 | char *end; | 53 | char *end; |
| 47 | int namelen; | 54 | int namelen; |
| @@ -74,7 +81,7 @@ rename_retry: | |||
| 74 | rcu_read_unlock(); | 81 | rcu_read_unlock(); |
| 75 | goto rename_retry; | 82 | goto rename_retry; |
| 76 | } | 83 | } |
| 77 | if (*end != '/') { | 84 | if ((flags & NFS_PATH_CANONICAL) && *end != '/') { |
| 78 | if (--buflen < 0) { | 85 | if (--buflen < 0) { |
| 79 | spin_unlock(&dentry->d_lock); | 86 | spin_unlock(&dentry->d_lock); |
| 80 | rcu_read_unlock(); | 87 | rcu_read_unlock(); |
| @@ -91,9 +98,11 @@ rename_retry: | |||
| 91 | return end; | 98 | return end; |
| 92 | } | 99 | } |
| 93 | namelen = strlen(base); | 100 | namelen = strlen(base); |
| 94 | /* Strip off excess slashes in base string */ | 101 | if (flags & NFS_PATH_CANONICAL) { |
| 95 | while (namelen > 0 && base[namelen - 1] == '/') | 102 | /* Strip off excess slashes in base string */ |
| 96 | namelen--; | 103 | while (namelen > 0 && base[namelen - 1] == '/') |
| 104 | namelen--; | ||
| 105 | } | ||
| 97 | buflen -= namelen; | 106 | buflen -= namelen; |
| 98 | if (buflen < 0) { | 107 | if (buflen < 0) { |
| 99 | spin_unlock(&dentry->d_lock); | 108 | spin_unlock(&dentry->d_lock); |
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 79fbb61ce202..1e09eb78543b 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
| @@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end) | |||
| 81 | static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) | 81 | static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) |
| 82 | { | 82 | { |
| 83 | char *limit; | 83 | char *limit; |
| 84 | char *path = nfs_path(&limit, dentry, buffer, buflen); | 84 | char *path = nfs_path(&limit, dentry, buffer, buflen, |
| 85 | NFS_PATH_CANONICAL); | ||
| 85 | if (!IS_ERR(path)) { | 86 | if (!IS_ERR(path)) { |
| 86 | char *path_component = nfs_path_component(path, limit); | 87 | char *path_component = nfs_path_component(path, limit); |
| 87 | if (path_component) | 88 | if (path_component) |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index e831bce49766..13c2a5be4765 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -771,7 +771,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root) | |||
| 771 | int err = 0; | 771 | int err = 0; |
| 772 | if (!page) | 772 | if (!page) |
| 773 | return -ENOMEM; | 773 | return -ENOMEM; |
| 774 | devname = nfs_path(&dummy, root, page, PAGE_SIZE); | 774 | devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0); |
| 775 | if (IS_ERR(devname)) | 775 | if (IS_ERR(devname)) |
| 776 | err = PTR_ERR(devname); | 776 | err = PTR_ERR(devname); |
| 777 | else | 777 | else |
