^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Persistent Storage - ramfs parts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/fsnotify.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/ramfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/parser.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/magic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/pstore.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #ifdef CONFIG_PSTORE_BOOT_LOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/pstore_ram.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define PSTORE_NAMELEN 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static DEFINE_MUTEX(records_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static LIST_HEAD(records_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static DEFINE_MUTEX(pstore_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static struct super_block *pstore_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct pstore_private {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct pstore_record *record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) size_t total_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct pstore_ftrace_seq_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) const void *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) size_t off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define REC_SIZE sizeof(struct pstore_ftrace_record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static void free_pstore_private(struct pstore_private *private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (!private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (private->record) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) kfree(private->record->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) kfree(private->record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) kfree(private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct pstore_private *ps = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct pstore_ftrace_seq_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) data = kzalloc(sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) data->off = ps->total_size % REC_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) data->off += *pos * REC_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (data->off + REC_SIZE > ps->total_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static void pstore_ftrace_seq_stop(struct seq_file *s, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) kfree(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static void *pstore_ftrace_seq_next(struct seq_file *s, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct pstore_private *ps = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct pstore_ftrace_seq_data *data = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) (*pos)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) data->off += REC_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (data->off + REC_SIZE > ps->total_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static int pstore_ftrace_seq_show(struct seq_file *s, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct pstore_private *ps = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct pstore_ftrace_seq_data *data = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct pstore_ftrace_record *rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) rec = (struct pstore_ftrace_record *)(ps->record->buf + data->off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) seq_printf(s, "CPU:%d ts:%llu %08lx %08lx %ps <- %pS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) pstore_ftrace_decode_cpu(rec),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pstore_ftrace_read_timestamp(rec),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) rec->ip, rec->parent_ip, (void *)rec->ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) (void *)rec->parent_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static const struct seq_operations pstore_ftrace_seq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .start = pstore_ftrace_seq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .next = pstore_ftrace_seq_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .stop = pstore_ftrace_seq_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .show = pstore_ftrace_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct seq_file *sf = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct pstore_private *ps = sf->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #ifdef CONFIG_PSTORE_BOOT_LOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) size_t size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct pstore_record *record = ps->record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (record->type == PSTORE_TYPE_BOOT_LOG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) size = ramoops_pstore_read_for_boot_log(ps->record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) size = simple_read_from_buffer(userbuf, count, ppos, record->buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (ps->record->type == PSTORE_TYPE_FTRACE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return seq_read(file, userbuf, count, ppos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return simple_read_from_buffer(userbuf, count, ppos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ps->record->buf, ps->total_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int pstore_file_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct pstore_private *ps = inode->i_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct seq_file *sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) const struct seq_operations *sops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (ps->record->type == PSTORE_TYPE_FTRACE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) sops = &pstore_ftrace_seq_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) err = seq_open(file, sops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) sf = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) sf->private = ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static loff_t pstore_file_llseek(struct file *file, loff_t off, int whence)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct seq_file *sf = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (sf->op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return seq_lseek(file, off, whence);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return default_llseek(file, off, whence);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static const struct file_operations pstore_file_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .open = pstore_file_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .read = pstore_file_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .llseek = pstore_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .release = seq_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * When a file is unlinked from our file system we call the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * platform driver to erase the record from persistent store.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static int pstore_unlink(struct inode *dir, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct pstore_private *p = d_inode(dentry)->i_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct pstore_record *record = p->record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!record->psi->erase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* Make sure we can't race while removing this file. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) mutex_lock(&records_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (!list_empty(&p->list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) list_del_init(&p->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) rc = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) p->dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) mutex_unlock(&records_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) mutex_lock(&record->psi->read_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) record->psi->erase(record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) mutex_unlock(&record->psi->read_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return simple_unlink(dir, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static void pstore_evict_inode(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct pstore_private *p = inode->i_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) clear_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) free_pstore_private(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static const struct inode_operations pstore_dir_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .lookup = simple_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .unlink = pstore_unlink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static struct inode *pstore_get_inode(struct super_block *sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct inode *inode = new_inode(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (inode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) inode->i_ino = get_next_ino();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) Opt_kmsg_bytes, Opt_err
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static const match_table_t tokens = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {Opt_kmsg_bytes, "kmsg_bytes=%u"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {Opt_err, NULL}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static void parse_options(char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) substring_t args[MAX_OPT_ARGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) while ((p = strsep(&options, ",")) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) int token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!*p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) token = match_token(p, tokens, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) switch (token) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) case Opt_kmsg_bytes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (!match_int(&args[0], &option))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) pstore_set_kmsg_bytes(option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * Display the mount options in /proc/mounts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int pstore_show_options(struct seq_file *m, struct dentry *root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (kmsg_bytes != PSTORE_DEFAULT_KMSG_BYTES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) seq_printf(m, ",kmsg_bytes=%lu", kmsg_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static int pstore_remount(struct super_block *sb, int *flags, char *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) sync_filesystem(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) parse_options(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static const struct super_operations pstore_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .statfs = simple_statfs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .drop_inode = generic_delete_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .evict_inode = pstore_evict_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .remount_fs = pstore_remount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .show_options = pstore_show_options,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static struct dentry *psinfo_lock_root(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct dentry *root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) mutex_lock(&pstore_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * Having no backend is fine -- no records appear.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * Not being mounted is fine -- nothing to do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (!psinfo || !pstore_sb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) mutex_unlock(&pstore_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) root = pstore_sb->s_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) inode_lock(d_inode(root));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) mutex_unlock(&pstore_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) int pstore_put_backend_records(struct pstore_info *psi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct pstore_private *pos, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct dentry *root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) root = psinfo_lock_root();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (!root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) mutex_lock(&records_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) list_for_each_entry_safe(pos, tmp, &records_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (pos->record->psi == psi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) list_del_init(&pos->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) rc = simple_unlink(d_inode(root), pos->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (WARN_ON(rc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) d_drop(pos->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) dput(pos->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) pos->dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) mutex_unlock(&records_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) inode_unlock(d_inode(root));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * Make a regular file in the root directory of our file system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * Load it up with "size" bytes of data from "buf".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * Set the mtime & ctime to the date that this record was originally stored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) int pstore_mkfile(struct dentry *root, struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) char name[PSTORE_NAMELEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct pstore_private *private, *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) size_t size = record->size + record->ecc_notice_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (WARN_ON(!inode_is_locked(d_inode(root))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) rc = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* Skip records that are already present in the filesystem. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) mutex_lock(&records_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) list_for_each_entry(pos, &records_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (pos->record->type == record->type &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) pos->record->id == record->id &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) pos->record->psi == record->psi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) inode = pstore_get_inode(root->d_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) inode->i_mode = S_IFREG | 0444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) inode->i_fop = &pstore_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) scnprintf(name, sizeof(name), "%s-%s-%llu%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) pstore_type_to_name(record->type),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) record->psi->name, record->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) record->compressed ? ".enc.z" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) private = kzalloc(sizeof(*private), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) goto fail_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) dentry = d_alloc_name(root, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (!dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) goto fail_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) private->dentry = dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) private->record = record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) inode->i_size = private->total_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) inode->i_private = private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (record->time.tv_sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) inode->i_mtime = inode->i_ctime = record->time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) d_add(dentry, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) list_add(&private->list, &records_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) mutex_unlock(&records_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) fail_private:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) free_pstore_private(private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) fail_inode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) iput(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) mutex_unlock(&records_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * Read all the records from the persistent store. Create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * files in our filesystem. Don't warn about -EEXIST errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * when we are re-scanning the backing store looking to add new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * error records.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) void pstore_get_records(int quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct dentry *root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) root = psinfo_lock_root();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (!root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) pstore_get_backend_records(psinfo, root, quiet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) inode_unlock(d_inode(root));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static int pstore_fill_super(struct super_block *sb, void *data, int silent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) sb->s_maxbytes = MAX_LFS_FILESIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) sb->s_blocksize = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) sb->s_blocksize_bits = PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) sb->s_magic = PSTOREFS_MAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) sb->s_op = &pstore_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) sb->s_time_gran = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) parse_options(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) inode = pstore_get_inode(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (inode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) inode->i_mode = S_IFDIR | 0750;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) inode->i_op = &pstore_dir_inode_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) inode->i_fop = &simple_dir_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) inc_nlink(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) sb->s_root = d_make_root(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (!sb->s_root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) mutex_lock(&pstore_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) pstore_sb = sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) mutex_unlock(&pstore_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) pstore_get_records(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static struct dentry *pstore_mount(struct file_system_type *fs_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int flags, const char *dev_name, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return mount_single(fs_type, flags, data, pstore_fill_super);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static void pstore_kill_sb(struct super_block *sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) mutex_lock(&pstore_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) WARN_ON(pstore_sb && pstore_sb != sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) kill_litter_super(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) pstore_sb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) mutex_lock(&records_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) INIT_LIST_HEAD(&records_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) mutex_unlock(&records_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) mutex_unlock(&pstore_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static struct file_system_type pstore_fs_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) .name = "pstore",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) .mount = pstore_mount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) .kill_sb = pstore_kill_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) int __init pstore_init_fs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /* Create a convenient mount point for people to access pstore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) err = sysfs_create_mount_point(fs_kobj, "pstore");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) err = register_filesystem(&pstore_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) sysfs_remove_mount_point(fs_kobj, "pstore");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) void __exit pstore_exit_fs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) unregister_filesystem(&pstore_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) sysfs_remove_mount_point(fs_kobj, "pstore");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }