diff options
author | Richard Braun <rbraun@sceen.net> | 2013-10-18 01:16:08 +0200 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2013-10-18 01:16:08 +0200 |
commit | 5ab5d98fa515cd19a64e8d5868fcbae85eec9dc5 (patch) | |
tree | 62f7b074c7f23216b049e4fa517e75591a0d6cb4 /libdiskfs | |
parent | 4660ac02b9723380b4581b4c6a46e54861b95059 (diff) |
libdiskfs: fix removal of socket nodes
When the file system supports ifsock shortcuts, a socket node can obtain
a right on a socket address. This reference is only lost if the address
is destroyed, through a dead-name notification. On the other hand,
pflocal keeps the address around until all references are dropped. This
leads to a situation where socket nodes, addresses, and their associated
sockets are leaked. To remedy the situation, make addresses get a light
reference on socket nodes, and properly deallocate it when the node is
destroyed, which will in turn make pflocal correctly remove the matching
address and socket.
* libdiskfs/ifsock.c (diskfs_S_ifsock_getsockaddr): Add a light reference
instead of a hard one.
* libdiskfs/node-nput.c (diskfs_nput): Deallocate right to socket address
when cleaning light references.
Diffstat (limited to 'libdiskfs')
-rw-r--r-- | libdiskfs/ifsock.c | 2 | ||||
-rw-r--r-- | libdiskfs/node-nput.c | 6 |
2 files changed, 7 insertions, 1 deletions
diff --git a/libdiskfs/ifsock.c b/libdiskfs/ifsock.c index 9199fdf6..01a9b1ea 100644 --- a/libdiskfs/ifsock.c +++ b/libdiskfs/ifsock.c @@ -121,7 +121,7 @@ diskfs_S_ifsock_getsockaddr (struct protid *cred, if (old != MACH_PORT_NULL) mach_port_deallocate (mach_task_self (), old); np->sockaddr = sockaddr; - diskfs_nref (np); + diskfs_nref_light (np); } } diff --git a/libdiskfs/node-nput.c b/libdiskfs/node-nput.c index 35f05b5d..5043ad1a 100644 --- a/libdiskfs/node-nput.c +++ b/libdiskfs/node-nput.c @@ -56,6 +56,12 @@ diskfs_nput (struct node *np) np->references++; pthread_spin_unlock (&diskfs_node_refcnt_lock); + if (np->sockaddr != MACH_PORT_NULL) + { + mach_port_deallocate (mach_task_self (), np->sockaddr); + np->sockaddr = MACH_PORT_NULL; + } + diskfs_try_dropping_softrefs (np); /* But there's no value in looping forever in this |