📄 sock.c
字号:
/* * linux/fs/nfs/sock.c * * Copyright (C) 1992, 1993 Rick Sladkey * * low-level nfs remote procedure call interface */#include <linux/config.h>#include <linux/sched.h>#include <linux/nfs_fs.h>#include <linux/errno.h>#include <linux/socket.h>#include <linux/fcntl.h>#include <asm/segment.h>#include <linux/in.h>#include <linux/net.h>extern struct socket *socki_lookup(struct inode *inode);#define _S(nr) (1<<((nr)-1))/* * We violate some modularity principles here by poking around * in some socket internals. Besides having to call socket * functions from kernel-space instead of user space, the socket * interface does not lend itself well to being cleanly called * without a file descriptor. Since the nfs calls can run on * behalf of any process, the superblock maintains a file pointer * to the server socket. */static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end){ struct file *file; struct inode *inode; struct socket *sock; unsigned short fs; int result; int xid; int len; select_table wait_table; struct select_table_entry entry; int (*select) (struct inode *, struct file *, int, select_table *); int init_timeout, max_timeout; int timeout; int retrans; int major_timeout_seen; char *server_name; int n; int addrlen; unsigned long old_mask; xid = start[0]; len = ((char *) end) - ((char *) start); file = server->file; inode = file->f_inode; select = file->f_op->select; sock = socki_lookup(inode); if (!sock) { printk("nfs_rpc_call: socki_lookup failed\n"); return -EBADF; } init_timeout = server->timeo; max_timeout = NFS_MAX_RPC_TIMEOUT*HZ/10; retrans = server->retrans; major_timeout_seen = 0; server_name = server->hostname; old_mask = current->blocked; current->blocked |= ~(_S(SIGKILL)#if 0 | _S(SIGSTOP)#endif | ((server->flags & NFS_MOUNT_INTR) ? ((current->sigaction[SIGINT - 1].sa_handler == SIG_DFL ? _S(SIGINT) : 0) | (current->sigaction[SIGQUIT - 1].sa_handler == SIG_DFL ? _S(SIGQUIT) : 0)) : 0)); fs = get_fs(); set_fs(get_ds()); for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) { result = sock->ops->send(sock, (void *) start, len, 0, 0); if (result < 0) { printk("nfs_rpc_call: send error = %d\n", result); break; } re_select: wait_table.nr = 0; wait_table.entry = &entry; current->state = TASK_INTERRUPTIBLE; if (!select(inode, file, SEL_IN, &wait_table) && !select(inode, file, SEL_IN, NULL)) { if (timeout > max_timeout) timeout = max_timeout; current->timeout = jiffies + timeout; schedule(); remove_wait_queue(entry.wait_address, &entry.wait); current->state = TASK_RUNNING; if (current->signal & ~current->blocked) { current->timeout = 0; result = -ERESTARTSYS; break; } if (!current->timeout) { if (n < retrans) continue; if (server->flags & NFS_MOUNT_SOFT) { printk("NFS server %s not responding, " "timed out\n", server_name); result = -EIO; break; } n = 0; timeout = init_timeout; init_timeout <<= 1; if (!major_timeout_seen) { printk("NFS server %s not responding, " "still trying\n", server_name); } major_timeout_seen = 1; continue; } else current->timeout = 0; } else if (wait_table.nr) remove_wait_queue(entry.wait_address, &entry.wait); current->state = TASK_RUNNING; addrlen = 0; result = sock->ops->recvfrom(sock, (void *) start, PAGE_SIZE, 1, 0, NULL, &addrlen); if (result < 0) { if (result == -EAGAIN) {#if 0 printk("nfs_rpc_call: bad select ready\n");#endif goto re_select; } if (result == -ECONNREFUSED) {#if 0 printk("nfs_rpc_call: server playing coy\n");#endif goto re_select; } if (result != -ERESTARTSYS) { printk("nfs_rpc_call: recv error = %d\n", -result); } break; } if (*start == xid) { if (major_timeout_seen) printk("NFS server %s OK\n", server_name); break; }#if 0 printk("nfs_rpc_call: XID mismatch\n");#endif } current->blocked = old_mask; set_fs(fs); return result;}/* * For now we lock out other simulaneous nfs calls for the same filesytem * because we are single-threaded and don't want to get mismatched * RPC replies. */int nfs_rpc_call(struct nfs_server *server, int *start, int *end){ int result; while (server->lock) sleep_on(&server->wait); server->lock = 1; result = do_nfs_rpc_call(server, start, end); server->lock = 0; wake_up(&server->wait); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -