cls_flower.stats.lastused);
 }
 
+static struct cls_fl_head *fl_head_dereference(struct tcf_proto *tp)
+{
+       /* Flower classifier only changes root pointer during init and destroy.
+        * Users must obtain reference to tcf_proto instance before calling its
+        * API, so tp->root pointer is protected from concurrent call to
+        * fl_destroy() by reference counting.
+        */
+       return rcu_dereference_raw(tp->root);
+}
+
 static bool __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f,
                        struct netlink_ext_ack *extack)
 {
-       struct cls_fl_head *head = rtnl_dereference(tp->root);
+       struct cls_fl_head *head = fl_head_dereference(tp);
        bool async = tcf_exts_get_net(&f->exts);
        bool last;
 
 static void fl_destroy(struct tcf_proto *tp, bool rtnl_held,
                       struct netlink_ext_ack *extack)
 {
-       struct cls_fl_head *head = rtnl_dereference(tp->root);
+       struct cls_fl_head *head = fl_head_dereference(tp);
        struct fl_flow_mask *mask, *next_mask;
        struct cls_fl_filter *f, *next;
 
 
 static void *fl_get(struct tcf_proto *tp, u32 handle)
 {
-       struct cls_fl_head *head = rtnl_dereference(tp->root);
+       struct cls_fl_head *head = fl_head_dereference(tp);
 
        return idr_find(&head->handle_idr, handle);
 }
                     void **arg, bool ovr, bool rtnl_held,
                     struct netlink_ext_ack *extack)
 {
-       struct cls_fl_head *head = rtnl_dereference(tp->root);
+       struct cls_fl_head *head = fl_head_dereference(tp);
        struct cls_fl_filter *fold = *arg;
        struct cls_fl_filter *fnew;
        struct fl_flow_mask *mask;
 static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
                     bool rtnl_held, struct netlink_ext_ack *extack)
 {
-       struct cls_fl_head *head = rtnl_dereference(tp->root);
+       struct cls_fl_head *head = fl_head_dereference(tp);
        struct cls_fl_filter *f = arg;
 
        rhashtable_remove_fast(&f->mask->ht, &f->ht_node,
 static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg,
                    bool rtnl_held)
 {
-       struct cls_fl_head *head = rtnl_dereference(tp->root);
+       struct cls_fl_head *head = fl_head_dereference(tp);
        struct cls_fl_filter *f;
 
        arg->count = arg->skip;
 static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
                        void *cb_priv, struct netlink_ext_ack *extack)
 {
-       struct cls_fl_head *head = rtnl_dereference(tp->root);
+       struct cls_fl_head *head = fl_head_dereference(tp);
        struct tc_cls_flower_offload cls_flower = {};
        struct tcf_block *block = tp->chain->block;
        struct fl_flow_mask *mask;