static int ubi_attach_fastmap(struct ubi_scan_info *ubi, struct ubi_attach_info *ai, struct ubi_fastmap_layout *fm) { struct ubi_fm_hdr *fmhdr; struct ubi_fm_scan_pool *fmpl1, *fmpl2; struct ubi_fm_ec *fmec; struct ubi_fm_volhdr *fmvhdr; struct ubi_fm_eba *fm_eba; int ret, i, j, pool_size, wl_pool_size; size_t fm_pos = 0, fm_size = ubi->fm_size; void *fm_raw = ubi->fm_buf; memset(ubi->fm_used, 0, sizeof(ubi->fm_used)); fm_pos += sizeof(struct ubi_fm_sb); if (fm_pos >= fm_size) goto fail_bad; fmhdr = (struct ubi_fm_hdr *)(fm_raw + fm_pos); fm_pos += sizeof(*fmhdr); if (fm_pos >= fm_size) goto fail_bad; if (be32_to_cpu(fmhdr->magic) != UBI_FM_HDR_MAGIC) { ubi_err("bad fastmap header magic: 0x%x, expected: 0x%x", be32_to_cpu(fmhdr->magic), UBI_FM_HDR_MAGIC); goto fail_bad; } fmpl1 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos); fm_pos += sizeof(*fmpl1); if (fm_pos >= fm_size) goto fail_bad; if (be32_to_cpu(fmpl1->magic) != UBI_FM_POOL_MAGIC) { ubi_err("bad fastmap pool magic: 0x%x, expected: 0x%x", be32_to_cpu(fmpl1->magic), UBI_FM_POOL_MAGIC); goto fail_bad; } fmpl2 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos); fm_pos += sizeof(*fmpl2); if (fm_pos >= fm_size) goto fail_bad; if (be32_to_cpu(fmpl2->magic) != UBI_FM_POOL_MAGIC) { ubi_err("bad fastmap pool magic: 0x%x, expected: 0x%x", be32_to_cpu(fmpl2->magic), UBI_FM_POOL_MAGIC); goto fail_bad; } pool_size = be16_to_cpu(fmpl1->size); wl_pool_size = be16_to_cpu(fmpl2->size); fm->max_pool_size = be16_to_cpu(fmpl1->max_size); fm->max_wl_pool_size = be16_to_cpu(fmpl2->max_size); if (pool_size > UBI_FM_MAX_POOL_SIZE || pool_size < 0) { ubi_err("bad pool size: %i", pool_size); goto fail_bad; } if (wl_pool_size > UBI_FM_MAX_POOL_SIZE || wl_pool_size < 0) { ubi_err("bad WL pool size: %i", wl_pool_size); goto fail_bad; } if (fm->max_pool_size > UBI_FM_MAX_POOL_SIZE || fm->max_pool_size < 0) { ubi_err("bad maximal pool size: %i", fm->max_pool_size); goto fail_bad; } if (fm->max_wl_pool_size > UBI_FM_MAX_POOL_SIZE || fm->max_wl_pool_size < 0) { ubi_err("bad maximal WL pool size: %i", fm->max_wl_pool_size); goto fail_bad; } /* read EC values from free list */ for (i = 0; i < be32_to_cpu(fmhdr->free_peb_count); i++) { fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos); fm_pos += sizeof(*fmec); if (fm_pos >= fm_size) goto fail_bad; } /* read EC values from used list */ for (i = 0; i < be32_to_cpu(fmhdr->used_peb_count); i++) { fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos); fm_pos += sizeof(*fmec); if (fm_pos >= fm_size) goto fail_bad; generic_set_bit(be32_to_cpu(fmec->pnum), ubi->fm_used); } /* read EC values from scrub list */ for (i = 0; i < be32_to_cpu(fmhdr->scrub_peb_count); i++) { fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos); fm_pos += sizeof(*fmec); if (fm_pos >= fm_size) goto fail_bad; } /* read EC values from erase list */ for (i = 0; i < be32_to_cpu(fmhdr->erase_peb_count); i++) { fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos); fm_pos += sizeof(*fmec); if (fm_pos >= fm_size) goto fail_bad; } /* Iterate over all volumes and read their EBA table */ for (i = 0; i < be32_to_cpu(fmhdr->vol_count); i++) { u32 vol_id, vol_type, used, reserved; fmvhdr = (struct ubi_fm_volhdr *)(fm_raw + fm_pos); fm_pos += sizeof(*fmvhdr); if (fm_pos >= fm_size) goto fail_bad; if (be32_to_cpu(fmvhdr->magic) != UBI_FM_VHDR_MAGIC) { ubi_err("bad fastmap vol header magic: 0x%x, " \ "expected: 0x%x", be32_to_cpu(fmvhdr->magic), UBI_FM_VHDR_MAGIC); goto fail_bad; } vol_id = be32_to_cpu(fmvhdr->vol_id); vol_type = fmvhdr->vol_type; used = be32_to_cpu(fmvhdr->used_ebs); fm_eba = (struct ubi_fm_eba *)(fm_raw + fm_pos); fm_pos += sizeof(*fm_eba); fm_pos += (sizeof(__be32) * be32_to_cpu(fm_eba->reserved_pebs)); if (fm_pos >= fm_size) goto fail_bad; if (be32_to_cpu(fm_eba->magic) != UBI_FM_EBA_MAGIC) { ubi_err("bad fastmap EBA header magic: 0x%x, " \ "expected: 0x%x", be32_to_cpu(fm_eba->magic), UBI_FM_EBA_MAGIC); goto fail_bad; } reserved = be32_to_cpu(fm_eba->reserved_pebs); ubi_dbg("FA: vol %u used %u res: %u", vol_id, used, reserved); for (j = 0; j < reserved; j++) { int pnum = be32_to_cpu(fm_eba->pnum[j]); if ((int)be32_to_cpu(fm_eba->pnum[j]) < 0) continue; if (!__test_and_clear_bit(pnum, ubi->fm_used)) continue; /* * We only handle static volumes so used_ebs * needs to be handed in. And we do not assign * the reserved blocks */ if (j >= used) continue; ret = assign_aeb_to_av(ubi, pnum, j, vol_id, vol_type, used); if (!ret) continue; /* * Nasty: The fastmap claims that the volume * has one block more than it, but that block * is always empty and the other blocks have * the correct number of total LEBs in the * headers. Deal with it. */ if (ret != UBI_IO_FF && j != used - 1) goto fail_bad; ubi_dbg("FA: Vol: %u Ignoring empty LEB %d of %d", vol_id, j, used); } } ret = scan_pool(ubi, fmpl1->pebs, pool_size); if (ret) goto fail; ret = scan_pool(ubi, fmpl2->pebs, wl_pool_size); if (ret) goto fail; #ifdef CHECKME /* * If fastmap is leaking PEBs (must not happen), raise a * fat warning and fall back to scanning mode. * We do this here because in ubi_wl_init() it's too late * and we cannot fall back to scanning. */ if (WARN_ON(count_fastmap_pebs(ai) != ubi->peb_count - ai->bad_peb_count - fm->used_blocks)) goto fail_bad; #endif return 0; fail_bad: ret = UBI_BAD_FASTMAP; fail: return ret; }
int main() { int i; char ipstr[STRSIZE]; struct sockaddr_in laddr; struct sigaction sa,osa1,osa2; sigset_t set,oset; /* signal */ sa.sa_handler = usr2_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIG_NOTIFY,&sa,&osa1); /*if error*/ sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NOCLDWAIT; sigaction(SIGCHLD,&sa,&osa2); /*if error*/ sigemptyset(&set); sigaddset(&set,SIG_NOTIFY); sigprocmask(SIG_BLOCK,&set,&oset); /* init */ serverpool = mmap(NULL,sizeof(struct server_st)*MAXCLIENT,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0); if(serverpool == MAP_FAILED) { perror("mmap()"); exit(1); } for(i = 0 ; i < MAXCLIENT; i++) serverpool[i].pid = -1; /* socket */ sd = socket(AF_INET,SOCK_STREAM,0/*IPPROTO_TCP,IPPROTO_SCTP*/); if(sd < 0) { perror("socket()"); exit(1); } int val = 1; if(setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val)) < 0) { perror("setsockopt()"); exit(1); } laddr.sin_family = AF_INET; laddr.sin_port = htons(atoi(SERVERPORT)); inet_pton(AF_INET,"0.0.0.0",&laddr.sin_addr); if(bind(sd,(void *)&laddr,sizeof(laddr)) < 0) { perror("bind()"); exit(1); } if(listen(sd,200) < 0) { perror("listen()"); exit(1); } for(i = 0 ; i < MINSPARESERVER; i++) add_1_server(); while(1) { sigsuspend(&oset); scan_pool(); if(idle_count > MAXSPARESERVER) { for(i = 0 ; i < idle_count-MAXSPARESERVER; i++) del_1_server(); } else if(idle_count < MINSPARESERVER) { for(i = 0 ; i < MINSPARESERVER-idle_count; i++) add_1_server(); } for(i = 0 ; i < MAXCLIENT; i++) { if(serverpool[i].pid == -1) putchar('n'); else { if(serverpool[i].state == STATE_IDLE) putchar('.'); else putchar('x'); } } printf("\n"); } /*free destroy*/ sigprocmask(SIG_SETMASK,&oset,NULL); exit(0); }