]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ext3/namei.c
[PATCH] switch all filesystems over to d_obtain_alias
[linux-2.6-omap-h63xx.git] / fs / ext3 / namei.c
index ec8170adac5397de65b862fa549e27acdc9ab294..880b54400ac09dd6eb11f880040294180b7fbe4c 100644 (file)
@@ -57,10 +57,15 @@ static struct buffer_head *ext3_append(handle_t *handle,
 
        *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
 
-       if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
+       bh = ext3_bread(handle, inode, *block, 1, err);
+       if (bh) {
                inode->i_size += inode->i_sb->s_blocksize;
                EXT3_I(inode)->i_disksize = inode->i_size;
-               ext3_journal_get_write_access(handle,bh);
+               *err = ext3_journal_get_write_access(handle, bh);
+               if (*err) {
+                       brelse(bh);
+                       bh = NULL;
+               }
        }
        return bh;
 }
@@ -176,6 +181,16 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
 static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
                             struct inode *inode);
 
+/*
+ * p is at least 6 bytes before the end of page
+ */
+static inline struct ext3_dir_entry_2 *
+ext3_next_entry(struct ext3_dir_entry_2 *p)
+{
+       return (struct ext3_dir_entry_2 *)((char *)p +
+               ext3_rec_len_from_disk(p->rec_len));
+}
+
 /*
  * Future: use high four bits of block for coalesce-on-delete flags
  * Mask them off for now.
@@ -225,13 +240,13 @@ static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
 {
        unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) -
                EXT3_DIR_REC_LEN(2) - infosize;
-       return 0? 20: entry_space / sizeof(struct dx_entry);
+       return entry_space / sizeof(struct dx_entry);
 }
 
 static inline unsigned dx_node_limit (struct inode *dir)
 {
        unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0);
-       return 0? 22: entry_space / sizeof(struct dx_entry);
+       return entry_space / sizeof(struct dx_entry);
 }
 
 /*
@@ -280,7 +295,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_ent
                        space += EXT3_DIR_REC_LEN(de->name_len);
                        names++;
                }
-               de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
+               de = ext3_next_entry(de);
        }
        printk("(%i)\n", names);
        return (struct stats) { names, space, 1 };
@@ -346,7 +361,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
        if (root->info.hash_version != DX_HASH_TEA &&
            root->info.hash_version != DX_HASH_HALF_MD4 &&
            root->info.hash_version != DX_HASH_LEGACY) {
-               ext3_warning(dir->i_sb, __FUNCTION__,
+               ext3_warning(dir->i_sb, __func__,
                             "Unrecognised inode hash code %d",
                             root->info.hash_version);
                brelse(bh);
@@ -360,7 +375,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
        hash = hinfo->hash;
 
        if (root->info.unused_flags & 1) {
-               ext3_warning(dir->i_sb, __FUNCTION__,
+               ext3_warning(dir->i_sb, __func__,
                             "Unimplemented inode hash flags: %#06x",
                             root->info.unused_flags);
                brelse(bh);
@@ -369,7 +384,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
        }
 
        if ((indirect = root->info.indirect_levels) > 1) {
-               ext3_warning(dir->i_sb, __FUNCTION__,
+               ext3_warning(dir->i_sb, __func__,
                             "Unimplemented inode hash depth: %#06x",
                             root->info.indirect_levels);
                brelse(bh);
@@ -382,7 +397,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 
        if (dx_get_limit(entries) != dx_root_limit(dir,
                                                   root->info.info_length)) {
-               ext3_warning(dir->i_sb, __FUNCTION__,
+               ext3_warning(dir->i_sb, __func__,
                             "dx entry: limit != root limit");
                brelse(bh);
                *err = ERR_BAD_DX_DIR;
@@ -394,7 +409,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
        {
                count = dx_get_count(entries);
                if (!count || count > dx_get_limit(entries)) {
-                       ext3_warning(dir->i_sb, __FUNCTION__,
+                       ext3_warning(dir->i_sb, __func__,
                                     "dx entry: no count or count > limit");
                        brelse(bh);
                        *err = ERR_BAD_DX_DIR;
@@ -439,7 +454,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
                        goto fail2;
                at = entries = ((struct dx_node *) bh->b_data)->entries;
                if (dx_get_limit(entries) != dx_node_limit (dir)) {
-                       ext3_warning(dir->i_sb, __FUNCTION__,
+                       ext3_warning(dir->i_sb, __func__,
                                     "dx entry: limit != node limit");
                        brelse(bh);
                        *err = ERR_BAD_DX_DIR;
@@ -455,7 +470,7 @@ fail2:
        }
 fail:
        if (*err == ERR_BAD_DX_DIR)
-               ext3_warning(dir->i_sb, __FUNCTION__,
+               ext3_warning(dir->i_sb, __func__,
                             "Corrupt dir inode %ld, running e2fsck is "
                             "recommended.", dir->i_ino);
        return NULL;
@@ -546,14 +561,6 @@ static int ext3_htree_next_block(struct inode *dir, __u32 hash,
 }
 
 
-/*
- * p is at least 6 bytes before the end of page
- */
-static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p)
-{
-       return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len));
-}
-
 /*
  * This function fills a red-black tree with information from a
  * directory block.  It returns the number directory entries loaded
@@ -720,7 +727,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
                        cond_resched();
                }
                /* XXX: do we need to check rec_len == 0 case? -Chris */
-               de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
+               de = ext3_next_entry(de);
        }
        return count;
 }
@@ -822,7 +829,7 @@ static inline int search_dirblock(struct buffer_head * bh,
                        return 1;
                }
                /* prevent looping on a bad block */
-               de_len = le16_to_cpu(de->rec_len);
+               de_len = ext3_rec_len_from_disk(de->rec_len);
                if (de_len <= 0)
                        return -1;
                offset += de_len;
@@ -858,14 +865,10 @@ static struct buffer_head * ext3_find_entry (struct dentry *dentry,
        int nblocks, i, err;
        struct inode *dir = dentry->d_parent->d_inode;
        int namelen;
-       const u8 *name;
-       unsigned blocksize;
 
        *res_dir = NULL;
        sb = dir->i_sb;
-       blocksize = sb->s_blocksize;
        namelen = dentry->d_name.len;
-       name = dentry->d_name.name;
        if (namelen > EXT3_NAME_LEN)
                return NULL;
        if (is_dx(dir)) {
@@ -915,7 +918,7 @@ restart:
                wait_on_buffer(bh);
                if (!buffer_uptodate(bh)) {
                        /* read error, skip block & hope for the best */
-                       ext3_error(sb, __FUNCTION__, "reading directory #%lu "
+                       ext3_error(sb, __func__, "reading directory #%lu "
                                   "offset %lu", dir->i_ino, block);
                        brelse(bh);
                        goto next;
@@ -988,26 +991,28 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
                de = (struct ext3_dir_entry_2 *) bh->b_data;
                top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize -
                                       EXT3_DIR_REC_LEN(0));
-               for (; de < top; de = ext3_next_entry(de))
-               if (ext3_match (namelen, name, de)) {
-                       if (!ext3_check_dir_entry("ext3_find_entry",
-                                                 dir, de, bh,
-                                 (block<<EXT3_BLOCK_SIZE_BITS(sb))
-                                         +((char *)de - bh->b_data))) {
-                               brelse (bh);
+               for (; de < top; de = ext3_next_entry(de)) {
+                       int off = (block << EXT3_BLOCK_SIZE_BITS(sb))
+                                 + ((char *) de - bh->b_data);
+
+                       if (!ext3_check_dir_entry(__func__, dir, de, bh, off)) {
+                               brelse(bh);
                                *err = ERR_BAD_DX_DIR;
                                goto errout;
                        }
-                       *res_dir = de;
-                       dx_release (frames);
-                       return bh;
+
+                       if (ext3_match(namelen, name, de)) {
+                               *res_dir = de;
+                               dx_release(frames);
+                               return bh;
+                       }
                }
                brelse (bh);
                /* Check to see if we should continue to search */
                retval = ext3_htree_next_block(dir, hash, frame,
                                               frames, NULL);
                if (retval < 0) {
-                       ext3_warning(sb, __FUNCTION__,
+                       ext3_warning(sb, __func__,
                             "error reading index page in directory #%lu",
                             dir->i_ino);
                        *err = retval;
@@ -1039,17 +1044,11 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
                if (!ext3_valid_inum(dir->i_sb, ino)) {
                        ext3_error(dir->i_sb, "ext3_lookup",
                                   "bad inode number: %lu", ino);
-                       inode = NULL;
-               } else
-                       inode = iget(dir->i_sb, ino);
-
-               if (!inode)
-                       return ERR_PTR(-EACCES);
-
-               if (is_bad_inode(inode)) {
-                       iput(inode);
-                       return ERR_PTR(-ENOENT);
+                       return ERR_PTR(-EIO);
                }
+               inode = ext3_iget(dir->i_sb, ino);
+               if (IS_ERR(inode))
+                       return ERR_CAST(inode);
        }
        return d_splice_alias(inode, dentry);
 }
@@ -1058,8 +1057,6 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
 struct dentry *ext3_get_parent(struct dentry *child)
 {
        unsigned long ino;
-       struct dentry *parent;
-       struct inode *inode;
        struct dentry dotdot;
        struct ext3_dir_entry_2 * de;
        struct buffer_head *bh;
@@ -1069,7 +1066,6 @@ struct dentry *ext3_get_parent(struct dentry *child)
        dotdot.d_parent = child; /* confusing, isn't it! */
 
        bh = ext3_find_entry(&dotdot, &de);
-       inode = NULL;
        if (!bh)
                return ERR_PTR(-ENOENT);
        ino = le32_to_cpu(de->inode);
@@ -1078,24 +1074,10 @@ struct dentry *ext3_get_parent(struct dentry *child)
        if (!ext3_valid_inum(child->d_inode->i_sb, ino)) {
                ext3_error(child->d_inode->i_sb, "ext3_get_parent",
                           "bad inode number: %lu", ino);
-               inode = NULL;
-       } else
-               inode = iget(child->d_inode->i_sb, ino);
-
-       if (!inode)
-               return ERR_PTR(-EACCES);
-
-       if (is_bad_inode(inode)) {
-               iput(inode);
-               return ERR_PTR(-ENOENT);
+               return ERR_PTR(-EIO);
        }
 
-       parent = d_alloc_anon(inode);
-       if (!parent) {
-               iput(inode);
-               parent = ERR_PTR(-ENOMEM);
-       }
-       return parent;
+       return d_obtain_alias(ext3_iget(child->d_inode->i_sb, ino));
 }
 
 #define S_SHIFT 12
@@ -1130,7 +1112,7 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
                rec_len = EXT3_DIR_REC_LEN(de->name_len);
                memcpy (to, de, rec_len);
                ((struct ext3_dir_entry_2 *) to)->rec_len =
-                               cpu_to_le16(rec_len);
+                               ext3_rec_len_to_disk(rec_len);
                de->inode = 0;
                map++;
                to += rec_len;
@@ -1149,13 +1131,12 @@ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
 
        prev = to = de;
        while ((char*)de < base + size) {
-               next = (struct ext3_dir_entry_2 *) ((char *) de +
-                                                   le16_to_cpu(de->rec_len));
+               next = ext3_next_entry(de);
                if (de->inode && de->name_len) {
                        rec_len = EXT3_DIR_REC_LEN(de->name_len);
                        if (de > to)
                                memmove(to, de, rec_len);
-                       to->rec_len = cpu_to_le16(rec_len);
+                       to->rec_len = ext3_rec_len_to_disk(rec_len);
                        prev = to;
                        to = (struct ext3_dir_entry_2 *) (((char *) to) + rec_len);
                }
@@ -1229,8 +1210,8 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        /* Fancy dance to stay within two buffers */
        de2 = dx_move_dirents(data1, data2, map + split, count - split);
        de = dx_pack_dirents(data1,blocksize);
-       de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-       de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
+       de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de);
+       de2->rec_len = ext3_rec_len_to_disk(data2 + blocksize - (char *) de2);
        dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1));
        dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1));
 
@@ -1300,7 +1281,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
                                return -EEXIST;
                        }
                        nlen = EXT3_DIR_REC_LEN(de->name_len);
-                       rlen = le16_to_cpu(de->rec_len);
+                       rlen = ext3_rec_len_from_disk(de->rec_len);
                        if ((de->inode? rlen - nlen: rlen) >= reclen)
                                break;
                        de = (struct ext3_dir_entry_2 *)((char *)de + rlen);
@@ -1319,11 +1300,11 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
 
        /* By now the buffer is marked for journaling */
        nlen = EXT3_DIR_REC_LEN(de->name_len);
-       rlen = le16_to_cpu(de->rec_len);
+       rlen = ext3_rec_len_from_disk(de->rec_len);
        if (de->inode) {
                struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen);
-               de1->rec_len = cpu_to_le16(rlen - nlen);
-               de->rec_len = cpu_to_le16(nlen);
+               de1->rec_len = ext3_rec_len_to_disk(rlen - nlen);
+               de->rec_len = ext3_rec_len_to_disk(nlen);
                de = de1;
        }
        de->file_type = EXT3_FT_UNKNOWN;
@@ -1400,17 +1381,18 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
 
        /* The 0th block becomes the root, move the dirents out */
        fde = &root->dotdot;
-       de = (struct ext3_dir_entry_2 *)((char *)fde + le16_to_cpu(fde->rec_len));
+       de = (struct ext3_dir_entry_2 *)((char *)fde +
+                       ext3_rec_len_from_disk(fde->rec_len));
        len = ((char *) root) + blocksize - (char *) de;
        memcpy (data1, de, len);
        de = (struct ext3_dir_entry_2 *) data1;
        top = data1 + len;
-       while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top)
+       while ((char *)(de2 = ext3_next_entry(de)) < top)
                de = de2;
-       de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+       de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de);
        /* Initialize the root; the dot dirents already exist */
        de = (struct ext3_dir_entry_2 *) (&root->dotdot);
-       de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2));
+       de->rec_len = ext3_rec_len_to_disk(blocksize - EXT3_DIR_REC_LEN(2));
        memset (&root->info, 0, sizeof(root->info));
        root->info.info_length = sizeof(root->info);
        root->info.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version;
@@ -1490,7 +1472,7 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
                return retval;
        de = (struct ext3_dir_entry_2 *) bh->b_data;
        de->inode = 0;
-       de->rec_len = cpu_to_le16(blocksize);
+       de->rec_len = ext3_rec_len_to_disk(blocksize);
        return add_dirent_to_buf(handle, dentry, inode, de, bh);
 }
 
@@ -1543,7 +1525,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
 
                if (levels && (dx_get_count(frames->entries) ==
                               dx_get_limit(frames->entries))) {
-                       ext3_warning(sb, __FUNCTION__,
+                       ext3_warning(sb, __func__,
                                     "Directory index full!");
                        err = -ENOSPC;
                        goto cleanup;
@@ -1553,7 +1535,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
                        goto cleanup;
                node2 = (struct dx_node *)(bh2->b_data);
                entries2 = node2->entries;
-               node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
+               node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize);
                node2->fake.inode = 0;
                BUFFER_TRACE(frame->bh, "get_write_access");
                err = ext3_journal_get_write_access(handle, frame->bh);
@@ -1651,9 +1633,9 @@ static int ext3_delete_entry (handle_t *handle,
                        BUFFER_TRACE(bh, "get_write_access");
                        ext3_journal_get_write_access(handle, bh);
                        if (pde)
-                               pde->rec_len =
-                                       cpu_to_le16(le16_to_cpu(pde->rec_len) +
-                                                   le16_to_cpu(de->rec_len));
+                               pde->rec_len = ext3_rec_len_to_disk(
+                                       ext3_rec_len_from_disk(pde->rec_len) +
+                                       ext3_rec_len_from_disk(de->rec_len));
                        else
                                de->inode = 0;
                        dir->i_version++;
@@ -1661,10 +1643,9 @@ static int ext3_delete_entry (handle_t *handle,
                        ext3_journal_dirty_metadata(handle, bh);
                        return 0;
                }
-               i += le16_to_cpu(de->rec_len);
+               i += ext3_rec_len_from_disk(de->rec_len);
                pde = de;
-               de = (struct ext3_dir_entry_2 *)
-                       ((char *) de + le16_to_cpu(de->rec_len));
+               de = ext3_next_entry(de);
        }
        return -ENOENT;
 }
@@ -1798,13 +1779,13 @@ retry:
        de = (struct ext3_dir_entry_2 *) dir_block->b_data;
        de->inode = cpu_to_le32(inode->i_ino);
        de->name_len = 1;
-       de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(de->name_len));
+       de->rec_len = ext3_rec_len_to_disk(EXT3_DIR_REC_LEN(de->name_len));
        strcpy (de->name, ".");
        ext3_set_de_type(dir->i_sb, de, S_IFDIR);
-       de = (struct ext3_dir_entry_2 *)
-                       ((char *) de + le16_to_cpu(de->rec_len));
+       de = ext3_next_entry(de);
        de->inode = cpu_to_le32(dir->i_ino);
-       de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1));
+       de->rec_len = ext3_rec_len_to_disk(inode->i_sb->s_blocksize -
+                                       EXT3_DIR_REC_LEN(1));
        de->name_len = 2;
        strcpy (de->name, "..");
        ext3_set_de_type(dir->i_sb, de, S_IFDIR);
@@ -1846,18 +1827,17 @@ static int empty_dir (struct inode * inode)
        if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) ||
            !(bh = ext3_bread (NULL, inode, 0, 0, &err))) {
                if (err)
-                       ext3_error(inode->i_sb, __FUNCTION__,
+                       ext3_error(inode->i_sb, __func__,
                                   "error %d reading directory #%lu offset 0",
                                   err, inode->i_ino);
                else
-                       ext3_warning(inode->i_sb, __FUNCTION__,
+                       ext3_warning(inode->i_sb, __func__,
                                     "bad directory (dir #%lu) - no data block",
                                     inode->i_ino);
                return 1;
        }
        de = (struct ext3_dir_entry_2 *) bh->b_data;
-       de1 = (struct ext3_dir_entry_2 *)
-                       ((char *) de + le16_to_cpu(de->rec_len));
+       de1 = ext3_next_entry(de);
        if (le32_to_cpu(de->inode) != inode->i_ino ||
                        !le32_to_cpu(de1->inode) ||
                        strcmp (".", de->name) ||
@@ -1868,9 +1848,9 @@ static int empty_dir (struct inode * inode)
                brelse (bh);
                return 1;
        }
-       offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
-       de = (struct ext3_dir_entry_2 *)
-                       ((char *) de1 + le16_to_cpu(de1->rec_len));
+       offset = ext3_rec_len_from_disk(de->rec_len) +
+                       ext3_rec_len_from_disk(de1->rec_len);
+       de = ext3_next_entry(de1);
        while (offset < inode->i_size ) {
                if (!bh ||
                        (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
@@ -1880,7 +1860,7 @@ static int empty_dir (struct inode * inode)
                                offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err);
                        if (!bh) {
                                if (err)
-                                       ext3_error(sb, __FUNCTION__,
+                                       ext3_error(sb, __func__,
                                                   "error %d reading directory"
                                                   " #%lu offset %lu",
                                                   err, inode->i_ino, offset);
@@ -1899,9 +1879,8 @@ static int empty_dir (struct inode * inode)
                        brelse (bh);
                        return 0;
                }
-               offset += le16_to_cpu(de->rec_len);
-               de = (struct ext3_dir_entry_2 *)
-                               ((char *) de + le16_to_cpu(de->rec_len));
+               offset += ext3_rec_len_from_disk(de->rec_len);
+               de = ext3_next_entry(de);
        }
        brelse (bh);
        return 1;
@@ -2255,8 +2234,7 @@ retry:
 }
 
 #define PARENT_INO(buffer) \
-       ((struct ext3_dir_entry_2 *) ((char *) buffer + \
-       le16_to_cpu(((struct ext3_dir_entry_2 *) buffer)->rec_len)))->inode
+       (ext3_next_entry((struct ext3_dir_entry_2 *)(buffer))->inode)
 
 /*
  * Anybody can rename anything with this: the permission checks are left to the
@@ -2335,6 +2313,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
                                              EXT3_FEATURE_INCOMPAT_FILETYPE))
                        new_de->file_type = old_de->file_type;
                new_dir->i_version++;
+               new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME_SEC;
+               ext3_mark_inode_dirty(handle, new_dir);
                BUFFER_TRACE(new_bh, "call ext3_journal_dirty_metadata");
                ext3_journal_dirty_metadata(handle, new_bh);
                brelse(new_bh);