NFS cache writeback is now invoked periodically by a timer.
[bluesky.git] / nfs3 / nfs3.c
index 3f858ac..8be68bd 100644 (file)
@@ -27,14 +27,27 @@ gboolean validate_filename(const char *filename)
     return TRUE;
 }
 
+/* Arrange for a reference to an inode to be dropped when the RPC request
+ * completes. */
+void schedule_inode_unref(RPCRequest *req, BlueSkyInode *inode)
+{
+    struct cleanup_list *c = g_new(struct cleanup_list, 1);
+    c->func = (void (*)(void *))bluesky_inode_unref;
+    c->arg = inode;
+    c->next = req->cleanup;
+    req->cleanup = c;
+}
+
 /* Look up a BlueSkyInode given an NFS filehandle.  Returns NULL if the
  * filehandle is invalid. */
-BlueSkyInode *lookup_fh(nfs_fh3 *fh)
+BlueSkyInode *lookup_fh(RPCRequest *req, nfs_fh3 *fh)
 {
     BlueSkyInode *inode = NULL;
     if (fh->data.data_len == 8) {
         uint64_t inum = GUINT64_FROM_BE(*(uint64_t *)(fh->data.data_val));
         inode = bluesky_get_inode(fs, inum);
+        if (inode != NULL)
+            schedule_inode_unref(req, inode);
     }
     return inode;
 }
@@ -146,7 +159,7 @@ void nfsproc3_getattr_3_svc(nfs_fh3 *argp, RPCRequest *req)
     getattr3res result;
     memset(&result, 0, sizeof(result));
 
-    BlueSkyInode *inode = lookup_fh(argp);
+    BlueSkyInode *inode = lookup_fh(req, argp);
     if (inode != NULL) {
         result.status = NFS3_OK;
         encode_fattr3(&result.getattr3res_u.attributes, inode);
@@ -164,7 +177,7 @@ void nfsproc3_setattr_3_svc(setattr3args *argp, RPCRequest *req)
 
     result.wccstat3_u.wcc.before.present = FALSE;
     result.wccstat3_u.wcc.after.present = FALSE;
-    BlueSkyInode *inode = lookup_fh(&argp->object);
+    BlueSkyInode *inode = lookup_fh(req, &argp->object);
     if (inode == NULL) {
         result.status = NFS3ERR_STALE;
         async_rpc_send_reply(req, &result);
@@ -197,7 +210,7 @@ void nfsproc3_lookup_3_svc(diropargs3 *argp, RPCRequest *req)
     lookup3res result;
     memset(&result, 0, sizeof(result));
 
-    BlueSkyInode *dir = lookup_fh(&argp->dir);
+    BlueSkyInode *dir = lookup_fh(req, &argp->dir);
     if (dir == NULL) {
         result.status = NFS3ERR_STALE;
         result.lookup3res_u.resfail.present = FALSE;
@@ -229,6 +242,7 @@ void nfsproc3_lookup_3_svc(diropargs3 *argp, RPCRequest *req)
         async_rpc_send_reply(req, &result);
         return;
     }
+    schedule_inode_unref(req, inode);
 
     result.status = NFS3_OK;
     result.lookup3res_u.resok.dir_attributes.present = TRUE;
@@ -249,7 +263,7 @@ void nfsproc3_access_3_svc(access3args *argp, RPCRequest *req)
     access3res result;
     memset(&result, 0, sizeof(result));
 
-    BlueSkyInode *inode = lookup_fh(&argp->object);
+    BlueSkyInode *inode = lookup_fh(req, &argp->object);
     if (inode == NULL) {
         result.status = NFS3ERR_STALE;
         result.access3res_u.resfail.present = FALSE;
@@ -270,7 +284,7 @@ void nfsproc3_readlink_3_svc(nfs_fh3 *argp, RPCRequest *req)
     readlink3res result;
     memset(&result, 0, sizeof(result));
 
-    BlueSkyInode *inode = lookup_fh(argp);
+    BlueSkyInode *inode = lookup_fh(req, argp);
     if (inode != NULL) {
         if (inode->type == BLUESKY_SYMLINK) {
             result.status = NFS3_OK;
@@ -295,7 +309,7 @@ void nfsproc3_read_3_svc(read3args *argp, RPCRequest *req)
     memset(&result, 0, sizeof(result));
     char buf[32768];
 
-    BlueSkyInode *inode = lookup_fh(&argp->file);
+    BlueSkyInode *inode = lookup_fh(req, &argp->file);
     if (inode == NULL) {
         result.status = NFS3ERR_STALE;
         result.read3res_u.resfail.present = FALSE;
@@ -334,7 +348,7 @@ void nfsproc3_write_3_svc(write3args *argp, RPCRequest *req)
     struct wcc_data wcc;
     memset(&wcc, 0, sizeof(wcc));
 
-    BlueSkyInode *inode = lookup_fh(&argp->file);
+    BlueSkyInode *inode = lookup_fh(req, &argp->file);
     if (inode == NULL) {
         result.status = NFS3ERR_STALE;
         result.write3res_u.resfail = wcc;
@@ -378,7 +392,7 @@ void nfsproc3_create_3_svc(create3args *argp, RPCRequest *req)
     struct wcc_data wcc;
     memset(&wcc, 0, sizeof(wcc));
 
-    BlueSkyInode *dir = lookup_fh(&argp->where.dir);
+    BlueSkyInode *dir = lookup_fh(req, &argp->where.dir);
     if (dir == NULL) {
         result.status = NFS3ERR_STALE;
         result.diropres3_u.resfail = wcc;
@@ -442,7 +456,7 @@ void nfsproc3_mkdir_3_svc(mkdir3args *argp, RPCRequest *req)
     struct wcc_data wcc;
     memset(&wcc, 0, sizeof(wcc));
 
-    BlueSkyInode *dir = lookup_fh(&argp->where.dir);
+    BlueSkyInode *dir = lookup_fh(req, &argp->where.dir);
     if (dir == NULL) {
         result.status = NFS3ERR_STALE;
         result.diropres3_u.resfail = wcc;
@@ -506,7 +520,7 @@ void nfsproc3_symlink_3_svc(symlink3args *argp, RPCRequest *req)
     struct wcc_data wcc;
     memset(&wcc, 0, sizeof(wcc));
 
-    BlueSkyInode *dir = lookup_fh(&argp->where.dir);
+    BlueSkyInode *dir = lookup_fh(req, &argp->where.dir);
     if (dir == NULL) {
         result.status = NFS3ERR_STALE;
         result.diropres3_u.resfail = wcc;
@@ -578,7 +592,7 @@ void nfsproc3_remove_3_svc(diropargs3 *argp, RPCRequest *req)
     wccstat3 result;
     memset(&result, 0, sizeof(result));
 
-    BlueSkyInode *dir = lookup_fh(&argp->dir);
+    BlueSkyInode *dir = lookup_fh(req, &argp->dir);
     if (dir == NULL) {
         result.status = NFS3ERR_STALE;
         async_rpc_send_reply(req, &result);
@@ -613,7 +627,7 @@ void nfsproc3_rmdir_3_svc(diropargs3 *argp, RPCRequest *req)
     wccstat3 result;
     memset(&result, 0, sizeof(result));
 
-    BlueSkyInode *dir = lookup_fh(&argp->dir);
+    BlueSkyInode *dir = lookup_fh(req, &argp->dir);
     if (dir == NULL) {
         result.status = NFS3ERR_STALE;
         async_rpc_send_reply(req, &result);
@@ -638,6 +652,7 @@ void nfsproc3_rmdir_3_svc(diropargs3 *argp, RPCRequest *req)
         async_rpc_send_reply(req, &result);
         return;
     }
+    schedule_inode_unref(req, inode);
 
     if (inode->type != BLUESKY_DIRECTORY) {
         result.status = NFS3ERR_NOTDIR;
@@ -671,7 +686,7 @@ void nfsproc3_rename_3_svc(rename3args *argp, RPCRequest *req)
     wcc_data *wcc1 = &result.rename3res_u.res.fromdir_wcc;
     wcc_data *wcc2 = &result.rename3res_u.res.todir_wcc;
 
-    BlueSkyInode *dir1 = lookup_fh(&argp->from.dir);
+    BlueSkyInode *dir1 = lookup_fh(req, &argp->from.dir);
     if (dir1 == NULL) {
         result.status = NFS3ERR_STALE;
         async_rpc_send_reply(req, &result);
@@ -679,7 +694,7 @@ void nfsproc3_rename_3_svc(rename3args *argp, RPCRequest *req)
     }
     encode_pre_wcc(wcc1, dir1);
 
-    BlueSkyInode *dir2 = lookup_fh(&argp->to.dir);
+    BlueSkyInode *dir2 = lookup_fh(req, &argp->to.dir);
     if (dir2 == NULL) {
         result.status = NFS3ERR_STALE;
         async_rpc_send_reply(req, &result);
@@ -710,7 +725,7 @@ void nfsproc3_link_3_svc(link3args *argp, RPCRequest *req)
     struct wcc_data wcc;
     memset(&wcc, 0, sizeof(wcc));
 
-    BlueSkyInode *inode = lookup_fh(&argp->file);
+    BlueSkyInode *inode = lookup_fh(req, &argp->file);
     if (inode == NULL) {
         result.status = NFS3ERR_STALE;
         result.link3res_u.res.linkdir_wcc = wcc;
@@ -718,7 +733,7 @@ void nfsproc3_link_3_svc(link3args *argp, RPCRequest *req)
         return;
     }
 
-    BlueSkyInode *dir = lookup_fh(&argp->link.dir);
+    BlueSkyInode *dir = lookup_fh(req, &argp->link.dir);
     if (dir == NULL) {
         result.status = NFS3ERR_STALE;
         result.link3res_u.res.linkdir_wcc = wcc;
@@ -773,7 +788,7 @@ void nfsproc3_readdir_3_svc(readdir3args *argp, RPCRequest *req)
     readdir3res result;
     memset(&result, 0, sizeof(result));
 
-    BlueSkyInode *dir = lookup_fh(&argp->dir);
+    BlueSkyInode *dir = lookup_fh(req, &argp->dir);
     if (dir == NULL) {
         result.status = NFS3ERR_STALE;
         result.readdir3res_u.resfail.present = FALSE;
@@ -827,7 +842,7 @@ void nfsproc3_readdirplus_3_svc(readdirplus3args *argp, RPCRequest *req)
     readdirplus3res result;
     memset(&result, 0, sizeof(result));
 
-    BlueSkyInode *dir = lookup_fh(&argp->dir);
+    BlueSkyInode *dir = lookup_fh(req, &argp->dir);
     if (dir == NULL) {
         result.status = NFS3ERR_STALE;
         result.readdirplus3res_u.resfail.present = FALSE;
@@ -874,6 +889,7 @@ void nfsproc3_readdirplus_3_svc(readdirplus3args *argp, RPCRequest *req)
             if (count > 0)
                 dirents[count - 1].nextentry = &dirents[count];
             count++;
+            bluesky_inode_unref(inode);
         }
         i = g_sequence_iter_next(i);
     }
@@ -892,7 +908,7 @@ void nfsproc3_fsstat_3_svc(nfs_fh3 *argp, RPCRequest *req)
     fsstat3res result;
     memset(&result, 0, sizeof(result));
 
-    BlueSkyInode *inode = lookup_fh(argp);
+    BlueSkyInode *inode = lookup_fh(req, argp);
     if (inode == NULL) {
         result.status = NFS3ERR_STALE;
         result.fsstat3res_u.resfail.present = FALSE;
@@ -936,6 +952,7 @@ void nfsproc3_fsinfo_3_svc(nfs_fh3 *argp, RPCRequest *req)
     result.fsinfo3res_u.resok.time_delta.nseconds = 1000;
     result.fsinfo3res_u.resok.properties
         = FSF3_LINK | FSF3_SYMLINK | FSF3_HOMOGENEOUS | FSF3_CANSETTIME;
+    bluesky_inode_unref(inode);
 
     async_rpc_send_reply(req, &result);
 }
@@ -955,6 +972,7 @@ void nfsproc3_pathconf_3_svc(nfs_fh3 *argp, RPCRequest *req)
     result.pathconf3res_u.resok.chown_restricted = TRUE;
     result.pathconf3res_u.resok.case_insensitive = FALSE;
     result.pathconf3res_u.resok.case_preserving = TRUE;
+    bluesky_inode_unref(inode);
 
     async_rpc_send_reply(req, &result);
 }