/* * cfsd_logfile_destroy * * Description: * Arguments: * Returns: * Preconditions: */ void cfsd_logfile_destroy(cfsd_logfile_object_t *logfile_object_p) { dbug_enter("cfsd_logfile_destroy"); logfile_sync(logfile_object_p); logfile_teardown(logfile_object_p); cfsd_free(logfile_object_p); dbug_leave("cfsd_logfile_destroy"); }
/* * fscache_roll * * Description: * Rolls the contents of the log to the server. * Arguments: * kmodp interface to kernel functions * Returns: * Returns 0 for success or ETIMEDOUT if a timeout error occurred. * Preconditions: * precond(kmodp) */ int fscache_roll(cfsd_fscache_object_t *fscache_object_p, cfsd_kmod_object_t *kmod_object_p) { int error = 0; cfsd_logelem_object_t *logelem_object_p; char namebuf[MAXPATHLEN]; char backupfile[MAXPATHLEN]; int xx; cfs_dlog_entry_t *entp; off_t next_offset; ulong_t curseq = 0; int eof = 0; char *xp; cfsd_logfile_object_t *logfile_object_p; cfsd_maptbl_object_t *maptbl_object_p; dbug_enter("fscache_roll"); dbug_precond(fscache_object_p); dbug_precond(kmod_object_p); /* map in the log file */ logfile_object_p = cfsd_logfile_create(); snprintf(namebuf, sizeof (namebuf), "%s/%s/%s", fscache_object_p->i_cachepath, fscache_object_p->i_name, CACHEFS_DLOG_FILE); xx = logfile_setup(logfile_object_p, namebuf, CFS_DLOG_ENTRY_MAXSIZE); if (xx) { if (xx == ENOENT) { cfsd_logfile_destroy(logfile_object_p); dbug_leave("fscache_roll"); return (0); } fscache_fsproblem(fscache_object_p, kmod_object_p); cfsd_logfile_destroy(logfile_object_p); dbug_leave("fscache_roll"); return (0); } fscache_lock(fscache_object_p); fscache_changes(fscache_object_p, 1); fscache_unlock(fscache_object_p); /* create a hashed mapping table for changes to cids */ maptbl_object_p = cfsd_maptbl_create(); snprintf(namebuf, sizeof (namebuf), "%s/%s/%s", fscache_object_p->i_cachepath, fscache_object_p->i_name, CACHEFS_DMAP_FILE); xx = maptbl_setup(maptbl_object_p, namebuf); if (xx) { fscache_fsproblem(fscache_object_p, kmod_object_p); cfsd_logfile_destroy(logfile_object_p); cfsd_maptbl_destroy(maptbl_object_p); dbug_leave("fscache_roll"); return (0); } /* * lock is not needed because they are only used when * rolling the log by fscache_roll and fscache_addagain */ fscache_object_p->i_again_offset = 0; fscache_object_p->i_again_seq = 0; /* Pass 1: collect all cid to fid mappings */ next_offset = LOGFILE_ENTRY_START; for (;;) { /* get a pointer to the next record */ xx = logfile_entry(logfile_object_p, next_offset, &entp); if (xx == 1) break; if (xx == -1) { fscache_fsproblem(fscache_object_p, kmod_object_p); cfsd_logfile_destroy(logfile_object_p); cfsd_maptbl_destroy(maptbl_object_p); dbug_leave("fscache_roll"); return (0); } next_offset += entp->dl_len; /* skip record if not valid */ if (entp->dl_valid != CFS_DLOG_VAL_COMMITTED) continue; /* create an object for the appropriate log type */ logelem_object_p = NULL; switch (entp->dl_op) { case CFS_DLOG_CREATE: case CFS_DLOG_REMOVE: case CFS_DLOG_LINK: case CFS_DLOG_RENAME: case CFS_DLOG_MKDIR: case CFS_DLOG_RMDIR: case CFS_DLOG_SYMLINK: case CFS_DLOG_SETATTR: case CFS_DLOG_SETSECATTR: case CFS_DLOG_MODIFIED: case CFS_DLOG_TRAILER: break; case CFS_DLOG_MAPFID: dbug_print(("info", "mapfid")); logelem_object_p = cfsd_logelem_mapfid_create( maptbl_object_p, logfile_object_p, kmod_object_p); break; default: dbug_assert(0); fscache_fsproblem(fscache_object_p, kmod_object_p); break; } /* do not bother if ignoring the record */ if (logelem_object_p == NULL) continue; /* debuggging */ logelem_dump(logelem_object_p); /* roll the entry */ xx = logelem_roll(logelem_object_p, (ulong_t *)NULL); if (xx) { fscache_fsproblem(fscache_object_p, kmod_object_p); cfsd_logelem_destroy(logelem_object_p); cfsd_maptbl_destroy(maptbl_object_p); cfsd_logfile_destroy(logfile_object_p); dbug_leave("fscache_roll"); return (0); } /* mark record as completed */ entp->dl_valid = CFS_DLOG_VAL_PROCESSED; xx = logfile_sync(logfile_object_p); if (xx) { fscache_fsproblem(fscache_object_p, kmod_object_p); cfsd_logelem_destroy(logelem_object_p); cfsd_maptbl_destroy(maptbl_object_p); cfsd_logfile_destroy(logfile_object_p); dbug_leave("fscache_roll"); return (0); } /* destroy the object */ cfsd_logelem_destroy(logelem_object_p); } /* Pass 2: modify the back file system */ next_offset = LOGFILE_ENTRY_START; for (;;) { /* if we need the seq number of a deferred modify */ if (fscache_object_p->i_again_offset && (fscache_object_p->i_again_seq == 0)) { /* get a pointer to the next record */ xx = logfile_entry(logfile_object_p, fscache_object_p->i_again_offset, &entp); if (xx == 1) break; if (xx == -1) { fscache_fsproblem(fscache_object_p, kmod_object_p); cfsd_logfile_destroy(logfile_object_p); cfsd_maptbl_destroy(maptbl_object_p); dbug_leave("fscache_roll"); return (0); } dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); fscache_object_p->i_again_seq = entp->dl_seq; dbug_assert(fscache_object_p->i_again_seq != 0); } /* get a pointer to the next record to process */ if (!eof) { xx = logfile_entry(logfile_object_p, next_offset, &entp); if (xx == 1) { eof = 1; curseq = ULONG_MAX; } else if (xx) { break; } else { curseq = entp->dl_seq; } } /* if its time to process a deferred modify entry */ if (fscache_object_p->i_again_seq && (eof || (fscache_object_p->i_again_seq < entp->dl_seq))) { xx = logfile_entry(logfile_object_p, fscache_object_p->i_again_offset, &entp); if (xx) break; dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); curseq = entp->dl_seq; fscache_object_p->i_again_offset = entp->dl_u.dl_modify.dl_next; fscache_object_p->i_again_seq = 0; entp->dl_u.dl_modify.dl_next = -1; } else if (eof) { xx = 0; break; } /* else move the offset to the next record */ else { next_offset += entp->dl_len; } /* skip record if not valid */ if (entp->dl_valid != CFS_DLOG_VAL_COMMITTED) continue; /* process the record */ xx = fscache_rollone(fscache_object_p, kmod_object_p, maptbl_object_p, logfile_object_p, curseq); if (xx == ETIMEDOUT) { /* timeout error, back to disconnected */ cfsd_maptbl_destroy(maptbl_object_p); cfsd_logfile_destroy(logfile_object_p); dbug_print(("info", "timeout error occurred")); dbug_leave("fscache_roll"); return (xx); } else if (xx == EIO) { break; } else if (xx == EAGAIN) { continue; } else if (xx) { /* should never happen */ dbug_assert(0); break; } else { /* mark record as completed */ entp->dl_valid = CFS_DLOG_VAL_PROCESSED; xx = logfile_sync(logfile_object_p); if (xx) break; } } /* if an unrecoverable error occurred */ if (xx) { dbug_print(("error", "error processing log file")); fscache_fsproblem(fscache_object_p, kmod_object_p); } /* dump stats about the hash table */ maptbl_dumpstats(maptbl_object_p); /* dump stats about the log file */ logfile_dumpstats(logfile_object_p); /* debugging hack, rename the log files */ if (snprintf(namebuf, sizeof (namebuf), "%s/%s/%s", fscache_object_p->i_cachepath, fscache_object_p->i_name, CACHEFS_DLOG_FILE) > ((sizeof (backupfile)) - (sizeof (".bak")))) { dbug_print(("error", "unable to create backup dlog_file " "for %s, path name is too long", namebuf)); } else { /* * No need to check return value from snprintf() as * the previous check should suffice. */ snprintf(backupfile, sizeof (backupfile), "%s.bak", namebuf); if (rename(namebuf, backupfile) == -1) { dbug_print(("error", "unable to create backup dlog_file")); } } if (snprintf(namebuf, sizeof (namebuf), "%s/%s/%s", fscache_object_p->i_cachepath, fscache_object_p->i_name, CACHEFS_DMAP_FILE) > ((sizeof (backupfile)) - (sizeof (".bak")))) { dbug_print(("error", "unable to create backup dmap_file " "for %s, path name is too long", namebuf)); } else { /* * No need to check return value from snprintf() as * the previous check should suffice. */ snprintf(backupfile, sizeof (backupfile), "%s.bak", namebuf); if (rename(namebuf, backupfile) == -1) { dbug_print(("error", "unable to create backup dmap_file")); } } /* delete the log file */ /* XXX */ cfsd_maptbl_destroy(maptbl_object_p); cfsd_logfile_destroy(logfile_object_p); dbug_leave("fscache_roll"); return (error); }