/* * logfile_getaddr * * Description: * Returns an address of a particular offset in the file. * The size of the item to map is i_maxmap * This routine assumes that if we have to remap that i_maxmap * will fit inside the default mapping size. * Arguments: * start offset in the file to map * map 0 means use map_entry, 1 means use map_offset * Returns: * Returns NULL for a failure with the mapping file. * Preconditions: */ caddr_t logfile_getaddr(cfsd_logfile_object_t *logfile_object_p, off_t start, int map) { mmap_info_t *mmp; caddr_t pa; off_t end; dbug_enter("logfile_getaddr"); mmp = (map == 0) ? &logfile_object_p->i_map_entry : &logfile_object_p->i_map_offset; /* determine the end of the item */ end = start + logfile_object_p->i_maxmap - 1; /* map the entry in if necessary */ if ((start < mmp->i_paoff) || (mmp->i_paend < end)) { if (logfile_domap(logfile_object_p, start & logfile_object_p->i_pagemask, map)) { dbug_leave("logfile_getaddr"); return (NULL); } dbug_assert((mmp->i_paoff <= start) && (end <= mmp->i_paend)); } /* make an address and return it */ pa = mmp->i_pa + (start - mmp->i_paoff); dbug_leave("logfile_getaddr"); return (pa); }
/* * logfile_dumpstats * * Description: * Prints out various stats about the hashing. * Arguments: * Returns: * Preconditions: */ void logfile_dumpstats(cfsd_logfile_object_t *logfile_object_p) { int xx; double dd; dbug_enter("logfile_dumpstats"); dbug_print(("dump", "Request - next %d", logfile_object_p->i_stat_nextcnt)); dbug_print(("dump", "Request - offset %d", logfile_object_p->i_stat_offcnt)); dbug_print(("dump", "Map Moves %d", logfile_object_p->i_stat_mapmove)); dbug_print(("dump", "Mapping Size %d", logfile_object_p->i_maplen)); dbug_print(("dump", "Item Size %d", logfile_object_p->i_maxmap)); dbug_print(("dump", "File Size %d", logfile_object_p->i_size)); if (logfile_object_p->i_stat_mapmove == 0) { dbug_leave("logfile_dumpstats"); return; } dd = (double)logfile_object_p->i_stat_mapmove / (logfile_object_p->i_stat_nextcnt + logfile_object_p->i_stat_offcnt); dbug_print(("dump", "Mmap moves per Request %.2f", dd)); xx = logfile_object_p->i_stat_mapdist / logfile_object_p->i_stat_mapmove; dbug_print(("dump", "Average distance per mmap moves %d", xx)); dbug_leave("logfile_dumpstats"); }
/* * logfile_entry * * Description: * Sets addrp to the address of the log entry at offset * The mapping remains in effect until: * a) this routine is called again * b) logfile_teardown is called * c) this object is destroyed * Arguments: * offset offset to start of entry * entpp place to store address * Returns: * Returns 0 for success, 1 for EOF, -1 if a fatal error occurs. * Preconditions: * precond(addrp) */ int logfile_entry(cfsd_logfile_object_t *logfile_object_p, off_t offset, cfs_dlog_entry_t **entpp) { cfs_dlog_entry_t *entp; dbug_enter("logfile_entry"); dbug_precond(entpp); dbug_precond(offset >= sizeof (long)); logfile_object_p->i_stat_nextcnt++; /* check for eof */ if (offset >= logfile_object_p->i_size) { dbug_leave("logfile_entry"); return (1); } dbug_assert((offset & 3) == 0); /* get the address of the entry */ entp = (cfs_dlog_entry_t *)logfile_getaddr(logfile_object_p, offset, 0); if (entp == NULL) { dbug_leave("logfile_entry"); return (-1); } /* sanity check, record should be alligned */ if (entp->dl_len & 3) { dbug_print(("error", "Record at offset %d length is not alligned %d", offset, entp->dl_len)); dbug_leave("logfile_entry"); return (-1); } /* sanity check record should a reasonable size */ if ((entp->dl_len < CFS_DLOG_ENTRY_MINSIZE) || (entp->dl_len > CFS_DLOG_ENTRY_MAXSIZE)) { dbug_print(("error", "Record at offset %d has an invalid size %d", offset, entp->dl_len)); dbug_leave("logfile_entry"); return (-1); } /* preserve offset and pointer */ logfile_object_p->i_cur_offset = offset; logfile_object_p->i_cur_entry = entp; /* return success */ *entpp = entp; dbug_leave("logfile_entry"); return (0); }
/* * logfile_domap * * Description: * Maps in the specified section of the file. * Arguments: * off The offset to map in. Must be i_pagesize aligned. * map 0 means use map_entry, 1 means use map_offset * Returns: * Returns 0 for success or an errno value on failure. * Preconditions: */ int logfile_domap(cfsd_logfile_object_t *logfile_object_p, off_t off, int map) { int xx; int len; mmap_info_t *mmp; dbug_enter("logfile_domap"); dbug_precond(logfile_object_p->i_fid >= 0); len = logfile_object_p->i_maplen; mmp = (map == 0) ? &logfile_object_p->i_map_entry : &logfile_object_p->i_map_offset; logfile_object_p->i_stat_mapmove++; /* destroy old mapping if it exists */ if (mmp->i_pa) { /* determine how far we have to move the map */ logfile_object_p->i_stat_mapdist += abs(mmp->i_paoff - off); /* remove the map */ xx = munmap(mmp->i_pa, mmp->i_palen); if (xx == -1) { xx = errno; dbug_print(("error", "Could not unmap %s, %d, %p, %d", logfile_object_p->i_name, xx, mmp->i_pa, mmp->i_palen)); } mmp->i_pa = NULL; mmp->i_palen = 0; mmp->i_paoff = 0; mmp->i_paend = 0; } /* do the mapping */ mmp->i_pa = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, logfile_object_p->i_fid, off); if (mmp->i_pa == MAP_FAILED) { xx = errno; dbug_print(("error", "Could not map %s, error %d, off %d, len %d", logfile_object_p->i_name, xx, off, len)); mmp->i_pa = NULL; dbug_leave("logfile_domap"); return (xx); } mmp->i_palen = len; mmp->i_paoff = off; mmp->i_paend = off + len - 1; dbug_leave("logfile_domap"); return (0); }
/* * fscache_fsproblem * * Description: * Arguments: * kmodp * Returns: * Preconditions: * precond(kmodp) */ void fscache_fsproblem(cfsd_fscache_object_t *fscache_object_p, cfsd_kmod_object_t *kmod_object_p) { #if 0 int xx; #endif dbug_enter("fscache_fsproblem"); dbug_precond(fscache_object_p); dbug_precond(kmod_object_p); #if 0 /* first try to put all modified files in lost+found */ xx = kmod_lostfoundall(kmod_object_p); if (xx) { /* if that failed, put file system in read-only mode */ kmod_rofs(kmod_object_p); #endif fscache_lock(fscache_object_p); fscache_object_p->i_disconnectable = 0; fscache_object_p->i_modify++; fscache_unlock(fscache_object_p); #if 0 } #endif dbug_leave("fscache_fsproblem"); }
/* * ----------------------------------------------------------------- * cfsd_fscache_destroy * * Description: * Arguments: * Returns: * Preconditions: */ void cfsd_fscache_destroy(cfsd_fscache_object_t *fscache_object_p) { int xx; dbug_enter("cfsd_fscache_destroy"); dbug_precond(fscache_object_p); /* dbug_assert(fscache_object_p->i_refcnt == 0); */ /* close down the message file descriptor */ if (fscache_object_p->i_ofd >= 0) { if (close(fscache_object_p->i_ofd)) dbug_print(("error", "cannot close fscache fd error %d", errno)); fscache_object_p->i_ofd = -1; } /* destroy the locking mutex */ xx = mutex_destroy(&fscache_object_p->i_lock); dbug_assert(xx == 0); /* destroy the conditional variable */ xx = cond_destroy(&fscache_object_p->i_cvwait); dbug_assert(xx == 0); cfsd_free(fscache_object_p); dbug_leave("cfsd_fscache_destroy"); }
/* * ------------------------------------------------------------ * all_cachefstab_update * * Description: * Arguments: * Returns: * Preconditions: */ void all_cachefstab_update(cfsd_all_object_t *all_object_p) { cfsd_cache_object_t *cache_object_p; FILE *fout; dbug_enter("all_cachefstab_update"); fout = fopen(CACHEFSTAB, "w"); if (fout == NULL) { dbug_print(("error", "cannot write %s", CACHEFSTAB)); } else { cache_object_p = all_object_p->i_cachelist; while (cache_object_p != NULL) { dbug_assert(cache_object_p); fprintf(fout, "%s\n", cache_object_p->i_cachedir); cache_object_p = cache_object_p->i_next; } if (fclose(fout)) dbug_print(("error", "cannot close %s error %d", CACHEFSTAB, errno)); } dbug_leave("all_cachefstab_update"); }
/* * ------------------------------------------------------------ * cfsd_all_destroy * * Description: * Arguments: * Returns: * Preconditions: */ void cfsd_all_destroy(cfsd_all_object_t *all_object_p) { cfsd_cache_object_t *cache_object_p; cfsd_cache_object_t *tmp_cache_object_p; int xx; dbug_enter("cfsd_all_destroy"); /* dbug_assert(all_object_p->i_hoardp == NULL); */ /* get rid of any cache objects */ cache_object_p = all_object_p->i_cachelist; while (cache_object_p != NULL) { tmp_cache_object_p = cache_object_p->i_next; cfsd_cache_destroy(cache_object_p); cache_object_p = tmp_cache_object_p; } /* destroy the locking mutex */ xx = mutex_destroy(&all_object_p->i_lock); dbug_assert(xx == 0); cfsd_free(all_object_p); dbug_leave("cfsd_all_destroy"); }
/* * ------------------------------------------------------------ * all_unlock * * Description: * Arguments: * Returns: * Preconditions: */ void all_unlock(cfsd_all_object_t *all_object_p) { dbug_enter("all_unlock"); mutex_unlock(&all_object_p->i_lock); dbug_leave("all_unlock"); }
/* * ----------------------------------------------------------------- * fscache_unlock * * Description: * Arguments: * Returns: * Preconditions: */ void fscache_unlock(cfsd_fscache_object_t *fscache_object_p) { dbug_enter("fscache_unlock"); dbug_precond(fscache_object_p); mutex_unlock(&fscache_object_p->i_lock); dbug_leave("fscache_unlock"); }
/* * 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_changes * * Description: * Used to specify whether or not there are changes to roll to the * server. * Arguments: * tt * Returns: * Preconditions: */ void fscache_changes(cfsd_fscache_object_t *fscache_object_p, int tt) { dbug_enter("fscache_changes"); dbug_precond(fscache_object_p); fscache_object_p->i_changes = tt; fscache_object_p->i_modify++; dbug_leave("fscache_changes"); }
/* * logfile_sync * * Description: * Performs an fsync on the log file. * Arguments: * Returns: * Returns 0 for success or an errno value on failure. * Preconditions: */ int logfile_sync(cfsd_logfile_object_t *logfile_object_p) { int xx; dbug_enter("logfile_sync"); if (logfile_object_p->i_fid == -1) { dbug_leave("logfile_sync"); return (0); } xx = fsync(logfile_object_p->i_fid); if (xx) { xx = errno; dbug_print(("error", "fsync failed %d", xx)); } dbug_leave("logfile_sync"); return (xx); }
/* * ------------------------------------------------------------ * all_cachelist_add * * Description: * Arguments: * cachep * Returns: * Preconditions: * precond(cachep) */ void all_cachelist_add(cfsd_all_object_t *all_object_p, cfsd_cache_object_t *cache_object_p) { dbug_enter("all_cachelist_add"); dbug_precond(cache_object_p); cache_object_p->i_next = all_object_p->i_cachelist; all_object_p->i_cachelist = cache_object_p; all_object_p->i_modify++; all_object_p->i_cachecount++; dbug_leave("all_cachelist_add"); }
/* * logfile_teardown * * Description: * Uninitializes the object. * Call logfile_setup before using this object again. * Arguments: * Returns: * Preconditions: */ void logfile_teardown(cfsd_logfile_object_t *logfile_object_p) { int xx; dbug_enter("logfile_teardown"); if (logfile_object_p->i_map_entry.i_pa) { xx = munmap(logfile_object_p->i_map_entry.i_pa, logfile_object_p->i_map_entry.i_palen); if (xx == -1) { xx = errno; dbug_print(("error", "Could not unmap %s, %d, %p, %d", logfile_object_p->i_name, xx, logfile_object_p->i_map_entry.i_pa, logfile_object_p->i_map_entry.i_palen)); } logfile_object_p->i_map_entry.i_pa = NULL; } logfile_object_p->i_map_entry.i_paoff = 0; logfile_object_p->i_map_entry.i_paend = 0; logfile_object_p->i_map_entry.i_palen = 0; if (logfile_object_p->i_map_offset.i_pa) { xx = munmap(logfile_object_p->i_map_offset.i_pa, logfile_object_p->i_map_offset.i_palen); if (xx == -1) { xx = errno; dbug_print(("error", "Could not unmap %s, %d, %p, %d", logfile_object_p->i_name, xx, logfile_object_p->i_map_offset.i_pa, logfile_object_p->i_map_offset.i_palen)); } logfile_object_p->i_map_offset.i_pa = NULL; } logfile_object_p->i_map_offset.i_paoff = 0; logfile_object_p->i_map_offset.i_paend = 0; logfile_object_p->i_map_offset.i_palen = 0; if (logfile_object_p->i_fid != -1) { if (close(logfile_object_p->i_fid)) dbug_print(("error", "Could not close %s, %d", logfile_object_p->i_name, errno)); logfile_object_p->i_fid = -1; } logfile_object_p->i_cur_offset = 0; logfile_object_p->i_cur_entry = NULL; dbug_leave("logfile_teardown"); }
/* * logfile_offset * * Description: * Sets addrp to the address of the specified offset. * The mapping remains in effect until: * a) this routine is called again * b) logfile_teardown is called * c) this object is destroyed * Arguments: * offset offset into file, must be 0 <= offset < i_size * addrp returns mapped address * Returns: * Returns 0 for success, -1 if a fatal error occurs. * Preconditions: * precond(addrp) */ int logfile_offset(cfsd_logfile_object_t *logfile_object_p, off_t offset, caddr_t *addrp) { caddr_t pa; dbug_enter("logfile_offset"); dbug_precond(addrp); dbug_precond((0 <= offset) && (offset < logfile_object_p->i_size)); logfile_object_p->i_stat_offcnt++; /* get the address for the offset */ pa = logfile_getaddr(logfile_object_p, offset, 1); if (pa == NULL) { dbug_leave("logfile_offset"); return (-1); } /* return success */ *addrp = pa; dbug_leave("logfile_offset"); return (0); }
/* * ----------------------------------------------------------------- * cfsd_fscache_create * * Description: * Arguments: * name * cachepath * Returns: * Preconditions: * precond(name) * precond(cachepath) */ cfsd_fscache_object_t * cfsd_fscache_create(const char *name, const char *cachepath, int fscacheid) { cfsd_fscache_object_t *fscache_object_p; int xx; dbug_enter("cfsd_fscache_create"); dbug_precond(name); dbug_precond(cachepath); fscache_object_p = cfsd_calloc(sizeof (cfsd_fscache_object_t)); strlcpy(fscache_object_p->i_name, name, sizeof (fscache_object_p->i_name)); strlcpy(fscache_object_p->i_cachepath, cachepath, sizeof (fscache_object_p->i_cachepath)); fscache_object_p->i_fscacheid = fscacheid; fscache_object_p->i_refcnt = 0; fscache_object_p->i_disconnectable = 0; fscache_object_p->i_mounted = 0; fscache_object_p->i_threaded = 0; fscache_object_p->i_connected = 0; fscache_object_p->i_reconcile = 0; fscache_object_p->i_changes = 0; fscache_object_p->i_simdis = 0; fscache_object_p->i_tryunmount = 0; fscache_object_p->i_backunmount = 0; fscache_object_p->i_time_state = 0; fscache_object_p->i_time_mnt = 0; fscache_object_p->i_modify = 1; fscache_object_p->i_threadid = 0; fscache_object_p->i_ofd = -1; fscache_object_p->i_next = NULL; /* initialize the locking mutex */ xx = mutex_init(&fscache_object_p->i_lock, USYNC_THREAD, NULL); dbug_assert(xx == 0); xx = cond_init(&fscache_object_p->i_cvwait, USYNC_THREAD, 0); dbug_assert(xx == 0); dbug_leave("cfsd_fscache_create"); return (fscache_object_p); }
int fscache_pingserver(cfsd_fscache_object_t *fscache_object_p) { static struct timeval TIMEOUT = { 25, 0 }; CLIENT *clnt; enum clnt_stat retval; int ret = 0; char hostname[sizeof (fscache_object_p->i_backfs)]; char *cptr; dbug_enter("fscache_pingserver"); dbug_precond(fscache_object_p); strlcpy(hostname, fscache_object_p->i_backfs, sizeof (hostname)); if (cptr = strchr(hostname, ':')) *cptr = '\0'; dbug_assert(cptr != NULL); dbug_print(("info", "remote host '%s' before clnt_create", hostname)); dbug_print(("info", "before clnt_create")); /* XXX this takes 75 seconds to time out */ /* XXX should use lower level routines to reduce overhead */ clnt = clnt_create(hostname, NFS_PROGRAM, NFS_VERSION, "udp"); if (clnt == NULL) { /* XXX what if this fails other than TIMEDOUT */ /* clnt_pcreateerror(hostname); */ dbug_print(("info", "clnt_create failed")); ret = -1; } else { dbug_print(("info", "before null rpc")); /* XXX this takes 45 seconds to time out */ retval = clnt_call(clnt, 0, xdr_void, NULL, xdr_void, NULL, TIMEOUT); if (retval != RPC_SUCCESS) { /* clnt_perror(clnt, "null rpc call failed"); */ dbug_print(("info", "null rpc call failed %d", retval)); ret = -1; } clnt_destroy(clnt); } dbug_leave("fscache_pingserver"); return (ret); }
/* * ------------------------------------------------------------ * all_cachelist_at * * Description: * Arguments: * index * Returns: * Returns ... * Preconditions: */ cfsd_cache_object_t * all_cachelist_at(cfsd_all_object_t *all_object_p, size_t index) { cfsd_cache_object_t *cache_object_p; int i = 0; dbug_enter("all_cachelist_at"); /* find the correct cache object */ cache_object_p = all_object_p->i_cachelist; while ((cache_object_p != NULL) && (i++ < index)) { cache_object_p = cache_object_p->i_next; } dbug_leave("all_cachelist_at"); return (cache_object_p); }
/* * ------------------------------------------------------------ * cfsd_all_create * * Description: * Arguments: * Returns: * Preconditions: */ cfsd_all_object_t * cfsd_all_create(void) { /* get the host name */ struct utsname info; cfsd_all_object_t *all_object_p; int xx; char buffer[MAXPATHLEN]; dbug_enter("cfsd_all_create"); all_object_p = (cfsd_all_object_t *)cfsd_calloc(sizeof (cfsd_all_object_t)); xx = uname(&info); if (xx == -1) { dbug_print(("error", "cannot get host name")); strlcpy(all_object_p->i_machname, gettext("unknown"), sizeof (all_object_p->i_machname)); } else { strlcpy(all_object_p->i_machname, info.nodename, sizeof (all_object_p->i_machname)); } /* initialize the locking mutex */ xx = mutex_init(&all_object_p->i_lock, USYNC_THREAD, NULL); dbug_assert(xx == 0); all_object_p->i_nextcacheid = 0; all_object_p->i_modify = 1; all_object_p->i_cachelist = NULL; all_object_p->i_cachecount = 0; /* all_object_p->i_hoardp = NULL; */ snprintf(buffer, sizeof (buffer), gettext("host name is \"%s\""), all_object_p->i_machname); dbug_print(("info", buffer)); dbug_leave("cfsd_all_create"); return (all_object_p); }
/* * ------------------------------------------------------------ * all_cachelist_find * * Description: * Arguments: * namep * Returns: * Returns ... * Preconditions: * precond(namep) */ cfsd_cache_object_t * all_cachelist_find(cfsd_all_object_t *all_object_p, const char *namep) { cfsd_cache_object_t *cache_object_p; dbug_enter("all_cachelist_find"); dbug_precond(namep); /* find the correct cache object */ cache_object_p = all_object_p->i_cachelist; while ((cache_object_p != NULL) && strcmp(namep, cache_object_p->i_cachedir)) { cache_object_p = cache_object_p->i_next; } dbug_leave("all_cachelist_find"); return (cache_object_p); }
/* * cfsd_logfile_create * * Description: * Arguments: * Returns: * Preconditions: */ cfsd_logfile_object_t * cfsd_logfile_create(void) { cfsd_logfile_object_t *logfile_object_p; dbug_enter("cfsd_logfile_create"); logfile_object_p = cfsd_calloc(sizeof (cfsd_logfile_object_t)); logfile_object_p->i_fid = -1; logfile_object_p->i_map_entry.i_pa = NULL; logfile_object_p->i_map_entry.i_paoff = 0; logfile_object_p->i_map_entry.i_paend = 0; logfile_object_p->i_map_entry.i_palen = 0; logfile_object_p->i_map_offset.i_pa = NULL; logfile_object_p->i_map_offset.i_paoff = 0; logfile_object_p->i_map_offset.i_paend = 0; logfile_object_p->i_map_offset.i_palen = 0; logfile_object_p->i_cur_offset = 0; logfile_object_p->i_cur_entry = NULL; dbug_leave("cfsd_logfile_create"); return (logfile_object_p); }
/* * ----------------------------------------------------------------- * fscache_setup * * Description: * Arguments: * Returns: * Preconditions: */ void fscache_setup(cfsd_fscache_object_t *fscache_object_p) { char *tmp; char cfs_mnt_filename[MAXPATHLEN]; FILE *fin; /* * Line input buffer allows for type field (magic number size * of 50 is historic), the field separator ": ", a large value * (again historic) and a '\n' character. */ char type[50]; char value[MAXPATHLEN * 4]; char buf[sizeof (type) + 2 + sizeof (value) + 1]; int err = 0; int xx; char *options[] = { "snr", "disconnectable", NULL }; char *strp = buf; char *dummy; struct stat64 sinfo; time_t mtime; dbug_enter("fscache_setup"); dbug_precond(fscache_object_p); fscache_object_p->i_modify++; fscache_object_p->i_disconnectable = 0; fscache_object_p->i_connected = 0; fscache_object_p->i_reconcile = 0; fscache_object_p->i_changes = 0; fscache_object_p->i_time_state = 0; fscache_object_p->i_time_mnt = 0; fscache_object_p->i_mntpt[0] = '\0'; fscache_object_p->i_backfs[0] = '\0'; fscache_object_p->i_backpath[0] = '\0'; fscache_object_p->i_backfstype[0] = '\0'; fscache_object_p->i_cfsopt[0] = '\0'; fscache_object_p->i_bfsopt[0] = '\0'; snprintf(cfs_mnt_filename, sizeof (cfs_mnt_filename), "%s/%s/%s", fscache_object_p->i_cachepath, fscache_object_p->i_name, CACHEFS_MNT_FILE); /* open for reading the file with the mount information */ fin = fopen(cfs_mnt_filename, "r"); if (fin == NULL) { dbug_print(("err", "could not open %s, %d", cfs_mnt_filename, errno)); dbug_leave("fscache_setup"); return; } /* get the modify time of the mount file */ if (fstat64(fileno(fin), &sinfo) == -1) { dbug_print(("err", "could not stat %s, %d", cfs_mnt_filename, errno)); if (fclose(fin)) dbug_print(("err", "cannot close %s, %d", cfs_mnt_filename, errno)); dbug_leave("fscache_setup"); return; } mtime = sinfo.st_mtime; /* read the mount information from the file */ while (fgets(buf, sizeof (buf), fin) != NULL) { tmp = strtok(buf, ":"); if (strlcpy(type, tmp, sizeof (type)) >= sizeof (type)) { /* Buffer Overflow */ dbug_print(("err", "overflow in type field" " of file %s", cfs_mnt_filename)); if (fclose(fin)) dbug_print(("err", "cannot close %s, %d", cfs_mnt_filename, errno)); dbug_leave("fscache_setup"); return; } tmp = strtok(NULL, "\n"); if (tmp != NULL && *tmp == ' ') { /* * There is a valid value string so skip * the space after the ":". */ tmp++; if (strlcpy(value, tmp, sizeof (value)) >= sizeof (value)) { /* Buffer Overflow */ dbug_print(("err", "overflow in value field" " of file %s", cfs_mnt_filename)); if (fclose(fin)) dbug_print(("err", "cannot close %s, %d", cfs_mnt_filename, errno)); dbug_leave("fscache_setup"); return; } } else { value[0] = '\0'; } dbug_print(("info", "\"%s\" \"%s\"", type, value)); if (strcmp(type, "cachedir") == 0) { if (strcmp(fscache_object_p->i_cachepath, value) != 0) { err = 1; dbug_print(("err", "caches do not match %s, %s", fscache_object_p->i_cachepath, buf)); } } else if (strcmp(type, "mnt_point") == 0) { strlcpy(fscache_object_p->i_mntpt, value, sizeof (fscache_object_p->i_mntpt)); } else if (strcmp(type, "special") == 0) { strlcpy(fscache_object_p->i_backfs, value, sizeof (fscache_object_p->i_backfs)); } else if (strcmp(type, "backpath") == 0) { strlcpy(fscache_object_p->i_backpath, value, sizeof (fscache_object_p->i_backpath)); } else if (strcmp(type, "backfstype") == 0) { strlcpy(fscache_object_p->i_backfstype, value, sizeof (fscache_object_p->i_backfstype)); } else if (strcmp(type, "cacheid") == 0) { if (strcmp(fscache_object_p->i_name, value) != 0) { err = 1; dbug_print(("err", "ids do not match %s, %s", fscache_object_p->i_name, value)); } } else if (strcmp(type, "cachefs_options") == 0) { strlcpy(fscache_object_p->i_cfsopt, value, sizeof (fscache_object_p->i_cfsopt)); } else if (strcmp(type, "backfs_options") == 0) { strlcpy(fscache_object_p->i_bfsopt, value, sizeof (fscache_object_p->i_bfsopt)); } else if (strcmp(type, "mount_time") == 0) { continue; } else { dbug_print(("err", "unknown keyword \"%s\"", type)); err = 1; } } if (fclose(fin)) dbug_print(("err", "cannot close %s, %d", cfs_mnt_filename, errno)); /* see if this is a file system that is disconnectable */ if ((err == 0) && (fscache_object_p->i_backfs[0] && fscache_object_p->i_cfsopt[0])) { strlcpy(buf, fscache_object_p->i_cfsopt, sizeof (buf)); while (*strp != '\0') { xx = getsubopt(&strp, options, &dummy); if (xx != -1) { fscache_object_p->i_disconnectable = 1; break; } } } /* * open up a fd on the sysmsg so we have a place to write * log rolling errors */ if (fscache_object_p->i_disconnectable) { if (fscache_object_p->i_ofd < 0) fscache_object_p->i_ofd = open("/dev/sysmsg", O_WRONLY); if (fscache_object_p->i_ofd < 0) { fprintf(stderr, gettext("cachefsd: File system %s cannot be" " disconnected.\n"), fscache_object_p->i_mntpt); fprintf(stderr, gettext("cachefsd: Cannot open /dev/sysmsg\n")); fscache_object_p->i_disconnectable = 0; } } /* see if the file system is mounted */ snprintf(cfs_mnt_filename, sizeof (cfs_mnt_filename), "%s/%s/%s", fscache_object_p->i_cachepath, fscache_object_p->i_name, CACHEFS_UNMNT_FILE); if (stat64(cfs_mnt_filename, &sinfo) == 0) { fscache_object_p->i_mounted = 0; mtime = sinfo.st_mtime; } else fscache_object_p->i_mounted = 1; /* save the time of the last mount or unmount */ fscache_object_p->i_time_mnt = mtime; dbug_print(("info", "disconnectable == %d, mounted == %d", fscache_object_p->i_disconnectable, fscache_object_p->i_mounted)); dbug_leave("fscache_setup"); }
/* * fscache_addagain * * Description: * Arguments: * lfp * Returns: * Returns ... * Preconditions: * precond(lfp) */ int fscache_addagain(cfsd_fscache_object_t *fscache_object_p, cfsd_logfile_object_t *logfile_object_p, ulong_t nseq) { int xx; cfs_dlog_entry_t *entp; off_t noffset; off_t prevoff = 0; off_t toff; dbug_enter("fscache_addagain"); dbug_precond(fscache_object_p); dbug_precond(logfile_object_p); entp = logfile_object_p->i_cur_entry; noffset = logfile_object_p->i_cur_offset; dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); dbug_assert(nseq); /* both set or both zero */ dbug_assert((!fscache_object_p->i_again_seq ^ !fscache_object_p->i_again_offset) == 0); entp->dl_seq = nseq; /* simple case, first one on list */ if ((fscache_object_p->i_again_seq == 0) || (nseq < fscache_object_p->i_again_seq)) { entp->dl_u.dl_modify.dl_next = fscache_object_p->i_again_offset; fscache_object_p->i_again_seq = nseq; fscache_object_p->i_again_offset = noffset; dbug_leave("fscache_addagain"); return (0); } /* Search until we find the element on the list prior to the */ /* insertion point. */ for (toff = fscache_object_p->i_again_offset; toff != 0; toff = entp->dl_u.dl_modify.dl_next) { /* get pointer to next element on the list */ xx = logfile_entry(logfile_object_p, toff, &entp); if (xx) { dbug_leave("fscache_addagain"); return (xx); } dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); /* done if we found the element after the insertion point */ if (nseq < entp->dl_seq) break; prevoff = toff; } dbug_assert(prevoff); /* get pointer to element prior to the insertion point */ xx = logfile_entry(logfile_object_p, prevoff, &entp); if (xx) { dbug_leave("fscache_addagain"); return (xx); } dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); dbug_assert(entp->dl_u.dl_modify.dl_next == toff); /* set element to point to our new element */ entp->dl_u.dl_modify.dl_next = noffset; /* get pointer to our new element */ xx = logfile_entry(logfile_object_p, noffset, &entp); if (xx) { dbug_leave("fscache_addagain"); return (xx); } dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); /* set it to point to next link or end of list */ entp->dl_u.dl_modify.dl_next = toff; /* return success */ dbug_leave("fscache_addagain"); return (0); }
/* * fscache_rollone * * Description: * Arguments: * kmodp * tblp * lfp * Returns: * Returns ... * Preconditions: * precond(kmodp) * precond(tblp) * precond(lfp) */ int fscache_rollone(cfsd_fscache_object_t *fscache_object_p, cfsd_kmod_object_t *kmod_object_p, cfsd_maptbl_object_t *maptbl_object_p, cfsd_logfile_object_t *logfile_object_p, ulong_t seq) { cfsd_logelem_object_t *logelem_object_p = NULL; cfs_dlog_entry_t *entp; int xx; char *strp; dbug_enter("fscache_rollone"); dbug_precond(fscache_object_p); dbug_precond(kmod_object_p); dbug_precond(maptbl_object_p); dbug_precond(logfile_object_p); entp = logfile_object_p->i_cur_entry; /* create an object for the appropriate log type */ switch (entp->dl_op) { case CFS_DLOG_CREATE: dbug_print(("info", "create")); logelem_object_p = cfsd_logelem_create_create(maptbl_object_p, logfile_object_p, kmod_object_p); break; case CFS_DLOG_REMOVE: dbug_print(("info", "remove")); logelem_object_p = cfsd_logelem_remove_create(maptbl_object_p, logfile_object_p, kmod_object_p); break; case CFS_DLOG_LINK: dbug_print(("info", "link")); logelem_object_p = cfsd_logelem_link_create(maptbl_object_p, logfile_object_p, kmod_object_p); break; case CFS_DLOG_RENAME: dbug_print(("info", "rename")); logelem_object_p = cfsd_logelem_rename_create(maptbl_object_p, logfile_object_p, kmod_object_p); break; case CFS_DLOG_MKDIR: dbug_print(("info", "mkdir")); logelem_object_p = cfsd_logelem_mkdir_create(maptbl_object_p, logfile_object_p, kmod_object_p); break; case CFS_DLOG_RMDIR: dbug_print(("info", "rmdir")); logelem_object_p = cfsd_logelem_rmdir_create(maptbl_object_p, logfile_object_p, kmod_object_p); break; case CFS_DLOG_SYMLINK: dbug_print(("info", "symlink")); logelem_object_p = cfsd_logelem_symlink_create(maptbl_object_p, logfile_object_p, kmod_object_p); break; case CFS_DLOG_SETATTR: dbug_print(("info", "setattr")); logelem_object_p = cfsd_logelem_setattr_create(maptbl_object_p, logfile_object_p, kmod_object_p); break; case CFS_DLOG_SETSECATTR: dbug_print(("info", "setsecattr")); logelem_object_p = cfsd_logelem_setsecattr_create( maptbl_object_p, logfile_object_p, kmod_object_p); break; case CFS_DLOG_MODIFIED: dbug_print(("info", "modified")); logelem_object_p = cfsd_logelem_modified_create(maptbl_object_p, logfile_object_p, kmod_object_p); break; case CFS_DLOG_MAPFID: dbug_print(("info", "mapfid")); break; case CFS_DLOG_TRAILER: dbug_print(("info", "trailer")); break; default: dbug_assert(0); dbug_leave("fscache_rollone"); return (EIO); } /* do not bother if ignoring the record */ if (logelem_object_p == NULL) { dbug_print(("info", "record ignored")); dbug_leave("fscache_rollone"); return (0); } /* XXX debugging */ logelem_dump(logelem_object_p); /* roll the entry */ xx = logelem_roll(logelem_object_p, &seq); strp = logelem_object_p->i_messagep; if (strp) { write(fscache_object_p->i_ofd, strp, strlen(strp)); dbug_print(("conflict", "%s", strp)); } if (xx == EAGAIN) { dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); xx = fscache_addagain(fscache_object_p, logfile_object_p, seq); if (xx == 0) xx = EAGAIN; } /* destroy the object */ cfsd_logelem_destroy(logelem_object_p); dbug_leave("fscache_rollone"); return (xx); }
/* * ----------------------------------------------------------------- * fscache_process * * Description: * Arguments: * Returns: * Preconditions: */ void fscache_process(cfsd_fscache_object_t *fscache_object_p) { int xx; int changes; cfsd_kmod_object_t *kmod_object_p; int setup = 1; int state; dbug_enter("fscache_process"); dbug_precond(fscache_object_p); kmod_object_p = cfsd_kmod_create(); for (;;) { fscache_lock(fscache_object_p); fscache_object_p->i_time_state = time(NULL); fscache_object_p->i_modify++; /* if we should try to unmount the file system */ if (fscache_object_p->i_tryunmount) { /* shut down the interface to the kmod */ if (setup == 0) { kmod_shutdown(kmod_object_p); setup = 1; } /* try to unmount the file system */ if (umount(fscache_object_p->i_mntpt) == -1) { xx = errno; dbug_print(("info", "unmount failed %s", strerror(xx))); } else { fscache_object_p->i_mounted = 0; } /* wake up thread blocked in fscache_unmount */ fscache_object_p->i_tryunmount = 0; xx = cond_broadcast(&fscache_object_p->i_cvwait); dbug_assert(xx == 0); /* all done if unmount succeeded */ if (fscache_object_p->i_mounted == 0) { fscache_unlock(fscache_object_p); break; } } if (setup) { setup = 0; /* * make an interface into the cachefs kmod for * this fs */ xx = kmod_setup(kmod_object_p, fscache_object_p->i_mntpt); if (xx != 0) { dbug_print(("err", "setup of kmod interface failed %d", xx)); fscache_object_p->i_disconnectable = 0; fscache_object_p->i_modify++; fscache_unlock(fscache_object_p); break; } /* verify that we got the file system we expected XXX */ } /* get the current state of the file system */ state = kmod_stateget(kmod_object_p); if (fscache_object_p->i_simdis && (state == CFS_FS_CONNECTED)) { dbug_print(("simdis", "simulating disconnection on %s", fscache_object_p->i_mntpt)); xx = kmod_stateset(kmod_object_p, CFS_FS_DISCONNECTED); dbug_assert(xx == 0); state = kmod_stateget(kmod_object_p); dbug_assert(state == CFS_FS_DISCONNECTED); } fscache_unlock(fscache_object_p); switch (state) { case CFS_FS_CONNECTED: fscache_lock(fscache_object_p); fscache_object_p->i_connected = 1; fscache_object_p->i_reconcile = 0; fscache_object_p->i_modify++; fscache_unlock(fscache_object_p); /* wait for fs to switch to disconnecting */ dbug_print(("info", "about to xwait")); xx = kmod_xwait(kmod_object_p); if (xx == EINTR) { dbug_print(("info", "a. EINTR from xwait")); continue; } dbug_assert(xx == 0); state = kmod_stateget(kmod_object_p); dbug_assert(state == CFS_FS_DISCONNECTED); break; case CFS_FS_DISCONNECTED: fscache_lock(fscache_object_p); fscache_object_p->i_connected = 0; fscache_object_p->i_reconcile = 0; fscache_object_p->i_modify++; fscache_unlock(fscache_object_p); /* wait until we are reconnected */ fscache_server_alive(fscache_object_p, kmod_object_p); if (fscache_object_p->i_tryunmount) continue; /* switch to reconnecting mode */ xx = kmod_stateset(kmod_object_p, CFS_FS_RECONNECTING); dbug_assert(xx == 0); break; case CFS_FS_RECONNECTING: fscache_lock(fscache_object_p); fscache_object_p->i_connected = 1; fscache_object_p->i_reconcile = 1; fscache_object_p->i_modify++; changes = fscache_object_p->i_changes; fscache_unlock(fscache_object_p); /* roll the log */ xx = fscache_roll(fscache_object_p, kmod_object_p); if (xx) { dbug_assert(xx == ETIMEDOUT); /* switch to disconnected */ xx = kmod_stateset(kmod_object_p, CFS_FS_DISCONNECTED); dbug_assert(xx == 0); } else { /* switch to connected */ xx = kmod_stateset(kmod_object_p, CFS_FS_CONNECTED); dbug_assert(xx == 0); changes = 0; } fscache_lock(fscache_object_p); fscache_object_p->i_reconcile = 0; fscache_changes(fscache_object_p, changes); fscache_object_p->i_modify++; fscache_unlock(fscache_object_p); break; default: dbug_assert(0); break; } } cfsd_kmod_destroy(kmod_object_p); dbug_leave("fscache_process"); }
/* * fscache_simdisconnect * * Description: * Simulates disconnection or reconnects from a simulated disconnection. * Arguments: * disconnect 1 means disconnect, !1 means connect * Returns: * Returns 0 for success, !0 on an error * Preconditions: */ int fscache_simdisconnect(cfsd_fscache_object_t *fscache_object_p, int disconnect) { int xx; int ret = 0; char *strp; int tcon; int trec; dbug_enter("fscache_simdisconnect"); dbug_precond(fscache_object_p); strp = disconnect ? "disconnection" : "reconnection"; dbug_print(("simdis", "About to simulate %s", strp)); fscache_lock(fscache_object_p); if (disconnect) { /* if file system cannot be disconnected */ if (fscache_object_p->i_disconnectable == 0) { ret = 1; goto out; } /* if file system is already disconnected */ if (fscache_object_p->i_connected == 0) { ret = 2; goto out; } fscache_object_p->i_simdis = 1; } else { /* if file system is already connected */ if (fscache_object_p->i_connected) { ret = 1; goto out; } /* if file system is not "simulated" disconnected */ if (fscache_object_p->i_simdis == 0) { ret = 2; goto out; } fscache_object_p->i_simdis = 0; } /* if fs thread not running */ if (fscache_object_p->i_threaded == 0) { if (fscache_object_p->i_mounted) { dbug_print(("simdis", "thread not running")); ret = -1; } else { if (fscache_object_p->i_simdis) fscache_object_p->i_connected = 0; else fscache_object_p->i_connected = 1; } goto out; } /* get the attention of the thread */ dbug_print(("info", "thread %d, killing %d with sigusr1", thr_self(), fscache_object_p->i_threadid)); xx = thr_kill(fscache_object_p->i_threadid, SIGUSR1); if (xx) { dbug_print(("simdis", "thr_kill failed %d, threadid %d", xx, fscache_object_p->i_threadid)); ret = -1; } out: fscache_unlock(fscache_object_p); if (ret == 0) { for (;;) { dbug_print(("simdis", " waiting for simulated %s", strp)); fscache_lock(fscache_object_p); tcon = fscache_object_p->i_connected; trec = fscache_object_p->i_reconcile; fscache_unlock(fscache_object_p); if (disconnect) { if (tcon == 0) break; } else { if ((tcon == 1) && (trec == 0)) break; } cfsd_sleep(1); } dbug_print(("simdis", "DONE waiting for simulated %s", strp)); } else { dbug_print(("simdis", "simulated %s failed %d", strp, ret)); } dbug_leave("fscache_simdisconnect"); return (ret); }
/* * 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); }
int fscache_unmount(cfsd_fscache_object_t *fscache_object_p, int flag) { int xx; int ret = 0; dbug_enter("fscache_unmount"); dbug_precond(fscache_object_p); fscache_lock(fscache_object_p); /* if there is a thread running */ if (fscache_object_p->i_threaded) { /* do not bother unmounting if rolling the log */ if (fscache_object_p->i_reconcile) { ret = EBUSY; goto out; } /* inform the thread to try the unmount */ fscache_object_p->i_tryunmount = 1; fscache_object_p->i_modify++; /* get the attention of the thread */ dbug_print(("info", "about to do umount kill")); xx = thr_kill(fscache_object_p->i_threadid, SIGUSR1); if (xx) { dbug_print(("error", "thr_kill failed %d, threadid %d", xx, fscache_object_p->i_threadid)); ret = EIO; goto out; } /* wait for the thread to wake us up */ while (fscache_object_p->i_tryunmount) { xx = cond_wait(&fscache_object_p->i_cvwait, &fscache_object_p->i_lock); dbug_print(("info", "cond_wait woke up %d %d", xx, fscache_object_p->i_tryunmount)); } /* if the file system is still mounted */ if (fscache_object_p->i_mounted) ret = EBUSY; } /* else if there is no thread running */ else { /* try to unmount the file system */ if (umount2(fscache_object_p->i_mntpt, flag) == -1) { xx = errno; dbug_print(("info", "unmount failed %s", strerror(xx))); if (xx == EBUSY) ret = EBUSY; else if (xx == ENOTSUP) ret = ENOTSUP; else ret = EIO; } else { fscache_object_p->i_mounted = 0; fscache_object_p->i_modify++; } } out: fscache_unlock(fscache_object_p); dbug_leave("fscache_unmount"); return (ret); }
/* * ----------------------------------------------------------------- * fscache_server_alive * * Description: * Arguments: * Returns: * Preconditions: */ void fscache_server_alive(cfsd_fscache_object_t *fscache_object_p, cfsd_kmod_object_t *kmod_object_p) { int xx; cfs_fid_t rootfid; dl_cred_t cr; cfs_vattr_t va; char cfsopt[CFS_MAXMNTOPTLEN]; int child_pid; int stat_loc; dbug_enter("fscache_server_alive"); dbug_precond(fscache_object_p); dbug_precond(kmod_object_p); for (;;) { /* wait for a little while */ if (fscache_object_p->i_simdis == 0) cfsd_sleep(30); /* if simulating disconnect */ fscache_lock(fscache_object_p); while (fscache_object_p->i_simdis && !fscache_object_p->i_tryunmount) { dbug_print(("simdis", "before calling cond_wait")); xx = cond_wait(&fscache_object_p->i_cvwait, &fscache_object_p->i_lock); dbug_print(("simdis", "cond_wait woke up %d %d", xx, fscache_object_p->i_simdis)); } fscache_unlock(fscache_object_p); if (fscache_object_p->i_tryunmount) break; /* see if the server is alive */ if (fscache_pingserver(fscache_object_p) == -1) { /* dead server */ continue; } /* try to mount the back file system if needed */ if (fscache_object_p->i_backpath[0] == '\0') { dbug_precond(fscache_object_p->i_cfsopt[0]); dbug_precond(fscache_object_p->i_backfs[0]); dbug_precond(fscache_object_p->i_mntpt[0]); snprintf(cfsopt, sizeof (cfsopt), "%s,slide,remount", fscache_object_p->i_cfsopt); /* * Mounting of a cachefs file system is done by calling * out to /usr/lib/fs/cachefs/mount so that mounts * done by the user, autofs and by us here in cachefsd * are consistent. */ switch ((child_pid = fork1())) { case -1: /* * The original code used system() * but never checked for an error * occurring. The rest of the code * would suggest that "continue" is * the correct thing to do. */ dbug_print(("info", "unable to fork mount " "process for back fs %s %d", fscache_object_p->i_backfs, errno)); continue; case 0: (void) setsid(); execl("/usr/sbin/mount", "mount", "-F", "cachefs", "-o", cfsopt, fscache_object_p->i_backfs, fscache_object_p->i_mntpt, NULL); break; default: (void) waitpid(child_pid, &stat_loc, WUNTRACED); } } /* get the root fid of the file system */ xx = kmod_rootfid(kmod_object_p, &rootfid); if (xx) { dbug_print(("info", "could not mount back fs %s %d", fscache_object_p->i_backfs, xx)); continue; } /* dummy up a fake kcred */ (void) memset(&cr, 0, sizeof (cr)); /* try to get attrs on the root */ xx = kmod_getattrfid(kmod_object_p, &rootfid, &cr, &va); if ((xx == ETIMEDOUT) || (xx == EIO)) { dbug_print(("info", "Bogus error %d", xx)); continue; } break; } dbug_leave("fscache_server_alive"); }