ceph 集群空间使用情况

| 分类 ceph-internal  | 标签 ceph 

前言

部署ceph集群之后,会比较关心其存储集群的容量,包括总容量、已用容量,剩余容量。 今天之所以想写一篇文章介绍这个topic,源自一个很有意思的事情。

注意在上图中,pool01 是一个三副本的pool,该pool中USED是9086GB,按照三副本计算,其消耗的空间应该是:

9086* 3 = 27258GB

但是实际上, GLOBAL中AVAIL为25571GB,仅算pool 01 也少消耗了1T多,遑论还有其他的pool中也有不可忽视的数据。

为什么GLOBAL中 USED的空间要明显低于 所有的pool中USED的总和呢?

我们下面细细分析这部分逻辑。

ceph df 代码流程梳理

我们首先给出一个真实环境中的 ceph df的输出:

GLOBAL:
    SIZE      AVAIL     RAW USED     %RAW USED 
    2924T     1072T        1851T         63.32 
POOLS:
    NAME                   ID     USED       %USED     MAX AVAIL     OBJECTS  
    rbd                    0           0         0          188T            0 
    .ezs3                  1           0         0          188T            1 
    data                   2         230         0          188T      5071558 
    metadata               3      63358k         0          188T      1635135 
    .rgw.buckets           4           0         0          188T            0 
    .ezs3.central.log      5        386k         0          188T         1049 
    .ezs3.statistic        6      33879k         0          188T          530 
    .rgw.root              7         840         0          188T            3 
    .rgw.control           8           0         0          188T            8 
    .rgw                   9         207         0          188T            1 
    .rgw.gc                10          0         0          188T           32 
    .users.uid             11       6210         0          188T           12 
    .users.email           12        158         0          188T           12 
    .users                 13        158         0          188T           12 
    .users.swift           14        307         0          188T           23 
    .usage                 17          0         0          188T            2 
    pool                   18       917T     31.37          188T     37175243 
    yunweibu               19      4201G      0.14          186T       306273 
    .rgw.buckets.index     20          0         0          188T            1 
    rujiaTR                21      1981M         0          188T          698 
    rujiaAD                22      2012M         0          188T          652 

上面是一个真实ceph集群的空间使用情况,通过GLOBAL统计,我们可以看到,总空间2924T,用户已经使用了1851T,剩余空间1072T,注意,用户所有的pool都是双副本。也就是说,用户的数据在920+T。而剩余的1072T,还能存放500T左右的用户数据。

注意各个pool使用量(USED一栏) , 乘以副本个数,是和GLOBAL中的RAW USED 一栏是非常逼近的。 这也是符合我们的直观认识。

但是也有情况是前言的哪种,即各个Pool计算的USED以及考虑副本之后,和GLOBAL中的RAW USED 相去甚远,不能忽略其差距。

为何?

我们要细细考虑GLOBAL和POOL的数据来源是不同的。

源码分析之源头

ceph df这个命令,是由ceph-mon负责处理的。在Monitor::hanlde_command 函数中:

else if (prefix == "df") {
      bool verbose = (detail == "detail");
      if (f)
        f->open_object_section("stats");

      pgmon()->dump_fs_stats(ds, f.get(), verbose);
      if (!f) 
        ds << '\n';
      pgmon()->dump_pool_stats(ds, f.get(), verbose);

      if (f) {
        f->close_section();
        f->flush(ds);
        ds << '\n';
      }    
    }

从上述代码中可以看出来,数据分成两段

  • pgmon()->dump_fs_stats
  • pgmon()->dump_pool_stats

第一段是dump_fs_stat,也就是我们看到的GLOBAL,第二段是统计pool的,也就就是我们看到的POOL 。

dump_fs_stats

void PGMonitor::dump_fs_stats(stringstream &ss, Formatter *f, bool verbose)
{
  if (f) {
    f->open_object_section("stats");
    f->dump_int("total_bytes", pg_map.osd_sum.kb * 1024ull);
    f->dump_int("total_used_bytes", pg_map.osd_sum.kb_used * 1024ull);
    f->dump_int("total_avail_bytes", pg_map.osd_sum.kb_avail * 1024ull);
    if (verbose) {
      f->dump_int("total_objects", pg_map.pg_sum.stats.sum.num_objects);
    }
    f->close_section();
  } else {
    TextTable tbl;
    tbl.define_column("SIZE", TextTable::LEFT, TextTable::RIGHT);
    tbl.define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT);
    tbl.define_column("RAW USED", TextTable::LEFT, TextTable::RIGHT);
    tbl.define_column("%RAW USED", TextTable::LEFT, TextTable::RIGHT);
    if (verbose) {
      tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT);
    }
    tbl << stringify(si_t(pg_map.osd_sum.kb*1024))
        << stringify(si_t(pg_map.osd_sum.kb_avail*1024))
        << stringify(si_t(pg_map.osd_sum.kb_used*1024));
    float used = 0.0;
    if (pg_map.osd_sum.kb > 0) { 
      used = ((float)pg_map.osd_sum.kb_used / pg_map.osd_sum.kb);
    }
    tbl << percentify(used*100);
    if (verbose) {
       tbl << stringify(si_t(pg_map.pg_sum.stats.sum.num_objects));
    }
    tbl << TextTable::endrow;
    ss << "GLOBAL:\n";
    tbl.set_indent(4);
    ss << tbl;
  }
}

可以看到相关字段数值的输出主要依赖pg_map.osd_sum的值,而osd_sum是各个osd_stat的总和。所以我们需要知道单个osd的osd_stat_t是如何计算的。

单个osd_stat_t的计算在update_osd_stat 函数中:

void OSDService::update_osd_stat(vector<int>& hb_peers)
{
  Mutex::Locker lock(stat_lock);

  // fill in osd stats too
  struct statfs stbuf;
  /*注意OSD的store是FileStore*/
  osd->store->statfs(&stbuf);

  uint64_t bytes = stbuf.f_blocks * stbuf.f_bsize;
  uint64_t used = (stbuf.f_blocks - stbuf.f_bfree) * stbuf.f_bsize;
  uint64_t avail = stbuf.f_bavail * stbuf.f_bsize;

  osd_stat.kb = bytes >> 10;
  osd_stat.kb_used = used >> 10;
  osd_stat.kb_avail = avail >> 10;

  osd->logger->set(l_osd_stat_bytes, bytes);
  osd->logger->set(l_osd_stat_bytes_used, used);
  osd->logger->set(l_osd_stat_bytes_avail, avail);  
  
  osd_stat.hb_in.swap(hb_peers);
  osd_stat.hb_out.clear();

  check_nearfull_warning(osd_stat);

  osd->op_tracker.get_age_ms_histogram(&osd_stat.op_queue_age_hist);

  dout(20) << "update_osd_stat " << osd_stat << dendl;
}

注意,OSD的store的实例是FileStore,而FileStore的statfs实现如下:

int FileStore::statfs(struct statfs *buf)                          
{
  // basedir and current_fn are different fs if the backend is ZFS
  // we return current_fn statfs here because basedir only contains metadata and its size can be ignored.
  if (::statfs(current_fn.c_str(), buf) < 0) {
    int r = -errno;
    assert(!m_filestore_fail_eio || r != -EIO);
    return r;
  }
  return 0;
}

而这个就是我们常说的statfs,可以通过stat -f 这个shell命令查看OSD FileStore所在的本地文件系统的统计信息。

总结: ceph df输出中,GLOBAL一项,来源自OSD 所属Store,我们默认是FileStore对应的本地文件系统使用情况统计,这个统计和我们传统意义上的磁盘空间使用是一致的,比较准确地反应出了所有OSD的文件系统的 总体使用量和总体剩余空间。

dump_pool_stats

void PGMonitor::dump_pool_stats(stringstream &ss, Formatter *f, bool verbose) 
{
  TextTable tbl; 
  
  if (f) {
    f->open_array_section("pools");
  } else {
    tbl.define_column("NAME", TextTable::LEFT, TextTable::LEFT);
    tbl.define_column("ID", TextTable::LEFT, TextTable::LEFT);
    if (verbose)
      tbl.define_column("CATEGORY", TextTable::LEFT, TextTable::LEFT);
    tbl.define_column("USED", TextTable::LEFT, TextTable::RIGHT);
    tbl.define_column("%USED", TextTable::LEFT, TextTable::RIGHT);
    tbl.define_column("MAX AVAIL", TextTable::LEFT, TextTable::RIGHT);
    tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT);
    if (verbose) {
      tbl.define_column("DIRTY", TextTable::LEFT, TextTable::RIGHT);
      tbl.define_column("READ", TextTable::LEFT, TextTable::RIGHT);
      tbl.define_column("WRITE", TextTable::LEFT, TextTable::RIGHT);
    }    
  }
  
  map<int,uint64_t> avail_by_rule;
  OSDMap &osdmap = mon->osdmon()->osdmap;
  for (map<int64_t,pg_pool_t>::const_iterator p = osdmap.get_pools().begin();
       p != osdmap.get_pools().end(); ++p) {
    int64_t pool_id = p->first;
    if ((pool_id < 0) || (pg_map.pg_pool_sum.count(pool_id) == 0))
      continue;
    const string& pool_name = osdmap.get_pool_name(pool_id);
    pool_stat_t &stat = pg_map.pg_pool_sum[pool_id];
    
    const pg_pool_t *pool = osdmap.get_pg_pool(pool_id);
    int ruleno = osdmap.crush->find_rule(pool->get_crush_ruleset(),
                                         pool->get_type(),
                                         pool->get_size());
    int64_t avail;
    if (avail_by_rule.count(ruleno) == 0) {
      avail = get_rule_avail(osdmap, ruleno);
      if (avail < 0)
        avail = 0;
      avail_by_rule[ruleno] = avail;
    } else {
      avail = avail_by_rule[ruleno];
    }
    switch (pool->get_type()) {
    case pg_pool_t::TYPE_REPLICATED:
      avail /= pool->get_size();
      break;
    case pg_pool_t::TYPE_ERASURE:
      {
        const map<string,string>& ecp =
          osdmap.get_erasure_code_profile(pool->erasure_code_profile);
        map<string,string>::const_iterator pm = ecp.find("m");
        map<string,string>::const_iterator pk = ecp.find("k");
        if (pm != ecp.end() && pk != ecp.end()) {
          int k = atoi(pk->second.c_str());
          int m = atoi(pm->second.c_str());
          avail = avail * k / (m + k);
        }
      }
      break;
    default:
      assert(0 == "unrecognized pool type");
    }
    
    if (f) {
      f->open_object_section("pool");
      f->dump_string("name", pool_name);
      f->dump_int("id", pool_id);
      f->open_object_section("stats");
    } else {
      tbl << pool_name
          << pool_id;
      if (verbose)
        tbl << "-";
    }
                                                                        
    dump_object_stat_sum(tbl, f, stat.stats.sum, avail, verbose);
    if (f)
      f->close_section(); // stats
    else
      tbl << TextTable::endrow;
    /*如果命令是ceph df detail*/
    if (verbose) {
      if (f)
        f->open_array_section("categories"); 
      for (map<string,object_stat_sum_t>::iterator it = stat.stats.cat_sum.begin();
          it != stat.stats.cat_sum.end(); ++it) {
        if (f) {
          f->open_object_section(it->first.c_str());
        } else {
          tbl << ""
              << ""
              << it->first;
        }
        dump_object_stat_sum(tbl, f, it->second, avail, verbose);
        if (f)
          f->close_section(); // category name
        else
          tbl << TextTable::endrow;
      }
      if (f)
        f->close_section(); // categories
    }
    if (f)
      f->close_section(); // pool
  }
  if (f)
    f->close_section();
  else {
    ss << "POOLS:\n";
    tbl.set_indent(4);
    ss << tbl;
  }
}

其中中间输出数据部分是dump_object_stat_sum :

void PGMonitor::dump_object_stat_sum(TextTable &tbl, Formatter *f,
                                     object_stat_sum_t &sum, uint64_t avail,
                                     bool verbose)
{
  if (f) {
    f->dump_int("kb_used", SHIFT_ROUND_UP(sum.num_bytes, 10));
    f->dump_int("bytes_used", sum.num_bytes);
    f->dump_unsigned("max_avail", avail);
    f->dump_int("objects", sum.num_objects);
    if (verbose) {
      f->dump_int("dirty", sum.num_objects_dirty);
      f->dump_int("rd", sum.num_rd);
      f->dump_int("rd_bytes", sum.num_rd_kb * 1024ull);
      f->dump_int("wr", sum.num_wr);
      f->dump_int("wr_bytes", sum.num_wr_kb * 1024ull);
    }
  } else {
    /*ceph df 走这个分支*/
    tbl << stringify(si_t(sum.num_bytes));
    int64_t kb_used = SHIFT_ROUND_UP(sum.num_bytes, 10);
    float used = 0.0;
    if (pg_map.osd_sum.kb > 0)
      used = (float)kb_used / pg_map.osd_sum.kb; 
    tbl << percentify(used*100);
    tbl << si_t(avail);
    tbl << sum.num_objects;
    if (verbose) {
      /*如果是ceph df detail,则输出DIRTY READ 和WRITE*/
      tbl << stringify(si_t(sum.num_objects_dirty))
          << stringify(si_t(sum.num_rd))
          << stringify(si_t(sum.num_wr));
    }
  }
}

注意如果执行的是ceph df detail 则verbose == True输出的样式如下:

root@BEAN-2:~# ceph df detail
GLOBAL:
    SIZE     AVAIL     RAW USED     %RAW USED     OBJECTS 
    105G      103G        2010M          1.85        4575 
POOLS:
    NAME                  ID     CATEGORY     USED       %USED     MAX AVAIL     OBJECTS     DIRTY     READ       WRITE 
    rbd                   0      -            65600k      0.06        52162M          29        29      4702k     16317 
    .ezs3                 1      -                 0         0        52162M           0         0          0         0 
    data                  2      -              210M      0.19        52162M          64        64         12       118 
    metadata              3      -            13242k      0.01        52162M          23        23         75      4400 
    .rgw.buckets          4      -                 0         0        52162M           0         0          0         0 
    .ezs3.central.log     5      -             74570         0        52162M          93        93          0       164 
    .ezs3.statistic       6      -             3363k         0        52162M          58        58     11669k     6650k 
    .rgw.root             7      -               840         0        52162M           3         3       160k         3 
    .rgw.control          8      -                 0         0        52162M           8         8          0         0 
    .rgw                  9      -                 0         0        52162M           0         0          0         0 
    .rgw.gc               10     -                 0         0        52162M          32        32      73897     49298 
    .users.uid            11     -               367         0        52162M           1         1         45         4 
    .users.email          12     -                 9         0        52162M           1         1          0         1 
    .users                13     -                 9         0        52162M           1         1          0         1 
    .users.swift          14     -                 9         0        52162M           1         1          0         1 
    wsg                   15     -             1024M      0.94        34775M         261       261       179k      272k 
    hole                  16     -            16000M     14.75        52162M        4000      4000          0      4000 

数据的源头是?

通过分析代码我们知道,pool的使用空间(USED)是通过osd来更新的,因为有update(write,truncate,delete等)操作的的时候,会更新ctx->delta_stats,具体请见ReplicatedPG::do_osd_ops。举例的话,可以从处理WRITE的op为入手点,当处理CEPH_OSD_OP_WRITE类型的op的时候,会调用write_update_size_and_usage()。里面会更新ctx->delta_stats。当IO处理完,也就是applied和commited之后,会publish_stats_to_osd()。

void ReplicatedPG::write_update_size_and_usage(object_stat_sum_t& delta_stats, object_info_t& oi,
                                               SnapSet& ss, interval_set<uint64_t>& modified,
                                               uint64_t offset, uint64_t length, bool count_bytes)
{
  /*这个函数是用来写入之后更新统计量的*/
  interval_set<uint64_t> ch;
  if (length)
    ch.insert(offset, length);
  modified.union_of(ch);
  if (length && (offset + length > oi.size)) {
    uint64_t new_size = offset + length;
    delta_stats.num_bytes += new_size - oi.size;
    oi.size = new_size;
  }
  delta_stats.num_wr++;
  if (count_bytes)
    delta_stats.num_wr_kb += SHIFT_ROUND_UP(length, 10);
}             

这里会将变化的pg的stat_queue_item入队到pg_stat_queue中。然后设置osd_stat_updated为True。入队之后,由tick_timer在C_Tick_WithoutOSDLock这个ctx中通过send_pg_stats()将PG的状态发送给Monitor。这样Monitor就可以知道pg的的变化了。

注意,计算MAX AVAIL会比较麻烦一些,dump_pool_stats 之所以啰里啰唆一长段,很大的篇幅都是用来计算MAX AVAIL.

Ceph是先计算Available的值,然后根据副本策略再计算MAX AVAIL的值。Available的值是在get_rule_avail()中计算的。在该函数中通过get_rule_weight_osd_map()算出来一个有weight的osd列表。

注意这里的weight一般是小于1的,因为它除以了sum。而sum就是pool中所有osd weight的总和。在拿到weight列表后,就会根据pg_map.osd_stat中kb_avail的值进行除以weight,选出其中最小的,作为Available的值。

这么描述有些抽象了,具体举一个例子。比如这里我们的pool中有三个osd,假设kb_avail都是400G

即,{osd_0: 0.9, osd_1, 0.8, osd_2: 0.7}。计算出来的weight值是{osd_0: 0.9/2.4,osd_1: 0.8/2.4,osd_2: 0.7/2.4}

本文这一小节,大量参考Ceph中的容量计算与管理 , 无意剽窃前辈的成果,只是前辈写的太好,我就拿来主义了。

GLOBAL统计和Pool统计的不一致

我们回到开头的疑问,为什么GLOBAL统计的和Pool统计的数值有时候差距甚远。注意大多数情况下是一样的。相差无几的,但是有种情况是真实消耗的磁盘空间要小于所有pool中 USED 乘以副本个数对应的空间之和。

一个很容易构造的长久就是hole。

我们知道,文件可能有hole, 即,比如我要写一个1G的文件,我可能跳过了前面的1023MB,直接offset = 1023MB开始,写入1M的数据。那么这个文件是有洞的。前面的1023MB根本就不消耗磁盘空间。ceph也很容易构造这种场景。

我们以cephfs为例,我们在cephfs中的某个文件夹下,执行如下命令。

seq 1 4000 |xargs -I {} -P 10 dd if=/dev/zero of={} bs=1K seek=4095 count=1

注意,我们创造了4000个文件,但是我们通过seek,跳过前面的4095个1KB的内容,直接写最后的1KB,考虑到4MB 一个object 大小,表面上看,我们创造了4000个4MB的对象,但是实际上,在磁盘空间上,只消耗了很少了的空间。

我们首先比对下创建之前和之后,ceph df的输出情况:


root@BEAN-2:~# ceph df
GLOBAL:
    SIZE     AVAIL     RAW USED     %RAW USED 
    105G      103G        1928M          1.78 
POOLS:
    NAME                  ID     USED       %USED     MAX AVAIL     OBJECTS 
    rbd                   0      65600k      0.06        52195M          29 
    .ezs3                 1           0         0        52195M           0 
    data                  2        210M      0.19        52195M          64 
    metadata              3        402k         0        52195M          20 
    .rgw.buckets          4           0         0        52195M           0 
    .ezs3.central.log     5       73107         0        52195M          91 
    .ezs3.statistic       6       3363k         0        52195M          58 
    .rgw.root             7         840         0        52195M           3 
    .rgw.control          8           0         0        52195M           8 
    .rgw                  9           0         0        52195M           0 
    .rgw.gc               10          0         0        52195M          32 
    .users.uid            11        367         0        52195M           1 
    .users.email          12          9         0        52195M           1 
    .users                13          9         0        52195M           1 
    .users.swift          14          9         0        52195M           1 
    wsg                   15      1024M      0.94        34797M         261 
    hole                  16          0         0        52195M           0 
root@BEAN-2:~# 



seq 1 4000 |xargs -I {} -P 10 dd if=/dev/zero of={} bs=1K seek=4095 count=1


root@BEAN-2:~# ceph df
GLOBAL:
    SIZE     AVAIL     RAW USED     %RAW USED 
    105G      103G        2000M          1.84 
POOLS:
    NAME                  ID     USED       %USED     MAX AVAIL     OBJECTS 
    rbd                   0      65600k      0.06        52170M          29 
    .ezs3                 1           0         0        52170M           0 
    data                  2        210M      0.19        52170M          64 
    metadata              3      13242k      0.01        52170M          23 
    .rgw.buckets          4           0         0        52170M           0 
    .ezs3.central.log     5       73107         0        52170M          91 
    .ezs3.statistic       6       3363k         0        52170M          58 
    .rgw.root             7         840         0        52170M           3 
    .rgw.control          8           0         0        52170M           8 
    .rgw                  9           0         0        52170M           0 
    .rgw.gc               10          0         0        52170M          32 
    .users.uid            11        367         0        52170M           1 
    .users.email          12          9         0        52170M           1 
    .users                13          9         0        52170M           1 
    .users.swift          14          9         0        52170M           1 
    wsg                   15      1024M      0.94        34780M         261 
    hole                  16     16000M     14.75        52170M        4000 

注意hole这个pool 统计USED是4000*4M =16000MB,但是实际上GLOBAL中USED只增加了72MB。这是因为落到OSD 的FileStore下的本地文件系统来说,单个对象并未消耗4M空间,而是远远小于4M。

我们可以随意去一个文件,比如2005这个文件:

root@BEAN-2:/var/share/ezfs/shareroot/hole# cephfs /var/share/ezfs/shareroot/hole/2005 show_location
WARNING: This tool is deprecated.  Use the layout.* xattrs to query and modify layouts.
location.file_offset:  0
location.object_offset:0
location.object_no:    0
location.object_size:  4194304
location.object_name:  10000000bd9.00000000
location.block_offset: 0
location.block_size:   4194304
location.osd:          1
root@BEAN-2:/var/share/ezfs/shareroot/hole# ceph  osd map hole 10000000bd9.00000000
osdmap e129 pool 'hole' (16) object '10000000bd9.00000000' -> pg 16.61237fba (16.3ba) -> up ([1,2], p1) acting ([1,2], p1)

通过ceph osd map可以找到该文件位于OSD.1,所属PG为16.3ba。

root@BEAN-2:/data/osd.1/current/16.3ba_head# ll
total 328
drwxr-xr-x    2 root root    4096 Jan 22 02:04 ./
drwxr-xr-x 6385 root root  217088 Jan 22 01:59 ../
-rw-r--r--    1 root root 4194304 Jan 22 02:03 10000000816.00000000__head_EEA8D3BA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:03 10000000857.00000000__head_486277BA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:03 10000000874.00000000__head_B6B303BA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:03 100000009f4.00000000__head_3EBB4FBA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:03 10000000ae0.00000000__head_6C5023BA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:03 10000000bd9.00000000__head_61237FBA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:03 10000000c72.00000000__head_697163BA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:03 10000000cc6.00000000__head_414E17BA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:04 10000000eba.00000000__head_149CEBBA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:04 10000000ef6.00000000__head_CE01BFBA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:04 10000000ff5.00000000__head_D67A17BA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:04 10000001223.00000000__head_AE8D57BA__10
-rw-r--r--    1 root root 4194304 Jan 22 02:04 100000012c4.00000000__head_B12D2FBA__10
-rw-r--r--    1 root root       0 Jan 22 01:57 __head_000003BA__10

root@BEAN-2:/data/osd.1/current/16.3ba_head# du -sh .
112K	

注意,每个 文件都是4MB,但是这么多对象对应的本地文件,只占用了112KB的空间。

我们通过debugfs的stat 命令可以查看单个对象对应本地文件数据块的个数及数值:,

可以看到,数据块就占用了1块 779263, 数据块消耗了4K的空间。

Inode: 2230199   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 2862717981    Version: 0x00000000:00000001
User:     0   Group:     0   Size: 4194304
File ACL: 8923093    Directory ACL: 0
Links: 1   Blockcount: 16
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x5883a284:9dfc1d60 -- Sun Jan 22 02:03:48 2017
 atime: 0x5883a284:9dfc1d60 -- Sun Jan 22 02:03:48 2017
 mtime: 0x5883a284:9dfc1d60 -- Sun Jan 22 02:03:48 2017
crtime: 0x5883a284:9dfc1d60 -- Sun Jan 22 02:03:48 2017
Size of extra inode fields: 28
Extended attributes stored in inode body: 
  cephos.spill_out = "30 00 " (2)
EXTENTS:
(1023):779263
(END)

上一篇     下一篇