/* * Write a file's data to the staging file. We write the file out * in 4meg chunks. */ int save_filedata( dm_sessid_t sid, void *hanp, size_t hlen, int stg_fd, dm_size_t fsize) { char *filebuf; int i, nbufs; int retval; dm_ssize_t nread, lastbuf; ssize_t nwrite; dm_off_t off; nbufs = fsize / CHUNKSIZE; off = 0; retval = 0; filebuf = malloc(CHUNKSIZE); if (filebuf == NULL) { err_msg("%s/%d: Can't alloc memory for file buffer", __FILE__, __LINE__); goto out; } for (i = 0; i<nbufs; i++) { nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off, (dm_ssize_t)CHUNKSIZE, filebuf); if (nread != CHUNKSIZE) { #ifdef __sgi errno_msg("%s/%d: invis read err: got %lld, expected %lld, buf %d", #else errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d", #endif __FILE__, __LINE__, nread, (dm_ssize_t)CHUNKSIZE, i); retval = 1; goto out; } off += nread; nwrite = write(stg_fd, filebuf, CHUNKSIZE); if (nwrite != CHUNKSIZE) { errno_msg("%s/%d: write err %d, expected %d, buf %d", __FILE__, __LINE__, nwrite, CHUNKSIZE, i); retval = 1; goto out; } }
int main( int argc, char **argv) { dm_sessid_t sid, oldsid, targetsid, *newsidp, *sidbufp; dm_token_t token, *tokenp, *rtokenp, *tokenbufp; dm_attrname_t *attrnamep; dm_off_t off, *offp, *roffp; dm_extent_t *extentp; dm_inherit_t *inheritbufp; dm_stat_t *statp; dm_size_t len, *dmrlenp, *retvalp; dm_attrloc_t *locp; dm_eventset_t *eventsetp; dm_config_t flagname; dm_region_t *regbufp; dm_response_t response; dm_right_t right, *rightp; dm_igen_t igen, *igenp; dm_msgtype_t msgtype; dm_fileattr_t *attrp; dm_boolean_t enable, *exactflagp; dm_timestruct_t *delay; mode_t mode; size_t hlen, dirhlen, hlen1, hlen2, targhlen, *fshlenp, *hlenp; size_t msglen, buflen, *rlenp; u_int nelem, mask, maxmsgs, uflags, *nelemp, maxevent; void *hanp, *dirhanp, *hanp1, *hanp2, *targhanp; void *msgdatap, *bufp, **hanpp, *respbufp, **fshanpp; dm_fsid_t fsid, *fsidp; dm_ino_t ino, *inop; char *cname, *sessinfop, *path, *pathbufp, **versionstrpp; int flags, fd, setdtime, reterror; u_int urc; int rc; dm_ssize_t ssrc; /* Definitions per the prototypes in dmport.h, in the same order. */ rc = dm_clear_inherit(sid, hanp, hlen, token, attrnamep); rc = dm_create_by_handle(sid, dirhanp, dirhlen, token, hanp, hlen, cname); rc = dm_create_session(oldsid, sessinfop, newsidp); rc = dm_create_userevent(sid, msglen, msgdatap, tokenp); rc = dm_destroy_session(sid); rc = dm_downgrade_right(sid, hanp, hlen, token); rc = dm_fd_to_handle(fd, hanpp, hlenp); rc = dm_find_eventmsg(sid, token, buflen, bufp, rlenp); rc = dm_get_allocinfo(sid, hanp, hlen, token, offp, nelem, extentp, nelemp); rc = dm_get_bulkall(sid, hanp, hlen, token, mask, attrnamep, locp, buflen, bufp, rlenp); rc = dm_get_bulkattr(sid, hanp, hlen, token, mask, locp, buflen, bufp, rlenp); rc = dm_get_config(hanp, hlen, flagname, retvalp); rc = dm_get_config_events(hanp, hlen, nelem, eventsetp, nelemp); rc = dm_get_dirattrs(sid, hanp, hlen, token, mask, locp, buflen, bufp, rlenp); rc = dm_get_dmattr(sid, hanp, hlen, token, attrnamep, buflen, bufp, rlenp); rc = dm_get_eventlist(sid, hanp, hlen, token, nelem, eventsetp, nelemp); rc = dm_get_events(sid, maxmsgs, flags, buflen, bufp, rlenp); rc = dm_get_fileattr(sid, hanp, hlen, token, mask, statp); rc = dm_get_mountinfo(sid, hanp, hlen, token, buflen, bufp, rlenp); rc = dm_get_region(sid, hanp, hlen, token, nelem, regbufp, nelemp); rc = dm_getall_disp(sid, buflen, bufp, rlenp); rc = dm_getall_dmattr(sid, hanp, hlen, token, buflen, bufp, rlenp); rc = dm_getall_inherit(sid, hanp, hlen, token, nelem, inheritbufp, nelemp); rc = dm_getall_sessions(nelem, sidbufp, nelemp); rc = dm_getall_tokens(sid, nelem, tokenbufp, nelemp); rc = dm_handle_cmp(hanp1, hlen1, hanp2, hlen2); dm_handle_free(hanp, hlen); urc = dm_handle_hash(hanp, hlen); rc = dm_handle_is_valid(hanp, hlen); rc = dm_handle_to_fshandle(hanp, hlen, fshanpp, fshlenp); rc = dm_handle_to_fsid(hanp, hlen, fsidp); rc = dm_handle_to_igen(hanp, hlen, igenp); rc = dm_handle_to_ino(hanp, hlen, inop); rc = dm_handle_to_path(dirhanp, dirhlen, targhanp, targhlen, buflen, pathbufp, rlenp); rc = dm_init_attrloc(sid, hanp, hlen, token, locp); rc = dm_init_service(versionstrpp); rc = dm_make_handle(&fsid, &ino, &igen, hanpp, hlenp); rc = dm_make_fshandle(&fsid, hanpp, hlenp); rc = dm_mkdir_by_handle(sid, dirhanp, dirhlen, token, hanp, hlen, cname); rc = dm_move_event(sid, token, targetsid, rtokenp); rc = dm_obj_ref_hold(sid, token, hanp, hlen); rc = dm_obj_ref_query(sid, token, hanp, hlen); rc = dm_obj_ref_rele(sid, token, hanp, hlen); rc = dm_path_to_fshandle(path, hanpp, hlenp); rc = dm_path_to_handle(path, hanpp, hlenp); rc = dm_pending(sid, token, delay); rc = dm_probe_hole(sid, hanp, hlen, token, off, len, roffp, dmrlenp); rc = dm_punch_hole(sid, hanp, hlen, token, off, len); rc = dm_query_right(sid, hanp, hlen, token, rightp); rc = dm_query_session(sid, buflen, bufp, rlenp); ssrc = dm_read_invis(sid, hanp, hlen, token, off, len, bufp); rc = dm_release_right(sid, hanp, hlen, token); rc = dm_remove_dmattr(sid, hanp, hlen, token, setdtime, attrnamep); rc = dm_request_right(sid, hanp, hlen, token, uflags, right); rc = dm_respond_event(sid, token, response, reterror, buflen, respbufp); rc = dm_send_msg(sid, msgtype, buflen, bufp); rc = dm_set_disp(sid, hanp, hlen, token, eventsetp, maxevent); rc = dm_set_dmattr(sid, hanp, hlen, token, attrnamep, setdtime, buflen, bufp); rc = dm_set_eventlist(sid, hanp, hlen, token, eventsetp, maxevent); rc = dm_set_fileattr(sid, hanp, hlen, token, mask, attrp); rc = dm_set_inherit(sid, hanp, hlen, token, attrnamep, mode); rc = dm_set_region(sid, hanp, hlen, token, nelem, regbufp, exactflagp); rc = dm_set_return_on_destroy(sid, hanp, hlen, token, attrnamep, enable); rc = dm_symlink_by_handle(sid, dirhanp, dirhlen, token, hanp, hlen, cname, path); rc = dm_sync_by_handle(sid, hanp, hlen, token); rc = dm_upgrade_right(sid, hanp, hlen, token); ssrc = dm_write_invis(sid, hanp, hlen, flags, token, off, len, bufp); exit(0); }
goto out; } off += nread; nwrite = write(stg_fd, filebuf, CHUNKSIZE); if (nwrite != CHUNKSIZE) { errno_msg("%s/%d: write err %d, expected %d, buf %d", __FILE__, __LINE__, nwrite, CHUNKSIZE, i); retval = 1; goto out; } } lastbuf = fsize % CHUNKSIZE; nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off, (dm_ssize_t)lastbuf, filebuf); if (nread != lastbuf) { #ifdef __sgi errno_msg("%s/%d: invis read error- got %lld, expected %lld, last buf", #else errno_msg("%s/%d: invis read error- got %d, expected %d, last buf", #endif __FILE__, __LINE__, nread, lastbuf); retval = 1; goto out; } nwrite = write(stg_fd, filebuf, (int)lastbuf); if (nwrite != lastbuf) { #ifdef __sgi
/* migrate one file */ static int hsm_migrate(const char *path) { int ret; void *hanp = NULL; size_t hlen = 0; dm_attrname_t attrname; uint8_t buf[0x1000]; size_t rlen; struct stat st; struct hsm_attr h; dm_region_t region; dm_boolean_t exactFlag; off_t ofs; int retval = 1; struct hsm_store_handle *handle; dmapi.token = DM_NO_TOKEN; ret = dm_path_to_handle(discard_const(path), &hanp, &hlen); if (ret != 0) { printf("dm_path_to_handle failed for %s - %s\n", path, strerror(errno)); exit(1); } /* we create a user event which we use to gain exclusive rights on the file */ ret = dm_create_userevent(dmapi.sid, 0, NULL, &dmapi.token); if (ret != 0) { printf("dm_create_userevent failed for %s - %s\n", path, strerror(errno)); exit(1); } /* getting an exclusive right first guarantees that two migrate commands don't happen at the same time on the same file, and also guarantees that a recall isn't happening at the same time. We then downgrade to a shared right immediately, which still gives the same guarantee, but means that any reads on the file can proceeed while we are saving away the data during the migrate */ ret = dm_request_right(dmapi.sid, hanp, hlen, dmapi.token, DM_RR_WAIT, DM_RIGHT_EXCL); if (ret != 0) { printf("dm_request_right failed for %s - %s\n", path, strerror(errno)); goto respond; } /* now downgrade the right - reads on the file can then proceed during the expensive migration step */ ret = dm_downgrade_right(dmapi.sid, hanp, hlen, dmapi.token); if (ret != 0) { printf("dm_downgrade_right failed for %s - %s\n", path, strerror(errno)); goto respond; } memset(attrname.an_chars, 0, DM_ATTR_NAME_SIZE); strncpy((char*)attrname.an_chars, HSM_ATTRNAME, DM_ATTR_NAME_SIZE); /* get any existing attribute on the file */ ret = dm_get_dmattr(dmapi.sid, hanp, hlen, dmapi.token, &attrname, sizeof(h), &h, &rlen); if (ret != 0 && errno != ENOENT) { printf("dm_get_dmattr failed for %s - %s\n", path, strerror(errno)); goto respond; } /* check it is valid */ if (ret == 0) { if (strncmp(h.magic, HSM_MAGIC, sizeof(h.magic)) != 0) { printf("Bad magic '%*.*s'\n", (int)sizeof(h.magic), (int)sizeof(h.magic), h.magic); exit(1); } if (h.state == HSM_STATE_START) { /* a migration has died on this file */ printf("Continuing migration of partly migrated file\n"); hsm_store_remove(store_ctx, h.device, h.inode); } else { /* it is either fully migrated, or waiting recall */ printf("Not migrating already migrated file %s\n", path); goto respond; } } if (lstat(path, &st) != 0) { printf("failed to stat %s - %s\n", path, strerror(errno)); goto respond; } if (!S_ISREG(st.st_mode)) { printf("Not migrating non-regular file %s\n", path); goto respond; } if (st.st_size == 0) { printf("Not migrating file '%s' of size 0\n", path); goto respond; } /* open up the store file */ handle = hsm_store_open(store_ctx, st.st_dev, st.st_ino, false); if (handle == NULL) { printf("Failed to open store file for %s - %s\n", path, strerror(errno)); goto respond; } /* read the file data and store it away */ ofs = 0; while ((ret = dm_read_invis(dmapi.sid, hanp, hlen, dmapi.token, ofs, sizeof(buf), buf)) > 0) { if (hsm_store_write(handle, buf, ret) != 0) { printf("Failed to write to store for %s - %s\n", path, strerror(errno)); hsm_store_close(handle); hsm_store_remove(store_ctx, st.st_dev, st.st_ino); goto respond; } ofs += ret; } if (ret == -1) { printf("failed dm_read_invis on %s - %s\n", path, strerror(errno)); hsm_store_close(handle); hsm_store_remove(store_ctx, st.st_dev, st.st_ino); goto respond; } hsm_store_close(handle); /* now upgrade to a exclusive right on the file before we change the dmattr and punch holes in the file. */ ret = dm_upgrade_right(dmapi.sid, hanp, hlen, dmapi.token); if (ret != 0) { printf("dm_upgrade_right failed for %s - %s\n", path, strerror(errno)); goto respond; } strncpy(h.magic, HSM_MAGIC, sizeof(h.magic)); h.size = st.st_size; h.migrate_time = time(NULL); h.device = st.st_dev; h.inode = st.st_ino; h.state = HSM_STATE_START; /* mark the file as starting to migrate */ ret = dm_set_dmattr(dmapi.sid, hanp, hlen, dmapi.token, &attrname, 0, sizeof(h), (void*)&h); if (ret == -1) { printf("failed dm_set_dmattr on %s - %s\n", path, strerror(errno)); hsm_store_remove(store_ctx, st.st_dev, st.st_ino); goto respond; } /* mark the whole file as offline, including parts beyond EOF */ region.rg_offset = 0; region.rg_size = 0; /* zero means the whole file */ region.rg_flags = DM_REGION_WRITE | DM_REGION_READ; ret = dm_set_region(dmapi.sid, hanp, hlen, dmapi.token, 1, ®ion, &exactFlag); if (ret == -1) { printf("failed dm_set_region on %s - %s\n", path, strerror(errno)); hsm_store_remove(store_ctx, st.st_dev, st.st_ino); goto respond; } /* this dm_get_dmattr() is not strictly necessary - it is just paranoia */ ret = dm_get_dmattr(dmapi.sid, hanp, hlen, dmapi.token, &attrname, sizeof(h), &h, &rlen); if (ret != 0) { printf("ERROR: Abandoning partial migrate - attribute gone!?\n"); goto respond; } if (h.state != HSM_STATE_START) { printf("ERROR: Abandoning partial migrate - state=%d\n", h.state); goto respond; } ret = dm_punch_hole(dmapi.sid, hanp, hlen, dmapi.token, 0, st.st_size); if (ret == -1) { printf("failed dm_punch_hole on %s - %s\n", path, strerror(errno)); hsm_store_remove(store_ctx, st.st_dev, st.st_ino); goto respond; } h.state = HSM_STATE_MIGRATED; /* mark the file as fully migrated */ ret = dm_set_dmattr(dmapi.sid, hanp, hlen, dmapi.token, &attrname, 0, sizeof(h), (void*)&h); if (ret == -1) { printf("failed dm_set_dmattr on %s - %s\n", path, strerror(errno)); hsm_store_remove(store_ctx, st.st_dev, st.st_ino); goto respond; } printf("Migrated file '%s' of size %d\n", path, (int)st.st_size); retval = 0; respond: /* destroy our userevent */ ret = dm_respond_event(dmapi.sid, dmapi.token, DM_RESP_CONTINUE, 0, 0, NULL); if (ret == -1) { printf("failed dm_respond_event on %s - %s\n", path, strerror(errno)); exit(1); } dmapi.token = DM_NO_TOKEN; dm_handle_free(hanp, hlen); return retval; }