Exemple #1
0
static inline uint8_t sclass_univ_delete_entry(uint8_t nleng,const uint8_t *name,uint16_t esclassid) {
	uint32_t sclassid,fsclassid;
	if (sclass_name_check(nleng,name)==0) {
		return MFS_ERROR_EINVAL;
	}
	fsclassid = 0;
	for (sclassid=1 ; fsclassid==0 && sclassid<firstneverused ; sclassid++) {
		if (sclasstab[sclassid].nleng==nleng && memcmp(sclasstab[sclassid].name,name,nleng)==0) {
			fsclassid = sclassid;
		}
	}
	if (fsclassid==0) {
		return MFS_ERROR_NOSUCHCLASS;
	}
	if (fsclassid<FIRSTSCLASSID) {
		return MFS_ERROR_EPERM;
	}
	if (sclasstab[fsclassid].files>0 || sclasstab[fsclassid].directories>0) {
		return MFS_ERROR_CLASSINUSE;
	}
	if (esclassid!=0 && fsclassid!=esclassid) {
		return MFS_ERROR_MISMATCH;
	}
	sclasstab[fsclassid].nleng = 0;
	if (esclassid==0) {
		changelog("%"PRIu32"|SCDEL(%s):%"PRIu32,main_time(),changelog_escape_name(nleng,name),fsclassid);
	} else {
		meta_version_inc();
	}
	return MFS_STATUS_OK;
}
Exemple #2
0
static inline uint8_t sclass_univ_rename_entry(uint8_t oldnleng,const uint8_t *oldname,uint8_t newnleng,const uint8_t *newname,uint16_t esclassid) {
	uint32_t sclassid,fsclassid;
	if (sclass_name_check(oldnleng,oldname)==0 || sclass_name_check(newnleng,newname)==0) {
		return MFS_ERROR_EINVAL;
	}
	fsclassid = 0;
	for (sclassid=1 ; fsclassid==0 && sclassid<firstneverused ; sclassid++) {
		if (sclasstab[sclassid].nleng==oldnleng && memcmp(sclasstab[sclassid].name,oldname,oldnleng)==0) {
			fsclassid = sclassid;
		}
	}
	if (fsclassid==0) {
		return MFS_ERROR_NOSUCHCLASS;
	}
	if (fsclassid<FIRSTSCLASSID) {
		return MFS_ERROR_EPERM;
	}
	if (esclassid!=0 && fsclassid!=esclassid) {
		return MFS_ERROR_MISMATCH;
	}
	for (sclassid=1 ; sclassid<firstneverused ; sclassid++) {
		if (sclasstab[sclassid].nleng==newnleng && memcmp(sclasstab[sclassid].name,newname,newnleng)==0) {
			return MFS_ERROR_CLASSEXISTS;
		}
	}
	sclasstab[fsclassid].nleng = newnleng;
	memcpy(sclasstab[fsclassid].name,newname,newnleng);
	if (esclassid==0) {
		changelog("%"PRIu32"|SCREN(%s,%s):%"PRIu32,main_time(),changelog_escape_name(oldnleng,oldname),changelog_escape_name(newnleng,newname),fsclassid);
	} else {
		meta_version_inc();
	}
	return MFS_STATUS_OK;
}
Exemple #3
0
void csdb_disconnectcheck(void) {
	static uint8_t laststate=0;
	if (disconnected_servers && laststate==0) {
		disconnecttime = main_time();
		laststate = 1;
	} else if (disconnected_servers==0) {
		disconnecttime = 0;
		laststate = 0;
	}
}
Exemple #4
0
void masterconn_serve(struct pollfd *pdesc) {
    uint32_t now=main_time();
    packetstruct *pptr,*paptr;
    masterconn *eptr = masterconnsingleton;

    if (eptr->pdescpos>=0 && (pdesc[eptr->pdescpos].revents & (POLLHUP | POLLERR))) {
        if (eptr->mode==CONNECTING) {
            masterconn_connecttest(eptr);
        } else {
            eptr->mode = KILL;
        }
    }
    if (eptr->mode==CONNECTING) {
        if (eptr->sock>=0 && eptr->pdescpos>=0 && (pdesc[eptr->pdescpos].revents & POLLOUT)) { // FD_ISSET(eptr->sock,wset)) {
            masterconn_connecttest(eptr);
        }
    } else {
        if (eptr->pdescpos>=0) {
            if ((eptr->mode==HEADER || eptr->mode==DATA) && (pdesc[eptr->pdescpos].revents & POLLIN)) { // FD_ISSET(eptr->sock,rset)) {
                eptr->lastread = now;
                masterconn_read(eptr);
            }
            if ((eptr->mode==HEADER || eptr->mode==DATA) && (pdesc[eptr->pdescpos].revents & POLLOUT)) { // FD_ISSET(eptr->sock,wset)) {
                eptr->lastwrite = now;
                masterconn_write(eptr);
            }
            if ((eptr->mode==HEADER || eptr->mode==DATA) && eptr->lastread+Timeout<now) {
                eptr->mode = KILL;
            }
            if ((eptr->mode==HEADER || eptr->mode==DATA) && eptr->lastwrite+(Timeout/3)<now && eptr->outputhead==NULL) {
                masterconn_createpacket(eptr,ANTOAN_NOP,0);
            }
        }
    }
    if (eptr->mode == KILL) {
        masterconn_beforeclose(eptr);
        tcpclose(eptr->sock);
        if (eptr->inputpacket.packet) {
            free(eptr->inputpacket.packet);
        }
        pptr = eptr->outputhead;
        while (pptr) {
            if (pptr->packet) {
                free(pptr->packet);
            }
            paptr = pptr;
            pptr = pptr->next;
            free(paptr);
        }
        eptr->mode = FREE;
    }
}
Exemple #5
0
void masterconn_connected(masterconn *eptr) {
    tcpnodelay(eptr->sock);
    eptr->mode=HEADER;
    eptr->inputpacket.next = NULL;
    eptr->inputpacket.bytesleft = 8;
    eptr->inputpacket.startptr = eptr->hdrbuff;
    eptr->inputpacket.packet = NULL;
    eptr->outputhead = NULL;
    eptr->outputtail = &(eptr->outputhead);

    masterconn_sendregister(eptr);
    masterconn_metadownloadinit();
    eptr->lastread = eptr->lastwrite = main_time();
}
Exemple #6
0
void chartsdata_refresh(void) {
	uint64_t data[CHARTS];
	uint32_t fsdata[16];
	uint32_t i,del,repl; //,bin,bout,opr,opw,dbr,dbw,dopr,dopw,repl;
	struct itimerval uc,pc;
	uint32_t ucusec,pcusec;

	for (i=0 ; i<CHARTS ; i++) {
		data[i]=0;
	}

	setitimer(ITIMER_VIRTUAL,&it_set,&uc);             // user time
	setitimer(ITIMER_PROF,&it_set,&pc);                // user time + system time

	if (uc.it_value.tv_sec<=999) {	// on fucken linux timers can go backward !!!
		uc.it_value.tv_sec = 999-uc.it_value.tv_sec;
		uc.it_value.tv_usec = 999999-uc.it_value.tv_usec;
	} else {
		uc.it_value.tv_sec = 0;
		uc.it_value.tv_usec = 0;
	}
	if (pc.it_value.tv_sec<=999) {	// as abowe - who the hell has invented this stupid os !!!
		pc.it_value.tv_sec = 999-pc.it_value.tv_sec;
		pc.it_value.tv_usec = 999999-pc.it_value.tv_usec;
	} else {
		pc.it_value.tv_sec = 0;
		uc.it_value.tv_usec = 0;
	}

	ucusec = uc.it_value.tv_sec*1000000+uc.it_value.tv_usec;
	pcusec = pc.it_value.tv_sec*1000000+pc.it_value.tv_usec;

	if (pcusec>ucusec) {
		pcusec-=ucusec;
	} else {
		pcusec=0;
	}
	data[CHARTS_UCPU] = ucusec;
	data[CHARTS_SCPU] = pcusec;

	chunk_stats(&del,&repl);
	data[CHARTS_DELCHUNK]=del;
	data[CHARTS_REPLCHUNK]=repl;
	fs_stats(fsdata);
	for (i=0 ; i<16 ; i++) {
		data[CHARTS_STATFS+i]=fsdata[i];
	}

	charts_add(data,main_time()-60);
}
Exemple #7
0
//向Master注册,调用masterconn_sendregister()封装注册packet
//调用:masterconn_initconnect()
void masterconn_connected(masterconn *eptr) {
#ifdef BGJOBS
	eptr->jpool = job_pool_new(10,BGJOBSCNT,&(eptr->jobfd));
#endif
	tcpnodelay(eptr->sock);
	eptr->mode=HEADER;
	eptr->inputpacket.next = NULL;
	eptr->inputpacket.bytesleft = 8;
	eptr->inputpacket.startptr = eptr->hdrbuff;
	eptr->inputpacket.packet = NULL;
	eptr->outputhead = NULL;
	eptr->outputtail = &(eptr->outputhead);

	masterconn_sendregister(eptr);
	eptr->lastread = eptr->lastwrite = main_time();
}
Exemple #8
0
static inline void changelog_store_logstring(uint64_t version,uint8_t *logstr,uint32_t logstrsize) {
	old_changes_block *oc;
	old_changes_entry *oce;
	uint32_t ts;

	matomlserv_broadcast_logstring(version,logstr,logstrsize);
//	matomaserv_broadcast_logstring(version,(uint8_t*)printbuff,leng);

	if (ChangelogSecondsToRemember==0) {
		while (old_changes_head) {
			oc = old_changes_head->next;
			changelog_old_changes_free_block(old_changes_head);
			old_changes_head = oc;
		}
		return;
	}
	if (old_changes_current==NULL || old_changes_head==NULL || old_changes_current->entries>=OLD_CHANGES_BLOCK_SIZE) {
		oc = malloc(sizeof(old_changes_block));
		passert(oc);
		ts = main_time();
		oc->entries = 0;
		oc->minversion = version;
		oc->mintimestamp = ts;
		oc->next = NULL;
		if (old_changes_current==NULL || old_changes_head==NULL) {
			old_changes_head = old_changes_current = oc;
		} else {
			old_changes_current->next = oc;
			old_changes_current = oc;
		}
		while (old_changes_head && old_changes_head->next && old_changes_head->next->mintimestamp+ChangelogSecondsToRemember<ts) {
			oc = old_changes_head->next;
			changelog_old_changes_free_block(old_changes_head);
			old_changes_head = oc;
		}
	}
	oc = old_changes_current;
	oce = oc->old_changes_block + oc->entries;
	oce->version = version;
	oce->length = logstrsize;
	oce->data = malloc(logstrsize);
	passert(oce->data);
	memcpy(oce->data,logstr,logstrsize);
	oc->entries++;
}
Exemple #9
0
void matomlserv_serve(struct pollfd *pdesc) {
	uint32_t now=main_time();
	matomlserventry *eptr,**kptr;
	packetstruct *pptr,*paptr;
	int ns;
	static uint64_t lastaction = 0;
	uint64_t unow;
	uint32_t timeoutadd;

	if (lastaction==0) {
		lastaction = main_precise_utime();
	}

	if (lsockpdescpos>=0 && (pdesc[lsockpdescpos].revents & POLLIN)) {
		ns=tcpaccept(lsock);
		if (ns<0) {
			mfs_errlog_silent(LOG_NOTICE,"Master<->ML socket: accept error");
		} else {
			tcpnonblock(ns);
			tcpnodelay(ns);
			eptr = malloc(sizeof(matomlserventry));
			passert(eptr);
			eptr->next = matomlservhead;
			matomlservhead = eptr;
			eptr->sock = ns;
			eptr->pdescpos = -1;
			eptr->mode = HEADER;
			eptr->lastread = now;
			eptr->lastwrite = now;
			eptr->inputpacket.next = NULL;
			eptr->inputpacket.bytesleft = 8;
			eptr->inputpacket.startptr = eptr->hdrbuff;
			eptr->inputpacket.packet = NULL;
			eptr->outputhead = NULL;
			eptr->outputtail = &(eptr->outputhead);
			eptr->timeout = 10;

			tcpgetpeer(eptr->sock,&(eptr->servip),NULL);
			eptr->servstrip = matomlserv_makestrip(eptr->servip);
			eptr->version=0;
			eptr->metafd=-1;
			eptr->chain1fd=-1;
			eptr->chain2fd=-1;
            eptr->logindex=-1;
            eptr->logf=NULL;
            eptr->currentversion=0;
		}
	}

// read
	for (eptr=matomlservhead ; eptr ; eptr=eptr->next) {
		if (eptr->pdescpos>=0) {
			if (pdesc[eptr->pdescpos].revents & (POLLERR|POLLHUP)) {
				eptr->mode = KILL;
			}
			if ((pdesc[eptr->pdescpos].revents & POLLIN) && eptr->mode!=KILL) {
				eptr->lastread = now;
				matomlserv_read(eptr);
			}
		}
	}

// timeout fix
	unow = main_precise_utime();
	timeoutadd = (unow-lastaction)/1000000;
	if (timeoutadd) {
		for (eptr=matomlservhead ; eptr ; eptr=eptr->next) {
			eptr->lastread += timeoutadd;
		}
	}
	lastaction = unow;

// write
	for (eptr=matomlservhead ; eptr ; eptr=eptr->next) {
		if ((uint32_t)(eptr->lastwrite+(eptr->timeout/3))<(uint32_t)now && eptr->outputhead==NULL) {
			matomlserv_createpacket(eptr,ANTOAN_NOP,0);
		}
		if (eptr->pdescpos>=0) {
			if ((((pdesc[eptr->pdescpos].events & POLLOUT)==0 && (eptr->outputhead)) || (pdesc[eptr->pdescpos].revents & POLLOUT)) && eptr->mode!=KILL) {
				eptr->lastwrite = now;
				matomlserv_write(eptr);
			}
            if (eptr->mode!=KILL && eptr->logf && eptr->outputhead==NULL) {
                matomlserv_send_old_changes(eptr, eptr->currentversion);
            }
		}
		if ((uint32_t)(eptr->lastread+eptr->timeout)<(uint32_t)now) {
			eptr->mode = KILL;
		}
	}

// close
	kptr = &matomlservhead;
	while ((eptr=*kptr)) {
		if (eptr->mode == KILL) {
			matomlserv_beforeclose(eptr);
			tcpclose(eptr->sock);
			if (eptr->inputpacket.packet) {
				free(eptr->inputpacket.packet);
			}
			pptr = eptr->outputhead;
			while (pptr) {
				if (pptr->packet) {
					free(pptr->packet);
				}
				paptr = pptr;
				pptr = pptr->next;
				free(paptr);
			}
			if (eptr->servstrip) {
				free(eptr->servstrip);
			}
			*kptr = eptr->next;
			free(eptr);
		} else {
			kptr = &(eptr->next);
		}
	}
}
Exemple #10
0
static inline void flock_lock_remove(lock *l) {
	if (l->state==STATE_ACTIVE) {
		changelog("%"PRIu32"|FLOCK(%"PRIu32",%"PRIu32",%"PRIu64",U)",main_time(),l->parent->inode,l->sessionid,l->owner);
	}
	flock_do_lock_remove(l);
}
Exemple #11
0
static inline void flock_lock_inode_attach(lock *l) {
	if (l->state==STATE_ACTIVE) {
		changelog("%"PRIu32"|FLOCK(%"PRIu32",%"PRIu32",%"PRIu64",%c)",main_time(),l->parent->inode,l->sessionid,l->owner,l->ltype==LTYPE_READER?'R':'W');
	}
	flock_do_lock_inode_attach(l);
}
Exemple #12
0
void chartsdata_refresh(void) {
    uint64_t data[CHARTS];
    uint32_t i,bin,bout,opr,opw,dbr,dbw,dopr,dopw,repl;
    uint32_t op_cr,op_de,op_ve,op_du,op_tr,op_dt,op_te;
    uint32_t csservjobs,masterjobs;
    struct itimerval uc,pc;
    uint32_t ucusec,pcusec;
//	struct rusage sru,chru;
//	long ru_nswap,ru_minflt,ru_majflt,ru_inblock,ru_oublock,ru_nvcsw,ru_nivcsw;
//	static long l_nswap=0,l_minflt=0,l_majflt=0,l_inblock=0,l_oublock=0,l_nvcsw=0,l_nivcsw=0;

    for (i=0 ; i<CHARTS ; i++) {
        data[i]=0;
    }

//	getrusage(RUSAGE_SELF,&sru);
//	getrusage(RUSAGE_CHILDREN,&chru);

//	ru_minflt = sru.ru_minflt + chru.ru_minflt;
//	ru_majflt = sru.ru_majflt + chru.ru_majflt;
//	ru_nswap = sru.ru_nswap + chru.ru_nswap;
//	ru_inblock = sru.ru_inblock + chru.ru_inblock;
//	ru_oublock = sru.ru_oublock + chru.ru_oublock;
//	ru_nvcsw = sru.ru_nvcsw + chru.ru_nvcsw;
//	ru_nivcsw = sru.ru_nivcsw + chru.ru_nivcsw;
//	data[CHARTS_MINFLT] = ru_minflt - l_minflt;
//	data[CHARTS_MAJFLT] = ru_majflt - l_majflt;
//	data[CHARTS_NSWAP] = ru_nswap - l_nswap;
//	data[CHARTS_INBLOCK] = ru_inblock - l_inblock;
//	data[CHARTS_OUBLOCK] = ru_oublock - l_oublock;
//	data[CHARTS_NVCSW] = ru_nvcsw - l_nvcsw;
//	data[CHARTS_NIVCSW] = ru_nivcsw - l_nivcsw;
//	l_minflt = ru_minflt;
//	l_majflt = ru_majflt;
//	l_nswap = ru_nswap;
//	l_inblock = ru_inblock;
//	l_oublock = ru_oublock;
//	l_nvcsw = ru_nvcsw;
//	l_nivcsw = ru_nivcsw;

    setitimer(ITIMER_VIRTUAL,&it_set,&uc);             // user time
    setitimer(ITIMER_PROF,&it_set,&pc);                // user time + system time

    if (uc.it_value.tv_sec<=999) {	// on fucken linux timers can go backward !!!
        uc.it_value.tv_sec = 999-uc.it_value.tv_sec;
        uc.it_value.tv_usec = 999999-uc.it_value.tv_usec;
    } else {
        uc.it_value.tv_sec = 0;
        uc.it_value.tv_usec = 0;
    }
    if (pc.it_value.tv_sec<=999) {	// as abowe - who the hell has invented this stupid os !!!
        pc.it_value.tv_sec = 999-pc.it_value.tv_sec;
        pc.it_value.tv_usec = 999999-pc.it_value.tv_usec;
    } else {
        pc.it_value.tv_sec = 0;
        uc.it_value.tv_usec = 0;
    }

    ucusec = uc.it_value.tv_sec*1000000+uc.it_value.tv_usec;
    pcusec = pc.it_value.tv_sec*1000000+pc.it_value.tv_usec;

    if (pcusec>ucusec) {
        pcusec-=ucusec;
    } else {
        pcusec=0;
    }
    data[CHARTS_UCPU] = ucusec;
    data[CHARTS_SCPU] = pcusec;

    masterconn_stats(&bin,&bout,&masterjobs);
    data[CHARTS_MASTERIN]=bin;
    data[CHARTS_MASTEROUT]=bout;
    data[CHARTS_CHUNKOPJOBS]=masterjobs;
//	cstocsconn_stats(&bin,&bout);
//	data[CHARTS_CSCONNIN]=bin;
//	data[CHARTS_CSCONNOUT]=bout;
    data[CHARTS_CSCONNIN]=0;
    data[CHARTS_CSCONNOUT]=0;
    csserv_stats(&bin,&bout,&opr,&opw,&csservjobs);
    data[CHARTS_CSSERVIN]=bin;
    data[CHARTS_CSSERVOUT]=bout;
    data[CHARTS_CHUNKIOJOBS]=csservjobs;
    data[CHARTS_HLOPR]=opr;
    data[CHARTS_HLOPW]=opw;
    hdd_stats(&bin,&bout,&opr,&opw,&dbr,&dbw,&dopr,&dopw,data+CHARTS_RTIME,data+CHARTS_WTIME);
    data[CHARTS_BYTESR]=bin;
    data[CHARTS_BYTESW]=bout;
    data[CHARTS_LLOPR]=opr;
    data[CHARTS_LLOPW]=opw;
    data[CHARTS_DATABYTESR]=dbr;
    data[CHARTS_DATABYTESW]=dbw;
    data[CHARTS_DATALLOPR]=dopr;
    data[CHARTS_DATALLOPW]=dopw;
    replicator_stats(&repl);
    data[CHARTS_REPL]=repl;
    hdd_op_stats(&op_cr,&op_de,&op_ve,&op_du,&op_tr,&op_dt,&op_te);
    data[CHARTS_CREATE]=op_cr;
    data[CHARTS_DELETE]=op_de;
    data[CHARTS_VERSION]=op_ve;
    data[CHARTS_DUPLICATE]=op_du;
    data[CHARTS_TRUNCATE]=op_tr;
    data[CHARTS_DUPTRUNC]=op_dt;
    data[CHARTS_TEST]=op_te;

    charts_add(data,main_time()-60);
}
Exemple #13
0
static inline void sclass_make_changelog(uint16_t sclassid,uint8_t new_flag) {
	uint32_t i,j;
	char chlogstr[CHLOGSTRSIZE];
	int chlogstrleng;

	chlogstrleng=0;
	for (i=0 ; i<sclasstab[sclassid].create_labelscnt ; i++) {
		for (j=0 ; j<MASKORGROUP ; j++) {
			if (chlogstrleng<CHLOGSTRSIZE) {
				chlogstrleng += snprintf(chlogstr+chlogstrleng,CHLOGSTRSIZE-chlogstrleng,"%"PRIu32",",sclasstab[sclassid].create_labelmasks[i][j]);
			}
		}
	}
	for (i=0 ; i<sclasstab[sclassid].keep_labelscnt ; i++) {
		for (j=0 ; j<MASKORGROUP ; j++) {
			if (chlogstrleng<CHLOGSTRSIZE) {
				chlogstrleng += snprintf(chlogstr+chlogstrleng,CHLOGSTRSIZE-chlogstrleng,"%"PRIu32",",sclasstab[sclassid].keep_labelmasks[i][j]);
			}
		}
	}
	for (i=0 ; i<sclasstab[sclassid].arch_labelscnt ; i++) {
		for (j=0 ; j<MASKORGROUP ; j++) {
			if (chlogstrleng<CHLOGSTRSIZE) {
				chlogstrleng += snprintf(chlogstr+chlogstrleng,CHLOGSTRSIZE-chlogstrleng,"%"PRIu32",",sclasstab[sclassid].arch_labelmasks[i][j]);
			}
		}
	}
	if (chlogstrleng>0) {
		chlogstr[chlogstrleng-1]='\0';
	} else {
		chlogstr[0]='-';
		chlogstr[1]='\0';
	}
	changelog("%"PRIu32"|SCSET(%s,%"PRIu8",W%"PRIu8",K%"PRIu8",A%"PRIu8",%"PRIu8",%"PRIu16",%"PRIu8",%s):%"PRIu16,main_time(),changelog_escape_name(sclasstab[sclassid].nleng,sclasstab[sclassid].name),new_flag,sclasstab[sclassid].create_labelscnt,sclasstab[sclassid].keep_labelscnt,sclasstab[sclassid].arch_labelscnt,sclasstab[sclassid].create_mode,sclasstab[sclassid].arch_delay,sclasstab[sclassid].admin_only,chlogstr,sclassid);

}
Exemple #14
0
static inline uint8_t sclass_univ_duplicate_entry(uint8_t oldnleng,const uint8_t *oldname,uint8_t newnleng,const uint8_t *newname,uint16_t essclassid,uint16_t edsclassid) {
	uint32_t sclassid,fssclassid,fdsclassid;
	uint32_t i;
	if (sclass_name_check(oldnleng,oldname)==0 || sclass_name_check(newnleng,newname)==0 || (essclassid==0 && edsclassid>0) || (edsclassid==0 && essclassid>0)) {
		return MFS_ERROR_EINVAL;
	}
	fssclassid = 0;
	for (sclassid=1 ; fssclassid==0 && sclassid<firstneverused ; sclassid++) {
		if (sclasstab[sclassid].nleng==oldnleng && memcmp(sclasstab[sclassid].name,oldname,oldnleng)==0) {
			fssclassid = sclassid;
		}
	}
	if (fssclassid==0) {
		return MFS_ERROR_NOSUCHCLASS;
	}
	if (essclassid!=0 && fssclassid!=essclassid) {
		return MFS_ERROR_MISMATCH;
	}
	fdsclassid = 0;
	for (sclassid=1 ; sclassid<firstneverused ; sclassid++) {
		if (sclasstab[sclassid].nleng==newnleng && memcmp(sclasstab[sclassid].name,newname,newnleng)==0) {
			return MFS_ERROR_CLASSEXISTS;
		}
		if (sclasstab[sclassid].nleng==0 && fdsclassid==0) {
			fdsclassid = sclassid;
		}
	}
	if (fdsclassid==0) {
		if (firstneverused==MAXSCLASS) {
			return MFS_ERROR_CLASSLIMITREACH;
		}
		fdsclassid = firstneverused;
		firstneverused++;
	}
	if (edsclassid!=0 && fdsclassid!=edsclassid) {
		return MFS_ERROR_MISMATCH;
	}
	sclasstab[fdsclassid].nleng = newnleng;
	memcpy(sclasstab[fdsclassid].name,newname,newnleng);
	sclasstab[fdsclassid].admin_only = sclasstab[fssclassid].admin_only;
	sclasstab[fdsclassid].create_mode = sclasstab[fssclassid].create_mode;
	sclasstab[fdsclassid].create_labelscnt = sclasstab[fssclassid].create_labelscnt;
	for (i=0 ; i<sclasstab[fssclassid].create_labelscnt ; i++) {
		memcpy(sclasstab[fdsclassid].create_labelmasks[i],sclasstab[fssclassid].create_labelmasks[i],MASKORGROUP*sizeof(uint32_t));
	}
	sclasstab[fdsclassid].has_create_labels = sclasstab[fssclassid].has_create_labels;
	sclasstab[fdsclassid].keep_labelscnt = sclasstab[fssclassid].keep_labelscnt;
	for (i=0 ; i<sclasstab[fssclassid].keep_labelscnt ; i++) {
		memcpy(sclasstab[fdsclassid].keep_labelmasks[i],sclasstab[fssclassid].keep_labelmasks[i],MASKORGROUP*sizeof(uint32_t));
	}
	sclasstab[fdsclassid].has_keep_labels = sclasstab[fssclassid].has_keep_labels;
	sclasstab[fdsclassid].arch_labelscnt = sclasstab[fssclassid].arch_labelscnt;
	for (i=0 ; i<sclasstab[fssclassid].arch_labelscnt ; i++) {
		memcpy(sclasstab[fdsclassid].arch_labelmasks[i],sclasstab[fssclassid].arch_labelmasks[i],MASKORGROUP*sizeof(uint32_t));
	}
	sclasstab[fdsclassid].has_arch_labels = sclasstab[fssclassid].has_arch_labels;
	sclasstab[fdsclassid].arch_delay = sclasstab[fssclassid].arch_delay;
	if (essclassid==0 && edsclassid==0) {
		changelog("%"PRIu32"|SCDUP(%s,%s):%"PRIu32",%"PRIu32,main_time(),changelog_escape_name(oldnleng,oldname),changelog_escape_name(newnleng,newname),fssclassid,fdsclassid);
	} else {
		meta_version_inc();
	}
	return MFS_STATUS_OK;
}