diff options
author | Mark Fasheh <mfasheh@suse.com> | 2008-11-12 18:43:34 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-04-03 14:39:15 -0400 |
commit | 4a12ca3a00a244e1fd1e673d151ea38b71e11d55 (patch) | |
tree | 84e30310a7d93ead9910f761e19d3fe73c5861b3 /fs/ocfs2/dir.c | |
parent | 59b526a30722f29e5dba6210a6e0fc34e3149b94 (diff) |
ocfs2: Introduce dir lookup helper struct
Many directory manipulation calls pass around a tuple of dirent, and it's
containing buffer_head. Dir indexing has a bit more state, but instead of
adding yet more arguments to functions, we introduce 'struct
ocfs2_dir_lookup_result'. In this patch, it simply holds the same tuple, but
future patches will add more state.
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Acked-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2/dir.c')
-rw-r--r-- | fs/ocfs2/dir.c | 99 |
1 files changed, 54 insertions, 45 deletions
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index f2c4098cf337..76ffb5c10b3e 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -152,6 +152,11 @@ static void ocfs2_init_dir_trailer(struct inode *inode, | |||
152 | trailer->db_blkno = cpu_to_le64(bh->b_blocknr); | 152 | trailer->db_blkno = cpu_to_le64(bh->b_blocknr); |
153 | } | 153 | } |
154 | 154 | ||
155 | void ocfs2_free_dir_lookup_result(struct ocfs2_dir_lookup_result *res) | ||
156 | { | ||
157 | brelse(res->dl_leaf_bh); | ||
158 | } | ||
159 | |||
155 | /* | 160 | /* |
156 | * bh passed here can be an inode block or a dir data block, depending | 161 | * bh passed here can be an inode block or a dir data block, depending |
157 | * on the inode inline data flag. | 162 | * on the inode inline data flag. |
@@ -483,36 +488,46 @@ cleanup_and_exit: | |||
483 | /* | 488 | /* |
484 | * Try to find an entry of the provided name within 'dir'. | 489 | * Try to find an entry of the provided name within 'dir'. |
485 | * | 490 | * |
486 | * If nothing was found, NULL is returned. Otherwise, a buffer_head | 491 | * If nothing was found, -ENOENT is returned. Otherwise, zero is |
487 | * and pointer to the dir entry are passed back. | 492 | * returned and the struct 'res' will contain information useful to |
493 | * other directory manipulation functions. | ||
488 | * | 494 | * |
489 | * Caller can NOT assume anything about the contents of the | 495 | * Caller can NOT assume anything about the contents of the |
490 | * buffer_head - it is passed back only so that it can be passed into | 496 | * buffer_heads - they are passed back only so that it can be passed into |
491 | * any one of the manipulation functions (add entry, delete entry, | 497 | * any one of the manipulation functions (add entry, delete entry, |
492 | * etc). As an example, bh in the extent directory case is a data | 498 | * etc). As an example, bh in the extent directory case is a data |
493 | * block, in the inline-data case it actually points to an inode. | 499 | * block, in the inline-data case it actually points to an inode. |
494 | */ | 500 | */ |
495 | struct buffer_head *ocfs2_find_entry(const char *name, int namelen, | 501 | int ocfs2_find_entry(const char *name, int namelen, |
496 | struct inode *dir, | 502 | struct inode *dir, struct ocfs2_dir_lookup_result *lookup) |
497 | struct ocfs2_dir_entry **res_dir) | ||
498 | { | 503 | { |
499 | *res_dir = NULL; | 504 | struct buffer_head *bh; |
505 | struct ocfs2_dir_entry *res_dir = NULL; | ||
500 | 506 | ||
501 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | 507 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) |
502 | return ocfs2_find_entry_id(name, namelen, dir, res_dir); | 508 | bh = ocfs2_find_entry_id(name, namelen, dir, &res_dir); |
509 | else | ||
510 | bh = ocfs2_find_entry_el(name, namelen, dir, &res_dir); | ||
503 | 511 | ||
504 | return ocfs2_find_entry_el(name, namelen, dir, res_dir); | 512 | if (bh == NULL) |
513 | return -ENOENT; | ||
514 | |||
515 | lookup->dl_leaf_bh = bh; | ||
516 | lookup->dl_entry = res_dir; | ||
517 | return 0; | ||
505 | } | 518 | } |
506 | 519 | ||
507 | /* | 520 | /* |
508 | * Update inode number and type of a previously found directory entry. | 521 | * Update inode number and type of a previously found directory entry. |
509 | */ | 522 | */ |
510 | int ocfs2_update_entry(struct inode *dir, handle_t *handle, | 523 | int ocfs2_update_entry(struct inode *dir, handle_t *handle, |
511 | struct buffer_head *de_bh, struct ocfs2_dir_entry *de, | 524 | struct ocfs2_dir_lookup_result *res, |
512 | struct inode *new_entry_inode) | 525 | struct inode *new_entry_inode) |
513 | { | 526 | { |
514 | int ret; | 527 | int ret; |
515 | ocfs2_journal_access_func access = ocfs2_journal_access_db; | 528 | ocfs2_journal_access_func access = ocfs2_journal_access_db; |
529 | struct ocfs2_dir_entry *de = res->dl_entry; | ||
530 | struct buffer_head *de_bh = res->dl_leaf_bh; | ||
516 | 531 | ||
517 | /* | 532 | /* |
518 | * The same code works fine for both inline-data and extent | 533 | * The same code works fine for both inline-data and extent |
@@ -629,13 +644,14 @@ static inline int ocfs2_delete_entry_el(handle_t *handle, | |||
629 | */ | 644 | */ |
630 | int ocfs2_delete_entry(handle_t *handle, | 645 | int ocfs2_delete_entry(handle_t *handle, |
631 | struct inode *dir, | 646 | struct inode *dir, |
632 | struct ocfs2_dir_entry *de_del, | 647 | struct ocfs2_dir_lookup_result *res) |
633 | struct buffer_head *bh) | ||
634 | { | 648 | { |
635 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | 649 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) |
636 | return ocfs2_delete_entry_id(handle, dir, de_del, bh); | 650 | return ocfs2_delete_entry_id(handle, dir, res->dl_entry, |
651 | res->dl_leaf_bh); | ||
637 | 652 | ||
638 | return ocfs2_delete_entry_el(handle, dir, de_del, bh); | 653 | return ocfs2_delete_entry_el(handle, dir, res->dl_entry, |
654 | res->dl_leaf_bh); | ||
639 | } | 655 | } |
640 | 656 | ||
641 | /* | 657 | /* |
@@ -666,15 +682,15 @@ static inline int ocfs2_dirent_would_fit(struct ocfs2_dir_entry *de, | |||
666 | /* we don't always have a dentry for what we want to add, so people | 682 | /* we don't always have a dentry for what we want to add, so people |
667 | * like orphan dir can call this instead. | 683 | * like orphan dir can call this instead. |
668 | * | 684 | * |
669 | * If you pass me insert_bh, I'll skip the search of the other dir | 685 | * The lookup context must have been filled from |
670 | * blocks and put the record in there. | 686 | * ocfs2_prepare_dir_for_insert. |
671 | */ | 687 | */ |
672 | int __ocfs2_add_entry(handle_t *handle, | 688 | int __ocfs2_add_entry(handle_t *handle, |
673 | struct inode *dir, | 689 | struct inode *dir, |
674 | const char *name, int namelen, | 690 | const char *name, int namelen, |
675 | struct inode *inode, u64 blkno, | 691 | struct inode *inode, u64 blkno, |
676 | struct buffer_head *parent_fe_bh, | 692 | struct buffer_head *parent_fe_bh, |
677 | struct buffer_head *insert_bh) | 693 | struct ocfs2_dir_lookup_result *lookup) |
678 | { | 694 | { |
679 | unsigned long offset; | 695 | unsigned long offset; |
680 | unsigned short rec_len; | 696 | unsigned short rec_len; |
@@ -683,6 +699,7 @@ int __ocfs2_add_entry(handle_t *handle, | |||
683 | struct super_block *sb = dir->i_sb; | 699 | struct super_block *sb = dir->i_sb; |
684 | int retval, status; | 700 | int retval, status; |
685 | unsigned int size = sb->s_blocksize; | 701 | unsigned int size = sb->s_blocksize; |
702 | struct buffer_head *insert_bh = lookup->dl_leaf_bh; | ||
686 | char *data_start = insert_bh->b_data; | 703 | char *data_start = insert_bh->b_data; |
687 | 704 | ||
688 | mlog_entry_void(); | 705 | mlog_entry_void(); |
@@ -1071,31 +1088,22 @@ int ocfs2_find_files_on_disk(const char *name, | |||
1071 | int namelen, | 1088 | int namelen, |
1072 | u64 *blkno, | 1089 | u64 *blkno, |
1073 | struct inode *inode, | 1090 | struct inode *inode, |
1074 | struct buffer_head **dirent_bh, | 1091 | struct ocfs2_dir_lookup_result *lookup) |
1075 | struct ocfs2_dir_entry **dirent) | ||
1076 | { | 1092 | { |
1077 | int status = -ENOENT; | 1093 | int status = -ENOENT; |
1078 | 1094 | ||
1079 | mlog_entry("(name=%.*s, blkno=%p, inode=%p, dirent_bh=%p, dirent=%p)\n", | 1095 | mlog(0, "name=%.*s, blkno=%p, inode=%llu\n", namelen, name, blkno, |
1080 | namelen, name, blkno, inode, dirent_bh, dirent); | 1096 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
1081 | 1097 | ||
1082 | *dirent_bh = ocfs2_find_entry(name, namelen, inode, dirent); | 1098 | status = ocfs2_find_entry(name, namelen, inode, lookup); |
1083 | if (!*dirent_bh || !*dirent) { | 1099 | if (status) |
1084 | status = -ENOENT; | ||
1085 | goto leave; | 1100 | goto leave; |
1086 | } | ||
1087 | 1101 | ||
1088 | *blkno = le64_to_cpu((*dirent)->inode); | 1102 | *blkno = le64_to_cpu(lookup->dl_entry->inode); |
1089 | 1103 | ||
1090 | status = 0; | 1104 | status = 0; |
1091 | leave: | 1105 | leave: |
1092 | if (status < 0) { | ||
1093 | *dirent = NULL; | ||
1094 | brelse(*dirent_bh); | ||
1095 | *dirent_bh = NULL; | ||
1096 | } | ||
1097 | 1106 | ||
1098 | mlog_exit(status); | ||
1099 | return status; | 1107 | return status; |
1100 | } | 1108 | } |
1101 | 1109 | ||
@@ -1107,11 +1115,10 @@ int ocfs2_lookup_ino_from_name(struct inode *dir, const char *name, | |||
1107 | int namelen, u64 *blkno) | 1115 | int namelen, u64 *blkno) |
1108 | { | 1116 | { |
1109 | int ret; | 1117 | int ret; |
1110 | struct buffer_head *bh = NULL; | 1118 | struct ocfs2_dir_lookup_result lookup = { NULL, }; |
1111 | struct ocfs2_dir_entry *dirent = NULL; | ||
1112 | 1119 | ||
1113 | ret = ocfs2_find_files_on_disk(name, namelen, blkno, dir, &bh, &dirent); | 1120 | ret = ocfs2_find_files_on_disk(name, namelen, blkno, dir, &lookup); |
1114 | brelse(bh); | 1121 | ocfs2_free_dir_lookup_result(&lookup); |
1115 | 1122 | ||
1116 | return ret; | 1123 | return ret; |
1117 | } | 1124 | } |
@@ -1128,20 +1135,18 @@ int ocfs2_check_dir_for_entry(struct inode *dir, | |||
1128 | int namelen) | 1135 | int namelen) |
1129 | { | 1136 | { |
1130 | int ret; | 1137 | int ret; |
1131 | struct buffer_head *dirent_bh = NULL; | 1138 | struct ocfs2_dir_lookup_result lookup = { NULL, }; |
1132 | struct ocfs2_dir_entry *dirent = NULL; | ||
1133 | 1139 | ||
1134 | mlog_entry("dir %llu, name '%.*s'\n", | 1140 | mlog_entry("dir %llu, name '%.*s'\n", |
1135 | (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name); | 1141 | (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name); |
1136 | 1142 | ||
1137 | ret = -EEXIST; | 1143 | ret = -EEXIST; |
1138 | dirent_bh = ocfs2_find_entry(name, namelen, dir, &dirent); | 1144 | if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0) |
1139 | if (dirent_bh) | ||
1140 | goto bail; | 1145 | goto bail; |
1141 | 1146 | ||
1142 | ret = 0; | 1147 | ret = 0; |
1143 | bail: | 1148 | bail: |
1144 | brelse(dirent_bh); | 1149 | ocfs2_free_dir_lookup_result(&lookup); |
1145 | 1150 | ||
1146 | mlog_exit(ret); | 1151 | mlog_exit(ret); |
1147 | return ret; | 1152 | return ret; |
@@ -1970,12 +1975,18 @@ bail: | |||
1970 | return status; | 1975 | return status; |
1971 | } | 1976 | } |
1972 | 1977 | ||
1978 | /* | ||
1979 | * Get a directory ready for insert. Any directory allocation required | ||
1980 | * happens here. Success returns zero, and enough context in the dir | ||
1981 | * lookup result that ocfs2_add_entry() will be able complete the task | ||
1982 | * with minimal performance impact. | ||
1983 | */ | ||
1973 | int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | 1984 | int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, |
1974 | struct inode *dir, | 1985 | struct inode *dir, |
1975 | struct buffer_head *parent_fe_bh, | 1986 | struct buffer_head *parent_fe_bh, |
1976 | const char *name, | 1987 | const char *name, |
1977 | int namelen, | 1988 | int namelen, |
1978 | struct buffer_head **ret_de_bh) | 1989 | struct ocfs2_dir_lookup_result *lookup) |
1979 | { | 1990 | { |
1980 | int ret; | 1991 | int ret; |
1981 | unsigned int blocks_wanted = 1; | 1992 | unsigned int blocks_wanted = 1; |
@@ -1984,8 +1995,6 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | |||
1984 | mlog(0, "getting ready to insert namelen %d into dir %llu\n", | 1995 | mlog(0, "getting ready to insert namelen %d into dir %llu\n", |
1985 | namelen, (unsigned long long)OCFS2_I(dir)->ip_blkno); | 1996 | namelen, (unsigned long long)OCFS2_I(dir)->ip_blkno); |
1986 | 1997 | ||
1987 | *ret_de_bh = NULL; | ||
1988 | |||
1989 | if (!namelen) { | 1998 | if (!namelen) { |
1990 | ret = -EINVAL; | 1999 | ret = -EINVAL; |
1991 | mlog_errno(ret); | 2000 | mlog_errno(ret); |
@@ -2020,7 +2029,7 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | |||
2020 | BUG_ON(!bh); | 2029 | BUG_ON(!bh); |
2021 | } | 2030 | } |
2022 | 2031 | ||
2023 | *ret_de_bh = bh; | 2032 | lookup->dl_leaf_bh = bh; |
2024 | bh = NULL; | 2033 | bh = NULL; |
2025 | out: | 2034 | out: |
2026 | brelse(bh); | 2035 | brelse(bh); |