From: Alexander Viro <viro@math.psu.edu>
To: Linus Torvalds <torvalds@transmeta.com>
Cc: Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [PATCH] fs/super.c fixes - second series (2/11)
Date: Sun, 12 Aug 2001 21:26:31 -0400 (EDT) [thread overview]
Message-ID: <Pine.GSO.4.21.0108122126140.7092-100000@weyl.math.psu.edu> (raw)
In-Reply-To: <Pine.GSO.4.21.0108110046040.440-100000@weyl.math.psu.edu>
Part 2/11
First part of get_sb_bdev() rewrite. We move opening the device to the
beginning of the function. If we already have a superblock from that device
- well, no problem. That, BTW, fixes a buglet with permissions: suppose
we mount /dev/foo, chmod it to 0 and say mount /dev/foo again. Old code
merrily didn't notice that permissions had been revoked and allowed mount.
Main reason for the change is different, though - we are getting the
blocking operations from the area we want to protect with sb_lock (see
the next chunk).
Cleanup: we move decrementing ->s_active into put_super(). Callers updated.
diff -urN S9-pre1-s_umount/fs/super.c S9-pre1-get_sb_bdev/fs/super.c
--- S9-pre1-s_umount/fs/super.c Sun Aug 12 20:45:49 2001
+++ S9-pre1-get_sb_bdev/fs/super.c Sun Aug 12 20:45:49 2001
@@ -872,6 +872,26 @@
kdevname(dev));
}
+static int grab_super(struct super_block *sb)
+{
+ sb->s_count++;
+ atomic_inc(&sb->s_active);
+ spin_unlock(&sb_lock);
+ down_write(&sb->s_umount);
+ if (sb->s_root) {
+ /* Still relying on mount_sem */
+ if (atomic_read(&sb->s_active) > 1) {
+ spin_lock(&sb_lock);
+ sb->s_count--;
+ spin_unlock(&sb_lock);
+ return 1;
+ }
+ }
+ atomic_dec(&sb->s_active);
+ put_super(sb);
+ return 0;
+}
+
static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
char *dev_name, int flags, void * data)
{
@@ -880,8 +900,11 @@
struct block_device_operations *bdops;
struct super_block * sb;
struct nameidata nd;
+ struct list_head *p;
kdev_t dev;
int error = 0;
+ mode_t mode = FMODE_READ; /* we always need it ;-) */
+
/* What device it is? */
if (!dev_name || !*dev_name)
return ERR_PTR(-EINVAL);
@@ -902,52 +925,45 @@
/* Done with lookups, semaphore down */
down(&mount_sem);
dev = to_kdev_t(bdev->bd_dev);
- sb = get_super(dev);
- if (sb) {
- if (fs_type == sb->s_type &&
- ((flags ^ sb->s_flags) & MS_RDONLY) == 0) {
-/*
- * We are heavily relying on mount_sem here. We _will_ get rid of that
- * ugliness RSN (and then atomicity of ->s_active will play), but first
- * we need to get rid of "reuse" branch of get_empty_super() and that
- * requires reference counters. Chicken and egg problem, but fortunately
- * we can use the fact that right now all accesses to ->s_active are
- * under mount_sem.
- */
- if (atomic_read(&sb->s_active)) {
- spin_lock(&sb_lock);
- sb->s_count--;
- spin_unlock(&sb_lock);
- }
- atomic_inc(&sb->s_active);
- /* Next chunk will drop it */
- up_read(&sb->s_umount);
- down_write(&sb->s_umount);
- path_release(&nd);
- return sb;
- }
- drop_super(sb);
- } else {
- mode_t mode = FMODE_READ; /* we always need it ;-) */
- if (!(flags & MS_RDONLY))
- mode |= FMODE_WRITE;
- error = blkdev_get(bdev, mode, 0, BDEV_FS);
- if (error)
- goto out;
- check_disk_change(dev);
- error = -EACCES;
- if (!(flags & MS_RDONLY) && is_read_only(dev))
+ if (!(flags & MS_RDONLY))
+ mode |= FMODE_WRITE;
+ error = blkdev_get(bdev, mode, 0, BDEV_FS);
+ if (error)
+ goto out;
+ check_disk_change(dev);
+ error = -EACCES;
+ if (!(flags & MS_RDONLY) && is_read_only(dev))
+ goto out1;
+
+ error = -EBUSY;
+restart:
+ spin_lock(&sb_lock);
+
+ list_for_each(p, &super_blocks) {
+ struct super_block *old = sb_entry(p);
+ if (old->s_dev != dev)
+ continue;
+ if (old->s_type != fs_type ||
+ ((flags ^ old->s_flags) & MS_RDONLY)) {
+ spin_unlock(&sb_lock);
goto out1;
- error = -EINVAL;
- sb = read_super(dev, bdev, fs_type, flags, data, 0);
- if (sb) {
- get_filesystem(fs_type);
- path_release(&nd);
- return sb;
}
-out1:
+ if (!grab_super(old))
+ goto restart;
blkdev_put(bdev, BDEV_FS);
+ path_release(&nd);
+ return old;
}
+ spin_unlock(&sb_lock);
+ error = -EINVAL;
+ sb = read_super(dev, bdev, fs_type, flags, data, 0);
+ if (sb) {
+ get_filesystem(fs_type);
+ path_release(&nd);
+ return sb;
+ }
+out1:
+ blkdev_put(bdev, BDEV_FS);
out:
path_release(&nd);
up(&mount_sem);
diff -urN S9-pre1-s_count/fs/super.c S9-pre1-put_super/fs/super.c
--- S9-pre1-s_count/fs/super.c Sun Aug 12 20:45:52 2001
+++ S9-pre1-put_super/fs/super.c Sun Aug 12 20:45:52 2001
@@ -666,6 +666,7 @@
static void put_super(struct super_block *sb)
{
+ atomic_dec(&sb->s_active);
up_write(&sb->s_umount);
__put_super(sb);
}
@@ -832,7 +833,6 @@
s->s_bdev = 0;
s->s_type = NULL;
unlock_super(s);
- atomic_dec(&s->s_active);
spin_lock(&sb_lock);
list_del(&s->s_list);
list_del(&s->s_instances);
@@ -885,7 +885,6 @@
}
spin_unlock(&sb_lock);
}
- atomic_dec(&sb->s_active);
put_super(sb);
return 0;
}
@@ -950,13 +949,11 @@
if (old->s_type != fs_type ||
((flags ^ old->s_flags) & MS_RDONLY)) {
spin_unlock(&sb_lock);
- atomic_dec(&s->s_active);
put_super(s);
goto out1;
}
if (!grab_super(old))
goto restart;
- atomic_dec(&s->s_active);
put_super(s);
blkdev_put(bdev, BDEV_FS);
path_release(&nd);
@@ -988,7 +985,6 @@
s->s_bdev = 0;
s->s_type = NULL;
unlock_super(s);
- atomic_dec(&s->s_active);
spin_lock(&sb_lock);
list_del(&s->s_list);
list_del(&s->s_instances);
@@ -1044,14 +1040,12 @@
s_instances);
if (!grab_super(old))
goto retry;
- atomic_dec(&s->s_active);
put_super(s);
do_remount_sb(old, flags, data);
return old;
} else {
kdev_t dev = get_unnamed_dev();
if (!dev) {
- atomic_dec(&s->s_active);
put_super(s);
up(&mount_sem);
return ERR_PTR(-EMFILE);
@@ -1075,7 +1069,6 @@
s->s_bdev = 0;
s->s_type = NULL;
unlock_super(s);
- atomic_dec(&s->s_active);
spin_lock(&sb_lock);
list_del(&s->s_list);
list_del(&s->s_instances);
@@ -1142,6 +1135,7 @@
list_del(&sb->s_list);
list_del(&sb->s_instances);
spin_unlock(&sb_lock);
+ atomic_inc(&sb->s_active);
put_super(sb);
}
next prev parent reply other threads:[~2001-08-13 1:26 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-08-11 4:17 Linux-2.4.8 Linus Torvalds
2001-08-13 1:25 ` [PATCH] fs/super.c fixes - second series (1/11) Alexander Viro
2001-08-13 1:26 ` Alexander Viro [this message]
2001-08-13 1:26 ` [PATCH] fs/super.c fixes - second series (3/11) Alexander Viro
2001-08-13 1:27 ` [PATCH] fs/super.c fixes - second series (4/11) Alexander Viro
2001-08-13 1:27 ` [PATCH] fs/super.c fixes - second series (5/11) Alexander Viro
2001-08-13 1:28 ` [PATCH] fs/super.c fixes - second series (6/11) Alexander Viro
2001-08-13 1:28 ` [PATCH] fs/super.c fixes - second series (7/11) Alexander Viro
2001-08-13 1:28 ` [PATCH] fs/super.c fixes - second series (8/11) Alexander Viro
2001-08-13 1:29 ` [PATCH] fs/super.c fixes - second series (9/11) Alexander Viro
2001-08-13 1:29 ` [PATCH] fs/super.c fixes - second series (10/11) Alexander Viro
2001-08-13 1:29 ` [PATCH] fs/super.c fixes - second series (11/11) Alexander Viro
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.GSO.4.21.0108122126140.7092-100000@weyl.math.psu.edu \
--to=viro@math.psu.edu \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@transmeta.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).