diff options
| author | Alexander Viro <viro@math.psu.edu> | 2002-07-20 20:48:09 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-07-20 20:48:09 -0700 |
| commit | 81d4c00c63a03a1a2fa54c6a2fde84454550338c (patch) | |
| tree | 62c4175d7fe1083edcacdea9c69b6b2586a0f96c /include/linux | |
| parent | 5844ac33e46839babf72edf7e8315b45cb95ebc6 (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.h | 32 |
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 */ |
