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.
BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs, BlueSkyFileType type);
BlueSkyInode *bluesky_get_inode(BlueSkyFS *fs, uint64_t inum);
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);
void bluesky_insert_inode(BlueSkyFS *fs, BlueSkyInode *inode);
void bluesky_dirent_destroy(gpointer dirent);
+/* 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. */
/* 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);
{
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);
getattr3res result;
memset(&result, 0, sizeof(result));
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);
if (inode != NULL) {
result.status = NFS3_OK;
encode_fattr3(&result.getattr3res_u.attributes, inode);
result.wccstat3_u.wcc.before.present = FALSE;
result.wccstat3_u.wcc.after.present = FALSE;
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);
if (inode == NULL) {
result.status = NFS3ERR_STALE;
async_rpc_send_reply(req, &result);
lookup3res result;
memset(&result, 0, sizeof(result));
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;
if (dir == NULL) {
result.status = NFS3ERR_STALE;
result.lookup3res_u.resfail.present = FALSE;
async_rpc_send_reply(req, &result);
return;
}
async_rpc_send_reply(req, &result);
return;
}
+ schedule_inode_unref(req, inode);
result.status = NFS3_OK;
result.lookup3res_u.resok.dir_attributes.present = TRUE;
result.status = NFS3_OK;
result.lookup3res_u.resok.dir_attributes.present = TRUE;
access3res result;
memset(&result, 0, sizeof(result));
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;
if (inode == NULL) {
result.status = NFS3ERR_STALE;
result.access3res_u.resfail.present = FALSE;
readlink3res result;
memset(&result, 0, sizeof(result));
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;
if (inode != NULL) {
if (inode->type == BLUESKY_SYMLINK) {
result.status = NFS3_OK;
memset(&result, 0, sizeof(result));
char buf[32768];
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;
if (inode == NULL) {
result.status = NFS3ERR_STALE;
result.read3res_u.resfail.present = FALSE;
struct wcc_data wcc;
memset(&wcc, 0, sizeof(wcc));
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;
if (inode == NULL) {
result.status = NFS3ERR_STALE;
result.write3res_u.resfail = wcc;
struct wcc_data wcc;
memset(&wcc, 0, sizeof(wcc));
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;
if (dir == NULL) {
result.status = NFS3ERR_STALE;
result.diropres3_u.resfail = wcc;
struct wcc_data wcc;
memset(&wcc, 0, sizeof(wcc));
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;
if (dir == NULL) {
result.status = NFS3ERR_STALE;
result.diropres3_u.resfail = wcc;
struct wcc_data wcc;
memset(&wcc, 0, sizeof(wcc));
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;
if (dir == NULL) {
result.status = NFS3ERR_STALE;
result.diropres3_u.resfail = wcc;
wccstat3 result;
memset(&result, 0, sizeof(result));
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);
if (dir == NULL) {
result.status = NFS3ERR_STALE;
async_rpc_send_reply(req, &result);
wccstat3 result;
memset(&result, 0, sizeof(result));
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);
if (dir == NULL) {
result.status = NFS3ERR_STALE;
async_rpc_send_reply(req, &result);
async_rpc_send_reply(req, &result);
return;
}
async_rpc_send_reply(req, &result);
return;
}
+ schedule_inode_unref(req, inode);
if (inode->type != BLUESKY_DIRECTORY) {
result.status = NFS3ERR_NOTDIR;
if (inode->type != BLUESKY_DIRECTORY) {
result.status = NFS3ERR_NOTDIR;
wcc_data *wcc1 = &result.rename3res_u.res.fromdir_wcc;
wcc_data *wcc2 = &result.rename3res_u.res.todir_wcc;
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);
if (dir1 == NULL) {
result.status = NFS3ERR_STALE;
async_rpc_send_reply(req, &result);
}
encode_pre_wcc(wcc1, dir1);
}
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);
if (dir2 == NULL) {
result.status = NFS3ERR_STALE;
async_rpc_send_reply(req, &result);
struct wcc_data wcc;
memset(&wcc, 0, sizeof(wcc));
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;
if (inode == NULL) {
result.status = NFS3ERR_STALE;
result.link3res_u.res.linkdir_wcc = wcc;
- 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;
if (dir == NULL) {
result.status = NFS3ERR_STALE;
result.link3res_u.res.linkdir_wcc = wcc;
readdir3res result;
memset(&result, 0, sizeof(result));
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;
if (dir == NULL) {
result.status = NFS3ERR_STALE;
result.readdir3res_u.resfail.present = FALSE;
readdirplus3res result;
memset(&result, 0, sizeof(result));
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;
if (dir == NULL) {
result.status = NFS3ERR_STALE;
result.readdirplus3res_u.resfail.present = FALSE;
if (count > 0)
dirents[count - 1].nextentry = &dirents[count];
count++;
if (count > 0)
dirents[count - 1].nextentry = &dirents[count];
count++;
+ bluesky_inode_unref(inode);
}
i = g_sequence_iter_next(i);
}
}
i = g_sequence_iter_next(i);
}
fsstat3res result;
memset(&result, 0, sizeof(result));
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;
if (inode == NULL) {
result.status = NFS3ERR_STALE;
result.fsstat3res_u.resfail.present = FALSE;
result.fsinfo3res_u.resok.time_delta.nseconds = 1000;
result.fsinfo3res_u.resok.properties
= FSF3_LINK | FSF3_SYMLINK | FSF3_HOMOGENEOUS | FSF3_CANSETTIME;
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);
}
async_rpc_send_reply(req, &result);
}
result.pathconf3res_u.resok.chown_restricted = TRUE;
result.pathconf3res_u.resok.case_insensitive = FALSE;
result.pathconf3res_u.resok.case_preserving = TRUE;
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);
}
async_rpc_send_reply(req, &result);
}
int frag_hdr_bytes;
} RPCConnection;
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 {
/* 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 {
/* Procedure to be used for encoding the eventual return value into XDR. */
xdrproc_t xdr_result;
/* 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);
} RPCRequest;
extern void async_rpc_send_reply(RPCRequest *req, void *result);
bluesky_options.synchronous_stores = 1;
bluesky_options.synchronous_stores = 1;
- store = bluesky_store_new("file");
+ store = bluesky_store_new("s3");
fs = bluesky_init_fs("export", store);
BlueSkyInode *root;
fs = bluesky_init_fs("export", store);
BlueSkyInode *root;
bluesky_insert_inode(fs, root);
}
bluesky_insert_inode(fs, root);
}
+ bluesky_debug_dump(fs);
+
svc_run();
fprintf(stderr, "%s", "svc_run returned");
exit(1);
svc_run();
fprintf(stderr, "%s", "svc_run returned");
exit(1);
if (req->raw_args != NULL)
g_string_free(req->raw_args, TRUE);
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);
+ }
+
if (req->raw_args != NULL)
g_string_free(req->raw_args, TRUE);
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);
+ }
+