/* 根据文件描述符来查找struct socket */ static inline struct socket *sockfd_lookup(int fd, struct file **pfile) { struct file *file; if (fd < 0 || fd >= NR_OPEN || !(file = current->filp[fd])) return(NULL); if (pfile) *pfile = file; return(socki_lookup(file->f_inode)); }
int sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg) { struct socket *sock; sock = socki_lookup (filp->f_inode); if (sock != NULL && sock->ops != NULL && sock->ops->fcntl != NULL) return(sock->ops->fcntl(sock, cmd, arg)); return(-EINVAL); }
/* 向socket文件中写数据 */ static int sock_write(struct inode *inode, struct file *file, char *ubuf, int size) { struct socket *sock; DPRINTF((net_debug, "NET: sock_write: buf=0x%x, size=%d\n", ubuf, size)); if (!(sock = socki_lookup(inode))) { printk("NET: sock_write: can't find socket for inode!\n"); return(-EBADF); } if (sock->flags & SO_ACCEPTCON) return(-EINVAL); return(sock->ops->write(sock, ubuf, size,(file->f_flags & O_NONBLOCK))); }
int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned int arg) { struct socket *sock; PRINTK("sock_ioctl: inode=0x%x cmd=0x%x arg=%d\n", inode, cmd, arg); if (!(sock = socki_lookup(inode))) { printk("sock_ioctl: can't find socket for inode!\n"); return -EBADF; } return sock->ops->ioctl(sock, cmd, arg); }
int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct socket *sock; DPRINTF((net_debug, "NET: sock_ioctl: inode=0x%x cmd=0x%x arg=%d\n", inode, cmd, arg)); if (!(sock = socki_lookup(inode))) { printk("NET: sock_ioctl: can't find socket for inode!\n"); return(-EBADF); } return(sock->ops->ioctl(sock, cmd, arg)); }
static int sock_read(struct inode *inode, struct file *file, char *ubuf, int size) { struct socket *sock; PRINTK("sock_read: buf=0x%x, size=%d\n", ubuf, size); if (!(sock = socki_lookup(inode))) { printk("sock_read: can't find socket for inode!\n"); return -EBADF; } if (sock->flags & SO_ACCEPTCON) return -EINVAL; return sock->ops->read(sock, ubuf, size, (file->f_flags & O_NONBLOCK)); }
/* 关闭socket文件 */ void sock_close(struct inode *inode, struct file *file) { struct socket *sock; DPRINTF((net_debug, "NET: sock_close: inode=0x%x (cnt=%d)\n", inode, inode->i_count)); /* It's possible the inode is NULL if we're closing an unfinished socket. */ if (!inode) return; if (!(sock = socki_lookup(inode))) { printk("NET: sock_close: can't find socket for inode!\n"); return; } /* 将socket释放 */ sock_release(sock); }
static int sock_select(struct inode *inode, struct file *file, int sel_type, select_table * wait) { struct socket *sock; DPRINTF((net_debug, "NET: sock_select: inode = 0x%x, kind = %s\n", inode, (sel_type == SEL_IN) ? "in" : (sel_type == SEL_OUT) ? "out" : "ex")); if (!(sock = socki_lookup(inode))) { printk("NET: sock_select: can't find socket for inode!\n"); return(0); } /* We can't return errors to select, so its either yes or no. */ if (sock->ops && sock->ops->select) return(sock->ops->select(sock, sel_type, wait)); return(0); }
void sock_close(struct inode *inode, struct file *file) { struct socket *sock; PRINTK("sock_close: inode=0x%x (cnt=%d)\n", inode, inode->i_count); /* * it's possible the inode is NULL if we're closing an unfinished * socket. */ if (!inode) return; if (!(sock = socki_lookup(inode))) { printk("sock_close: can't find socket for inode!\n"); return; } sock_release(sock); }
static struct socket *sockfd_lookup(int fd, int *err) { struct file *file; struct inode *inode; struct socket *sock; if (!(file = fget(fd))) { *err = -EBADF; return NULL; } inode = file->f_dentry->d_inode; if (!inode->i_sock || !(sock = socki_lookup(inode))) { *err = -ENOTSOCK; fput(file); return NULL; } if (sock->file != file) { printk(KERN_ERR "socki_lookup: socket file changed!\n"); sock->file = file; } return sock; }
static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size) { 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; /* JEJB/JSP 2/7/94 * This is for a 4 byte recv of the xid only */ int recv_xid; 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) { /* JEJB/JSP 2/7/94 * This is useful to see if the system is * hanging */ printk("NFS max timeout reached on %s\n", server_name); 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; /* JEJB/JSP 2/7/94 * Get the xid from the next packet using a peek, so keep it * on the recv queue. If it is wrong, it will be some reply * we don't now need, so discard it */ result = sock->ops->recvfrom(sock, (void *)&recv_xid, sizeof(recv_xid), 1, MSG_PEEK, 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 (recv_xid == xid) { if (major_timeout_seen) printk("NFS server %s OK\n", server_name); break; } /* JEJB/JSP 2/7/94 * we have xid mismatch, so discard the packet and start * again. What a hack! but I can't call recvfrom with * a null buffer yet. */ (void)sock->ops->recvfrom(sock, (void *)&recv_xid, sizeof(recv_xid), 1, 0, NULL, &addrlen); #if 0 printk("nfs_rpc_call: XID mismatch\n"); #endif goto re_select; } /* JEJB/JSP 2/7/94 * * we have the correct xid, so read into the correct place and * return it * */ result=sock->ops->recvfrom(sock, (void *)start, size + 1024, 1, 0, NULL, /* Here is NFS_SLACK_SPACE..., hack */ &addrlen); if (result < addrlen) { printk("NFS: just caught a too small read memory size..., email to NET channel\n"); printk("NFS: result=%d,addrlen=%d\n", result, addrlen); result = -EIO; } current->blocked = old_mask; set_fs(fs); return result; }