mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
[GFS2] Tidy up dir code as per Christoph Hellwig's comments
1. Comment whitespace fix 2. Removed unused header files from dir.c 3. Split the gfs2_dir_get_buffer() function into two functions Cc: Christoph Hellwig <hch@infradead.org> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
parent
1e09ae544e
commit
61e085a88c
@ -111,7 +111,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer,
|
||||
if (isdir) {
|
||||
block = gfs2_alloc_meta(ip);
|
||||
|
||||
error = gfs2_dir_get_buffer(ip, block, 1, &bh);
|
||||
error = gfs2_dir_get_new_buffer(ip, block, &bh);
|
||||
if (error)
|
||||
goto out_brelse;
|
||||
gfs2_buffer_copy_tail(bh,
|
||||
|
144
fs/gfs2/dir.c
144
fs/gfs2/dir.c
@ -8,61 +8,59 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Implements Extendible Hashing as described in:
|
||||
* "Extendible Hashing" by Fagin, et al in
|
||||
* __ACM Trans. on Database Systems__, Sept 1979.
|
||||
*
|
||||
*
|
||||
* Here's the layout of dirents which is essentially the same as that of ext2
|
||||
* within a single block. The field de_name_len is the number of bytes
|
||||
* actually required for the name (no null terminator). The field de_rec_len
|
||||
* is the number of bytes allocated to the dirent. The offset of the next
|
||||
* dirent in the block is (dirent + dirent->de_rec_len). When a dirent is
|
||||
* deleted, the preceding dirent inherits its allocated space, ie
|
||||
* prev->de_rec_len += deleted->de_rec_len. Since the next dirent is obtained
|
||||
* by adding de_rec_len to the current dirent, this essentially causes the
|
||||
* deleted dirent to get jumped over when iterating through all the dirents.
|
||||
*
|
||||
* When deleting the first dirent in a block, there is no previous dirent so
|
||||
* the field de_ino is set to zero to designate it as deleted. When allocating
|
||||
* a dirent, gfs2_dirent_alloc iterates through the dirents in a block. If the
|
||||
* first dirent has (de_ino == 0) and de_rec_len is large enough, this first
|
||||
* dirent is allocated. Otherwise it must go through all the 'used' dirents
|
||||
* searching for one in which the amount of total space minus the amount of
|
||||
* used space will provide enough space for the new dirent.
|
||||
*
|
||||
* There are two types of blocks in which dirents reside. In a stuffed dinode,
|
||||
* the dirents begin at offset sizeof(struct gfs2_dinode) from the beginning of
|
||||
* the block. In leaves, they begin at offset sizeof(struct gfs2_leaf) from the
|
||||
* beginning of the leaf block. The dirents reside in leaves when
|
||||
*
|
||||
* dip->i_di.di_flags & GFS2_DIF_EXHASH is true
|
||||
*
|
||||
* Otherwise, the dirents are "linear", within a single stuffed dinode block.
|
||||
*
|
||||
* When the dirents are in leaves, the actual contents of the directory file are
|
||||
* used as an array of 64-bit block pointers pointing to the leaf blocks. The
|
||||
* dirents are NOT in the directory file itself. There can be more than one block
|
||||
* pointer in the array that points to the same leaf. In fact, when a directory
|
||||
* is first converted from linear to exhash, all of the pointers point to the
|
||||
* same leaf.
|
||||
*
|
||||
* When a leaf is completely full, the size of the hash table can be
|
||||
* doubled unless it is already at the maximum size which is hard coded into
|
||||
* GFS2_DIR_MAX_DEPTH. After that, leaves are chained together in a linked list,
|
||||
* but never before the maximum hash table size has been reached.
|
||||
*/
|
||||
* Implements Extendible Hashing as described in:
|
||||
* "Extendible Hashing" by Fagin, et al in
|
||||
* __ACM Trans. on Database Systems__, Sept 1979.
|
||||
*
|
||||
*
|
||||
* Here's the layout of dirents which is essentially the same as that of ext2
|
||||
* within a single block. The field de_name_len is the number of bytes
|
||||
* actually required for the name (no null terminator). The field de_rec_len
|
||||
* is the number of bytes allocated to the dirent. The offset of the next
|
||||
* dirent in the block is (dirent + dirent->de_rec_len). When a dirent is
|
||||
* deleted, the preceding dirent inherits its allocated space, ie
|
||||
* prev->de_rec_len += deleted->de_rec_len. Since the next dirent is obtained
|
||||
* by adding de_rec_len to the current dirent, this essentially causes the
|
||||
* deleted dirent to get jumped over when iterating through all the dirents.
|
||||
*
|
||||
* When deleting the first dirent in a block, there is no previous dirent so
|
||||
* the field de_ino is set to zero to designate it as deleted. When allocating
|
||||
* a dirent, gfs2_dirent_alloc iterates through the dirents in a block. If the
|
||||
* first dirent has (de_ino == 0) and de_rec_len is large enough, this first
|
||||
* dirent is allocated. Otherwise it must go through all the 'used' dirents
|
||||
* searching for one in which the amount of total space minus the amount of
|
||||
* used space will provide enough space for the new dirent.
|
||||
*
|
||||
* There are two types of blocks in which dirents reside. In a stuffed dinode,
|
||||
* the dirents begin at offset sizeof(struct gfs2_dinode) from the beginning of
|
||||
* the block. In leaves, they begin at offset sizeof(struct gfs2_leaf) from the
|
||||
* beginning of the leaf block. The dirents reside in leaves when
|
||||
*
|
||||
* dip->i_di.di_flags & GFS2_DIF_EXHASH is true
|
||||
*
|
||||
* Otherwise, the dirents are "linear", within a single stuffed dinode block.
|
||||
*
|
||||
* When the dirents are in leaves, the actual contents of the directory file are
|
||||
* used as an array of 64-bit block pointers pointing to the leaf blocks. The
|
||||
* dirents are NOT in the directory file itself. There can be more than one
|
||||
* block pointer in the array that points to the same leaf. In fact, when a
|
||||
* directory is first converted from linear to exhash, all of the pointers
|
||||
* point to the same leaf.
|
||||
*
|
||||
* When a leaf is completely full, the size of the hash table can be
|
||||
* doubled unless it is already at the maximum size which is hard coded into
|
||||
* GFS2_DIR_MAX_DEPTH. After that, leaves are chained together in a linked list,
|
||||
* but never before the maximum hash table size has been reached.
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/sort.h>
|
||||
#include <linux/gfs2_ondisk.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/semaphore.h>
|
||||
|
||||
#include "gfs2.h"
|
||||
#include "lm_interface.h"
|
||||
@ -92,33 +90,36 @@ typedef int (*leaf_call_t) (struct gfs2_inode *dip,
|
||||
uint32_t index, uint32_t len, uint64_t leaf_no,
|
||||
void *data);
|
||||
|
||||
int gfs2_dir_get_buffer(struct gfs2_inode *ip, uint64_t block, int new,
|
||||
struct buffer_head **bhp)
|
||||
|
||||
int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, uint64_t block,
|
||||
struct buffer_head **bhp)
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
int error = 0;
|
||||
|
||||
if (new) {
|
||||
bh = gfs2_meta_new(ip->i_gl, block);
|
||||
gfs2_trans_add_bh(ip->i_gl, bh, 1);
|
||||
gfs2_metatype_set(bh, GFS2_METATYPE_JD, GFS2_FORMAT_JD);
|
||||
gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
|
||||
} else {
|
||||
error = gfs2_meta_read(ip->i_gl, block, DIO_START | DIO_WAIT,
|
||||
&bh);
|
||||
if (error)
|
||||
return error;
|
||||
if (gfs2_metatype_check(ip->i_sbd, bh, GFS2_METATYPE_JD)) {
|
||||
brelse(bh);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
bh = gfs2_meta_new(ip->i_gl, block);
|
||||
gfs2_trans_add_bh(ip->i_gl, bh, 1);
|
||||
gfs2_metatype_set(bh, GFS2_METATYPE_JD, GFS2_FORMAT_JD);
|
||||
gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
|
||||
*bhp = bh;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfs2_dir_get_existing_buffer(struct gfs2_inode *ip, uint64_t block,
|
||||
struct buffer_head **bhp)
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
int error;
|
||||
|
||||
error = gfs2_meta_read(ip->i_gl, block, DIO_START | DIO_WAIT, &bh);
|
||||
if (error)
|
||||
return error;
|
||||
if (gfs2_metatype_check(ip->i_sbd, bh, GFS2_METATYPE_JD)) {
|
||||
brelse(bh);
|
||||
return -EIO;
|
||||
}
|
||||
*bhp = bh;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
|
||||
unsigned int offset, unsigned int size)
|
||||
@ -205,9 +206,11 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
error = gfs2_dir_get_buffer(ip, dblock,
|
||||
(amount == sdp->sd_jbsize) ?
|
||||
1 : new, &bh);
|
||||
if (amount == sdp->sd_jbsize || new)
|
||||
error = gfs2_dir_get_new_buffer(ip, dblock, &bh);
|
||||
else
|
||||
error = gfs2_dir_get_existing_buffer(ip, dblock, &bh);
|
||||
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
@ -321,7 +324,10 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
|
||||
gfs2_meta_ra(ip->i_gl, dblock, extlen);
|
||||
|
||||
if (dblock) {
|
||||
error = gfs2_dir_get_buffer(ip, dblock, new, &bh);
|
||||
if (new)
|
||||
error = gfs2_dir_get_new_buffer(ip, dblock, &bh);
|
||||
else
|
||||
error = gfs2_dir_get_existing_buffer(ip, dblock, &bh);
|
||||
if (error)
|
||||
goto fail;
|
||||
dblock++;
|
||||
|
@ -41,8 +41,8 @@ int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
|
||||
|
||||
int gfs2_diradd_alloc_required(struct inode *dir,
|
||||
const struct qstr *filename);
|
||||
int gfs2_dir_get_buffer(struct gfs2_inode *ip, uint64_t block, int new,
|
||||
struct buffer_head **bhp);
|
||||
int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, uint64_t block,
|
||||
struct buffer_head **bhp);
|
||||
|
||||
static inline uint32_t gfs2_disk_hash(const char *data, int len)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user