aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);