GFS2: Use kmalloc when possible for ->readdir()
[linux-2.6.git] / fs / gfs2 / dir.c
index 26ca336..6b48d7c 100644 (file)
@@ -1231,6 +1231,25 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
        return 0;
 }
 
+static void *gfs2_alloc_sort_buffer(unsigned size)
+{
+       void *ptr = NULL;
+
+       if (size < KMALLOC_MAX_SIZE)
+               ptr = kmalloc(size, GFP_NOFS | __GFP_NOWARN);
+       if (!ptr)
+               ptr = __vmalloc(size, GFP_NOFS, PAGE_KERNEL);
+       return ptr;
+}
+
+static void gfs2_free_sort_buffer(void *ptr)
+{
+       if (is_vmalloc_addr(ptr))
+               vfree(ptr);
+       else
+               kfree(ptr);
+}
+
 static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
                              filldir_t filldir, int *copied, unsigned *depth,
                              u64 leaf_no)
@@ -1271,7 +1290,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
         * 99 is the maximum number of entries that can fit in a single
         * leaf block.
         */
-       larr = vmalloc((leaves + entries + 99) * sizeof(void *));
+       larr = gfs2_alloc_sort_buffer((leaves + entries + 99) * sizeof(void *));
        if (!larr)
                goto out;
        darr = (const struct gfs2_dirent **)(larr + leaves);
@@ -1282,7 +1301,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
        do {
                error = get_leaf(ip, lfn, &bh);
                if (error)
-                       goto out_kfree;
+                       goto out_free;
                lf = (struct gfs2_leaf *)bh->b_data;
                lfn = be64_to_cpu(lf->lf_next);
                if (lf->lf_entries) {
@@ -1291,7 +1310,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
                                                gfs2_dirent_gather, NULL, &g);
                        error = PTR_ERR(dent);
                        if (IS_ERR(dent))
-                               goto out_kfree;
+                               goto out_free;
                        if (entries2 != g.offset) {
                                fs_warn(sdp, "Number of entries corrupt in dir "
                                                "leaf %llu, entries2 (%u) != "
@@ -1300,7 +1319,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
                                        entries2, g.offset);
                                        
                                error = -EIO;
-                               goto out_kfree;
+                               goto out_free;
                        }
                        error = 0;
                        larr[leaf++] = bh;
@@ -1312,10 +1331,10 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
        BUG_ON(entries2 != entries);
        error = do_filldir_main(ip, offset, opaque, filldir, darr,
                                entries, copied);
-out_kfree:
+out_free:
        for(i = 0; i < leaf; i++)
                brelse(larr[i]);
-       vfree(larr);
+       gfs2_free_sort_buffer(larr);
 out:
        return error;
 }