提交 61e085a8 编写于 作者: S Steven Whitehouse

[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: NSteven Whitehouse <swhiteho@redhat.com>
上级 1e09ae54
...@@ -111,7 +111,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer, ...@@ -111,7 +111,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer,
if (isdir) { if (isdir) {
block = gfs2_alloc_meta(ip); 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) if (error)
goto out_brelse; goto out_brelse;
gfs2_buffer_copy_tail(bh, gfs2_buffer_copy_tail(bh,
......
...@@ -8,61 +8,59 @@ ...@@ -8,61 +8,59 @@
*/ */
/* /*
* Implements Extendible Hashing as described in: * Implements Extendible Hashing as described in:
* "Extendible Hashing" by Fagin, et al in * "Extendible Hashing" by Fagin, et al in
* __ACM Trans. on Database Systems__, Sept 1979. * __ACM Trans. on Database Systems__, Sept 1979.
* *
* *
* Here's the layout of dirents which is essentially the same as that of ext2 * 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 * 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 * 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 * 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 * dirent in the block is (dirent + dirent->de_rec_len). When a dirent is
* deleted, the preceding dirent inherits its allocated space, ie * deleted, the preceding dirent inherits its allocated space, ie
* prev->de_rec_len += deleted->de_rec_len. Since the next dirent is obtained * 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 * 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. * 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 * 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 * 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 * 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 * 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 * 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 * searching for one in which the amount of total space minus the amount of
* used space will provide enough space for the new dirent. * used space will provide enough space for the new dirent.
* *
* There are two types of blocks in which dirents reside. In a stuffed dinode, * 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 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 * 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 * beginning of the leaf block. The dirents reside in leaves when
* *
* dip->i_di.di_flags & GFS2_DIF_EXHASH is true * dip->i_di.di_flags & GFS2_DIF_EXHASH is true
* *
* Otherwise, the dirents are "linear", within a single stuffed dinode block. * 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 * 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 * 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 * dirents are NOT in the directory file itself. There can be more than one
* pointer in the array that points to the same leaf. In fact, when a directory * block pointer in the array that points to the same leaf. In fact, when a
* is first converted from linear to exhash, all of the pointers point to the * directory is first converted from linear to exhash, all of the pointers
* same leaf. * point to the same leaf.
* *
* When a leaf is completely full, the size of the hash table can be * 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 * 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, * 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. * but never before the maximum hash table size has been reached.
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/sort.h> #include <linux/sort.h>
#include <linux/gfs2_ondisk.h> #include <linux/gfs2_ondisk.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/semaphore.h>
#include "gfs2.h" #include "gfs2.h"
#include "lm_interface.h" #include "lm_interface.h"
...@@ -92,33 +90,36 @@ typedef int (*leaf_call_t) (struct gfs2_inode *dip, ...@@ -92,33 +90,36 @@ typedef int (*leaf_call_t) (struct gfs2_inode *dip,
uint32_t index, uint32_t len, uint64_t leaf_no, uint32_t index, uint32_t len, uint64_t leaf_no,
void *data); 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; 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; *bhp = bh;
return 0; 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, static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
unsigned int offset, unsigned int size) unsigned int offset, unsigned int size)
...@@ -205,9 +206,11 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, ...@@ -205,9 +206,11 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
goto fail; goto fail;
} }
error = gfs2_dir_get_buffer(ip, dblock, if (amount == sdp->sd_jbsize || new)
(amount == sdp->sd_jbsize) ? error = gfs2_dir_get_new_buffer(ip, dblock, &bh);
1 : new, &bh); else
error = gfs2_dir_get_existing_buffer(ip, dblock, &bh);
if (error) if (error)
goto fail; goto fail;
...@@ -321,7 +324,10 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf, ...@@ -321,7 +324,10 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
gfs2_meta_ra(ip->i_gl, dblock, extlen); gfs2_meta_ra(ip->i_gl, dblock, extlen);
if (dblock) { 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) if (error)
goto fail; goto fail;
dblock++; dblock++;
......
...@@ -41,8 +41,8 @@ int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip); ...@@ -41,8 +41,8 @@ int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
int gfs2_diradd_alloc_required(struct inode *dir, int gfs2_diradd_alloc_required(struct inode *dir,
const struct qstr *filename); const struct qstr *filename);
int gfs2_dir_get_buffer(struct gfs2_inode *ip, uint64_t block, int new, int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, uint64_t block,
struct buffer_head **bhp); struct buffer_head **bhp);
static inline uint32_t gfs2_disk_hash(const char *data, int len) static inline uint32_t gfs2_disk_hash(const char *data, int len)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册