EXPORT_SYMBOL(d_obtain_alias) rather than EXPORT_SYMBOL_GPL
[safe/jmp/linux-2.6] / fs / ext2 / dir.c
index 8dededd..2999d72 100644 (file)
@@ -41,8 +41,8 @@ static inline __le16 ext2_rec_len_to_disk(unsigned len)
 {
        if (len == (1 << 16))
                return cpu_to_le16(EXT2_MAX_REC_LEN);
-       else if (len > (1 << 16))
-               BUG();
+       else
+               BUG_ON(len > (1 << 16));
        return cpu_to_le16(len);
 }
 
@@ -95,15 +95,18 @@ static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len)
                mark_inode_dirty(dir);
        }
 
-       if (IS_DIRSYNC(dir))
+       if (IS_DIRSYNC(dir)) {
                err = write_one_page(page, 1);
-       else
+               if (!err)
+                       err = ext2_sync_inode(dir);
+       } else {
                unlock_page(page);
+       }
 
        return err;
 }
 
-static void ext2_check_page(struct page *page)
+static void ext2_check_page(struct page *page, int quiet)
 {
        struct inode *dir = page->mapping->host;
        struct super_block *sb = dir->i_sb;
@@ -146,10 +149,10 @@ out:
        /* Too bad, we had an error */
 
 Ebadsize:
-       ext2_error(sb, "ext2_check_page",
-               "size of directory #%lu is not a multiple of chunk size",
-               dir->i_ino
-       );
+       if (!quiet)
+               ext2_error(sb, __func__,
+                       "size of directory #%lu is not a multiple "
+                       "of chunk size", dir->i_ino);
        goto fail;
 Eshort:
        error = "rec_len is smaller than minimal";
@@ -166,32 +169,36 @@ Espan:
 Einumber:
        error = "inode out of bounds";
 bad_entry:
-       ext2_error (sb, "ext2_check_page", "bad entry in directory #%lu: %s - "
-               "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
-               dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
-               (unsigned long) le32_to_cpu(p->inode),
-               rec_len, p->name_len);
+       if (!quiet)
+               ext2_error(sb, __func__, "bad entry in directory #%lu: : %s - "
+                       "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
+                       dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
+                       (unsigned long) le32_to_cpu(p->inode),
+                       rec_len, p->name_len);
        goto fail;
 Eend:
-       p = (ext2_dirent *)(kaddr + offs);
-       ext2_error (sb, "ext2_check_page",
-               "entry in directory #%lu spans the page boundary"
-               "offset=%lu, inode=%lu",
-               dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
-               (unsigned long) le32_to_cpu(p->inode));
+       if (!quiet) {
+               p = (ext2_dirent *)(kaddr + offs);
+               ext2_error(sb, "ext2_check_page",
+                       "entry in directory #%lu spans the page boundary"
+                       "offset=%lu, inode=%lu",
+                       dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
+                       (unsigned long) le32_to_cpu(p->inode));
+       }
 fail:
        SetPageChecked(page);
        SetPageError(page);
 }
 
-static struct page * ext2_get_page(struct inode *dir, unsigned long n)
+static struct page * ext2_get_page(struct inode *dir, unsigned long n,
+                                  int quiet)
 {
        struct address_space *mapping = dir->i_mapping;
        struct page *page = read_mapping_page(mapping, n, NULL);
        if (!IS_ERR(page)) {
                kmap(page);
                if (!PageChecked(page))
-                       ext2_check_page(page);
+                       ext2_check_page(page, quiet);
                if (PageError(page))
                        goto fail;
        }
@@ -292,14 +299,14 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
        for ( ; n < npages; n++, offset = 0) {
                char *kaddr, *limit;
                ext2_dirent *de;
-               struct page *page = ext2_get_page(inode, n);
+               struct page *page = ext2_get_page(inode, n, 0);
 
                if (IS_ERR(page)) {
-                       ext2_error(sb, __FUNCTION__,
+                       ext2_error(sb, __func__,
                                   "bad page in #%lu",
                                   inode->i_ino);
                        filp->f_pos += PAGE_CACHE_SIZE - offset;
-                       return -EIO;
+                       return PTR_ERR(page);
                }
                kaddr = page_address(page);
                if (unlikely(need_revalidate)) {
@@ -314,7 +321,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
                limit = kaddr + ext2_last_byte(inode, n) - EXT2_DIR_REC_LEN(1);
                for ( ;(char*)de <= limit; de = ext2_next_entry(de)) {
                        if (de->rec_len == 0) {
-                               ext2_error(sb, __FUNCTION__,
+                               ext2_error(sb, __func__,
                                        "zero-length directory entry");
                                ext2_put_page(page);
                                return -EIO;
@@ -350,17 +357,18 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
  * (as a parameter - res_dir). Page is returned mapped and unlocked.
  * Entry is guaranteed to be valid.
  */
-struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
-                       struct dentry *dentry, struct page ** res_page)
+struct ext2_dir_entry_2 *ext2_find_entry (struct inode * dir,
+                       struct qstr *child, struct page ** res_page)
 {
-       const char *name = dentry->d_name.name;
-       int namelen = dentry->d_name.len;
+       const char *name = child->name;
+       int namelen = child->len;
        unsigned reclen = EXT2_DIR_REC_LEN(namelen);
        unsigned long start, n;
        unsigned long npages = dir_pages(dir);
        struct page *page = NULL;
        struct ext2_inode_info *ei = EXT2_I(dir);
        ext2_dirent * de;
+       int dir_has_error = 0;
 
        if (npages == 0)
                goto out;
@@ -374,14 +382,14 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
        n = start;
        do {
                char *kaddr;
-               page = ext2_get_page(dir, n);
+               page = ext2_get_page(dir, n, dir_has_error);
                if (!IS_ERR(page)) {
                        kaddr = page_address(page);
                        de = (ext2_dirent *) kaddr;
                        kaddr += ext2_last_byte(dir, n) - reclen;
                        while ((char *) de <= kaddr) {
                                if (de->rec_len == 0) {
-                                       ext2_error(dir->i_sb, __FUNCTION__,
+                                       ext2_error(dir->i_sb, __func__,
                                                "zero-length directory entry");
                                        ext2_put_page(page);
                                        goto out;
@@ -391,12 +399,14 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
                                de = ext2_next_entry(de);
                        }
                        ext2_put_page(page);
-               }
+               } else
+                       dir_has_error = 1;
+
                if (++n >= npages)
                        n = 0;
                /* next page is past the blocks we've got */
                if (unlikely(n > (dir->i_blocks >> (PAGE_CACHE_SHIFT - 9)))) {
-                       ext2_error(dir->i_sb, __FUNCTION__,
+                       ext2_error(dir->i_sb, __func__,
                                "dir %lu size %lld exceeds block count %llu",
                                dir->i_ino, dir->i_size,
                                (unsigned long long)dir->i_blocks);
@@ -414,7 +424,7 @@ found:
 
 struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
 {
-       struct page *page = ext2_get_page(dir, 0);
+       struct page *page = ext2_get_page(dir, 0, 0);
        ext2_dirent *de = NULL;
 
        if (!IS_ERR(page)) {
@@ -424,13 +434,13 @@ struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
        return de;
 }
 
-ino_t ext2_inode_by_name(struct inode * dir, struct dentry *dentry)
+ino_t ext2_inode_by_name(struct inode *dir, struct qstr *child)
 {
        ino_t res = 0;
-       struct ext2_dir_entry_2 * de;
+       struct ext2_dir_entry_2 *de;
        struct page *page;
        
-       de = ext2_find_entry (dir, dentry, &page);
+       de = ext2_find_entry (dir, child, &page);
        if (de) {
                res = le32_to_cpu(de->inode);
                ext2_put_page(page);
@@ -487,7 +497,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
        for (n = 0; n <= npages; n++) {
                char *dir_end;
 
-               page = ext2_get_page(dir, n);
+               page = ext2_get_page(dir, n, 0);
                err = PTR_ERR(page);
                if (IS_ERR(page))
                        goto out;
@@ -506,7 +516,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
                                goto got_it;
                        }
                        if (de->rec_len == 0) {
-                               ext2_error(dir->i_sb, __FUNCTION__,
+                               ext2_error(dir->i_sb, __func__,
                                        "zero-length directory entry");
                                err = -EIO;
                                goto out_unlock;
@@ -578,7 +588,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page )
 
        while ((char*)de < (char*)dir) {
                if (de->rec_len == 0) {
-                       ext2_error(inode->i_sb, __FUNCTION__,
+                       ext2_error(inode->i_sb, __func__,
                                "zero-length directory entry");
                        err = -EIO;
                        goto out;
@@ -655,14 +665,17 @@ int ext2_empty_dir (struct inode * inode)
 {
        struct page *page = NULL;
        unsigned long i, npages = dir_pages(inode);
+       int dir_has_error = 0;
 
        for (i = 0; i < npages; i++) {
                char *kaddr;
                ext2_dirent * de;
-               page = ext2_get_page(inode, i);
+               page = ext2_get_page(inode, i, dir_has_error);
 
-               if (IS_ERR(page))
+               if (IS_ERR(page)) {
+                       dir_has_error = 1;
                        continue;
+               }
 
                kaddr = page_address(page);
                de = (ext2_dirent *)kaddr;
@@ -670,7 +683,7 @@ int ext2_empty_dir (struct inode * inode)
 
                while ((char *)de <= kaddr) {
                        if (de->rec_len == 0) {
-                               ext2_error(inode->i_sb, __FUNCTION__,
+                               ext2_error(inode->i_sb, __func__,
                                        "zero-length directory entry");
                                printk("kaddr=%p, de=%p\n", kaddr, de);
                                goto not_empty;