diff options
Diffstat (limited to 'net/unix/garbage.c')
| -rw-r--r-- | net/unix/garbage.c | 70 | 
1 files changed, 28 insertions, 42 deletions
| diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 99f7012b23b9..a73a226f2d33 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -95,39 +95,36 @@ static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait);  unsigned int unix_tot_inflight; -  struct sock *unix_get_socket(struct file *filp)  {  	struct sock *u_sock = NULL;  	struct inode *inode = file_inode(filp); -	/* -	 *	Socket ? -	 */ +	/* Socket ? */  	if (S_ISSOCK(inode->i_mode) && !(filp->f_mode & FMODE_PATH)) {  		struct socket *sock = SOCKET_I(inode);  		struct sock *s = sock->sk; -		/* -		 *	PF_UNIX ? -		 */ +		/* PF_UNIX ? */  		if (s && sock->ops && sock->ops->family == PF_UNIX)  			u_sock = s;  	}  	return u_sock;  } -/* - *	Keep the number of times in flight count for the file - *	descriptor if it is for an AF_UNIX socket. +/* Keep the number of times in flight count for the file + * descriptor if it is for an AF_UNIX socket.   */  void unix_inflight(struct file *fp)  {  	struct sock *s = unix_get_socket(fp); +  	if (s) {  		struct unix_sock *u = unix_sk(s); +  		spin_lock(&unix_gc_lock); +  		if (atomic_long_inc_return(&u->inflight) == 1) {  			BUG_ON(!list_empty(&u->link));  			list_add_tail(&u->link, &gc_inflight_list); @@ -142,10 +139,13 @@ void unix_inflight(struct file *fp)  void unix_notinflight(struct file *fp)  {  	struct sock *s = unix_get_socket(fp); +  	if (s) {  		struct unix_sock *u = unix_sk(s); +  		spin_lock(&unix_gc_lock);  		BUG_ON(list_empty(&u->link)); +  		if (atomic_long_dec_and_test(&u->inflight))  			list_del_init(&u->link);  		unix_tot_inflight--; @@ -161,32 +161,27 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),  	spin_lock(&x->sk_receive_queue.lock);  	skb_queue_walk_safe(&x->sk_receive_queue, skb, next) { -		/* -		 *	Do we have file descriptors ? -		 */ +		/* Do we have file descriptors ? */  		if (UNIXCB(skb).fp) {  			bool hit = false; -			/* -			 *	Process the descriptors of this socket -			 */ +			/* Process the descriptors of this socket */  			int nfd = UNIXCB(skb).fp->count;  			struct file **fp = UNIXCB(skb).fp->fp; +  			while (nfd--) { -				/* -				 *	Get the socket the fd matches -				 *	if it indeed does so -				 */ +				/* Get the socket the fd matches if it indeed does so */  				struct sock *sk = unix_get_socket(*fp++); +  				if (sk) {  					struct unix_sock *u = unix_sk(sk); -					/* -					 * Ignore non-candidates, they could +					/* Ignore non-candidates, they could  					 * have been added to the queues after  					 * starting the garbage collection  					 */  					if (test_bit(UNIX_GC_CANDIDATE, &u->gc_flags)) {  						hit = true; +  						func(u);  					}  				} @@ -203,24 +198,22 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),  static void scan_children(struct sock *x, void (*func)(struct unix_sock *),  			  struct sk_buff_head *hitlist)  { -	if (x->sk_state != TCP_LISTEN) +	if (x->sk_state != TCP_LISTEN) {  		scan_inflight(x, func, hitlist); -	else { +	} else {  		struct sk_buff *skb;  		struct sk_buff *next;  		struct unix_sock *u;  		LIST_HEAD(embryos); -		/* -		 * For a listening socket collect the queued embryos +		/* For a listening socket collect the queued embryos  		 * and perform a scan on them as well.  		 */  		spin_lock(&x->sk_receive_queue.lock);  		skb_queue_walk_safe(&x->sk_receive_queue, skb, next) {  			u = unix_sk(skb->sk); -			/* -			 * An embryo cannot be in-flight, so it's safe +			/* An embryo cannot be in-flight, so it's safe  			 * to use the list link.  			 */  			BUG_ON(!list_empty(&u->link)); @@ -249,8 +242,7 @@ static void inc_inflight(struct unix_sock *usk)  static void inc_inflight_move_tail(struct unix_sock *u)  {  	atomic_long_inc(&u->inflight); -	/* -	 * If this still might be part of a cycle, move it to the end +	/* If this still might be part of a cycle, move it to the end  	 * of the list, so that it's checked even if it was already  	 * passed over  	 */ @@ -263,8 +255,7 @@ static bool gc_in_progress;  void wait_for_unix_gc(void)  { -	/* -	 * If number of inflight sockets is insane, +	/* If number of inflight sockets is insane,  	 * force a garbage collect right now.  	 */  	if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress) @@ -288,8 +279,7 @@ void unix_gc(void)  		goto out;  	gc_in_progress = true; -	/* -	 * First, select candidates for garbage collection.  Only +	/* First, select candidates for garbage collection.  Only  	 * in-flight sockets are considered, and from those only ones  	 * which don't have any external reference.  	 * @@ -320,15 +310,13 @@ void unix_gc(void)  		}  	} -	/* -	 * Now remove all internal in-flight reference to children of +	/* Now remove all internal in-flight reference to children of  	 * the candidates.  	 */  	list_for_each_entry(u, &gc_candidates, link)  		scan_children(&u->sk, dec_inflight, NULL); -	/* -	 * Restore the references for children of all candidates, +	/* Restore the references for children of all candidates,  	 * which have remaining references.  Do this recursively, so  	 * only those remain, which form cyclic references.  	 * @@ -350,8 +338,7 @@ void unix_gc(void)  	}  	list_del(&cursor); -	/* -	 * not_cycle_list contains those sockets which do not make up a +	/* not_cycle_list contains those sockets which do not make up a  	 * cycle.  Restore these to the inflight list.  	 */  	while (!list_empty(¬_cycle_list)) { @@ -360,8 +347,7 @@ void unix_gc(void)  		list_move_tail(&u->link, &gc_inflight_list);  	} -	/* -	 * Now gc_candidates contains only garbage.  Restore original +	/* Now gc_candidates contains only garbage.  Restore original  	 * inflight counters for these as well, and remove the skbuffs  	 * which are creating the cycle(s).  	 */ | 
