mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 13:53:33 +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
3 changed files with 78 additions and 72 deletions
|
@ -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,
|
||||||
|
|
144
fs/gfs2/dir.c
144
fs/gfs2/dir.c
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
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);
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue