From: Michael Vrable Date: Mon, 25 Jan 2010 01:35:14 +0000 (-0800) Subject: Properly decrement inode refcounts when finishing a request. X-Git-Url: http://git.vrable.net/?p=bluesky.git;a=commitdiff_plain;h=3c5c5e9b5a8650e0549712e20e007ba2399656bf Properly decrement inode refcounts when finishing a request. Track each refcount increase made, and when the request is finally replied to, drop those references. In a few cases we manually drop references, but this should be less error-prone if there are multiple possible return paths. --- diff --git a/bluesky/bluesky.h b/bluesky/bluesky.h index 41618b5..201cc17 100644 --- a/bluesky/bluesky.h +++ b/bluesky/bluesky.h @@ -211,6 +211,8 @@ uint64_t bluesky_fs_alloc_inode(BlueSkyFS *fs); BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs, BlueSkyFileType type); BlueSkyInode *bluesky_get_inode(BlueSkyFS *fs, uint64_t inum); +void bluesky_inode_ref(BlueSkyInode *inode); +void bluesky_inode_unref(BlueSkyInode *inode); void bluesky_insert_inode(BlueSkyFS *fs, BlueSkyInode *inode); void bluesky_dirent_destroy(gpointer dirent); diff --git a/nfs3/nfs3.c b/nfs3/nfs3.c index 3f858ac..8be68bd 100644 --- a/nfs3/nfs3.c +++ b/nfs3/nfs3.c @@ -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); } diff --git a/nfs3/nfs3_prot.h b/nfs3/nfs3_prot.h index 6a3e316..01ed7b5 100644 --- a/nfs3/nfs3_prot.h +++ b/nfs3/nfs3_prot.h @@ -655,6 +655,13 @@ typedef struct { int frag_hdr_bytes; } RPCConnection; +/* Linked list of cleanup functions to call when a request is completed. */ +struct cleanup_list { + void (*func)(void *arg); + void *arg; + struct cleanup_list *next; +}; + /* Used to track a single outstanding RPC request. Not all of the fields are * initially filled in, but more are filled in as the request is processed. */ typedef struct { @@ -684,6 +691,10 @@ typedef struct { /* Procedure to be used for encoding the eventual return value into XDR. */ xdrproc_t xdr_result; + + /* Functions to be called when the response is sent to clean up any + * resources. */ + struct cleanup_list *cleanup; } RPCRequest; extern void async_rpc_send_reply(RPCRequest *req, void *result); diff --git a/nfs3/nfsd.c b/nfs3/nfsd.c index 16011f4..55819e0 100644 --- a/nfs3/nfsd.c +++ b/nfs3/nfsd.c @@ -34,7 +34,7 @@ int main(int argc, char *argv[]) bluesky_options.synchronous_stores = 1; - store = bluesky_store_new("file"); + store = bluesky_store_new("s3"); fs = bluesky_init_fs("export", store); BlueSkyInode *root; @@ -47,6 +47,8 @@ int main(int argc, char *argv[]) bluesky_insert_inode(fs, root); } + bluesky_debug_dump(fs); + svc_run(); fprintf(stderr, "%s", "svc_run returned"); exit(1); diff --git a/nfs3/rpc.c b/nfs3/rpc.c index ae39154..7b73840 100644 --- a/nfs3/rpc.c +++ b/nfs3/rpc.c @@ -212,6 +212,13 @@ async_rpc_send_failure(RPCRequest *req, enum accept_stat stat) if (req->raw_args != NULL) g_string_free(req->raw_args, TRUE); + while (req->cleanup != NULL) { + struct cleanup_list *c = req->cleanup; + req->cleanup = c->next; + c->func(c->arg); + g_free(c); + } + g_free(req); } @@ -264,6 +271,13 @@ async_rpc_send_reply(RPCRequest *req, void *result) if (req->raw_args != NULL) g_string_free(req->raw_args, TRUE); + while (req->cleanup != NULL) { + struct cleanup_list *c = req->cleanup; + req->cleanup = c->next; + c->func(c->arg); + g_free(c); + } + g_free(req); }