aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2014-04-08 22:25:40 -0400
committerNeilBrown <neilb@suse.de>2014-04-08 22:26:59 -0400
commit035328c202d26a824b8632fd3b00635db5aee5a2 (patch)
treeea9f5c2d54e7e5397318ba9b91b0b88a33f179ae /drivers/md
parent455c6fdbd219161bd09b1165f11699d6d73de11c (diff)
md/bitmap: don't abuse i_writecount for bitmap files.
md bitmap code currently tries to use i_writecount to stop any other process from writing to out bitmap file. But that is really an abuse and has bit-rotted so locking is all wrong. So discard that - root should be allowed to shoot self in foot. Still use it in a much less intrusive way to stop the same file being used as bitmap on two different array, and apply other checks to ensure the file is at least vaguely usable for bitmap storage (is regular, is open for write. Support for ->bmap is already checked elsewhere). Reported-by: Al Viro <viro@ZenIV.linux.org.uk> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/bitmap.c1
-rw-r--r--drivers/md/md.c49
-rw-r--r--drivers/md/md.h1
3 files changed, 16 insertions, 35 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 4195a01b1535..9a8e66ae04f5 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1988,7 +1988,6 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
1988 if (mddev->bitmap_info.file) { 1988 if (mddev->bitmap_info.file) {
1989 struct file *f = mddev->bitmap_info.file; 1989 struct file *f = mddev->bitmap_info.file;
1990 mddev->bitmap_info.file = NULL; 1990 mddev->bitmap_info.file = NULL;
1991 restore_bitmap_write_access(f);
1992 fput(f); 1991 fput(f);
1993 } 1992 }
1994 } else { 1993 } else {
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 4ad5cc4e63e8..3fa2fc0a5dd2 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5181,32 +5181,6 @@ static int restart_array(struct mddev *mddev)
5181 return 0; 5181 return 0;
5182} 5182}
5183 5183
5184/* similar to deny_write_access, but accounts for our holding a reference
5185 * to the file ourselves */
5186static int deny_bitmap_write_access(struct file * file)
5187{
5188 struct inode *inode = file->f_mapping->host;
5189
5190 spin_lock(&inode->i_lock);
5191 if (atomic_read(&inode->i_writecount) > 1) {
5192 spin_unlock(&inode->i_lock);
5193 return -ETXTBSY;
5194 }
5195 atomic_set(&inode->i_writecount, -1);
5196 spin_unlock(&inode->i_lock);
5197
5198 return 0;
5199}
5200
5201void restore_bitmap_write_access(struct file *file)
5202{
5203 struct inode *inode = file->f_mapping->host;
5204
5205 spin_lock(&inode->i_lock);
5206 atomic_set(&inode->i_writecount, 1);
5207 spin_unlock(&inode->i_lock);
5208}
5209
5210static void md_clean(struct mddev *mddev) 5184static void md_clean(struct mddev *mddev)
5211{ 5185{
5212 mddev->array_sectors = 0; 5186 mddev->array_sectors = 0;
@@ -5427,7 +5401,6 @@ static int do_md_stop(struct mddev * mddev, int mode,
5427 5401
5428 bitmap_destroy(mddev); 5402 bitmap_destroy(mddev);
5429 if (mddev->bitmap_info.file) { 5403 if (mddev->bitmap_info.file) {
5430 restore_bitmap_write_access(mddev->bitmap_info.file);
5431 fput(mddev->bitmap_info.file); 5404 fput(mddev->bitmap_info.file);
5432 mddev->bitmap_info.file = NULL; 5405 mddev->bitmap_info.file = NULL;
5433 } 5406 }
@@ -5979,7 +5952,7 @@ abort_export:
5979 5952
5980static int set_bitmap_file(struct mddev *mddev, int fd) 5953static int set_bitmap_file(struct mddev *mddev, int fd)
5981{ 5954{
5982 int err; 5955 int err = 0;
5983 5956
5984 if (mddev->pers) { 5957 if (mddev->pers) {
5985 if (!mddev->pers->quiesce) 5958 if (!mddev->pers->quiesce)
@@ -5991,6 +5964,7 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
5991 5964
5992 5965
5993 if (fd >= 0) { 5966 if (fd >= 0) {
5967 struct inode *inode;
5994 if (mddev->bitmap) 5968 if (mddev->bitmap)
5995 return -EEXIST; /* cannot add when bitmap is present */ 5969 return -EEXIST; /* cannot add when bitmap is present */
5996 mddev->bitmap_info.file = fget(fd); 5970 mddev->bitmap_info.file = fget(fd);
@@ -6001,10 +5975,21 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
6001 return -EBADF; 5975 return -EBADF;
6002 } 5976 }
6003 5977
6004 err = deny_bitmap_write_access(mddev->bitmap_info.file); 5978 inode = mddev->bitmap_info.file->f_mapping->host;
6005 if (err) { 5979 if (!S_ISREG(inode->i_mode)) {
5980 printk(KERN_ERR "%s: error: bitmap file must be a regular file\n",
5981 mdname(mddev));
5982 err = -EBADF;
5983 } else if (!(mddev->bitmap_info.file->f_mode & FMODE_WRITE)) {
5984 printk(KERN_ERR "%s: error: bitmap file must open for write\n",
5985 mdname(mddev));
5986 err = -EBADF;
5987 } else if (atomic_read(&inode->i_writecount) != 1) {
6006 printk(KERN_ERR "%s: error: bitmap file is already in use\n", 5988 printk(KERN_ERR "%s: error: bitmap file is already in use\n",
6007 mdname(mddev)); 5989 mdname(mddev));
5990 err = -EBUSY;
5991 }
5992 if (err) {
6008 fput(mddev->bitmap_info.file); 5993 fput(mddev->bitmap_info.file);
6009 mddev->bitmap_info.file = NULL; 5994 mddev->bitmap_info.file = NULL;
6010 return err; 5995 return err;
@@ -6027,10 +6012,8 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
6027 mddev->pers->quiesce(mddev, 0); 6012 mddev->pers->quiesce(mddev, 0);
6028 } 6013 }
6029 if (fd < 0) { 6014 if (fd < 0) {
6030 if (mddev->bitmap_info.file) { 6015 if (mddev->bitmap_info.file)
6031 restore_bitmap_write_access(mddev->bitmap_info.file);
6032 fput(mddev->bitmap_info.file); 6016 fput(mddev->bitmap_info.file);
6033 }
6034 mddev->bitmap_info.file = NULL; 6017 mddev->bitmap_info.file = NULL;
6035 } 6018 }
6036 6019
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 07bba96de260..a49d991f3fe1 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -605,7 +605,6 @@ extern int md_check_no_bitmap(struct mddev *mddev);
605extern int md_integrity_register(struct mddev *mddev); 605extern int md_integrity_register(struct mddev *mddev);
606extern void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev); 606extern void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev);
607extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale); 607extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
608extern void restore_bitmap_write_access(struct file *file);
609 608
610extern void mddev_init(struct mddev *mddev); 609extern void mddev_init(struct mddev *mddev);
611extern int md_run(struct mddev *mddev); 610extern int md_run(struct mddev *mddev);