6868/* let's not notify more than 100 times per second */
6969#define CGROUP_FILE_NOTIFY_MIN_INTV DIV_ROUND_UP(HZ, 100)
7070
71- /*
72- * To avoid confusing the compiler (and generating warnings) with code
73- * that attempts to access what would be a 0-element array (i.e. sized
74- * to a potentially empty array when CGROUP_SUBSYS_COUNT == 0), this
75- * constant expression can be added.
76- */
77- #define CGROUP_HAS_SUBSYS_CONFIG (CGROUP_SUBSYS_COUNT > 0)
78-
7971/*
8072 * cgroup_mutex is the master lock. Any modification to cgroup or its
8173 * hierarchy must be performed while holding it.
@@ -107,12 +99,6 @@ static bool cgroup_debug __read_mostly;
10799 */
108100static DEFINE_SPINLOCK (cgroup_idr_lock );
109101
110- /*
111- * Protects cgroup_file->kn for !self csses. It synchronizes notifications
112- * against file removal/re-creation across css hiding.
113- */
114- static DEFINE_SPINLOCK (cgroup_file_kn_lock );
115-
116102DEFINE_PERCPU_RWSEM (cgroup_threadgroup_rwsem );
117103
118104#define cgroup_assert_mutex_or_rcu_locked () \
@@ -509,27 +495,6 @@ static u32 cgroup_ss_mask(struct cgroup *cgrp)
509495 return cgrp -> root -> subsys_mask ;
510496}
511497
512- /**
513- * cgroup_css - obtain a cgroup's css for the specified subsystem
514- * @cgrp: the cgroup of interest
515- * @ss: the subsystem of interest (%NULL returns @cgrp->self)
516- *
517- * Return @cgrp's css (cgroup_subsys_state) associated with @ss. This
518- * function must be called either under cgroup_mutex or rcu_read_lock() and
519- * the caller is responsible for pinning the returned css if it wants to
520- * keep accessing it outside the said locks. This function may return
521- * %NULL if @cgrp doesn't have @subsys_id enabled.
522- */
523- static struct cgroup_subsys_state * cgroup_css (struct cgroup * cgrp ,
524- struct cgroup_subsys * ss )
525- {
526- if (CGROUP_HAS_SUBSYS_CONFIG && ss )
527- return rcu_dereference_check (cgrp -> subsys [ss -> id ],
528- lockdep_is_held (& cgroup_mutex ));
529- else
530- return & cgrp -> self ;
531- }
532-
533498/**
534499 * cgroup_e_css_by_mask - obtain a cgroup's effective css for the specified ss
535500 * @cgrp: the cgroup of interest
@@ -741,32 +706,6 @@ EXPORT_SYMBOL_GPL(of_css);
741706 } \
742707} while (false)
743708
744- /* iterate over child cgrps, lock should be held throughout iteration */
745- #define cgroup_for_each_live_child (child , cgrp ) \
746- list_for_each_entry((child), &(cgrp)->self.children, self.sibling) \
747- if (({ lockdep_assert_held(&cgroup_mutex); \
748- cgroup_is_dead(child); })) \
749- ; \
750- else
751-
752- /* walk live descendants in pre order */
753- #define cgroup_for_each_live_descendant_pre (dsct , d_css , cgrp ) \
754- css_for_each_descendant_pre((d_css), cgroup_css((cgrp), NULL)) \
755- if (({ lockdep_assert_held(&cgroup_mutex); \
756- (dsct) = (d_css)->cgroup; \
757- cgroup_is_dead(dsct); })) \
758- ; \
759- else
760-
761- /* walk live descendants in postorder */
762- #define cgroup_for_each_live_descendant_post (dsct , d_css , cgrp ) \
763- css_for_each_descendant_post((d_css), cgroup_css((cgrp), NULL)) \
764- if (({ lockdep_assert_held(&cgroup_mutex); \
765- (dsct) = (d_css)->cgroup; \
766- cgroup_is_dead(dsct); })) \
767- ; \
768- else
769-
770709/*
771710 * The default css_set - used by init and its children prior to any
772711 * hierarchies being mounted. It contains a pointer to the root state
@@ -1748,9 +1687,9 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft)
17481687 struct cgroup_subsys_state * css = cgroup_css (cgrp , cft -> ss );
17491688 struct cgroup_file * cfile = (void * )css + cft -> file_offset ;
17501689
1751- spin_lock_irq (& cgroup_file_kn_lock );
1752- cfile -> kn = NULL ;
1753- spin_unlock_irq (& cgroup_file_kn_lock );
1690+ spin_lock_irq (& cfile -> lock );
1691+ WRITE_ONCE ( cfile -> kn , NULL ) ;
1692+ spin_unlock_irq (& cfile -> lock );
17541693
17551694 timer_delete_sync (& cfile -> notify_timer );
17561695 }
@@ -4429,10 +4368,8 @@ static int cgroup_add_file(struct cgroup_subsys_state *css, struct cgroup *cgrp,
44294368 struct cgroup_file * cfile = (void * )css + cft -> file_offset ;
44304369
44314370 timer_setup (& cfile -> notify_timer , cgroup_file_notify_timer , 0 );
4432-
4433- spin_lock_irq (& cgroup_file_kn_lock );
4371+ spin_lock_init (& cfile -> lock );
44344372 cfile -> kn = kn ;
4435- spin_unlock_irq (& cgroup_file_kn_lock );
44364373 }
44374374
44384375 return 0 ;
@@ -4687,21 +4624,32 @@ int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
46874624 */
46884625void cgroup_file_notify (struct cgroup_file * cfile )
46894626{
4690- unsigned long flags ;
4627+ unsigned long flags , last , next ;
4628+ struct kernfs_node * kn = NULL ;
46914629
4692- spin_lock_irqsave (& cgroup_file_kn_lock , flags );
4630+ if (!READ_ONCE (cfile -> kn ))
4631+ return ;
4632+
4633+ last = READ_ONCE (cfile -> notified_at );
4634+ next = last + CGROUP_FILE_NOTIFY_MIN_INTV ;
4635+ if (time_in_range (jiffies , last , next )) {
4636+ timer_reduce (& cfile -> notify_timer , next );
4637+ if (timer_pending (& cfile -> notify_timer ))
4638+ return ;
4639+ }
4640+
4641+ spin_lock_irqsave (& cfile -> lock , flags );
46934642 if (cfile -> kn ) {
4694- unsigned long last = cfile -> notified_at ;
4695- unsigned long next = last + CGROUP_FILE_NOTIFY_MIN_INTV ;
4643+ kn = cfile -> kn ;
4644+ kernfs_get (kn );
4645+ WRITE_ONCE (cfile -> notified_at , jiffies );
4646+ }
4647+ spin_unlock_irqrestore (& cfile -> lock , flags );
46964648
4697- if (time_in_range (jiffies , last , next )) {
4698- timer_reduce (& cfile -> notify_timer , next );
4699- } else {
4700- kernfs_notify (cfile -> kn );
4701- cfile -> notified_at = jiffies ;
4702- }
4649+ if (kn ) {
4650+ kernfs_notify (kn );
4651+ kernfs_put (kn );
47034652 }
4704- spin_unlock_irqrestore (& cgroup_file_kn_lock , flags );
47054653}
47064654EXPORT_SYMBOL_GPL (cgroup_file_notify );
47074655
@@ -4714,10 +4662,10 @@ void cgroup_file_show(struct cgroup_file *cfile, bool show)
47144662{
47154663 struct kernfs_node * kn ;
47164664
4717- spin_lock_irq (& cgroup_file_kn_lock );
4665+ spin_lock_irq (& cfile -> lock );
47184666 kn = cfile -> kn ;
47194667 kernfs_get (kn );
4720- spin_unlock_irq (& cgroup_file_kn_lock );
4668+ spin_unlock_irq (& cfile -> lock );
47214669
47224670 if (kn )
47234671 kernfs_show (kn , show );
0 commit comments