diff options
-rw-r--r-- | fs/ocfs2/alloc.c | 9 | ||||
-rw-r--r-- | fs/ocfs2/alloc.h | 9 | ||||
-rw-r--r-- | fs/ocfs2/extent_map.c | 346 | ||||
-rw-r--r-- | fs/ocfs2/extent_map.h | 3 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 1 |
5 files changed, 306 insertions, 62 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 10bfb466e068..29ff57ec5d1f 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -990,15 +990,6 @@ out: | |||
990 | } | 990 | } |
991 | 991 | ||
992 | /* | 992 | /* |
993 | * This is only valid for leaf nodes, which are the only ones that can | ||
994 | * have empty extents anyway. | ||
995 | */ | ||
996 | static inline int ocfs2_is_empty_extent(struct ocfs2_extent_rec *rec) | ||
997 | { | ||
998 | return !rec->e_leaf_clusters; | ||
999 | } | ||
1000 | |||
1001 | /* | ||
1002 | * This function will discard the rightmost extent record. | 993 | * This function will discard the rightmost extent record. |
1003 | */ | 994 | */ |
1004 | static void ocfs2_shift_records_right(struct ocfs2_extent_list *el) | 995 | static void ocfs2_shift_records_right(struct ocfs2_extent_list *el) |
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h index 42ff94bd8011..60cd3d59230c 100644 --- a/fs/ocfs2/alloc.h +++ b/fs/ocfs2/alloc.h | |||
@@ -146,4 +146,13 @@ static inline unsigned int ocfs2_rec_clusters(struct ocfs2_extent_list *el, | |||
146 | return le16_to_cpu(rec->e_leaf_clusters); | 146 | return le16_to_cpu(rec->e_leaf_clusters); |
147 | } | 147 | } |
148 | 148 | ||
149 | /* | ||
150 | * This is only valid for leaf nodes, which are the only ones that can | ||
151 | * have empty extents anyway. | ||
152 | */ | ||
153 | static inline int ocfs2_is_empty_extent(struct ocfs2_extent_rec *rec) | ||
154 | { | ||
155 | return !rec->e_leaf_clusters; | ||
156 | } | ||
157 | |||
149 | #endif /* OCFS2_ALLOC_H */ | 158 | #endif /* OCFS2_ALLOC_H */ |
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index c58668a326fe..aed268e80b49 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/fiemap.h> | ||
28 | 29 | ||
29 | #define MLOG_MASK_PREFIX ML_EXTENT_MAP | 30 | #define MLOG_MASK_PREFIX ML_EXTENT_MAP |
30 | #include <cluster/masklog.h> | 31 | #include <cluster/masklog.h> |
@@ -32,6 +33,7 @@ | |||
32 | #include "ocfs2.h" | 33 | #include "ocfs2.h" |
33 | 34 | ||
34 | #include "alloc.h" | 35 | #include "alloc.h" |
36 | #include "dlmglue.h" | ||
35 | #include "extent_map.h" | 37 | #include "extent_map.h" |
36 | #include "inode.h" | 38 | #include "inode.h" |
37 | #include "super.h" | 39 | #include "super.h" |
@@ -282,6 +284,51 @@ out: | |||
282 | kfree(new_emi); | 284 | kfree(new_emi); |
283 | } | 285 | } |
284 | 286 | ||
287 | static int ocfs2_last_eb_is_empty(struct inode *inode, | ||
288 | struct ocfs2_dinode *di) | ||
289 | { | ||
290 | int ret, next_free; | ||
291 | u64 last_eb_blk = le64_to_cpu(di->i_last_eb_blk); | ||
292 | struct buffer_head *eb_bh = NULL; | ||
293 | struct ocfs2_extent_block *eb; | ||
294 | struct ocfs2_extent_list *el; | ||
295 | |||
296 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), last_eb_blk, | ||
297 | &eb_bh, OCFS2_BH_CACHED, inode); | ||
298 | if (ret) { | ||
299 | mlog_errno(ret); | ||
300 | goto out; | ||
301 | } | ||
302 | |||
303 | eb = (struct ocfs2_extent_block *) eb_bh->b_data; | ||
304 | el = &eb->h_list; | ||
305 | |||
306 | if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) { | ||
307 | ret = -EROFS; | ||
308 | OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb); | ||
309 | goto out; | ||
310 | } | ||
311 | |||
312 | if (el->l_tree_depth) { | ||
313 | ocfs2_error(inode->i_sb, | ||
314 | "Inode %lu has non zero tree depth in " | ||
315 | "leaf block %llu\n", inode->i_ino, | ||
316 | (unsigned long long)eb_bh->b_blocknr); | ||
317 | ret = -EROFS; | ||
318 | goto out; | ||
319 | } | ||
320 | |||
321 | next_free = le16_to_cpu(el->l_next_free_rec); | ||
322 | |||
323 | if (next_free == 0 || | ||
324 | (next_free == 1 && ocfs2_is_empty_extent(&el->l_recs[0]))) | ||
325 | ret = 1; | ||
326 | |||
327 | out: | ||
328 | brelse(eb_bh); | ||
329 | return ret; | ||
330 | } | ||
331 | |||
285 | /* | 332 | /* |
286 | * Return the 1st index within el which contains an extent start | 333 | * Return the 1st index within el which contains an extent start |
287 | * larger than v_cluster. | 334 | * larger than v_cluster. |
@@ -373,42 +420,28 @@ out: | |||
373 | return ret; | 420 | return ret; |
374 | } | 421 | } |
375 | 422 | ||
376 | int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, | 423 | static int ocfs2_get_clusters_nocache(struct inode *inode, |
377 | u32 *p_cluster, u32 *num_clusters, | 424 | struct buffer_head *di_bh, |
378 | unsigned int *extent_flags) | 425 | u32 v_cluster, unsigned int *hole_len, |
426 | struct ocfs2_extent_rec *ret_rec, | ||
427 | unsigned int *is_last) | ||
379 | { | 428 | { |
380 | int ret, i; | 429 | int i, ret, tree_height, len; |
381 | unsigned int flags = 0; | ||
382 | struct buffer_head *di_bh = NULL; | ||
383 | struct buffer_head *eb_bh = NULL; | ||
384 | struct ocfs2_dinode *di; | 430 | struct ocfs2_dinode *di; |
385 | struct ocfs2_extent_block *eb; | 431 | struct ocfs2_extent_block *uninitialized_var(eb); |
386 | struct ocfs2_extent_list *el; | 432 | struct ocfs2_extent_list *el; |
387 | struct ocfs2_extent_rec *rec; | 433 | struct ocfs2_extent_rec *rec; |
388 | u32 coff; | 434 | struct buffer_head *eb_bh = NULL; |
389 | |||
390 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
391 | ret = -ERANGE; | ||
392 | mlog_errno(ret); | ||
393 | goto out; | ||
394 | } | ||
395 | |||
396 | ret = ocfs2_extent_map_lookup(inode, v_cluster, p_cluster, | ||
397 | num_clusters, extent_flags); | ||
398 | if (ret == 0) | ||
399 | goto out; | ||
400 | 435 | ||
401 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), OCFS2_I(inode)->ip_blkno, | 436 | memset(ret_rec, 0, sizeof(*ret_rec)); |
402 | &di_bh, OCFS2_BH_CACHED, inode); | 437 | if (is_last) |
403 | if (ret) { | 438 | *is_last = 0; |
404 | mlog_errno(ret); | ||
405 | goto out; | ||
406 | } | ||
407 | 439 | ||
408 | di = (struct ocfs2_dinode *) di_bh->b_data; | 440 | di = (struct ocfs2_dinode *) di_bh->b_data; |
409 | el = &di->id2.i_list; | 441 | el = &di->id2.i_list; |
442 | tree_height = le16_to_cpu(el->l_tree_depth); | ||
410 | 443 | ||
411 | if (el->l_tree_depth) { | 444 | if (tree_height > 0) { |
412 | ret = ocfs2_find_leaf(inode, el, v_cluster, &eb_bh); | 445 | ret = ocfs2_find_leaf(inode, el, v_cluster, &eb_bh); |
413 | if (ret) { | 446 | if (ret) { |
414 | mlog_errno(ret); | 447 | mlog_errno(ret); |
@@ -431,46 +464,143 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, | |||
431 | i = ocfs2_search_extent_list(el, v_cluster); | 464 | i = ocfs2_search_extent_list(el, v_cluster); |
432 | if (i == -1) { | 465 | if (i == -1) { |
433 | /* | 466 | /* |
434 | * A hole was found. Return some canned values that | 467 | * Holes can be larger than the maximum size of an |
435 | * callers can key on. If asked for, num_clusters will | 468 | * extent, so we return their lengths in a seperate |
436 | * be populated with the size of the hole. | 469 | * field. |
437 | */ | 470 | */ |
438 | *p_cluster = 0; | 471 | if (hole_len) { |
439 | if (num_clusters) { | ||
440 | ret = ocfs2_figure_hole_clusters(inode, el, eb_bh, | 472 | ret = ocfs2_figure_hole_clusters(inode, el, eb_bh, |
441 | v_cluster, | 473 | v_cluster, &len); |
442 | num_clusters); | ||
443 | if (ret) { | 474 | if (ret) { |
444 | mlog_errno(ret); | 475 | mlog_errno(ret); |
445 | goto out; | 476 | goto out; |
446 | } | 477 | } |
478 | |||
479 | *hole_len = len; | ||
447 | } | 480 | } |
448 | } else { | 481 | goto out_hole; |
449 | rec = &el->l_recs[i]; | 482 | } |
450 | 483 | ||
451 | BUG_ON(v_cluster < le32_to_cpu(rec->e_cpos)); | 484 | rec = &el->l_recs[i]; |
452 | 485 | ||
453 | if (!rec->e_blkno) { | 486 | BUG_ON(v_cluster < le32_to_cpu(rec->e_cpos)); |
454 | ocfs2_error(inode->i_sb, "Inode %lu has bad extent " | 487 | |
455 | "record (%u, %u, 0)", inode->i_ino, | 488 | if (!rec->e_blkno) { |
456 | le32_to_cpu(rec->e_cpos), | 489 | ocfs2_error(inode->i_sb, "Inode %lu has bad extent " |
457 | ocfs2_rec_clusters(el, rec)); | 490 | "record (%u, %u, 0)", inode->i_ino, |
458 | ret = -EROFS; | 491 | le32_to_cpu(rec->e_cpos), |
459 | goto out; | 492 | ocfs2_rec_clusters(el, rec)); |
493 | ret = -EROFS; | ||
494 | goto out; | ||
495 | } | ||
496 | |||
497 | *ret_rec = *rec; | ||
498 | |||
499 | /* | ||
500 | * Checking for last extent is potentially expensive - we | ||
501 | * might have to look at the next leaf over to see if it's | ||
502 | * empty. | ||
503 | * | ||
504 | * The first two checks are to see whether the caller even | ||
505 | * cares for this information, and if the extent is at least | ||
506 | * the last in it's list. | ||
507 | * | ||
508 | * If those hold true, then the extent is last if any of the | ||
509 | * additional conditions hold true: | ||
510 | * - Extent list is in-inode | ||
511 | * - Extent list is right-most | ||
512 | * - Extent list is 2nd to rightmost, with empty right-most | ||
513 | */ | ||
514 | if (is_last) { | ||
515 | if (i == (le16_to_cpu(el->l_next_free_rec) - 1)) { | ||
516 | if (tree_height == 0) | ||
517 | *is_last = 1; | ||
518 | else if (eb->h_blkno == di->i_last_eb_blk) | ||
519 | *is_last = 1; | ||
520 | else if (eb->h_next_leaf_blk == di->i_last_eb_blk) { | ||
521 | ret = ocfs2_last_eb_is_empty(inode, di); | ||
522 | if (ret < 0) { | ||
523 | mlog_errno(ret); | ||
524 | goto out; | ||
525 | } | ||
526 | if (ret == 1) | ||
527 | *is_last = 1; | ||
528 | } | ||
460 | } | 529 | } |
530 | } | ||
531 | |||
532 | out_hole: | ||
533 | ret = 0; | ||
534 | out: | ||
535 | brelse(eb_bh); | ||
536 | return ret; | ||
537 | } | ||
538 | |||
539 | static void ocfs2_relative_extent_offsets(struct super_block *sb, | ||
540 | u32 v_cluster, | ||
541 | struct ocfs2_extent_rec *rec, | ||
542 | u32 *p_cluster, u32 *num_clusters) | ||
543 | |||
544 | { | ||
545 | u32 coff = v_cluster - le32_to_cpu(rec->e_cpos); | ||
546 | |||
547 | *p_cluster = ocfs2_blocks_to_clusters(sb, le64_to_cpu(rec->e_blkno)); | ||
548 | *p_cluster = *p_cluster + coff; | ||
549 | |||
550 | if (num_clusters) | ||
551 | *num_clusters = le16_to_cpu(rec->e_leaf_clusters) - coff; | ||
552 | } | ||
553 | |||
554 | int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, | ||
555 | u32 *p_cluster, u32 *num_clusters, | ||
556 | unsigned int *extent_flags) | ||
557 | { | ||
558 | int ret; | ||
559 | unsigned int uninitialized_var(hole_len), flags = 0; | ||
560 | struct buffer_head *di_bh = NULL; | ||
561 | struct ocfs2_extent_rec rec; | ||
461 | 562 | ||
462 | coff = v_cluster - le32_to_cpu(rec->e_cpos); | 563 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { |
564 | ret = -ERANGE; | ||
565 | mlog_errno(ret); | ||
566 | goto out; | ||
567 | } | ||
463 | 568 | ||
464 | *p_cluster = ocfs2_blocks_to_clusters(inode->i_sb, | 569 | ret = ocfs2_extent_map_lookup(inode, v_cluster, p_cluster, |
465 | le64_to_cpu(rec->e_blkno)); | 570 | num_clusters, extent_flags); |
466 | *p_cluster = *p_cluster + coff; | 571 | if (ret == 0) |
572 | goto out; | ||
467 | 573 | ||
468 | if (num_clusters) | 574 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), OCFS2_I(inode)->ip_blkno, |
469 | *num_clusters = ocfs2_rec_clusters(el, rec) - coff; | 575 | &di_bh, OCFS2_BH_CACHED, inode); |
576 | if (ret) { | ||
577 | mlog_errno(ret); | ||
578 | goto out; | ||
579 | } | ||
470 | 580 | ||
471 | flags = rec->e_flags; | 581 | ret = ocfs2_get_clusters_nocache(inode, di_bh, v_cluster, &hole_len, |
582 | &rec, NULL); | ||
583 | if (ret) { | ||
584 | mlog_errno(ret); | ||
585 | goto out; | ||
586 | } | ||
472 | 587 | ||
473 | ocfs2_extent_map_insert_rec(inode, rec); | 588 | if (rec.e_blkno == 0ULL) { |
589 | /* | ||
590 | * A hole was found. Return some canned values that | ||
591 | * callers can key on. If asked for, num_clusters will | ||
592 | * be populated with the size of the hole. | ||
593 | */ | ||
594 | *p_cluster = 0; | ||
595 | if (num_clusters) { | ||
596 | *num_clusters = hole_len; | ||
597 | } | ||
598 | } else { | ||
599 | ocfs2_relative_extent_offsets(inode->i_sb, v_cluster, &rec, | ||
600 | p_cluster, num_clusters); | ||
601 | flags = rec.e_flags; | ||
602 | |||
603 | ocfs2_extent_map_insert_rec(inode, &rec); | ||
474 | } | 604 | } |
475 | 605 | ||
476 | if (extent_flags) | 606 | if (extent_flags) |
@@ -478,7 +608,6 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, | |||
478 | 608 | ||
479 | out: | 609 | out: |
480 | brelse(di_bh); | 610 | brelse(di_bh); |
481 | brelse(eb_bh); | ||
482 | return ret; | 611 | return ret; |
483 | } | 612 | } |
484 | 613 | ||
@@ -521,3 +650,114 @@ int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, | |||
521 | out: | 650 | out: |
522 | return ret; | 651 | return ret; |
523 | } | 652 | } |
653 | |||
654 | static int ocfs2_fiemap_inline(struct inode *inode, struct buffer_head *di_bh, | ||
655 | struct fiemap_extent_info *fieinfo, | ||
656 | u64 map_start) | ||
657 | { | ||
658 | int ret; | ||
659 | unsigned int id_count; | ||
660 | struct ocfs2_dinode *di; | ||
661 | u64 phys; | ||
662 | u32 flags = FIEMAP_EXTENT_DATA_INLINE|FIEMAP_EXTENT_LAST; | ||
663 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
664 | |||
665 | di = (struct ocfs2_dinode *)di_bh->b_data; | ||
666 | id_count = le16_to_cpu(di->id2.i_data.id_count); | ||
667 | |||
668 | if (map_start < id_count) { | ||
669 | phys = oi->ip_blkno << inode->i_sb->s_blocksize_bits; | ||
670 | phys += offsetof(struct ocfs2_dinode, id2.i_data.id_data); | ||
671 | |||
672 | ret = fiemap_fill_next_extent(fieinfo, 0, phys, id_count, | ||
673 | flags); | ||
674 | if (ret < 0) | ||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | return 0; | ||
679 | } | ||
680 | |||
681 | #define OCFS2_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC) | ||
682 | |||
683 | int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | ||
684 | u64 map_start, u64 map_len) | ||
685 | { | ||
686 | int ret, is_last; | ||
687 | u32 mapping_end, cpos; | ||
688 | unsigned int hole_size; | ||
689 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
690 | u64 len_bytes, phys_bytes, virt_bytes; | ||
691 | struct buffer_head *di_bh = NULL; | ||
692 | struct ocfs2_extent_rec rec; | ||
693 | |||
694 | ret = fiemap_check_flags(fieinfo, OCFS2_FIEMAP_FLAGS); | ||
695 | if (ret) | ||
696 | return ret; | ||
697 | |||
698 | ret = ocfs2_inode_lock(inode, &di_bh, 0); | ||
699 | if (ret) { | ||
700 | mlog_errno(ret); | ||
701 | goto out; | ||
702 | } | ||
703 | |||
704 | down_read(&OCFS2_I(inode)->ip_alloc_sem); | ||
705 | |||
706 | /* | ||
707 | * Handle inline-data separately. | ||
708 | */ | ||
709 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
710 | ret = ocfs2_fiemap_inline(inode, di_bh, fieinfo, map_start); | ||
711 | goto out_unlock; | ||
712 | } | ||
713 | |||
714 | cpos = map_start >> osb->s_clustersize_bits; | ||
715 | mapping_end = ocfs2_clusters_for_bytes(inode->i_sb, | ||
716 | map_start + map_len); | ||
717 | mapping_end -= cpos; | ||
718 | is_last = 0; | ||
719 | while (cpos < mapping_end && !is_last) { | ||
720 | u32 fe_flags; | ||
721 | |||
722 | ret = ocfs2_get_clusters_nocache(inode, di_bh, cpos, | ||
723 | &hole_size, &rec, &is_last); | ||
724 | if (ret) { | ||
725 | mlog_errno(ret); | ||
726 | goto out; | ||
727 | } | ||
728 | |||
729 | if (rec.e_blkno == 0ULL) { | ||
730 | cpos += hole_size; | ||
731 | continue; | ||
732 | } | ||
733 | |||
734 | fe_flags = 0; | ||
735 | if (rec.e_flags & OCFS2_EXT_UNWRITTEN) | ||
736 | fe_flags |= FIEMAP_EXTENT_UNWRITTEN; | ||
737 | if (is_last) | ||
738 | fe_flags |= FIEMAP_EXTENT_LAST; | ||
739 | len_bytes = (u64)le16_to_cpu(rec.e_leaf_clusters) << osb->s_clustersize_bits; | ||
740 | phys_bytes = le64_to_cpu(rec.e_blkno) << osb->sb->s_blocksize_bits; | ||
741 | virt_bytes = (u64)le32_to_cpu(rec.e_cpos) << osb->s_clustersize_bits; | ||
742 | |||
743 | ret = fiemap_fill_next_extent(fieinfo, virt_bytes, phys_bytes, | ||
744 | len_bytes, fe_flags); | ||
745 | if (ret) | ||
746 | break; | ||
747 | |||
748 | cpos = le32_to_cpu(rec.e_cpos)+ le16_to_cpu(rec.e_leaf_clusters); | ||
749 | } | ||
750 | |||
751 | if (ret > 0) | ||
752 | ret = 0; | ||
753 | |||
754 | out_unlock: | ||
755 | brelse(di_bh); | ||
756 | |||
757 | up_read(&OCFS2_I(inode)->ip_alloc_sem); | ||
758 | |||
759 | ocfs2_inode_unlock(inode, 0); | ||
760 | out: | ||
761 | |||
762 | return ret; | ||
763 | } | ||
diff --git a/fs/ocfs2/extent_map.h b/fs/ocfs2/extent_map.h index de91e3e41a22..1b97490e1ea8 100644 --- a/fs/ocfs2/extent_map.h +++ b/fs/ocfs2/extent_map.h | |||
@@ -50,4 +50,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, u32 *p_cluster, | |||
50 | int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, | 50 | int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, |
51 | u64 *ret_count, unsigned int *extent_flags); | 51 | u64 *ret_count, unsigned int *extent_flags); |
52 | 52 | ||
53 | int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | ||
54 | u64 map_start, u64 map_len); | ||
55 | |||
53 | #endif /* _EXTENT_MAP_H */ | 56 | #endif /* _EXTENT_MAP_H */ |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index ec2ed15c3daa..ed38796052d2 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -2228,6 +2228,7 @@ const struct inode_operations ocfs2_file_iops = { | |||
2228 | .getattr = ocfs2_getattr, | 2228 | .getattr = ocfs2_getattr, |
2229 | .permission = ocfs2_permission, | 2229 | .permission = ocfs2_permission, |
2230 | .fallocate = ocfs2_fallocate, | 2230 | .fallocate = ocfs2_fallocate, |
2231 | .fiemap = ocfs2_fiemap, | ||
2231 | }; | 2232 | }; |
2232 | 2233 | ||
2233 | const struct inode_operations ocfs2_special_file_iops = { | 2234 | const struct inode_operations ocfs2_special_file_iops = { |