struct p9_transport *p9_trans_create_tcp(const char *addr, int port) { int err; struct p9_transport *trans; struct socket *csocket; struct sockaddr_in sin_server; csocket = NULL; trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); if (!trans) return ERR_PTR(-ENOMEM); trans->write = p9_fd_write; trans->read = p9_fd_read; trans->close = p9_fd_close; trans->poll = p9_fd_poll; sin_server.sin_family = AF_INET; sin_server.sin_addr.s_addr = in_aton(addr); sin_server.sin_port = htons(port); sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); if (!csocket) { P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n"); err = -EIO; goto error; } err = csocket->ops->connect(csocket, (struct sockaddr *)&sin_server, sizeof(struct sockaddr_in), 0); if (err < 0) { P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem connecting socket to %s\n", addr); goto error; } err = p9_socket_open(trans, csocket); if (err < 0) goto error; return trans; error: if (csocket) sock_release(csocket); kfree(trans); return ERR_PTR(err); }
struct p9_transport *p9_trans_create_unix(const char *addr) { int err; struct socket *csocket; struct sockaddr_un sun_server; struct p9_transport *trans; csocket = NULL; trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); if (!trans) return ERR_PTR(-ENOMEM); trans->write = p9_fd_write; trans->read = p9_fd_read; trans->close = p9_fd_close; trans->poll = p9_fd_poll; if (strlen(addr) > UNIX_PATH_MAX) { P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", addr); err = -ENAMETOOLONG; goto error; } sun_server.sun_family = PF_UNIX; strcpy(sun_server.sun_path, addr); sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, sizeof(struct sockaddr_un) - 1, 0); if (err < 0) { P9_EPRINTK(KERN_ERR, "p9_trans_unix: problem connecting socket: %s: %d\n", addr, err); goto error; } err = p9_socket_open(trans, csocket); if (err < 0) goto error; return trans; error: if (csocket) sock_release(csocket); kfree(trans); return ERR_PTR(err); }
static int p9_socket_open(struct p9_transport *trans, struct socket *csocket) { int fd, ret; csocket->sk->sk_allocation = GFP_NOIO; fd = sock_map_fd(csocket); if (fd < 0) { P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n"); return fd; } ret = p9_fd_open(trans, fd, fd); if (ret < 0) { P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n"); sockfd_put(csocket); return ret; } ((struct p9_trans_fd *)trans->priv)->rd->f_flags |= O_NONBLOCK; return 0; }
static int buf_check_size(struct cbuf *buf, int len) { if (buf->p + len > buf->ep) { if (buf->p < buf->ep) { P9_EPRINTK(KERN_ERR, "buffer overflow: want %d has %d\n", len, (int)(buf->ep - buf->p)); dump_stack(); buf->p = buf->ep + 1; } return 0; } return 1; }
struct inode *v9fs_get_inode(struct super_block *sb, int mode, dev_t rdev) { int err; struct inode *inode; struct v9fs_session_info *v9ses = sb->s_fs_info; P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); inode = new_inode(sb); if (!inode) { P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n"); return ERR_PTR(-ENOMEM); } err = v9fs_init_inode(v9ses, inode, mode, rdev); if (err) { iput(inode); return ERR_PTR(err); } return inode; }
static int p9_size_wstat(struct p9_wstat *wstat, int dotu) { int size = 0; if (wstat == NULL) { P9_EPRINTK(KERN_ERR, "p9_size_stat: got a NULL stat pointer\n"); return 0; } size = /* 2 + *//* size[2] */ 2 + /* type[2] */ 4 + /* dev[4] */ 1 + /* qid.type[1] */ 4 + /* qid.vers[4] */ 8 + /* qid.path[8] */ 4 + /* mode[4] */ 4 + /* atime[4] */ 4 + /* mtime[4] */ 8 + /* length[8] */ 8; /* minimum sum of string lengths */ if (wstat->name) size += strlen(wstat->name); if (wstat->uid) size += strlen(wstat->uid); if (wstat->gid) size += strlen(wstat->gid); if (wstat->muid) size += strlen(wstat->muid); if (dotu) { size += 4 + /* n_uid[4] */ 4 + /* n_gid[4] */ 4 + /* n_muid[4] */ 2; /* string length of extension[4] */ if (wstat->extension) size += strlen(wstat->extension); } return size; }
int p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *rcall, int dotu) { struct cbuf buffer; struct cbuf *bufp = &buffer; int i = 0; buf_init(bufp, buf, buflen); rcall->size = buf_get_int32(bufp); rcall->id = buf_get_int8(bufp); rcall->tag = buf_get_int16(bufp); P9_DPRINTK(P9_DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id, rcall->tag); switch (rcall->id) { default: P9_EPRINTK(KERN_ERR, "unknown message type: %d\n", rcall->id); return -EPROTO; case P9_RVERSION: rcall->params.rversion.msize = buf_get_int32(bufp); buf_get_str(bufp, &rcall->params.rversion.version); break; case P9_RFLUSH: break; case P9_RATTACH: rcall->params.rattach.qid.type = buf_get_int8(bufp); rcall->params.rattach.qid.version = buf_get_int32(bufp); rcall->params.rattach.qid.path = buf_get_int64(bufp); break; case P9_RWALK: rcall->params.rwalk.nwqid = buf_get_int16(bufp); if (rcall->params.rwalk.nwqid > P9_MAXWELEM) { P9_EPRINTK(KERN_ERR, "Rwalk with more than %d qids: %d\n", P9_MAXWELEM, rcall->params.rwalk.nwqid); return -EPROTO; } for (i = 0; i < rcall->params.rwalk.nwqid; i++) buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]); break; case P9_ROPEN: buf_get_qid(bufp, &rcall->params.ropen.qid); rcall->params.ropen.iounit = buf_get_int32(bufp); break; case P9_RCREATE: buf_get_qid(bufp, &rcall->params.rcreate.qid); rcall->params.rcreate.iounit = buf_get_int32(bufp); break; case P9_RREAD: rcall->params.rread.count = buf_get_int32(bufp); rcall->params.rread.data = bufp->p; buf_check_size(bufp, rcall->params.rread.count); break; case P9_RWRITE: rcall->params.rwrite.count = buf_get_int32(bufp); break; case P9_RCLUNK: break; case P9_RREMOVE: break; case P9_RSTAT: buf_get_int16(bufp); buf_get_stat(bufp, &rcall->params.rstat.stat, dotu); break; case P9_RWSTAT: break; case P9_RERROR: buf_get_str(bufp, &rcall->params.rerror.error); if (dotu) rcall->params.rerror.errno = buf_get_int16(bufp); break; } if (buf_check_overflow(bufp)) { P9_DPRINTK(P9_DEBUG_ERROR, "buffer overflow\n"); return -EIO; } return bufp->p - bufp->sp; }