aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dir.c
diff options
context:
space:
mode:
authorMark Fasheh <mfasheh@suse.com>2008-11-12 18:43:34 -0500
committerMark Fasheh <mfasheh@suse.com>2009-04-03 14:39:15 -0400
commit4a12ca3a00a244e1fd1e673d151ea38b71e11d55 (patch)
tree84e30310a7d93ead9910f761e19d3fe73c5861b3 /fs/ocfs2/dir.c
parent59b526a30722f29e5dba6210a6e0fc34e3149b94 (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.c99
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
155void 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 */
495struct buffer_head *ocfs2_find_entry(const char *name, int namelen, 501int 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 */
510int ocfs2_update_entry(struct inode *dir, handle_t *handle, 523int 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 */
630int ocfs2_delete_entry(handle_t *handle, 645int 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 */
672int __ocfs2_add_entry(handle_t *handle, 688int __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;
1091leave: 1105leave:
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;
1143bail: 1148bail:
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 */
1973int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, 1984int 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;
2025out: 2034out:
2026 brelse(bh); 2035 brelse(bh);