Use readstr() for #device text buffers
[akaros.git] / kern / drivers / dev / gtfs.c
index a7284ba..9f82c77 100644 (file)
@@ -46,7 +46,10 @@ struct gtfs {
  * be_{length,mode,mtime} should be what the remote server thinks they are -
  * especially for length and mode.  The invariant is that e.g. the file's length
  * == be_length, and the qlock protects that invariant.  We don't care as much
  * be_{length,mode,mtime} should be what the remote server thinks they are -
  * especially for length and mode.  The invariant is that e.g. the file's length
  * == be_length, and the qlock protects that invariant.  We don't care as much
- * about mtime, since some 9p servers just change that on their own. */
+ * about mtime, since some 9p servers just change that on their own.
+ *
+ * Also note that you can't trust be_length for directories.  You'll often get
+ * 4096 or 0, depending on the 9p server you're talking to. */
 struct gtfs_priv {
        struct chan                                     *be_walk;       /* never opened */
        struct chan                                     *be_read;
 struct gtfs_priv {
        struct chan                                     *be_walk;       /* never opened */
        struct chan                                     *be_read;
@@ -187,9 +190,9 @@ static void purge_cb(struct tree_file *tf)
        poperror();
 }
 
        poperror();
 }
 
-static void __gtfs_destroy(uint32_t srcid, long a0, long a1, long a2)
+static void gtfs_release(struct kref *kref)
 {
 {
-       struct gtfs *gtfs = (struct gtfs*)a0;
+       struct gtfs *gtfs = container_of(kref, struct gtfs, users);
 
        tfs_frontend_purge(&gtfs->tfs, purge_cb);
        /* this is the ref from attach */
 
        tfs_frontend_purge(&gtfs->tfs, purge_cb);
        /* this is the ref from attach */
@@ -201,18 +204,6 @@ static void __gtfs_destroy(uint32_t srcid, long a0, long a1, long a2)
        kfree(gtfs);
 }
 
        kfree(gtfs);
 }
 
-static void gtfs_release(struct kref *kref)
-{
-       struct gtfs *gtfs = container_of(kref, struct gtfs, users);
-
-       /* We can't use RCU within an RCU callback, and release methods are often
-        * called from within callbacks.  We can use a kernel message, which can
-        * block and do whatever else it wants.  In essence, we break the connection
-        * to our current context (the rcu_mgmt_ktask) by using a kmsg. */
-       send_kernel_message(core_id(), __gtfs_destroy, (long)gtfs, 0, 0,
-                           KMSG_ROUTINE);
-}
-
 static struct gtfs *chan_to_gtfs(struct chan *c)
 {
        struct tree_file *tf = chan_to_tree_file(c);
 static struct gtfs *chan_to_gtfs(struct chan *c)
 {
        struct tree_file *tf = chan_to_tree_file(c);
@@ -323,10 +314,6 @@ static size_t __gtfs_fsf_read(struct fs_file *f, void *ubuf, size_t n,
 {
        struct gtfs_priv *gp = fsf_to_gtfs_priv(f);
 
 {
        struct gtfs_priv *gp = fsf_to_gtfs_priv(f);
 
-       if (off >= gp->be_length) {
-               /* We can skip the RPC, since we know it will return zero (EOF). */
-               return 0;
-       }
        if (!gp->be_read)
                gp->be_read = cclone_and_open(gp->be_walk, O_READ);
        return devtab[gp->be_read->type].read(gp->be_read, ubuf, n, off);
        if (!gp->be_read)
                gp->be_read = cclone_and_open(gp->be_walk, O_READ);
        return devtab[gp->be_read->type].read(gp->be_read, ubuf, n, off);
@@ -830,7 +817,6 @@ static void gtfs_sync_gtfs(struct gtfs *gtfs)
        tfs_frontend_for_each(&gtfs->tfs, gtfs_sync_tf);
 }
 
        tfs_frontend_for_each(&gtfs->tfs, gtfs_sync_tf);
 }
 
-/* chan_ctl or something can hook into these functions */
 static void gtfs_sync_chan(struct chan *c)
 {
        gtfs_sync_tf(chan_to_tree_file(c));
 static void gtfs_sync_chan(struct chan *c)
 {
        gtfs_sync_tf(chan_to_tree_file(c));
@@ -853,7 +839,7 @@ static unsigned long gtfs_chan_ctl(struct chan *c, int op, unsigned long a1,
                        gtfs_sync_chan(c);
                return 0;
        default:
                        gtfs_sync_chan(c);
                return 0;
        default:
-               error(EINVAL, "%s does not support %d", __func__, op);
+               return tree_chan_ctl(c, op, a1, a2, a3, a4);
        }
 }
 
        }
 }