IB/qib: Correct reference counting in debugfs qp_stats
authorMike Marciniszyn <mike.marciniszyn@intel.com>
Fri, 19 Sep 2014 12:32:19 +0000 (08:32 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 5 Oct 2014 21:52:22 +0000 (14:52 -0700)
commit 85cbb7c728bf39c45a9789b88c9471c0d7a58b0e upstream.

This particular reference count is not needed with the rcu protection,
and the current code leaks a reference count, causing a hang in
qib_qp_destroy().

Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/infiniband/hw/qib/qib_debugfs.c
drivers/infiniband/hw/qib/qib_qp.c

index 799a0c3..6abd3ed 100644 (file)
@@ -193,6 +193,7 @@ static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos)
        struct qib_qp_iter *iter;
        loff_t n = *pos;
 
+       rcu_read_lock();
        iter = qib_qp_iter_init(s->private);
        if (!iter)
                return NULL;
@@ -224,7 +225,7 @@ static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr,
 
 static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr)
 {
-       /* nothing for now */
+       rcu_read_unlock();
 }
 
 static int _qp_stats_seq_show(struct seq_file *s, void *iter_ptr)
index 0cad0c4..6a71b2b 100644 (file)
@@ -1324,7 +1324,6 @@ int qib_qp_iter_next(struct qib_qp_iter *iter)
        struct qib_qp *pqp = iter->qp;
        struct qib_qp *qp;
 
-       rcu_read_lock();
        for (; n < dev->qp_table_size; n++) {
                if (pqp)
                        qp = rcu_dereference(pqp->next);
@@ -1332,18 +1331,11 @@ int qib_qp_iter_next(struct qib_qp_iter *iter)
                        qp = rcu_dereference(dev->qp_table[n]);
                pqp = qp;
                if (qp) {
-                       if (iter->qp)
-                               atomic_dec(&iter->qp->refcount);
-                       atomic_inc(&qp->refcount);
-                       rcu_read_unlock();
                        iter->qp = qp;
                        iter->n = n;
                        return 0;
                }
        }
-       rcu_read_unlock();
-       if (iter->qp)
-               atomic_dec(&iter->qp->refcount);
        return ret;
 }