diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-08-17 23:54:15 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-26 21:08:49 -0400 |
commit | 28407630513b1a86133db0ef8b39fabad6c494af (patch) | |
tree | e7b44dc7d4690eb9f66dab7042a66fe04af2e61b /net/socket.c | |
parent | 5905db5ca0ac9a6d5bfe87f86b87cd1bdec3755a (diff) |
take descriptor handling from sock_alloc_file() to callers
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 62 |
1 files changed, 40 insertions, 22 deletions
diff --git a/net/socket.c b/net/socket.c index edc3c4af9085..a14ec19164b6 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -346,22 +346,15 @@ static struct file_system_type sock_fs_type = { | |||
346 | * but we take care of internal coherence yet. | 346 | * but we take care of internal coherence yet. |
347 | */ | 347 | */ |
348 | 348 | ||
349 | static int sock_alloc_file(struct socket *sock, struct file **f, int flags) | 349 | static struct file *sock_alloc_file(struct socket *sock, int flags) |
350 | { | 350 | { |
351 | struct qstr name = { .name = "" }; | 351 | struct qstr name = { .name = "" }; |
352 | struct path path; | 352 | struct path path; |
353 | struct file *file; | 353 | struct file *file; |
354 | int fd; | ||
355 | |||
356 | fd = get_unused_fd_flags(flags); | ||
357 | if (unlikely(fd < 0)) | ||
358 | return fd; | ||
359 | 354 | ||
360 | path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); | 355 | path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); |
361 | if (unlikely(!path.dentry)) { | 356 | if (unlikely(!path.dentry)) |
362 | put_unused_fd(fd); | 357 | return ERR_PTR(-ENOMEM); |
363 | return -ENOMEM; | ||
364 | } | ||
365 | path.mnt = mntget(sock_mnt); | 358 | path.mnt = mntget(sock_mnt); |
366 | 359 | ||
367 | d_instantiate(path.dentry, SOCK_INODE(sock)); | 360 | d_instantiate(path.dentry, SOCK_INODE(sock)); |
@@ -373,28 +366,31 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags) | |||
373 | /* drop dentry, keep inode */ | 366 | /* drop dentry, keep inode */ |
374 | ihold(path.dentry->d_inode); | 367 | ihold(path.dentry->d_inode); |
375 | path_put(&path); | 368 | path_put(&path); |
376 | put_unused_fd(fd); | 369 | return ERR_PTR(-ENFILE); |
377 | return -ENFILE; | ||
378 | } | 370 | } |
379 | 371 | ||
380 | sock->file = file; | 372 | sock->file = file; |
381 | file->f_flags = O_RDWR | (flags & O_NONBLOCK); | 373 | file->f_flags = O_RDWR | (flags & O_NONBLOCK); |
382 | file->f_pos = 0; | 374 | file->f_pos = 0; |
383 | file->private_data = sock; | 375 | file->private_data = sock; |
384 | 376 | return file; | |
385 | *f = file; | ||
386 | return fd; | ||
387 | } | 377 | } |
388 | 378 | ||
389 | int sock_map_fd(struct socket *sock, int flags) | 379 | int sock_map_fd(struct socket *sock, int flags) |
390 | { | 380 | { |
391 | struct file *newfile; | 381 | struct file *newfile; |
392 | int fd = sock_alloc_file(sock, &newfile, flags); | 382 | int fd = get_unused_fd_flags(flags); |
383 | if (unlikely(fd < 0)) | ||
384 | return fd; | ||
393 | 385 | ||
394 | if (likely(fd >= 0)) | 386 | newfile = sock_alloc_file(sock, flags); |
387 | if (likely(!IS_ERR(newfile))) { | ||
395 | fd_install(fd, newfile); | 388 | fd_install(fd, newfile); |
389 | return fd; | ||
390 | } | ||
396 | 391 | ||
397 | return fd; | 392 | put_unused_fd(fd); |
393 | return PTR_ERR(newfile); | ||
398 | } | 394 | } |
399 | EXPORT_SYMBOL(sock_map_fd); | 395 | EXPORT_SYMBOL(sock_map_fd); |
400 | 396 | ||
@@ -1394,17 +1390,32 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, | |||
1394 | if (err < 0) | 1390 | if (err < 0) |
1395 | goto out_release_both; | 1391 | goto out_release_both; |
1396 | 1392 | ||
1397 | fd1 = sock_alloc_file(sock1, &newfile1, flags); | 1393 | fd1 = get_unused_fd_flags(flags); |
1398 | if (unlikely(fd1 < 0)) { | 1394 | if (unlikely(fd1 < 0)) { |
1399 | err = fd1; | 1395 | err = fd1; |
1400 | goto out_release_both; | 1396 | goto out_release_both; |
1401 | } | 1397 | } |
1402 | 1398 | fd2 = get_unused_fd_flags(flags); | |
1403 | fd2 = sock_alloc_file(sock2, &newfile2, flags); | ||
1404 | if (unlikely(fd2 < 0)) { | 1399 | if (unlikely(fd2 < 0)) { |
1405 | err = fd2; | 1400 | err = fd2; |
1401 | put_unused_fd(fd1); | ||
1402 | goto out_release_both; | ||
1403 | } | ||
1404 | |||
1405 | newfile1 = sock_alloc_file(sock1, flags); | ||
1406 | if (unlikely(IS_ERR(newfile1))) { | ||
1407 | err = PTR_ERR(newfile1); | ||
1408 | put_unused_fd(fd1); | ||
1409 | put_unused_fd(fd2); | ||
1410 | goto out_release_both; | ||
1411 | } | ||
1412 | |||
1413 | newfile2 = sock_alloc_file(sock2, flags); | ||
1414 | if (IS_ERR(newfile2)) { | ||
1415 | err = PTR_ERR(newfile2); | ||
1406 | fput(newfile1); | 1416 | fput(newfile1); |
1407 | put_unused_fd(fd1); | 1417 | put_unused_fd(fd1); |
1418 | put_unused_fd(fd2); | ||
1408 | sock_release(sock2); | 1419 | sock_release(sock2); |
1409 | goto out; | 1420 | goto out; |
1410 | } | 1421 | } |
@@ -1536,12 +1547,19 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, | |||
1536 | */ | 1547 | */ |
1537 | __module_get(newsock->ops->owner); | 1548 | __module_get(newsock->ops->owner); |
1538 | 1549 | ||
1539 | newfd = sock_alloc_file(newsock, &newfile, flags); | 1550 | newfd = get_unused_fd_flags(flags); |
1540 | if (unlikely(newfd < 0)) { | 1551 | if (unlikely(newfd < 0)) { |
1541 | err = newfd; | 1552 | err = newfd; |
1542 | sock_release(newsock); | 1553 | sock_release(newsock); |
1543 | goto out_put; | 1554 | goto out_put; |
1544 | } | 1555 | } |
1556 | newfile = sock_alloc_file(newsock, flags); | ||
1557 | if (unlikely(IS_ERR(newfile))) { | ||
1558 | err = PTR_ERR(newfile); | ||
1559 | put_unused_fd(newfd); | ||
1560 | sock_release(newsock); | ||
1561 | goto out_put; | ||
1562 | } | ||
1545 | 1563 | ||
1546 | err = security_socket_accept(sock, newsock); | 1564 | err = security_socket_accept(sock, newsock); |
1547 | if (err) | 1565 | if (err) |