@@ -288,9 +288,14 @@ static const struct super_operations pstore_ops = {
.show_options = pstore_show_options,
};
-static struct dentry *psinfo_lock_root(struct pstore_info *psinfo)
+static struct dentry *psinfo_lock(struct pstore_info *psinfo)
{
- struct dentry *root;
+ struct dentry *dentry;
+ struct qstr qname;
+
+ qname.name = psinfo->name;
+ qname.len = strlen(psinfo->name);
+ qname.hash = full_name_hash(pstore_sb->s_root, qname.name, qname.len);
mutex_lock(&pstore_sb_lock);
/*
@@ -302,11 +307,16 @@ static struct dentry *psinfo_lock_root(struct pstore_info *psinfo)
return NULL;
}
- root = pstore_sb->s_root;
- inode_lock(d_inode(root));
+ dentry = d_lookup(pstore_sb->s_root, &qname);
+ if (!dentry) {
+ mutex_unlock(&pstore_sb_lock);
+ return NULL;
+ }
+
+ inode_lock(d_inode(dentry));
mutex_unlock(&pstore_sb_lock);
- return root;
+ return dentry;
}
int pstore_put_backend_records(struct pstore_info *psi)
@@ -315,7 +325,7 @@ int pstore_put_backend_records(struct pstore_info *psi)
struct dentry *root;
int rc = 0;
- root = psinfo_lock_root(psi);
+ root = psinfo_lock(psi);
if (!root)
return 0;
@@ -416,14 +426,60 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
*/
void pstore_get_records(struct pstore_info *psi, int pos, int quiet)
{
+ struct dentry *dentry;
+
+ dentry = psinfo_lock(psi);
+ if (!dentry)
+ return;
+
+ pstore_get_backend_records(psi, dentry, quiet, pos);
+ inode_unlock(d_inode(dentry));
+}
+
+void pstore_mksubdir(struct pstore_info *psi)
+{
+ struct dentry *dentry;
+ struct inode *inode;
struct dentry *root;
+ struct qstr qname;
- root = psinfo_lock_root(psi);
- if (!root)
+ if (!psi || !pstore_sb)
+ return;
+
+ root = pstore_sb->s_root;
+ qname.name = psi->name;
+ qname.len = strlen(psi->name);
+ qname.hash = full_name_hash(root, qname.name, qname.len);
+ dentry = d_lookup(root, &qname);
+
+ /* Skip if subdir is already present in the filesystem. */
+ if (dentry)
return;
- pstore_get_backend_records(psi, root, quiet, pos);
+ inode_lock(d_inode(root));
+
+ dentry = d_alloc_name(root, psi->name);
+ if (!dentry)
+ goto fail;
+
+ inode = pstore_get_inode(pstore_sb);
+ if (!inode) {
+ dput(dentry);
+ dentry = ERR_PTR(-ENOMEM);
+ goto fail;
+ }
+ inode->i_mode = S_IFDIR | 0750;
+ inode->i_op = &pstore_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+
+ inc_nlink(inode);
+ inc_nlink(d_inode(root));
+
+ d_add(dentry, inode);
+
+fail:
inode_unlock(d_inode(root));
+ return;
}
static int pstore_fill_super(struct super_block *sb, void *data, int silent)
@@ -456,10 +512,14 @@ static int pstore_fill_super(struct super_block *sb, void *data, int silent)
mutex_unlock(&pstore_sb_lock);
rcu_read_lock();
- list_for_each_entry_rcu(entry, &psback->list_entry, list)
+ list_for_each_entry_rcu(entry, &psback->list_entry, list) {
+ pstore_mksubdir(entry->psi);
pstore_get_records(entry->psi, entry->index, 0);
+ }
rcu_read_unlock();
+ psback->fs_ready = true;
+
return 0;
}
@@ -44,6 +44,7 @@ static inline void pstore_unregister_tty(void) {}
extern struct pstore_backends *psback;
extern void pstore_set_kmsg_bytes(int);
+extern void pstore_mksubdir(struct pstore_info *psi);
extern void pstore_get_records(struct pstore_info *psi, int pos,
int quiet);
extern void pstore_get_backend_records(struct pstore_info *psi,
@@ -652,7 +652,10 @@ int pstore_register(struct pstore_info *psi)
if (psi->flags & PSTORE_FLAGS_DMESG && !psback->front_cnt[PSTORE_TYPE_DMESG])
allocate_buf_for_compression(psi, newpsi->index);
- pstore_get_records(psi, newpsi->index, 0);
+ if (psback->fs_ready) {
+ pstore_mksubdir(psi);
+ pstore_get_records(psi, newpsi->index, 0);
+ }
list_add_rcu(&newpsi->list, &psback->list_entry);
@@ -220,6 +220,7 @@ struct pstore_info_list {
* @list_entry: entry of pstore backend driver information list
* @front_cnt: count of each enabled frontend
* @flag: bitmap of enabled pstore backend
+ * @fs_ready: whether the pstore filesystem is ready
*
*/
@@ -227,6 +228,7 @@ struct pstore_backends {
struct list_head list_entry;
int front_cnt[PSTORE_TYPE_MAX];
u16 flag;
+ bool fs_ready;
};
/* Supported frontends */