aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c50
1 files changed, 41 insertions, 9 deletions
diff --git a/net/socket.c b/net/socket.c
index 3ca2fd9e3720..ccc576a6a508 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -156,7 +156,7 @@ static const struct file_operations socket_file_ops = {
156 */ 156 */
157 157
158static DEFINE_SPINLOCK(net_family_lock); 158static DEFINE_SPINLOCK(net_family_lock);
159static const struct net_proto_family *net_families[NPROTO] __read_mostly; 159static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
160 160
161/* 161/*
162 * Statistics counters of the socket lists 162 * Statistics counters of the socket lists
@@ -262,6 +262,7 @@ static struct inode *sock_alloc_inode(struct super_block *sb)
262} 262}
263 263
264 264
265
265static void wq_free_rcu(struct rcu_head *head) 266static void wq_free_rcu(struct rcu_head *head)
266{ 267{
267 struct socket_wq *wq = container_of(head, struct socket_wq, rcu); 268 struct socket_wq *wq = container_of(head, struct socket_wq, rcu);
@@ -360,14 +361,14 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
360 if (unlikely(fd < 0)) 361 if (unlikely(fd < 0))
361 return fd; 362 return fd;
362 363
363 path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); 364 path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
364 if (unlikely(!path.dentry)) { 365 if (unlikely(!path.dentry)) {
365 put_unused_fd(fd); 366 put_unused_fd(fd);
366 return -ENOMEM; 367 return -ENOMEM;
367 } 368 }
368 path.mnt = mntget(sock_mnt); 369 path.mnt = mntget(sock_mnt);
369 370
370 path.dentry->d_op = &sockfs_dentry_operations; 371 d_set_d_op(path.dentry, &sockfs_dentry_operations);
371 d_instantiate(path.dentry, SOCK_INODE(sock)); 372 d_instantiate(path.dentry, SOCK_INODE(sock));
372 SOCK_INODE(sock)->i_fop = &socket_file_ops; 373 SOCK_INODE(sock)->i_fop = &socket_file_ops;
373 374
@@ -732,6 +733,21 @@ static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
732 return ret; 733 return ret;
733} 734}
734 735
736/**
737 * kernel_recvmsg - Receive a message from a socket (kernel space)
738 * @sock: The socket to receive the message from
739 * @msg: Received message
740 * @vec: Input s/g array for message data
741 * @num: Size of input s/g array
742 * @size: Number of bytes to read
743 * @flags: Message flags (MSG_DONTWAIT, etc...)
744 *
745 * On return the msg structure contains the scatter/gather array passed in the
746 * vec argument. The array is modified so that it consists of the unfilled
747 * portion of the original array.
748 *
749 * The returned value is the total number of bytes received, or an error.
750 */
735int kernel_recvmsg(struct socket *sock, struct msghdr *msg, 751int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
736 struct kvec *vec, size_t num, size_t size, int flags) 752 struct kvec *vec, size_t num, size_t size, int flags)
737{ 753{
@@ -1200,7 +1216,7 @@ int __sock_create(struct net *net, int family, int type, int protocol,
1200 * requested real, full-featured networking support upon configuration. 1216 * requested real, full-featured networking support upon configuration.
1201 * Otherwise module support will break! 1217 * Otherwise module support will break!
1202 */ 1218 */
1203 if (net_families[family] == NULL) 1219 if (rcu_access_pointer(net_families[family]) == NULL)
1204 request_module("net-pf-%d", family); 1220 request_module("net-pf-%d", family);
1205#endif 1221#endif
1206 1222
@@ -2332,10 +2348,11 @@ int sock_register(const struct net_proto_family *ops)
2332 } 2348 }
2333 2349
2334 spin_lock(&net_family_lock); 2350 spin_lock(&net_family_lock);
2335 if (net_families[ops->family]) 2351 if (rcu_dereference_protected(net_families[ops->family],
2352 lockdep_is_held(&net_family_lock)))
2336 err = -EEXIST; 2353 err = -EEXIST;
2337 else { 2354 else {
2338 net_families[ops->family] = ops; 2355 rcu_assign_pointer(net_families[ops->family], ops);
2339 err = 0; 2356 err = 0;
2340 } 2357 }
2341 spin_unlock(&net_family_lock); 2358 spin_unlock(&net_family_lock);
@@ -2363,7 +2380,7 @@ void sock_unregister(int family)
2363 BUG_ON(family < 0 || family >= NPROTO); 2380 BUG_ON(family < 0 || family >= NPROTO);
2364 2381
2365 spin_lock(&net_family_lock); 2382 spin_lock(&net_family_lock);
2366 net_families[family] = NULL; 2383 rcu_assign_pointer(net_families[family], NULL);
2367 spin_unlock(&net_family_lock); 2384 spin_unlock(&net_family_lock);
2368 2385
2369 synchronize_rcu(); 2386 synchronize_rcu();
@@ -2374,6 +2391,8 @@ EXPORT_SYMBOL(sock_unregister);
2374 2391
2375static int __init sock_init(void) 2392static int __init sock_init(void)
2376{ 2393{
2394 int err;
2395
2377 /* 2396 /*
2378 * Initialize sock SLAB cache. 2397 * Initialize sock SLAB cache.
2379 */ 2398 */
@@ -2390,8 +2409,15 @@ static int __init sock_init(void)
2390 */ 2409 */
2391 2410
2392 init_inodecache(); 2411 init_inodecache();
2393 register_filesystem(&sock_fs_type); 2412
2413 err = register_filesystem(&sock_fs_type);
2414 if (err)
2415 goto out_fs;
2394 sock_mnt = kern_mount(&sock_fs_type); 2416 sock_mnt = kern_mount(&sock_fs_type);
2417 if (IS_ERR(sock_mnt)) {
2418 err = PTR_ERR(sock_mnt);
2419 goto out_mount;
2420 }
2395 2421
2396 /* The real protocol initialization is performed in later initcalls. 2422 /* The real protocol initialization is performed in later initcalls.
2397 */ 2423 */
@@ -2404,7 +2430,13 @@ static int __init sock_init(void)
2404 skb_timestamping_init(); 2430 skb_timestamping_init();
2405#endif 2431#endif
2406 2432
2407 return 0; 2433out:
2434 return err;
2435
2436out_mount:
2437 unregister_filesystem(&sock_fs_type);
2438out_fs:
2439 goto out;
2408} 2440}
2409 2441
2410core_initcall(sock_init); /* early initcall */ 2442core_initcall(sock_init); /* early initcall */