Line data Source code
1 : /*
2 : * linux/fs/ext2/dir.c
3 : *
4 : * Copyright (C) 1992, 1993, 1994, 1995
5 : * Remy Card (card@masi.ibp.fr)
6 : * Laboratoire MASI - Institut Blaise Pascal
7 : * Universite Pierre et Marie Curie (Paris VI)
8 : *
9 : * from
10 : *
11 : * linux/fs/minix/dir.c
12 : *
13 : * Copyright (C) 1991, 1992 Linus Torvalds
14 : *
15 : * ext2 directory handling functions
16 : *
17 : * Big-endian to little-endian byte-swapping/bitmaps by
18 : * David S. Miller (davem@caip.rutgers.edu), 1995
19 : *
20 : * All code that works with directory layout had been switched to pagecache
21 : * and moved here. AV
22 : */
23 :
24 : #include "ext2.h"
25 : #include <linux/buffer_head.h>
26 : #include <linux/pagemap.h>
27 : #include <linux/swap.h>
28 :
29 1 : typedef struct ext2_dir_entry_2 ext2_dirent;
30 :
31 : static inline unsigned ext2_rec_len_from_disk(__le16 dlen)
32 : {
33 364 : unsigned len = le16_to_cpu(dlen);
34 :
35 364 : if (len == EXT2_MAX_REC_LEN)
36 182 : return 1 << 16;
37 182 : return len;
38 : }
39 :
40 : static inline __le16 ext2_rec_len_to_disk(unsigned len)
41 : {
42 312 : if (len == (1 << 16))
43 104 : return cpu_to_le16(EXT2_MAX_REC_LEN);
44 : else
45 624 : BUG_ON(len > (1 << 16));
46 104 : return cpu_to_le16(len);
47 : }
48 :
49 : /*
50 : * ext2 uses block-sized chunks. Arguably, sector-sized ones would be
51 : * more robust, but we have what we have
52 : */
53 : static inline unsigned ext2_chunk_size(struct inode *inode)
54 : {
55 238 : return inode->i_sb->s_blocksize;
56 : }
57 :
58 : static inline void ext2_put_page(struct page *page)
59 : {
60 696 : kunmap(page);
61 348 : page_cache_release(page);
62 348 : }
63 :
64 : static inline unsigned long dir_pages(struct inode *inode)
65 : {
66 140 : return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
67 : }
68 :
69 : /*
70 : * Return the offset into page `page_nr' of the last valid
71 : * byte in that page, plus one.
72 : */
73 : static unsigned
74 : ext2_last_byte(struct inode *inode, unsigned long page_nr)
75 : {
76 213 : unsigned last_byte = inode->i_size;
77 :
78 71 : last_byte -= page_nr << PAGE_CACHE_SHIFT;
79 142 : if (last_byte > PAGE_CACHE_SIZE)
80 71 : last_byte = PAGE_CACHE_SIZE;
81 71 : return last_byte;
82 : }
83 :
84 : static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len)
85 : {
86 128 : struct address_space *mapping = page->mapping;
87 128 : struct inode *dir = mapping->host;
88 128 : int err = 0;
89 :
90 64 : dir->i_version++;
91 64 : block_write_end(NULL, mapping, pos, len, len, page, NULL);
92 :
93 128 : if (pos+len > dir->i_size) {
94 128 : i_size_write(dir, pos+len);
95 128 : mark_inode_dirty(dir);
96 : }
97 :
98 512 : if (IS_DIRSYNC(dir)) {
99 128 : err = write_one_page(page, 1);
100 256 : if (!err)
101 256 : err = ext2_sync_inode(dir);
102 : } else {
103 128 : unlock_page(page);
104 : }
105 :
106 192 : return err;
107 : }
108 :
109 : static void ext2_check_page(struct page *page, int quiet)
110 : {
111 148 : struct inode *dir = page->mapping->host;
112 148 : struct super_block *sb = dir->i_sb;
113 296 : unsigned chunk_size = ext2_chunk_size(dir);
114 296 : char *kaddr = page_address(page);
115 296 : u32 max_inumber = le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count);
116 74 : unsigned offs, rec_len;
117 148 : unsigned limit = PAGE_CACHE_SIZE;
118 74 : ext2_dirent *p;
119 74 : char *error;
120 74 :
121 222 : if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) {
122 222 : limit = dir->i_size & ~PAGE_CACHE_MASK;
123 222 : if (limit & (chunk_size - 1))
124 74 : goto Ebadsize;
125 148 : if (!limit)
126 74 : goto out;
127 : }
128 370 : for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) {
129 222 : p = (ext2_dirent *)(kaddr + offs);
130 296 : rec_len = ext2_rec_len_from_disk(p->rec_len);
131 :
132 148 : if (rec_len < EXT2_DIR_REC_LEN(1))
133 74 : goto Eshort;
134 148 : if (rec_len & 3)
135 74 : goto Ealign;
136 222 : if (rec_len < EXT2_DIR_REC_LEN(p->name_len))
137 74 : goto Enamelen;
138 148 : if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1))
139 74 : goto Espan;
140 148 : if (le32_to_cpu(p->inode) > max_inumber)
141 74 : goto Einumber;
142 : }
143 148 : if (offs != limit)
144 74 : goto Eend;
145 : out:
146 296 : SetPageChecked(page);
147 74 : return;
148 148 :
149 : /* Too bad, we had an error */
150 :
151 : Ebadsize:
152 148 : if (!quiet)
153 222 : ext2_error(sb, __func__,
154 : "size of directory #%lu is not a multiple "
155 : "of chunk size", dir->i_ino);
156 148 : goto fail;
157 74 : Eshort:
158 74 : error = "rec_len is smaller than minimal";
159 74 : goto bad_entry;
160 74 : Ealign:
161 74 : error = "unaligned directory entry";
162 74 : goto bad_entry;
163 74 : Enamelen:
164 74 : error = "rec_len is too small for name_len";
165 74 : goto bad_entry;
166 74 : Espan:
167 74 : error = "directory entry across blocks";
168 74 : goto bad_entry;
169 74 : Einumber:
170 74 : error = "inode out of bounds";
171 74 : bad_entry:
172 148 : if (!quiet)
173 370 : ext2_error(sb, __func__, "bad entry in directory #%lu: : %s - "
174 : "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
175 : dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
176 : (unsigned long) le32_to_cpu(p->inode),
177 : rec_len, p->name_len);
178 148 : goto fail;
179 74 : Eend:
180 148 : if (!quiet) {
181 74 : p = (ext2_dirent *)(kaddr + offs);
182 296 : ext2_error(sb, "ext2_check_page",
183 : "entry in directory #%lu spans the page boundary"
184 : "offset=%lu, inode=%lu",
185 : dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
186 : (unsigned long) le32_to_cpu(p->inode));
187 : }
188 : fail:
189 1036 : SetPageChecked(page);
190 148 : SetPageError(page);
191 74 : }
192 :
193 : static struct page * ext2_get_page(struct inode *dir, unsigned long n,
194 : int quiet)
195 74 : {
196 148 : struct address_space *mapping = dir->i_mapping;
197 296 : struct page *page = read_mapping_page(mapping, n, NULL);
198 370 : if (!IS_ERR(page)) {
199 222 : kmap(page);
200 370 : if (!PageChecked(page))
201 296 : ext2_check_page(page, quiet);
202 444 : if (PageError(page))
203 74 : goto fail;
204 : }
205 148 : return page;
206 74 :
207 : fail:
208 148 : ext2_put_page(page);
209 222 : return ERR_PTR(-EIO);
210 : }
211 :
212 : /*
213 : * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
214 : *
215 : * len <= EXT2_NAME_LEN and de != NULL are guaranteed by caller.
216 : */
217 : static inline int ext2_match (int len, const char * const name,
218 : struct ext2_dir_entry_2 * de)
219 57 : {
220 171 : if (len != de->name_len)
221 57 : return 0;
222 114 : if (!de->inode)
223 57 : return 0;
224 114 : return !memcmp(name, de->name, len);
225 : }
226 :
227 : /*
228 : * p is at least 6 bytes before the end of page
229 : */
230 : static inline ext2_dirent *ext2_next_entry(ext2_dirent *p)
231 : {
232 295 : return (ext2_dirent *)((char *)p +
233 : ext2_rec_len_from_disk(p->rec_len));
234 : }
235 :
236 : static inline unsigned
237 : ext2_validate_entry(char *base, unsigned offset, unsigned mask)
238 : {
239 1 : ext2_dirent *de = (ext2_dirent*)(base + offset);
240 2 : ext2_dirent *p = (ext2_dirent*)(base + (offset&mask));
241 4 : while ((char*)p < (char*)de) {
242 4 : if (p->rec_len == 0)
243 2 : break;
244 2 : p = ext2_next_entry(p);
245 : }
246 2 : return (char *)p - base;
247 1 : }
248 :
249 1 : static unsigned char ext2_filetype_table[EXT2_FT_MAX] = {
250 : [EXT2_FT_UNKNOWN] = DT_UNKNOWN,
251 : [EXT2_FT_REG_FILE] = DT_REG,
252 : [EXT2_FT_DIR] = DT_DIR,
253 : [EXT2_FT_CHRDEV] = DT_CHR,
254 : [EXT2_FT_BLKDEV] = DT_BLK,
255 : [EXT2_FT_FIFO] = DT_FIFO,
256 : [EXT2_FT_SOCK] = DT_SOCK,
257 : [EXT2_FT_SYMLINK] = DT_LNK,
258 : };
259 :
260 : #define S_SHIFT 12
261 1 : static unsigned char ext2_type_by_mode[S_IFMT >> S_SHIFT] = {
262 : [S_IFREG >> S_SHIFT] = EXT2_FT_REG_FILE,
263 : [S_IFDIR >> S_SHIFT] = EXT2_FT_DIR,
264 : [S_IFCHR >> S_SHIFT] = EXT2_FT_CHRDEV,
265 : [S_IFBLK >> S_SHIFT] = EXT2_FT_BLKDEV,
266 : [S_IFIFO >> S_SHIFT] = EXT2_FT_FIFO,
267 : [S_IFSOCK >> S_SHIFT] = EXT2_FT_SOCK,
268 : [S_IFLNK >> S_SHIFT] = EXT2_FT_SYMLINK,
269 : };
270 :
271 : static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode)
272 : {
273 216 : mode_t mode = inode->i_mode;
274 360 : if (EXT2_HAS_INCOMPAT_FEATURE(inode->i_sb, EXT2_FEATURE_INCOMPAT_FILETYPE))
275 72 : de->file_type = ext2_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
276 : else
277 72 : de->file_type = 0;
278 72 : }
279 :
280 : static int
281 : ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
282 : {
283 1 : loff_t pos = filp->f_pos;
284 1 : struct inode *inode = filp->f_path.dentry->d_inode;
285 1 : struct super_block *sb = inode->i_sb;
286 2 : unsigned int offset = pos & ~PAGE_CACHE_MASK;
287 2 : unsigned long n = pos >> PAGE_CACHE_SHIFT;
288 4 : unsigned long npages = dir_pages(inode);
289 4 : unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
290 2 : unsigned char *types = NULL;
291 2 : int need_revalidate = filp->f_version != inode->i_version;
292 1 :
293 3 : if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
294 2 : return 0;
295 1 :
296 5 : if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE))
297 2 : types = ext2_filetype_table;
298 1 :
299 6 : for ( ; n < npages; n++, offset = 0) {
300 2 : char *kaddr, *limit;
301 3 : ext2_dirent *de;
302 6 : struct page *page = ext2_get_page(inode, n, 0);
303 1 :
304 5 : if (IS_ERR(page)) {
305 4 : ext2_error(sb, __func__,
306 1 : "bad page in #%lu",
307 1 : inode->i_ino);
308 3 : filp->f_pos += PAGE_CACHE_SIZE - offset;
309 4 : return PTR_ERR(page);
310 1 : }
311 3 : kaddr = page_address(page);
312 4 : if (unlikely(need_revalidate)) {
313 2 : if (offset) {
314 2 : offset = ext2_validate_entry(kaddr, offset, chunk_mask);
315 1 : filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset;
316 : }
317 2 : filp->f_version = inode->i_version;
318 2 : need_revalidate = 0;
319 : }
320 2 : de = (ext2_dirent *)(kaddr+offset);
321 5 : limit = kaddr + ext2_last_byte(inode, n) - EXT2_DIR_REC_LEN(1);
322 5 : for ( ;(char*)de <= limit; de = ext2_next_entry(de)) {
323 4 : if (de->rec_len == 0) {
324 5 : ext2_error(sb, __func__,
325 : "zero-length directory entry");
326 2 : ext2_put_page(page);
327 1 : return -EIO;
328 : }
329 2 : if (de->inode) {
330 : int over;
331 1 : unsigned char d_type = DT_UNKNOWN;
332 :
333 5 : if (types && de->file_type < EXT2_FT_MAX)
334 2 : d_type = types[de->file_type];
335 :
336 1 : offset = (char *)de - kaddr;
337 3 : over = filldir(dirent, de->name, de->name_len,
338 : (n<<PAGE_CACHE_SHIFT) | offset,
339 : le32_to_cpu(de->inode), d_type);
340 2 : if (over) {
341 2 : ext2_put_page(page);
342 1 : return 0;
343 : }
344 : }
345 4 : filp->f_pos += ext2_rec_len_from_disk(de->rec_len);
346 : }
347 2 : ext2_put_page(page);
348 : }
349 1 : return 0;
350 : }
351 :
352 : /*
353 : * ext2_find_entry()
354 : *
355 : * finds an entry in the specified directory with the wanted name. It
356 : * returns the page in which the entry was found (as a parameter - res_page),
357 : * and the entry itself. Page is returned mapped and unlocked.
358 : * Entry is guaranteed to be valid.
359 : */
360 : struct ext2_dir_entry_2 *ext2_find_entry (struct inode * dir,
361 : struct qstr *child, struct page ** res_page)
362 : {
363 87 : const char *name = child->name;
364 87 : int namelen = child->len;
365 58 : unsigned reclen = EXT2_DIR_REC_LEN(namelen);
366 29 : unsigned long start, n;
367 116 : unsigned long npages = dir_pages(dir);
368 58 : struct page *page = NULL;
369 116 : struct ext2_inode_info *ei = EXT2_I(dir);
370 29 : ext2_dirent * de;
371 58 : int dir_has_error = 0;
372 29 :
373 87 : if (npages == 0)
374 58 : goto out;
375 29 :
376 29 : /* OFFSET_CACHE */
377 58 : *res_page = NULL;
378 29 :
379 87 : start = ei->i_dir_start_lookup;
380 87 : if (start >= npages)
381 29 : start = 0;
382 29 : n = start;
383 29 : do {
384 : char *kaddr;
385 116 : page = ext2_get_page(dir, n, dir_has_error);
386 116 : if (!IS_ERR(page)) {
387 87 : kaddr = page_address(page);
388 29 : de = (ext2_dirent *) kaddr;
389 87 : kaddr += ext2_last_byte(dir, n) - reclen;
390 87 : while ((char *) de <= kaddr) {
391 116 : if (de->rec_len == 0) {
392 116 : ext2_error(dir->i_sb, __func__,
393 : "zero-length directory entry");
394 58 : ext2_put_page(page);
395 29 : goto out;
396 : }
397 116 : if (ext2_match (namelen, name, de))
398 29 : goto found;
399 58 : de = ext2_next_entry(de);
400 : }
401 87 : ext2_put_page(page);
402 : } else
403 29 : dir_has_error = 1;
404 :
405 174 : if (++n >= npages)
406 58 : n = 0;
407 : /* next page is past the blocks we've got */
408 174 : if (unlikely(n > (dir->i_blocks >> (PAGE_CACHE_SHIFT - 9)))) {
409 116 : ext2_error(dir->i_sb, __func__,
410 : "dir %lu size %lld exceeds block count %llu",
411 : dir->i_ino, dir->i_size,
412 : (unsigned long long)dir->i_blocks);
413 29 : goto out;
414 : }
415 58 : } while (n != start);
416 : out:
417 145 : return NULL;
418 29 :
419 : found:
420 29 : *res_page = page;
421 29 : ei->i_dir_start_lookup = n;
422 58 : return de;
423 : }
424 :
425 : struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
426 : {
427 24 : struct page *page = ext2_get_page(dir, 0, 0);
428 8 : ext2_dirent *de = NULL;
429 4 :
430 20 : if (!IS_ERR(page)) {
431 20 : de = ext2_next_entry((ext2_dirent *) page_address(page));
432 4 : *p = page;
433 : }
434 8 : return de;
435 : }
436 :
437 : ino_t ext2_inode_by_name(struct inode *dir, struct qstr *child)
438 : {
439 10 : ino_t res = 0;
440 5 : struct ext2_dir_entry_2 *de;
441 5 : struct page *page;
442 :
443 30 : de = ext2_find_entry (dir, child, &page);
444 10 : if (de) {
445 10 : res = le32_to_cpu(de->inode);
446 10 : ext2_put_page(page);
447 : }
448 10 : return res;
449 : }
450 :
451 : /* Releases the page */
452 : void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
453 : struct page *page, struct inode *inode, int update_times)
454 : {
455 48 : loff_t pos = page_offset(page) +
456 8 : (char *) de - (char *) page_address(page);
457 40 : unsigned len = ext2_rec_len_from_disk(de->rec_len);
458 8 : int err;
459 8 :
460 24 : lock_page(page);
461 24 : err = __ext2_write_begin(NULL, page->mapping, pos, len,
462 8 : AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
463 56 : BUG_ON(err);
464 24 : de->inode = cpu_to_le32(inode->i_ino);
465 24 : ext2_set_de_type(de, inode);
466 32 : err = ext2_commit_chunk(page, pos, len);
467 16 : ext2_put_page(page);
468 16 : if (update_times)
469 48 : dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
470 24 : EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
471 16 : mark_inode_dirty(dir);
472 8 : }
473 :
474 : /*
475 : * Parent is locked.
476 : */
477 : int ext2_add_link (struct dentry *dentry, struct inode *inode)
478 : {
479 56 : struct inode *dir = dentry->d_parent->d_inode;
480 56 : const char *name = dentry->d_name.name;
481 56 : int namelen = dentry->d_name.len;
482 112 : unsigned chunk_size = ext2_chunk_size(dir);
483 56 : unsigned reclen = EXT2_DIR_REC_LEN(namelen);
484 28 : unsigned short rec_len, name_len;
485 56 : struct page *page = NULL;
486 28 : ext2_dirent * de;
487 112 : unsigned long npages = dir_pages(dir);
488 28 : unsigned long n;
489 28 : char *kaddr;
490 28 : loff_t pos;
491 28 : int err;
492 28 :
493 28 : /*
494 28 : * We take care of directory expansion in the same loop.
495 28 : * This code plays outside i_size, so it locks the page
496 28 : * to protect that region.
497 28 : */
498 168 : for (n = 0; n <= npages; n++) {
499 56 : char *dir_end;
500 84 :
501 140 : page = ext2_get_page(dir, n, 0);
502 112 : err = PTR_ERR(page);
503 140 : if (IS_ERR(page))
504 56 : goto out;
505 84 : lock_page(page);
506 112 : kaddr = page_address(page);
507 112 : dir_end = kaddr + ext2_last_byte(dir, n);
508 56 : de = (ext2_dirent *)kaddr;
509 28 : kaddr += PAGE_CACHE_SIZE - reclen;
510 84 : while ((char *)de <= kaddr) {
511 84 : if ((char *)de == dir_end) {
512 28 : /* We hit i_size */
513 28 : name_len = 0;
514 28 : rec_len = chunk_size;
515 84 : de->rec_len = ext2_rec_len_to_disk(chunk_size);
516 28 : de->inode = 0;
517 28 : goto got_it;
518 : }
519 84 : if (de->rec_len == 0) {
520 84 : ext2_error(dir->i_sb, __func__,
521 : "zero-length directory entry");
522 28 : err = -EIO;
523 28 : goto out_unlock;
524 : }
525 28 : err = -EEXIST;
526 112 : if (ext2_match (namelen, name, de))
527 28 : goto out_unlock;
528 56 : name_len = EXT2_DIR_REC_LEN(de->name_len);
529 112 : rec_len = ext2_rec_len_from_disk(de->rec_len);
530 112 : if (!de->inode && rec_len >= reclen)
531 28 : goto got_it;
532 56 : if (rec_len >= name_len + reclen)
533 28 : goto got_it;
534 28 : de = (ext2_dirent *) ((char *) de + rec_len);
535 28 : }
536 28 : unlock_page(page);
537 56 : ext2_put_page(page);
538 : }
539 56 : BUG();
540 28 : return -EINVAL;
541 56 :
542 : got_it:
543 196 : pos = page_offset(page) +
544 : (char*)de - (char*)page_address(page);
545 56 : err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0,
546 : &page, NULL);
547 56 : if (err)
548 28 : goto out_unlock;
549 56 : if (de->inode) {
550 28 : ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len);
551 84 : de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len);
552 84 : de->rec_len = ext2_rec_len_to_disk(name_len);
553 28 : de = de1;
554 : }
555 56 : de->name_len = namelen;
556 56 : memcpy(de->name, name, namelen);
557 112 : de->inode = cpu_to_le32(inode->i_ino);
558 112 : ext2_set_de_type (de, inode);
559 112 : err = ext2_commit_chunk(page, pos, rec_len);
560 168 : dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
561 84 : EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
562 56 : mark_inode_dirty(dir);
563 : /* OFFSET_CACHE */
564 28 : out_put:
565 224 : ext2_put_page(page);
566 : out:
567 84 : return err;
568 84 : out_unlock:
569 84 : unlock_page(page);
570 84 : goto out_put;
571 : }
572 :
573 : /*
574 : * ext2_delete_entry deletes a directory entry by merging it with the
575 : * previous entry. Page is up-to-date. Releases the page.
576 : */
577 : int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page )
578 : {
579 24 : struct address_space *mapping = page->mapping;
580 24 : struct inode *inode = mapping->host;
581 48 : char *kaddr = page_address(page);
582 48 : unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1);
583 60 : unsigned to = ((char *)dir - kaddr) +
584 12 : ext2_rec_len_from_disk(dir->rec_len);
585 12 : loff_t pos;
586 24 : ext2_dirent * pde = NULL;
587 24 : ext2_dirent * de = (ext2_dirent *) (kaddr + from);
588 12 : int err;
589 12 :
590 48 : while ((char*)de < (char*)dir) {
591 60 : if (de->rec_len == 0) {
592 60 : ext2_error(inode->i_sb, __func__,
593 12 : "zero-length directory entry");
594 24 : err = -EIO;
595 24 : goto out;
596 12 : }
597 24 : pde = de;
598 24 : de = ext2_next_entry(de);
599 : }
600 36 : if (pde)
601 36 : from = (char*)pde - (char*)page_address(page);
602 60 : pos = page_offset(page) + from;
603 24 : lock_page(page);
604 24 : err = __ext2_write_begin(NULL, page->mapping, pos, to - from, 0,
605 : &page, NULL);
606 72 : BUG_ON(err);
607 24 : if (pde)
608 36 : pde->rec_len = ext2_rec_len_to_disk(to - from);
609 24 : dir->inode = 0;
610 96 : err = ext2_commit_chunk(page, pos, to - from);
611 72 : inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
612 36 : EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL;
613 24 : mark_inode_dirty(inode);
614 : out:
615 60 : ext2_put_page(page);
616 12 : return err;
617 : }
618 :
619 : /*
620 : * Set the first fragment of directory.
621 : */
622 : int ext2_make_empty(struct inode *inode, struct inode *parent)
623 : {
624 8 : struct address_space *mapping = inode->i_mapping;
625 16 : struct page *page = grab_cache_page(mapping, 0);
626 16 : unsigned chunk_size = ext2_chunk_size(inode);
627 4 : struct ext2_dir_entry_2 * de;
628 4 : int err;
629 4 : void *kaddr;
630 4 :
631 12 : if (!page)
632 4 : return -ENOMEM;
633 :
634 8 : err = __ext2_write_begin(NULL, page->mapping, 0, chunk_size, 0,
635 : &page, NULL);
636 8 : if (err) {
637 4 : unlock_page(page);
638 4 : goto fail;
639 : }
640 8 : kaddr = kmap_atomic(page, KM_USER0);
641 4 : memset(kaddr, 0, chunk_size);
642 4 : de = (struct ext2_dir_entry_2 *)kaddr;
643 4 : de->name_len = 1;
644 12 : de->rec_len = ext2_rec_len_to_disk(EXT2_DIR_REC_LEN(1));
645 4 : memcpy (de->name, ".\0\0", 4);
646 8 : de->inode = cpu_to_le32(inode->i_ino);
647 8 : ext2_set_de_type (de, inode);
648 :
649 4 : de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1));
650 4 : de->name_len = 2;
651 12 : de->rec_len = ext2_rec_len_to_disk(chunk_size - EXT2_DIR_REC_LEN(1));
652 8 : de->inode = cpu_to_le32(parent->i_ino);
653 4 : memcpy (de->name, "..\0", 4);
654 8 : ext2_set_de_type (de, inode);
655 8 : kunmap_atomic(kaddr, KM_USER0);
656 16 : err = ext2_commit_chunk(page, 0, chunk_size);
657 : fail:
658 12 : page_cache_release(page);
659 8 : return err;
660 : }
661 :
662 : /*
663 : * routine to check that the specified directory is empty (for rmdir)
664 : */
665 : int ext2_empty_dir (struct inode * inode)
666 : {
667 24 : struct page *page = NULL;
668 48 : unsigned long i, npages = dir_pages(inode);
669 24 : int dir_has_error = 0;
670 12 :
671 84 : for (i = 0; i < npages; i++) {
672 48 : char *kaddr;
673 24 : ext2_dirent * de;
674 60 : page = ext2_get_page(inode, i, dir_has_error);
675 12 :
676 60 : if (IS_ERR(page)) {
677 12 : dir_has_error = 1;
678 12 : continue;
679 : }
680 :
681 36 : kaddr = page_address(page);
682 12 : de = (ext2_dirent *)kaddr;
683 36 : kaddr += ext2_last_byte(inode, i) - EXT2_DIR_REC_LEN(1);
684 :
685 36 : while ((char *)de <= kaddr) {
686 48 : if (de->rec_len == 0) {
687 48 : ext2_error(inode->i_sb, __func__,
688 : "zero-length directory entry");
689 12 : printk("kaddr=%p, de=%p\n", kaddr, de);
690 12 : goto not_empty;
691 : }
692 24 : if (de->inode != 0) {
693 : /* check for . and .. */
694 24 : if (de->name[0] != '.')
695 12 : goto not_empty;
696 36 : if (de->name_len > 2)
697 12 : goto not_empty;
698 36 : if (de->name_len < 2) {
699 36 : if (de->inode !=
700 : cpu_to_le32(inode->i_ino))
701 12 : goto not_empty;
702 24 : } else if (de->name[1] != '.')
703 12 : goto not_empty;
704 : }
705 24 : de = ext2_next_entry(de);
706 : }
707 36 : ext2_put_page(page);
708 : }
709 24 : return 1;
710 24 :
711 : not_empty:
712 48 : ext2_put_page(page);
713 12 : return 0;
714 : }
715 :
716 1 : const struct file_operations ext2_dir_operations = {
717 : .llseek = generic_file_llseek,
718 : .read = generic_read_dir,
719 : .readdir = ext2_readdir,
720 : .unlocked_ioctl = ext2_ioctl,
721 : #ifdef CONFIG_COMPAT
722 : .compat_ioctl = ext2_compat_ioctl,
723 : #endif
724 : .fsync = ext2_fsync,
725 : };
|