summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/buffer.c9
-rw-r--r--fs/devfs/base.c16
-rw-r--r--fs/devices.c89
-rw-r--r--fs/dquot.c2
-rw-r--r--fs/ext2/inode.c5
-rw-r--r--fs/fcntl.c69
-rw-r--r--fs/nfsd/auth.c7
-rw-r--r--fs/nfsd/nfsctl.c4
-rw-r--r--fs/nfsd/vfs.c33
-rw-r--r--fs/partitions/check.c1
-rw-r--r--fs/proc/proc_misc.c23
-rw-r--r--fs/select.c2
-rw-r--r--fs/super.c27
-rw-r--r--fs/vfat/namei.c7
14 files changed, 163 insertions, 131 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index 20790847f..8b5d19bda 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -708,11 +708,11 @@ static void refill_freelist(int size)
}
}
-void init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *dev_id)
+void init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private)
{
bh->b_list = BUF_CLEAN;
bh->b_end_io = handler;
- bh->b_dev_id = dev_id;
+ bh->b_private = private;
}
static void end_buffer_io_sync(struct buffer_head *bh, int uptodate)
@@ -1742,7 +1742,7 @@ static void end_buffer_io_kiobuf(struct buffer_head *bh, int uptodate)
mark_buffer_uptodate(bh, uptodate);
- kiobuf = bh->b_kiobuf;
+ kiobuf = bh->b_private;
unlock_buffer(bh);
end_kio_request(kiobuf, uptodate);
}
@@ -1862,11 +1862,10 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
set_bh_page(tmp, map, offset);
tmp->b_this_page = tmp;
- init_buffer(tmp, end_buffer_io_kiobuf, NULL);
+ init_buffer(tmp, end_buffer_io_kiobuf, iobuf);
tmp->b_dev = dev;
tmp->b_blocknr = blocknr;
tmp->b_state = 1 << BH_Mapped;
- tmp->b_kiobuf = iobuf;
if (rw == WRITE) {
set_bit(BH_Uptodate, &tmp->b_state);
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 38a773d72..ad28db63a 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -1246,8 +1246,7 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
}
if (ops == NULL)
{
- if ( S_ISCHR (mode) ) ops = get_chrfops (major, 0);
- else if ( S_ISBLK (mode) ) ops = (void *) get_blkfops (major);
+ if ( S_ISBLK (mode) ) ops = (void *) get_blkfops (major);
if (ops == NULL)
{
printk ("%s: devfs_register(%s): NULL ops pointer\n",
@@ -2506,6 +2505,19 @@ static int devfs_open (struct inode *inode, struct file *file)
else
{
/* Fallback to legacy scheme */
+ /*
+ * Do we need it? Richard, could you verify it?
+ * It can legitimately happen if
+ * it is a character device and
+ * df->ops == NULL and
+ * de->registered is true,
+ * but AFAICS it can't happen - in devfs_register() we never set
+ * ->ops to NULL, in unregister() we set ->registered to false,
+ * in devfs_mknod() we set it to NULL only if ->register is false.
+ *
+ * Looks like this fallback is not needed at all.
+ * AV
+ */
if ( S_ISCHR (inode->i_mode) ) err = chrdev_open (inode, file);
else err = -ENODEV;
}
diff --git a/fs/devices.c b/fs/devices.c
index 3023747da..dd7db7730 100644
--- a/fs/devices.c
+++ b/fs/devices.c
@@ -35,6 +35,7 @@ struct device_struct {
struct file_operations * fops;
};
+static rwlock_t chrdevs_lock = RW_LOCK_UNLOCKED;
static struct device_struct chrdevs[MAX_CHRDEV] = {
{ NULL, NULL },
};
@@ -47,11 +48,13 @@ int get_device_list(char * page)
int len;
len = sprintf(page, "Character devices:\n");
+ read_lock(&chrdevs_lock);
for (i = 0; i < MAX_CHRDEV ; i++) {
if (chrdevs[i].fops) {
len += sprintf(page+len, "%3d %s\n", i, chrdevs[i].name);
}
}
+ read_unlock(&chrdevs_lock);
len += get_blkdev_list(page+len);
return len;
}
@@ -59,68 +62,66 @@ int get_device_list(char * page)
/*
Return the function table of a device.
Load the driver if needed.
+ Increment the reference count of module in question.
*/
-static struct file_operations * get_fops(
- unsigned int major,
- unsigned int minor,
- unsigned int maxdev,
- const char *mangle, /* String to use to build the module name */
- struct device_struct tb[])
+static struct file_operations * get_chrfops(unsigned int major, unsigned int minor)
{
struct file_operations *ret = NULL;
- if (major < maxdev){
+ if (!major || major >= MAX_CHRDEV)
+ return NULL;
+
+ read_lock(&chrdevs_lock);
+ ret = fops_get(chrdevs[major].fops);
+ read_unlock(&chrdevs_lock);
#ifdef CONFIG_KMOD
- /*
- * I do get request for device 0. I have no idea why. It happen
- * at shutdown time for one. Without the following test, the
- * kernel will happily trigger a request_module() which will
- * trigger kmod and modprobe for nothing (since there
- * is no device with major number == 0. And furthermore
- * it locks the reboot process :-(
- *
- * Jacques Gelinas (jacques@solucorp.qc.ca)
- *
- * A. Haritsis <ah@doc.ic.ac.uk>: fix for serial module
- * though we need the minor here to check if serial dev,
- * we pass only the normal major char dev to kmod
- * as there is no other loadable dev on these majors
- */
- if ((isa_tty_dev(major) && need_serial(major,minor)) ||
- (major != 0 && !tb[major].fops)) {
- char name[20];
- sprintf(name, mangle, major);
- request_module(name);
+ if (ret && isa_tty_dev(major)) {
+ lock_kernel();
+ if (need_serial(major,minor)) {
+ /* Force request_module anyway, but what for? */
+ fops_put(ret);
+ ret = NULL;
}
-#endif
- ret = tb[major].fops;
+ unlock_kernel();
}
- return ret;
-}
+ if (!ret) {
+ char name[20];
+ sprintf(name, "char-major-%d", major);
+ request_module(name);
+ }
+ read_lock(&chrdevs_lock);
+ ret = fops_get(chrdevs[major].fops);
+ read_unlock(&chrdevs_lock);
-struct file_operations * get_chrfops(unsigned int major, unsigned int minor)
-{
- return get_fops (major,minor,MAX_CHRDEV,"char-major-%d",chrdevs);
+#endif
+ return ret;
}
int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
{
if (major == 0) {
+ write_lock(&chrdevs_lock);
for (major = MAX_CHRDEV-1; major > 0; major--) {
if (chrdevs[major].fops == NULL) {
chrdevs[major].name = name;
chrdevs[major].fops = fops;
+ write_unlock(&chrdevs_lock);
return major;
}
}
+ write_unlock(&chrdevs_lock);
return -EBUSY;
}
if (major >= MAX_CHRDEV)
return -EINVAL;
- if (chrdevs[major].fops && chrdevs[major].fops != fops)
+ write_lock(&chrdevs_lock);
+ if (chrdevs[major].fops && chrdevs[major].fops != fops) {
+ write_unlock(&chrdevs_lock);
return -EBUSY;
+ }
chrdevs[major].name = name;
chrdevs[major].fops = fops;
+ write_unlock(&chrdevs_lock);
return 0;
}
@@ -128,12 +129,14 @@ int unregister_chrdev(unsigned int major, const char * name)
{
if (major >= MAX_CHRDEV)
return -EINVAL;
- if (!chrdevs[major].fops)
- return -EINVAL;
- if (strcmp(chrdevs[major].name, name))
+ write_lock(&chrdevs_lock);
+ if (!chrdevs[major].fops || strcmp(chrdevs[major].name, name)) {
+ write_unlock(&chrdevs_lock);
return -EINVAL;
+ }
chrdevs[major].name = NULL;
chrdevs[major].fops = NULL;
+ write_unlock(&chrdevs_lock);
return 0;
}
@@ -144,15 +147,15 @@ int chrdev_open(struct inode * inode, struct file * filp)
{
int ret = -ENODEV;
- lock_kernel();
- filp->f_op = fops_get(get_chrfops(MAJOR(inode->i_rdev),
- MINOR(inode->i_rdev)));
+ filp->f_op = get_chrfops(MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
if (filp->f_op) {
ret = 0;
- if (filp->f_op->open != NULL)
+ if (filp->f_op->open != NULL) {
+ lock_kernel();
ret = filp->f_op->open(inode,filp);
+ unlock_kernel();
+ }
}
- unlock_kernel();
return ret;
}
diff --git a/fs/dquot.c b/fs/dquot.c
index 022dd3423..42d91c35f 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -732,7 +732,7 @@ put_it:
/* Free list of dquots - called from inode.c */
void put_dquot_list(struct list_head *tofree_head)
{
- struct list_head *act_head = tofree_head;
+ struct list_head *act_head = tofree_head.next;
struct dquot *dquot;
/* So now we have dquots on the list... Just free them */
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 5792d7b95..70e806b02 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -259,10 +259,9 @@ repeat:
ext2_debug ("goal = %d.\n", goal);
tmp = ext2_alloc_block (inode, goal, err);
- if (!tmp) {
- *err = -ENOSPC;
+ if (!tmp)
return NULL;
- }
+
if (metadata) {
result = getblk (inode->i_dev, tmp, blocksize);
if (!buffer_uptodate(result))
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 37e32a012..659821873 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -15,45 +15,80 @@
extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
+/* Expand files. Return <0 on error; 0 nothing done; 1 files expanded,
+ * we may have blocked.
+ *
+ * Should be called with the files->file_lock spinlock held for write.
+ */
+static int expand_files(struct files_struct *files, int nr)
+{
+ int err, expand = 0;
+#ifdef FDSET_DEBUG
+ printk (KERN_ERR __FUNCTION__ " %d: nr = %d\n", current->pid, nr);
+#endif
+
+ if (nr >= files->max_fdset) {
+ expand = 1;
+ if ((err = expand_fdset(files, nr)))
+ goto out;
+ }
+ if (nr >= files->max_fds) {
+ expand = 1;
+ if ((err = expand_fd_array(files, nr)))
+ goto out;
+ }
+ err = expand;
+ out:
+#ifdef FDSET_DEBUG
+ if (err)
+ printk (KERN_ERR __FUNCTION__ " %d: return %d\n", current->pid, err);
+#endif
+ return err;
+}
+
/*
* locate_fd finds a free file descriptor in the open_fds fdset,
* expanding the fd arrays if necessary. The files write lock will be
* held on exit to ensure that the fd can be entered atomically.
*/
-static inline int locate_fd(struct files_struct *files,
- struct file *file, int start)
+static int locate_fd(struct files_struct *files,
+ struct file *file, int orig_start)
{
unsigned int newfd;
int error;
+ int start;
write_lock(&files->file_lock);
repeat:
- error = -EMFILE;
+ /*
+ * Someone might have closed fd's in the range
+ * orig_start..files->next_fd
+ */
+ start = orig_start;
if (start < files->next_fd)
start = files->next_fd;
- if (start >= files->max_fdset) {
- expand:
- error = expand_files(files, start);
- if (error < 0)
- goto out;
- goto repeat;
+
+ newfd = start;
+ if (start < files->max_fdset) {
+ newfd = find_next_zero_bit(files->open_fds->fds_bits,
+ files->max_fdset, start);
}
- newfd = find_next_zero_bit(files->open_fds->fds_bits,
- files->max_fdset, start);
-
error = -EMFILE;
if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
goto out;
- if (newfd >= files->max_fdset)
- goto expand;
error = expand_files(files, newfd);
if (error < 0)
goto out;
- if (error) /* If we might have blocked, try again. */
+
+ /*
+ * If we needed to expand the fs array we
+ * might have blocked - try again.
+ */
+ if (error)
goto repeat;
if (start <= files->next_fd)
@@ -104,8 +139,8 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
if (newfd == oldfd)
goto out_unlock;
err = -EBADF;
- if (newfd >= NR_OPEN)
- goto out_unlock; /* following POSIX.1 6.2.1 */
+ if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
+ goto out_unlock;
get_file(file); /* We are now finished with oldfd */
err = expand_files(files, newfd);
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 74f174d63..12fa97fe1 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -10,6 +10,7 @@
#include <linux/sunrpc/svcauth.h>
#include <linux/nfsd/nfsd.h>
+#define CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
void
nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
{
@@ -50,10 +51,10 @@ nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
current->ngroups = i;
if ((cred->cr_uid)) {
- cap_t(current->cap_effective) &= ~CAP_FS_MASK;
+ cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
} else {
- cap_t(current->cap_effective) |= (CAP_FS_MASK &
- current->cap_permitted);
+ cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
+ current->cap_permitted);
}
rqstp->rq_userset = 1;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index d3bb67b53..20e82fa7a 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -331,10 +331,6 @@ init_module(void)
void
cleanup_module(void)
{
- if (MOD_IN_USE) {
- printk("nfsd: nfsd busy, remove delayed\n");
- return;
- }
do_nfsservctl = NULL;
nfsd_export_shutdown();
nfsd_cache_shutdown();
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 2cdec3ec8..20fa7fafe 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -196,7 +196,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
int ftype = 0;
int imode;
int err;
- kernel_cap_t saved_cap = 0;
int size_change = 0;
if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
@@ -283,10 +282,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
iap->ia_valid |= ATTR_CTIME;
- if (current->fsuid != 0) {
- saved_cap = current->cap_effective;
- cap_clear(current->cap_effective);
- }
#ifdef CONFIG_QUOTA
/* DQUOT_TRANSFER needs both ia_uid and ia_gid defined */
if (iap->ia_valid & (ATTR_UID|ATTR_GID)) {
@@ -312,8 +307,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
fh_unlock(fhp);
put_write_access(inode);
}
- if (current->fsuid != 0)
- current->cap_effective = saved_cap;
if (err)
goto out_nfserr;
if (EX_ISSYNC(fhp->fh_export))
@@ -640,9 +633,6 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
mm_segment_t oldfs;
int err = 0;
int stable = *stablep;
-#ifdef CONFIG_QUOTA
- uid_t saved_euid;
-#endif
err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file);
if (err)
@@ -680,15 +670,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
/* Write the data. */
oldfs = get_fs(); set_fs(KERNEL_DS);
-#ifdef CONFIG_QUOTA
- /* This is for disk quota. */
- saved_euid = current->euid;
- current->euid = current->fsuid;
- err = file.f_op->write(&file, buf, cnt, &file.f_pos);
- current->euid = saved_euid;
-#else
err = file.f_op->write(&file, buf, cnt, &file.f_pos);
-#endif
if (err >= 0)
nfsdstats.io_write += cnt;
set_fs(oldfs);
@@ -696,17 +678,10 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
/* clear setuid/setgid flag after write */
if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) {
struct iattr ia;
- kernel_cap_t saved_cap = 0;
ia.ia_valid = ATTR_MODE;
ia.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
- if (current->fsuid != 0) {
- saved_cap = current->cap_effective;
- cap_clear(current->cap_effective);
- }
notify_change(dentry, &ia);
- if (current->fsuid != 0)
- current->cap_effective = saved_cap;
}
if (err >= 0 && stable) {
@@ -1463,7 +1438,6 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
{
struct inode *inode = dentry->d_inode;
int err;
- kernel_cap_t saved_cap = 0;
if (acc == MAY_NOP)
return 0;
@@ -1522,10 +1496,6 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
inode->i_uid == current->fsuid)
return 0;
- if (current->fsuid != 0) {
- saved_cap = current->cap_effective;
- cap_clear(current->cap_effective);
- }
err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC));
@@ -1533,9 +1503,6 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
if (err == -EACCES && S_ISREG(inode->i_mode) && acc == MAY_READ)
err = permission(inode, MAY_EXEC);
- if (current->fsuid != 0)
- current->cap_effective = saved_cap;
-
return err? nfserrno(err) : 0;
}
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index a72e2ccbc..29b93e5a5 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -34,7 +34,6 @@
#include "ultrix.h"
extern void device_init(void);
-extern void md_run_setup(void);
extern int *blk_size[];
extern void rd_load(void);
extern void initrd_load(void);
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 9f574e278..d7aabc334 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -287,18 +287,21 @@ static int kstat_read_proc(char *page, char **start, off_t off,
int i, len;
extern unsigned long total_forks;
unsigned long jif = hz_to_std(jiffies);
- unsigned sum = 0;
+ unsigned int sum = 0, user = 0, nice = 0, system = 0;
int major, disk;
- for (i = 0 ; i < NR_IRQS ; i++)
- sum += kstat_irqs(i);
-
- len = sprintf(page,
- "cpu %u %u %u %lu\n",
- hz_to_std(kstat.cpu_user),
- hz_to_std(kstat.cpu_nice),
- hz_to_std(kstat.cpu_system),
- jif*smp_num_cpus - hz_to_std(kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system));
+ for (i = 0 ; i < smp_num_cpus; i++) {
+ int cpu = cpu_logical_map(i), j;
+
+ user += hz_to_std(kstat.per_cpu_user[cpu]);
+ nice += hz_to_std(kstat.per_cpu_nice[cpu]);
+ system += hz_to_std(kstat.per_cpu_system[cpu]);
+ for (j = 0 ; j < NR_IRQS ; j++)
+ sum += kstat.irqs[cpu][j];
+ }
+
+ len = sprintf(page, "cpu %u %u %u %lu\n", user, nice, system,
+ jif * smp_num_cpus - (user + nice + system));
for (i = 0 ; i < smp_num_cpus; i++)
len += sprintf(page + len, "cpu%d %u %u %u %lu\n",
i,
diff --git a/fs/select.c b/fs/select.c
index 0b3718309..a49213ecb 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -37,7 +37,7 @@ struct poll_table_page {
};
#define POLL_TABLE_FULL(table) \
- ((unsigned long)(table->entry+1) > PAGE_SIZE + (unsigned long)(table))
+ ((unsigned long)((table)->entry+1) > PAGE_SIZE + (unsigned long)(table))
/*
* Ok, Peter made a complicated, but straightforward multiple_wait() function.
diff --git a/fs/super.c b/fs/super.c
index 3303789f6..91e17f2b6 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -285,7 +285,7 @@ static LIST_HEAD(vfsmntlist);
* add_vfsmnt - add a new mount node
* @nd: location of mountpoint or %NULL if we want a root node
* @root: root of (sub)tree to be mounted
- * @dev_name: device name to show in /proc/mounts
+ * @dev_name: device name to show in /proc/mounts or %NULL (for "none").
*
* This is VFS idea of mount. New node is allocated, bound to a tree
* we are mounting and optionally (OK, usually) registered as mounted
@@ -295,6 +295,13 @@ static LIST_HEAD(vfsmntlist);
* Potential reason for failure (aside of trivial lack of memory) is a
* deleted mountpoint. Caller must hold ->i_zombie on mountpoint
* dentry (if any).
+ *
+ * Node is marked as MNT_VISIBLE (visible in /proc/mounts) unless both
+ * @nd and @devname are %NULL. It works since we pass non-%NULL @devname
+ * when we are mounting root and kern_mount() filesystems are deviceless.
+ * If we will get a kern_mount() filesystem with nontrivial @devname we
+ * will have to pass the visibility flag explicitly, so if we will add
+ * support for such beasts we'll have to change prototype.
*/
static struct vfsmount *add_vfsmnt(struct nameidata *nd,
@@ -310,6 +317,9 @@ static struct vfsmount *add_vfsmnt(struct nameidata *nd,
goto out;
memset(mnt, 0, sizeof(struct vfsmount));
+ if (nd || dev_name)
+ mnt->mnt_flags = MNT_VISIBLE;
+
/* It may be NULL, but who cares? */
if (dev_name) {
name = kmalloc(strlen(dev_name)+1, GFP_KERNEL);
@@ -344,7 +354,8 @@ out:
return mnt;
fail:
spin_unlock(&dcache_lock);
- kfree(mnt->mnt_devname);
+ if (mnt->mnt_devname)
+ kfree(mnt->mnt_devname);
kfree(mnt);
return NULL;
}
@@ -370,7 +381,8 @@ static void move_vfsmnt(struct vfsmount *mnt,
/* flip names */
if (new_devname) {
- kfree(mnt->mnt_devname);
+ if (mnt->mnt_devname)
+ kfree(mnt->mnt_devname);
mnt->mnt_devname = new_devname;
}
@@ -411,7 +423,8 @@ static void remove_vfsmnt(struct vfsmount *mnt)
dput(mnt->mnt_mountpoint);
dput(mnt->mnt_root);
- kfree(mnt->mnt_devname);
+ if (mnt->mnt_devname)
+ kfree(mnt->mnt_devname);
kfree(mnt);
}
@@ -460,11 +473,13 @@ int get_filesystem_info( char *buf )
for (p = vfsmntlist.next; p!=&vfsmntlist && len < PAGE_SIZE - 160;
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, path,
+ tmp->mnt_devname ? tmp->mnt_devname : "none", path,
tmp->mnt_sb->s_type->name,
tmp->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw" );
for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
@@ -922,7 +937,7 @@ struct vfsmount *kern_mount(struct file_system_type *type)
put_unnamed_dev(dev);
return ERR_PTR(-EINVAL);
}
- mnt = add_vfsmnt(NULL, sb->s_root, "none");
+ mnt = add_vfsmnt(NULL, sb->s_root, NULL);
if (!mnt) {
kill_super(sb, 0);
return ERR_PTR(-ENOMEM);
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 9c38896a3..3895b0774 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -453,10 +453,11 @@ static int vfat_valid_shortname(struct nls_table *nls, wchar_t *name, int len)
if (charbuf[chi] != vfat_tolower(nls, c)) return -EINVAL;
if (strchr(replace_chars,c)) return -EINVAL;
if (c < ' '|| c==':') return -EINVAL;
- if (c == '.') break;
+ if (c == '.') goto dot;
space = c == ' ';
}
}
+dot:;
if (space) return -EINVAL;
if (len && c != '.') {
len--;
@@ -464,6 +465,7 @@ static int vfat_valid_shortname(struct nls_table *nls, wchar_t *name, int len)
if (charbuf[0] != '.') return -EINVAL;
} else
return -EINVAL;
+ c = '.';
}
if (c == '.') {
if (len >= 4) return -EINVAL;
@@ -522,7 +524,7 @@ static int vfat_format_name(struct nls_table *nls, wchar_t *name,
if (chl == 0)
return -EINVAL;
for (chi = 0; chi < chl; chi++){
- if (charbuf[chi] == '.') break;
+ if (charbuf[chi] == '.') goto dot;
if (!charbuf[chi]) return -EINVAL;
if (walk-res == 8) return -EINVAL;
if (strchr(replace_chars,charbuf[chi])) return -EINVAL;
@@ -532,6 +534,7 @@ static int vfat_format_name(struct nls_table *nls, wchar_t *name,
walk++;
}
}
+dot:;
if (space) return -EINVAL;
if (len >= 0) {
while (walk-res < 8) *walk++ = ' ';