summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorAlexander Viro <viro@math.psu.edu>2002-07-20 20:48:09 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-07-20 20:48:09 -0700
commit81d4c00c63a03a1a2fa54c6a2fde84454550338c (patch)
tree62c4175d7fe1083edcacdea9c69b6b2586a0f96c /include/linux
parent5844ac33e46839babf72edf7e8315b45cb95ebc6 (diff)
[PATCH] partition handling locking cleanups
Horrors with open/reread_partition exclusion are starting to get fixed. It's not the final variant, but at least we are getting the logics into one place; switch to final variant will happen once we get per-disk analog of gendisks. New fields - ->bd_part_sem and ->bd_part_count. The latter counts the amount of opened partitions. The former protects said count _and_ is held while we are rereading partition tables. Helpers - dev_part_lock()/dev_part_unlock() (currently taking kdev_t; that will change pretty soon). No more ->open() and ->release() for partitions, all that logics went to generic code. Lock hierachy is currently messy: ->bd_sem for partitions -> ->bd_part_sem -> ->bd_sem for entire disks Ugly, but that'll go away and to get the final variant of locking right now would take _really_ big patch - with a lot of steps glued together. The damn thing is large as it is...
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/fs.h32
1 files changed, 30 insertions, 2 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 83f5a21b5d26..b58c1b43f734 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -342,7 +342,7 @@ struct block_device {
struct inode * bd_inode;
dev_t bd_dev; /* not a kdev_t - it's a search key */
int bd_openers;
- const struct block_device_operations *bd_op;
+ struct block_device_operations *bd_op;
struct request_queue *bd_queue;
struct semaphore bd_sem; /* open/close mutex */
struct list_head bd_inodes;
@@ -351,6 +351,8 @@ struct block_device {
struct block_device * bd_contains;
unsigned bd_block_size;
unsigned long bd_offset;
+ struct semaphore bd_part_sem;
+ unsigned bd_part_count;
};
struct inode {
@@ -1083,7 +1085,7 @@ extern void bd_release(struct block_device *);
extern void blk_run_queues(void);
/* fs/devices.c */
-extern const struct block_device_operations *get_blkfops(unsigned int);
+extern struct block_device_operations *get_blkfops(unsigned int);
extern int register_chrdev(unsigned int, const char *, struct file_operations *);
extern int unregister_chrdev(unsigned int, const char *);
extern int chrdev_open(struct inode *, struct file *);
@@ -1293,5 +1295,31 @@ static inline ino_t parent_ino(struct dentry *dentry)
return res;
}
+/* NOTE NOTE NOTE: this interface _will_ change in a couple of patches */
+
+static inline int dev_lock_part(kdev_t dev)
+{
+ struct block_device *bdev = bdget(kdev_t_to_nr(dev));
+ if (!bdev)
+ return -ENOMEM;
+ if (!down_trylock(&bdev->bd_part_sem)) {
+ if (!bdev->bd_part_count)
+ return 0;
+ up(&bdev->bd_part_sem);
+ }
+ bdput(bdev);
+ return -EBUSY;
+}
+
+static inline void dev_unlock_part(kdev_t dev)
+{
+ struct block_device *bdev = bdget(kdev_t_to_nr(dev));
+ if (!bdev)
+ BUG();
+ up(&bdev->bd_part_sem);
+ bdput(bdev);
+ bdput(bdev);
+}
+
#endif /* __KERNEL__ */
#endif /* _LINUX_FS_H */