// update a file's manifest, in response to a remote call // return 0 on success // return -ENOENT if not found // return -ESTALE if not local // return -errno on error // NOTE: the permissions will already have been checked by the server static int UG_impl_manifest_patch( struct SG_gateway* gateway, struct SG_request_data* reqdat, struct SG_manifest* write_delta, void* cls ) { int rc = 0; int ref_rc = 0; struct fskit_entry* fent = NULL; struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway ); struct fskit_core* fs = UG_state_fs( ug ); struct UG_inode* inode = NULL; struct ms_client* ms = SG_gateway_ms( gateway ); uint64_t volume_id = ms_client_get_volume_id( ms ); rc = UG_consistency_path_ensure_fresh( gateway, reqdat->fs_path ); if( rc != 0 ) { SG_error("UG_consistency_path_ensure_fresh('%s') rc = %d\n", reqdat->fs_path, rc ); return rc; } rc = UG_consistency_manifest_ensure_fresh( gateway, reqdat->fs_path ); if( rc != 0 ) { SG_error("UG_consistency_manifest_ensure_fresh('%s') rc = %d\n", reqdat->fs_path, rc ); return rc; } // look up fent = fskit_entry_resolve_path( fs, reqdat->fs_path, reqdat->user_id, volume_id, true, &rc ); if( fent == NULL ) { return rc; } inode = (struct UG_inode*)fskit_entry_get_user_data( fent ); // must be coordinated by us if( UG_inode_coordinator_id( inode ) != SG_gateway_id( gateway ) ) { fskit_entry_unlock( fent ); return -ESTALE; } // update the manifest fskit_entry_ref_entry( fent ); rc = UG_write_patch_manifest( gateway, reqdat, inode, write_delta ); fskit_entry_unlock( fent ); ref_rc = fskit_entry_unref( fs, reqdat->fs_path, fent ); if( ref_rc != 0 ) { SG_warn("fskit_entry_unref('%s') rc = %d\n", reqdat->fs_path, rc ); } return rc; }
// sync: sync as usual // NOTE: since this is backed by FUSE, this handler will only be called for regular files int vdevfs_sync( struct fskit_core* core, struct fskit_match_group* grp, struct fskit_entry* fent ) { void* user_data = fskit_entry_get_user_data( fent ); // careful... int fd = 0; memcpy( &fd, &user_data, 4 ); int rc = 0; rc = fsync( fd ); if( rc < 0 ) { rc = -errno; vdev_error("fsync(%d '%s') rc = %d\n", fd, grp->path, rc ); return rc; } return rc; }
// stat a file's block--build a manifest request, and set its mode // return 0 on success // return -ESTALE if the inode is not local // return -ENOENT if we don't have it // return -ENOMEM on OOM // return -errno on error static int UG_impl_stat_block( struct SG_gateway* gateway, struct SG_request_data* reqdat, struct SG_request_data* entity_info, mode_t* mode, void* cls ) { int rc = 0; struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway ); int64_t block_version = 0; UG_handle_t* fi = NULL; struct fskit_entry* fent = NULL; struct UG_inode* inode = NULL; uint64_t file_id = 0; int64_t file_version = 0; int close_rc = 0; fi = UG_open( ug, reqdat->fs_path, O_RDONLY, &rc ); if( fi == NULL ) { SG_error("UG_open('%s') rc = %d\n", reqdat->fs_path, rc ); return rc; } fskit_file_handle_rlock( fi->fh ); fent = fskit_file_handle_get_entry( fi->fh ); if( fent == NULL ) { SG_error("BUG: no entry for handle %p\n", fi->fh ); exit(1); } fskit_entry_rlock( fent ); inode = (struct UG_inode*)fskit_entry_get_user_data( fent ); if( inode == NULL ) { SG_error("BUG: no inode for entry %p\n", fent ); exit(1); } if( UG_inode_coordinator_id( inode ) != SG_gateway_id( gateway ) ) { // not ours SG_error("Not the coordinator of '%s' (it is now %" PRIu64 ")\n", reqdat->fs_path, UG_inode_coordinator_id( inode ) ); fskit_entry_unlock( fent ); fskit_file_handle_unlock( fi->fh ); rc = UG_close( ug, fi ); if( rc != 0 ) { SG_error("UG_close('%s') rc = %d\n", reqdat->fs_path, rc ); } return rc; } file_id = UG_inode_file_id( inode ); file_version = UG_inode_file_version( inode ); if( mode != NULL ) { *mode = fskit_entry_get_mode( fent ); } if( entity_info != NULL ) { rc = UG_getblockinfo( ug, reqdat->block_id, &block_version, NULL, fi ); } fskit_entry_unlock( fent ); fskit_file_handle_unlock( fi->fh ); inode = NULL; if( rc != 0 ) { SG_error("UG_getblockinfo(%s[%" PRIu64 "]) rc = %d\n", reqdat->fs_path, reqdat->block_id, rc); goto UG_impl_stat_block_out; } rc = SG_request_data_init_block( gateway, reqdat->fs_path, file_id, file_version, reqdat->block_id, block_version, entity_info ); if( rc != 0 ) { SG_error("SG_request_data_init_block rc = %d\n", rc ); goto UG_impl_stat_block_out; } UG_impl_stat_block_out: close_rc = UG_close( ug, fi ); if( close_rc != 0 ) { SG_error("UG_close('%s') rc = %d\n", reqdat->fs_path, close_rc ); } return rc; }