aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-09-07 21:21:26 -0400
committerMark Fasheh <mark.fasheh@oracle.com>2007-10-12 14:54:36 -0400
commit316f4b9f98a353ac1be93199694fd97272378815 (patch)
treec54f7feb08fc1693f64879d8a3edc18cf3bb2713 /fs
parent1d410a6e337a0d2d5543ad1d9bccb670a7a05312 (diff)
ocfs2: Move directory manipulation code into dir.c
The code for adding, removing, deleting directory entries was splattered all over namei.c. I'd rather have this all centralized, so that it's easier to make changes for inline dir data, and eventually indexed directories. None of the code in any of the functions was changed. I only removed the static keyword from some prototypes so that they could be exported. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com> Reviewed-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/dir.c430
-rw-r--r--fs/ocfs2/dir.h44
-rw-r--r--fs/ocfs2/journal.c2
-rw-r--r--fs/ocfs2/namei.c433
-rw-r--r--fs/ocfs2/namei.h19
5 files changed, 461 insertions, 467 deletions
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 0d5fdde959c..8e0ae022b2e 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -55,10 +55,16 @@
55#include "journal.h" 55#include "journal.h"
56#include "namei.h" 56#include "namei.h"
57#include "suballoc.h" 57#include "suballoc.h"
58#include "super.h"
58#include "uptodate.h" 59#include "uptodate.h"
59 60
60#include "buffer_head_io.h" 61#include "buffer_head_io.h"
61 62
63#define NAMEI_RA_CHUNKS 2
64#define NAMEI_RA_BLOCKS 4
65#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
66#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
67
62static unsigned char ocfs2_filetype_table[] = { 68static unsigned char ocfs2_filetype_table[] = {
63 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK 69 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
64}; 70};
@@ -67,6 +73,347 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
67 struct inode *dir, 73 struct inode *dir,
68 struct buffer_head *parent_fe_bh, 74 struct buffer_head *parent_fe_bh,
69 struct buffer_head **new_de_bh); 75 struct buffer_head **new_de_bh);
76static int ocfs2_do_extend_dir(struct super_block *sb,
77 handle_t *handle,
78 struct inode *dir,
79 struct buffer_head *parent_fe_bh,
80 struct ocfs2_alloc_context *data_ac,
81 struct ocfs2_alloc_context *meta_ac,
82 struct buffer_head **new_bh);
83
84int ocfs2_check_dir_entry(struct inode * dir,
85 struct ocfs2_dir_entry * de,
86 struct buffer_head * bh,
87 unsigned long offset)
88{
89 const char *error_msg = NULL;
90 const int rlen = le16_to_cpu(de->rec_len);
91
92 if (rlen < OCFS2_DIR_REC_LEN(1))
93 error_msg = "rec_len is smaller than minimal";
94 else if (rlen % 4 != 0)
95 error_msg = "rec_len % 4 != 0";
96 else if (rlen < OCFS2_DIR_REC_LEN(de->name_len))
97 error_msg = "rec_len is too small for name_len";
98 else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
99 error_msg = "directory entry across blocks";
100
101 if (error_msg != NULL)
102 mlog(ML_ERROR, "bad entry in directory #%llu: %s - "
103 "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n",
104 (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg,
105 offset, (unsigned long long)le64_to_cpu(de->inode), rlen,
106 de->name_len);
107 return error_msg == NULL ? 1 : 0;
108}
109
110static inline int ocfs2_match(int len,
111 const char * const name,
112 struct ocfs2_dir_entry *de)
113{
114 if (len != de->name_len)
115 return 0;
116 if (!de->inode)
117 return 0;
118 return !memcmp(name, de->name, len);
119}
120
121/*
122 * Returns 0 if not found, -1 on failure, and 1 on success
123 */
124static int inline ocfs2_search_dirblock(struct buffer_head *bh,
125 struct inode *dir,
126 const char *name, int namelen,
127 unsigned long offset,
128 struct ocfs2_dir_entry **res_dir)
129{
130 struct ocfs2_dir_entry *de;
131 char *dlimit, *de_buf;
132 int de_len;
133 int ret = 0;
134
135 mlog_entry_void();
136
137 de_buf = bh->b_data;
138 dlimit = de_buf + dir->i_sb->s_blocksize;
139
140 while (de_buf < dlimit) {
141 /* this code is executed quadratically often */
142 /* do minimal checking `by hand' */
143
144 de = (struct ocfs2_dir_entry *) de_buf;
145
146 if (de_buf + namelen <= dlimit &&
147 ocfs2_match(namelen, name, de)) {
148 /* found a match - just to be sure, do a full check */
149 if (!ocfs2_check_dir_entry(dir, de, bh, offset)) {
150 ret = -1;
151 goto bail;
152 }
153 *res_dir = de;
154 ret = 1;
155 goto bail;
156 }
157
158 /* prevent looping on a bad block */
159 de_len = le16_to_cpu(de->rec_len);
160 if (de_len <= 0) {
161 ret = -1;
162 goto bail;
163 }
164
165 de_buf += de_len;
166 offset += de_len;
167 }
168
169bail:
170 mlog_exit(ret);
171 return ret;
172}
173
174struct buffer_head *ocfs2_find_entry(const char *name, int namelen,
175 struct inode *dir,
176 struct ocfs2_dir_entry **res_dir)
177{
178 struct super_block *sb;
179 struct buffer_head *bh_use[NAMEI_RA_SIZE];
180 struct buffer_head *bh, *ret = NULL;
181 unsigned long start, block, b;
182 int ra_max = 0; /* Number of bh's in the readahead
183 buffer, bh_use[] */
184 int ra_ptr = 0; /* Current index into readahead
185 buffer */
186 int num = 0;
187 int nblocks, i, err;
188
189 mlog_entry_void();
190
191 *res_dir = NULL;
192 sb = dir->i_sb;
193
194 nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
195 start = OCFS2_I(dir)->ip_dir_start_lookup;
196 if (start >= nblocks)
197 start = 0;
198 block = start;
199
200restart:
201 do {
202 /*
203 * We deal with the read-ahead logic here.
204 */
205 if (ra_ptr >= ra_max) {
206 /* Refill the readahead buffer */
207 ra_ptr = 0;
208 b = block;
209 for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
210 /*
211 * Terminate if we reach the end of the
212 * directory and must wrap, or if our
213 * search has finished at this block.
214 */
215 if (b >= nblocks || (num && block == start)) {
216 bh_use[ra_max] = NULL;
217 break;
218 }
219 num++;
220
221 bh = ocfs2_bread(dir, b++, &err, 1);
222 bh_use[ra_max] = bh;
223 }
224 }
225 if ((bh = bh_use[ra_ptr++]) == NULL)
226 goto next;
227 wait_on_buffer(bh);
228 if (!buffer_uptodate(bh)) {
229 /* read error, skip block & hope for the best */
230 ocfs2_error(dir->i_sb, "reading directory %llu, "
231 "offset %lu\n",
232 (unsigned long long)OCFS2_I(dir)->ip_blkno,
233 block);
234 brelse(bh);
235 goto next;
236 }
237 i = ocfs2_search_dirblock(bh, dir, name, namelen,
238 block << sb->s_blocksize_bits,
239 res_dir);
240 if (i == 1) {
241 OCFS2_I(dir)->ip_dir_start_lookup = block;
242 ret = bh;
243 goto cleanup_and_exit;
244 } else {
245 brelse(bh);
246 if (i < 0)
247 goto cleanup_and_exit;
248 }
249 next:
250 if (++block >= nblocks)
251 block = 0;
252 } while (block != start);
253
254 /*
255 * If the directory has grown while we were searching, then
256 * search the last part of the directory before giving up.
257 */
258 block = nblocks;
259 nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
260 if (block < nblocks) {
261 start = 0;
262 goto restart;
263 }
264
265cleanup_and_exit:
266 /* Clean up the read-ahead blocks */
267 for (; ra_ptr < ra_max; ra_ptr++)
268 brelse(bh_use[ra_ptr]);
269
270 mlog_exit_ptr(ret);
271 return ret;
272}
273
274/*
275 * ocfs2_delete_entry deletes a directory entry by merging it with the
276 * previous entry
277 */
278int ocfs2_delete_entry(handle_t *handle,
279 struct inode *dir,
280 struct ocfs2_dir_entry *de_del,
281 struct buffer_head *bh)
282{
283 struct ocfs2_dir_entry *de, *pde;
284 int i, status = -ENOENT;
285
286 mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh);
287
288 i = 0;
289 pde = NULL;
290 de = (struct ocfs2_dir_entry *) bh->b_data;
291 while (i < bh->b_size) {
292 if (!ocfs2_check_dir_entry(dir, de, bh, i)) {
293 status = -EIO;
294 mlog_errno(status);
295 goto bail;
296 }
297 if (de == de_del) {
298 status = ocfs2_journal_access(handle, dir, bh,
299 OCFS2_JOURNAL_ACCESS_WRITE);
300 if (status < 0) {
301 status = -EIO;
302 mlog_errno(status);
303 goto bail;
304 }
305 if (pde)
306 pde->rec_len =
307 cpu_to_le16(le16_to_cpu(pde->rec_len) +
308 le16_to_cpu(de->rec_len));
309 else
310 de->inode = 0;
311 dir->i_version++;
312 status = ocfs2_journal_dirty(handle, bh);
313 goto bail;
314 }
315 i += le16_to_cpu(de->rec_len);
316 pde = de;
317 de = (struct ocfs2_dir_entry *)((char *)de + le16_to_cpu(de->rec_len));
318 }
319bail:
320 mlog_exit(status);
321 return status;
322}
323
324/* we don't always have a dentry for what we want to add, so people
325 * like orphan dir can call this instead.
326 *
327 * If you pass me insert_bh, I'll skip the search of the other dir
328 * blocks and put the record in there.
329 */
330int __ocfs2_add_entry(handle_t *handle,
331 struct inode *dir,
332 const char *name, int namelen,
333 struct inode *inode, u64 blkno,
334 struct buffer_head *parent_fe_bh,
335 struct buffer_head *insert_bh)
336{
337 unsigned long offset;
338 unsigned short rec_len;
339 struct ocfs2_dir_entry *de, *de1;
340 struct super_block *sb;
341 int retval, status;
342
343 mlog_entry_void();
344
345 sb = dir->i_sb;
346
347 if (!namelen)
348 return -EINVAL;
349
350 rec_len = OCFS2_DIR_REC_LEN(namelen);
351 offset = 0;
352 de = (struct ocfs2_dir_entry *) insert_bh->b_data;
353 while (1) {
354 BUG_ON((char *)de >= sb->s_blocksize + insert_bh->b_data);
355 /* These checks should've already been passed by the
356 * prepare function, but I guess we can leave them
357 * here anyway. */
358 if (!ocfs2_check_dir_entry(dir, de, insert_bh, offset)) {
359 retval = -ENOENT;
360 goto bail;
361 }
362 if (ocfs2_match(namelen, name, de)) {
363 retval = -EEXIST;
364 goto bail;
365 }
366 if (((le64_to_cpu(de->inode) == 0) &&
367 (le16_to_cpu(de->rec_len) >= rec_len)) ||
368 (le16_to_cpu(de->rec_len) >=
369 (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) {
370 dir->i_mtime = dir->i_ctime = CURRENT_TIME;
371 retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
372 if (retval < 0) {
373 mlog_errno(retval);
374 goto bail;
375 }
376
377 status = ocfs2_journal_access(handle, dir, insert_bh,
378 OCFS2_JOURNAL_ACCESS_WRITE);
379 /* By now the buffer is marked for journaling */
380 offset += le16_to_cpu(de->rec_len);
381 if (le64_to_cpu(de->inode)) {
382 de1 = (struct ocfs2_dir_entry *)((char *) de +
383 OCFS2_DIR_REC_LEN(de->name_len));
384 de1->rec_len =
385 cpu_to_le16(le16_to_cpu(de->rec_len) -
386 OCFS2_DIR_REC_LEN(de->name_len));
387 de->rec_len = cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
388 de = de1;
389 }
390 de->file_type = OCFS2_FT_UNKNOWN;
391 if (blkno) {
392 de->inode = cpu_to_le64(blkno);
393 ocfs2_set_de_type(de, inode->i_mode);
394 } else
395 de->inode = 0;
396 de->name_len = namelen;
397 memcpy(de->name, name, namelen);
398
399 dir->i_version++;
400 status = ocfs2_journal_dirty(handle, insert_bh);
401 retval = 0;
402 goto bail;
403 }
404 offset += le16_to_cpu(de->rec_len);
405 de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
406 }
407
408 /* when you think about it, the assert above should prevent us
409 * from ever getting here. */
410 retval = -ENOSPC;
411bail:
412
413 mlog_exit(retval);
414 return retval;
415}
416
70/* 417/*
71 * ocfs2_readdir() 418 * ocfs2_readdir()
72 * 419 *
@@ -347,14 +694,83 @@ int ocfs2_empty_dir(struct inode *inode)
347 return 1; 694 return 1;
348} 695}
349 696
697int ocfs2_fill_new_dir(struct ocfs2_super *osb,
698 handle_t *handle,
699 struct inode *parent,
700 struct inode *inode,
701 struct buffer_head *fe_bh,
702 struct ocfs2_alloc_context *data_ac)
703{
704 int status;
705 struct buffer_head *new_bh = NULL;
706 struct ocfs2_dir_entry *de = NULL;
707
708 mlog_entry_void();
709
710 status = ocfs2_do_extend_dir(osb->sb, handle, inode, fe_bh,
711 data_ac, NULL, &new_bh);
712 if (status < 0) {
713 mlog_errno(status);
714 goto bail;
715 }
716
717 ocfs2_set_new_buffer_uptodate(inode, new_bh);
718
719 status = ocfs2_journal_access(handle, inode, new_bh,
720 OCFS2_JOURNAL_ACCESS_CREATE);
721 if (status < 0) {
722 mlog_errno(status);
723 goto bail;
724 }
725 memset(new_bh->b_data, 0, osb->sb->s_blocksize);
726
727 de = (struct ocfs2_dir_entry *) new_bh->b_data;
728 de->inode = cpu_to_le64(OCFS2_I(inode)->ip_blkno);
729 de->name_len = 1;
730 de->rec_len =
731 cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
732 strcpy(de->name, ".");
733 ocfs2_set_de_type(de, S_IFDIR);
734 de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len));
735 de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno);
736 de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize -
737 OCFS2_DIR_REC_LEN(1));
738 de->name_len = 2;
739 strcpy(de->name, "..");
740 ocfs2_set_de_type(de, S_IFDIR);
741
742 status = ocfs2_journal_dirty(handle, new_bh);
743 if (status < 0) {
744 mlog_errno(status);
745 goto bail;
746 }
747
748 i_size_write(inode, inode->i_sb->s_blocksize);
749 inode->i_nlink = 2;
750 inode->i_blocks = ocfs2_inode_sector_count(inode);
751 status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
752 if (status < 0) {
753 mlog_errno(status);
754 goto bail;
755 }
756
757 status = 0;
758bail:
759 if (new_bh)
760 brelse(new_bh);
761
762 mlog_exit(status);
763 return status;
764}
765
350/* returns a bh of the 1st new block in the allocation. */ 766/* returns a bh of the 1st new block in the allocation. */
351int ocfs2_do_extend_dir(struct super_block *sb, 767static int ocfs2_do_extend_dir(struct super_block *sb,
352 handle_t *handle, 768 handle_t *handle,
353 struct inode *dir, 769 struct inode *dir,
354 struct buffer_head *parent_fe_bh, 770 struct buffer_head *parent_fe_bh,
355 struct ocfs2_alloc_context *data_ac, 771 struct ocfs2_alloc_context *data_ac,
356 struct ocfs2_alloc_context *meta_ac, 772 struct ocfs2_alloc_context *meta_ac,
357 struct buffer_head **new_bh) 773 struct buffer_head **new_bh)
358{ 774{
359 int status; 775 int status;
360 int extend; 776 int extend;
diff --git a/fs/ocfs2/dir.h b/fs/ocfs2/dir.h
index 3f67e146864..7bf9c0a01cd 100644
--- a/fs/ocfs2/dir.h
+++ b/fs/ocfs2/dir.h
@@ -26,6 +26,31 @@
26#ifndef OCFS2_DIR_H 26#ifndef OCFS2_DIR_H
27#define OCFS2_DIR_H 27#define OCFS2_DIR_H
28 28
29struct buffer_head *ocfs2_find_entry(const char *name,
30 int namelen,
31 struct inode *dir,
32 struct ocfs2_dir_entry **res_dir);
33int ocfs2_delete_entry(handle_t *handle,
34 struct inode *dir,
35 struct ocfs2_dir_entry *de_del,
36 struct buffer_head *bh);
37int __ocfs2_add_entry(handle_t *handle,
38 struct inode *dir,
39 const char *name, int namelen,
40 struct inode *inode, u64 blkno,
41 struct buffer_head *parent_fe_bh,
42 struct buffer_head *insert_bh);
43static inline int ocfs2_add_entry(handle_t *handle,
44 struct dentry *dentry,
45 struct inode *inode, u64 blkno,
46 struct buffer_head *parent_fe_bh,
47 struct buffer_head *insert_bh)
48{
49 return __ocfs2_add_entry(handle, dentry->d_parent->d_inode,
50 dentry->d_name.name, dentry->d_name.len,
51 inode, blkno, parent_fe_bh, insert_bh);
52}
53
29int ocfs2_check_dir_for_entry(struct inode *dir, 54int ocfs2_check_dir_for_entry(struct inode *dir,
30 const char *name, 55 const char *name,
31 int namelen); 56 int namelen);
@@ -44,11 +69,16 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
44 int namelen, 69 int namelen,
45 struct buffer_head **ret_de_bh); 70 struct buffer_head **ret_de_bh);
46struct ocfs2_alloc_context; 71struct ocfs2_alloc_context;
47int ocfs2_do_extend_dir(struct super_block *sb, 72int ocfs2_fill_new_dir(struct ocfs2_super *osb,
48 handle_t *handle, 73 handle_t *handle,
49 struct inode *dir, 74 struct inode *parent,
50 struct buffer_head *parent_fe_bh, 75 struct inode *inode,
51 struct ocfs2_alloc_context *data_ac, 76 struct buffer_head *fe_bh,
52 struct ocfs2_alloc_context *meta_ac, 77 struct ocfs2_alloc_context *data_ac);
53 struct buffer_head **new_bh); 78
79int ocfs2_check_dir_entry(struct inode *dir,
80 struct ocfs2_dir_entry *de,
81 struct buffer_head *bh,
82 unsigned long offset);
83
54#endif /* OCFS2_DIR_H */ 84#endif /* OCFS2_DIR_H */
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index dbfb20bb27e..8bbfc80e5c5 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -35,13 +35,13 @@
35#include "ocfs2.h" 35#include "ocfs2.h"
36 36
37#include "alloc.h" 37#include "alloc.h"
38#include "dir.h"
38#include "dlmglue.h" 39#include "dlmglue.h"
39#include "extent_map.h" 40#include "extent_map.h"
40#include "heartbeat.h" 41#include "heartbeat.h"
41#include "inode.h" 42#include "inode.h"
42#include "journal.h" 43#include "journal.h"
43#include "localalloc.h" 44#include "localalloc.h"
44#include "namei.h"
45#include "slot_map.h" 45#include "slot_map.h"
46#include "super.h" 46#include "super.h"
47#include "vote.h" 47#include "vote.h"
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 701e6d04ed5..aae6c0bf669 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -64,29 +64,6 @@
64 64
65#include "buffer_head_io.h" 65#include "buffer_head_io.h"
66 66
67#define NAMEI_RA_CHUNKS 2
68#define NAMEI_RA_BLOCKS 4
69#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
70#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
71
72static int inline ocfs2_search_dirblock(struct buffer_head *bh,
73 struct inode *dir,
74 const char *name, int namelen,
75 unsigned long offset,
76 struct ocfs2_dir_entry **res_dir);
77
78static int ocfs2_delete_entry(handle_t *handle,
79 struct inode *dir,
80 struct ocfs2_dir_entry *de_del,
81 struct buffer_head *bh);
82
83static int __ocfs2_add_entry(handle_t *handle,
84 struct inode *dir,
85 const char *name, int namelen,
86 struct inode *inode, u64 blkno,
87 struct buffer_head *parent_fe_bh,
88 struct buffer_head *insert_bh);
89
90static int ocfs2_mknod_locked(struct ocfs2_super *osb, 67static int ocfs2_mknod_locked(struct ocfs2_super *osb,
91 struct inode *dir, 68 struct inode *dir,
92 struct dentry *dentry, int mode, 69 struct dentry *dentry, int mode,
@@ -97,13 +74,6 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
97 struct inode **ret_inode, 74 struct inode **ret_inode,
98 struct ocfs2_alloc_context *inode_ac); 75 struct ocfs2_alloc_context *inode_ac);
99 76
100static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
101 handle_t *handle,
102 struct inode *parent,
103 struct inode *inode,
104 struct buffer_head *fe_bh,
105 struct ocfs2_alloc_context *data_ac);
106
107static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, 77static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
108 struct inode **ret_orphan_dir, 78 struct inode **ret_orphan_dir,
109 struct inode *inode, 79 struct inode *inode,
@@ -123,17 +93,6 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
123 struct inode *inode, 93 struct inode *inode,
124 const char *symname); 94 const char *symname);
125 95
126static inline int ocfs2_add_entry(handle_t *handle,
127 struct dentry *dentry,
128 struct inode *inode, u64 blkno,
129 struct buffer_head *parent_fe_bh,
130 struct buffer_head *insert_bh)
131{
132 return __ocfs2_add_entry(handle, dentry->d_parent->d_inode,
133 dentry->d_name.name, dentry->d_name.len,
134 inode, blkno, parent_fe_bh, insert_bh);
135}
136
137/* An orphan dir name is an 8 byte value, printed as a hex string */ 96/* An orphan dir name is an 8 byte value, printed as a hex string */
138#define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) 97#define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64)))
139 98
@@ -232,75 +191,6 @@ bail:
232 return ret; 191 return ret;
233} 192}
234 193
235static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
236 handle_t *handle,
237 struct inode *parent,
238 struct inode *inode,
239 struct buffer_head *fe_bh,
240 struct ocfs2_alloc_context *data_ac)
241{
242 int status;
243 struct buffer_head *new_bh = NULL;
244 struct ocfs2_dir_entry *de = NULL;
245
246 mlog_entry_void();
247
248 status = ocfs2_do_extend_dir(osb->sb, handle, inode, fe_bh,
249 data_ac, NULL, &new_bh);
250 if (status < 0) {
251 mlog_errno(status);
252 goto bail;
253 }
254
255 ocfs2_set_new_buffer_uptodate(inode, new_bh);
256
257 status = ocfs2_journal_access(handle, inode, new_bh,
258 OCFS2_JOURNAL_ACCESS_CREATE);
259 if (status < 0) {
260 mlog_errno(status);
261 goto bail;
262 }
263 memset(new_bh->b_data, 0, osb->sb->s_blocksize);
264
265 de = (struct ocfs2_dir_entry *) new_bh->b_data;
266 de->inode = cpu_to_le64(OCFS2_I(inode)->ip_blkno);
267 de->name_len = 1;
268 de->rec_len =
269 cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
270 strcpy(de->name, ".");
271 ocfs2_set_de_type(de, S_IFDIR);
272 de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len));
273 de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno);
274 de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize -
275 OCFS2_DIR_REC_LEN(1));
276 de->name_len = 2;
277 strcpy(de->name, "..");
278 ocfs2_set_de_type(de, S_IFDIR);
279
280 status = ocfs2_journal_dirty(handle, new_bh);
281 if (status < 0) {
282 mlog_errno(status);
283 goto bail;
284 }
285
286 i_size_write(inode, inode->i_sb->s_blocksize);
287 inode->i_nlink = 2;
288 inode->i_blocks = ocfs2_inode_sector_count(inode);
289 status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
290 if (status < 0) {
291 mlog_errno(status);
292 goto bail;
293 }
294
295 status = 0;
296bail:
297 if (new_bh)
298 brelse(new_bh);
299
300 mlog_exit(status);
301 return status;
302}
303
304static int ocfs2_mknod(struct inode *dir, 194static int ocfs2_mknod(struct inode *dir,
305 struct dentry *dentry, 195 struct dentry *dentry,
306 int mode, 196 int mode,
@@ -1767,329 +1657,6 @@ bail:
1767 return status; 1657 return status;
1768} 1658}
1769 1659
1770int ocfs2_check_dir_entry(struct inode * dir,
1771 struct ocfs2_dir_entry * de,
1772 struct buffer_head * bh,
1773 unsigned long offset)
1774{
1775 const char *error_msg = NULL;
1776 const int rlen = le16_to_cpu(de->rec_len);
1777
1778 if (rlen < OCFS2_DIR_REC_LEN(1))
1779 error_msg = "rec_len is smaller than minimal";
1780 else if (rlen % 4 != 0)
1781 error_msg = "rec_len % 4 != 0";
1782 else if (rlen < OCFS2_DIR_REC_LEN(de->name_len))
1783 error_msg = "rec_len is too small for name_len";
1784 else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
1785 error_msg = "directory entry across blocks";
1786
1787 if (error_msg != NULL)
1788 mlog(ML_ERROR, "bad entry in directory #%llu: %s - "
1789 "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n",
1790 (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg,
1791 offset, (unsigned long long)le64_to_cpu(de->inode), rlen,
1792 de->name_len);
1793 return error_msg == NULL ? 1 : 0;
1794}
1795
1796/* we don't always have a dentry for what we want to add, so people
1797 * like orphan dir can call this instead.
1798 *
1799 * If you pass me insert_bh, I'll skip the search of the other dir
1800 * blocks and put the record in there.
1801 */
1802static int __ocfs2_add_entry(handle_t *handle,
1803 struct inode *dir,
1804 const char *name, int namelen,
1805 struct inode *inode, u64 blkno,
1806 struct buffer_head *parent_fe_bh,
1807 struct buffer_head *insert_bh)
1808{
1809 unsigned long offset;
1810 unsigned short rec_len;
1811 struct ocfs2_dir_entry *de, *de1;
1812 struct super_block *sb;
1813 int retval, status;
1814
1815 mlog_entry_void();
1816
1817 sb = dir->i_sb;
1818
1819 if (!namelen)
1820 return -EINVAL;
1821
1822 rec_len = OCFS2_DIR_REC_LEN(namelen);
1823 offset = 0;
1824 de = (struct ocfs2_dir_entry *) insert_bh->b_data;
1825 while (1) {
1826 BUG_ON((char *)de >= sb->s_blocksize + insert_bh->b_data);
1827 /* These checks should've already been passed by the
1828 * prepare function, but I guess we can leave them
1829 * here anyway. */
1830 if (!ocfs2_check_dir_entry(dir, de, insert_bh, offset)) {
1831 retval = -ENOENT;
1832 goto bail;
1833 }
1834 if (ocfs2_match(namelen, name, de)) {
1835 retval = -EEXIST;
1836 goto bail;
1837 }
1838 if (((le64_to_cpu(de->inode) == 0) &&
1839 (le16_to_cpu(de->rec_len) >= rec_len)) ||
1840 (le16_to_cpu(de->rec_len) >=
1841 (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) {
1842 dir->i_mtime = dir->i_ctime = CURRENT_TIME;
1843 retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
1844 if (retval < 0) {
1845 mlog_errno(retval);
1846 goto bail;
1847 }
1848
1849 status = ocfs2_journal_access(handle, dir, insert_bh,
1850 OCFS2_JOURNAL_ACCESS_WRITE);
1851 /* By now the buffer is marked for journaling */
1852 offset += le16_to_cpu(de->rec_len);
1853 if (le64_to_cpu(de->inode)) {
1854 de1 = (struct ocfs2_dir_entry *)((char *) de +
1855 OCFS2_DIR_REC_LEN(de->name_len));
1856 de1->rec_len =
1857 cpu_to_le16(le16_to_cpu(de->rec_len) -
1858 OCFS2_DIR_REC_LEN(de->name_len));
1859 de->rec_len = cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
1860 de = de1;
1861 }
1862 de->file_type = OCFS2_FT_UNKNOWN;
1863 if (blkno) {
1864 de->inode = cpu_to_le64(blkno);
1865 ocfs2_set_de_type(de, inode->i_mode);
1866 } else
1867 de->inode = 0;
1868 de->name_len = namelen;
1869 memcpy(de->name, name, namelen);
1870
1871 dir->i_version++;
1872 status = ocfs2_journal_dirty(handle, insert_bh);
1873 retval = 0;
1874 goto bail;
1875 }
1876 offset += le16_to_cpu(de->rec_len);
1877 de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
1878 }
1879
1880 /* when you think about it, the assert above should prevent us
1881 * from ever getting here. */
1882 retval = -ENOSPC;
1883bail:
1884
1885 mlog_exit(retval);
1886 return retval;
1887}
1888
1889
1890/*
1891 * ocfs2_delete_entry deletes a directory entry by merging it with the
1892 * previous entry
1893 */
1894static int ocfs2_delete_entry(handle_t *handle,
1895 struct inode *dir,
1896 struct ocfs2_dir_entry *de_del,
1897 struct buffer_head *bh)
1898{
1899 struct ocfs2_dir_entry *de, *pde;
1900 int i, status = -ENOENT;
1901
1902 mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh);
1903
1904 i = 0;
1905 pde = NULL;
1906 de = (struct ocfs2_dir_entry *) bh->b_data;
1907 while (i < bh->b_size) {
1908 if (!ocfs2_check_dir_entry(dir, de, bh, i)) {
1909 status = -EIO;
1910 mlog_errno(status);
1911 goto bail;
1912 }
1913 if (de == de_del) {
1914 status = ocfs2_journal_access(handle, dir, bh,
1915 OCFS2_JOURNAL_ACCESS_WRITE);
1916 if (status < 0) {
1917 status = -EIO;
1918 mlog_errno(status);
1919 goto bail;
1920 }
1921 if (pde)
1922 pde->rec_len =
1923 cpu_to_le16(le16_to_cpu(pde->rec_len) +
1924 le16_to_cpu(de->rec_len));
1925 else
1926 de->inode = 0;
1927 dir->i_version++;
1928 status = ocfs2_journal_dirty(handle, bh);
1929 goto bail;
1930 }
1931 i += le16_to_cpu(de->rec_len);
1932 pde = de;
1933 de = (struct ocfs2_dir_entry *)((char *)de + le16_to_cpu(de->rec_len));
1934 }
1935bail:
1936 mlog_exit(status);
1937 return status;
1938}
1939
1940/*
1941 * Returns 0 if not found, -1 on failure, and 1 on success
1942 */
1943static int inline ocfs2_search_dirblock(struct buffer_head *bh,
1944 struct inode *dir,
1945 const char *name, int namelen,
1946 unsigned long offset,
1947 struct ocfs2_dir_entry **res_dir)
1948{
1949 struct ocfs2_dir_entry *de;
1950 char *dlimit, *de_buf;
1951 int de_len;
1952 int ret = 0;
1953
1954 mlog_entry_void();
1955
1956 de_buf = bh->b_data;
1957 dlimit = de_buf + dir->i_sb->s_blocksize;
1958
1959 while (de_buf < dlimit) {
1960 /* this code is executed quadratically often */
1961 /* do minimal checking `by hand' */
1962
1963 de = (struct ocfs2_dir_entry *) de_buf;
1964
1965 if (de_buf + namelen <= dlimit &&
1966 ocfs2_match(namelen, name, de)) {
1967 /* found a match - just to be sure, do a full check */
1968 if (!ocfs2_check_dir_entry(dir, de, bh, offset)) {
1969 ret = -1;
1970 goto bail;
1971 }
1972 *res_dir = de;
1973 ret = 1;
1974 goto bail;
1975 }
1976
1977 /* prevent looping on a bad block */
1978 de_len = le16_to_cpu(de->rec_len);
1979 if (de_len <= 0) {
1980 ret = -1;
1981 goto bail;
1982 }
1983
1984 de_buf += de_len;
1985 offset += de_len;
1986 }
1987
1988bail:
1989 mlog_exit(ret);
1990 return ret;
1991}
1992
1993struct buffer_head *ocfs2_find_entry(const char *name, int namelen,
1994 struct inode *dir,
1995 struct ocfs2_dir_entry **res_dir)
1996{
1997 struct super_block *sb;
1998 struct buffer_head *bh_use[NAMEI_RA_SIZE];
1999 struct buffer_head *bh, *ret = NULL;
2000 unsigned long start, block, b;
2001 int ra_max = 0; /* Number of bh's in the readahead
2002 buffer, bh_use[] */
2003 int ra_ptr = 0; /* Current index into readahead
2004 buffer */
2005 int num = 0;
2006 int nblocks, i, err;
2007
2008 mlog_entry_void();
2009
2010 *res_dir = NULL;
2011 sb = dir->i_sb;
2012
2013 nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
2014 start = OCFS2_I(dir)->ip_dir_start_lookup;
2015 if (start >= nblocks)
2016 start = 0;
2017 block = start;
2018
2019restart:
2020 do {
2021 /*
2022 * We deal with the read-ahead logic here.
2023 */
2024 if (ra_ptr >= ra_max) {
2025 /* Refill the readahead buffer */
2026 ra_ptr = 0;
2027 b = block;
2028 for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
2029 /*
2030 * Terminate if we reach the end of the
2031 * directory and must wrap, or if our
2032 * search has finished at this block.
2033 */
2034 if (b >= nblocks || (num && block == start)) {
2035 bh_use[ra_max] = NULL;
2036 break;
2037 }
2038 num++;
2039
2040 bh = ocfs2_bread(dir, b++, &err, 1);
2041 bh_use[ra_max] = bh;
2042 }
2043 }
2044 if ((bh = bh_use[ra_ptr++]) == NULL)
2045 goto next;
2046 wait_on_buffer(bh);
2047 if (!buffer_uptodate(bh)) {
2048 /* read error, skip block & hope for the best */
2049 ocfs2_error(dir->i_sb, "reading directory %llu, "
2050 "offset %lu\n",
2051 (unsigned long long)OCFS2_I(dir)->ip_blkno,
2052 block);
2053 brelse(bh);
2054 goto next;
2055 }
2056 i = ocfs2_search_dirblock(bh, dir, name, namelen,
2057 block << sb->s_blocksize_bits,
2058 res_dir);
2059 if (i == 1) {
2060 OCFS2_I(dir)->ip_dir_start_lookup = block;
2061 ret = bh;
2062 goto cleanup_and_exit;
2063 } else {
2064 brelse(bh);
2065 if (i < 0)
2066 goto cleanup_and_exit;
2067 }
2068 next:
2069 if (++block >= nblocks)
2070 block = 0;
2071 } while (block != start);
2072
2073 /*
2074 * If the directory has grown while we were searching, then
2075 * search the last part of the directory before giving up.
2076 */
2077 block = nblocks;
2078 nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
2079 if (block < nblocks) {
2080 start = 0;
2081 goto restart;
2082 }
2083
2084cleanup_and_exit:
2085 /* Clean up the read-ahead blocks */
2086 for (; ra_ptr < ra_max; ra_ptr++)
2087 brelse(bh_use[ra_ptr]);
2088
2089 mlog_exit_ptr(ret);
2090 return ret;
2091}
2092
2093static int ocfs2_blkno_stringify(u64 blkno, char *name) 1660static int ocfs2_blkno_stringify(u64 blkno, char *name)
2094{ 1661{
2095 int status, namelen; 1662 int status, namelen;
diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h
index 0975c7b7212..688aef64c87 100644
--- a/fs/ocfs2/namei.h
+++ b/fs/ocfs2/namei.h
@@ -30,29 +30,10 @@ extern const struct inode_operations ocfs2_dir_iops;
30 30
31struct dentry *ocfs2_get_parent(struct dentry *child); 31struct dentry *ocfs2_get_parent(struct dentry *child);
32 32
33int ocfs2_check_dir_entry (struct inode *dir,
34 struct ocfs2_dir_entry *de,
35 struct buffer_head *bh,
36 unsigned long offset);
37struct buffer_head *ocfs2_find_entry(const char *name,
38 int namelen,
39 struct inode *dir,
40 struct ocfs2_dir_entry **res_dir);
41int ocfs2_orphan_del(struct ocfs2_super *osb, 33int ocfs2_orphan_del(struct ocfs2_super *osb,
42 handle_t *handle, 34 handle_t *handle,
43 struct inode *orphan_dir_inode, 35 struct inode *orphan_dir_inode,
44 struct inode *inode, 36 struct inode *inode,
45 struct buffer_head *orphan_dir_bh); 37 struct buffer_head *orphan_dir_bh);
46 38
47static inline int ocfs2_match(int len,
48 const char * const name,
49 struct ocfs2_dir_entry *de)
50{
51 if (len != de->name_len)
52 return 0;
53 if (!de->inode)
54 return 0;
55 return !memcmp(name, de->name, len);
56}
57
58#endif /* OCFS2_NAMEI_H */ 39#endif /* OCFS2_NAMEI_H */