v9ses->uid = ~0;
        v9ses->dfltuid = V9FS_DEFUID;
        v9ses->dfltgid = V9FS_DEFGID;
-       v9ses->options = kstrdup(data, GFP_KERNEL);
-       if (!v9ses->options) {
-               P9_DPRINTK(P9_DEBUG_ERROR,
+       if (data) {
+               v9ses->options = kstrdup(data, GFP_KERNEL);
+               if (!v9ses->options) {
+                       P9_DPRINTK(P9_DEBUG_ERROR,
                           "failed to allocate copy of option string\n");
-               retval = -ENOMEM;
-               goto error;
+                       retval = -ENOMEM;
+                       goto error;
+               }
        }
 
        rc = v9fs_parse_options(v9ses);
        return fid;
 
 error:
-       v9fs_session_close(v9ses);
        return ERR_PTR(retval);
 }
 
 
        fid = v9fs_session_init(v9ses, dev_name, data);
        if (IS_ERR(fid)) {
                retval = PTR_ERR(fid);
-               fid = NULL;
-               kfree(v9ses);
-               v9ses = NULL;
-               goto error;
+               goto close_session;
        }
 
        st = p9_client_stat(fid);
        if (IS_ERR(st)) {
                retval = PTR_ERR(st);
-               goto error;
+               goto clunk_fid;
        }
 
        sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
        if (IS_ERR(sb)) {
                retval = PTR_ERR(sb);
-               goto error;
+               goto free_stat;
        }
        v9fs_fill_super(sb, v9ses, flags);
 
        inode = v9fs_get_inode(sb, S_IFDIR | mode);
        if (IS_ERR(inode)) {
                retval = PTR_ERR(inode);
-               goto error;
+               goto release_sb;
        }
 
        inode->i_uid = uid;
        root = d_alloc_root(inode);
        if (!root) {
                retval = -ENOMEM;
-               goto error;
+               goto release_sb;
        }
 
        sb->s_root = root;
 
        return simple_set_mnt(mnt, sb);
 
-error:
-       kfree(st);
-       if (fid)
-               p9_client_clunk(fid);
-
-       if (v9ses) {
-               v9fs_session_close(v9ses);
-               kfree(v9ses);
-       }
-
+release_sb:
        if (sb) {
                up_write(&sb->s_umount);
                deactivate_super(sb);
        }
 
+free_stat:
+       kfree(st);
+
+clunk_fid:
+       p9_client_clunk(fid);
+
+close_session:
+       v9fs_session_close(v9ses);
+       kfree(v9ses);
+
        return retval;
 }
 
 
 
 int p9_error_init(void);
 int p9_errstr2errno(char *, int);
+int p9_trans_fd_init(void);
 #endif /* NET_9P_H */
 
 void v9fs_register_trans(struct p9_trans_module *m);
 struct p9_trans_module *v9fs_match_trans(const substring_t *name);
 struct p9_trans_module *v9fs_default_trans(void);
-
 #endif /* NET_9P_TRANSPORT_H */
 
 
          If unsure, say N.
 
-config NET_9P_FD
-       depends on NET_9P
-       default y if NET_9P
-       tristate "9P File Descriptor Transports (Experimental)"
-       help
-         This builds support for file descriptor transports for 9p
-         which includes support for TCP/IP, named pipes, or passed
-         file descriptors.  TCP/IP is the default transport for 9p,
-         so if you are going to use 9p, you'll likely want this.
-
 config NET_9P_VIRTIO
        depends on NET_9P && EXPERIMENTAL && VIRTIO
        tristate "9P Virtio Transport (Experimental)"
 
 obj-$(CONFIG_NET_9P) := 9pnet.o
-obj-$(CONFIG_NET_9P_FD) += 9pnet_fd.o
 obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o
 
 9pnet-objs := \
        error.o \
        fcprint.o \
        util.o \
-
-9pnet_fd-objs := \
        trans_fd.o \
 
 9pnet_virtio-objs := \
 
 
        p9_error_init();
        printk(KERN_INFO "Installing 9P2000 support\n");
+       p9_trans_fd_init();
 
        return ret;
 }
 
        kfree(ts);
 }
 
+/*
+ * stolen from NFS - maybe should be made a generic function?
+ */
+static inline int valid_ipaddr4(const char *buf)
+{
+       int rc, count, in[4];
+
+       rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
+       if (rc != 4)
+               return -EINVAL;
+       for (count = 0; count < 4; count++) {
+               if (in[count] > 255)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
 static struct p9_trans *
 p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu)
 {
        if (err < 0)
                return ERR_PTR(err);
 
+       if (valid_ipaddr4(addr) < 0)
+               return ERR_PTR(-EINVAL);
+
        csocket = NULL;
        trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
        if (!trans)
        .create = p9_trans_create_fd,
 };
 
-static int __init p9_trans_fd_init(void)
+int p9_trans_fd_init(void)
 {
        int ret = p9_mux_global_init();
        if (ret) {
 
        return 0;
 }
-
-module_init(p9_trans_fd_init);
-
-MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
-MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
-MODULE_LICENSE("GPL");
+EXPORT_SYMBOL(p9_trans_fd_init);