8
8
9
9
#include <linux/kernel.h>
10
10
#include <linux/module.h>
11
- #include "../../block/blk.h"
12
11
#include <linux/blkdev.h>
13
12
#include <linux/string.h>
14
13
#include <linux/of.h>
15
14
#include <linux/of_address.h>
16
15
#include <linux/platform_device.h>
17
16
#include <linux/pstore_blk.h>
17
+ #include <linux/fs.h>
18
+ #include <linux/file.h>
19
+ #include <linux/init_syscalls.h>
18
20
#include <linux/mount.h>
19
- #include <linux/uio.h>
20
21
21
22
static long kmsg_size = CONFIG_PSTORE_BLK_KMSG_SIZE ;
22
23
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
60
61
*
61
62
* Usually, this will be a partition of a block device.
62
63
*
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
68
67
* 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
70
69
* 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
72
75
* unique id of a partition if the partition table provides it.
73
76
* The UUID may be either an EFI/GPT UUID, or refer to an MSDOS
74
77
* partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero-
75
78
* filled hex representation of the 32-bit "NT disk signature", and PP
76
79
* 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
78
81
* 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
80
83
* a colon.
81
84
*/
82
85
static char blkdev [80 ] = CONFIG_PSTORE_BLK_BLKDEV ;
@@ -88,15 +91,9 @@ MODULE_PARM_DESC(blkdev, "block device for pstore storage");
88
91
* during the register/unregister functions.
89
92
*/
90
93
static DEFINE_MUTEX (pstore_blk_lock );
91
- static struct block_device * psblk_bdev ;
94
+ static struct file * psblk_file ;
92
95
static struct pstore_zone_info * pstore_zone_info ;
93
96
94
- struct bdev_info {
95
- dev_t devt ;
96
- sector_t nr_sects ;
97
- sector_t start_sect ;
98
- };
99
-
100
97
#define check_size (name , alignsize ) ({ \
101
98
long _##name_ = (name); \
102
99
_##name_ = _##name_ <= 0 ? 0 : (_##name_ * 1024); \
@@ -219,203 +216,73 @@ void unregister_pstore_device(struct pstore_device_info *dev)
219
216
}
220
217
EXPORT_SYMBOL_GPL (unregister_pstore_device );
221
218
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
-
291
219
static ssize_t psblk_generic_blk_read (char * buf , size_t bytes , loff_t pos )
292
220
{
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 );
313
222
}
314
223
315
224
static ssize_t psblk_generic_blk_write (const char * buf , size_t bytes ,
316
225
loff_t pos )
317
226
{
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
-
328
227
/* Console/Ftrace backend may handle buffer until flush dirty zones */
329
228
if (in_interrupt () || irqs_disabled ())
330
229
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 );
355
231
}
356
232
357
233
/*
358
234
* This takes its configuration only from the module parameters now.
359
- * See psblk_get_bdev() and blkdev.
360
235
*/
361
- static int __register_pstore_blk (void )
236
+ static int __register_pstore_blk (const char * devpath )
362
237
{
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 ;
368
243
int ret = - ENODEV ;
369
244
370
245
lockdep_assert_held (& pstore_blk_lock );
371
246
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 ;
378
252
}
379
253
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 ;
385
258
}
386
259
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 );
394
262
395
263
ret = __register_pstore_device (& dev );
396
264
if (ret )
397
- goto err_put_bdev ;
265
+ goto err_fput ;
398
266
399
- bdevname (bdev , bdev_name );
400
- pr_info ("attached %s (no dedicated panic_write!)\n" , bdev_name );
401
267
return 0 ;
402
268
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
+
406
274
return ret ;
407
275
}
408
276
409
- static void __unregister_pstore_blk (unsigned int major )
277
+ static void __unregister_pstore_blk (struct file * device )
410
278
{
411
279
struct pstore_device_info dev = { .read = psblk_generic_blk_read };
412
- void * holder = blkdev ;
413
280
414
281
lockdep_assert_held (& pstore_blk_lock );
415
- if (psblk_bdev && MAJOR ( psblk_bdev -> bd_dev ) == major ) {
282
+ if (psblk_file && psblk_file == device ) {
416
283
__unregister_pstore_device (& dev );
417
- psblk_put_bdev ( psblk_bdev , holder );
418
- psblk_bdev = NULL ;
284
+ fput ( psblk_file );
285
+ psblk_file = NULL ;
419
286
}
420
287
}
421
288
@@ -433,13 +300,48 @@ int pstore_blk_get_config(struct pstore_blk_config *info)
433
300
}
434
301
EXPORT_SYMBOL_GPL (pstore_blk_get_config );
435
302
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
+
436
333
static int __init pstore_blk_init (void )
437
334
{
438
335
int ret = 0 ;
439
336
440
337
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
+ }
443
345
mutex_unlock (& pstore_blk_lock );
444
346
445
347
return ret ;
@@ -449,8 +351,8 @@ late_initcall(pstore_blk_init);
449
351
static void __exit pstore_blk_exit (void )
450
352
{
451
353
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 );
454
356
else {
455
357
struct pstore_device_info dev = { };
456
358
0 commit comments