Skip to content

Commit 7bb9557

Browse files
committed
pstore/blk: Use the normal block device I/O path
Stop poking into block layer internals and just open the block device file an use kernel_read and kernel_write on it. Note that this means the transformation from name_to_dev_t can't be used anymore when pstore_blk is loaded as a module: a full filesystem device path name must be used instead. Additionally removes ":internal:" kerndoc link, since no such documentation remains. Co-developed-by: Christoph Hellwig <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Kees Cook <[email protected]>
1 parent 2a03ddb commit 7bb9557

File tree

2 files changed

+83
-184
lines changed

2 files changed

+83
-184
lines changed

Documentation/admin-guide/pstore-blk.rst

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,5 @@ For developer reference, here are all the important structures and APIs:
227227
.. kernel-doc:: include/linux/pstore_zone.h
228228
:internal:
229229

230-
.. kernel-doc:: fs/pstore/blk.c
231-
:internal:
232-
233230
.. kernel-doc:: include/linux/pstore_blk.h
234231
:internal:

fs/pstore/blk.c

Lines changed: 83 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@
88

99
#include <linux/kernel.h>
1010
#include <linux/module.h>
11-
#include "../../block/blk.h"
1211
#include <linux/blkdev.h>
1312
#include <linux/string.h>
1413
#include <linux/of.h>
1514
#include <linux/of_address.h>
1615
#include <linux/platform_device.h>
1716
#include <linux/pstore_blk.h>
17+
#include <linux/fs.h>
18+
#include <linux/file.h>
19+
#include <linux/init_syscalls.h>
1820
#include <linux/mount.h>
19-
#include <linux/uio.h>
2021

2122
static long kmsg_size = CONFIG_PSTORE_BLK_KMSG_SIZE;
2223
module_param(kmsg_size, long, 0400);
@@ -60,23 +61,25 @@ MODULE_PARM_DESC(best_effort, "use best effort to write (i.e. do not require sto
6061
*
6162
* Usually, this will be a partition of a block device.
6263
*
63-
* blkdev accepts the following variants:
64-
* 1) <hex_major><hex_minor> device number in hexadecimal representation,
65-
* with no leading 0x, for example b302.
66-
* 2) /dev/<disk_name> represents the device number of disk
67-
* 3) /dev/<disk_name><decimal> represents the device number
64+
* blkdev accepts the following variants, when built as a module:
65+
* 1) /dev/<disk_name> represents the device number of disk
66+
* 2) /dev/<disk_name><decimal> represents the device number
6867
* of partition - device number of disk plus the partition number
69-
* 4) /dev/<disk_name>p<decimal> - same as the above, that form is
68+
* 3) /dev/<disk_name>p<decimal> - same as the above, that form is
7069
* used when disk name of partitioned disk ends on a digit.
71-
* 5) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
70+
*
71+
* blkdev accepts the following variants when built into the kernel:
72+
* 1) <hex_major><hex_minor> device number in hexadecimal representation,
73+
* with no leading 0x, for example b302.
74+
* 2) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
7275
* unique id of a partition if the partition table provides it.
7376
* The UUID may be either an EFI/GPT UUID, or refer to an MSDOS
7477
* partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero-
7578
* filled hex representation of the 32-bit "NT disk signature", and PP
7679
* is a zero-filled hex representation of the 1-based partition number.
77-
* 6) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to
80+
* 3) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to
7881
* a partition with a known unique id.
79-
* 7) <major>:<minor> major and minor number of the device separated by
82+
* 4) <major>:<minor> major and minor number of the device separated by
8083
* a colon.
8184
*/
8285
static char blkdev[80] = CONFIG_PSTORE_BLK_BLKDEV;
@@ -88,15 +91,9 @@ MODULE_PARM_DESC(blkdev, "block device for pstore storage");
8891
* during the register/unregister functions.
8992
*/
9093
static DEFINE_MUTEX(pstore_blk_lock);
91-
static struct block_device *psblk_bdev;
94+
static struct file *psblk_file;
9295
static struct pstore_zone_info *pstore_zone_info;
9396

94-
struct bdev_info {
95-
dev_t devt;
96-
sector_t nr_sects;
97-
sector_t start_sect;
98-
};
99-
10097
#define check_size(name, alignsize) ({ \
10198
long _##name_ = (name); \
10299
_##name_ = _##name_ <= 0 ? 0 : (_##name_ * 1024); \
@@ -219,203 +216,73 @@ void unregister_pstore_device(struct pstore_device_info *dev)
219216
}
220217
EXPORT_SYMBOL_GPL(unregister_pstore_device);
221218

222-
/**
223-
* psblk_get_bdev() - open block device
224-
*
225-
* @holder: Exclusive holder identifier
226-
* @info: Information about bdev to fill in
227-
*
228-
* Return: pointer to block device on success and others on error.
229-
*
230-
* On success, the returned block_device has reference count of one.
231-
*/
232-
static struct block_device *psblk_get_bdev(void *holder,
233-
struct bdev_info *info)
234-
{
235-
struct block_device *bdev = ERR_PTR(-ENODEV);
236-
fmode_t mode = FMODE_READ | FMODE_WRITE;
237-
sector_t nr_sects;
238-
239-
lockdep_assert_held(&pstore_blk_lock);
240-
241-
if (pstore_zone_info)
242-
return ERR_PTR(-EBUSY);
243-
244-
if (!blkdev[0])
245-
return ERR_PTR(-ENODEV);
246-
247-
if (holder)
248-
mode |= FMODE_EXCL;
249-
bdev = blkdev_get_by_path(blkdev, mode, holder);
250-
if (IS_ERR(bdev)) {
251-
dev_t devt;
252-
253-
devt = name_to_dev_t(blkdev);
254-
if (devt == 0)
255-
return ERR_PTR(-ENODEV);
256-
bdev = blkdev_get_by_dev(devt, mode, holder);
257-
if (IS_ERR(bdev))
258-
return bdev;
259-
}
260-
261-
nr_sects = bdev_nr_sectors(bdev);
262-
if (!nr_sects) {
263-
pr_err("not enough space for '%s'\n", blkdev);
264-
blkdev_put(bdev, mode);
265-
return ERR_PTR(-ENOSPC);
266-
}
267-
268-
if (info) {
269-
info->devt = bdev->bd_dev;
270-
info->nr_sects = nr_sects;
271-
info->start_sect = get_start_sect(bdev);
272-
}
273-
274-
return bdev;
275-
}
276-
277-
static void psblk_put_bdev(struct block_device *bdev, void *holder)
278-
{
279-
fmode_t mode = FMODE_READ | FMODE_WRITE;
280-
281-
lockdep_assert_held(&pstore_blk_lock);
282-
283-
if (!bdev)
284-
return;
285-
286-
if (holder)
287-
mode |= FMODE_EXCL;
288-
blkdev_put(bdev, mode);
289-
}
290-
291219
static ssize_t psblk_generic_blk_read(char *buf, size_t bytes, loff_t pos)
292220
{
293-
struct block_device *bdev = psblk_bdev;
294-
struct file file;
295-
struct kiocb kiocb;
296-
struct iov_iter iter;
297-
struct kvec iov = {.iov_base = buf, .iov_len = bytes};
298-
299-
if (!bdev)
300-
return -ENODEV;
301-
302-
memset(&file, 0, sizeof(struct file));
303-
file.f_mapping = bdev->bd_inode->i_mapping;
304-
file.f_flags = O_DSYNC | __O_SYNC | O_NOATIME;
305-
file.f_inode = bdev->bd_inode;
306-
file_ra_state_init(&file.f_ra, file.f_mapping);
307-
308-
init_sync_kiocb(&kiocb, &file);
309-
kiocb.ki_pos = pos;
310-
iov_iter_kvec(&iter, READ, &iov, 1, bytes);
311-
312-
return generic_file_read_iter(&kiocb, &iter);
221+
return kernel_read(psblk_file, buf, bytes, &pos);
313222
}
314223

315224
static ssize_t psblk_generic_blk_write(const char *buf, size_t bytes,
316225
loff_t pos)
317226
{
318-
struct block_device *bdev = psblk_bdev;
319-
struct iov_iter iter;
320-
struct kiocb kiocb;
321-
struct file file;
322-
ssize_t ret;
323-
struct kvec iov = {.iov_base = (void *)buf, .iov_len = bytes};
324-
325-
if (!bdev)
326-
return -ENODEV;
327-
328227
/* Console/Ftrace backend may handle buffer until flush dirty zones */
329228
if (in_interrupt() || irqs_disabled())
330229
return -EBUSY;
331-
332-
memset(&file, 0, sizeof(struct file));
333-
file.f_mapping = bdev->bd_inode->i_mapping;
334-
file.f_flags = O_DSYNC | __O_SYNC | O_NOATIME;
335-
file.f_inode = bdev->bd_inode;
336-
337-
init_sync_kiocb(&kiocb, &file);
338-
kiocb.ki_pos = pos;
339-
iov_iter_kvec(&iter, WRITE, &iov, 1, bytes);
340-
341-
inode_lock(bdev->bd_inode);
342-
ret = generic_write_checks(&kiocb, &iter);
343-
if (ret > 0)
344-
ret = generic_perform_write(&file, &iter, pos);
345-
inode_unlock(bdev->bd_inode);
346-
347-
if (likely(ret > 0)) {
348-
const struct file_operations f_op = {.fsync = blkdev_fsync};
349-
350-
file.f_op = &f_op;
351-
kiocb.ki_pos += ret;
352-
ret = generic_write_sync(&kiocb, ret);
353-
}
354-
return ret;
230+
return kernel_write(psblk_file, buf, bytes, &pos);
355231
}
356232

357233
/*
358234
* This takes its configuration only from the module parameters now.
359-
* See psblk_get_bdev() and blkdev.
360235
*/
361-
static int __register_pstore_blk(void)
236+
static int __register_pstore_blk(const char *devpath)
362237
{
363-
char bdev_name[BDEVNAME_SIZE];
364-
struct block_device *bdev;
365-
struct pstore_device_info dev;
366-
struct bdev_info binfo;
367-
void *holder = blkdev;
238+
struct pstore_device_info dev = {
239+
.read = psblk_generic_blk_read,
240+
.write = psblk_generic_blk_write,
241+
};
242+
struct inode *inode;
368243
int ret = -ENODEV;
369244

370245
lockdep_assert_held(&pstore_blk_lock);
371246

372-
/* hold bdev exclusively */
373-
memset(&binfo, 0, sizeof(binfo));
374-
bdev = psblk_get_bdev(holder, &binfo);
375-
if (IS_ERR(bdev)) {
376-
pr_err("failed to open '%s'!\n", blkdev);
377-
return PTR_ERR(bdev);
247+
psblk_file = filp_open(devpath, O_RDWR | O_DSYNC | O_NOATIME | O_EXCL, 0);
248+
if (IS_ERR(psblk_file)) {
249+
ret = PTR_ERR(psblk_file);
250+
pr_err("failed to open '%s': %d!\n", devpath, ret);
251+
goto err;
378252
}
379253

380-
/* only allow driver matching the @blkdev */
381-
if (!binfo.devt) {
382-
pr_debug("no major\n");
383-
ret = -ENODEV;
384-
goto err_put_bdev;
254+
inode = file_inode(psblk_file);
255+
if (!S_ISBLK(inode->i_mode)) {
256+
pr_err("'%s' is not block device!\n", devpath);
257+
goto err_fput;
385258
}
386259

387-
/* psblk_bdev must be assigned before register to pstore/blk */
388-
psblk_bdev = bdev;
389-
390-
memset(&dev, 0, sizeof(dev));
391-
dev.total_size = binfo.nr_sects << SECTOR_SHIFT;
392-
dev.read = psblk_generic_blk_read;
393-
dev.write = psblk_generic_blk_write;
260+
inode = I_BDEV(psblk_file->f_mapping->host)->bd_inode;
261+
dev.total_size = i_size_read(inode);
394262

395263
ret = __register_pstore_device(&dev);
396264
if (ret)
397-
goto err_put_bdev;
265+
goto err_fput;
398266

399-
bdevname(bdev, bdev_name);
400-
pr_info("attached %s (no dedicated panic_write!)\n", bdev_name);
401267
return 0;
402268

403-
err_put_bdev:
404-
psblk_bdev = NULL;
405-
psblk_put_bdev(bdev, holder);
269+
err_fput:
270+
fput(psblk_file);
271+
err:
272+
psblk_file = NULL;
273+
406274
return ret;
407275
}
408276

409-
static void __unregister_pstore_blk(unsigned int major)
277+
static void __unregister_pstore_blk(struct file *device)
410278
{
411279
struct pstore_device_info dev = { .read = psblk_generic_blk_read };
412-
void *holder = blkdev;
413280

414281
lockdep_assert_held(&pstore_blk_lock);
415-
if (psblk_bdev && MAJOR(psblk_bdev->bd_dev) == major) {
282+
if (psblk_file && psblk_file == device) {
416283
__unregister_pstore_device(&dev);
417-
psblk_put_bdev(psblk_bdev, holder);
418-
psblk_bdev = NULL;
284+
fput(psblk_file);
285+
psblk_file = NULL;
419286
}
420287
}
421288

@@ -433,13 +300,48 @@ int pstore_blk_get_config(struct pstore_blk_config *info)
433300
}
434301
EXPORT_SYMBOL_GPL(pstore_blk_get_config);
435302

303+
304+
#ifndef MODULE
305+
static const char devname[] = "/dev/pstore-blk";
306+
static __init const char *early_boot_devpath(const char *initial_devname)
307+
{
308+
/*
309+
* During early boot the real root file system hasn't been
310+
* mounted yet, and no device nodes are present yet. Use the
311+
* same scheme to find the device that we use for mounting
312+
* the root file system.
313+
*/
314+
dev_t dev = name_to_dev_t(initial_devname);
315+
316+
if (!dev) {
317+
pr_err("failed to resolve '%s'!\n", initial_devname);
318+
return initial_devname;
319+
}
320+
321+
init_unlink(devname);
322+
init_mknod(devname, S_IFBLK | 0600, new_encode_dev(dev));
323+
324+
return devname;
325+
}
326+
#else
327+
static inline const char *early_boot_devpath(const char *initial_devname)
328+
{
329+
return initial_devname;
330+
}
331+
#endif
332+
436333
static int __init pstore_blk_init(void)
437334
{
438335
int ret = 0;
439336

440337
mutex_lock(&pstore_blk_lock);
441-
if (!pstore_zone_info && best_effort && blkdev[0])
442-
ret = __register_pstore_blk();
338+
if (!pstore_zone_info && best_effort && blkdev[0]) {
339+
ret = __register_pstore_blk(early_boot_devpath(blkdev));
340+
if (ret == 0 && pstore_zone_info)
341+
pr_info("attached %s:%s (%zu) (no dedicated panic_write!)\n",
342+
pstore_zone_info->name, blkdev,
343+
pstore_zone_info->total_size);
344+
}
443345
mutex_unlock(&pstore_blk_lock);
444346

445347
return ret;
@@ -449,8 +351,8 @@ late_initcall(pstore_blk_init);
449351
static void __exit pstore_blk_exit(void)
450352
{
451353
mutex_lock(&pstore_blk_lock);
452-
if (psblk_bdev)
453-
__unregister_pstore_blk(MAJOR(psblk_bdev->bd_dev));
354+
if (psblk_file)
355+
__unregister_pstore_blk(psblk_file);
454356
else {
455357
struct pstore_device_info dev = { };
456358

0 commit comments

Comments
 (0)