17336d0e6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2b3b94faaSDavid Teigland /*
3b3b94faaSDavid Teigland * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
43a8a9a10SSteven Whitehouse * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
5b3b94faaSDavid Teigland */
6b3b94faaSDavid Teigland
7b3b94faaSDavid Teigland /*
8b3b94faaSDavid Teigland * Implements Extendible Hashing as described in:
9b3b94faaSDavid Teigland * "Extendible Hashing" by Fagin, et al in
10b3b94faaSDavid Teigland * __ACM Trans. on Database Systems__, Sept 1979.
11b3b94faaSDavid Teigland *
12b3b94faaSDavid Teigland *
13b3b94faaSDavid Teigland * Here's the layout of dirents which is essentially the same as that of ext2
14b3b94faaSDavid Teigland * within a single block. The field de_name_len is the number of bytes
15b3b94faaSDavid Teigland * actually required for the name (no null terminator). The field de_rec_len
16b3b94faaSDavid Teigland * is the number of bytes allocated to the dirent. The offset of the next
17b3b94faaSDavid Teigland * dirent in the block is (dirent + dirent->de_rec_len). When a dirent is
18b3b94faaSDavid Teigland * deleted, the preceding dirent inherits its allocated space, ie
19b3b94faaSDavid Teigland * prev->de_rec_len += deleted->de_rec_len. Since the next dirent is obtained
20b3b94faaSDavid Teigland * by adding de_rec_len to the current dirent, this essentially causes the
21b3b94faaSDavid Teigland * deleted dirent to get jumped over when iterating through all the dirents.
22b3b94faaSDavid Teigland *
23b3b94faaSDavid Teigland * When deleting the first dirent in a block, there is no previous dirent so
24b3b94faaSDavid Teigland * the field de_ino is set to zero to designate it as deleted. When allocating
25b3b94faaSDavid Teigland * a dirent, gfs2_dirent_alloc iterates through the dirents in a block. If the
26b3b94faaSDavid Teigland * first dirent has (de_ino == 0) and de_rec_len is large enough, this first
27b3b94faaSDavid Teigland * dirent is allocated. Otherwise it must go through all the 'used' dirents
28b3b94faaSDavid Teigland * searching for one in which the amount of total space minus the amount of
29b3b94faaSDavid Teigland * used space will provide enough space for the new dirent.
30b3b94faaSDavid Teigland *
31b3b94faaSDavid Teigland * There are two types of blocks in which dirents reside. In a stuffed dinode,
32b3b94faaSDavid Teigland * the dirents begin at offset sizeof(struct gfs2_dinode) from the beginning of
33b3b94faaSDavid Teigland * the block. In leaves, they begin at offset sizeof(struct gfs2_leaf) from the
34b3b94faaSDavid Teigland * beginning of the leaf block. The dirents reside in leaves when
35b3b94faaSDavid Teigland *
36383f01fbSSteven Whitehouse * dip->i_diskflags & GFS2_DIF_EXHASH is true
37b3b94faaSDavid Teigland *
38b3b94faaSDavid Teigland * Otherwise, the dirents are "linear", within a single stuffed dinode block.
39b3b94faaSDavid Teigland *
40b3b94faaSDavid Teigland * When the dirents are in leaves, the actual contents of the directory file are
41b3b94faaSDavid Teigland * used as an array of 64-bit block pointers pointing to the leaf blocks. The
4261e085a8SSteven Whitehouse * dirents are NOT in the directory file itself. There can be more than one
4361e085a8SSteven Whitehouse * block pointer in the array that points to the same leaf. In fact, when a
4461e085a8SSteven Whitehouse * directory is first converted from linear to exhash, all of the pointers
4561e085a8SSteven Whitehouse * point to the same leaf.
46b3b94faaSDavid Teigland *
47b3b94faaSDavid Teigland * When a leaf is completely full, the size of the hash table can be
48b3b94faaSDavid Teigland * doubled unless it is already at the maximum size which is hard coded into
49b3b94faaSDavid Teigland * GFS2_DIR_MAX_DEPTH. After that, leaves are chained together in a linked list,
50b3b94faaSDavid Teigland * but never before the maximum hash table size has been reached.
51b3b94faaSDavid Teigland */
52b3b94faaSDavid Teigland
53d77d1b58SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
54d77d1b58SJoe Perches
55b3b94faaSDavid Teigland #include <linux/slab.h>
56b3b94faaSDavid Teigland #include <linux/spinlock.h>
57b3b94faaSDavid Teigland #include <linux/buffer_head.h>
58b3b94faaSDavid Teigland #include <linux/sort.h>
595c676f6dSSteven Whitehouse #include <linux/gfs2_ondisk.h>
6071b86f56SSteven Whitehouse #include <linux/crc32.h>
61fe1bdedcSSteven Whitehouse #include <linux/vmalloc.h>
622f8b5444SChristoph Hellwig #include <linux/bio.h>
63b3b94faaSDavid Teigland
64b3b94faaSDavid Teigland #include "gfs2.h"
655c676f6dSSteven Whitehouse #include "incore.h"
66b3b94faaSDavid Teigland #include "dir.h"
67b3b94faaSDavid Teigland #include "glock.h"
68b3b94faaSDavid Teigland #include "inode.h"
69b3b94faaSDavid Teigland #include "meta_io.h"
70b3b94faaSDavid Teigland #include "quota.h"
71b3b94faaSDavid Teigland #include "rgrp.h"
72b3b94faaSDavid Teigland #include "trans.h"
73e13940baSSteven Whitehouse #include "bmap.h"
745c676f6dSSteven Whitehouse #include "util.h"
75b3b94faaSDavid Teigland
76dfe4d34bSBob Peterson #define MAX_RA_BLOCKS 32 /* max read-ahead blocks */
77dfe4d34bSBob Peterson
78cd915493SSteven Whitehouse #define gfs2_disk_hash2offset(h) (((u64)(h)) >> 1)
79cd915493SSteven Whitehouse #define gfs2_dir_offset2hash(p) ((u32)(((u64)(p)) << 1))
80471f3db2SBenjamin Marzinski #define GFS2_HASH_INDEX_MASK 0xffffc000
81471f3db2SBenjamin Marzinski #define GFS2_USE_HASH_FLAG 0x2000
82b3b94faaSDavid Teigland
838d123585SSteven Whitehouse struct qstr gfs2_qdot __read_mostly;
848d123585SSteven Whitehouse struct qstr gfs2_qdotdot __read_mostly;
858d123585SSteven Whitehouse
862bdbc5d7SSteven Whitehouse typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent,
872bdbc5d7SSteven Whitehouse const struct qstr *name, void *opaque);
88b3b94faaSDavid Teigland
gfs2_dir_get_new_buffer(struct gfs2_inode * ip,u64 block,struct buffer_head ** bhp)89cd915493SSteven Whitehouse int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
90e13940baSSteven Whitehouse struct buffer_head **bhp)
91e13940baSSteven Whitehouse {
92e13940baSSteven Whitehouse struct buffer_head *bh;
93e13940baSSteven Whitehouse
94e13940baSSteven Whitehouse bh = gfs2_meta_new(ip->i_gl, block);
95350a9b0aSSteven Whitehouse gfs2_trans_add_meta(ip->i_gl, bh);
96e13940baSSteven Whitehouse gfs2_metatype_set(bh, GFS2_METATYPE_JD, GFS2_FORMAT_JD);
97e13940baSSteven Whitehouse gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
9861e085a8SSteven Whitehouse *bhp = bh;
9961e085a8SSteven Whitehouse return 0;
10061e085a8SSteven Whitehouse }
10161e085a8SSteven Whitehouse
gfs2_dir_get_existing_buffer(struct gfs2_inode * ip,u64 block,struct buffer_head ** bhp)102cd915493SSteven Whitehouse static int gfs2_dir_get_existing_buffer(struct gfs2_inode *ip, u64 block,
10361e085a8SSteven Whitehouse struct buffer_head **bhp)
10461e085a8SSteven Whitehouse {
10561e085a8SSteven Whitehouse struct buffer_head *bh;
10661e085a8SSteven Whitehouse int error;
10761e085a8SSteven Whitehouse
108c8d57703SAndreas Gruenbacher error = gfs2_meta_read(ip->i_gl, block, DIO_WAIT, 0, &bh);
109e13940baSSteven Whitehouse if (error)
110e13940baSSteven Whitehouse return error;
111feaa7bbaSSteven Whitehouse if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_JD)) {
112e13940baSSteven Whitehouse brelse(bh);
113e13940baSSteven Whitehouse return -EIO;
114e13940baSSteven Whitehouse }
115e13940baSSteven Whitehouse *bhp = bh;
116e13940baSSteven Whitehouse return 0;
117e13940baSSteven Whitehouse }
118e13940baSSteven Whitehouse
gfs2_dir_write_stuffed(struct gfs2_inode * ip,const char * buf,unsigned int offset,unsigned int size)119e13940baSSteven Whitehouse static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
120e13940baSSteven Whitehouse unsigned int offset, unsigned int size)
121e13940baSSteven Whitehouse {
122e13940baSSteven Whitehouse struct buffer_head *dibh;
123e13940baSSteven Whitehouse int error;
124e13940baSSteven Whitehouse
125e13940baSSteven Whitehouse error = gfs2_meta_inode_buffer(ip, &dibh);
126e13940baSSteven Whitehouse if (error)
127e13940baSSteven Whitehouse return error;
128e13940baSSteven Whitehouse
129350a9b0aSSteven Whitehouse gfs2_trans_add_meta(ip->i_gl, dibh);
130c752666cSSteven Whitehouse memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
131a2e0f799SSteven Whitehouse if (ip->i_inode.i_size < offset + size)
132a2e0f799SSteven Whitehouse i_size_write(&ip->i_inode, offset + size);
1338a8b8d91SJeff Layton ip->i_inode.i_mtime = inode_set_ctime_current(&ip->i_inode);
134539e5d6bSSteven Whitehouse gfs2_dinode_out(ip, dibh->b_data);
135e13940baSSteven Whitehouse
136e13940baSSteven Whitehouse brelse(dibh);
137e13940baSSteven Whitehouse
138e13940baSSteven Whitehouse return size;
139e13940baSSteven Whitehouse }
140e13940baSSteven Whitehouse
141e13940baSSteven Whitehouse
142e13940baSSteven Whitehouse
143e13940baSSteven Whitehouse /**
144e13940baSSteven Whitehouse * gfs2_dir_write_data - Write directory information to the inode
145e13940baSSteven Whitehouse * @ip: The GFS2 inode
146e13940baSSteven Whitehouse * @buf: The buffer containing information to be written
147e13940baSSteven Whitehouse * @offset: The file offset to start writing at
148e13940baSSteven Whitehouse * @size: The amount of data to write
149e13940baSSteven Whitehouse *
150e13940baSSteven Whitehouse * Returns: The number of bytes correctly written or error code
151e13940baSSteven Whitehouse */
gfs2_dir_write_data(struct gfs2_inode * ip,const char * buf,u64 offset,unsigned int size)152e13940baSSteven Whitehouse static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
153cd915493SSteven Whitehouse u64 offset, unsigned int size)
154e13940baSSteven Whitehouse {
155feaa7bbaSSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
156e13940baSSteven Whitehouse struct buffer_head *dibh;
157cd915493SSteven Whitehouse u64 lblock, dblock;
158cd915493SSteven Whitehouse u32 extlen = 0;
159e13940baSSteven Whitehouse unsigned int o;
160e13940baSSteven Whitehouse int copied = 0;
161e13940baSSteven Whitehouse int error = 0;
1629153dac1SAndreas Gruenbacher bool new = false;
163e13940baSSteven Whitehouse
164e13940baSSteven Whitehouse if (!size)
165e13940baSSteven Whitehouse return 0;
166e13940baSSteven Whitehouse
167235628c5SAndreas Gruenbacher if (gfs2_is_stuffed(ip) && offset + size <= gfs2_max_stuffed_size(ip))
168568f4c96SSteven Whitehouse return gfs2_dir_write_stuffed(ip, buf, (unsigned int)offset,
169568f4c96SSteven Whitehouse size);
170e13940baSSteven Whitehouse
171e13940baSSteven Whitehouse if (gfs2_assert_warn(sdp, gfs2_is_jdata(ip)))
172e13940baSSteven Whitehouse return -EINVAL;
173e13940baSSteven Whitehouse
174e13940baSSteven Whitehouse if (gfs2_is_stuffed(ip)) {
1757a607a41SAndreas Gruenbacher error = gfs2_unstuff_dinode(ip);
176e13940baSSteven Whitehouse if (error)
177e13940baSSteven Whitehouse return error;
178e13940baSSteven Whitehouse }
179e13940baSSteven Whitehouse
180e13940baSSteven Whitehouse lblock = offset;
181e13940baSSteven Whitehouse o = do_div(lblock, sdp->sd_jbsize) + sizeof(struct gfs2_meta_header);
182e13940baSSteven Whitehouse
183e13940baSSteven Whitehouse while (copied < size) {
184e13940baSSteven Whitehouse unsigned int amount;
185e13940baSSteven Whitehouse struct buffer_head *bh;
186e13940baSSteven Whitehouse
187e13940baSSteven Whitehouse amount = size - copied;
188e13940baSSteven Whitehouse if (amount > sdp->sd_sb.sb_bsize - o)
189e13940baSSteven Whitehouse amount = sdp->sd_sb.sb_bsize - o;
190e13940baSSteven Whitehouse
191e13940baSSteven Whitehouse if (!extlen) {
1929153dac1SAndreas Gruenbacher extlen = 1;
1939153dac1SAndreas Gruenbacher error = gfs2_alloc_extent(&ip->i_inode, lblock, &dblock,
1949153dac1SAndreas Gruenbacher &extlen, &new);
195e13940baSSteven Whitehouse if (error)
196e13940baSSteven Whitehouse goto fail;
197e13940baSSteven Whitehouse error = -EIO;
198e13940baSSteven Whitehouse if (gfs2_assert_withdraw(sdp, dblock))
199e13940baSSteven Whitehouse goto fail;
200e13940baSSteven Whitehouse }
201e13940baSSteven Whitehouse
20261e085a8SSteven Whitehouse if (amount == sdp->sd_jbsize || new)
20361e085a8SSteven Whitehouse error = gfs2_dir_get_new_buffer(ip, dblock, &bh);
20461e085a8SSteven Whitehouse else
20561e085a8SSteven Whitehouse error = gfs2_dir_get_existing_buffer(ip, dblock, &bh);
20661e085a8SSteven Whitehouse
207e13940baSSteven Whitehouse if (error)
208e13940baSSteven Whitehouse goto fail;
209e13940baSSteven Whitehouse
210350a9b0aSSteven Whitehouse gfs2_trans_add_meta(ip->i_gl, bh);
211e13940baSSteven Whitehouse memcpy(bh->b_data + o, buf, amount);
212e13940baSSteven Whitehouse brelse(bh);
213e13940baSSteven Whitehouse
214899bb264SSteven Whitehouse buf += amount;
215e13940baSSteven Whitehouse copied += amount;
216e13940baSSteven Whitehouse lblock++;
217e13940baSSteven Whitehouse dblock++;
218e13940baSSteven Whitehouse extlen--;
219e13940baSSteven Whitehouse
220e13940baSSteven Whitehouse o = sizeof(struct gfs2_meta_header);
221e13940baSSteven Whitehouse }
222e13940baSSteven Whitehouse
223e13940baSSteven Whitehouse out:
224e13940baSSteven Whitehouse error = gfs2_meta_inode_buffer(ip, &dibh);
225e13940baSSteven Whitehouse if (error)
226e13940baSSteven Whitehouse return error;
227e13940baSSteven Whitehouse
228a2e0f799SSteven Whitehouse if (ip->i_inode.i_size < offset + copied)
229a2e0f799SSteven Whitehouse i_size_write(&ip->i_inode, offset + copied);
2308a8b8d91SJeff Layton ip->i_inode.i_mtime = inode_set_ctime_current(&ip->i_inode);
231e13940baSSteven Whitehouse
232350a9b0aSSteven Whitehouse gfs2_trans_add_meta(ip->i_gl, dibh);
233539e5d6bSSteven Whitehouse gfs2_dinode_out(ip, dibh->b_data);
234e13940baSSteven Whitehouse brelse(dibh);
235e13940baSSteven Whitehouse
236e13940baSSteven Whitehouse return copied;
237e13940baSSteven Whitehouse fail:
238e13940baSSteven Whitehouse if (copied)
239e13940baSSteven Whitehouse goto out;
240e13940baSSteven Whitehouse return error;
241e13940baSSteven Whitehouse }
242e13940baSSteven Whitehouse
gfs2_dir_read_stuffed(struct gfs2_inode * ip,__be64 * buf,unsigned int size)2434c28d338SSteven Whitehouse static int gfs2_dir_read_stuffed(struct gfs2_inode *ip, __be64 *buf,
2444c28d338SSteven Whitehouse unsigned int size)
245e13940baSSteven Whitehouse {
246e13940baSSteven Whitehouse struct buffer_head *dibh;
247e13940baSSteven Whitehouse int error;
248e13940baSSteven Whitehouse
249e13940baSSteven Whitehouse error = gfs2_meta_inode_buffer(ip, &dibh);
250e13940baSSteven Whitehouse if (!error) {
2514c28d338SSteven Whitehouse memcpy(buf, dibh->b_data + sizeof(struct gfs2_dinode), size);
252e13940baSSteven Whitehouse brelse(dibh);
253e13940baSSteven Whitehouse }
254e13940baSSteven Whitehouse
255e13940baSSteven Whitehouse return (error) ? error : size;
256e13940baSSteven Whitehouse }
257e13940baSSteven Whitehouse
258e13940baSSteven Whitehouse
259e13940baSSteven Whitehouse /**
260e13940baSSteven Whitehouse * gfs2_dir_read_data - Read a data from a directory inode
261e13940baSSteven Whitehouse * @ip: The GFS2 Inode
262e13940baSSteven Whitehouse * @buf: The buffer to place result into
263e13940baSSteven Whitehouse * @size: Amount of data to transfer
264e13940baSSteven Whitehouse *
265e13940baSSteven Whitehouse * Returns: The amount of data actually copied or the error
266e13940baSSteven Whitehouse */
gfs2_dir_read_data(struct gfs2_inode * ip,__be64 * buf,unsigned int size)2674c28d338SSteven Whitehouse static int gfs2_dir_read_data(struct gfs2_inode *ip, __be64 *buf,
2684c28d338SSteven Whitehouse unsigned int size)
269e13940baSSteven Whitehouse {
270feaa7bbaSSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
271cd915493SSteven Whitehouse u64 lblock, dblock;
272cd915493SSteven Whitehouse u32 extlen = 0;
273e13940baSSteven Whitehouse unsigned int o;
274e13940baSSteven Whitehouse int copied = 0;
275e13940baSSteven Whitehouse int error = 0;
276e13940baSSteven Whitehouse
277e13940baSSteven Whitehouse if (gfs2_is_stuffed(ip))
2784c28d338SSteven Whitehouse return gfs2_dir_read_stuffed(ip, buf, size);
279e13940baSSteven Whitehouse
280e13940baSSteven Whitehouse if (gfs2_assert_warn(sdp, gfs2_is_jdata(ip)))
281e13940baSSteven Whitehouse return -EINVAL;
282e13940baSSteven Whitehouse
2834c28d338SSteven Whitehouse lblock = 0;
284e13940baSSteven Whitehouse o = do_div(lblock, sdp->sd_jbsize) + sizeof(struct gfs2_meta_header);
285e13940baSSteven Whitehouse
286e13940baSSteven Whitehouse while (copied < size) {
287e13940baSSteven Whitehouse unsigned int amount;
288e13940baSSteven Whitehouse struct buffer_head *bh;
289e13940baSSteven Whitehouse
290e13940baSSteven Whitehouse amount = size - copied;
291e13940baSSteven Whitehouse if (amount > sdp->sd_sb.sb_bsize - o)
292e13940baSSteven Whitehouse amount = sdp->sd_sb.sb_bsize - o;
293e13940baSSteven Whitehouse
294e13940baSSteven Whitehouse if (!extlen) {
2959153dac1SAndreas Gruenbacher extlen = 32;
2969153dac1SAndreas Gruenbacher error = gfs2_get_extent(&ip->i_inode, lblock,
297fd88de56SSteven Whitehouse &dblock, &extlen);
2987276b3b0SSteven Whitehouse if (error || !dblock)
2997276b3b0SSteven Whitehouse goto fail;
3007276b3b0SSteven Whitehouse BUG_ON(extlen < 1);
3017276b3b0SSteven Whitehouse bh = gfs2_meta_ra(ip->i_gl, dblock, extlen);
302b7d8ac3eSAdrian Bunk } else {
303c8d57703SAndreas Gruenbacher error = gfs2_meta_read(ip->i_gl, dblock, DIO_WAIT, 0, &bh);
304e13940baSSteven Whitehouse if (error)
305e13940baSSteven Whitehouse goto fail;
306e13940baSSteven Whitehouse }
3077276b3b0SSteven Whitehouse error = gfs2_metatype_check(sdp, bh, GFS2_METATYPE_JD);
3087276b3b0SSteven Whitehouse if (error) {
3097276b3b0SSteven Whitehouse brelse(bh);
310e13940baSSteven Whitehouse goto fail;
3117276b3b0SSteven Whitehouse }
312e13940baSSteven Whitehouse dblock++;
313e13940baSSteven Whitehouse extlen--;
314e13940baSSteven Whitehouse memcpy(buf, bh->b_data + o, amount);
315e13940baSSteven Whitehouse brelse(bh);
3164c28d338SSteven Whitehouse buf += (amount/sizeof(__be64));
317e13940baSSteven Whitehouse copied += amount;
318e13940baSSteven Whitehouse lblock++;
319e13940baSSteven Whitehouse o = sizeof(struct gfs2_meta_header);
320e13940baSSteven Whitehouse }
321e13940baSSteven Whitehouse
322e13940baSSteven Whitehouse return copied;
323e13940baSSteven Whitehouse fail:
324e13940baSSteven Whitehouse return (copied) ? copied : error;
325e13940baSSteven Whitehouse }
326e13940baSSteven Whitehouse
32717d539f0SSteven Whitehouse /**
32817d539f0SSteven Whitehouse * gfs2_dir_get_hash_table - Get pointer to the dir hash table
32917d539f0SSteven Whitehouse * @ip: The inode in question
33017d539f0SSteven Whitehouse *
33117d539f0SSteven Whitehouse * Returns: The hash table or an error
33217d539f0SSteven Whitehouse */
33317d539f0SSteven Whitehouse
gfs2_dir_get_hash_table(struct gfs2_inode * ip)33417d539f0SSteven Whitehouse static __be64 *gfs2_dir_get_hash_table(struct gfs2_inode *ip)
33517d539f0SSteven Whitehouse {
33617d539f0SSteven Whitehouse struct inode *inode = &ip->i_inode;
33717d539f0SSteven Whitehouse int ret;
33817d539f0SSteven Whitehouse u32 hsize;
33917d539f0SSteven Whitehouse __be64 *hc;
34017d539f0SSteven Whitehouse
34117d539f0SSteven Whitehouse BUG_ON(!(ip->i_diskflags & GFS2_DIF_EXHASH));
34217d539f0SSteven Whitehouse
34317d539f0SSteven Whitehouse hc = ip->i_hash_cache;
34417d539f0SSteven Whitehouse if (hc)
34517d539f0SSteven Whitehouse return hc;
34617d539f0SSteven Whitehouse
34747a9a527SFabian Frederick hsize = BIT(ip->i_depth);
34817d539f0SSteven Whitehouse hsize *= sizeof(__be64);
34917d539f0SSteven Whitehouse if (hsize != i_size_read(&ip->i_inode)) {
35017d539f0SSteven Whitehouse gfs2_consist_inode(ip);
35117d539f0SSteven Whitehouse return ERR_PTR(-EIO);
35217d539f0SSteven Whitehouse }
35317d539f0SSteven Whitehouse
354e8830d88SBob Peterson hc = kmalloc(hsize, GFP_NOFS | __GFP_NOWARN);
355e8830d88SBob Peterson if (hc == NULL)
35688dca4caSChristoph Hellwig hc = __vmalloc(hsize, GFP_NOFS);
357e8830d88SBob Peterson
35817d539f0SSteven Whitehouse if (hc == NULL)
35917d539f0SSteven Whitehouse return ERR_PTR(-ENOMEM);
36017d539f0SSteven Whitehouse
3614c28d338SSteven Whitehouse ret = gfs2_dir_read_data(ip, hc, hsize);
36217d539f0SSteven Whitehouse if (ret < 0) {
3633cdcf63eSAl Viro kvfree(hc);
36417d539f0SSteven Whitehouse return ERR_PTR(ret);
36517d539f0SSteven Whitehouse }
36617d539f0SSteven Whitehouse
36717d539f0SSteven Whitehouse spin_lock(&inode->i_lock);
3689265f1d0SAl Viro if (likely(!ip->i_hash_cache)) {
36917d539f0SSteven Whitehouse ip->i_hash_cache = hc;
3709265f1d0SAl Viro hc = NULL;
3719265f1d0SAl Viro }
37217d539f0SSteven Whitehouse spin_unlock(&inode->i_lock);
3739265f1d0SAl Viro kvfree(hc);
37417d539f0SSteven Whitehouse
37517d539f0SSteven Whitehouse return ip->i_hash_cache;
37617d539f0SSteven Whitehouse }
37717d539f0SSteven Whitehouse
37817d539f0SSteven Whitehouse /**
37917d539f0SSteven Whitehouse * gfs2_dir_hash_inval - Invalidate dir hash
38017d539f0SSteven Whitehouse * @ip: The directory inode
38117d539f0SSteven Whitehouse *
38217d539f0SSteven Whitehouse * Must be called with an exclusive glock, or during glock invalidation.
38317d539f0SSteven Whitehouse */
gfs2_dir_hash_inval(struct gfs2_inode * ip)38417d539f0SSteven Whitehouse void gfs2_dir_hash_inval(struct gfs2_inode *ip)
38517d539f0SSteven Whitehouse {
386c36b97e9SBob Peterson __be64 *hc;
387c36b97e9SBob Peterson
388c36b97e9SBob Peterson spin_lock(&ip->i_inode.i_lock);
389c36b97e9SBob Peterson hc = ip->i_hash_cache;
39017d539f0SSteven Whitehouse ip->i_hash_cache = NULL;
391c36b97e9SBob Peterson spin_unlock(&ip->i_inode.i_lock);
392c36b97e9SBob Peterson
3933cdcf63eSAl Viro kvfree(hc);
39417d539f0SSteven Whitehouse }
39517d539f0SSteven Whitehouse
gfs2_dirent_sentinel(const struct gfs2_dirent * dent)3965e7d65cdSSteven Whitehouse static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent)
3975e7d65cdSSteven Whitehouse {
3985e7d65cdSSteven Whitehouse return dent->de_inum.no_addr == 0 || dent->de_inum.no_formal_ino == 0;
3995e7d65cdSSteven Whitehouse }
4005e7d65cdSSteven Whitehouse
__gfs2_dirent_find(const struct gfs2_dirent * dent,const struct qstr * name,int ret)401c752666cSSteven Whitehouse static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent,
402c752666cSSteven Whitehouse const struct qstr *name, int ret)
403b3b94faaSDavid Teigland {
4045e7d65cdSSteven Whitehouse if (!gfs2_dirent_sentinel(dent) &&
405c752666cSSteven Whitehouse be32_to_cpu(dent->de_hash) == name->hash &&
406c752666cSSteven Whitehouse be16_to_cpu(dent->de_name_len) == name->len &&
4072bdbc5d7SSteven Whitehouse memcmp(dent+1, name->name, name->len) == 0)
408c752666cSSteven Whitehouse return ret;
409b3b94faaSDavid Teigland return 0;
410b3b94faaSDavid Teigland }
411b3b94faaSDavid Teigland
gfs2_dirent_find(const struct gfs2_dirent * dent,const struct qstr * name,void * opaque)412c752666cSSteven Whitehouse static int gfs2_dirent_find(const struct gfs2_dirent *dent,
41371b86f56SSteven Whitehouse const struct qstr *name,
41471b86f56SSteven Whitehouse void *opaque)
415c752666cSSteven Whitehouse {
416c752666cSSteven Whitehouse return __gfs2_dirent_find(dent, name, 1);
417c752666cSSteven Whitehouse }
418c752666cSSteven Whitehouse
gfs2_dirent_prev(const struct gfs2_dirent * dent,const struct qstr * name,void * opaque)419c752666cSSteven Whitehouse static int gfs2_dirent_prev(const struct gfs2_dirent *dent,
42071b86f56SSteven Whitehouse const struct qstr *name,
42171b86f56SSteven Whitehouse void *opaque)
422c752666cSSteven Whitehouse {
423c752666cSSteven Whitehouse return __gfs2_dirent_find(dent, name, 2);
424c752666cSSteven Whitehouse }
425c752666cSSteven Whitehouse
426c752666cSSteven Whitehouse /*
427c752666cSSteven Whitehouse * name->name holds ptr to start of block.
428c752666cSSteven Whitehouse * name->len holds size of block.
429c752666cSSteven Whitehouse */
gfs2_dirent_last(const struct gfs2_dirent * dent,const struct qstr * name,void * opaque)430c752666cSSteven Whitehouse static int gfs2_dirent_last(const struct gfs2_dirent *dent,
43171b86f56SSteven Whitehouse const struct qstr *name,
43271b86f56SSteven Whitehouse void *opaque)
433c752666cSSteven Whitehouse {
434c752666cSSteven Whitehouse const char *start = name->name;
435c752666cSSteven Whitehouse const char *end = (const char *)dent + be16_to_cpu(dent->de_rec_len);
436c752666cSSteven Whitehouse if (name->len == (end - start))
437c752666cSSteven Whitehouse return 1;
438c752666cSSteven Whitehouse return 0;
439c752666cSSteven Whitehouse }
440c752666cSSteven Whitehouse
44134017472SBenjamin Marzinski /* Look for the dirent that contains the offset specified in data. Once we
44234017472SBenjamin Marzinski * find that dirent, there must be space available there for the new dirent */
gfs2_dirent_find_offset(const struct gfs2_dirent * dent,const struct qstr * name,void * ptr)44334017472SBenjamin Marzinski static int gfs2_dirent_find_offset(const struct gfs2_dirent *dent,
44434017472SBenjamin Marzinski const struct qstr *name,
44534017472SBenjamin Marzinski void *ptr)
44634017472SBenjamin Marzinski {
44734017472SBenjamin Marzinski unsigned required = GFS2_DIRENT_SIZE(name->len);
44834017472SBenjamin Marzinski unsigned actual = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len));
44934017472SBenjamin Marzinski unsigned totlen = be16_to_cpu(dent->de_rec_len);
45034017472SBenjamin Marzinski
45134017472SBenjamin Marzinski if (ptr < (void *)dent || ptr >= (void *)dent + totlen)
45234017472SBenjamin Marzinski return 0;
45334017472SBenjamin Marzinski if (gfs2_dirent_sentinel(dent))
45434017472SBenjamin Marzinski actual = 0;
45534017472SBenjamin Marzinski if (ptr < (void *)dent + actual)
45634017472SBenjamin Marzinski return -1;
45734017472SBenjamin Marzinski if ((void *)dent + totlen >= ptr + required)
45834017472SBenjamin Marzinski return 1;
45934017472SBenjamin Marzinski return -1;
46034017472SBenjamin Marzinski }
46134017472SBenjamin Marzinski
gfs2_dirent_find_space(const struct gfs2_dirent * dent,const struct qstr * name,void * opaque)462c752666cSSteven Whitehouse static int gfs2_dirent_find_space(const struct gfs2_dirent *dent,
46371b86f56SSteven Whitehouse const struct qstr *name,
46471b86f56SSteven Whitehouse void *opaque)
465c752666cSSteven Whitehouse {
466c752666cSSteven Whitehouse unsigned required = GFS2_DIRENT_SIZE(name->len);
467c752666cSSteven Whitehouse unsigned actual = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len));
468c752666cSSteven Whitehouse unsigned totlen = be16_to_cpu(dent->de_rec_len);
469c752666cSSteven Whitehouse
4705e7d65cdSSteven Whitehouse if (gfs2_dirent_sentinel(dent))
471728a756bSBob Peterson actual = 0;
472c5392124SJan Engelhardt if (totlen - actual >= required)
473c752666cSSteven Whitehouse return 1;
474c752666cSSteven Whitehouse return 0;
475c752666cSSteven Whitehouse }
476c752666cSSteven Whitehouse
47771b86f56SSteven Whitehouse struct dirent_gather {
47871b86f56SSteven Whitehouse const struct gfs2_dirent **pdent;
47971b86f56SSteven Whitehouse unsigned offset;
48071b86f56SSteven Whitehouse };
48171b86f56SSteven Whitehouse
gfs2_dirent_gather(const struct gfs2_dirent * dent,const struct qstr * name,void * opaque)48271b86f56SSteven Whitehouse static int gfs2_dirent_gather(const struct gfs2_dirent *dent,
48371b86f56SSteven Whitehouse const struct qstr *name,
48471b86f56SSteven Whitehouse void *opaque)
48571b86f56SSteven Whitehouse {
48671b86f56SSteven Whitehouse struct dirent_gather *g = opaque;
4875e7d65cdSSteven Whitehouse if (!gfs2_dirent_sentinel(dent)) {
48871b86f56SSteven Whitehouse g->pdent[g->offset++] = dent;
48971b86f56SSteven Whitehouse }
49071b86f56SSteven Whitehouse return 0;
49171b86f56SSteven Whitehouse }
49271b86f56SSteven Whitehouse
493c752666cSSteven Whitehouse /*
494c752666cSSteven Whitehouse * Other possible things to check:
495c752666cSSteven Whitehouse * - Inode located within filesystem size (and on valid block)
496c752666cSSteven Whitehouse * - Valid directory entry type
497c752666cSSteven Whitehouse * Not sure how heavy-weight we want to make this... could also check
498c752666cSSteven Whitehouse * hash is correct for example, but that would take a lot of extra time.
499c752666cSSteven Whitehouse * For now the most important thing is to check that the various sizes
500c752666cSSteven Whitehouse * are correct.
501c752666cSSteven Whitehouse */
gfs2_check_dirent(struct gfs2_sbd * sdp,struct gfs2_dirent * dent,unsigned int offset,unsigned int size,unsigned int len,int first)502e54c78a2SBob Peterson static int gfs2_check_dirent(struct gfs2_sbd *sdp,
503e54c78a2SBob Peterson struct gfs2_dirent *dent, unsigned int offset,
504c752666cSSteven Whitehouse unsigned int size, unsigned int len, int first)
505c752666cSSteven Whitehouse {
506c752666cSSteven Whitehouse const char *msg = "gfs2_dirent too small";
507c752666cSSteven Whitehouse if (unlikely(size < sizeof(struct gfs2_dirent)))
508c752666cSSteven Whitehouse goto error;
509c752666cSSteven Whitehouse msg = "gfs2_dirent misaligned";
510c752666cSSteven Whitehouse if (unlikely(offset & 0x7))
511c752666cSSteven Whitehouse goto error;
512c752666cSSteven Whitehouse msg = "gfs2_dirent points beyond end of block";
513c752666cSSteven Whitehouse if (unlikely(offset + size > len))
514c752666cSSteven Whitehouse goto error;
515c752666cSSteven Whitehouse msg = "zero inode number";
5165e7d65cdSSteven Whitehouse if (unlikely(!first && gfs2_dirent_sentinel(dent)))
517c752666cSSteven Whitehouse goto error;
518c752666cSSteven Whitehouse msg = "name length is greater than space in dirent";
5195e7d65cdSSteven Whitehouse if (!gfs2_dirent_sentinel(dent) &&
520c752666cSSteven Whitehouse unlikely(sizeof(struct gfs2_dirent)+be16_to_cpu(dent->de_name_len) >
521c752666cSSteven Whitehouse size))
522c752666cSSteven Whitehouse goto error;
523c752666cSSteven Whitehouse return 0;
524c752666cSSteven Whitehouse error:
525e54c78a2SBob Peterson fs_warn(sdp, "%s: %s (%s)\n",
526d77d1b58SJoe Perches __func__, msg, first ? "first in block" : "not first in block");
527c752666cSSteven Whitehouse return -EIO;
528c752666cSSteven Whitehouse }
529c752666cSSteven Whitehouse
gfs2_dirent_offset(struct gfs2_sbd * sdp,const void * buf)530e54c78a2SBob Peterson static int gfs2_dirent_offset(struct gfs2_sbd *sdp, const void *buf)
531c752666cSSteven Whitehouse {
53271b86f56SSteven Whitehouse const struct gfs2_meta_header *h = buf;
53371b86f56SSteven Whitehouse int offset;
534c752666cSSteven Whitehouse
535c752666cSSteven Whitehouse BUG_ON(buf == NULL);
536c752666cSSteven Whitehouse
537e3167dedSSteven Whitehouse switch(be32_to_cpu(h->mh_type)) {
538c752666cSSteven Whitehouse case GFS2_METATYPE_LF:
539c752666cSSteven Whitehouse offset = sizeof(struct gfs2_leaf);
540c752666cSSteven Whitehouse break;
541c752666cSSteven Whitehouse case GFS2_METATYPE_DI:
542c752666cSSteven Whitehouse offset = sizeof(struct gfs2_dinode);
543c752666cSSteven Whitehouse break;
544c752666cSSteven Whitehouse default:
545c752666cSSteven Whitehouse goto wrong_type;
546c752666cSSteven Whitehouse }
54771b86f56SSteven Whitehouse return offset;
54871b86f56SSteven Whitehouse wrong_type:
549e54c78a2SBob Peterson fs_warn(sdp, "%s: wrong block type %u\n", __func__,
550e54c78a2SBob Peterson be32_to_cpu(h->mh_type));
55171b86f56SSteven Whitehouse return -1;
55271b86f56SSteven Whitehouse }
553c752666cSSteven Whitehouse
gfs2_dirent_scan(struct inode * inode,void * buf,unsigned int len,gfs2_dscan_t scan,const struct qstr * name,void * opaque)5542bdbc5d7SSteven Whitehouse static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf,
55571b86f56SSteven Whitehouse unsigned int len, gfs2_dscan_t scan,
55671b86f56SSteven Whitehouse const struct qstr *name,
55771b86f56SSteven Whitehouse void *opaque)
55871b86f56SSteven Whitehouse {
55971b86f56SSteven Whitehouse struct gfs2_dirent *dent, *prev;
56071b86f56SSteven Whitehouse unsigned offset;
56171b86f56SSteven Whitehouse unsigned size;
56271b86f56SSteven Whitehouse int ret = 0;
56371b86f56SSteven Whitehouse
564e54c78a2SBob Peterson ret = gfs2_dirent_offset(GFS2_SB(inode), buf);
56571b86f56SSteven Whitehouse if (ret < 0)
56671b86f56SSteven Whitehouse goto consist_inode;
56771b86f56SSteven Whitehouse
56871b86f56SSteven Whitehouse offset = ret;
569c752666cSSteven Whitehouse prev = NULL;
5702bdbc5d7SSteven Whitehouse dent = buf + offset;
571c752666cSSteven Whitehouse size = be16_to_cpu(dent->de_rec_len);
572e54c78a2SBob Peterson if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, len, 1))
573c752666cSSteven Whitehouse goto consist_inode;
574c752666cSSteven Whitehouse do {
57571b86f56SSteven Whitehouse ret = scan(dent, name, opaque);
576c752666cSSteven Whitehouse if (ret)
577c752666cSSteven Whitehouse break;
578c752666cSSteven Whitehouse offset += size;
579c752666cSSteven Whitehouse if (offset == len)
580c752666cSSteven Whitehouse break;
581c752666cSSteven Whitehouse prev = dent;
5822bdbc5d7SSteven Whitehouse dent = buf + offset;
583c752666cSSteven Whitehouse size = be16_to_cpu(dent->de_rec_len);
584e54c78a2SBob Peterson if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size,
585e54c78a2SBob Peterson len, 0))
586c752666cSSteven Whitehouse goto consist_inode;
587c752666cSSteven Whitehouse } while(1);
588c752666cSSteven Whitehouse
589c752666cSSteven Whitehouse switch(ret) {
590c752666cSSteven Whitehouse case 0:
591c752666cSSteven Whitehouse return NULL;
592c752666cSSteven Whitehouse case 1:
593c752666cSSteven Whitehouse return dent;
594c752666cSSteven Whitehouse case 2:
595c752666cSSteven Whitehouse return prev ? prev : dent;
596c752666cSSteven Whitehouse default:
597c752666cSSteven Whitehouse BUG_ON(ret > 0);
598c752666cSSteven Whitehouse return ERR_PTR(ret);
599c752666cSSteven Whitehouse }
600c752666cSSteven Whitehouse
601c752666cSSteven Whitehouse consist_inode:
602feaa7bbaSSteven Whitehouse gfs2_consist_inode(GFS2_I(inode));
603c752666cSSteven Whitehouse return ERR_PTR(-EIO);
604c752666cSSteven Whitehouse }
605c752666cSSteven Whitehouse
dirent_check_reclen(struct gfs2_inode * dip,const struct gfs2_dirent * d,const void * end_p)6062bdbc5d7SSteven Whitehouse static int dirent_check_reclen(struct gfs2_inode *dip,
6072bdbc5d7SSteven Whitehouse const struct gfs2_dirent *d, const void *end_p)
6082bdbc5d7SSteven Whitehouse {
6092bdbc5d7SSteven Whitehouse const void *ptr = d;
6102bdbc5d7SSteven Whitehouse u16 rec_len = be16_to_cpu(d->de_rec_len);
6112bdbc5d7SSteven Whitehouse
6122bdbc5d7SSteven Whitehouse if (unlikely(rec_len < sizeof(struct gfs2_dirent)))
6132bdbc5d7SSteven Whitehouse goto broken;
6142bdbc5d7SSteven Whitehouse ptr += rec_len;
6152bdbc5d7SSteven Whitehouse if (ptr < end_p)
6162bdbc5d7SSteven Whitehouse return rec_len;
6172bdbc5d7SSteven Whitehouse if (ptr == end_p)
6182bdbc5d7SSteven Whitehouse return -ENOENT;
6192bdbc5d7SSteven Whitehouse broken:
6202bdbc5d7SSteven Whitehouse gfs2_consist_inode(dip);
6212bdbc5d7SSteven Whitehouse return -EIO;
6222bdbc5d7SSteven Whitehouse }
6232bdbc5d7SSteven Whitehouse
624b3b94faaSDavid Teigland /**
625b3b94faaSDavid Teigland * dirent_next - Next dirent
626b3b94faaSDavid Teigland * @dip: the directory
627b3b94faaSDavid Teigland * @bh: The buffer
628b3b94faaSDavid Teigland * @dent: Pointer to list of dirents
629b3b94faaSDavid Teigland *
630b3b94faaSDavid Teigland * Returns: 0 on success, error code otherwise
631b3b94faaSDavid Teigland */
632b3b94faaSDavid Teigland
dirent_next(struct gfs2_inode * dip,struct buffer_head * bh,struct gfs2_dirent ** dent)633b3b94faaSDavid Teigland static int dirent_next(struct gfs2_inode *dip, struct buffer_head *bh,
634b3b94faaSDavid Teigland struct gfs2_dirent **dent)
635b3b94faaSDavid Teigland {
6362bdbc5d7SSteven Whitehouse struct gfs2_dirent *cur = *dent, *tmp;
6372bdbc5d7SSteven Whitehouse char *bh_end = bh->b_data + bh->b_size;
6382bdbc5d7SSteven Whitehouse int ret;
639b3b94faaSDavid Teigland
6402bdbc5d7SSteven Whitehouse ret = dirent_check_reclen(dip, cur, bh_end);
6412bdbc5d7SSteven Whitehouse if (ret < 0)
6422bdbc5d7SSteven Whitehouse return ret;
643b3b94faaSDavid Teigland
6442bdbc5d7SSteven Whitehouse tmp = (void *)cur + ret;
6452bdbc5d7SSteven Whitehouse ret = dirent_check_reclen(dip, tmp, bh_end);
6462bdbc5d7SSteven Whitehouse if (ret == -EIO)
6472bdbc5d7SSteven Whitehouse return ret;
6484dd651adSSteven Whitehouse
649b3b94faaSDavid Teigland /* Only the first dent could ever have de_inum.no_addr == 0 */
6505e7d65cdSSteven Whitehouse if (gfs2_dirent_sentinel(tmp)) {
651b3b94faaSDavid Teigland gfs2_consist_inode(dip);
652b3b94faaSDavid Teigland return -EIO;
653b3b94faaSDavid Teigland }
654b3b94faaSDavid Teigland
655b3b94faaSDavid Teigland *dent = tmp;
656b3b94faaSDavid Teigland return 0;
657b3b94faaSDavid Teigland }
658b3b94faaSDavid Teigland
659b3b94faaSDavid Teigland /**
660b3b94faaSDavid Teigland * dirent_del - Delete a dirent
661b3b94faaSDavid Teigland * @dip: The GFS2 inode
662b3b94faaSDavid Teigland * @bh: The buffer
663b3b94faaSDavid Teigland * @prev: The previous dirent
664b3b94faaSDavid Teigland * @cur: The current dirent
665b3b94faaSDavid Teigland *
666b3b94faaSDavid Teigland */
667b3b94faaSDavid Teigland
dirent_del(struct gfs2_inode * dip,struct buffer_head * bh,struct gfs2_dirent * prev,struct gfs2_dirent * cur)668b3b94faaSDavid Teigland static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh,
669b3b94faaSDavid Teigland struct gfs2_dirent *prev, struct gfs2_dirent *cur)
670b3b94faaSDavid Teigland {
671cd915493SSteven Whitehouse u16 cur_rec_len, prev_rec_len;
672b3b94faaSDavid Teigland
6735e7d65cdSSteven Whitehouse if (gfs2_dirent_sentinel(cur)) {
674b3b94faaSDavid Teigland gfs2_consist_inode(dip);
675b3b94faaSDavid Teigland return;
676b3b94faaSDavid Teigland }
677b3b94faaSDavid Teigland
678350a9b0aSSteven Whitehouse gfs2_trans_add_meta(dip->i_gl, bh);
679b3b94faaSDavid Teigland
680b3b94faaSDavid Teigland /* If there is no prev entry, this is the first entry in the block.
681b3b94faaSDavid Teigland The de_rec_len is already as big as it needs to be. Just zero
682b3b94faaSDavid Teigland out the inode number and return. */
683b3b94faaSDavid Teigland
684b3b94faaSDavid Teigland if (!prev) {
6855e7d65cdSSteven Whitehouse cur->de_inum.no_addr = 0;
6865e7d65cdSSteven Whitehouse cur->de_inum.no_formal_ino = 0;
687b3b94faaSDavid Teigland return;
688b3b94faaSDavid Teigland }
689b3b94faaSDavid Teigland
690b3b94faaSDavid Teigland /* Combine this dentry with the previous one. */
691b3b94faaSDavid Teigland
692fc69d0d3SSteven Whitehouse prev_rec_len = be16_to_cpu(prev->de_rec_len);
693fc69d0d3SSteven Whitehouse cur_rec_len = be16_to_cpu(cur->de_rec_len);
694b3b94faaSDavid Teigland
695b3b94faaSDavid Teigland if ((char *)prev + prev_rec_len != (char *)cur)
696b3b94faaSDavid Teigland gfs2_consist_inode(dip);
697b3b94faaSDavid Teigland if ((char *)cur + cur_rec_len > bh->b_data + bh->b_size)
698b3b94faaSDavid Teigland gfs2_consist_inode(dip);
699b3b94faaSDavid Teigland
700b3b94faaSDavid Teigland prev_rec_len += cur_rec_len;
701fc69d0d3SSteven Whitehouse prev->de_rec_len = cpu_to_be16(prev_rec_len);
702b3b94faaSDavid Teigland }
703b3b94faaSDavid Teigland
70434017472SBenjamin Marzinski
do_init_dirent(struct inode * inode,struct gfs2_dirent * dent,const struct qstr * name,struct buffer_head * bh,unsigned offset)70534017472SBenjamin Marzinski static struct gfs2_dirent *do_init_dirent(struct inode *inode,
706c752666cSSteven Whitehouse struct gfs2_dirent *dent,
707c752666cSSteven Whitehouse const struct qstr *name,
70834017472SBenjamin Marzinski struct buffer_head *bh,
70934017472SBenjamin Marzinski unsigned offset)
710b3b94faaSDavid Teigland {
711feaa7bbaSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode);
712c752666cSSteven Whitehouse struct gfs2_dirent *ndent;
71334017472SBenjamin Marzinski unsigned totlen;
714b3b94faaSDavid Teigland
715c752666cSSteven Whitehouse totlen = be16_to_cpu(dent->de_rec_len);
716c752666cSSteven Whitehouse BUG_ON(offset + name->len > totlen);
717350a9b0aSSteven Whitehouse gfs2_trans_add_meta(ip->i_gl, bh);
718c752666cSSteven Whitehouse ndent = (struct gfs2_dirent *)((char *)dent + offset);
719c752666cSSteven Whitehouse dent->de_rec_len = cpu_to_be16(offset);
720c752666cSSteven Whitehouse gfs2_qstr2dirent(name, totlen - offset, ndent);
721c752666cSSteven Whitehouse return ndent;
722b3b94faaSDavid Teigland }
723b3b94faaSDavid Teigland
72434017472SBenjamin Marzinski
72534017472SBenjamin Marzinski /*
72634017472SBenjamin Marzinski * Takes a dent from which to grab space as an argument. Returns the
72734017472SBenjamin Marzinski * newly created dent.
72834017472SBenjamin Marzinski */
gfs2_init_dirent(struct inode * inode,struct gfs2_dirent * dent,const struct qstr * name,struct buffer_head * bh)72934017472SBenjamin Marzinski static struct gfs2_dirent *gfs2_init_dirent(struct inode *inode,
73034017472SBenjamin Marzinski struct gfs2_dirent *dent,
73134017472SBenjamin Marzinski const struct qstr *name,
73234017472SBenjamin Marzinski struct buffer_head *bh)
73334017472SBenjamin Marzinski {
73434017472SBenjamin Marzinski unsigned offset = 0;
73534017472SBenjamin Marzinski
73634017472SBenjamin Marzinski if (!gfs2_dirent_sentinel(dent))
73734017472SBenjamin Marzinski offset = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len));
73834017472SBenjamin Marzinski return do_init_dirent(inode, dent, name, bh, offset);
73934017472SBenjamin Marzinski }
74034017472SBenjamin Marzinski
gfs2_dirent_split_alloc(struct inode * inode,struct buffer_head * bh,const struct qstr * name,void * ptr)74134017472SBenjamin Marzinski static struct gfs2_dirent *gfs2_dirent_split_alloc(struct inode *inode,
742c752666cSSteven Whitehouse struct buffer_head *bh,
74334017472SBenjamin Marzinski const struct qstr *name,
74434017472SBenjamin Marzinski void *ptr)
745b3b94faaSDavid Teigland {
746b3b94faaSDavid Teigland struct gfs2_dirent *dent;
74771b86f56SSteven Whitehouse dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
74834017472SBenjamin Marzinski gfs2_dirent_find_offset, name, ptr);
74915a798f7SKefeng Wang if (IS_ERR_OR_NULL(dent))
750c752666cSSteven Whitehouse return dent;
75134017472SBenjamin Marzinski return do_init_dirent(inode, dent, name, bh,
75234017472SBenjamin Marzinski (unsigned)(ptr - (void *)dent));
753b3b94faaSDavid Teigland }
754b3b94faaSDavid Teigland
get_leaf(struct gfs2_inode * dip,u64 leaf_no,struct buffer_head ** bhp)755cd915493SSteven Whitehouse static int get_leaf(struct gfs2_inode *dip, u64 leaf_no,
756b3b94faaSDavid Teigland struct buffer_head **bhp)
757b3b94faaSDavid Teigland {
758b3b94faaSDavid Teigland int error;
759b3b94faaSDavid Teigland
760c8d57703SAndreas Gruenbacher error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_WAIT, 0, bhp);
761feaa7bbaSSteven Whitehouse if (!error && gfs2_metatype_check(GFS2_SB(&dip->i_inode), *bhp, GFS2_METATYPE_LF)) {
762d77d1b58SJoe Perches /* pr_info("block num=%llu\n", leaf_no); */
763b3b94faaSDavid Teigland error = -EIO;
764feaa7bbaSSteven Whitehouse }
765b3b94faaSDavid Teigland
766b3b94faaSDavid Teigland return error;
767b3b94faaSDavid Teigland }
768b3b94faaSDavid Teigland
769b3b94faaSDavid Teigland /**
770b3b94faaSDavid Teigland * get_leaf_nr - Get a leaf number associated with the index
771b3b94faaSDavid Teigland * @dip: The GFS2 inode
7723ae3a7d6SBob Peterson * @index: hash table index of the targeted leaf
7733ae3a7d6SBob Peterson * @leaf_out: Resulting leaf block number
774b3b94faaSDavid Teigland *
775b3b94faaSDavid Teigland * Returns: 0 on success, error code otherwise
776b3b94faaSDavid Teigland */
777b3b94faaSDavid Teigland
get_leaf_nr(struct gfs2_inode * dip,u32 index,u64 * leaf_out)7783ae3a7d6SBob Peterson static int get_leaf_nr(struct gfs2_inode *dip, u32 index, u64 *leaf_out)
779b3b94faaSDavid Teigland {
78017d539f0SSteven Whitehouse __be64 *hash;
781287980e4SArnd Bergmann int error;
782b3b94faaSDavid Teigland
78317d539f0SSteven Whitehouse hash = gfs2_dir_get_hash_table(dip);
784287980e4SArnd Bergmann error = PTR_ERR_OR_ZERO(hash);
785287980e4SArnd Bergmann
786287980e4SArnd Bergmann if (!error)
78717d539f0SSteven Whitehouse *leaf_out = be64_to_cpu(*(hash + index));
788287980e4SArnd Bergmann
789287980e4SArnd Bergmann return error;
790b3b94faaSDavid Teigland }
791b3b94faaSDavid Teigland
get_first_leaf(struct gfs2_inode * dip,u32 index,struct buffer_head ** bh_out)792cd915493SSteven Whitehouse static int get_first_leaf(struct gfs2_inode *dip, u32 index,
793b3b94faaSDavid Teigland struct buffer_head **bh_out)
794b3b94faaSDavid Teigland {
795cd915493SSteven Whitehouse u64 leaf_no;
796b3b94faaSDavid Teigland int error;
797b3b94faaSDavid Teigland
798b3b94faaSDavid Teigland error = get_leaf_nr(dip, index, &leaf_no);
799287980e4SArnd Bergmann if (!error)
800b3b94faaSDavid Teigland error = get_leaf(dip, leaf_no, bh_out);
801b3b94faaSDavid Teigland
802b3b94faaSDavid Teigland return error;
803b3b94faaSDavid Teigland }
804b3b94faaSDavid Teigland
gfs2_dirent_search(struct inode * inode,const struct qstr * name,gfs2_dscan_t scan,struct buffer_head ** pbh)805c752666cSSteven Whitehouse static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
806c752666cSSteven Whitehouse const struct qstr *name,
807c752666cSSteven Whitehouse gfs2_dscan_t scan,
808c752666cSSteven Whitehouse struct buffer_head **pbh)
809b3b94faaSDavid Teigland {
810c752666cSSteven Whitehouse struct buffer_head *bh;
811c752666cSSteven Whitehouse struct gfs2_dirent *dent;
812feaa7bbaSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode);
813c752666cSSteven Whitehouse int error;
814c752666cSSteven Whitehouse
815383f01fbSSteven Whitehouse if (ip->i_diskflags & GFS2_DIF_EXHASH) {
816b3b94faaSDavid Teigland struct gfs2_leaf *leaf;
81747a9a527SFabian Frederick unsigned int hsize = BIT(ip->i_depth);
81847a9a527SFabian Frederick unsigned int index;
819c752666cSSteven Whitehouse u64 ln;
820a2e0f799SSteven Whitehouse if (hsize * sizeof(u64) != i_size_read(inode)) {
821c752666cSSteven Whitehouse gfs2_consist_inode(ip);
822c752666cSSteven Whitehouse return ERR_PTR(-EIO);
823b3b94faaSDavid Teigland }
824b3b94faaSDavid Teigland
8259a004508SSteven Whitehouse index = name->hash >> (32 - ip->i_depth);
826c752666cSSteven Whitehouse error = get_first_leaf(ip, index, &bh);
827b3b94faaSDavid Teigland if (error)
828c752666cSSteven Whitehouse return ERR_PTR(error);
829b3b94faaSDavid Teigland do {
830c752666cSSteven Whitehouse dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
83171b86f56SSteven Whitehouse scan, name, NULL);
832c752666cSSteven Whitehouse if (dent)
833c752666cSSteven Whitehouse goto got_dent;
834c752666cSSteven Whitehouse leaf = (struct gfs2_leaf *)bh->b_data;
835c752666cSSteven Whitehouse ln = be64_to_cpu(leaf->lf_next);
836f4154ea0SSteven Whitehouse brelse(bh);
837c752666cSSteven Whitehouse if (!ln)
838b3b94faaSDavid Teigland break;
839feaa7bbaSSteven Whitehouse
840c752666cSSteven Whitehouse error = get_leaf(ip, ln, &bh);
841c752666cSSteven Whitehouse } while(!error);
842b3b94faaSDavid Teigland
843c752666cSSteven Whitehouse return error ? ERR_PTR(error) : NULL;
844b3b94faaSDavid Teigland }
845b3b94faaSDavid Teigland
846feaa7bbaSSteven Whitehouse
847c752666cSSteven Whitehouse error = gfs2_meta_inode_buffer(ip, &bh);
848c752666cSSteven Whitehouse if (error)
849c752666cSSteven Whitehouse return ERR_PTR(error);
85071b86f56SSteven Whitehouse dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, scan, name, NULL);
851c752666cSSteven Whitehouse got_dent:
85215a798f7SKefeng Wang if (IS_ERR_OR_NULL(dent)) {
853ed386507SSteven Whitehouse brelse(bh);
854ed386507SSteven Whitehouse bh = NULL;
855ed386507SSteven Whitehouse }
856c752666cSSteven Whitehouse *pbh = bh;
857c752666cSSteven Whitehouse return dent;
858b3b94faaSDavid Teigland }
859b3b94faaSDavid Teigland
new_leaf(struct inode * inode,struct buffer_head ** pbh,u16 depth)860c752666cSSteven Whitehouse static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, u16 depth)
861c752666cSSteven Whitehouse {
862feaa7bbaSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode);
863b45e41d7SSteven Whitehouse unsigned int n = 1;
86409010978SSteven Whitehouse u64 bn;
86509010978SSteven Whitehouse int error;
86609010978SSteven Whitehouse struct buffer_head *bh;
867c752666cSSteven Whitehouse struct gfs2_leaf *leaf;
868c752666cSSteven Whitehouse struct gfs2_dirent *dent;
86995582b00SDeepa Dinamani struct timespec64 tv = current_time(inode);
87009010978SSteven Whitehouse
871*d92445b2SAndreas Gruenbacher error = gfs2_alloc_blocks(ip, &bn, &n, 0);
87209010978SSteven Whitehouse if (error)
87309010978SSteven Whitehouse return NULL;
87409010978SSteven Whitehouse bh = gfs2_meta_new(ip->i_gl, bn);
875c752666cSSteven Whitehouse if (!bh)
876c752666cSSteven Whitehouse return NULL;
87709010978SSteven Whitehouse
878fbb27873SAndreas Gruenbacher gfs2_trans_remove_revoke(GFS2_SB(inode), bn, 1);
879350a9b0aSSteven Whitehouse gfs2_trans_add_meta(ip->i_gl, bh);
880c752666cSSteven Whitehouse gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF);
881c752666cSSteven Whitehouse leaf = (struct gfs2_leaf *)bh->b_data;
882c752666cSSteven Whitehouse leaf->lf_depth = cpu_to_be16(depth);
8832bdbc5d7SSteven Whitehouse leaf->lf_entries = 0;
884a2d7d021SAl Viro leaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE);
8852bdbc5d7SSteven Whitehouse leaf->lf_next = 0;
88601bcb0deSSteven Whitehouse leaf->lf_inode = cpu_to_be64(ip->i_no_addr);
88701bcb0deSSteven Whitehouse leaf->lf_dist = cpu_to_be32(1);
88801bcb0deSSteven Whitehouse leaf->lf_nsec = cpu_to_be32(tv.tv_nsec);
88901bcb0deSSteven Whitehouse leaf->lf_sec = cpu_to_be64(tv.tv_sec);
89001bcb0deSSteven Whitehouse memset(leaf->lf_reserved2, 0, sizeof(leaf->lf_reserved2));
891c752666cSSteven Whitehouse dent = (struct gfs2_dirent *)(leaf+1);
892cdf01226SDavid Howells gfs2_qstr2dirent(&empty_name, bh->b_size - sizeof(struct gfs2_leaf), dent);
893c752666cSSteven Whitehouse *pbh = bh;
894c752666cSSteven Whitehouse return leaf;
895b3b94faaSDavid Teigland }
896b3b94faaSDavid Teigland
897b3b94faaSDavid Teigland /**
898b3b94faaSDavid Teigland * dir_make_exhash - Convert a stuffed directory into an ExHash directory
8993ae3a7d6SBob Peterson * @inode: The directory inode to be converted to exhash
900b3b94faaSDavid Teigland *
901b3b94faaSDavid Teigland * Returns: 0 on success, error code otherwise
902b3b94faaSDavid Teigland */
903b3b94faaSDavid Teigland
dir_make_exhash(struct inode * inode)904c752666cSSteven Whitehouse static int dir_make_exhash(struct inode *inode)
905b3b94faaSDavid Teigland {
906feaa7bbaSSteven Whitehouse struct gfs2_inode *dip = GFS2_I(inode);
907feaa7bbaSSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(inode);
908b3b94faaSDavid Teigland struct gfs2_dirent *dent;
909c752666cSSteven Whitehouse struct qstr args;
910b3b94faaSDavid Teigland struct buffer_head *bh, *dibh;
911b3b94faaSDavid Teigland struct gfs2_leaf *leaf;
912b3b94faaSDavid Teigland int y;
913cd915493SSteven Whitehouse u32 x;
914b44b84d7SAl Viro __be64 *lp;
915b44b84d7SAl Viro u64 bn;
916b3b94faaSDavid Teigland int error;
917b3b94faaSDavid Teigland
918b3b94faaSDavid Teigland error = gfs2_meta_inode_buffer(dip, &dibh);
919b3b94faaSDavid Teigland if (error)
920b3b94faaSDavid Teigland return error;
921b3b94faaSDavid Teigland
922b3b94faaSDavid Teigland /* Turn over a new leaf */
923b3b94faaSDavid Teigland
924c752666cSSteven Whitehouse leaf = new_leaf(inode, &bh, 0);
925c752666cSSteven Whitehouse if (!leaf)
926c752666cSSteven Whitehouse return -ENOSPC;
927c752666cSSteven Whitehouse bn = bh->b_blocknr;
928b3b94faaSDavid Teigland
92947a9a527SFabian Frederick gfs2_assert(sdp, dip->i_entries < BIT(16));
930ad6203f2SSteven Whitehouse leaf->lf_entries = cpu_to_be16(dip->i_entries);
931b3b94faaSDavid Teigland
932b3b94faaSDavid Teigland /* Copy dirents */
933b3b94faaSDavid Teigland
934b3b94faaSDavid Teigland gfs2_buffer_copy_tail(bh, sizeof(struct gfs2_leaf), dibh,
935b3b94faaSDavid Teigland sizeof(struct gfs2_dinode));
936b3b94faaSDavid Teigland
937b3b94faaSDavid Teigland /* Find last entry */
938b3b94faaSDavid Teigland
939b3b94faaSDavid Teigland x = 0;
940c752666cSSteven Whitehouse args.len = bh->b_size - sizeof(struct gfs2_dinode) +
941c752666cSSteven Whitehouse sizeof(struct gfs2_leaf);
942c752666cSSteven Whitehouse args.name = bh->b_data;
943feaa7bbaSSteven Whitehouse dent = gfs2_dirent_scan(&dip->i_inode, bh->b_data, bh->b_size,
94471b86f56SSteven Whitehouse gfs2_dirent_last, &args, NULL);
945c752666cSSteven Whitehouse if (!dent) {
946c752666cSSteven Whitehouse brelse(bh);
947c752666cSSteven Whitehouse brelse(dibh);
948c752666cSSteven Whitehouse return -EIO;
949b3b94faaSDavid Teigland }
950c752666cSSteven Whitehouse if (IS_ERR(dent)) {
951c752666cSSteven Whitehouse brelse(bh);
952c752666cSSteven Whitehouse brelse(dibh);
953c752666cSSteven Whitehouse return PTR_ERR(dent);
954c752666cSSteven Whitehouse }
955b3b94faaSDavid Teigland
956b3b94faaSDavid Teigland /* Adjust the last dirent's record length
957b3b94faaSDavid Teigland (Remember that dent still points to the last entry.) */
958b3b94faaSDavid Teigland
9594dd651adSSteven Whitehouse dent->de_rec_len = cpu_to_be16(be16_to_cpu(dent->de_rec_len) +
960b3b94faaSDavid Teigland sizeof(struct gfs2_dinode) -
9614dd651adSSteven Whitehouse sizeof(struct gfs2_leaf));
962b3b94faaSDavid Teigland
963b3b94faaSDavid Teigland brelse(bh);
964b3b94faaSDavid Teigland
965b3b94faaSDavid Teigland /* We're done with the new leaf block, now setup the new
966b3b94faaSDavid Teigland hash table. */
967b3b94faaSDavid Teigland
968350a9b0aSSteven Whitehouse gfs2_trans_add_meta(dip->i_gl, dibh);
969b3b94faaSDavid Teigland gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
970b3b94faaSDavid Teigland
971b44b84d7SAl Viro lp = (__be64 *)(dibh->b_data + sizeof(struct gfs2_dinode));
972b3b94faaSDavid Teigland
973b3b94faaSDavid Teigland for (x = sdp->sd_hash_ptrs; x--; lp++)
974b3b94faaSDavid Teigland *lp = cpu_to_be64(bn);
975b3b94faaSDavid Teigland
976a2e0f799SSteven Whitehouse i_size_write(inode, sdp->sd_sb.sb_bsize / 2);
97777658aadSSteven Whitehouse gfs2_add_inode_blocks(&dip->i_inode, 1);
978383f01fbSSteven Whitehouse dip->i_diskflags |= GFS2_DIF_EXHASH;
979b3b94faaSDavid Teigland
980b3b94faaSDavid Teigland for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ;
9819a004508SSteven Whitehouse dip->i_depth = y;
982b3b94faaSDavid Teigland
983539e5d6bSSteven Whitehouse gfs2_dinode_out(dip, dibh->b_data);
984b3b94faaSDavid Teigland
985b3b94faaSDavid Teigland brelse(dibh);
986b3b94faaSDavid Teigland
987b3b94faaSDavid Teigland return 0;
988b3b94faaSDavid Teigland }
989b3b94faaSDavid Teigland
990b3b94faaSDavid Teigland /**
991b3b94faaSDavid Teigland * dir_split_leaf - Split a leaf block into two
9923ae3a7d6SBob Peterson * @inode: The directory inode to be split
9933ae3a7d6SBob Peterson * @name: name of the dirent we're trying to insert
994b3b94faaSDavid Teigland *
995b3b94faaSDavid Teigland * Returns: 0 on success, error code on failure
996b3b94faaSDavid Teigland */
997b3b94faaSDavid Teigland
dir_split_leaf(struct inode * inode,const struct qstr * name)998c752666cSSteven Whitehouse static int dir_split_leaf(struct inode *inode, const struct qstr *name)
999b3b94faaSDavid Teigland {
1000feaa7bbaSSteven Whitehouse struct gfs2_inode *dip = GFS2_I(inode);
1001b3b94faaSDavid Teigland struct buffer_head *nbh, *obh, *dibh;
1002b3b94faaSDavid Teigland struct gfs2_leaf *nleaf, *oleaf;
10034da3c646SSteven Whitehouse struct gfs2_dirent *dent = NULL, *prev = NULL, *next = NULL, *new;
1004cd915493SSteven Whitehouse u32 start, len, half_len, divider;
1005b44b84d7SAl Viro u64 bn, leaf_no;
1006b44b84d7SAl Viro __be64 *lp;
1007cd915493SSteven Whitehouse u32 index;
1008d1b0cb93SColin Ian King int x;
1009b3b94faaSDavid Teigland int error;
1010b3b94faaSDavid Teigland
10119a004508SSteven Whitehouse index = name->hash >> (32 - dip->i_depth);
1012c752666cSSteven Whitehouse error = get_leaf_nr(dip, index, &leaf_no);
1013287980e4SArnd Bergmann if (error)
1014c752666cSSteven Whitehouse return error;
1015b3b94faaSDavid Teigland
1016b3b94faaSDavid Teigland /* Get the old leaf block */
1017b3b94faaSDavid Teigland error = get_leaf(dip, leaf_no, &obh);
1018b3b94faaSDavid Teigland if (error)
1019e90deff5SSteven Whitehouse return error;
1020e90deff5SSteven Whitehouse
1021e90deff5SSteven Whitehouse oleaf = (struct gfs2_leaf *)obh->b_data;
10229a004508SSteven Whitehouse if (dip->i_depth == be16_to_cpu(oleaf->lf_depth)) {
1023e90deff5SSteven Whitehouse brelse(obh);
1024e90deff5SSteven Whitehouse return 1; /* can't split */
1025e90deff5SSteven Whitehouse }
1026b3b94faaSDavid Teigland
1027350a9b0aSSteven Whitehouse gfs2_trans_add_meta(dip->i_gl, obh);
1028b3b94faaSDavid Teigland
1029c752666cSSteven Whitehouse nleaf = new_leaf(inode, &nbh, be16_to_cpu(oleaf->lf_depth) + 1);
1030c752666cSSteven Whitehouse if (!nleaf) {
1031c752666cSSteven Whitehouse brelse(obh);
1032c752666cSSteven Whitehouse return -ENOSPC;
1033c752666cSSteven Whitehouse }
1034c752666cSSteven Whitehouse bn = nbh->b_blocknr;
1035b3b94faaSDavid Teigland
1036c752666cSSteven Whitehouse /* Compute the start and len of leaf pointers in the hash table. */
103747a9a527SFabian Frederick len = BIT(dip->i_depth - be16_to_cpu(oleaf->lf_depth));
1038b3b94faaSDavid Teigland half_len = len >> 1;
1039b3b94faaSDavid Teigland if (!half_len) {
1040e54c78a2SBob Peterson fs_warn(GFS2_SB(inode), "i_depth %u lf_depth %u index %u\n",
1041d77d1b58SJoe Perches dip->i_depth, be16_to_cpu(oleaf->lf_depth), index);
1042b3b94faaSDavid Teigland gfs2_consist_inode(dip);
1043b3b94faaSDavid Teigland error = -EIO;
1044b3b94faaSDavid Teigland goto fail_brelse;
1045b3b94faaSDavid Teigland }
1046b3b94faaSDavid Teigland
1047b3b94faaSDavid Teigland start = (index & ~(len - 1));
1048b3b94faaSDavid Teigland
1049b3b94faaSDavid Teigland /* Change the pointers.
1050b3b94faaSDavid Teigland Don't bother distinguishing stuffed from non-stuffed.
1051b3b94faaSDavid Teigland This code is complicated enough already. */
10526da2ec56SKees Cook lp = kmalloc_array(half_len, sizeof(__be64), GFP_NOFS);
10534244b52eSDavid Rientjes if (!lp) {
10544244b52eSDavid Rientjes error = -ENOMEM;
10554244b52eSDavid Rientjes goto fail_brelse;
10564244b52eSDavid Rientjes }
10574244b52eSDavid Rientjes
1058b3b94faaSDavid Teigland /* Change the pointers */
1059b3b94faaSDavid Teigland for (x = 0; x < half_len; x++)
1060b3b94faaSDavid Teigland lp[x] = cpu_to_be64(bn);
1061b3b94faaSDavid Teigland
106217d539f0SSteven Whitehouse gfs2_dir_hash_inval(dip);
106317d539f0SSteven Whitehouse
1064cd915493SSteven Whitehouse error = gfs2_dir_write_data(dip, (char *)lp, start * sizeof(u64),
1065cd915493SSteven Whitehouse half_len * sizeof(u64));
1066cd915493SSteven Whitehouse if (error != half_len * sizeof(u64)) {
1067b3b94faaSDavid Teigland if (error >= 0)
1068b3b94faaSDavid Teigland error = -EIO;
1069b3b94faaSDavid Teigland goto fail_lpfree;
1070b3b94faaSDavid Teigland }
1071b3b94faaSDavid Teigland
1072b3b94faaSDavid Teigland kfree(lp);
1073b3b94faaSDavid Teigland
1074b3b94faaSDavid Teigland /* Compute the divider */
10759a004508SSteven Whitehouse divider = (start + half_len) << (32 - dip->i_depth);
1076b3b94faaSDavid Teigland
1077b3b94faaSDavid Teigland /* Copy the entries */
10781579343aSSteven Whitehouse dent = (struct gfs2_dirent *)(obh->b_data + sizeof(struct gfs2_leaf));
1079b3b94faaSDavid Teigland
1080b3b94faaSDavid Teigland do {
1081b3b94faaSDavid Teigland next = dent;
1082b3b94faaSDavid Teigland if (dirent_next(dip, obh, &next))
1083b3b94faaSDavid Teigland next = NULL;
1084b3b94faaSDavid Teigland
10855e7d65cdSSteven Whitehouse if (!gfs2_dirent_sentinel(dent) &&
1086b3b94faaSDavid Teigland be32_to_cpu(dent->de_hash) < divider) {
1087c752666cSSteven Whitehouse struct qstr str;
108834017472SBenjamin Marzinski void *ptr = ((char *)dent - obh->b_data) + nbh->b_data;
1089c752666cSSteven Whitehouse str.name = (char*)(dent+1);
1090c752666cSSteven Whitehouse str.len = be16_to_cpu(dent->de_name_len);
1091c752666cSSteven Whitehouse str.hash = be32_to_cpu(dent->de_hash);
109234017472SBenjamin Marzinski new = gfs2_dirent_split_alloc(inode, nbh, &str, ptr);
1093c752666cSSteven Whitehouse if (IS_ERR(new)) {
1094c752666cSSteven Whitehouse error = PTR_ERR(new);
1095c752666cSSteven Whitehouse break;
1096c752666cSSteven Whitehouse }
1097b3b94faaSDavid Teigland
1098b3b94faaSDavid Teigland new->de_inum = dent->de_inum; /* No endian worries */
1099b3b94faaSDavid Teigland new->de_type = dent->de_type; /* No endian worries */
1100bb16b342SMarcin Slusarz be16_add_cpu(&nleaf->lf_entries, 1);
1101b3b94faaSDavid Teigland
1102b3b94faaSDavid Teigland dirent_del(dip, obh, prev, dent);
1103b3b94faaSDavid Teigland
1104b3b94faaSDavid Teigland if (!oleaf->lf_entries)
1105b3b94faaSDavid Teigland gfs2_consist_inode(dip);
1106bb16b342SMarcin Slusarz be16_add_cpu(&oleaf->lf_entries, -1);
1107b3b94faaSDavid Teigland
1108b3b94faaSDavid Teigland if (!prev)
1109b3b94faaSDavid Teigland prev = dent;
1110c752666cSSteven Whitehouse } else {
1111b3b94faaSDavid Teigland prev = dent;
1112c752666cSSteven Whitehouse }
1113b3b94faaSDavid Teigland dent = next;
1114c752666cSSteven Whitehouse } while (dent);
1115b3b94faaSDavid Teigland
1116c752666cSSteven Whitehouse oleaf->lf_depth = nleaf->lf_depth;
1117b3b94faaSDavid Teigland
1118b3b94faaSDavid Teigland error = gfs2_meta_inode_buffer(dip, &dibh);
1119feaa7bbaSSteven Whitehouse if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) {
1120350a9b0aSSteven Whitehouse gfs2_trans_add_meta(dip->i_gl, dibh);
112177658aadSSteven Whitehouse gfs2_add_inode_blocks(&dip->i_inode, 1);
1122539e5d6bSSteven Whitehouse gfs2_dinode_out(dip, dibh->b_data);
1123b3b94faaSDavid Teigland brelse(dibh);
1124b3b94faaSDavid Teigland }
1125b3b94faaSDavid Teigland
1126b3b94faaSDavid Teigland brelse(obh);
1127b3b94faaSDavid Teigland brelse(nbh);
1128b3b94faaSDavid Teigland
1129b3b94faaSDavid Teigland return error;
1130b3b94faaSDavid Teigland
1131b3b94faaSDavid Teigland fail_lpfree:
1132b3b94faaSDavid Teigland kfree(lp);
1133b3b94faaSDavid Teigland
1134b3b94faaSDavid Teigland fail_brelse:
1135b3b94faaSDavid Teigland brelse(obh);
1136b3b94faaSDavid Teigland brelse(nbh);
1137b3b94faaSDavid Teigland return error;
1138b3b94faaSDavid Teigland }
1139b3b94faaSDavid Teigland
1140b3b94faaSDavid Teigland /**
1141b3b94faaSDavid Teigland * dir_double_exhash - Double size of ExHash table
1142b3b94faaSDavid Teigland * @dip: The GFS2 dinode
1143b3b94faaSDavid Teigland *
1144b3b94faaSDavid Teigland * Returns: 0 on success, error code on failure
1145b3b94faaSDavid Teigland */
1146b3b94faaSDavid Teigland
dir_double_exhash(struct gfs2_inode * dip)1147b3b94faaSDavid Teigland static int dir_double_exhash(struct gfs2_inode *dip)
1148b3b94faaSDavid Teigland {
1149b3b94faaSDavid Teigland struct buffer_head *dibh;
1150cd915493SSteven Whitehouse u32 hsize;
115117d539f0SSteven Whitehouse u32 hsize_bytes;
115217d539f0SSteven Whitehouse __be64 *hc;
115317d539f0SSteven Whitehouse __be64 *hc2, *h;
1154b3b94faaSDavid Teigland int x;
1155b3b94faaSDavid Teigland int error = 0;
1156b3b94faaSDavid Teigland
115747a9a527SFabian Frederick hsize = BIT(dip->i_depth);
115817d539f0SSteven Whitehouse hsize_bytes = hsize * sizeof(__be64);
1159b3b94faaSDavid Teigland
116017d539f0SSteven Whitehouse hc = gfs2_dir_get_hash_table(dip);
116117d539f0SSteven Whitehouse if (IS_ERR(hc))
116217d539f0SSteven Whitehouse return PTR_ERR(hc);
1163b3b94faaSDavid Teigland
11646da2ec56SKees Cook hc2 = kmalloc_array(hsize_bytes, 2, GFP_NOFS | __GFP_NOWARN);
1165e8830d88SBob Peterson if (hc2 == NULL)
116688dca4caSChristoph Hellwig hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS);
1167e8830d88SBob Peterson
116817d539f0SSteven Whitehouse if (!hc2)
11694244b52eSDavid Rientjes return -ENOMEM;
1170b3b94faaSDavid Teigland
1171512cbf02SBob Peterson h = hc2;
1172b3b94faaSDavid Teigland error = gfs2_meta_inode_buffer(dip, &dibh);
117317d539f0SSteven Whitehouse if (error)
117417d539f0SSteven Whitehouse goto out_kfree;
117517d539f0SSteven Whitehouse
117617d539f0SSteven Whitehouse for (x = 0; x < hsize; x++) {
117717d539f0SSteven Whitehouse *h++ = *hc;
117817d539f0SSteven Whitehouse *h++ = *hc;
117917d539f0SSteven Whitehouse hc++;
118017d539f0SSteven Whitehouse }
118117d539f0SSteven Whitehouse
118217d539f0SSteven Whitehouse error = gfs2_dir_write_data(dip, (char *)hc2, 0, hsize_bytes * 2);
118317d539f0SSteven Whitehouse if (error != (hsize_bytes * 2))
118417d539f0SSteven Whitehouse goto fail;
118517d539f0SSteven Whitehouse
118617d539f0SSteven Whitehouse gfs2_dir_hash_inval(dip);
118717d539f0SSteven Whitehouse dip->i_hash_cache = hc2;
11889a004508SSteven Whitehouse dip->i_depth++;
1189539e5d6bSSteven Whitehouse gfs2_dinode_out(dip, dibh->b_data);
1190b3b94faaSDavid Teigland brelse(dibh);
119117d539f0SSteven Whitehouse return 0;
1192b3b94faaSDavid Teigland
1193b3b94faaSDavid Teigland fail:
119417d539f0SSteven Whitehouse /* Replace original hash table & size */
119517d539f0SSteven Whitehouse gfs2_dir_write_data(dip, (char *)hc, 0, hsize_bytes);
119617d539f0SSteven Whitehouse i_size_write(&dip->i_inode, hsize_bytes);
119717d539f0SSteven Whitehouse gfs2_dinode_out(dip, dibh->b_data);
119817d539f0SSteven Whitehouse brelse(dibh);
119917d539f0SSteven Whitehouse out_kfree:
12003cdcf63eSAl Viro kvfree(hc2);
1201b3b94faaSDavid Teigland return error;
1202b3b94faaSDavid Teigland }
1203b3b94faaSDavid Teigland
1204b3b94faaSDavid Teigland /**
1205b3b94faaSDavid Teigland * compare_dents - compare directory entries by hash value
1206b3b94faaSDavid Teigland * @a: first dent
1207b3b94faaSDavid Teigland * @b: second dent
1208b3b94faaSDavid Teigland *
1209b3b94faaSDavid Teigland * When comparing the hash entries of @a to @b:
1210b3b94faaSDavid Teigland * gt: returns 1
1211b3b94faaSDavid Teigland * lt: returns -1
1212b3b94faaSDavid Teigland * eq: returns 0
1213b3b94faaSDavid Teigland */
1214b3b94faaSDavid Teigland
compare_dents(const void * a,const void * b)1215b3b94faaSDavid Teigland static int compare_dents(const void *a, const void *b)
1216b3b94faaSDavid Teigland {
12172bdbc5d7SSteven Whitehouse const struct gfs2_dirent *dent_a, *dent_b;
1218cd915493SSteven Whitehouse u32 hash_a, hash_b;
1219b3b94faaSDavid Teigland int ret = 0;
1220b3b94faaSDavid Teigland
12212bdbc5d7SSteven Whitehouse dent_a = *(const struct gfs2_dirent **)a;
1222471f3db2SBenjamin Marzinski hash_a = dent_a->de_cookie;
1223b3b94faaSDavid Teigland
12242bdbc5d7SSteven Whitehouse dent_b = *(const struct gfs2_dirent **)b;
1225471f3db2SBenjamin Marzinski hash_b = dent_b->de_cookie;
1226b3b94faaSDavid Teigland
1227b3b94faaSDavid Teigland if (hash_a > hash_b)
1228b3b94faaSDavid Teigland ret = 1;
1229b3b94faaSDavid Teigland else if (hash_a < hash_b)
1230b3b94faaSDavid Teigland ret = -1;
1231b3b94faaSDavid Teigland else {
12324dd651adSSteven Whitehouse unsigned int len_a = be16_to_cpu(dent_a->de_name_len);
12334dd651adSSteven Whitehouse unsigned int len_b = be16_to_cpu(dent_b->de_name_len);
1234b3b94faaSDavid Teigland
1235b3b94faaSDavid Teigland if (len_a > len_b)
1236b3b94faaSDavid Teigland ret = 1;
1237b3b94faaSDavid Teigland else if (len_a < len_b)
1238b3b94faaSDavid Teigland ret = -1;
1239b3b94faaSDavid Teigland else
12402bdbc5d7SSteven Whitehouse ret = memcmp(dent_a + 1, dent_b + 1, len_a);
1241b3b94faaSDavid Teigland }
1242b3b94faaSDavid Teigland
1243b3b94faaSDavid Teigland return ret;
1244b3b94faaSDavid Teigland }
1245b3b94faaSDavid Teigland
1246b3b94faaSDavid Teigland /**
1247b3b94faaSDavid Teigland * do_filldir_main - read out directory entries
1248b3b94faaSDavid Teigland * @dip: The GFS2 inode
1249d81a8ef5SAl Viro * @ctx: what to feed the entries to
1250b3b94faaSDavid Teigland * @darr: an array of struct gfs2_dirent pointers to read
1251b3b94faaSDavid Teigland * @entries: the number of entries in darr
12523ae3a7d6SBob Peterson * @sort_start: index of the directory array to start our sort
1253b3b94faaSDavid Teigland * @copied: pointer to int that's non-zero if a entry has been copied out
1254b3b94faaSDavid Teigland *
1255b3b94faaSDavid Teigland * Jump through some hoops to make sure that if there are hash collsions,
1256b3b94faaSDavid Teigland * they are read out at the beginning of a buffer. We want to minimize
1257b3b94faaSDavid Teigland * the possibility that they will fall into different readdir buffers or
1258b3b94faaSDavid Teigland * that someone will want to seek to that location.
1259b3b94faaSDavid Teigland *
1260d81a8ef5SAl Viro * Returns: errno, >0 if the actor tells you to stop
1261b3b94faaSDavid Teigland */
1262b3b94faaSDavid Teigland
do_filldir_main(struct gfs2_inode * dip,struct dir_context * ctx,struct gfs2_dirent ** darr,u32 entries,u32 sort_start,int * copied)1263d81a8ef5SAl Viro static int do_filldir_main(struct gfs2_inode *dip, struct dir_context *ctx,
1264471f3db2SBenjamin Marzinski struct gfs2_dirent **darr, u32 entries,
1265471f3db2SBenjamin Marzinski u32 sort_start, int *copied)
1266b3b94faaSDavid Teigland {
126771b86f56SSteven Whitehouse const struct gfs2_dirent *dent, *dent_next;
1268cd915493SSteven Whitehouse u64 off, off_next;
1269b3b94faaSDavid Teigland unsigned int x, y;
1270b3b94faaSDavid Teigland int run = 0;
1271b3b94faaSDavid Teigland
1272471f3db2SBenjamin Marzinski if (sort_start < entries)
1273471f3db2SBenjamin Marzinski sort(&darr[sort_start], entries - sort_start,
1274471f3db2SBenjamin Marzinski sizeof(struct gfs2_dirent *), compare_dents, NULL);
1275b3b94faaSDavid Teigland
1276b3b94faaSDavid Teigland dent_next = darr[0];
1277471f3db2SBenjamin Marzinski off_next = dent_next->de_cookie;
1278b3b94faaSDavid Teigland
1279b3b94faaSDavid Teigland for (x = 0, y = 1; x < entries; x++, y++) {
1280b3b94faaSDavid Teigland dent = dent_next;
1281b3b94faaSDavid Teigland off = off_next;
1282b3b94faaSDavid Teigland
1283b3b94faaSDavid Teigland if (y < entries) {
1284b3b94faaSDavid Teigland dent_next = darr[y];
1285471f3db2SBenjamin Marzinski off_next = dent_next->de_cookie;
1286b3b94faaSDavid Teigland
1287d81a8ef5SAl Viro if (off < ctx->pos)
1288b3b94faaSDavid Teigland continue;
1289d81a8ef5SAl Viro ctx->pos = off;
1290b3b94faaSDavid Teigland
1291b3b94faaSDavid Teigland if (off_next == off) {
1292b3b94faaSDavid Teigland if (*copied && !run)
1293b3b94faaSDavid Teigland return 1;
1294b3b94faaSDavid Teigland run = 1;
1295b3b94faaSDavid Teigland } else
1296b3b94faaSDavid Teigland run = 0;
1297b3b94faaSDavid Teigland } else {
1298d81a8ef5SAl Viro if (off < ctx->pos)
1299b3b94faaSDavid Teigland continue;
1300d81a8ef5SAl Viro ctx->pos = off;
1301b3b94faaSDavid Teigland }
1302b3b94faaSDavid Teigland
1303d81a8ef5SAl Viro if (!dir_emit(ctx, (const char *)(dent + 1),
13044dd651adSSteven Whitehouse be16_to_cpu(dent->de_name_len),
1305d81a8ef5SAl Viro be64_to_cpu(dent->de_inum.no_addr),
1306d81a8ef5SAl Viro be16_to_cpu(dent->de_type)))
1307b3b94faaSDavid Teigland return 1;
1308b3b94faaSDavid Teigland
1309b3b94faaSDavid Teigland *copied = 1;
1310b3b94faaSDavid Teigland }
1311b3b94faaSDavid Teigland
1312d81a8ef5SAl Viro /* Increment the ctx->pos by one, so the next time we come into the
1313b3b94faaSDavid Teigland do_filldir fxn, we get the next entry instead of the last one in the
1314b3b94faaSDavid Teigland current leaf */
1315b3b94faaSDavid Teigland
1316d81a8ef5SAl Viro ctx->pos++;
1317b3b94faaSDavid Teigland
1318b3b94faaSDavid Teigland return 0;
1319b3b94faaSDavid Teigland }
1320b3b94faaSDavid Teigland
gfs2_alloc_sort_buffer(unsigned size)1321d2a97a4eSSteven Whitehouse static void *gfs2_alloc_sort_buffer(unsigned size)
1322d2a97a4eSSteven Whitehouse {
1323d2a97a4eSSteven Whitehouse void *ptr = NULL;
1324d2a97a4eSSteven Whitehouse
1325d2a97a4eSSteven Whitehouse if (size < KMALLOC_MAX_SIZE)
1326d2a97a4eSSteven Whitehouse ptr = kmalloc(size, GFP_NOFS | __GFP_NOWARN);
1327d2a97a4eSSteven Whitehouse if (!ptr)
132888dca4caSChristoph Hellwig ptr = __vmalloc(size, GFP_NOFS);
1329d2a97a4eSSteven Whitehouse return ptr;
1330d2a97a4eSSteven Whitehouse }
1331d2a97a4eSSteven Whitehouse
1332471f3db2SBenjamin Marzinski
gfs2_set_cookies(struct gfs2_sbd * sdp,struct buffer_head * bh,unsigned leaf_nr,struct gfs2_dirent ** darr,unsigned entries)1333471f3db2SBenjamin Marzinski static int gfs2_set_cookies(struct gfs2_sbd *sdp, struct buffer_head *bh,
1334471f3db2SBenjamin Marzinski unsigned leaf_nr, struct gfs2_dirent **darr,
1335471f3db2SBenjamin Marzinski unsigned entries)
1336471f3db2SBenjamin Marzinski {
1337471f3db2SBenjamin Marzinski int sort_id = -1;
1338471f3db2SBenjamin Marzinski int i;
1339471f3db2SBenjamin Marzinski
1340471f3db2SBenjamin Marzinski for (i = 0; i < entries; i++) {
1341471f3db2SBenjamin Marzinski unsigned offset;
1342471f3db2SBenjamin Marzinski
1343471f3db2SBenjamin Marzinski darr[i]->de_cookie = be32_to_cpu(darr[i]->de_hash);
1344471f3db2SBenjamin Marzinski darr[i]->de_cookie = gfs2_disk_hash2offset(darr[i]->de_cookie);
1345471f3db2SBenjamin Marzinski
1346471f3db2SBenjamin Marzinski if (!sdp->sd_args.ar_loccookie)
1347471f3db2SBenjamin Marzinski continue;
1348471f3db2SBenjamin Marzinski offset = (char *)(darr[i]) -
1349e54c78a2SBob Peterson (bh->b_data + gfs2_dirent_offset(sdp, bh->b_data));
1350471f3db2SBenjamin Marzinski offset /= GFS2_MIN_DIRENT_SIZE;
1351471f3db2SBenjamin Marzinski offset += leaf_nr * sdp->sd_max_dents_per_leaf;
1352471f3db2SBenjamin Marzinski if (offset >= GFS2_USE_HASH_FLAG ||
1353471f3db2SBenjamin Marzinski leaf_nr >= GFS2_USE_HASH_FLAG) {
1354471f3db2SBenjamin Marzinski darr[i]->de_cookie |= GFS2_USE_HASH_FLAG;
1355471f3db2SBenjamin Marzinski if (sort_id < 0)
1356471f3db2SBenjamin Marzinski sort_id = i;
1357471f3db2SBenjamin Marzinski continue;
1358471f3db2SBenjamin Marzinski }
1359471f3db2SBenjamin Marzinski darr[i]->de_cookie &= GFS2_HASH_INDEX_MASK;
1360471f3db2SBenjamin Marzinski darr[i]->de_cookie |= offset;
1361471f3db2SBenjamin Marzinski }
1362471f3db2SBenjamin Marzinski return sort_id;
1363471f3db2SBenjamin Marzinski }
1364471f3db2SBenjamin Marzinski
1365471f3db2SBenjamin Marzinski
gfs2_dir_read_leaf(struct inode * inode,struct dir_context * ctx,int * copied,unsigned * depth,u64 leaf_no)1366d81a8ef5SAl Viro static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
1367d81a8ef5SAl Viro int *copied, unsigned *depth,
13683699e3a4SSteven Whitehouse u64 leaf_no)
1369b3b94faaSDavid Teigland {
1370feaa7bbaSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode);
1371bdd19a22SSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(inode);
137271b86f56SSteven Whitehouse struct buffer_head *bh;
137371b86f56SSteven Whitehouse struct gfs2_leaf *lf;
1374bdd19a22SSteven Whitehouse unsigned entries = 0, entries2 = 0;
1375471f3db2SBenjamin Marzinski unsigned leaves = 0, leaf = 0, offset, sort_offset;
1376471f3db2SBenjamin Marzinski struct gfs2_dirent **darr, *dent;
137771b86f56SSteven Whitehouse struct dirent_gather g;
137871b86f56SSteven Whitehouse struct buffer_head **larr;
1379471f3db2SBenjamin Marzinski int error, i, need_sort = 0, sort_id;
138071b86f56SSteven Whitehouse u64 lfn = leaf_no;
1381b3b94faaSDavid Teigland
1382b3b94faaSDavid Teigland do {
138371b86f56SSteven Whitehouse error = get_leaf(ip, lfn, &bh);
1384b3b94faaSDavid Teigland if (error)
138571b86f56SSteven Whitehouse goto out;
138671b86f56SSteven Whitehouse lf = (struct gfs2_leaf *)bh->b_data;
138771b86f56SSteven Whitehouse if (leaves == 0)
138871b86f56SSteven Whitehouse *depth = be16_to_cpu(lf->lf_depth);
138971b86f56SSteven Whitehouse entries += be16_to_cpu(lf->lf_entries);
1390b3b94faaSDavid Teigland leaves++;
139171b86f56SSteven Whitehouse lfn = be64_to_cpu(lf->lf_next);
139271b86f56SSteven Whitehouse brelse(bh);
139371b86f56SSteven Whitehouse } while(lfn);
1394b3b94faaSDavid Teigland
1395471f3db2SBenjamin Marzinski if (*depth < GFS2_DIR_MAX_DEPTH || !sdp->sd_args.ar_loccookie) {
1396471f3db2SBenjamin Marzinski need_sort = 1;
1397471f3db2SBenjamin Marzinski sort_offset = 0;
1398471f3db2SBenjamin Marzinski }
1399471f3db2SBenjamin Marzinski
1400b3b94faaSDavid Teigland if (!entries)
1401b3b94faaSDavid Teigland return 0;
1402b3b94faaSDavid Teigland
140371b86f56SSteven Whitehouse error = -ENOMEM;
1404bdd19a22SSteven Whitehouse /*
1405bdd19a22SSteven Whitehouse * The extra 99 entries are not normally used, but are a buffer
1406bdd19a22SSteven Whitehouse * zone in case the number of entries in the leaf is corrupt.
1407bdd19a22SSteven Whitehouse * 99 is the maximum number of entries that can fit in a single
1408bdd19a22SSteven Whitehouse * leaf block.
1409bdd19a22SSteven Whitehouse */
1410d2a97a4eSSteven Whitehouse larr = gfs2_alloc_sort_buffer((leaves + entries + 99) * sizeof(void *));
1411b3b94faaSDavid Teigland if (!larr)
1412b3b94faaSDavid Teigland goto out;
1413471f3db2SBenjamin Marzinski darr = (struct gfs2_dirent **)(larr + leaves);
1414471f3db2SBenjamin Marzinski g.pdent = (const struct gfs2_dirent **)darr;
141571b86f56SSteven Whitehouse g.offset = 0;
141671b86f56SSteven Whitehouse lfn = leaf_no;
1417b3b94faaSDavid Teigland
141871b86f56SSteven Whitehouse do {
141971b86f56SSteven Whitehouse error = get_leaf(ip, lfn, &bh);
1420b3b94faaSDavid Teigland if (error)
1421d2a97a4eSSteven Whitehouse goto out_free;
142271b86f56SSteven Whitehouse lf = (struct gfs2_leaf *)bh->b_data;
142371b86f56SSteven Whitehouse lfn = be64_to_cpu(lf->lf_next);
142471b86f56SSteven Whitehouse if (lf->lf_entries) {
1425471f3db2SBenjamin Marzinski offset = g.offset;
1426bdd19a22SSteven Whitehouse entries2 += be16_to_cpu(lf->lf_entries);
142771b86f56SSteven Whitehouse dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
142871b86f56SSteven Whitehouse gfs2_dirent_gather, NULL, &g);
142971b86f56SSteven Whitehouse error = PTR_ERR(dent);
1430bdd19a22SSteven Whitehouse if (IS_ERR(dent))
1431d2a97a4eSSteven Whitehouse goto out_free;
1432bdd19a22SSteven Whitehouse if (entries2 != g.offset) {
1433f391a4eaSakpm@linux-foundation.org fs_warn(sdp, "Number of entries corrupt in dir "
1434f391a4eaSakpm@linux-foundation.org "leaf %llu, entries2 (%u) != "
1435f391a4eaSakpm@linux-foundation.org "g.offset (%u)\n",
1436f391a4eaSakpm@linux-foundation.org (unsigned long long)bh->b_blocknr,
1437f391a4eaSakpm@linux-foundation.org entries2, g.offset);
1438d87d62b7SBob Peterson gfs2_consist_inode(ip);
1439bdd19a22SSteven Whitehouse error = -EIO;
1440d2a97a4eSSteven Whitehouse goto out_free;
1441b3b94faaSDavid Teigland }
144271b86f56SSteven Whitehouse error = 0;
1443471f3db2SBenjamin Marzinski sort_id = gfs2_set_cookies(sdp, bh, leaf, &darr[offset],
1444471f3db2SBenjamin Marzinski be16_to_cpu(lf->lf_entries));
1445471f3db2SBenjamin Marzinski if (!need_sort && sort_id >= 0) {
1446471f3db2SBenjamin Marzinski need_sort = 1;
1447471f3db2SBenjamin Marzinski sort_offset = offset + sort_id;
1448471f3db2SBenjamin Marzinski }
144971b86f56SSteven Whitehouse larr[leaf++] = bh;
1450b3b94faaSDavid Teigland } else {
1451471f3db2SBenjamin Marzinski larr[leaf++] = NULL;
145271b86f56SSteven Whitehouse brelse(bh);
1453b3b94faaSDavid Teigland }
145471b86f56SSteven Whitehouse } while(lfn);
1455b3b94faaSDavid Teigland
1456bdd19a22SSteven Whitehouse BUG_ON(entries2 != entries);
1457471f3db2SBenjamin Marzinski error = do_filldir_main(ip, ctx, darr, entries, need_sort ?
1458471f3db2SBenjamin Marzinski sort_offset : entries, copied);
1459d2a97a4eSSteven Whitehouse out_free:
146071b86f56SSteven Whitehouse for(i = 0; i < leaf; i++)
146171b86f56SSteven Whitehouse brelse(larr[i]);
14623cdcf63eSAl Viro kvfree(larr);
146371b86f56SSteven Whitehouse out:
1464b3b94faaSDavid Teigland return error;
1465b3b94faaSDavid Teigland }
1466b3b94faaSDavid Teigland
146779c4c379SSteven Whitehouse /**
146879c4c379SSteven Whitehouse * gfs2_dir_readahead - Issue read-ahead requests for leaf blocks.
14693ae3a7d6SBob Peterson * @inode: the directory inode
14703ae3a7d6SBob Peterson * @hsize: hash table size
14713ae3a7d6SBob Peterson * @index: index into the hash table
14723ae3a7d6SBob Peterson * @f_ra: read-ahead parameters
1473dfe4d34bSBob Peterson *
1474dfe4d34bSBob Peterson * Note: we can't calculate each index like dir_e_read can because we don't
1475dfe4d34bSBob Peterson * have the leaf, and therefore we don't have the depth, and therefore we
1476dfe4d34bSBob Peterson * don't have the length. So we have to just read enough ahead to make up
147779c4c379SSteven Whitehouse * for the loss of information.
147879c4c379SSteven Whitehouse */
gfs2_dir_readahead(struct inode * inode,unsigned hsize,u32 index,struct file_ra_state * f_ra)1479dfe4d34bSBob Peterson static void gfs2_dir_readahead(struct inode *inode, unsigned hsize, u32 index,
1480dfe4d34bSBob Peterson struct file_ra_state *f_ra)
1481dfe4d34bSBob Peterson {
1482dfe4d34bSBob Peterson struct gfs2_inode *ip = GFS2_I(inode);
1483dfe4d34bSBob Peterson struct gfs2_glock *gl = ip->i_gl;
1484dfe4d34bSBob Peterson struct buffer_head *bh;
1485dfe4d34bSBob Peterson u64 blocknr = 0, last;
1486dfe4d34bSBob Peterson unsigned count;
1487dfe4d34bSBob Peterson
1488dfe4d34bSBob Peterson /* First check if we've already read-ahead for the whole range. */
148979c4c379SSteven Whitehouse if (index + MAX_RA_BLOCKS < f_ra->start)
1490dfe4d34bSBob Peterson return;
1491dfe4d34bSBob Peterson
1492dfe4d34bSBob Peterson f_ra->start = max((pgoff_t)index, f_ra->start);
1493dfe4d34bSBob Peterson for (count = 0; count < MAX_RA_BLOCKS; count++) {
1494dfe4d34bSBob Peterson if (f_ra->start >= hsize) /* if exceeded the hash table */
1495dfe4d34bSBob Peterson break;
1496dfe4d34bSBob Peterson
1497dfe4d34bSBob Peterson last = blocknr;
1498dfe4d34bSBob Peterson blocknr = be64_to_cpu(ip->i_hash_cache[f_ra->start]);
1499dfe4d34bSBob Peterson f_ra->start++;
1500dfe4d34bSBob Peterson if (blocknr == last)
1501dfe4d34bSBob Peterson continue;
1502dfe4d34bSBob Peterson
1503dfe4d34bSBob Peterson bh = gfs2_getbuf(gl, blocknr, 1);
1504dfe4d34bSBob Peterson if (trylock_buffer(bh)) {
1505dfe4d34bSBob Peterson if (buffer_uptodate(bh)) {
1506dfe4d34bSBob Peterson unlock_buffer(bh);
1507dfe4d34bSBob Peterson brelse(bh);
1508dfe4d34bSBob Peterson continue;
1509dfe4d34bSBob Peterson }
1510dfe4d34bSBob Peterson bh->b_end_io = end_buffer_read_sync;
15111420c4a5SBart Van Assche submit_bh(REQ_OP_READ | REQ_RAHEAD | REQ_META |
15121420c4a5SBart Van Assche REQ_PRIO, bh);
1513dfe4d34bSBob Peterson continue;
1514dfe4d34bSBob Peterson }
1515dfe4d34bSBob Peterson brelse(bh);
1516dfe4d34bSBob Peterson }
1517dfe4d34bSBob Peterson }
151817d539f0SSteven Whitehouse
1519b3b94faaSDavid Teigland /**
1520b3b94faaSDavid Teigland * dir_e_read - Reads the entries from a directory into a filldir buffer
15213ae3a7d6SBob Peterson * @inode: the directory inode
1522d81a8ef5SAl Viro * @ctx: actor to feed the entries to
15233ae3a7d6SBob Peterson * @f_ra: read-ahead parameters
1524b3b94faaSDavid Teigland *
1525b3b94faaSDavid Teigland * Returns: errno
1526b3b94faaSDavid Teigland */
1527b3b94faaSDavid Teigland
dir_e_read(struct inode * inode,struct dir_context * ctx,struct file_ra_state * f_ra)1528d81a8ef5SAl Viro static int dir_e_read(struct inode *inode, struct dir_context *ctx,
1529d81a8ef5SAl Viro struct file_ra_state *f_ra)
1530b3b94faaSDavid Teigland {
1531feaa7bbaSSteven Whitehouse struct gfs2_inode *dip = GFS2_I(inode);
1532cd915493SSteven Whitehouse u32 hsize, len = 0;
1533cd915493SSteven Whitehouse u32 hash, index;
1534b44b84d7SAl Viro __be64 *lp;
1535b3b94faaSDavid Teigland int copied = 0;
1536b3b94faaSDavid Teigland int error = 0;
15374da3c646SSteven Whitehouse unsigned depth = 0;
1538b3b94faaSDavid Teigland
153947a9a527SFabian Frederick hsize = BIT(dip->i_depth);
1540d81a8ef5SAl Viro hash = gfs2_dir_offset2hash(ctx->pos);
15419a004508SSteven Whitehouse index = hash >> (32 - dip->i_depth);
1542b3b94faaSDavid Teigland
154379c4c379SSteven Whitehouse if (dip->i_hash_cache == NULL)
1544dfe4d34bSBob Peterson f_ra->start = 0;
154517d539f0SSteven Whitehouse lp = gfs2_dir_get_hash_table(dip);
154617d539f0SSteven Whitehouse if (IS_ERR(lp))
154717d539f0SSteven Whitehouse return PTR_ERR(lp);
1548b3b94faaSDavid Teigland
1549dfe4d34bSBob Peterson gfs2_dir_readahead(inode, hsize, index, f_ra);
1550dfe4d34bSBob Peterson
1551b3b94faaSDavid Teigland while (index < hsize) {
1552d81a8ef5SAl Viro error = gfs2_dir_read_leaf(inode, ctx,
155371b86f56SSteven Whitehouse &copied, &depth,
155417d539f0SSteven Whitehouse be64_to_cpu(lp[index]));
1555b3b94faaSDavid Teigland if (error)
155671b86f56SSteven Whitehouse break;
1557b3b94faaSDavid Teigland
155847a9a527SFabian Frederick len = BIT(dip->i_depth - depth);
1559b3b94faaSDavid Teigland index = (index & ~(len - 1)) + len;
1560b3b94faaSDavid Teigland }
1561b3b94faaSDavid Teigland
156271b86f56SSteven Whitehouse if (error > 0)
156371b86f56SSteven Whitehouse error = 0;
1564b3b94faaSDavid Teigland return error;
1565b3b94faaSDavid Teigland }
1566b3b94faaSDavid Teigland
gfs2_dir_read(struct inode * inode,struct dir_context * ctx,struct file_ra_state * f_ra)1567d81a8ef5SAl Viro int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
1568d81a8ef5SAl Viro struct file_ra_state *f_ra)
1569b3b94faaSDavid Teigland {
1570feaa7bbaSSteven Whitehouse struct gfs2_inode *dip = GFS2_I(inode);
1571bdd19a22SSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(inode);
157271b86f56SSteven Whitehouse struct dirent_gather g;
1573471f3db2SBenjamin Marzinski struct gfs2_dirent **darr, *dent;
1574b3b94faaSDavid Teigland struct buffer_head *dibh;
1575b3b94faaSDavid Teigland int copied = 0;
1576b3b94faaSDavid Teigland int error;
1577b3b94faaSDavid Teigland
1578ad6203f2SSteven Whitehouse if (!dip->i_entries)
157971b86f56SSteven Whitehouse return 0;
158071b86f56SSteven Whitehouse
1581383f01fbSSteven Whitehouse if (dip->i_diskflags & GFS2_DIF_EXHASH)
1582d81a8ef5SAl Viro return dir_e_read(inode, ctx, f_ra);
158371b86f56SSteven Whitehouse
1584b3b94faaSDavid Teigland if (!gfs2_is_stuffed(dip)) {
1585b3b94faaSDavid Teigland gfs2_consist_inode(dip);
1586b3b94faaSDavid Teigland return -EIO;
1587b3b94faaSDavid Teigland }
1588b3b94faaSDavid Teigland
1589b3b94faaSDavid Teigland error = gfs2_meta_inode_buffer(dip, &dibh);
1590b3b94faaSDavid Teigland if (error)
1591b3b94faaSDavid Teigland return error;
1592b3b94faaSDavid Teigland
159371b86f56SSteven Whitehouse error = -ENOMEM;
1594bdd19a22SSteven Whitehouse /* 96 is max number of dirents which can be stuffed into an inode */
15956da2ec56SKees Cook darr = kmalloc_array(96, sizeof(struct gfs2_dirent *), GFP_NOFS);
159671b86f56SSteven Whitehouse if (darr) {
1597471f3db2SBenjamin Marzinski g.pdent = (const struct gfs2_dirent **)darr;
159871b86f56SSteven Whitehouse g.offset = 0;
159971b86f56SSteven Whitehouse dent = gfs2_dirent_scan(inode, dibh->b_data, dibh->b_size,
160071b86f56SSteven Whitehouse gfs2_dirent_gather, NULL, &g);
160171b86f56SSteven Whitehouse if (IS_ERR(dent)) {
160271b86f56SSteven Whitehouse error = PTR_ERR(dent);
160371b86f56SSteven Whitehouse goto out;
160471b86f56SSteven Whitehouse }
1605ad6203f2SSteven Whitehouse if (dip->i_entries != g.offset) {
1606bdd19a22SSteven Whitehouse fs_warn(sdp, "Number of entries corrupt in dir %llu, "
1607ad6203f2SSteven Whitehouse "ip->i_entries (%u) != g.offset (%u)\n",
1608dbb7cae2SSteven Whitehouse (unsigned long long)dip->i_no_addr,
1609ad6203f2SSteven Whitehouse dip->i_entries,
1610bdd19a22SSteven Whitehouse g.offset);
1611d87d62b7SBob Peterson gfs2_consist_inode(dip);
1612bdd19a22SSteven Whitehouse error = -EIO;
1613bdd19a22SSteven Whitehouse goto out;
1614bdd19a22SSteven Whitehouse }
1615471f3db2SBenjamin Marzinski gfs2_set_cookies(sdp, dibh, 0, darr, dip->i_entries);
1616d81a8ef5SAl Viro error = do_filldir_main(dip, ctx, darr,
1617471f3db2SBenjamin Marzinski dip->i_entries, 0, &copied);
161871b86f56SSteven Whitehouse out:
161971b86f56SSteven Whitehouse kfree(darr);
162071b86f56SSteven Whitehouse }
162171b86f56SSteven Whitehouse
1622b3b94faaSDavid Teigland if (error > 0)
1623b3b94faaSDavid Teigland error = 0;
1624b3b94faaSDavid Teigland
1625b3b94faaSDavid Teigland brelse(dibh);
1626b3b94faaSDavid Teigland
1627b3b94faaSDavid Teigland return error;
1628b3b94faaSDavid Teigland }
1629b3b94faaSDavid Teigland
1630b3b94faaSDavid Teigland /**
1631b3b94faaSDavid Teigland * gfs2_dir_search - Search a directory
16323ae3a7d6SBob Peterson * @dir: The GFS2 directory inode
16335a00f3ccSSteven Whitehouse * @name: The name we are looking up
16345a00f3ccSSteven Whitehouse * @fail_on_exist: Fail if the name exists rather than looking it up
1635b3b94faaSDavid Teigland *
1636b3b94faaSDavid Teigland * This routine searches a directory for a file or another directory.
1637b3b94faaSDavid Teigland * Assumes a glock is held on dip.
1638b3b94faaSDavid Teigland *
1639b3b94faaSDavid Teigland * Returns: errno
1640b3b94faaSDavid Teigland */
1641b3b94faaSDavid Teigland
gfs2_dir_search(struct inode * dir,const struct qstr * name,bool fail_on_exist)16425a00f3ccSSteven Whitehouse struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name,
16435a00f3ccSSteven Whitehouse bool fail_on_exist)
1644b3b94faaSDavid Teigland {
1645c752666cSSteven Whitehouse struct buffer_head *bh;
1646c752666cSSteven Whitehouse struct gfs2_dirent *dent;
16475a00f3ccSSteven Whitehouse u64 addr, formal_ino;
16485a00f3ccSSteven Whitehouse u16 dtype;
1649dbb7cae2SSteven Whitehouse
1650dbb7cae2SSteven Whitehouse dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
1651dbb7cae2SSteven Whitehouse if (dent) {
1652c8d57703SAndreas Gruenbacher struct inode *inode;
1653c8d57703SAndreas Gruenbacher u16 rahead;
1654c8d57703SAndreas Gruenbacher
1655dbb7cae2SSteven Whitehouse if (IS_ERR(dent))
1656e231c2eeSDavid Howells return ERR_CAST(dent);
16575a00f3ccSSteven Whitehouse dtype = be16_to_cpu(dent->de_type);
1658c8d57703SAndreas Gruenbacher rahead = be16_to_cpu(dent->de_rahead);
16595a00f3ccSSteven Whitehouse addr = be64_to_cpu(dent->de_inum.no_addr);
16605a00f3ccSSteven Whitehouse formal_ino = be64_to_cpu(dent->de_inum.no_formal_ino);
1661dbb7cae2SSteven Whitehouse brelse(bh);
16625a00f3ccSSteven Whitehouse if (fail_on_exist)
16635a00f3ccSSteven Whitehouse return ERR_PTR(-EEXIST);
16643ce37b2cSAndreas Gruenbacher inode = gfs2_inode_lookup(dir->i_sb, dtype, addr, formal_ino,
16653ce37b2cSAndreas Gruenbacher GFS2_BLKST_FREE /* ignore */);
1666c8d57703SAndreas Gruenbacher if (!IS_ERR(inode))
1667c8d57703SAndreas Gruenbacher GFS2_I(inode)->i_rahead = rahead;
1668c8d57703SAndreas Gruenbacher return inode;
1669dbb7cae2SSteven Whitehouse }
1670dbb7cae2SSteven Whitehouse return ERR_PTR(-ENOENT);
1671dbb7cae2SSteven Whitehouse }
1672dbb7cae2SSteven Whitehouse
gfs2_dir_check(struct inode * dir,const struct qstr * name,const struct gfs2_inode * ip)1673dbb7cae2SSteven Whitehouse int gfs2_dir_check(struct inode *dir, const struct qstr *name,
1674dbb7cae2SSteven Whitehouse const struct gfs2_inode *ip)
1675dbb7cae2SSteven Whitehouse {
1676dbb7cae2SSteven Whitehouse struct buffer_head *bh;
1677dbb7cae2SSteven Whitehouse struct gfs2_dirent *dent;
1678dbb7cae2SSteven Whitehouse int ret = -ENOENT;
1679c752666cSSteven Whitehouse
1680c752666cSSteven Whitehouse dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
1681c752666cSSteven Whitehouse if (dent) {
1682c752666cSSteven Whitehouse if (IS_ERR(dent))
1683c752666cSSteven Whitehouse return PTR_ERR(dent);
1684dbb7cae2SSteven Whitehouse if (ip) {
1685dbb7cae2SSteven Whitehouse if (be64_to_cpu(dent->de_inum.no_addr) != ip->i_no_addr)
1686dbb7cae2SSteven Whitehouse goto out;
1687dbb7cae2SSteven Whitehouse if (be64_to_cpu(dent->de_inum.no_formal_ino) !=
1688dbb7cae2SSteven Whitehouse ip->i_no_formal_ino)
1689dbb7cae2SSteven Whitehouse goto out;
1690dbb7cae2SSteven Whitehouse if (unlikely(IF2DT(ip->i_inode.i_mode) !=
1691dbb7cae2SSteven Whitehouse be16_to_cpu(dent->de_type))) {
1692dbb7cae2SSteven Whitehouse gfs2_consist_inode(GFS2_I(dir));
1693dbb7cae2SSteven Whitehouse ret = -EIO;
1694dbb7cae2SSteven Whitehouse goto out;
1695c752666cSSteven Whitehouse }
1696dbb7cae2SSteven Whitehouse }
1697dbb7cae2SSteven Whitehouse ret = 0;
1698dbb7cae2SSteven Whitehouse out:
1699dbb7cae2SSteven Whitehouse brelse(bh);
1700dbb7cae2SSteven Whitehouse }
1701dbb7cae2SSteven Whitehouse return ret;
1702c752666cSSteven Whitehouse }
1703c752666cSSteven Whitehouse
170401bcb0deSSteven Whitehouse /**
170501bcb0deSSteven Whitehouse * dir_new_leaf - Add a new leaf onto hash chain
170601bcb0deSSteven Whitehouse * @inode: The directory
170701bcb0deSSteven Whitehouse * @name: The name we are adding
170801bcb0deSSteven Whitehouse *
170901bcb0deSSteven Whitehouse * This adds a new dir leaf onto an existing leaf when there is not
171001bcb0deSSteven Whitehouse * enough space to add a new dir entry. This is a last resort after
171101bcb0deSSteven Whitehouse * we've expanded the hash table to max size and also split existing
171201bcb0deSSteven Whitehouse * leaf blocks, so it will only occur for very large directories.
171301bcb0deSSteven Whitehouse *
171401bcb0deSSteven Whitehouse * The dist parameter is set to 1 for leaf blocks directly attached
171501bcb0deSSteven Whitehouse * to the hash table, 2 for one layer of indirection, 3 for two layers
171601bcb0deSSteven Whitehouse * etc. We are thus able to tell the difference between an old leaf
171701bcb0deSSteven Whitehouse * with dist set to zero (i.e. "don't know") and a new one where we
171801bcb0deSSteven Whitehouse * set this information for debug/fsck purposes.
171901bcb0deSSteven Whitehouse *
172001bcb0deSSteven Whitehouse * Returns: 0 on success, or -ve on error
172101bcb0deSSteven Whitehouse */
172201bcb0deSSteven Whitehouse
dir_new_leaf(struct inode * inode,const struct qstr * name)1723c752666cSSteven Whitehouse static int dir_new_leaf(struct inode *inode, const struct qstr *name)
1724c752666cSSteven Whitehouse {
1725c752666cSSteven Whitehouse struct buffer_head *bh, *obh;
1726feaa7bbaSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode);
1727c752666cSSteven Whitehouse struct gfs2_leaf *leaf, *oleaf;
172801bcb0deSSteven Whitehouse u32 dist = 1;
1729b3b94faaSDavid Teigland int error;
1730c752666cSSteven Whitehouse u32 index;
1731c752666cSSteven Whitehouse u64 bn;
1732b3b94faaSDavid Teigland
17339a004508SSteven Whitehouse index = name->hash >> (32 - ip->i_depth);
1734c752666cSSteven Whitehouse error = get_first_leaf(ip, index, &obh);
1735c752666cSSteven Whitehouse if (error)
1736b3b94faaSDavid Teigland return error;
1737c752666cSSteven Whitehouse do {
173801bcb0deSSteven Whitehouse dist++;
1739c752666cSSteven Whitehouse oleaf = (struct gfs2_leaf *)obh->b_data;
1740c752666cSSteven Whitehouse bn = be64_to_cpu(oleaf->lf_next);
1741c752666cSSteven Whitehouse if (!bn)
1742c752666cSSteven Whitehouse break;
1743c752666cSSteven Whitehouse brelse(obh);
1744c752666cSSteven Whitehouse error = get_leaf(ip, bn, &obh);
1745c752666cSSteven Whitehouse if (error)
1746c752666cSSteven Whitehouse return error;
1747c752666cSSteven Whitehouse } while(1);
1748c752666cSSteven Whitehouse
1749350a9b0aSSteven Whitehouse gfs2_trans_add_meta(ip->i_gl, obh);
1750c752666cSSteven Whitehouse
1751c752666cSSteven Whitehouse leaf = new_leaf(inode, &bh, be16_to_cpu(oleaf->lf_depth));
1752c752666cSSteven Whitehouse if (!leaf) {
1753c752666cSSteven Whitehouse brelse(obh);
1754c752666cSSteven Whitehouse return -ENOSPC;
1755c752666cSSteven Whitehouse }
175601bcb0deSSteven Whitehouse leaf->lf_dist = cpu_to_be32(dist);
17574d8012b6SSteven Whitehouse oleaf->lf_next = cpu_to_be64(bh->b_blocknr);
1758c752666cSSteven Whitehouse brelse(bh);
1759c752666cSSteven Whitehouse brelse(obh);
1760c752666cSSteven Whitehouse
1761c752666cSSteven Whitehouse error = gfs2_meta_inode_buffer(ip, &bh);
1762c752666cSSteven Whitehouse if (error)
1763c752666cSSteven Whitehouse return error;
1764350a9b0aSSteven Whitehouse gfs2_trans_add_meta(ip->i_gl, bh);
176577658aadSSteven Whitehouse gfs2_add_inode_blocks(&ip->i_inode, 1);
1766539e5d6bSSteven Whitehouse gfs2_dinode_out(ip, bh->b_data);
1767c752666cSSteven Whitehouse brelse(bh);
1768c752666cSSteven Whitehouse return 0;
1769b3b94faaSDavid Teigland }
1770b3b94faaSDavid Teigland
gfs2_inode_ra_len(const struct gfs2_inode * ip)177144aaada9SSteven Whitehouse static u16 gfs2_inode_ra_len(const struct gfs2_inode *ip)
177244aaada9SSteven Whitehouse {
177344aaada9SSteven Whitehouse u64 where = ip->i_no_addr + 1;
177444aaada9SSteven Whitehouse if (ip->i_eattr == where)
177544aaada9SSteven Whitehouse return 1;
177644aaada9SSteven Whitehouse return 0;
177744aaada9SSteven Whitehouse }
177844aaada9SSteven Whitehouse
1779b3b94faaSDavid Teigland /**
1780b3b94faaSDavid Teigland * gfs2_dir_add - Add new filename into directory
17812b47dad8SSteven Whitehouse * @inode: The directory inode
17822b47dad8SSteven Whitehouse * @name: The new name
17832b47dad8SSteven Whitehouse * @nip: The GFS2 inode to be linked in to the directory
17842b47dad8SSteven Whitehouse * @da: The directory addition info
17852b47dad8SSteven Whitehouse *
17862b47dad8SSteven Whitehouse * If the call to gfs2_diradd_alloc_required resulted in there being
17872b47dad8SSteven Whitehouse * no need to allocate any new directory blocks, then it will contain
17882b47dad8SSteven Whitehouse * a pointer to the directory entry and the bh in which it resides. We
17892b47dad8SSteven Whitehouse * can use that without having to repeat the search. If there was no
17902b47dad8SSteven Whitehouse * free space, then we must now create more space.
1791b3b94faaSDavid Teigland *
1792b3b94faaSDavid Teigland * Returns: 0 on success, error code on failure
1793b3b94faaSDavid Teigland */
1794b3b94faaSDavid Teigland
gfs2_dir_add(struct inode * inode,const struct qstr * name,const struct gfs2_inode * nip,struct gfs2_diradd * da)1795c752666cSSteven Whitehouse int gfs2_dir_add(struct inode *inode, const struct qstr *name,
17962b47dad8SSteven Whitehouse const struct gfs2_inode *nip, struct gfs2_diradd *da)
1797b3b94faaSDavid Teigland {
1798feaa7bbaSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode);
17992b47dad8SSteven Whitehouse struct buffer_head *bh = da->bh;
18002b47dad8SSteven Whitehouse struct gfs2_dirent *dent = da->dent;
180195582b00SDeepa Dinamani struct timespec64 tv;
1802c752666cSSteven Whitehouse struct gfs2_leaf *leaf;
1803b3b94faaSDavid Teigland int error;
1804b3b94faaSDavid Teigland
1805c752666cSSteven Whitehouse while(1) {
18062b47dad8SSteven Whitehouse if (da->bh == NULL) {
18072b47dad8SSteven Whitehouse dent = gfs2_dirent_search(inode, name,
18082b47dad8SSteven Whitehouse gfs2_dirent_find_space, &bh);
18092b47dad8SSteven Whitehouse }
1810c752666cSSteven Whitehouse if (dent) {
1811c752666cSSteven Whitehouse if (IS_ERR(dent))
1812c752666cSSteven Whitehouse return PTR_ERR(dent);
1813c752666cSSteven Whitehouse dent = gfs2_init_dirent(inode, dent, name, bh);
1814dbb7cae2SSteven Whitehouse gfs2_inum_out(nip, dent);
18153d6ecb7dSSteven Whitehouse dent->de_type = cpu_to_be16(IF2DT(nip->i_inode.i_mode));
181644aaada9SSteven Whitehouse dent->de_rahead = cpu_to_be16(gfs2_inode_ra_len(nip));
18178a8b8d91SJeff Layton tv = inode_set_ctime_current(&ip->i_inode);
1818383f01fbSSteven Whitehouse if (ip->i_diskflags & GFS2_DIF_EXHASH) {
1819c752666cSSteven Whitehouse leaf = (struct gfs2_leaf *)bh->b_data;
1820bb16b342SMarcin Slusarz be16_add_cpu(&leaf->lf_entries, 1);
182101bcb0deSSteven Whitehouse leaf->lf_nsec = cpu_to_be32(tv.tv_nsec);
182201bcb0deSSteven Whitehouse leaf->lf_sec = cpu_to_be64(tv.tv_sec);
1823c752666cSSteven Whitehouse }
18242b47dad8SSteven Whitehouse da->dent = NULL;
18252b47dad8SSteven Whitehouse da->bh = NULL;
1826c752666cSSteven Whitehouse brelse(bh);
1827ad6203f2SSteven Whitehouse ip->i_entries++;
18288a8b8d91SJeff Layton ip->i_inode.i_mtime = tv;
18293d6ecb7dSSteven Whitehouse if (S_ISDIR(nip->i_inode.i_mode))
18303d6ecb7dSSteven Whitehouse inc_nlink(&ip->i_inode);
1831343cd8f0SBob Peterson mark_inode_dirty(inode);
1832c752666cSSteven Whitehouse error = 0;
1833c752666cSSteven Whitehouse break;
1834c752666cSSteven Whitehouse }
1835383f01fbSSteven Whitehouse if (!(ip->i_diskflags & GFS2_DIF_EXHASH)) {
1836c752666cSSteven Whitehouse error = dir_make_exhash(inode);
1837c752666cSSteven Whitehouse if (error)
1838c752666cSSteven Whitehouse break;
1839c752666cSSteven Whitehouse continue;
1840c752666cSSteven Whitehouse }
1841c752666cSSteven Whitehouse error = dir_split_leaf(inode, name);
1842c752666cSSteven Whitehouse if (error == 0)
1843c752666cSSteven Whitehouse continue;
1844e90deff5SSteven Whitehouse if (error < 0)
1845c752666cSSteven Whitehouse break;
18469a004508SSteven Whitehouse if (ip->i_depth < GFS2_DIR_MAX_DEPTH) {
1847c752666cSSteven Whitehouse error = dir_double_exhash(ip);
1848c752666cSSteven Whitehouse if (error)
1849c752666cSSteven Whitehouse break;
1850c752666cSSteven Whitehouse error = dir_split_leaf(inode, name);
1851e90deff5SSteven Whitehouse if (error < 0)
1852c752666cSSteven Whitehouse break;
1853e90deff5SSteven Whitehouse if (error == 0)
1854c752666cSSteven Whitehouse continue;
1855c752666cSSteven Whitehouse }
1856c752666cSSteven Whitehouse error = dir_new_leaf(inode, name);
1857c752666cSSteven Whitehouse if (!error)
1858c752666cSSteven Whitehouse continue;
1859c752666cSSteven Whitehouse error = -ENOSPC;
1860c752666cSSteven Whitehouse break;
1861c752666cSSteven Whitehouse }
1862b3b94faaSDavid Teigland return error;
1863b3b94faaSDavid Teigland }
1864b3b94faaSDavid Teigland
1865c752666cSSteven Whitehouse
1866b3b94faaSDavid Teigland /**
1867b3b94faaSDavid Teigland * gfs2_dir_del - Delete a directory entry
1868b3b94faaSDavid Teigland * @dip: The GFS2 inode
18693ae3a7d6SBob Peterson * @dentry: The directory entry we want to delete
1870b3b94faaSDavid Teigland *
1871b3b94faaSDavid Teigland * Returns: 0 on success, error code on failure
1872b3b94faaSDavid Teigland */
1873b3b94faaSDavid Teigland
gfs2_dir_del(struct gfs2_inode * dip,const struct dentry * dentry)1874855d23ceSSteven Whitehouse int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry)
1875b3b94faaSDavid Teigland {
1876855d23ceSSteven Whitehouse const struct qstr *name = &dentry->d_name;
1877c752666cSSteven Whitehouse struct gfs2_dirent *dent, *prev = NULL;
1878c752666cSSteven Whitehouse struct buffer_head *bh;
18798a8b8d91SJeff Layton struct timespec64 tv;
1880b3b94faaSDavid Teigland
1881c752666cSSteven Whitehouse /* Returns _either_ the entry (if its first in block) or the
1882c752666cSSteven Whitehouse previous entry otherwise */
1883feaa7bbaSSteven Whitehouse dent = gfs2_dirent_search(&dip->i_inode, name, gfs2_dirent_prev, &bh);
1884c752666cSSteven Whitehouse if (!dent) {
1885c752666cSSteven Whitehouse gfs2_consist_inode(dip);
1886c752666cSSteven Whitehouse return -EIO;
1887c752666cSSteven Whitehouse }
1888c752666cSSteven Whitehouse if (IS_ERR(dent)) {
1889c752666cSSteven Whitehouse gfs2_consist_inode(dip);
1890c752666cSSteven Whitehouse return PTR_ERR(dent);
1891c752666cSSteven Whitehouse }
1892c752666cSSteven Whitehouse /* If not first in block, adjust pointers accordingly */
189371b86f56SSteven Whitehouse if (gfs2_dirent_find(dent, name, NULL) == 0) {
1894c752666cSSteven Whitehouse prev = dent;
1895c752666cSSteven Whitehouse dent = (struct gfs2_dirent *)((char *)dent + be16_to_cpu(prev->de_rec_len));
1896c752666cSSteven Whitehouse }
1897c752666cSSteven Whitehouse
1898c752666cSSteven Whitehouse dirent_del(dip, bh, prev, dent);
18998a8b8d91SJeff Layton tv = inode_set_ctime_current(&dip->i_inode);
1900383f01fbSSteven Whitehouse if (dip->i_diskflags & GFS2_DIF_EXHASH) {
1901c752666cSSteven Whitehouse struct gfs2_leaf *leaf = (struct gfs2_leaf *)bh->b_data;
1902c752666cSSteven Whitehouse u16 entries = be16_to_cpu(leaf->lf_entries);
1903c752666cSSteven Whitehouse if (!entries)
1904c752666cSSteven Whitehouse gfs2_consist_inode(dip);
1905c752666cSSteven Whitehouse leaf->lf_entries = cpu_to_be16(--entries);
190601bcb0deSSteven Whitehouse leaf->lf_nsec = cpu_to_be32(tv.tv_nsec);
190701bcb0deSSteven Whitehouse leaf->lf_sec = cpu_to_be64(tv.tv_sec);
1908c752666cSSteven Whitehouse }
1909ed386507SSteven Whitehouse brelse(bh);
1910c752666cSSteven Whitehouse
1911ad6203f2SSteven Whitehouse if (!dip->i_entries)
1912c752666cSSteven Whitehouse gfs2_consist_inode(dip);
1913ad6203f2SSteven Whitehouse dip->i_entries--;
19148a8b8d91SJeff Layton dip->i_inode.i_mtime = tv;
1915e36cb0b8SDavid Howells if (d_is_dir(dentry))
1916855d23ceSSteven Whitehouse drop_nlink(&dip->i_inode);
1917feaa7bbaSSteven Whitehouse mark_inode_dirty(&dip->i_inode);
1918b3b94faaSDavid Teigland
1919ab9bbda0SSteven Whitehouse return 0;
1920b3b94faaSDavid Teigland }
1921b3b94faaSDavid Teigland
1922b3b94faaSDavid Teigland /**
1923b3b94faaSDavid Teigland * gfs2_dir_mvino - Change inode number of directory entry
19243ae3a7d6SBob Peterson * @dip: The GFS2 directory inode
19253ae3a7d6SBob Peterson * @filename: the filename to be moved
19263ae3a7d6SBob Peterson * @nip: the new GFS2 inode
19273ae3a7d6SBob Peterson * @new_type: the de_type of the new dirent
1928b3b94faaSDavid Teigland *
1929b3b94faaSDavid Teigland * This routine changes the inode number of a directory entry. It's used
1930b3b94faaSDavid Teigland * by rename to change ".." when a directory is moved.
1931b3b94faaSDavid Teigland * Assumes a glock is held on dvp.
1932b3b94faaSDavid Teigland *
1933b3b94faaSDavid Teigland * Returns: errno
1934b3b94faaSDavid Teigland */
1935b3b94faaSDavid Teigland
gfs2_dir_mvino(struct gfs2_inode * dip,const struct qstr * filename,const struct gfs2_inode * nip,unsigned int new_type)1936c752666cSSteven Whitehouse int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
1937dbb7cae2SSteven Whitehouse const struct gfs2_inode *nip, unsigned int new_type)
1938b3b94faaSDavid Teigland {
1939c752666cSSteven Whitehouse struct buffer_head *bh;
1940c752666cSSteven Whitehouse struct gfs2_dirent *dent;
1941b3b94faaSDavid Teigland
1942feaa7bbaSSteven Whitehouse dent = gfs2_dirent_search(&dip->i_inode, filename, gfs2_dirent_find, &bh);
1943c752666cSSteven Whitehouse if (!dent) {
1944c752666cSSteven Whitehouse gfs2_consist_inode(dip);
1945c752666cSSteven Whitehouse return -EIO;
1946c752666cSSteven Whitehouse }
1947c752666cSSteven Whitehouse if (IS_ERR(dent))
1948c752666cSSteven Whitehouse return PTR_ERR(dent);
1949b3b94faaSDavid Teigland
1950350a9b0aSSteven Whitehouse gfs2_trans_add_meta(dip->i_gl, bh);
1951dbb7cae2SSteven Whitehouse gfs2_inum_out(nip, dent);
1952c752666cSSteven Whitehouse dent->de_type = cpu_to_be16(new_type);
1953c752666cSSteven Whitehouse brelse(bh);
1954c752666cSSteven Whitehouse
19558a8b8d91SJeff Layton dip->i_inode.i_mtime = inode_set_ctime_current(&dip->i_inode);
195683998ccdSAndreas Gruenbacher mark_inode_dirty_sync(&dip->i_inode);
1957c752666cSSteven Whitehouse return 0;
1958b3b94faaSDavid Teigland }
1959b3b94faaSDavid Teigland
1960b3b94faaSDavid Teigland /**
1961b3b94faaSDavid Teigland * leaf_dealloc - Deallocate a directory leaf
1962b3b94faaSDavid Teigland * @dip: the directory
1963b3b94faaSDavid Teigland * @index: the hash table offset in the directory
1964b3b94faaSDavid Teigland * @len: the number of pointers to this leaf
1965b3b94faaSDavid Teigland * @leaf_no: the leaf number
1966ec038c82SBob Peterson * @leaf_bh: buffer_head for the starting leaf
19673ae3a7d6SBob Peterson * @last_dealloc: 1 if this is the final dealloc for the leaf, else 0
1968b3b94faaSDavid Teigland *
1969b3b94faaSDavid Teigland * Returns: errno
1970b3b94faaSDavid Teigland */
1971b3b94faaSDavid Teigland
leaf_dealloc(struct gfs2_inode * dip,u32 index,u32 len,u64 leaf_no,struct buffer_head * leaf_bh,int last_dealloc)1972cd915493SSteven Whitehouse static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
1973ec038c82SBob Peterson u64 leaf_no, struct buffer_head *leaf_bh,
1974ec038c82SBob Peterson int last_dealloc)
1975b3b94faaSDavid Teigland {
1976feaa7bbaSSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
1977c752666cSSteven Whitehouse struct gfs2_leaf *tmp_leaf;
1978b3b94faaSDavid Teigland struct gfs2_rgrp_list rlist;
1979b3b94faaSDavid Teigland struct buffer_head *bh, *dibh;
1980cd915493SSteven Whitehouse u64 blk, nblk;
1981b3b94faaSDavid Teigland unsigned int rg_blocks = 0, l_blocks = 0;
1982b3b94faaSDavid Teigland char *ht;
1983cd915493SSteven Whitehouse unsigned int x, size = len * sizeof(u64);
1984b3b94faaSDavid Teigland int error;
1985b3b94faaSDavid Teigland
19865e2f7d61SBob Peterson error = gfs2_rindex_update(sdp);
19875e2f7d61SBob Peterson if (error)
19885e2f7d61SBob Peterson return error;
19895e2f7d61SBob Peterson
1990b3b94faaSDavid Teigland memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
1991b3b94faaSDavid Teigland
19928be04b93SJoe Perches ht = kzalloc(size, GFP_NOFS | __GFP_NOWARN);
1993e8830d88SBob Peterson if (ht == NULL)
199488dca4caSChristoph Hellwig ht = __vmalloc(size, GFP_NOFS | __GFP_NOWARN | __GFP_ZERO);
1995b3b94faaSDavid Teigland if (!ht)
1996b3b94faaSDavid Teigland return -ENOMEM;
1997b3b94faaSDavid Teigland
1998f4108a60SEric W. Biederman error = gfs2_quota_hold(dip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
1999b3b94faaSDavid Teigland if (error)
20005407e242SBob Peterson goto out;
2001b3b94faaSDavid Teigland
2002b3b94faaSDavid Teigland /* Count the number of leaves */
2003ec038c82SBob Peterson bh = leaf_bh;
2004b3b94faaSDavid Teigland
2005c752666cSSteven Whitehouse for (blk = leaf_no; blk; blk = nblk) {
2006ec038c82SBob Peterson if (blk != leaf_no) {
2007b3b94faaSDavid Teigland error = get_leaf(dip, blk, &bh);
2008b3b94faaSDavid Teigland if (error)
2009b3b94faaSDavid Teigland goto out_rlist;
2010ec038c82SBob Peterson }
2011c752666cSSteven Whitehouse tmp_leaf = (struct gfs2_leaf *)bh->b_data;
2012c752666cSSteven Whitehouse nblk = be64_to_cpu(tmp_leaf->lf_next);
2013ec038c82SBob Peterson if (blk != leaf_no)
2014b3b94faaSDavid Teigland brelse(bh);
2015b3b94faaSDavid Teigland
201670b0c365SSteven Whitehouse gfs2_rlist_add(dip, &rlist, blk);
2017b3b94faaSDavid Teigland l_blocks++;
2018b3b94faaSDavid Teigland }
2019b3b94faaSDavid Teigland
202044dab005SAndreas Gruenbacher gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, LM_FLAG_NODE_SCOPE);
2021b3b94faaSDavid Teigland
2022b3b94faaSDavid Teigland for (x = 0; x < rlist.rl_rgrps; x++) {
20236f6597baSAndreas Gruenbacher struct gfs2_rgrpd *rgd = gfs2_glock2rgrp(rlist.rl_ghs[x].gh_gl);
20246f6597baSAndreas Gruenbacher
2025bb8d8a6fSSteven Whitehouse rg_blocks += rgd->rd_length;
2026b3b94faaSDavid Teigland }
2027b3b94faaSDavid Teigland
2028b3b94faaSDavid Teigland error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
2029b3b94faaSDavid Teigland if (error)
2030b3b94faaSDavid Teigland goto out_rlist;
2031b3b94faaSDavid Teigland
2032b3b94faaSDavid Teigland error = gfs2_trans_begin(sdp,
20335c676f6dSSteven Whitehouse rg_blocks + (DIV_ROUND_UP(size, sdp->sd_jbsize) + 1) +
2034cc44457fSBob Peterson RES_DINODE + RES_STATFS + RES_QUOTA, RES_DINODE +
2035cc44457fSBob Peterson l_blocks);
2036b3b94faaSDavid Teigland if (error)
2037b3b94faaSDavid Teigland goto out_rg_gunlock;
2038b3b94faaSDavid Teigland
2039ec038c82SBob Peterson bh = leaf_bh;
2040ec038c82SBob Peterson
2041c752666cSSteven Whitehouse for (blk = leaf_no; blk; blk = nblk) {
20420ddeded4SAndreas Gruenbacher struct gfs2_rgrpd *rgd;
20430ddeded4SAndreas Gruenbacher
2044ec038c82SBob Peterson if (blk != leaf_no) {
2045b3b94faaSDavid Teigland error = get_leaf(dip, blk, &bh);
2046b3b94faaSDavid Teigland if (error)
2047b3b94faaSDavid Teigland goto out_end_trans;
2048ec038c82SBob Peterson }
2049c752666cSSteven Whitehouse tmp_leaf = (struct gfs2_leaf *)bh->b_data;
2050c752666cSSteven Whitehouse nblk = be64_to_cpu(tmp_leaf->lf_next);
2051ec038c82SBob Peterson if (blk != leaf_no)
2052b3b94faaSDavid Teigland brelse(bh);
2053b3b94faaSDavid Teigland
20540ddeded4SAndreas Gruenbacher rgd = gfs2_blk2rgrpd(sdp, blk, true);
20550ddeded4SAndreas Gruenbacher gfs2_free_meta(dip, rgd, blk, 1);
205677658aadSSteven Whitehouse gfs2_add_inode_blocks(&dip->i_inode, -1);
2057b3b94faaSDavid Teigland }
2058b3b94faaSDavid Teigland
2059cd915493SSteven Whitehouse error = gfs2_dir_write_data(dip, ht, index * sizeof(u64), size);
2060b3b94faaSDavid Teigland if (error != size) {
2061b3b94faaSDavid Teigland if (error >= 0)
2062b3b94faaSDavid Teigland error = -EIO;
2063b3b94faaSDavid Teigland goto out_end_trans;
2064b3b94faaSDavid Teigland }
2065b3b94faaSDavid Teigland
2066b3b94faaSDavid Teigland error = gfs2_meta_inode_buffer(dip, &dibh);
2067b3b94faaSDavid Teigland if (error)
2068b3b94faaSDavid Teigland goto out_end_trans;
2069b3b94faaSDavid Teigland
2070350a9b0aSSteven Whitehouse gfs2_trans_add_meta(dip->i_gl, dibh);
2071d24a7a43SBob Peterson /* On the last dealloc, make this a regular file in case we crash.
2072d24a7a43SBob Peterson (We don't want to free these blocks a second time.) */
2073d24a7a43SBob Peterson if (last_dealloc)
2074d24a7a43SBob Peterson dip->i_inode.i_mode = S_IFREG;
2075539e5d6bSSteven Whitehouse gfs2_dinode_out(dip, dibh->b_data);
2076b3b94faaSDavid Teigland brelse(dibh);
2077b3b94faaSDavid Teigland
2078b3b94faaSDavid Teigland out_end_trans:
2079b3b94faaSDavid Teigland gfs2_trans_end(sdp);
2080b3b94faaSDavid Teigland out_rg_gunlock:
2081b3b94faaSDavid Teigland gfs2_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs);
2082b3b94faaSDavid Teigland out_rlist:
2083b3b94faaSDavid Teigland gfs2_rlist_free(&rlist);
2084b3b94faaSDavid Teigland gfs2_quota_unhold(dip);
2085182fe5abSCyrill Gorcunov out:
20863cdcf63eSAl Viro kvfree(ht);
2087b3b94faaSDavid Teigland return error;
2088b3b94faaSDavid Teigland }
2089b3b94faaSDavid Teigland
2090b3b94faaSDavid Teigland /**
2091b3b94faaSDavid Teigland * gfs2_dir_exhash_dealloc - free all the leaf blocks in a directory
2092b3b94faaSDavid Teigland * @dip: the directory
2093b3b94faaSDavid Teigland *
2094b3b94faaSDavid Teigland * Dealloc all on-disk directory leaves to FREEMETA state
2095b3b94faaSDavid Teigland * Change on-disk inode type to "regular file"
2096b3b94faaSDavid Teigland *
2097b3b94faaSDavid Teigland * Returns: errno
2098b3b94faaSDavid Teigland */
2099b3b94faaSDavid Teigland
gfs2_dir_exhash_dealloc(struct gfs2_inode * dip)2100b3b94faaSDavid Teigland int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip)
2101b3b94faaSDavid Teigland {
2102556bb179SBob Peterson struct buffer_head *bh;
2103556bb179SBob Peterson struct gfs2_leaf *leaf;
2104556bb179SBob Peterson u32 hsize, len;
2105556bb179SBob Peterson u32 index = 0, next_index;
2106556bb179SBob Peterson __be64 *lp;
2107556bb179SBob Peterson u64 leaf_no;
2108556bb179SBob Peterson int error = 0, last;
2109556bb179SBob Peterson
211047a9a527SFabian Frederick hsize = BIT(dip->i_depth);
2111556bb179SBob Peterson
211217d539f0SSteven Whitehouse lp = gfs2_dir_get_hash_table(dip);
211317d539f0SSteven Whitehouse if (IS_ERR(lp))
211417d539f0SSteven Whitehouse return PTR_ERR(lp);
2115556bb179SBob Peterson
2116556bb179SBob Peterson while (index < hsize) {
211717d539f0SSteven Whitehouse leaf_no = be64_to_cpu(lp[index]);
2118556bb179SBob Peterson if (leaf_no) {
2119556bb179SBob Peterson error = get_leaf(dip, leaf_no, &bh);
2120556bb179SBob Peterson if (error)
2121556bb179SBob Peterson goto out;
2122556bb179SBob Peterson leaf = (struct gfs2_leaf *)bh->b_data;
212347a9a527SFabian Frederick len = BIT(dip->i_depth - be16_to_cpu(leaf->lf_depth));
2124556bb179SBob Peterson
2125556bb179SBob Peterson next_index = (index & ~(len - 1)) + len;
2126556bb179SBob Peterson last = ((next_index >= hsize) ? 1 : 0);
2127556bb179SBob Peterson error = leaf_dealloc(dip, index, len, leaf_no, bh,
2128556bb179SBob Peterson last);
2129556bb179SBob Peterson brelse(bh);
2130556bb179SBob Peterson if (error)
2131556bb179SBob Peterson goto out;
2132556bb179SBob Peterson index = next_index;
2133556bb179SBob Peterson } else
2134556bb179SBob Peterson index++;
2135556bb179SBob Peterson }
2136556bb179SBob Peterson
2137556bb179SBob Peterson if (index != hsize) {
2138556bb179SBob Peterson gfs2_consist_inode(dip);
2139556bb179SBob Peterson error = -EIO;
2140556bb179SBob Peterson }
2141556bb179SBob Peterson
2142556bb179SBob Peterson out:
2143556bb179SBob Peterson
2144556bb179SBob Peterson return error;
2145b3b94faaSDavid Teigland }
2146b3b94faaSDavid Teigland
2147b3b94faaSDavid Teigland /**
2148b3b94faaSDavid Teigland * gfs2_diradd_alloc_required - find if adding entry will require an allocation
21493ae3a7d6SBob Peterson * @inode: the directory inode being written to
21503ae3a7d6SBob Peterson * @name: the filename that's going to be added
21513c1c0ae1SSteven Whitehouse * @da: The structure to return dir alloc info
2152b3b94faaSDavid Teigland *
21533c1c0ae1SSteven Whitehouse * Returns: 0 if ok, -ve on error
2154b3b94faaSDavid Teigland */
2155b3b94faaSDavid Teigland
gfs2_diradd_alloc_required(struct inode * inode,const struct qstr * name,struct gfs2_diradd * da)21563c1c0ae1SSteven Whitehouse int gfs2_diradd_alloc_required(struct inode *inode, const struct qstr *name,
21573c1c0ae1SSteven Whitehouse struct gfs2_diradd *da)
2158b3b94faaSDavid Teigland {
215922b5a6c0SSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode);
21603c1c0ae1SSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(inode);
216122b5a6c0SSteven Whitehouse const unsigned int extra = sizeof(struct gfs2_dinode) - sizeof(struct gfs2_leaf);
2162c752666cSSteven Whitehouse struct gfs2_dirent *dent;
2163c752666cSSteven Whitehouse struct buffer_head *bh;
2164b3b94faaSDavid Teigland
21653c1c0ae1SSteven Whitehouse da->nr_blocks = 0;
21662b47dad8SSteven Whitehouse da->bh = NULL;
21672b47dad8SSteven Whitehouse da->dent = NULL;
21683c1c0ae1SSteven Whitehouse
2169c752666cSSteven Whitehouse dent = gfs2_dirent_search(inode, name, gfs2_dirent_find_space, &bh);
2170ed386507SSteven Whitehouse if (!dent) {
21713c1c0ae1SSteven Whitehouse da->nr_blocks = sdp->sd_max_dirres;
217222b5a6c0SSteven Whitehouse if (!(ip->i_diskflags & GFS2_DIF_EXHASH) &&
217322b5a6c0SSteven Whitehouse (GFS2_DIRENT_SIZE(name->len) < extra))
217422b5a6c0SSteven Whitehouse da->nr_blocks = 1;
21753c1c0ae1SSteven Whitehouse return 0;
2176ed386507SSteven Whitehouse }
2177c752666cSSteven Whitehouse if (IS_ERR(dent))
2178c752666cSSteven Whitehouse return PTR_ERR(dent);
217919aeb5a6SBob Peterson
218019aeb5a6SBob Peterson if (da->save_loc) {
21812b47dad8SSteven Whitehouse da->bh = bh;
21822b47dad8SSteven Whitehouse da->dent = dent;
218319aeb5a6SBob Peterson } else {
218419aeb5a6SBob Peterson brelse(bh);
218519aeb5a6SBob Peterson }
2186c752666cSSteven Whitehouse return 0;
2187b3b94faaSDavid Teigland }
2188b3b94faaSDavid Teigland
2189