]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
nfs: Show original device name verbatim in /proc/*/mount{s,info}
authorBen Hutchings <ben@decadent.org.uk>
Sun, 21 Oct 2012 18:23:52 +0000 (19:23 +0100)
committerBen Hutchings <ben@decadent.org.uk>
Fri, 16 Nov 2012 16:47:05 +0000 (16:47 +0000)
commit 97a54868262da1629a3e65121e65b8e8c4419d9f upstream.

Since commit c7f404b ('vfs: new superblock methods to override
/proc/*/mount{s,info}'), nfs_path() is used to generate the mounted
device name reported back to userland.

nfs_path() always generates a trailing slash when the given dentry is
the root of an NFS mount, but userland may expect the original device
name to be returned verbatim (as it used to be).  Make this
canonicalisation optional and change the callers accordingly.

[jrnieder@gmail.com: use flag instead of bool argument]
Reported-and-tested-by: Chris Hiestand <chiestand@salk.edu>
Reference: http://bugs.debian.org/669314
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
[bwh: Backported to 3.2:
 - Adjust context
 - nfs_show_devname() still takes a pointer to struct vfsmount]

fs/nfs/internal.h
fs/nfs/namespace.c
fs/nfs/nfs4namespace.c
fs/nfs/super.c

index 68b3f2041a115a93d249e232b594b002c5e8d03a..c5af878109ec900614ddd668edeaacfc4f755569 100644 (file)
@@ -274,8 +274,9 @@ extern void nfs_sb_active(struct super_block *sb);
 extern void nfs_sb_deactive(struct super_block *sb);
 
 /* namespace.c */
+#define NFS_PATH_CANONICAL 1
 extern char *nfs_path(char **p, struct dentry *dentry,
-                     char *buffer, ssize_t buflen);
+                     char *buffer, ssize_t buflen, unsigned flags);
 extern struct vfsmount *nfs_d_automount(struct path *path);
 #ifdef CONFIG_NFS_V4
 rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);
@@ -364,7 +365,7 @@ static inline char *nfs_devname(struct dentry *dentry,
                                char *buffer, ssize_t buflen)
 {
        char *dummy;
-       return nfs_path(&dummy, dentry, buffer, buflen);
+       return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL);
 }
 
 /*
index 8102391bb3744077ae778af2d5bdb5d135ed3fbf..a86873e721390b2b7f2eb8c02c5df72226d1624a 100644 (file)
@@ -37,6 +37,7 @@ static struct vfsmount *nfs_do_submount(struct dentry *dentry,
  * @dentry - pointer to dentry
  * @buffer - result buffer
  * @buflen - length of buffer
+ * @flags - options (see below)
  *
  * Helper function for constructing the server pathname
  * by arbitrary hashed dentry.
@@ -44,8 +45,14 @@ static struct vfsmount *nfs_do_submount(struct dentry *dentry,
  * This is mainly for use in figuring out the path on the
  * server side when automounting on top of an existing partition
  * and in generating /proc/mounts and friends.
+ *
+ * Supported flags:
+ * NFS_PATH_CANONICAL: ensure there is exactly one slash after
+ *                    the original device (export) name
+ *                    (if unset, the original name is returned verbatim)
  */
-char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen)
+char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen,
+              unsigned flags)
 {
        char *end;
        int namelen;
@@ -78,7 +85,7 @@ rename_retry:
                rcu_read_unlock();
                goto rename_retry;
        }
-       if (*end != '/') {
+       if ((flags & NFS_PATH_CANONICAL) && *end != '/') {
                if (--buflen < 0) {
                        spin_unlock(&dentry->d_lock);
                        rcu_read_unlock();
@@ -95,9 +102,11 @@ rename_retry:
                return end;
        }
        namelen = strlen(base);
-       /* Strip off excess slashes in base string */
-       while (namelen > 0 && base[namelen - 1] == '/')
-               namelen--;
+       if (flags & NFS_PATH_CANONICAL) {
+               /* Strip off excess slashes in base string */
+               while (namelen > 0 && base[namelen - 1] == '/')
+                       namelen--;
+       }
        buflen -= namelen;
        if (buflen < 0) {
                spin_unlock(&dentry->d_lock);
index bb80c49b6533b44aab58171dcd69397ff02f39a2..96f2b67aac30a8059a90afaaeb9280562750ba70 100644 (file)
@@ -57,7 +57,8 @@ Elong:
 static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
 {
        char *limit;
-       char *path = nfs_path(&limit, dentry, buffer, buflen);
+       char *path = nfs_path(&limit, dentry, buffer, buflen,
+                             NFS_PATH_CANONICAL);
        if (!IS_ERR(path)) {
                char *colon = strchr(path, ':');
                if (colon && colon < limit)
index e42d6f65d6e29b3d77fc6289469b954c3e82eae0..81503449f78d8c7418543483342817ee28d55f5a 100644 (file)
@@ -768,7 +768,7 @@ static int nfs_show_devname(struct seq_file *m, struct vfsmount *mnt)
        int err = 0;
        if (!page)
                return -ENOMEM;
-       devname = nfs_path(&dummy, mnt->mnt_root, page, PAGE_SIZE);
+       devname = nfs_path(&dummy, mnt->mnt_root, page, PAGE_SIZE, 0);
        if (IS_ERR(devname))
                err = PTR_ERR(devname);
        else