The BLKISFROZEN ioctl can be used to check the freeze state of a block device (it is possible to freeze a block device that does not have a filesystem sitting on top of it). If allowing the umounting of frozen filesystems is deemed acceptable this ioctl will be extended to check the state of the associated superblock if any. Cc: Josef Bacik <jbacik@xxxxxxxxxxxx> Cc: Eric Sandeen <sandeen@xxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxxxxxxxxx> Cc: Jan Kara <jack@xxxxxxx> Cc: Dave Chinner <dchinner@xxxxxxxxxx> Signed-off-by: Fernando Luis Vazquez Cao <fernando@xxxxxxxxxxxxx> --- diff -urNp linux-3.6-orig/block/compat_ioctl.c linux-3.6/block/compat_ioctl.c --- linux-3.6-orig/block/compat_ioctl.c 2012-10-01 08:47:46.000000000 +0900 +++ linux-3.6/block/compat_ioctl.c 2012-10-04 12:38:51.860275389 +0900 @@ -746,6 +746,13 @@ long compat_blkdev_ioctl(struct file *fi case BLKTRACETEARDOWN: /* compatible */ ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); return ret; + case BLKISFROZEN: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ret = isfrozen_bdev(bdev); + if (ret >= 0) + return compat_put_int(arg, ret); + return ret; default: if (disk->fops->compat_ioctl) ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); diff -urNp linux-3.6-orig/block/ioctl.c linux-3.6/block/ioctl.c --- linux-3.6-orig/block/ioctl.c 2012-10-01 08:47:46.000000000 +0900 +++ linux-3.6/block/ioctl.c 2012-10-04 12:38:51.860275389 +0900 @@ -396,6 +396,13 @@ int blkdev_ioctl(struct block_device *bd case BLKTRACETEARDOWN: ret = blk_trace_ioctl(bdev, cmd, (char __user *) arg); break; + case BLKISFROZEN: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ret = isfrozen_bdev(bdev); + if (ret >= 0) + return put_int(arg, ret); + return ret; default: ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); } diff -urNp linux-3.6-orig/fs/block_dev.c linux-3.6/fs/block_dev.c --- linux-3.6-orig/fs/block_dev.c 2012-10-04 12:35:51.828269380 +0900 +++ linux-3.6/fs/block_dev.c 2012-10-04 12:38:51.860275389 +0900 @@ -337,6 +337,11 @@ out: } EXPORT_SYMBOL(thaw_bdev); +int isfrozen_bdev(struct block_device *bdev) +{ + return bdev->bd_fsfreeze_count > 0; +} + static int blkdev_writepage(struct page *page, struct writeback_control *wbc) { return block_write_full_page(page, blkdev_get_block, wbc); diff -urNp linux-3.6-orig/include/linux/fs.h linux-3.6/include/linux/fs.h --- linux-3.6-orig/include/linux/fs.h 2012-10-04 12:38:27.056275050 +0900 +++ linux-3.6/include/linux/fs.h 2012-10-04 12:38:51.860275389 +0900 @@ -335,6 +335,7 @@ struct inodes_stat_t { #define BLKDISCARDZEROES _IO(0x12,124) #define BLKSECDISCARD _IO(0x12,125) #define BLKROTATIONAL _IO(0x12,126) +#define BLKISFROZEN _IOR(0x12,127, int) /* get file system freeze state */ #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ #define FIBMAP _IO(0x00,1) /* bmap access */ @@ -2251,6 +2252,7 @@ extern void kill_bdev(struct block_devic extern struct super_block *freeze_bdev(struct block_device *); extern void emergency_thaw_all(void); extern int thaw_bdev(struct block_device *bdev, struct super_block *sb); +extern int isfrozen_bdev(struct block_device *bdev); extern int fsync_bdev(struct block_device *); #else static inline void bd_forget(struct inode *inode) {} @@ -2271,6 +2273,11 @@ static inline int thaw_bdev(struct block static inline void iterate_bdevs(void (*f)(struct block_device *, void *), void *arg) { } + +static int isfrozen_bdev(struct block_device *bdev) +{ + return 0; +} #endif extern int sync_filesystem(struct super_block *); extern const struct file_operations def_blk_fops; -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html