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--;
		spin_unlock(&unix_gc_lock);
	}
}
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);
		} else {
			BUG_ON(list_empty(&u->link));
		}
		unix_tot_inflight++;
		spin_unlock(&unix_gc_lock);
	}
}
static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
			  struct sk_buff_head *hitlist)
{
	struct sk_buff *skb;
	struct sk_buff *next;

	spin_lock(&x->sk_receive_queue.lock);
	receive_queue_for_each_skb(x, next, skb) {
		/*
		 *	Do we have file descriptors ?
		 */
		if (UNIXCB(skb).fp) {
			bool hit = false;
			/*
			 *	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
				 */
				struct sock *sk = unix_get_socket(*fp++);
				if (sk) {
					struct unix_sock *u = unix_sk(sk);

					/*
					 * Ignore non-candidates, they could
					 * have been added to the queues after
					 * starting the garbage collection
					 */
					if (u->gc_candidate) {
						hit = true;
						func(u);
					}
				}
			}
			if (hit && hitlist != NULL) {
				__skb_unlink(skb, &x->sk_receive_queue);
				__skb_queue_tail(hitlist, skb);
			}
		}
	}
	spin_unlock(&x->sk_receive_queue.lock);
}
static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
			  struct sk_buff_head *hitlist)
{
	struct sk_buff *skb;
	struct sk_buff *next;

	spin_lock(&x->sk_receive_queue.lock);
	receive_queue_for_each_skb(x, next, skb) {
		/*
		 *	Do we have file descriptors ?
		 */
		if (UNIXCB(skb).fp) {
			bool hit = false;
			/*
			 *	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
				 */
				struct sock *sk = unix_get_socket(*fp++);
				if (sk) {
					hit = true;
					func(unix_sk(sk));
				}
			}
			if (hit && hitlist != NULL) {
				__skb_unlink(skb, &x->sk_receive_queue);
				__skb_queue_tail(hitlist, skb);
			}
		}
	}
	spin_unlock(&x->sk_receive_queue.lock);
}
Beispiel #5
0
void unix_notinflight(struct file *fp)
{
	unix_socket *s=unix_get_socket(fp);
	if(s)
		s->protinfo.af_unix.inflight--;
}
Beispiel #6
0
void unix_gc(void)
{
	static int in_unix_gc=0;
	unix_socket *s;
	unix_socket *next;
	
	/*
	 *	Avoid a recursive GC.
	 */

	if(in_unix_gc)
		return;
	in_unix_gc=1;
	
	stack=(unix_socket **)get_free_page(GFP_KERNEL);
	
	/*
	 *	Assume everything is now unmarked 
	 */

	/* Invariant to be maintained:
		- everything marked is either:
		-- (a) on the stack, or
		-- (b) has all of its children marked
		- everything on the stack is always marked
		- nothing is ever pushed onto the stack twice, because:
		-- nothing previously marked is ever pushed on the stack
	 */

	/*
	 *	Push root set
	 */

	for(s=unix_socket_list;s!=NULL;s=s->next)
	{
		/*
		 *	If all instances of the descriptor are not
		 *	in flight we are in use.
		 */
		if(s->socket && s->socket->file && s->socket->file->f_count > s->protinfo.af_unix.inflight)
			maybe_mark_and_push(s);
	}

	/*
	 *	Mark phase 
	 */

	while (!empty_stack())
	{
		unix_socket *x = pop_stack();
		unix_socket *f=NULL,*sk;
		struct sk_buff *skb;
tail:		
		skb=skb_peek(&x->receive_queue);
		
		/*
		 *	Loop through all but first born 
		 */
		
		while(skb && skb != (struct sk_buff *)&x->receive_queue)
		{
			/*
			 *	Do we have file descriptors ?
			 */
			if(skb->h.filp)
			{
				/*
				 *	Process the descriptors of this socket
				 */
				int nfd=*(int *)skb->h.filp;
				struct file **fp=(struct file **)(skb->h.filp+sizeof(int));
				while(nfd--)
				{
					/*
					 *	Get the socket the fd matches if
					 *	it indeed does so
					 */
					if((sk=unix_get_socket(*fp++))!=NULL)
					{
						/*
						 *	Remember the first, mark the
						 *	rest.
						 */
						if(f==NULL)
							f=sk;
						else
							maybe_mark_and_push(sk);
					}
				}
			}
			skb=skb->next;
		}
		/*
		 *	Handle first born specially 
		 */

		if (f) 
		{
			if (!(f->protinfo.af_unix.marksweep&MARKED))
			{
				f->protinfo.af_unix.marksweep|=MARKED;
				x=f;
				f=NULL;
				goto tail;
			}
		}
	}

	/*
	 *	Sweep phase.  NOTE: this part dominates the time complexity 
	 */

	for(s=unix_socket_list;s!=NULL;s=next)
	{
		next=s->next;
		if (!(s->protinfo.af_unix.marksweep&MARKED))
		{
			/*
			 *	We exist only in the passing tree of sockets
			 *	that is no longer connected to active descriptors
			 *	Time to die..
			 *
			 *	Subtle item: We will correctly sweep out the
			 *	socket that has just been closed by the user.
			 *	We must not close this as we are in the middle
			 *	of its close at this moment. Skip that file
			 *	using f_count==0 to spot it.
			 */
			 
			if(s->socket && s->socket->file && s->socket->file->f_count)
				close_fp(s->socket->file);
		}
		else
			s->protinfo.af_unix.marksweep&=~MARKED;	/* unmark everything for next collection */
	}
	
	in_unix_gc=0;
	
	free_page((long)stack);
}