summaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c89
1 files changed, 64 insertions, 25 deletions
diff --git a/fs/super.c b/fs/super.c
index 8576d79d0..81a3fafc2 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -10,13 +10,12 @@
* - umount system call
* - ustat system call
*
- * Added options to /proc/mounts
- * Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996.
- *
* GK 2/5/95 - Changed to support mounting the root fs via NFS
*
* Added kerneld support: Jacques Gelinas and Bjorn Ekwall
* Added change_root: Werner Almesberger & Hans Lermen, Feb '96
+ * Added options to /proc/mounts:
+ * Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996.
* Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998
* Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000
*/
@@ -428,6 +427,33 @@ static void remove_vfsmnt(struct vfsmount *mnt)
kfree(mnt);
}
+
+/* Use octal escapes, like mount does, for embedded spaces etc. */
+static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
+
+static int
+mangle(const unsigned char *s, char *buf, int len) {
+ char *sp;
+ int n;
+
+ sp = buf;
+ while(*s && sp-buf < len-3) {
+ for (n = 0; n < sizeof(need_escaping); n++) {
+ if (*s == need_escaping[n]) {
+ *sp++ = '\\';
+ *sp++ = '0' + ((*s & 0300) >> 6);
+ *sp++ = '0' + ((*s & 070) >> 3);
+ *sp++ = '0' + (*s & 07);
+ goto next;
+ }
+ }
+ *sp++ = *s;
+ next:
+ s++;
+ }
+ return sp - buf; /* no trailing NUL */
+}
+
static struct proc_fs_info {
int flag;
char *str;
@@ -466,27 +492,32 @@ int get_filesystem_info( char *buf )
struct proc_fs_info *fs_infop;
struct proc_nfs_info *nfs_infop;
struct nfs_server *nfss;
- int len = 0;
- char *path,*buffer = (char *) __get_free_page(GFP_KERNEL);
+ int len, prevlen;
+ char *path, *buffer = (char *) __get_free_page(GFP_KERNEL);
if (!buffer) return 0;
- for (p = vfsmntlist.next; p!=&vfsmntlist && len < PAGE_SIZE - 160;
- p = p->next) {
+ len = prevlen = 0;
+
+#define FREEROOM ((int)PAGE_SIZE-200-len)
+#define MANGLE(s) len += mangle((s), buf+len, FREEROOM);
+
+ for (p = vfsmntlist.next; p != &vfsmntlist; p = p->next) {
struct vfsmount *tmp = list_entry(p, struct vfsmount, mnt_list);
if (!(tmp->mnt_flags & MNT_VISIBLE))
continue;
path = d_path(tmp->mnt_root, tmp, buffer, PAGE_SIZE);
if (!path)
continue;
- len += sprintf( buf + len, "%s %s %s %s",
- tmp->mnt_devname ? tmp->mnt_devname : "none", path,
- tmp->mnt_sb->s_type->name,
- tmp->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw" );
+ MANGLE(tmp->mnt_devname ? tmp->mnt_devname : "none");
+ buf[len++] = ' ';
+ MANGLE(path);
+ buf[len++] = ' ';
+ MANGLE(tmp->mnt_sb->s_type->name);
+ len += sprintf(buf+len, " %s",
+ tmp->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw");
for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
- if (tmp->mnt_sb->s_flags & fs_infop->flag) {
- strcpy(buf + len, fs_infop->str);
- len += strlen(fs_infop->str);
- }
+ if (tmp->mnt_sb->s_flags & fs_infop->flag)
+ MANGLE(fs_infop->str);
}
if (!strcmp("nfs", tmp->mnt_sb->s_type->name)) {
nfss = &tmp->mnt_sb->u.nfs_sb.s_server;
@@ -527,17 +558,24 @@ int get_filesystem_info( char *buf )
str = nfs_infop->str;
else
str = nfs_infop->nostr;
- strcpy(buf + len, str);
- len += strlen(str);
+ MANGLE(str);
}
- len += sprintf(buf+len, ",addr=%s",
- nfss->hostname);
+ len += sprintf(buf+len, ",addr=");
+ MANGLE(nfss->hostname);
+ }
+ len += sprintf(buf + len, " 0 0\n");
+ if (FREEROOM <= 3) {
+ len = prevlen;
+ len += sprintf(buf+len, "# truncated\n");
+ break;
}
- len += sprintf( buf + len, " 0 0\n" );
+ prevlen = len;
}
free_page((unsigned long) buffer);
return len;
+#undef MANGLE
+#undef FREEROOM
}
/**
@@ -775,7 +813,8 @@ static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
dev = to_kdev_t(bdev->bd_dev);
sb = get_super(dev);
if (sb) {
- if (fs_type == sb->s_type) {
+ if (fs_type == sb->s_type &&
+ ((flags ^ sb->s_flags) & MS_RDONLY) == 0) {
path_release(&nd);
return sb;
}
@@ -1090,7 +1129,7 @@ asmlinkage long sys_umount(char * name, int flags)
if (retval)
goto out;
retval = -EINVAL;
- if (nd.dentry!=nd.mnt->mnt_root)
+ if (nd.dentry != nd.mnt->mnt_root)
goto dput_and_out;
retval = -EPERM;
@@ -1263,8 +1302,8 @@ static int copy_mount_options (const void *data, unsigned long *where)
* PAGE_SIZE-1 bytes, which can contain arbitrary fs-dependent
* information (or be NULL).
*
- * NOTE! As old versions of mount() didn't use this setup, the flags
- * have to have a special 16-bit magic number in the high word:
+ * NOTE! As pre-0.97 versions of mount() didn't use this setup, the
+ * flags have to have a special 16-bit magic number in the high word:
* 0xC0ED. If this magic word isn't present, the flags and data info
* aren't used, as the syscall assumes we are talking to an older
* version that didn't understand them.
@@ -1736,7 +1775,7 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
printk("okay\n");
return 0;
}
- printk(KERN_ERR "error %d\n",blivet);
+ printk(KERN_ERR "error %d\n", blivet);
return error;
}
/* FIXME: we should hold i_zombie on nd.dentry */