static ssize_t lssu_print_suinfo(__u64 segnum, ssize_t nsi, int all) { struct tm tm; time_t t; char timebuf[LSSU_BUFSIZE]; ssize_t i, n = 0; for (i = 0; i < nsi; i++, segnum++) { if (all || !nilfs_suinfo_clean(&suinfos[i])) { t = (time_t)suinfos[i].sui_lastmod; if (t != 0) { localtime_r(&t, &tm); strftime(timebuf, LSSU_BUFSIZE, "%F %T", &tm); } else snprintf(timebuf, LSSU_BUFSIZE, "---------- --:--:--"); printf("%20llu %s %c%c%c %10u\n", (unsigned long long)segnum, timebuf, nilfs_suinfo_active(&suinfos[i]) ? 'a' : '-', nilfs_suinfo_dirty(&suinfos[i]) ? 'd' : '-', nilfs_suinfo_error(&suinfos[i]) ? 'e' : '-', suinfos[i].sui_nblocks); n++; } } return n; }
static ssize_t lssu_print_suinfo(struct nilfs *nilfs, uint64_t segnum, ssize_t nsi, uint64_t protseq) { struct tm tm; time_t t; char timebuf[LSSU_BUFSIZE]; ssize_t i, n = 0, ret; int ratio; int protected; size_t nliveblks; for (i = 0; i < nsi; i++, segnum++) { if (!all && nilfs_suinfo_clean(&suinfos[i])) continue; t = (time_t)suinfos[i].sui_lastmod; if (t != 0) { localtime_r(&t, &tm); strftime(timebuf, LSSU_BUFSIZE, "%F %T", &tm); } else snprintf(timebuf, LSSU_BUFSIZE, "---------- --:--:--"); switch (disp_mode) { case LSSU_MODE_NORMAL: printf(lssu_format[disp_mode].body, (unsigned long long)segnum, timebuf, nilfs_suinfo_active(&suinfos[i]) ? 'a' : '-', nilfs_suinfo_dirty(&suinfos[i]) ? 'd' : '-', nilfs_suinfo_error(&suinfos[i]) ? 'e' : '-', suinfos[i].sui_nblocks); break; case LSSU_MODE_LATEST_USAGE: nliveblks = 0; ratio = 0; protected = (t >= prottime && t <= now); if (!nilfs_suinfo_dirty(&suinfos[i]) || nilfs_suinfo_error(&suinfos[i])) goto skip_scan; ret = lssu_get_latest_usage(nilfs, segnum, protseq, protcno); if (ret >= 0) { nliveblks = ret; ratio = (ret * 100 + 99) / blocks_per_segment; } else if (likely(ret == -2)) { nliveblks = suinfos[i].sui_nblocks; ratio = 100; protected = 1; } else {
static ssize_t lssu_print_suinfo(struct nilfs *nilfs, __u64 segnum, ssize_t nsi, __u64 protseq, unsigned long* bitmap) { ssize_t i, n = 0; int all = 1; for (i = 0; i < nsi; i++, segnum++) { if (!all && nilfs_suinfo_clean(&suinfos[i])) continue; log_mesg(3, 0, 0, fs_opt.debug, "%s: seg %llu, %c %c %c , %i\n", __FILE__, (unsigned long long)segnum, nilfs_suinfo_active(&suinfos[i]) ? 'a' : '-', nilfs_suinfo_dirty(&suinfos[i]) ? 'd' : '-', nilfs_suinfo_error(&suinfos[i]) ? 'e' : '-', suinfos[i].sui_nblocks); if (nilfs_suinfo_active(&suinfos[i]) || nilfs_suinfo_dirty(&suinfos[i])){ set_bitmap(bitmap, (unsigned long long)segnum, suinfos[i].sui_nblocks); } n++; } return n; }
/** * nilfs_sufile_set_suinfo - sets segment usage info * @sufile: inode of segment usage file * @buf: array of suinfo_update * @supsz: byte size of suinfo_update * @nsup: size of suinfo_update array * * Description: Takes an array of nilfs_suinfo_update structs and updates * segment usage accordingly. Only the fields indicated by the sup_flags * are updated. * * Return Value: On success, 0 is returned. On error, one of the * following negative error codes is returned. * * %-EIO - I/O error. * * %-ENOMEM - Insufficient amount of memory available. * * %-EINVAL - Invalid values in input (segment number, flags or nblocks) */ ssize_t nilfs_sufile_set_suinfo(struct inode *sufile, void *buf, unsigned int supsz, size_t nsup) { struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; struct buffer_head *header_bh, *bh; struct nilfs_suinfo_update *sup, *supend = buf + supsz * nsup; struct nilfs_segment_usage *su; void *kaddr; unsigned long blkoff, prev_blkoff; int cleansi, cleansu, dirtysi, dirtysu; long ncleaned = 0, ndirtied = 0; int ret = 0; if (unlikely(nsup == 0)) return ret; for (sup = buf; sup < supend; sup = (void *)sup + supsz) { if (sup->sup_segnum >= nilfs->ns_nsegments || (sup->sup_flags & (~0UL << __NR_NILFS_SUINFO_UPDATE_FIELDS)) || (nilfs_suinfo_update_nblocks(sup) && sup->sup_sui.sui_nblocks > nilfs->ns_blocks_per_segment)) return -EINVAL; } down_write(&NILFS_MDT(sufile)->mi_sem); ret = nilfs_sufile_get_header_block(sufile, &header_bh); if (ret < 0) goto out_sem; sup = buf; blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum); ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh); if (ret < 0) goto out_header; for (;;) { kaddr = kmap_atomic(bh->b_page, KM_USER0); su = nilfs_sufile_block_get_segment_usage( sufile, sup->sup_segnum, bh, kaddr); if (nilfs_suinfo_update_lastmod(sup)) su->su_lastmod = cpu_to_le64(sup->sup_sui.sui_lastmod); if (nilfs_suinfo_update_nblocks(sup)) su->su_nblocks = cpu_to_le32(sup->sup_sui.sui_nblocks); if (nilfs_suinfo_update_flags(sup)) { /* * Active flag is a virtual flag projected by running * nilfs kernel code - drop it not to write it to * disk. */ sup->sup_sui.sui_flags &= ~(1UL << NILFS_SEGMENT_USAGE_ACTIVE); cleansi = nilfs_suinfo_clean(&sup->sup_sui); cleansu = nilfs_segment_usage_clean(su); dirtysi = nilfs_suinfo_dirty(&sup->sup_sui); dirtysu = nilfs_segment_usage_dirty(su); if (cleansi && !cleansu) ++ncleaned; else if (!cleansi && cleansu) --ncleaned; if (dirtysi && !dirtysu) ++ndirtied; else if (!dirtysi && dirtysu) --ndirtied; su->su_flags = cpu_to_le32(sup->sup_sui.sui_flags); } kunmap_atomic(kaddr, KM_USER0); sup = (void *)sup + supsz; if (sup >= supend) break; prev_blkoff = blkoff; blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum); if (blkoff == prev_blkoff) continue; /* get different block */ mark_buffer_dirty(bh); put_bh(bh); ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh); if (unlikely(ret < 0)) goto out_mark; } mark_buffer_dirty(bh); put_bh(bh); out_mark: if (ncleaned || ndirtied) { nilfs_sufile_mod_counter(header_bh, (u64)ncleaned, (u64)ndirtied); NILFS_SUI(sufile)->ncleansegs += ncleaned; } nilfs_mdt_mark_dirty(sufile); out_header: put_bh(header_bh); out_sem: up_write(&NILFS_MDT(sufile)->mi_sem); return ret; }