diff --git a/kernel/file.c b/kernel/file.c
index 116eb97..25fa226 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -166,10 +166,10 @@ filewrite(struct file *f, uint64 addr, int n)
       iunlock(f->ip);
       end_op();
 
-      if(r < 0)
+      if(r != n1){
+        // error from writei
         break;
-      if(r != n1)
-        panic("short filewrite");
+      }
       i += r;
     }
     ret = (i == n ? n : -1);
diff --git a/kernel/fs.c b/kernel/fs.c
index 848b2c9..f33553a 100644
--- a/kernel/fs.c
+++ b/kernel/fs.c
@@ -480,6 +480,9 @@ readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n)
 // Caller must hold ip->lock.
 // If user_src==1, then src is a user virtual address;
 // otherwise, src is a kernel address.
+// Returns the number of bytes successfully written.
+// If the return value is less than the requested n,
+// there was an error of some kind.
 int
 writei(struct inode *ip, int user_src, uint64 src, uint off, uint n)
 {
@@ -496,23 +499,21 @@ writei(struct inode *ip, int user_src, uint64 src, uint off, uint n)
     m = min(n - tot, BSIZE - off%BSIZE);
     if(either_copyin(bp->data + (off % BSIZE), user_src, src, m) == -1) {
       brelse(bp);
-      n = -1;
       break;
     }
     log_write(bp);
     brelse(bp);
   }
 
-  if(n > 0){
-    if(off > ip->size)
-      ip->size = off;
-    // write the i-node back to disk even if the size didn't change
-    // because the loop above might have called bmap() and added a new
-    // block to ip->addrs[].
-    iupdate(ip);
-  }
+  if(off > ip->size)
+    ip->size = off;
 
-  return n;
+  // write the i-node back to disk even if the size didn't change
+  // because the loop above might have called bmap() and added a new
+  // block to ip->addrs[].
+  iupdate(ip);
+
+  return tot;
 }
 
 // Directories