item_ops.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:16k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
  3.  */
  4. #include <linux/sched.h>
  5. #include <linux/reiserfs_fs.h>
  6. // this contains item handlers for old item types: sd, direct,
  7. // indirect, directory
  8. /* and where are the comments? how about saying where we can find an
  9.    explanation of each item handler method? -Hans */
  10. //////////////////////////////////////////////////////////////////////////////
  11. // stat data functions
  12. //
  13. static int sd_bytes_number (struct item_head * ih, int block_size)
  14. {
  15.   return 0;
  16. }
  17. static void sd_decrement_key (struct cpu_key * key)
  18. {
  19.     key->on_disk_key.k_objectid --;
  20.     set_cpu_key_k_type (key, TYPE_ANY);
  21.     set_cpu_key_k_offset(key, (loff_t)(-1));
  22. }
  23. static int sd_is_left_mergeable (struct key * key, unsigned long bsize)
  24. {
  25.     return 0;
  26. }
  27. static char * print_time (time_t t)
  28. {
  29.     static char timebuf[256];
  30.     sprintf (timebuf, "%ld", t);
  31.     return timebuf;
  32. }
  33. static void sd_print_item (struct item_head * ih, char * item)
  34. {
  35.     printk ("tmode | size | nlinks | first direct | mtimen");
  36.     if (stat_data_v1 (ih)) {
  37.        struct stat_data_v1 * sd = (struct stat_data_v1 *)item;
  38. printk ("t0%-6o | %6u | %2u | %d | %sn", sd_v1_mode(sd),
  39.                 sd_v1_size(sd), sd_v1_nlink(sd), sd_v1_first_direct_byte(sd),
  40.                 print_time( sd_v1_mtime(sd) ) );
  41.     } else {
  42. struct stat_data * sd = (struct stat_data *)item;
  43. printk ("t0%-6o | %6Lu | %2u | %d | %sn", sd_v2_mode(sd),
  44.             (unsigned long long)sd_v2_size(sd), sd_v2_nlink(sd),
  45.             sd_v2_rdev(sd), print_time(sd_v2_mtime(sd)));
  46.     }
  47. }
  48. static void sd_check_item (struct item_head * ih, char * item)
  49. {
  50.     // FIXME: type something here!
  51. }
  52. static int sd_create_vi (struct virtual_node * vn,
  53.  struct virtual_item * vi, 
  54.  int is_affected, 
  55.  int insert_size)
  56. {
  57.     vi->vi_index = TYPE_STAT_DATA;
  58.     //vi->vi_type |= VI_TYPE_STAT_DATA;// not needed?
  59.     return 0;
  60. }
  61. static int sd_check_left (struct virtual_item * vi, int free, 
  62.   int start_skip, int end_skip)
  63. {
  64.     if (start_skip || end_skip)
  65. BUG ();
  66.     return -1;
  67. }
  68. static int sd_check_right (struct virtual_item * vi, int free)
  69. {
  70.     return -1;
  71. }
  72. static int sd_part_size (struct virtual_item * vi, int first, int count)
  73. {
  74.     if (count)
  75. BUG ();
  76.     return 0;
  77. }
  78. static int sd_unit_num (struct virtual_item * vi)
  79. {
  80.     return vi->vi_item_len - IH_SIZE;
  81. }
  82. static void sd_print_vi (struct virtual_item * vi)
  83. {
  84.     reiserfs_warning ("STATDATA, index %d, type 0x%x, %hn", 
  85.       vi->vi_index, vi->vi_type, vi->vi_ih);
  86. }
  87. struct item_operations stat_data_ops = {
  88.     sd_bytes_number,
  89.     sd_decrement_key,
  90.     sd_is_left_mergeable,
  91.     sd_print_item,
  92.     sd_check_item,
  93.     sd_create_vi,
  94.     sd_check_left,
  95.     sd_check_right,
  96.     sd_part_size,
  97.     sd_unit_num,
  98.     sd_print_vi
  99. };
  100. //////////////////////////////////////////////////////////////////////////////
  101. // direct item functions
  102. //
  103. static int direct_bytes_number (struct item_head * ih, int block_size)
  104. {
  105.   return ih_item_len(ih);
  106. }
  107. // FIXME: this should probably switch to indirect as well
  108. static void direct_decrement_key (struct cpu_key * key)
  109. {
  110.     cpu_key_k_offset_dec (key);
  111.     if (cpu_key_k_offset (key) == 0)
  112. set_cpu_key_k_type (key, TYPE_STAT_DATA);
  113. }
  114. static int direct_is_left_mergeable (struct key * key, unsigned long bsize)
  115. {
  116.     int version = le_key_version (key);
  117.     return ((le_key_k_offset (version, key) & (bsize - 1)) != 1);
  118. }
  119. static void direct_print_item (struct item_head * ih, char * item)
  120. {
  121.     int j = 0;
  122. //    return;
  123.     printk (""");
  124.     while (j < ih_item_len(ih))
  125. printk ("%c", item[j++]);
  126.     printk (""n");
  127. }
  128. static void direct_check_item (struct item_head * ih, char * item)
  129. {
  130.     // FIXME: type something here!
  131. }
  132. static int direct_create_vi (struct virtual_node * vn,
  133.      struct virtual_item * vi, 
  134.      int is_affected, 
  135.      int insert_size)
  136. {
  137.     vi->vi_index = TYPE_DIRECT;
  138.     //vi->vi_type |= VI_TYPE_DIRECT;
  139.     return 0;
  140. }
  141. static int direct_check_left (struct virtual_item * vi, int free,
  142.       int start_skip, int end_skip)
  143. {
  144.     int bytes;
  145.     bytes = free - free % 8;
  146.     return bytes ?: -1;    
  147. }
  148. static int direct_check_right (struct virtual_item * vi, int free)
  149. {
  150.     return direct_check_left (vi, free, 0, 0);
  151. }
  152. static int direct_part_size (struct virtual_item * vi, int first, int count)
  153. {
  154.     return count;
  155. }
  156. static int direct_unit_num (struct virtual_item * vi)
  157. {
  158.     return vi->vi_item_len - IH_SIZE;
  159. }
  160. static void direct_print_vi (struct virtual_item * vi)
  161. {
  162.     reiserfs_warning ("DIRECT, index %d, type 0x%x, %hn", 
  163.       vi->vi_index, vi->vi_type, vi->vi_ih);
  164. }
  165. struct item_operations direct_ops = {
  166.     direct_bytes_number,
  167.     direct_decrement_key,
  168.     direct_is_left_mergeable,
  169.     direct_print_item,
  170.     direct_check_item,
  171.     direct_create_vi,
  172.     direct_check_left,
  173.     direct_check_right,
  174.     direct_part_size,
  175.     direct_unit_num,
  176.     direct_print_vi
  177. };
  178. //////////////////////////////////////////////////////////////////////////////
  179. // indirect item functions
  180. //
  181. static int indirect_bytes_number (struct item_head * ih, int block_size)
  182. {
  183.   return ih_item_len(ih) / UNFM_P_SIZE * block_size; //- get_ih_free_space (ih);
  184. }
  185. // decrease offset, if it becomes 0, change type to stat data
  186. static void indirect_decrement_key (struct cpu_key * key)
  187. {
  188.     cpu_key_k_offset_dec (key);
  189.     if (cpu_key_k_offset (key) == 0)
  190. set_cpu_key_k_type (key, TYPE_STAT_DATA);
  191. }
  192. // if it is not first item of the body, then it is mergeable
  193. static int indirect_is_left_mergeable (struct key * key, unsigned long bsize)
  194. {
  195.     int version = le_key_version (key);
  196.     return (le_key_k_offset (version, key) != 1);
  197. }
  198. // printing of indirect item
  199. static void start_new_sequence (__u32 * start, int * len, __u32 new)
  200. {
  201.     *start = new;
  202.     *len = 1;
  203. }
  204. static int sequence_finished (__u32 start, int * len, __u32 new)
  205. {
  206.     if (start == INT_MAX)
  207. return 1;
  208.     if (start == 0 && new == 0) {
  209. (*len) ++;
  210. return 0;
  211.     }
  212.     if (start != 0 && (start + *len) == new) {
  213. (*len) ++;
  214. return 0;
  215.     }
  216.     return 1;
  217. }
  218. static void print_sequence (__u32 start, int len)
  219. {
  220.     if (start == INT_MAX)
  221. return;
  222.     if (len == 1)
  223. printk (" %d", start);
  224.     else
  225. printk (" %d(%d)", start, len);
  226. }
  227. static void indirect_print_item (struct item_head * ih, char * item)
  228. {
  229.     int j;
  230.     __u32 * unp, prev = INT_MAX;
  231.     int num;
  232.     unp = (__u32 *)item;
  233.     if (ih_item_len(ih) % UNFM_P_SIZE)
  234. printk ("indirect_print_item: invalid item len");  
  235.     printk ("%d pointersn[ ", (int)I_UNFM_NUM (ih));
  236.     for (j = 0; j < I_UNFM_NUM (ih); j ++) {
  237. if (sequence_finished (prev, &num, get_block_num(unp, j))) {
  238.     print_sequence (prev, num);
  239.     start_new_sequence (&prev, &num, get_block_num(unp, j));
  240. }
  241.     }
  242.     print_sequence (prev, num);
  243.     printk ("]n");
  244. }
  245. static void indirect_check_item (struct item_head * ih, char * item)
  246. {
  247.     // FIXME: type something here!
  248. }
  249. static int indirect_create_vi (struct virtual_node * vn,
  250.        struct virtual_item * vi, 
  251.        int is_affected, 
  252.        int insert_size)
  253. {
  254.     vi->vi_index = TYPE_INDIRECT;
  255.     //vi->vi_type |= VI_TYPE_INDIRECT;
  256.     return 0;
  257. }
  258. static int indirect_check_left (struct virtual_item * vi, int free,
  259. int start_skip, int end_skip)
  260. {
  261.     int bytes;
  262.     bytes = free - free % UNFM_P_SIZE;
  263.     return bytes ?: -1;    
  264. }
  265. static int indirect_check_right (struct virtual_item * vi, int free)
  266. {
  267.     return indirect_check_left (vi, free, 0, 0);
  268. }
  269. // return size in bytes of 'units' units. If first == 0 - calculate from the head (left), otherwise - from tail (right)
  270. static int indirect_part_size (struct virtual_item * vi, int first, int units)
  271. {
  272.     // unit of indirect item is byte (yet)
  273.     return units;
  274. }
  275. static int indirect_unit_num (struct virtual_item * vi)
  276. {
  277.     // unit of indirect item is byte (yet)
  278.     return vi->vi_item_len - IH_SIZE;
  279. }
  280. static void indirect_print_vi (struct virtual_item * vi)
  281. {
  282.     reiserfs_warning ("INDIRECT, index %d, type 0x%x, %hn", 
  283.       vi->vi_index, vi->vi_type, vi->vi_ih);
  284. }
  285. struct item_operations indirect_ops = {
  286.     indirect_bytes_number,
  287.     indirect_decrement_key,
  288.     indirect_is_left_mergeable,
  289.     indirect_print_item,
  290.     indirect_check_item,
  291.     indirect_create_vi,
  292.     indirect_check_left,
  293.     indirect_check_right,
  294.     indirect_part_size,
  295.     indirect_unit_num,
  296.     indirect_print_vi
  297. };
  298. //////////////////////////////////////////////////////////////////////////////
  299. // direntry functions
  300. //
  301. static int direntry_bytes_number (struct item_head * ih, int block_size)
  302. {
  303.     reiserfs_warning ("vs-16090: direntry_bytes_number: "
  304.       "bytes number is asked for direntry");
  305.     return 0;
  306. }
  307. static void direntry_decrement_key (struct cpu_key * key)
  308. {
  309.     cpu_key_k_offset_dec (key);
  310.     if (cpu_key_k_offset (key) == 0)
  311. set_cpu_key_k_type (key, TYPE_STAT_DATA);
  312. }
  313. static int direntry_is_left_mergeable (struct key * key, unsigned long bsize)
  314. {
  315.     if (le32_to_cpu (key->u.k_offset_v1.k_offset) == DOT_OFFSET)
  316. return 0;
  317.     return 1;
  318. }
  319. static void direntry_print_item (struct item_head * ih, char * item)
  320. {
  321.     int i;
  322.     int namelen;
  323.     struct reiserfs_de_head * deh;
  324.     char * name;
  325.     static char namebuf [80];
  326.     printk ("n # %-15s%-30s%-15s%-15s%-15sn", "Name", "Key of pointed object", "Hash", "Gen number", "Status");
  327.     deh = (struct reiserfs_de_head *)item;
  328.     for (i = 0; i < I_ENTRY_COUNT (ih); i ++, deh ++) {
  329. namelen = (i ? (deh_location(deh - 1)) : ih_item_len(ih)) - deh_location(deh);
  330. name = item + deh_location(deh);
  331. if (name[namelen-1] == 0)
  332.   namelen = strlen (name);
  333. namebuf[0] = '"';
  334. if (namelen > sizeof (namebuf) - 3) {
  335.     strncpy (namebuf + 1, name, sizeof (namebuf) - 3);
  336.     namebuf[sizeof (namebuf) - 2] = '"';
  337.     namebuf[sizeof (namebuf) - 1] = 0;
  338. } else {
  339.     memcpy (namebuf + 1, name, namelen);
  340.     namebuf[namelen + 1] = '"';
  341.     namebuf[namelen + 2] = 0;
  342. }
  343. printk ("%d:  %-15s%-15d%-15d%-15Ld%-15Ld(%s)n", 
  344. i, namebuf,
  345. deh_dir_id(deh), deh_objectid(deh),
  346. GET_HASH_VALUE (deh_offset (deh)), GET_GENERATION_NUMBER ((deh_offset (deh))),
  347. (de_hidden (deh)) ? "HIDDEN" : "VISIBLE");
  348.     }
  349. }
  350. static void direntry_check_item (struct item_head * ih, char * item)
  351. {
  352.     int i;
  353.     struct reiserfs_de_head * deh;
  354.     // FIXME: type something here!
  355.     deh = (struct reiserfs_de_head *)item;
  356.     for (i = 0; i < I_ENTRY_COUNT (ih); i ++, deh ++) {
  357. ;
  358.     }
  359. }
  360. #define DIRENTRY_VI_FIRST_DIRENTRY_ITEM 1
  361. struct direntry_uarea {
  362.     int flags;
  363.     __u16 entry_count;
  364.     __u16 entry_sizes[1];
  365. } __attribute__ ((__packed__)) ;
  366. /*
  367.  * function returns old entry number in directory item in real node
  368.  * using new entry number in virtual item in virtual node */
  369. static inline int old_entry_num (int is_affected, int virtual_entry_num, int pos_in_item, int mode)
  370. {
  371.     if ( mode == M_INSERT || mode == M_DELETE)
  372. return virtual_entry_num;
  373.     
  374.     if (!is_affected)
  375. /* cut or paste is applied to another item */
  376. return virtual_entry_num;
  377.     if (virtual_entry_num < pos_in_item)
  378. return virtual_entry_num;
  379.     if (mode == M_CUT)
  380. return virtual_entry_num + 1;
  381.     RFALSE( mode != M_PASTE || virtual_entry_num == 0,
  382.     "vs-8015: old_entry_num: mode must be M_PASTE (mode = '%c'", mode);
  383.     
  384.     return virtual_entry_num - 1;
  385. }
  386. /* Create an array of sizes of directory entries for virtual
  387.    item. Return space used by an item. FIXME: no control over
  388.    consuming of space used by this item handler */
  389. static int direntry_create_vi (struct virtual_node * vn,
  390.        struct virtual_item * vi, 
  391.        int is_affected, 
  392.        int insert_size)
  393. {
  394.     struct direntry_uarea * dir_u = vi->vi_uarea;
  395.     int i, j;
  396.     int size = sizeof (struct direntry_uarea);
  397.     struct reiserfs_de_head * deh;
  398.   
  399.     vi->vi_index = TYPE_DIRENTRY;
  400.     if (!(vi->vi_ih) || !vi->vi_item)
  401. BUG ();
  402.     dir_u->flags = 0;
  403.     if (le_ih_k_offset (vi->vi_ih) == DOT_OFFSET)
  404. dir_u->flags |= DIRENTRY_VI_FIRST_DIRENTRY_ITEM;
  405.     deh = (struct reiserfs_de_head *)(vi->vi_item);
  406.     
  407.     
  408.     /* virtual directory item have this amount of entry after */
  409.     dir_u->entry_count = ih_entry_count (vi->vi_ih) + 
  410. ((is_affected) ? ((vn->vn_mode == M_CUT) ? -1 :
  411.   (vn->vn_mode == M_PASTE ? 1 : 0)) : 0);
  412.     
  413.     for (i = 0; i < dir_u->entry_count; i ++) {
  414. j = old_entry_num (is_affected, i, vn->vn_pos_in_item, vn->vn_mode);
  415.         dir_u->entry_sizes[i] = (j ? deh_location( &(deh[j - 1]) ) :
  416.                                 ih_item_len (vi->vi_ih)) -
  417.                                 deh_location( &(deh[j])) + DEH_SIZE;
  418.     }
  419.     size += (dir_u->entry_count * sizeof (short));
  420.     
  421.     /* set size of pasted entry */
  422.     if (is_affected && vn->vn_mode == M_PASTE)
  423. dir_u->entry_sizes[vn->vn_pos_in_item] = insert_size;
  424. #ifdef CONFIG_REISERFS_CHECK
  425.     /* compare total size of entries with item length */
  426.     {
  427. int k, l;
  428.     
  429. l = 0;
  430. for (k = 0; k < dir_u->entry_count; k ++)
  431.     l += dir_u->entry_sizes[k];
  432.     
  433. if (l + IH_SIZE != vi->vi_item_len + 
  434.     ((is_affected && (vn->vn_mode == M_PASTE || vn->vn_mode == M_CUT)) ? insert_size : 0) ) {
  435.     reiserfs_panic (0, "vs-8025: set_entry_sizes: (mode==%c, insert_size==%d), invalid length of directory item",
  436.     vn->vn_mode, insert_size);
  437. }
  438.     }
  439. #endif
  440.     return size;
  441. }
  442. //
  443. // return number of entries which may fit into specified amount of
  444. // free space, or -1 if free space is not enough even for 1 entry
  445. //
  446. static int direntry_check_left (struct virtual_item * vi, int free,
  447. int start_skip, int end_skip)
  448. {
  449.     int i;
  450.     int entries = 0;
  451.     struct direntry_uarea * dir_u = vi->vi_uarea;
  452.     for (i = start_skip; i < dir_u->entry_count - end_skip; i ++) {
  453. if (dir_u->entry_sizes[i] > free)
  454.     /* i-th entry doesn't fit into the remaining free space */
  455.     break;
  456.   
  457. free -= dir_u->entry_sizes[i];
  458. entries ++;
  459.     }
  460.     if (entries == dir_u->entry_count) {
  461. printk ("free spze %d, entry_count %dn", free, dir_u->entry_count);
  462. BUG ();
  463.     }
  464.     /* "." and ".." can not be separated from each other */
  465.     if (start_skip == 0 && (dir_u->flags & DIRENTRY_VI_FIRST_DIRENTRY_ITEM) && entries < 2)
  466. entries = 0;
  467.     
  468.     return entries ?: -1;
  469. }
  470. static int direntry_check_right (struct virtual_item * vi, int free)
  471. {
  472.     int i;
  473.     int entries = 0;
  474.     struct direntry_uarea * dir_u = vi->vi_uarea;
  475.     
  476.     for (i = dir_u->entry_count - 1; i >= 0; i --) {
  477. if (dir_u->entry_sizes[i] > free)
  478.     /* i-th entry doesn't fit into the remaining free space */
  479.     break;
  480. free -= dir_u->entry_sizes[i];
  481. entries ++;
  482.     }
  483.     if (entries == dir_u->entry_count)
  484. BUG ();
  485.     /* "." and ".." can not be separated from each other */
  486.     if ((dir_u->flags & DIRENTRY_VI_FIRST_DIRENTRY_ITEM) && entries > dir_u->entry_count - 2)
  487. entries = dir_u->entry_count - 2;
  488.     return entries ?: -1;
  489. }
  490. /* sum of entry sizes between from-th and to-th entries including both edges */
  491. static int direntry_part_size (struct virtual_item * vi, int first, int count)
  492. {
  493.     int i, retval;
  494.     int from, to;
  495.     struct direntry_uarea * dir_u = vi->vi_uarea;
  496.     
  497.     retval = 0;
  498.     if (first == 0)
  499. from = 0;
  500.     else
  501. from = dir_u->entry_count - count;
  502.     to = from + count - 1;
  503.     for (i = from; i <= to; i ++)
  504. retval += dir_u->entry_sizes[i];
  505.     return retval;
  506. }
  507. static int direntry_unit_num (struct virtual_item * vi)
  508. {
  509.     struct direntry_uarea * dir_u = vi->vi_uarea;
  510.     
  511.     return dir_u->entry_count;
  512. }
  513. static void direntry_print_vi (struct virtual_item * vi)
  514. {
  515.     int i;
  516.     struct direntry_uarea * dir_u = vi->vi_uarea;
  517.     reiserfs_warning ("DIRENTRY, index %d, type 0x%x, %h, flags 0x%xn", 
  518.       vi->vi_index, vi->vi_type, vi->vi_ih, dir_u->flags);
  519.     printk ("%d entries: ", dir_u->entry_count);
  520.     for (i = 0; i < dir_u->entry_count; i ++)
  521. printk ("%d ", dir_u->entry_sizes[i]);
  522.     printk ("n");
  523. }
  524. struct item_operations direntry_ops = {
  525.     direntry_bytes_number,
  526.     direntry_decrement_key,
  527.     direntry_is_left_mergeable,
  528.     direntry_print_item,
  529.     direntry_check_item,
  530.     direntry_create_vi,
  531.     direntry_check_left,
  532.     direntry_check_right,
  533.     direntry_part_size,
  534.     direntry_unit_num,
  535.     direntry_print_vi
  536. };
  537. //////////////////////////////////////////////////////////////////////////////
  538. //
  539. //
  540. #if ! (TYPE_STAT_DATA == 0 && TYPE_INDIRECT == 1 && TYPE_DIRECT == 2 && TYPE_DIRENTRY == 3)
  541.   do not compile
  542. #endif
  543. struct item_operations * item_ops [4] = {
  544.   &stat_data_ops,
  545.   &indirect_ops,
  546.   &direct_ops,
  547.   &direntry_ops
  548. };