Declare the seq_operations and the size of the session state and let
procfs open and free the seq_file of /proc/fs/jbd2/<dev>/info.
->proc_open() only takes the snapshot of the statistics now and
->proc_release() frees it. Reading the file then no longer holds up its
removal when the journal goes away.

Signed-off-by: Christian Brauner (Amutable) <[email protected]>
---
 fs/jbd2/journal.c | 33 +++++++++------------------------
 1 file changed, 9 insertions(+), 24 deletions(-)

diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 3a4f3f613ead..1e4f4e95a00e 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1173,51 +1173,36 @@ static const struct seq_operations jbd2_seq_info_ops = {
        .show   = jbd2_seq_info_show,
 };
 
+/* procfs opened the seq_file and allocated @s */
 static int jbd2_seq_info_open(struct inode *inode, struct file *file)
 {
        journal_t *journal = pde_data(inode);
-       struct jbd2_stats_proc_session *s;
-       int rc, size;
+       struct jbd2_stats_proc_session *s = ((struct seq_file 
*)file->private_data)->private;
+       int size = sizeof(struct transaction_stats_s);
 
-       s = kmalloc_obj(*s);
-       if (s == NULL)
-               return -ENOMEM;
-       size = sizeof(struct transaction_stats_s);
        s->stats = kmalloc(size, GFP_KERNEL);
-       if (s->stats == NULL) {
-               kfree(s);
+       if (s->stats == NULL)
                return -ENOMEM;
-       }
        spin_lock(&journal->j_history_lock);
        memcpy(s->stats, &journal->j_stats, size);
        s->journal = journal;
        spin_unlock(&journal->j_history_lock);
-
-       rc = seq_open(file, &jbd2_seq_info_ops);
-       if (rc == 0) {
-               struct seq_file *m = file->private_data;
-               m->private = s;
-       } else {
-               kfree(s->stats);
-               kfree(s);
-       }
-       return rc;
-
+       return 0;
 }
 
 static int jbd2_seq_info_release(struct inode *inode, struct file *file)
 {
        struct seq_file *seq = file->private_data;
        struct jbd2_stats_proc_session *s = seq->private;
+
        kfree(s->stats);
-       kfree(s);
-       return seq_release(inode, file);
+       return 0;
 }
 
 static const struct proc_ops jbd2_info_proc_ops = {
+       .proc_seq_ops   = &jbd2_seq_info_ops,
+       .proc_state_size = sizeof(struct jbd2_stats_proc_session),
        .proc_open      = jbd2_seq_info_open,
-       .proc_read      = seq_read,
-       .proc_lseek     = seq_lseek,
        .proc_release   = jbd2_seq_info_release,
 };
 

-- 
2.53.0

Reply via email to