glops.o inode.o lm.o log.o lops.o locking.o lvb.o main.o meta_io.o \
mount.o ondisk.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
ops_fstype.o ops_inode.o ops_super.o ops_vm.o page.o quota.o \
- recovery.o rgrp.o super.o sys.o trans.o unlinked.o util.o
+ recovery.o rgrp.o super.o sys.o trans.o util.o
obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += locking/nolock/
obj-$(CONFIG_GFS2_FS_LOCKING_DLM) += locking/dlm/
int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access)
{
- if (!ip->i_sbd->sd_args.ar_posix_acl)
+ if (!GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl)
return -EOPNOTSUPP;
if (current->fsuid != ip->i_di.di_uid && !capable(CAP_FOWNER))
return -EPERM;
struct posix_acl *acl = NULL;
int error;
- error = acl_get(inode->u.generic_ip, ACL_ACCESS, &acl, NULL, NULL, NULL);
+ error = acl_get(GFS2_I(inode), ACL_ACCESS, &acl, NULL, NULL, NULL);
if (error)
return error;
int gfs2_check_acl(struct inode *inode, int mask)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder i_gh;
int error;
static int munge_mode(struct gfs2_inode *ip, mode_t mode)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head *dibh;
int error;
int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct posix_acl *acl = NULL, *clone;
struct gfs2_ea_request er;
mode_t mode = ip->i_di.di_mode;
static unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
uint64_t *arr;
unsigned int max, height;
static int build_height(struct inode *inode, unsigned height)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
unsigned new_height = height - ip->i_di.di_height;
struct buffer_head *dibh;
struct buffer_head *blocks[GFS2_MAX_META_HEIGHT];
static void find_metapath(struct gfs2_inode *ip, uint64_t block,
struct metapath *mp)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
uint64_t b = block;
unsigned int i;
int *boundary,
struct metapath *mp)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
struct buffer_head *bh;
int create = *new;
unsigned int bsize;
static inline void bmap_lock(struct inode *inode, int create)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
if (create)
down_write(&ip->i_rw_mutex);
else
static inline void bmap_unlock(struct inode *inode, int create)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
if (create)
up_write(&ip->i_rw_mutex);
else
int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
struct metapath mp;
struct buffer_head *bh;
int boundary;
uint64_t block, int first, block_call_t bc,
void *data)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head *bh = NULL;
uint64_t *top, *bottom;
uint64_t bn;
struct buffer_head *bh, uint64_t *top, uint64_t *bottom,
unsigned int height, void *data)
{
- struct strip_mine *sm = (struct strip_mine *)data;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct strip_mine *sm = data;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrp_list rlist;
uint64_t bn, bstart;
uint32_t blen;
static int do_grow(struct gfs2_inode *ip, uint64_t size)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al;
struct buffer_head *dibh;
unsigned int h;
h = calc_tree_height(ip, size);
if (ip->i_di.di_height < h) {
down_write(&ip->i_rw_mutex);
- error = build_height(ip->i_vnode, h);
+ error = build_height(&ip->i_inode, h);
up_write(&ip->i_rw_mutex);
if (error)
goto out_end_trans;
static int trunc_start(struct gfs2_inode *ip, uint64_t size)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head *dibh;
int journaled = gfs2_is_jdata(ip);
int error;
} else {
if (size & (uint64_t)(sdp->sd_sb.sb_bsize - 1))
- error = gfs2_block_truncate_page(ip->i_vnode->i_mapping);
+ error = gfs2_block_truncate_page(ip->i_inode.i_mapping);
if (!error) {
ip->i_di.di_size = size;
if (!size)
lblock = 0;
else
- lblock = (size - 1) >> ip->i_sbd->sd_sb.sb_bsize_shift;
+ lblock = (size - 1) >> GFS2_SB(&ip->i_inode)->sd_sb.sb_bsize_shift;
find_metapath(ip, lblock, &mp);
gfs2_alloc_get(ip);
static int trunc_end(struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head *dibh;
int error;
{
int error;
- if (gfs2_assert_warn(ip->i_sbd, S_ISREG(ip->i_di.di_mode)))
+ if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_di.di_mode)))
return -EINVAL;
if (size > ip->i_di.di_size)
void gfs2_write_calc_reserv(struct gfs2_inode *ip, unsigned int len,
unsigned int *data_blocks, unsigned int *ind_blocks)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
unsigned int tmp;
if (gfs2_is_dir(ip)) {
int gfs2_write_alloc_required(struct gfs2_inode *ip, uint64_t offset,
unsigned int len, int *alloc_required)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
uint64_t lblock, lblock_stop, dblock;
uint32_t extlen;
int new = 0;
}
for (; lblock < lblock_stop; lblock += extlen) {
- error = gfs2_extent_map(ip->i_vnode, lblock, &new, &dblock, &extlen);
+ error = gfs2_extent_map(&ip->i_inode, lblock, &new, &dblock, &extlen);
if (error)
return error;
#include "quota.h"
#include "recovery.h"
#include "super.h"
-#include "unlinked.h"
#include "util.h"
/* This uses schedule_timeout() instead of msleep() because it's good for
return 0;
}
-/**
- * gfs2_inoded - Deallocate unlinked inodes
- * @sdp: Pointer to GFS2 superblock
- *
- */
-
-int gfs2_inoded(void *data)
-{
- struct gfs2_sbd *sdp = data;
- unsigned long t;
- int error;
-
- while (!kthread_should_stop()) {
- error = gfs2_unlinked_dealloc(sdp);
- if (error &&
- error != -EROFS &&
- !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
- fs_err(sdp, "inoded: error = %d\n", error);
-
- t = gfs2_tune_get(sdp, gt_inoded_secs) * HZ;
- schedule_timeout_interruptible(t);
- }
-
- return 0;
-}
-
int gfs2_recoverd(void *data);
int gfs2_logd(void *data);
int gfs2_quotad(void *data);
-int gfs2_inoded(void *data);
#endif /* __DAEMON_DOT_H__ */
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)) {
+ if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_JD)) {
brelse(bh);
return -EIO;
}
static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
uint64_t offset, unsigned int size)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head *dibh;
uint64_t lblock, dblock;
uint32_t extlen = 0;
if (!extlen) {
new = 1;
- error = gfs2_extent_map(ip->i_vnode, lblock, &new,
+ error = gfs2_extent_map(&ip->i_inode, lblock, &new,
&dblock, &extlen);
if (error)
goto fail;
static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
uint64_t offset, unsigned int size)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
uint64_t lblock, dblock;
uint32_t extlen = 0;
unsigned int o;
if (!extlen) {
new = 0;
- error = gfs2_extent_map(ip->i_vnode, lblock, &new,
+ error = gfs2_extent_map(&ip->i_inode, lblock, &new,
&dblock, &extlen);
if (error)
goto fail;
}
consist_inode:
- gfs2_consist_inode(inode->u.generic_ip);
+ gfs2_consist_inode(GFS2_I(inode));
return ERR_PTR(-EIO);
}
struct gfs2_meta_header *h = (struct gfs2_meta_header *)bh->b_data;
if (be32_to_cpu(h->mh_type) == GFS2_METATYPE_LF) {
- if (gfs2_meta_check(dip->i_sbd, bh))
+ if (gfs2_meta_check(GFS2_SB(&dip->i_inode), bh))
return -EIO;
*dent = (struct gfs2_dirent *)(bh->b_data +
sizeof(struct gfs2_leaf));
return IS_LEAF;
} else {
- if (gfs2_metatype_check(dip->i_sbd, bh, GFS2_METATYPE_DI))
+ if (gfs2_metatype_check(GFS2_SB(&dip->i_inode), bh, GFS2_METATYPE_DI))
return -EIO;
*dent = (struct gfs2_dirent *)(bh->b_data +
sizeof(struct gfs2_dinode));
const struct qstr *name,
struct buffer_head *bh)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_dirent *ndent;
unsigned offset = 0, totlen;
int error;
error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_START | DIO_WAIT, bhp);
- if (!error && gfs2_metatype_check(dip->i_sbd, *bhp, GFS2_METATYPE_LF))
+ if (!error && gfs2_metatype_check(GFS2_SB(&dip->i_inode), *bhp, GFS2_METATYPE_LF)) {
+ /* printk(KERN_INFO "block num=%llu\n", leaf_no); */
error = -EIO;
+ }
return error;
}
{
struct buffer_head *bh;
struct gfs2_dirent *dent;
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
int error;
if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
gfs2_consist_inode(ip);
return ERR_PTR(-EIO);
}
-
+
index = name->hash >> (32 - ip->i_di.di_depth);
error = get_first_leaf(ip, index, &bh);
if (error)
brelse(bh);
if (!ln)
break;
+
error = get_leaf(ip, ln, &bh);
} while(!error);
return error ? ERR_PTR(error) : NULL;
}
+
error = gfs2_meta_inode_buffer(ip, &bh);
if (error)
return ERR_PTR(error);
static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, u16 depth)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
u64 bn = gfs2_alloc_meta(ip);
struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn);
struct gfs2_leaf *leaf;
struct qstr name = { .name = "", .len = 0, .hash = 0 };
if (!bh)
return NULL;
+
gfs2_trans_add_bh(ip->i_gl, bh, 1);
gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF);
leaf = (struct gfs2_leaf *)bh->b_data;
static int dir_make_exhash(struct inode *inode)
{
- struct gfs2_inode *dip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_inode *dip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_dirent *dent;
struct qstr args;
struct buffer_head *bh, *dibh;
args.len = bh->b_size - sizeof(struct gfs2_dinode) +
sizeof(struct gfs2_leaf);
args.name = bh->b_data;
- dent = gfs2_dirent_scan(dip->i_vnode, bh->b_data, bh->b_size,
+ dent = gfs2_dirent_scan(&dip->i_inode, bh->b_data, bh->b_size,
gfs2_dirent_last, &args, NULL);
if (!dent) {
brelse(bh);
static int dir_split_leaf(struct inode *inode, const struct qstr *name)
{
- struct gfs2_inode *dip = inode->u.generic_ip;
+ struct gfs2_inode *dip = GFS2_I(inode);
struct buffer_head *nbh, *obh, *dibh;
struct gfs2_leaf *nleaf, *oleaf;
struct gfs2_dirent *dent, *prev = NULL, *next = NULL, *new;
oleaf->lf_depth = nleaf->lf_depth;
error = gfs2_meta_inode_buffer(dip, &dibh);
- if (!gfs2_assert_withdraw(dip->i_sbd, !error)) {
+ if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) {
dip->i_di.di_blocks++;
gfs2_dinode_out(&dip->i_di, dibh->b_data);
brelse(dibh);
static int dir_double_exhash(struct gfs2_inode *dip)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct buffer_head *dibh;
uint32_t hsize;
uint64_t *buf;
gfs2_filldir_t filldir, int *copied,
unsigned *depth, u64 leaf_no)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *bh;
struct gfs2_leaf *lf;
unsigned entries = 0;
static int dir_e_read(struct inode *inode, uint64_t *offset, void *opaque,
gfs2_filldir_t filldir)
{
- struct gfs2_inode *dip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_inode *dip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
uint32_t hsize, len = 0;
uint32_t ht_offset, lp_offset, ht_offset_cur = -1;
uint32_t hash, index;
int gfs2_dir_read(struct inode *inode, uint64_t *offset, void *opaque,
gfs2_filldir_t filldir)
{
- struct gfs2_inode *dip = inode->u.generic_ip;
+ struct gfs2_inode *dip = GFS2_I(inode);
struct dirent_gather g;
const struct gfs2_dirent **darr, *dent;
struct buffer_head *dibh;
static int dir_new_leaf(struct inode *inode, const struct qstr *name)
{
struct buffer_head *bh, *obh;
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_leaf *leaf, *oleaf;
int error;
u32 index;
int gfs2_dir_add(struct inode *inode, const struct qstr *name,
const struct gfs2_inum *inum, unsigned type)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *bh;
struct gfs2_dirent *dent;
struct gfs2_leaf *leaf;
/* Returns _either_ the entry (if its first in block) or the
previous entry otherwise */
- dent = gfs2_dirent_search(dip->i_vnode, name, gfs2_dirent_prev, &bh);
+ dent = gfs2_dirent_search(&dip->i_inode, name, gfs2_dirent_prev, &bh);
if (!dent) {
gfs2_consist_inode(dip);
return -EIO;
dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
gfs2_dinode_out(&dip->i_di, bh->b_data);
brelse(bh);
+ mark_inode_dirty(&dip->i_inode);
return error;
}
struct gfs2_dirent *dent;
int error;
- dent = gfs2_dirent_search(dip->i_vnode, filename, gfs2_dirent_find, &bh);
+ dent = gfs2_dirent_search(&dip->i_inode, filename, gfs2_dirent_find, &bh);
if (!dent) {
gfs2_consist_inode(dip);
return -EIO;
static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct buffer_head *bh;
struct gfs2_leaf *leaf;
uint32_t hsize, len;
static int leaf_dealloc(struct gfs2_inode *dip, uint32_t index, uint32_t len,
uint64_t leaf_no, void *data)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_leaf *tmp_leaf;
struct gfs2_rgrp_list rlist;
struct buffer_head *bh, *dibh;
int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct buffer_head *bh;
int error;
static int user_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
- struct inode *inode = ip->i_vnode;
+ struct inode *inode = &ip->i_inode;
int error = permission(inode, MAY_READ, NULL);
if (error)
return error;
static int user_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
- struct inode *inode = ip->i_vnode;
+ struct inode *inode = &ip->i_inode;
if (S_ISREG(inode->i_mode) ||
(S_ISDIR(inode->i_mode) && !(inode->i_mode & S_ISVTX))) {
static int user_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
- struct inode *inode = ip->i_vnode;
+ struct inode *inode = &ip->i_inode;
if (S_ISREG(inode->i_mode) ||
(S_ISDIR(inode->i_mode) && !(inode->i_mode & S_ISVTX))) {
!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (ip->i_sbd->sd_args.ar_posix_acl == 0 &&
+ if (GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl == 0 &&
(GFS2_ACL_IS_ACCESS(er->er_name, er->er_name_len) ||
GFS2_ACL_IS_DEFAULT(er->er_name, er->er_name_len)))
return -EOPNOTSUPP;
static int security_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
- struct inode *inode = ip->i_vnode;
+ struct inode *inode = &ip->i_inode;
int error = permission(inode, MAY_READ, NULL);
if (error)
return error;
static int security_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
- struct inode *inode = ip->i_vnode;
+ struct inode *inode = &ip->i_inode;
int error = permission(inode, MAY_WRITE, NULL);
if (error)
return error;
static int security_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
- struct inode *inode = ip->i_vnode;
+ struct inode *inode = &ip->i_inode;
int error = permission(inode, MAY_WRITE, NULL);
if (error)
return error;
struct gfs2_ea_header *ea, *prev = NULL;
int error = 0;
- if (gfs2_metatype_check(ip->i_sbd, bh, GFS2_METATYPE_EA))
+ if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_EA))
return -EIO;
for (ea = GFS2_EA_BH2FIRST(bh);; prev = ea, ea = GFS2_EA2NEXT(ea)) {
goto out;
}
- if (gfs2_metatype_check(ip->i_sbd, bh, GFS2_METATYPE_IN)) {
+ if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_IN)) {
error = -EIO;
goto out;
}
eablk = (uint64_t *)(bh->b_data + sizeof(struct gfs2_meta_header));
- end = eablk + ip->i_sbd->sd_inptrs;
+ end = eablk + GFS2_SB(&ip->i_inode)->sd_inptrs;
for (; eablk < end; eablk++) {
uint64_t bn;
struct gfs2_ea_header *prev, void *private)
{
int *leave = private;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrpd *rgd;
struct gfs2_holder rg_gh;
struct buffer_head *dibh;
if (error)
goto out_alloc;
- error = gfs2_rindex_hold(ip->i_sbd, &al->al_ri_gh);
+ error = gfs2_rindex_hold(GFS2_SB(&ip->i_inode), &al->al_ri_gh);
if (error)
goto out_quota;
static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
char *data)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head **bh;
unsigned int amount = GFS2_EA_DATA_LEN(ea);
unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize);
static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_ea_header *ea;
uint64_t block;
static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
struct gfs2_ea_request *er)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
ea->ea_data_len = cpu_to_be32(er->er_data_len);
ea->ea_name_len = er->er_name_len;
if (error)
goto out_gunlock_q;
- error = gfs2_trans_begin(ip->i_sbd,
+ error = gfs2_trans_begin(GFS2_SB(&ip->i_inode),
blks + al->al_rgd->rd_ri.ri_length +
RES_DINODE + RES_STATFS + RES_QUOTA, 0);
if (error)
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
if (er->er_flags & GFS2_ERF_MODE) {
- gfs2_assert_withdraw(ip->i_sbd,
+ gfs2_assert_withdraw(GFS2_SB(&ip->i_inode),
(ip->i_di.di_mode & S_IFMT) ==
(er->er_mode & S_IFMT));
ip->i_di.di_mode = er->er_mode;
}
out_end_trans:
- gfs2_trans_end(ip->i_sbd);
+ gfs2_trans_end(GFS2_SB(&ip->i_inode));
out_ipres:
gfs2_inplace_release(ip);
static int ea_init(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
- unsigned int jbsize = ip->i_sbd->sd_jbsize;
+ unsigned int jbsize = GFS2_SB(&ip->i_inode)->sd_jbsize;
unsigned int blks = 1;
if (GFS2_EAREQ_SIZE_STUFFED(er) > jbsize)
return;
} else if (GFS2_EA2NEXT(prev) != ea) {
prev = GFS2_EA2NEXT(prev);
- gfs2_assert_withdraw(ip->i_sbd, GFS2_EA2NEXT(prev) == ea);
+ gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), GFS2_EA2NEXT(prev) == ea);
}
len = GFS2_EA_REC_LEN(prev) + GFS2_EA_REC_LEN(ea);
struct buffer_head *dibh;
int error;
- error = gfs2_trans_begin(ip->i_sbd, RES_DINODE + 2 * RES_EATTR, 0);
+ error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + 2 * RES_EATTR, 0);
if (error)
return error;
goto out;
if (er->er_flags & GFS2_ERF_MODE) {
- gfs2_assert_withdraw(ip->i_sbd,
+ gfs2_assert_withdraw(GFS2_SB(&ip->i_inode),
(ip->i_di.di_mode & S_IFMT) == (er->er_mode & S_IFMT));
ip->i_di.di_mode = er->er_mode;
}
gfs2_dinode_out(&ip->i_di, dibh->b_data);
brelse(dibh);
out:
- gfs2_trans_end(ip->i_sbd);
+ gfs2_trans_end(GFS2_SB(&ip->i_inode));
return error;
}
int stuffed;
int error;
- stuffed = ea_calc_size(ip->i_sbd, es->es_er, &size);
+ stuffed = ea_calc_size(GFS2_SB(&ip->i_inode), es->es_er, &size);
if (ea->ea_type == GFS2_EATYPE_UNUSED) {
if (GFS2_EA_REC_LEN(ea) < size)
es->es_bh = bh;
es->es_ea = ea;
blks = 2 + DIV_ROUND_UP(es->es_er->er_data_len,
- ip->i_sbd->sd_jbsize);
+ GFS2_SB(&ip->i_inode)->sd_jbsize);
error = ea_alloc_skeleton(ip, es->es_er, blks,
ea_set_simple_alloc, es);
static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
void *private)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head *indbh, *newbh;
uint64_t *eablk;
int error;
if (!(ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT))
blks++;
- if (GFS2_EAREQ_SIZE_STUFFED(er) > ip->i_sbd->sd_jbsize)
- blks += DIV_ROUND_UP(er->er_data_len, ip->i_sbd->sd_jbsize);
+ if (GFS2_EAREQ_SIZE_STUFFED(er) > GFS2_SB(&ip->i_inode)->sd_jbsize)
+ blks += DIV_ROUND_UP(er->er_data_len, GFS2_SB(&ip->i_inode)->sd_jbsize);
return ea_alloc_skeleton(ip, er, blks, ea_set_block, el);
}
{
if (el->el_prev && GFS2_EA2NEXT(el->el_prev) != el->el_ea) {
el->el_prev = GFS2_EA2NEXT(el->el_prev);
- gfs2_assert_withdraw(ip->i_sbd,
+ gfs2_assert_withdraw(GFS2_SB(&ip->i_inode),
GFS2_EA2NEXT(el->el_prev) == el->el_ea);
}
er->er_data = NULL;
er->er_data_len = 0;
}
- error = ea_check_size(ip->i_sbd, er);
+ error = ea_check_size(GFS2_SB(&ip->i_inode), er);
if (error)
return error;
if (error)
return error;
- if (IS_IMMUTABLE(ip->i_vnode))
+ if (IS_IMMUTABLE(&ip->i_inode))
error = -EPERM;
else
error = gfs2_ea_ops[er->er_type]->eo_set(ip, er);
struct buffer_head *dibh;
int error;
- error = gfs2_trans_begin(ip->i_sbd, RES_DINODE + RES_EATTR, 0);
+ error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + RES_EATTR, 0);
if (error)
return error;
brelse(dibh);
}
- gfs2_trans_end(ip->i_sbd);
+ gfs2_trans_end(GFS2_SB(&ip->i_inode));
return error;
}
if (error)
return error;
- if (IS_IMMUTABLE(ip->i_vnode) || IS_APPEND(ip->i_vnode))
+ if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode))
error = -EPERM;
else
error = gfs2_ea_ops[er->er_type]->eo_remove(ip, er);
static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
struct gfs2_ea_header *ea, char *data)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head **bh;
unsigned int amount = GFS2_EA_DATA_LEN(ea);
unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize);
int error;
if (GFS2_EA_IS_STUFFED(el->el_ea)) {
- error = gfs2_trans_begin(ip->i_sbd, RES_DINODE + RES_EATTR, 0);
+ error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + RES_EATTR, 0);
if (error)
return error;
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
- error = inode_setattr(ip->i_vnode, attr);
- gfs2_assert_warn(ip->i_sbd, !error);
+ error = inode_setattr(&ip->i_inode, attr);
+ gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error);
gfs2_inode_attr_out(ip);
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(&ip->i_di, dibh->b_data);
brelse(dibh);
}
- gfs2_trans_end(ip->i_sbd);
+ gfs2_trans_end(GFS2_SB(&ip->i_inode));
return error;
}
static int ea_dealloc_indirect(struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrp_list rlist;
struct buffer_head *indbh, *dibh;
uint64_t *eablk, *end;
static int ea_dealloc_block(struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc;
struct gfs2_rgrpd *rgd;
struct buffer_head *dibh;
if (error)
goto out_alloc;
- error = gfs2_rindex_hold(ip->i_sbd, &al->al_ri_gh);
+ error = gfs2_rindex_hold(GFS2_SB(&ip->i_inode), &al->al_ri_gh);
if (error)
goto out_quota;
* Gives caller exclusive access to manipulate a glock structure.
*/
-void gfs2_glmutex_lock(struct gfs2_glock *gl)
+static void gfs2_glmutex_lock(struct gfs2_glock *gl)
{
struct gfs2_holder gh;
*
*/
-void gfs2_glmutex_unlock(struct gfs2_glock *gl)
+static void gfs2_glmutex_unlock(struct gfs2_glock *gl)
{
spin_lock(&gl->gl_spin);
clear_bit(GLF_LOCK, &gl->gl_flags);
{
struct gfs2_holder *gh, *new_gh = NULL;
- restart:
+restart:
spin_lock(&gl->gl_spin);
list_for_each_entry(gh, &gl->gl_waiters2, gh_list) {
goto restart;
}
- out:
+out:
spin_unlock(&gl->gl_spin);
if (new_gh)
gfs2_holder_put(new_gh);
}
+void gfs2_glock_inode_squish(struct inode *inode)
+{
+ struct gfs2_holder gh;
+ struct gfs2_glock *gl = GFS2_I(inode)->i_gl;
+ gfs2_holder_init(gl, LM_ST_UNLOCKED, 0, &gh);
+ set_bit(HIF_DEMOTE, &gh.gh_iflags);
+ spin_lock(&gl->gl_spin);
+ gfs2_assert(inode->i_sb->s_fs_info, list_empty(&gl->gl_holders));
+ list_add_tail(&gh.gh_list, &gl->gl_waiters2);
+ run_queue(gl);
+ spin_unlock(&gl->gl_spin);
+ gfs2_holder_uninit(&gh);
+}
+
/**
* state_change - record that the glock is now in a different state
* @gl: the glock
struct greedy *gr;
struct gfs2_holder *gh;
- if (!time ||
- gl->gl_sbd->sd_args.ar_localcaching ||
+ if (!time || gl->gl_sbd->sd_args.ar_localcaching ||
test_and_set_bit(GLF_GREEDY, &gl->gl_flags))
return 1;
}
/**
- * gfs2_try_toss_inode - try to remove a particular inode struct from cache
- * sdp: the filesystem
- * inum: the inode number
- *
- */
-
-void gfs2_try_toss_inode(struct gfs2_sbd *sdp, struct gfs2_inum *inum)
-{
- struct gfs2_glock *gl;
- struct gfs2_inode *ip;
- int error;
-
- error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_inode_glops,
- NO_CREATE, &gl);
- if (error || !gl)
- return;
-
- if (!gfs2_glmutex_trylock(gl))
- goto out;
-
- ip = gl->gl_object;
- if (!ip)
- goto out_unlock;
-
- if (atomic_read(&ip->i_count))
- goto out_unlock;
-
- gfs2_inode_destroy(ip, 1);
-
- out_unlock:
- gfs2_glmutex_unlock(gl);
-
- out:
- gfs2_glock_put(gl);
-}
-
-/**
* gfs2_iopen_go_callback - Try to kick the inode/vnode associated with an
* iopen glock from memory
* @io_gl: the iopen glock
void gfs2_iopen_go_callback(struct gfs2_glock *io_gl, unsigned int state)
{
- struct gfs2_glock *i_gl;
if (state != LM_ST_UNLOCKED)
return;
-
- spin_lock(&io_gl->gl_spin);
- i_gl = io_gl->gl_object;
- if (i_gl) {
- gfs2_glock_hold(i_gl);
- spin_unlock(&io_gl->gl_spin);
- } else {
- spin_unlock(&io_gl->gl_spin);
- return;
- }
-
- if (gfs2_glmutex_trylock(i_gl)) {
- struct gfs2_inode *ip = i_gl->gl_object;
- if (ip) {
- gfs2_try_toss_vnode(ip);
- gfs2_glmutex_unlock(i_gl);
- gfs2_glock_schedule_for_reclaim(i_gl);
- goto out;
- }
- gfs2_glmutex_unlock(i_gl);
- }
-
- out:
- gfs2_glock_put(i_gl);
+ /* FIXME: remove this? */
}
/**
atomic_inc(&sdp->sd_reclaimed);
if (gfs2_glmutex_trylock(gl)) {
- if (gl->gl_ops == &gfs2_inode_glops) {
- struct gfs2_inode *ip = gl->gl_object;
- if (ip && !atomic_read(&ip->i_count))
- gfs2_inode_destroy(ip, 1);
- }
if (queue_empty(gl, &gl->gl_holders) &&
gl->gl_state != LM_ST_UNLOCKED &&
demote_ok(gl))
if (gfs2_glmutex_trylock(gl)) {
if (gl->gl_ops == &gfs2_inode_glops) {
struct gfs2_inode *ip = gl->gl_object;
- if (ip && !atomic_read(&ip->i_count))
+ if (ip)
goto out_schedule;
}
if (queue_empty(gl, &gl->gl_holders) &&
}
if (gfs2_glmutex_trylock(gl)) {
- if (gl->gl_ops == &gfs2_inode_glops) {
- struct gfs2_inode *ip = gl->gl_object;
- if (ip && !atomic_read(&ip->i_count))
- gfs2_inode_destroy(ip, 1);
- }
if (queue_empty(gl, &gl->gl_holders) &&
gl->gl_state != LM_ST_UNLOCKED)
handle_callback(gl, LM_ST_UNLOCKED);
(unsigned long long)ip->i_num.no_formal_ino,
(unsigned long long)ip->i_num.no_addr);
printk(KERN_INFO " type = %u\n", IF2DT(ip->i_di.di_mode));
- printk(KERN_INFO " i_count = %d\n", atomic_read(&ip->i_count));
printk(KERN_INFO " i_flags =");
for (x = 0; x < 32; x++)
if (test_bit(x, &ip->i_flags))
printk(" %u", x);
printk(" \n");
- printk(KERN_INFO " vnode = %s\n", (ip->i_vnode) ? "yes" : "no");
error = 0;
void gfs2_glock_xmote_th(struct gfs2_glock *gl, unsigned int state, int flags);
void gfs2_glock_drop_th(struct gfs2_glock *gl);
-void gfs2_glmutex_lock(struct gfs2_glock *gl);
-void gfs2_glmutex_unlock(struct gfs2_glock *gl);
-
int gfs2_glock_nq(struct gfs2_holder *gh);
int gfs2_glock_poll(struct gfs2_holder *gh);
int gfs2_glock_wait(struct gfs2_holder *gh);
void gfs2_glock_prefetch_num(struct gfs2_sbd *sdp, uint64_t number,
struct gfs2_glock_operations *glops,
unsigned int state, int flags);
+void gfs2_glock_inode_squish(struct inode *inode);
/**
* gfs2_glock_nq_init - intialize a holder and enqueue it on a glock
void gfs2_glock_cb(lm_fsdata_t *fsdata, unsigned int type, void *data);
-void gfs2_try_toss_inode(struct gfs2_sbd *sdp, struct gfs2_inum *inum);
void gfs2_iopen_go_callback(struct gfs2_glock *gl, unsigned int state);
void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl);
static void inode_go_drop_th(struct gfs2_glock *gl)
{
+ printk(KERN_INFO "drop th %p\n", gl->gl_object);
gfs2_pte_inval(gl);
gfs2_glock_drop_th(gl);
}
if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
if (meta && data) {
+ printk(KERN_INFO "sync all\n");
gfs2_page_sync(gl, flags | DIO_START);
gfs2_log_flush(gl->gl_sbd, gl);
gfs2_meta_sync(gl, flags | DIO_START | DIO_WAIT);
return 0;
if (ip->i_vn != gl->gl_vn) {
+ printk(KERN_INFO "refresh inode %p\n", &ip->i_inode);
error = gfs2_inode_refresh(ip);
if (error)
return error;
spin_unlock(&ip->i_spin);
- gfs2_inode_put(ip);
+ iput(&ip->i_inode);
}
/**
static void trans_go_xmote_bh(struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
- struct gfs2_inode *ip = sdp->sd_jdesc->jd_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode);
struct gfs2_glock *j_gl = ip->i_gl;
struct gfs2_log_header head;
int error;
if (gl->gl_state != LM_ST_UNLOCKED &&
test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
- gfs2_meta_cache_flush(sdp->sd_jdesc->jd_inode->u.generic_ip);
+ gfs2_meta_cache_flush(GFS2_I(sdp->sd_jdesc->jd_inode));
j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA);
error = gfs2_find_jhead(sdp->sd_jdesc, &head);
struct gfs2_file;
struct gfs2_revoke;
struct gfs2_revoke_replay;
-struct gfs2_unlinked;
struct gfs2_quota_data;
struct gfs2_log_buf;
struct gfs2_trans;
struct inode i_inode;
struct gfs2_inum i_num;
- atomic_t i_count;
unsigned long i_flags; /* GIF_... */
uint64_t i_vn;
- struct gfs2_dinode i_di;
-
- struct gfs2_glock *i_gl;
- struct gfs2_sbd *i_sbd;
- struct inode *i_vnode;
+ struct gfs2_dinode i_di; /* To be replaced by ref to block */
+ struct gfs2_glock *i_gl; /* Move into i_gh? */
struct gfs2_holder i_iopen_gh;
struct gfs2_holder i_gh; /* for prepare/commit_write only */
struct gfs2_alloc i_alloc;
spinlock_t i_spin;
struct rw_semaphore i_rw_mutex;
-
unsigned int i_greedy;
unsigned long i_last_pfault;
struct buffer_head *i_cache[GFS2_MAX_META_HEIGHT];
};
+/*
+ * Since i_inode is the first element of struct gfs2_inode,
+ * this is effectively a cast.
+ */
static inline struct gfs2_inode *GFS2_I(struct inode *inode)
{
return container_of(inode, struct gfs2_inode, i_inode);
}
+/* To be removed? */
+static inline struct gfs2_sbd *GFS2_SB(struct inode *inode)
+{
+ return inode->i_sb->s_fs_info;
+}
+
enum {
GFF_DID_DIRECT_ALLOC = 0,
};
};
enum {
- ULF_LOCKED = 0,
-};
-
-struct gfs2_unlinked {
- struct list_head ul_list;
- unsigned int ul_count;
- struct gfs2_unlinked_tag ul_ut;
- unsigned long ul_flags; /* ULF_... */
- unsigned int ul_slot;
-};
-
-enum {
QDF_USER = 0,
QDF_CHANGE = 1,
QDF_LOCKED = 2,
unsigned int gt_recoverd_secs;
unsigned int gt_logd_secs;
unsigned int gt_quotad_secs;
- unsigned int gt_inoded_secs;
unsigned int gt_quota_simul_sync; /* Max quotavals to sync at once */
unsigned int gt_quota_warn_period; /* Secs between quota warn msgs */
uint32_t sd_hash_bsize; /* sizeof(exhash block) */
uint32_t sd_hash_bsize_shift;
uint32_t sd_hash_ptrs; /* Number of pointers in a hash block */
- uint32_t sd_ut_per_block;
uint32_t sd_qc_per_block;
uint32_t sd_max_dirres; /* Max blocks needed to add a directory entry */
uint32_t sd_max_height; /* Max height of a file's metadata tree */
struct inode *sd_statfs_inode;
struct inode *sd_ir_inode;
struct inode *sd_sc_inode;
- struct inode *sd_ut_inode;
struct inode *sd_qc_inode;
struct inode *sd_rindex;
struct inode *sd_quota_inode;
struct gfs2_holder sd_ir_gh;
struct gfs2_holder sd_sc_gh;
- struct gfs2_holder sd_ut_gh;
struct gfs2_holder sd_qc_gh;
/* Daemon stuff */
struct task_struct *sd_recoverd_process;
struct task_struct *sd_logd_process;
struct task_struct *sd_quotad_process;
- struct task_struct *sd_inoded_process;
struct task_struct *sd_glockd_process[GFS2_GLOCKD_MAX];
unsigned int sd_glockd_num;
- /* Unlinked inode stuff */
-
- struct list_head sd_unlinked_list;
- atomic_t sd_unlinked_count;
- spinlock_t sd_unlinked_spin;
- struct mutex sd_unlinked_mutex;
-
- unsigned int sd_unlinked_slots;
- unsigned int sd_unlinked_chunks;
- unsigned char **sd_unlinked_bitmap;
-
/* Quota stuff */
struct list_head sd_quota_list;
#include "quota.h"
#include "rgrp.h"
#include "trans.h"
-#include "unlinked.h"
#include "util.h"
/**
inode->i_ctime.tv_nsec = 0;
inode->i_blksize = PAGE_SIZE;
inode->i_blocks = ip->i_di.di_blocks <<
- (ip->i_sbd->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
+ (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
if (ip->i_di.di_flags & GFS2_DIF_IMMUTABLE)
inode->i_flags |= S_IMMUTABLE;
void gfs2_inode_attr_in(struct gfs2_inode *ip)
{
- struct inode *inode;
-
- inode = gfs2_ip2v_lookup(ip);
- if (inode) {
- inode_attr_in(ip, inode);
- iput(inode);
- }
+ struct inode *inode = &ip->i_inode;
+ inode_attr_in(ip, inode);
}
/**
void gfs2_inode_attr_out(struct gfs2_inode *ip)
{
- struct inode *inode = ip->i_vnode;
+ struct inode *inode = &ip->i_inode;
- gfs2_assert_withdraw(ip->i_sbd,
+ gfs2_assert_withdraw(GFS2_SB(inode),
(ip->i_di.di_mode & S_IFMT) == (inode->i_mode & S_IFMT));
ip->i_di.di_mode = inode->i_mode;
ip->i_di.di_uid = inode->i_uid;
ip->i_di.di_ctime = inode->i_ctime.tv_sec;
}
-/**
- * gfs2_ip2v_lookup - Get the struct inode for a struct gfs2_inode
- * @ip: the struct gfs2_inode to get the struct inode for
- *
- * Returns: A VFS inode, or NULL if none
- */
+static int iget_test(struct inode *inode, void *opaque)
+{
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_inum *inum = opaque;
+
+ if (ip && ip->i_num.no_addr == inum->no_addr)
+ return 1;
-struct inode *gfs2_ip2v_lookup(struct gfs2_inode *ip)
+ return 0;
+}
+
+static int iget_set(struct inode *inode, void *opaque)
{
- struct inode *inode = NULL;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_inum *inum = opaque;
- gfs2_assert_warn(ip->i_sbd, test_bit(GIF_MIN_INIT, &ip->i_flags));
+ ip->i_num = *inum;
+ return 0;
+}
- spin_lock(&ip->i_spin);
- if (ip->i_vnode)
- inode = igrab(ip->i_vnode);
- spin_unlock(&ip->i_spin);
+struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum *inum)
+{
+ return ilookup5(sb, (unsigned long)inum->no_formal_ino,
+ iget_test, inum);
+}
- return inode;
+static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum *inum)
+{
+ return iget5_locked(sb, (unsigned long)inum->no_formal_ino,
+ iget_test, iget_set, inum);
}
/**
- * gfs2_ip2v - Get/Create a struct inode for a struct gfs2_inode
- * @ip: the struct gfs2_inode to get the struct inode for
+ * gfs2_inode_lookup - Lookup an inode
+ * @sb: The super block
+ * @inum: The inode number
+ * @type: The type of the inode
*
- * Returns: A VFS inode, or NULL if no mem
+ * Returns: A VFS inode, or an error
*/
-struct inode *gfs2_ip2v(struct gfs2_inode *ip)
+struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum *inum, unsigned int type)
{
- struct inode *inode, *tmp;
-
- inode = gfs2_ip2v_lookup(ip);
- if (inode)
- return inode;
-
- tmp = new_inode(ip->i_sbd->sd_vfs);
- if (!tmp)
- return NULL;
-
- inode_attr_in(ip, tmp);
-
- if (S_ISREG(ip->i_di.di_mode)) {
- tmp->i_op = &gfs2_file_iops;
- tmp->i_fop = &gfs2_file_fops;
- tmp->i_mapping->a_ops = &gfs2_file_aops;
- } else if (S_ISDIR(ip->i_di.di_mode)) {
- tmp->i_op = &gfs2_dir_iops;
- tmp->i_fop = &gfs2_dir_fops;
- } else if (S_ISLNK(ip->i_di.di_mode)) {
- tmp->i_op = &gfs2_symlink_iops;
- } else {
- tmp->i_op = &gfs2_dev_iops;
- init_special_inode(tmp, tmp->i_mode, tmp->i_rdev);
- }
-
- tmp->u.generic_ip = NULL;
-
- for (;;) {
- spin_lock(&ip->i_spin);
- if (!ip->i_vnode)
- break;
- inode = igrab(ip->i_vnode);
- spin_unlock(&ip->i_spin);
+ struct inode *inode = gfs2_iget(sb, inum);
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_glock *io_gl;
+ int error;
- if (inode) {
- iput(tmp);
- return inode;
+ if (inode->i_state & I_NEW) {
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
+ umode_t mode = DT2IF(type);
+ inode->u.generic_ip = ip;
+ inode->i_mode = mode;
+
+ if (S_ISREG(mode)) {
+ inode->i_op = &gfs2_file_iops;
+ inode->i_fop = &gfs2_file_fops;
+ inode->i_mapping->a_ops = &gfs2_file_aops;
+ } else if (S_ISDIR(mode)) {
+ inode->i_op = &gfs2_dir_iops;
+ inode->i_fop = &gfs2_dir_fops;
+ } else if (S_ISLNK(mode)) {
+ inode->i_op = &gfs2_symlink_iops;
+ } else {
+ inode->i_op = &gfs2_dev_iops;
}
- yield();
- }
- inode = tmp;
+ error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
+ if (unlikely(error))
+ goto fail;
+ ip->i_gl->gl_object = ip;
- gfs2_inode_hold(ip);
- ip->i_vnode = inode;
- inode->u.generic_ip = ip;
+ error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
+ if (unlikely(error))
+ goto fail_put;
- spin_unlock(&ip->i_spin);
+ ip->i_vn = ip->i_gl->gl_vn - 1;
+ error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
+ if (unlikely(error))
+ goto fail_iopen;
- insert_inode_hash(inode);
+ gfs2_glock_put(io_gl);
+ unlock_new_inode(inode);
+ }
return inode;
-}
-
-static int iget_test(struct inode *inode, void *opaque)
-{
- struct gfs2_inode *ip = inode->u.generic_ip;
- struct gfs2_inum *inum = (struct gfs2_inum *)opaque;
-
- if (ip && ip->i_num.no_addr == inum->no_addr)
- return 1;
-
- return 0;
-}
-
-struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum *inum)
-{
- return ilookup5(sb, (unsigned long)inum->no_formal_ino,
- iget_test, inum);
-}
-
-void gfs2_inode_min_init(struct gfs2_inode *ip, unsigned int type)
-{
- if (!test_and_set_bit(GIF_MIN_INIT, &ip->i_flags)) {
- ip->i_di.di_nlink = 1;
- ip->i_di.di_mode = DT2IF(type);
- }
+fail_iopen:
+ gfs2_glock_put(io_gl);
+fail_put:
+ ip->i_gl->gl_object = NULL;
+ gfs2_glock_put(ip->i_gl);
+fail:
+ iput(inode);
+ return ERR_PTR(error);
}
/**
if (error)
return error;
- if (gfs2_metatype_check(ip->i_sbd, dibh, GFS2_METATYPE_DI)) {
+ if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), dibh, GFS2_METATYPE_DI)) {
brelse(dibh);
return -EIO;
}
return 0;
}
-/**
- * inode_create - create a struct gfs2_inode
- * @i_gl: The glock covering the inode
- * @inum: The inode number
- * @io_gl: the iopen glock to acquire/hold (using holder in new gfs2_inode)
- * @io_state: the state the iopen glock should be acquired in
- * @ipp: pointer to put the returned inode in
- *
- * Returns: errno
- */
-
-static int inode_create(struct gfs2_glock *i_gl, const struct gfs2_inum *inum,
- struct gfs2_glock *io_gl, unsigned int io_state,
- struct gfs2_inode **ipp, int need_lock)
+int gfs2_dinode_dealloc(struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = i_gl->gl_sbd;
- struct gfs2_inode *ip;
- int error = 0;
-
- ip = kmem_cache_alloc(gfs2_inode_cachep, GFP_KERNEL);
- if (!ip)
- return -ENOMEM;
- memset(ip, 0, sizeof(struct gfs2_inode));
- ip->i_num = *inum;
- atomic_set(&ip->i_count, 1);
- ip->i_vn = i_gl->gl_vn - 1;
- ip->i_gl = i_gl;
- ip->i_sbd = sdp;
- spin_lock_init(&ip->i_spin);
- init_rwsem(&ip->i_rw_mutex);
- ip->i_greedy = gfs2_tune_get(sdp, gt_greedy_default);
-
- if (need_lock) {
- error = gfs2_glock_nq_init(io_gl,
- io_state, GL_LOCAL_EXCL | GL_EXACT,
- &ip->i_iopen_gh);
- if (error)
- goto fail;
-
- spin_lock(&io_gl->gl_spin);
- gfs2_glock_hold(i_gl);
- io_gl->gl_object = i_gl;
- spin_unlock(&io_gl->gl_spin);
- }
-
- gfs2_glock_hold(i_gl);
- i_gl->gl_object = ip;
- atomic_inc(&sdp->sd_inode_count);
- *ipp = ip;
- return 0;
-
-fail:
- gfs2_meta_cache_flush(ip);
- kmem_cache_free(gfs2_inode_cachep, ip);
- *ipp = NULL;
- return error;
-}
-
-/**
- * gfs2_inode_get - Create or get a reference on an inode
- * @i_gl: The glock covering the inode
- * @inum: The inode number
- * @create:
- * @ipp: pointer to put the returned inode in
- *
- * Returns: errno
- */
-
-int gfs2_inode_get(struct gfs2_glock *i_gl, const struct gfs2_inum *inum,
- int create, struct gfs2_inode **ipp)
-{
- struct gfs2_sbd *sdp = i_gl->gl_sbd;
- struct gfs2_glock *io_gl;
- int error = 0;
-
- gfs2_glmutex_lock(i_gl);
-
- *ipp = i_gl->gl_object;
- if (*ipp) {
- error = -ESTALE;
- if ((*ipp)->i_num.no_formal_ino != inum->no_formal_ino)
- goto out;
- atomic_inc(&(*ipp)->i_count);
- error = 0;
- goto out;
- }
-
- if (!create)
- goto out;
-
- error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_iopen_glops,
- CREATE, &io_gl);
- if (!error) {
- error = inode_create(i_gl, inum, io_gl, LM_ST_SHARED, ipp, 1);
- gfs2_glock_put(io_gl);
- }
-
- out:
- gfs2_glmutex_unlock(i_gl);
-
- return error;
-}
-
-void gfs2_inode_hold(struct gfs2_inode *ip)
-{
- gfs2_assert(ip->i_sbd, atomic_read(&ip->i_count) > 0);
- atomic_inc(&ip->i_count);
-}
-
-void gfs2_inode_put(struct gfs2_inode *ip)
-{
- gfs2_assert(ip->i_sbd, atomic_read(&ip->i_count) > 0);
- atomic_dec(&ip->i_count);
-}
-
-void gfs2_inode_destroy(struct gfs2_inode *ip, int unlock)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_glock *i_gl = ip->i_gl;
-
- gfs2_assert_warn(sdp, !atomic_read(&ip->i_count));
- if (unlock) {
- struct gfs2_glock *io_gl = ip->i_iopen_gh.gh_gl;
- gfs2_assert(sdp, io_gl->gl_object == i_gl);
-
- spin_lock(&io_gl->gl_spin);
- io_gl->gl_object = NULL;
- spin_unlock(&io_gl->gl_spin);
- gfs2_glock_put(i_gl);
-
- gfs2_glock_dq_uninit(&ip->i_iopen_gh);
- }
-
- gfs2_meta_cache_flush(ip);
- kmem_cache_free(gfs2_inode_cachep, ip);
-
- i_gl->gl_object = NULL;
- gfs2_glock_put(i_gl);
-
- atomic_dec(&sdp->sd_inode_count);
-}
-
-static int dinode_dealloc(struct gfs2_inode *ip, struct gfs2_unlinked *ul)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al;
struct gfs2_rgrpd *rgd;
int error;
if (error)
goto out_rindex_relse;
- error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_UNLINKED +
+ error = gfs2_trans_begin(sdp, RES_RG_BIT +
RES_STATFS + RES_QUOTA, 1);
if (error)
goto out_rg_gunlock;
gfs2_free_di(rgd, ip);
- error = gfs2_unlinked_ondisk_rm(sdp, ul);
-
gfs2_trans_end(sdp);
clear_bit(GLF_STICKY, &ip->i_gl->gl_flags);
- out_rg_gunlock:
+out_rg_gunlock:
gfs2_glock_dq_uninit(&al->al_rgd_gh);
-
- out_rindex_relse:
+out_rindex_relse:
gfs2_glock_dq_uninit(&al->al_ri_gh);
-
- out_qs:
+out_qs:
gfs2_quota_unhold(ip);
-
- out:
- gfs2_alloc_put(ip);
-
- return error;
-}
-
-/**
- * inode_dealloc - Deallocate all on-disk blocks for an inode (dinode)
- * @sdp: the filesystem
- * @inum: the inode number to deallocate
- * @io_gh: a holder for the iopen glock for this inode
- *
- * N.B. When we enter this we already hold the iopen glock and getting
- * the glock for the inode means that we are grabbing the locks in the
- * "wrong" order so we must only so a try lock operation and fail if we
- * don't get the lock. Thats ok, since if we fail it means someone else
- * is using the inode still and thus we shouldn't be deallocating it
- * anyway.
- *
- * Returns: errno
- */
-
-static int inode_dealloc(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul,
- struct gfs2_holder *io_gh)
-{
- struct gfs2_inode *ip;
- struct gfs2_holder i_gh;
- int error;
-
- error = gfs2_glock_nq_num(sdp, ul->ul_ut.ut_inum.no_addr,
- &gfs2_inode_glops, LM_ST_EXCLUSIVE,
- LM_FLAG_TRY_1CB|GL_DUMP, &i_gh);
- switch(error) {
- case 0:
- break;
- case GLR_TRYFAILED:
- return 1; /* or back off and relock in different order? */
- default:
- return error;
- }
-
- gfs2_assert_warn(sdp, !i_gh.gh_gl->gl_object);
- error = inode_create(i_gh.gh_gl, &ul->ul_ut.ut_inum, io_gh->gh_gl,
- LM_ST_EXCLUSIVE, &ip, 0);
-
- if (error)
- goto out;
-
- error = gfs2_inode_refresh(ip);
- if (error)
- goto out_iput;
-
- if (ip->i_di.di_nlink) {
- if (gfs2_consist_inode(ip))
- gfs2_dinode_print(&ip->i_di);
- error = -EIO;
- goto out_iput;
- }
-
- if (S_ISDIR(ip->i_di.di_mode) &&
- (ip->i_di.di_flags & GFS2_DIF_EXHASH)) {
- error = gfs2_dir_exhash_dealloc(ip);
- if (error)
- goto out_iput;
- }
-
- if (ip->i_di.di_eattr) {
- error = gfs2_ea_dealloc(ip);
- if (error)
- goto out_iput;
- }
-
- if (!gfs2_is_stuffed(ip)) {
- error = gfs2_file_dealloc(ip);
- if (error)
- goto out_iput;
- }
-
- error = dinode_dealloc(ip, ul);
- if (error)
- goto out_iput;
-
-out_iput:
- gfs2_glmutex_lock(i_gh.gh_gl);
- gfs2_inode_put(ip);
- gfs2_inode_destroy(ip, 0);
- gfs2_glmutex_unlock(i_gh.gh_gl);
-
out:
- gfs2_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * try_inode_dealloc - Try to deallocate an inode and all its blocks
- * @sdp: the filesystem
- *
- * Returns: 0 on success, -errno on error, 1 on busy (inode open)
- */
-
-static int try_inode_dealloc(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- int error = 0;
- struct gfs2_holder iogh;
-
- gfs2_try_toss_inode(sdp, &ul->ul_ut.ut_inum);
- error = gfs2_glock_nq_num(sdp, ul->ul_ut.ut_inum.no_addr,
- &gfs2_iopen_glops, LM_ST_EXCLUSIVE,
- LM_FLAG_TRY_1CB, &iogh);
- switch (error) {
- case 0:
- break;
- case GLR_TRYFAILED:
- return 1;
- default:
- return error;
- }
-
- error = inode_dealloc(sdp, ul, &iogh);
- gfs2_glock_dq_uninit(&iogh);
-
- return error;
-}
-
-static int inode_dealloc_uninit(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- struct gfs2_rgrpd *rgd;
- struct gfs2_holder ri_gh, rgd_gh;
- int error;
-
- error = gfs2_rindex_hold(sdp, &ri_gh);
- if (error)
- return error;
-
- rgd = gfs2_blk2rgrpd(sdp, ul->ul_ut.ut_inum.no_addr);
- if (!rgd) {
- gfs2_consist(sdp);
- error = -EIO;
- goto out;
- }
-
- error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rgd_gh);
- if (error)
- goto out;
-
- error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_UNLINKED + RES_STATFS, 0);
- if (error)
- goto out_gunlock;
-
- gfs2_free_uninit_di(rgd, ul->ul_ut.ut_inum.no_addr);
- gfs2_unlinked_ondisk_rm(sdp, ul);
-
- gfs2_trans_end(sdp);
-
- out_gunlock:
- gfs2_glock_dq_uninit(&rgd_gh);
- out:
- gfs2_glock_dq_uninit(&ri_gh);
-
+ gfs2_alloc_put(ip);
return error;
}
-int gfs2_inode_dealloc(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- if (ul->ul_ut.ut_flags & GFS2_UTF_UNINIT)
- return inode_dealloc_uninit(sdp, ul);
- else
- return try_inode_dealloc(sdp, ul);
-}
-
/**
* gfs2_change_nlink - Change nlink count on inode
* @ip: The GFS2 inode
int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
{
+ struct gfs2_sbd *sdp = ip->i_inode.i_sb->s_fs_info;
struct buffer_head *dibh;
uint32_t nlink;
int error;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(&ip->i_di, dibh->b_data);
brelse(dibh);
+ mark_inode_dirty(&ip->i_inode);
- return 0;
+ if (ip->i_di.di_nlink == 0) {
+ struct gfs2_rgrpd *rgd;
+ struct gfs2_holder ri_gh, rg_gh;
+
+ error = gfs2_rindex_hold(sdp, &ri_gh);
+ if (error)
+ goto out;
+ error = -EIO;
+ rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+ if (!rgd)
+ goto out_norgrp;
+ error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rg_gh);
+ if (error)
+ goto out_norgrp;
+
+ gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */
+ gfs2_glock_dq_uninit(&rg_gh);
+out_norgrp:
+ gfs2_glock_dq_uninit(&ri_gh);
+ }
+out:
+ return error;
}
struct inode *gfs2_lookup_simple(struct inode *dip, const char *name)
* Returns: errno
*/
-struct inode *gfs2_lookupi(struct inode *dir, struct qstr *name, int is_root,
- struct nameidata *nd)
+struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
+ int is_root, struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
- struct gfs2_inode *ipp;
- struct gfs2_inode *dip = dir->u.generic_ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_inode *dip = GFS2_I(dir);
struct gfs2_holder d_gh;
struct gfs2_inum inum;
unsigned int type;
- struct gfs2_glock *gl;
int error = 0;
struct inode *inode = NULL;
if (error)
goto out;
- error = gfs2_glock_get(sdp, inum.no_addr, &gfs2_inode_glops,
- CREATE, &gl);
- if (error)
- goto out;
-
- error = gfs2_inode_get(gl, &inum, CREATE, &ipp);
- if (!error)
- gfs2_inode_min_init(ipp, type);
-
- gfs2_glock_put(gl);
+ inode = gfs2_inode_lookup(sb, &inum, type);
out:
gfs2_glock_dq_uninit(&d_gh);
if (error == -ENOENT)
return NULL;
- if (error == 0) {
- inode = gfs2_ip2v(ipp);
- gfs2_inode_put(ipp);
- if (!inode)
- return ERR_PTR(-ENOMEM);
- return inode;
- }
- return ERR_PTR(error);
+ return inode;
}
static int pick_formal_ino_1(struct gfs2_sbd *sdp, uint64_t *formal_ino)
{
- struct gfs2_inode *ip = sdp->sd_ir_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode);
struct buffer_head *bh;
struct gfs2_inum_range ir;
int error;
static int pick_formal_ino_2(struct gfs2_sbd *sdp, uint64_t *formal_ino)
{
- struct gfs2_inode *ip = sdp->sd_ir_inode->u.generic_ip;
- struct gfs2_inode *m_ip = sdp->sd_inum_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode);
+ struct gfs2_inode *m_ip = GFS2_I(sdp->sd_inum_inode);
struct gfs2_holder gh;
struct buffer_head *bh;
struct gfs2_inum_range ir;
* Returns: errno
*/
-static int create_ok(struct gfs2_inode *dip, struct qstr *name,
+static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
unsigned int mode)
{
int error;
- error = gfs2_repermission(dip->i_vnode, MAY_WRITE | MAY_EXEC, NULL);
+ error = gfs2_repermission(&dip->i_inode, MAY_WRITE | MAY_EXEC, NULL);
if (error)
return error;
if (!dip->i_di.di_nlink)
return -EPERM;
- error = gfs2_dir_search(dip->i_vnode, name, NULL, NULL);
+ error = gfs2_dir_search(&dip->i_inode, name, NULL, NULL);
switch (error) {
case -ENOENT:
error = 0;
static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode,
unsigned int *uid, unsigned int *gid)
{
- if (dip->i_sbd->sd_args.ar_suiddir &&
+ if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir &&
(dip->i_di.di_mode & S_ISUID) &&
dip->i_di.di_uid) {
if (S_ISDIR(*mode))
*gid = current->fsgid;
}
-static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_unlinked *ul)
+static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum *inum)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
int error;
gfs2_alloc_get(dip);
if (error)
goto out;
- error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_UNLINKED +
- RES_STATFS, 0);
+ error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS, 0);
if (error)
goto out_ipreserv;
- ul->ul_ut.ut_inum.no_addr = gfs2_alloc_di(dip);
-
- ul->ul_ut.ut_flags = GFS2_UTF_UNINIT;
- error = gfs2_unlinked_ondisk_add(sdp, ul);
+ inum->no_addr = gfs2_alloc_di(dip);
gfs2_trans_end(sdp);
struct gfs2_inum *inum, unsigned int mode,
unsigned int uid, unsigned int gid)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_dinode *di;
struct buffer_head *dibh;
}
static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
- unsigned int mode, struct gfs2_unlinked *ul)
+ unsigned int mode, struct gfs2_inum *inum)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
unsigned int uid, gid;
int error;
if (error)
goto out_quota;
- error = gfs2_trans_begin(sdp, RES_DINODE + RES_UNLINKED + RES_QUOTA, 0);
+ error = gfs2_trans_begin(sdp, RES_DINODE + RES_QUOTA, 0);
if (error)
goto out_quota;
- ul->ul_ut.ut_flags = 0;
- error = gfs2_unlinked_ondisk_munge(sdp, ul);
- init_dinode(dip, gl, &ul->ul_ut.ut_inum, mode, uid, gid);
+ init_dinode(dip, gl, inum, mode, uid, gid);
gfs2_quota_change(dip, +1, uid, gid);
gfs2_trans_end(sdp);
- out_quota:
+out_quota:
gfs2_quota_unlock(dip);
-
- out:
+out:
gfs2_alloc_put(dip);
return error;
}
-static int link_dinode(struct gfs2_inode *dip, struct qstr *name,
- struct gfs2_inode *ip, struct gfs2_unlinked *ul)
+static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
+ struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_alloc *al;
int alloc_required;
struct buffer_head *dibh;
if (error)
goto fail;
- error = alloc_required = gfs2_diradd_alloc_required(dip->i_vnode, name);
+ error = alloc_required = gfs2_diradd_alloc_required(&dip->i_inode, name);
if (alloc_required < 0)
goto fail;
if (alloc_required) {
error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
al->al_rgd->rd_ri.ri_length +
- 2 * RES_DINODE + RES_UNLINKED +
+ 2 * RES_DINODE +
RES_STATFS + RES_QUOTA, 0);
if (error)
goto fail_ipreserv;
} else {
- error = gfs2_trans_begin(sdp,
- RES_LEAF +
- 2 * RES_DINODE +
- RES_UNLINKED, 0);
+ error = gfs2_trans_begin(sdp, RES_LEAF + 2 * RES_DINODE, 0);
if (error)
goto fail_quota_locks;
}
- error = gfs2_dir_add(dip->i_vnode, name, &ip->i_num, IF2DT(ip->i_di.di_mode));
+ error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_di.di_mode));
if (error)
goto fail_end_trans;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(&ip->i_di, dibh->b_data);
brelse(dibh);
-
- error = gfs2_unlinked_ondisk_rm(sdp, ul);
- if (error)
- goto fail_end_trans;
-
return 0;
fail_end_trans:
* Returns: An inode
*/
-struct inode *gfs2_createi(struct gfs2_holder *ghs, struct qstr *name,
+struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
unsigned int mode)
{
struct inode *inode;
struct gfs2_inode *dip = ghs->gh_gl->gl_object;
- struct gfs2_sbd *sdp = dip->i_sbd;
- struct gfs2_unlinked *ul;
- struct gfs2_inode *ip;
+ struct inode *dir = &dip->i_inode;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
+ struct gfs2_inum inum;
int error;
if (!name->len || name->len > GFS2_FNAMESIZE)
return ERR_PTR(-ENAMETOOLONG);
- error = gfs2_unlinked_get(sdp, &ul);
- if (error)
- return ERR_PTR(error);
-
gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, ghs);
error = gfs2_glock_nq(ghs);
if (error)
if (error)
goto fail_gunlock;
- error = pick_formal_ino(sdp, &ul->ul_ut.ut_inum.no_formal_ino);
+ error = pick_formal_ino(sdp, &inum.no_formal_ino);
if (error)
goto fail_gunlock;
- error = alloc_dinode(dip, ul);
+ error = alloc_dinode(dip, &inum);
if (error)
goto fail_gunlock;
- if (ul->ul_ut.ut_inum.no_addr < dip->i_num.no_addr) {
+ if (inum.no_addr < dip->i_num.no_addr) {
gfs2_glock_dq(ghs);
- error = gfs2_glock_nq_num(sdp, ul->ul_ut.ut_inum.no_addr,
+ error = gfs2_glock_nq_num(sdp, inum.no_addr,
&gfs2_inode_glops, LM_ST_EXCLUSIVE,
GL_SKIP, ghs + 1);
if (error) {
- gfs2_unlinked_put(sdp, ul);
return ERR_PTR(error);
}
error = gfs2_glock_nq(ghs);
if (error) {
gfs2_glock_dq_uninit(ghs + 1);
- gfs2_unlinked_put(sdp, ul);
return ERR_PTR(error);
}
if (error)
goto fail_gunlock2;
} else {
- error = gfs2_glock_nq_num(sdp, ul->ul_ut.ut_inum.no_addr,
+ error = gfs2_glock_nq_num(sdp, inum.no_addr,
&gfs2_inode_glops, LM_ST_EXCLUSIVE,
GL_SKIP, ghs + 1);
if (error)
goto fail_gunlock;
}
- error = make_dinode(dip, ghs[1].gh_gl, mode, ul);
+ error = make_dinode(dip, ghs[1].gh_gl, mode, &inum);
if (error)
goto fail_gunlock2;
- error = gfs2_inode_get(ghs[1].gh_gl, &ul->ul_ut.ut_inum, CREATE, &ip);
- if (error)
+ inode = gfs2_inode_lookup(dir->i_sb, &inum, IF2DT(mode));
+ if (IS_ERR(inode))
goto fail_gunlock2;
- error = gfs2_inode_refresh(ip);
+ error = gfs2_inode_refresh(GFS2_I(inode));
if (error)
goto fail_iput;
- error = gfs2_acl_create(dip, ip);
+ error = gfs2_acl_create(dip, GFS2_I(inode));
if (error)
goto fail_iput;
- error = link_dinode(dip, name, ip, ul);
+ error = link_dinode(dip, name, GFS2_I(inode));
if (error)
goto fail_iput;
- gfs2_unlinked_put(sdp, ul);
-
- inode = gfs2_ip2v(ip);
- gfs2_inode_put(ip);
if (!inode)
return ERR_PTR(-ENOMEM);
return inode;
fail_iput:
- gfs2_inode_put(ip);
-
+ iput(inode);
fail_gunlock2:
gfs2_glock_dq_uninit(ghs + 1);
-
fail_gunlock:
gfs2_glock_dq(ghs);
-
fail:
- gfs2_unlinked_put(sdp, ul);
return ERR_PTR(error);
}
/**
- * gfs2_unlinki - Unlink a file
- * @dip: The inode of the directory
- * @name: The name of the file to be unlinked
- * @ip: The inode of the file to be removed
- *
- * Assumes Glocks on both dip and ip are held.
- *
- * Returns: errno
- */
-
-int gfs2_unlinki(struct gfs2_inode *dip, struct qstr *name,
- struct gfs2_inode *ip, struct gfs2_unlinked *ul)
-{
- struct gfs2_sbd *sdp = dip->i_sbd;
- int error;
-
- error = gfs2_dir_del(dip, name);
- if (error)
- return error;
-
- error = gfs2_change_nlink(ip, -1);
- if (error)
- return error;
-
- /* If this inode is being unlinked from the directory structure,
- we need to mark that in the log so that it isn't lost during
- a crash. */
-
- if (!ip->i_di.di_nlink) {
- ul->ul_ut.ut_inum = ip->i_num;
- error = gfs2_unlinked_ondisk_add(sdp, ul);
- if (!error)
- set_bit(GLF_STICKY, &ip->i_gl->gl_flags);
- }
-
- return error;
-}
-
-/**
* gfs2_rmdiri - Remove a directory
* @dip: The parent directory of the directory to be removed
* @name: The name of the directory to be removed
* Returns: errno
*/
-int gfs2_rmdiri(struct gfs2_inode *dip, struct qstr *name,
- struct gfs2_inode *ip, struct gfs2_unlinked *ul)
+int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
+ struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
struct qstr dotname;
int error;
if (error)
return error;
- dotname.len = 2;
- dotname.name = "..";
- dotname.hash = gfs2_disk_hash(dotname.name, dotname.len);
+ gfs2_str2qstr(&dotname, "..");
error = gfs2_dir_del(ip, &dotname);
if (error)
return error;
if (error)
return error;
- /* This inode is being unlinked from the directory structure and
- we need to mark that in the log so that it isn't lost during
- a crash. */
-
- ul->ul_ut.ut_inum = ip->i_num;
- error = gfs2_unlinked_ondisk_add(sdp, ul);
- if (!error)
- set_bit(GLF_STICKY, &ip->i_gl->gl_flags);
-
return error;
}
* Returns: 0 if the parent/child relationship is correct, errno if it isn't
*/
-int gfs2_unlink_ok(struct gfs2_inode *dip, struct qstr *name,
+int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
struct gfs2_inode *ip)
{
struct gfs2_inum inum;
unsigned int type;
int error;
- if (IS_IMMUTABLE(ip->i_vnode) || IS_APPEND(ip->i_vnode))
+ if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode))
return -EPERM;
if ((dip->i_di.di_mode & S_ISVTX) &&
dip->i_di.di_uid != current->fsuid &&
- ip->i_di.di_uid != current->fsuid &&
- !capable(CAP_FOWNER))
+ ip->i_di.di_uid != current->fsuid && !capable(CAP_FOWNER))
return -EPERM;
- if (IS_APPEND(dip->i_vnode))
+ if (IS_APPEND(&dip->i_inode))
return -EPERM;
- error = gfs2_repermission(dip->i_vnode, MAY_WRITE | MAY_EXEC, NULL);
+ error = gfs2_repermission(&dip->i_inode, MAY_WRITE | MAY_EXEC, NULL);
if (error)
return error;
- error = gfs2_dir_search(dip->i_vnode, name, &inum, &type);
+ error = gfs2_dir_search(&dip->i_inode, name, &inum, &type);
if (error)
return error;
int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
{
- struct inode *dir = to->i_vnode;
+ struct inode *dir = &to->i_inode;
struct super_block *sb = dir->i_sb;
struct inode *tmp;
struct qstr dotdot;
igrab(dir);
for (;;) {
- if (dir == this->i_vnode) {
+ if (dir == &this->i_inode) {
error = -EINVAL;
break;
}
memcpy(*buf, dibh->b_data + sizeof(struct gfs2_dinode), x);
*len = x;
- out_brelse:
+out_brelse:
brelse(dibh);
-
- out:
+out:
gfs2_glock_dq_uninit(&i_gh);
-
return error;
}
return 0;
- fail_end_trans:
+fail_end_trans:
gfs2_trans_end(sdp);
-
- fail:
+fail:
gfs2_glock_dq(gh);
-
return error;
}
return error;
}
-/**
- * gfs2_try_toss_vnode - See if we can toss a vnode from memory
- * @ip: the inode
- *
- * Returns: 1 if the vnode was tossed
- */
-
-void gfs2_try_toss_vnode(struct gfs2_inode *ip)
-{
- struct inode *inode;
-
- inode = gfs2_ip2v_lookup(ip);
- if (!inode)
- return;
-
- d_prune_aliases(inode);
-
- if (S_ISDIR(ip->i_di.di_mode)) {
- struct list_head *head = &inode->i_dentry;
- struct dentry *d = NULL;
-
- spin_lock(&dcache_lock);
- if (list_empty(head))
- spin_unlock(&dcache_lock);
- else {
- d = list_entry(head->next, struct dentry, d_alias);
- dget_locked(d);
- spin_unlock(&dcache_lock);
-
- if (have_submounts(d))
- dput(d);
- else {
- shrink_dcache_parent(d);
- dput(d);
- d_prune_aliases(inode);
- }
- }
- }
-
- inode->i_nlink = 0;
- iput(inode);
-}
-
static int
__gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
- error = inode_setattr(ip->i_vnode, attr);
- gfs2_assert_warn(ip->i_sbd, !error);
+ error = inode_setattr(&ip->i_inode, attr);
+ gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error);
gfs2_inode_attr_out(ip);
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
if (current->journal_info)
return __gfs2_setattr_simple(ip, attr);
- error = gfs2_trans_begin(ip->i_sbd, RES_DINODE, 0);
+ error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE, 0);
if (error)
return error;
error = __gfs2_setattr_simple(ip, attr);
- gfs2_trans_end(ip->i_sbd);
+ gfs2_trans_end(GFS2_SB(&ip->i_inode));
return error;
}
void gfs2_inode_attr_in(struct gfs2_inode *ip);
void gfs2_inode_attr_out(struct gfs2_inode *ip);
-struct inode *gfs2_ip2v_lookup(struct gfs2_inode *ip);
-struct inode *gfs2_ip2v(struct gfs2_inode *ip);
-struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum *inum);
+struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum *inum, unsigned type);
+struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum *inum);
-void gfs2_inode_min_init(struct gfs2_inode *ip, unsigned int type);
int gfs2_inode_refresh(struct gfs2_inode *ip);
-int gfs2_inode_get(struct gfs2_glock *i_gl,
- const struct gfs2_inum *inum, int create,
- struct gfs2_inode **ipp);
-void gfs2_inode_hold(struct gfs2_inode *ip);
-void gfs2_inode_put(struct gfs2_inode *ip);
-void gfs2_inode_destroy(struct gfs2_inode *ip, int unlock);
-
-int gfs2_inode_dealloc(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul);
-
+int gfs2_dinode_dealloc(struct gfs2_inode *inode);
int gfs2_change_nlink(struct gfs2_inode *ip, int diff);
-struct inode *gfs2_lookupi(struct inode *dir, struct qstr *name, int is_root,
- struct nameidata *nd);
-struct inode *gfs2_createi(struct gfs2_holder *ghs, struct qstr *name,
+struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
+ int is_root, struct nameidata *nd);
+struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
unsigned int mode);
-int gfs2_unlinki(struct gfs2_inode *dip, struct qstr *name,
- struct gfs2_inode *ip, struct gfs2_unlinked *ul);
-int gfs2_rmdiri(struct gfs2_inode *dip, struct qstr *name,
- struct gfs2_inode *ip, struct gfs2_unlinked *ul);
-int gfs2_unlink_ok(struct gfs2_inode *dip, struct qstr *name,
+int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
+ struct gfs2_inode *ip);
+int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
struct gfs2_inode *ip);
int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to);
int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len);
int gfs2_glock_nq_atime(struct gfs2_holder *gh);
int gfs2_glock_nq_m_atime(unsigned int num_gh, struct gfs2_holder *ghs);
-void gfs2_try_toss_vnode(struct gfs2_inode *ip);
-
int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
int gfs2_repermission(struct inode *inode, int mask, struct nameidata *nd);
int bdy;
error = gfs2_block_map(sdp->sd_jdesc->jd_inode, lbn, &new, &dbn, &bdy);
+ if (!(!error && dbn)) {
+ printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, dbn, lbn);
+ }
gfs2_assert_withdraw(sdp, !error && dbn);
return dbn;
static void buf_lo_before_scan(struct gfs2_jdesc *jd,
struct gfs2_log_header *head, int pass)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (pass != 0)
return;
struct gfs2_log_descriptor *ld, __be64 *ptr,
int pass)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
struct gfs2_glock *gl = ip->i_gl;
unsigned int blks = be32_to_cpu(ld->ld_data1);
struct buffer_head *bh_log, *bh_ip;
static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (error) {
gfs2_meta_sync(ip->i_gl,
static void revoke_lo_before_scan(struct gfs2_jdesc *jd,
struct gfs2_log_header *head, int pass)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (pass != 0)
return;
struct gfs2_log_descriptor *ld, __be64 *ptr,
int pass)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
unsigned int blks = be32_to_cpu(ld->ld_length);
unsigned int revokes = be32_to_cpu(ld->ld_data1);
struct buffer_head *bh;
static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (error) {
gfs2_revoke_clean(sdp);
struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le);
struct gfs2_trans *tr = current->journal_info;
struct address_space *mapping = bd->bd_bh->b_page->mapping;
- struct gfs2_inode *ip = mapping->host->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(mapping->host);
tr->tr_touched = 1;
if (!list_empty(&bd->bd_list_tr) &&
struct gfs2_log_descriptor *ld,
__be64 *ptr, int pass)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
struct gfs2_glock *gl = ip->i_gl;
unsigned int blks = be32_to_cpu(ld->ld_data1);
struct buffer_head *bh_log, *bh_ip;
static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (error) {
gfs2_meta_sync(ip->i_gl,
if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR) {
inode_init_once(&ip->i_inode);
- atomic_set(&ip->i_count, 0);
- ip->i_vnode = &ip->i_inode;
spin_lock_init(&ip->i_spin);
init_rwsem(&ip->i_rw_mutex);
memset(ip->i_cache, 0, sizeof(ip->i_cache));
fs_warn(sdp, "ip = %llu %llu\n",
(unsigned long long)ip->i_num.no_formal_ino,
(unsigned long long)ip->i_num.no_addr);
- fs_warn(sdp, "ip->i_count = %d, ip->i_vnode = %s\n",
- atomic_read(&ip->i_count),
- (ip->i_vnode) ? "!NULL" : "NULL");
for (x = 0; x < GFS2_MAX_META_HEIGHT; x++)
fs_warn(sdp, "ip->i_cache[%u] = %s\n",
bd = kmem_cache_alloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL),
memset(bd, 0, sizeof(struct gfs2_bufdata));
-
bd->bd_bh = bh;
bd->bd_gl = gl;
void gfs2_meta_wipe(struct gfs2_inode *ip, uint64_t bstart, uint32_t blen)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct inode *aspace = ip->i_gl->gl_aspace;
struct buffer_head *bh;
if (new)
meta_prep_new(bh);
else {
- error = gfs2_meta_reread(ip->i_sbd, bh,
+ error = gfs2_meta_reread(GFS2_SB(&ip->i_inode), bh,
DIO_START | DIO_WAIT);
if (error) {
brelse(bh);
}
if (new) {
- if (gfs2_assert_warn(ip->i_sbd, height)) {
+ if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), height)) {
brelse(bh);
return -EIO;
}
gfs2_metatype_set(bh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
- } else if (gfs2_metatype_check(ip->i_sbd, bh,
+ } else if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh,
(height) ? GFS2_METATYPE_IN : GFS2_METATYPE_DI)) {
brelse(bh);
return -EIO;
str->sc_dinodes = cpu_to_be64(sc->sc_dinodes);
}
-void gfs2_unlinked_tag_in(struct gfs2_unlinked_tag *ut, char *buf)
-{
- struct gfs2_unlinked_tag *str = (struct gfs2_unlinked_tag *)buf;
-
- gfs2_inum_in(&ut->ut_inum, buf);
- ut->ut_flags = be32_to_cpu(str->ut_flags);
-}
-
-void gfs2_unlinked_tag_out(struct gfs2_unlinked_tag *ut, char *buf)
-{
- struct gfs2_unlinked_tag *str = (struct gfs2_unlinked_tag *)buf;
-
- gfs2_inum_out(&ut->ut_inum, buf);
- str->ut_flags = cpu_to_be32(ut->ut_flags);
- str->__pad = 0;
-}
-
void gfs2_quota_change_in(struct gfs2_quota_change *qc, char *buf)
{
struct gfs2_quota_change *str = (struct gfs2_quota_change *)buf;
static int get_block_noalloc(struct inode *inode, sector_t lblock,
struct buffer_head *bh_result, int create)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
int new = 0;
uint64_t dblock;
int error;
if (dblock)
map_bh(bh_result, inode->i_sb, dblock);
- else if (gfs2_assert_withdraw(ip->i_sbd, !create))
+ else if (gfs2_assert_withdraw(GFS2_SB(inode), !create))
error = -EIO;
if (boundary)
set_buffer_boundary(bh_result);
static int gfs2_writepage(struct page *page, struct writeback_control *wbc)
{
struct inode *inode = page->mapping->host;
- struct gfs2_inode *ip = page->mapping->host->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+ struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
loff_t i_size = i_size_read(inode);
pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
unsigned offset;
static int gfs2_readpage(struct file *file, struct page *page)
{
- struct gfs2_inode *ip = page->mapping->host->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+ struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
struct gfs2_holder gh;
int error;
struct list_head *pages, unsigned nr_pages)
{
struct inode *inode = mapping->host;
- struct gfs2_inode *ip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_holder gh;
unsigned page_idx;
int ret;
static int gfs2_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
- struct gfs2_inode *ip = page->mapping->host->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+ struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
unsigned int data_blocks, ind_blocks, rblocks;
int alloc_required;
int error = 0;
unsigned from, unsigned to)
{
struct inode *inode = page->mapping->host;
- struct gfs2_inode *ip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
int error = -EOPNOTSUPP;
struct buffer_head *dibh;
struct gfs2_alloc *al = &ip->i_alloc;;
static sector_t gfs2_bmap(struct address_space *mapping, sector_t lblock)
{
- struct gfs2_inode *ip = mapping->host->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(mapping->host);
struct gfs2_holder i_gh;
sector_t dblock = 0;
int error;
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder gh;
int rv;
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
- struct gfs2_inode *ip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
if (rw == WRITE)
return gfs2_direct_IO_write(iocb, iov, offset, nr_segs);
static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
{
struct dentry *parent = dget_parent(dentry);
- struct gfs2_sbd *sdp = parent->d_inode->i_sb->s_fs_info;
- struct gfs2_inode *dip = parent->d_inode->u.generic_ip;
+ struct gfs2_sbd *sdp = GFS2_SB(parent->d_inode);
+ struct gfs2_inode *dip = GFS2_I(parent->d_inode);
struct inode *inode = dentry->d_inode;
struct gfs2_holder d_gh;
struct gfs2_inode *ip;
goto fail_gunlock;
}
- ip = inode->u.generic_ip;
+ ip = GFS2_I(inode);
if (!gfs2_inum_equal(&ip->i_num, &inum))
goto invalid_gunlock;
{
struct inode *inode = dentry->d_inode;
struct super_block *sb = inode->i_sb;
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
if (*len < 4 || (connectable && *len < 8))
return 255;
spin_lock(&dentry->d_lock);
inode = dentry->d_parent->d_inode;
- ip = inode->u.generic_ip;
- gfs2_inode_hold(ip);
+ ip = GFS2_I(inode);
+ igrab(inode);
spin_unlock(&dentry->d_lock);
fh[4] = ip->i_num.no_formal_ino >> 32;
fh[7] = cpu_to_be32(fh[7]);
*len = 8;
- gfs2_inode_put(ip);
+ iput(inode);
return *len;
}
if (!S_ISDIR(dir->i_mode) || !inode)
return -EINVAL;
- dip = dir->u.generic_ip;
- ip = inode->u.generic_ip;
+ dip = GFS2_I(dir);
+ ip = GFS2_I(inode);
*name = 0;
gnfd.inum = ip->i_num;
static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_p)
{
struct gfs2_sbd *sdp = sb->s_fs_info;
- struct gfs2_inum *inum = (struct gfs2_inum *)inum_p;
+ struct gfs2_inum *inum = inum_p;
struct gfs2_holder i_gh, ri_gh, rgd_gh;
struct gfs2_rgrpd *rgd;
- struct gfs2_inode *ip;
struct inode *inode;
struct dentry *dentry;
int error;
/* System files? */
- inode = gfs2_iget(sb, inum);
+ inode = gfs2_ilookup(sb, inum);
if (inode) {
- ip = inode->u.generic_ip;
- if (ip->i_num.no_formal_ino != inum->no_formal_ino) {
+ if (GFS2_I(inode)->i_num.no_formal_ino != inum->no_formal_ino) {
iput(inode);
return ERR_PTR(-ESTALE);
}
goto out_inode;
}
- error = gfs2_glock_nq_num(sdp,
- inum->no_addr, &gfs2_inode_glops,
+ error = gfs2_glock_nq_num(sdp, inum->no_addr, &gfs2_inode_glops,
LM_ST_SHARED, LM_FLAG_ANY | GL_LOCAL_EXCL,
&i_gh);
if (error)
return ERR_PTR(error);
- error = gfs2_inode_get(i_gh.gh_gl, inum, NO_CREATE, &ip);
- if (error)
- goto fail;
- if (ip)
- goto out_ip;
-
error = gfs2_rindex_hold(sdp, &ri_gh);
if (error)
goto fail;
gfs2_glock_dq_uninit(&rgd_gh);
gfs2_glock_dq_uninit(&ri_gh);
- error = gfs2_inode_get(i_gh.gh_gl, inum, CREATE, &ip);
- if (error)
+ inode = gfs2_inode_lookup(sb, inum, DT_UNKNOWN);
+ if (!inode)
+ goto fail;
+ if (IS_ERR(inode)) {
+ error = PTR_ERR(inode);
goto fail;
+ }
- error = gfs2_inode_refresh(ip);
+ error = gfs2_inode_refresh(GFS2_I(inode));
if (error) {
- gfs2_inode_put(ip);
+ iput(inode);
goto fail;
}
- out_ip:
error = -EIO;
- if (ip->i_di.di_flags & GFS2_DIF_SYSTEM) {
- gfs2_inode_put(ip);
+ if (GFS2_I(inode)->i_di.di_flags & GFS2_DIF_SYSTEM) {
+ iput(inode);
goto fail;
}
gfs2_glock_dq_uninit(&i_gh);
- inode = gfs2_ip2v(ip);
- gfs2_inode_put(ip);
-
- if (!inode)
- return ERR_PTR(-ENOMEM);
-
- out_inode:
+out_inode:
dentry = d_alloc_anon(inode);
if (!dentry) {
iput(inode);
return dentry;
- fail_rgd:
+fail_rgd:
gfs2_glock_dq_uninit(&rgd_gh);
- fail_rindex:
+fail_rindex:
gfs2_glock_dq_uninit(&ri_gh);
- fail:
+fail:
gfs2_glock_dq_uninit(&i_gh);
return ERR_PTR(error);
}
int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
char *buf, loff_t *pos, unsigned size)
{
- struct inode *inode = ip->i_vnode;
+ struct inode *inode = &ip->i_inode;
read_descriptor_t desc;
desc.written = 0;
desc.arg.buf = buf;
static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin)
{
- struct gfs2_inode *ip = file->f_mapping->host->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
struct gfs2_holder i_gh;
loff_t error;
unsigned long nr_segs, loff_t *ppos)
{
struct file *filp = iocb->ki_filp;
- struct gfs2_inode *ip = filp->f_mapping->host->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(filp->f_mapping->host);
struct gfs2_holder gh;
ssize_t retval;
unsigned long seg;
static int readdir_reg(struct file *file, void *dirent, filldir_t filldir)
{
struct inode *dir = file->f_mapping->host;
- struct gfs2_inode *dip = dir->u.generic_ip;
+ struct gfs2_inode *dip = GFS2_I(dir);
struct filldir_reg fdr;
struct gfs2_holder d_gh;
uint64_t offset = file->f_pos;
int error;
- fdr.fdr_sbd = dip->i_sbd;
+ fdr.fdr_sbd = GFS2_SB(dir);
fdr.fdr_prefetch = 1;
fdr.fdr_filldir = filldir;
fdr.fdr_opaque = dirent;
static int readdir_bad(struct file *file, void *dirent, filldir_t filldir)
{
struct inode *dir = file->f_mapping->host;
- struct gfs2_inode *dip = dir->u.generic_ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_inode *dip = GFS2_I(dir);
+ struct gfs2_sbd *sdp = GFS2_SB(dir);
struct filldir_reg fdr;
unsigned int entries, size;
struct filldir_bad *fdb;
static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
{
struct inode *inode = filp->f_dentry->d_inode;
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder gh;
int error;
u32 iflags;
static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
{
struct inode *inode = filp->f_dentry->d_inode;
- struct gfs2_inode *ip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
struct buffer_head *bh;
struct gfs2_holder gh;
int error;
static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct gfs2_inode *ip = file->f_mapping->host->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
struct gfs2_holder i_gh;
int error;
static int gfs2_open(struct inode *inode, struct file *file)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder i_gh;
struct gfs2_file *fp;
int error;
mutex_init(&fp->f_fl_mutex);
- gfs2_assert_warn(ip->i_sbd, !file->private_data);
+ gfs2_assert_warn(GFS2_SB(inode), !file->private_data);
file->private_data = fp;
if (S_ISREG(ip->i_di.di_mode)) {
static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync)
{
- struct gfs2_inode *ip = dentry->d_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl);
static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
{
- struct gfs2_inode *ip = file->f_mapping->host->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
+ struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
struct lm_lockname name =
{ .ln_number = ip->i_num.no_addr,
.ln_type = LM_TYPE_PLOCK };
{
struct gfs2_file *fp = file->private_data;
struct gfs2_holder *fl_gh = &fp->f_fl_gh;
- struct gfs2_inode *ip = file->f_dentry->d_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(file->f_dentry->d_inode);
struct gfs2_glock *gl;
unsigned int state;
int flags;
&(struct file_lock){.fl_type = F_UNLCK});
gfs2_glock_dq_uninit(fl_gh);
} else {
- error = gfs2_glock_get(ip->i_sbd,
+ error = gfs2_glock_get(GFS2_SB(&ip->i_inode),
ip->i_num.no_addr, &gfs2_flock_glops,
CREATE, &gl);
if (error)
error = -EAGAIN;
} else {
error = flock_lock_file_wait(file, fl);
- gfs2_assert_warn(ip->i_sbd, !error);
+ gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error);
}
out:
static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl)
{
- struct gfs2_inode *ip = file->f_mapping->host->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
+ struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
if (!(fl->fl_flags & FL_FLOCK))
return -ENOLCK;
#include "recovery.h"
#include "rgrp.h"
#include "super.h"
-#include "unlinked.h"
#include "sys.h"
#include "util.h"
spin_lock_init(&sdp->sd_jindex_spin);
mutex_init(&sdp->sd_jindex_mutex);
- INIT_LIST_HEAD(&sdp->sd_unlinked_list);
- spin_lock_init(&sdp->sd_unlinked_spin);
- mutex_init(&sdp->sd_unlinked_mutex);
-
INIT_LIST_HEAD(&sdp->sd_quota_list);
spin_lock_init(&sdp->sd_quota_spin);
mutex_init(&sdp->sd_quota_mutex);
return 0;
- fail_trans:
+fail_trans:
gfs2_glock_put(sdp->sd_trans_gl);
- fail_rename:
+fail_rename:
gfs2_glock_put(sdp->sd_rename_gl);
- fail_live:
+fail_live:
gfs2_glock_dq_uninit(&sdp->sd_live_gh);
- fail_mount:
+fail_mount:
gfs2_glock_dq_uninit(mount_gh);
- fail:
+fail:
while (sdp->sd_glockd_num--)
kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]);
return error;
}
-static struct inode *gfs2_lookup_root(struct gfs2_sbd *sdp,
- const struct gfs2_inum *inum)
+static struct inode *gfs2_lookup_root(struct super_block *sb,
+ struct gfs2_inum *inum)
{
- int error;
- struct gfs2_glock *gl;
- struct gfs2_inode *ip;
- struct inode *inode;
-
- error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_inode_glops,
- CREATE, &gl);
- if (!error) {
- error = gfs2_inode_get(gl, inum, CREATE, &ip);
- if (!error) {
- gfs2_inode_min_init(ip, DT_DIR);
- inode = gfs2_ip2v(ip);
- gfs2_inode_put(ip);
- gfs2_glock_put(gl);
- return inode;
- }
- gfs2_glock_put(gl);
- }
- return ERR_PTR(error);
+ return gfs2_inode_lookup(sb, inum, DT_DIR);
}
static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
return 0;
}
- error = gfs2_glock_nq_num(sdp,
- GFS2_SB_LOCK, &gfs2_meta_glops,
+ error = gfs2_glock_nq_num(sdp, GFS2_SB_LOCK, &gfs2_meta_glops,
LM_ST_SHARED, 0, &sb_gh);
if (error) {
fs_err(sdp, "can't acquire superblock glock: %d\n", error);
inum = &sdp->sd_sb.sb_root_dir;
if (sb->s_type == &gfs2meta_fs_type)
inum = &sdp->sd_sb.sb_master_dir;
- inode = gfs2_lookup_root(sdp, inum);
+ inode = gfs2_lookup_root(sb, inum);
if (IS_ERR(inode)) {
error = PTR_ERR(inode);
fs_err(sdp, "can't read in root inode: %d\n", error);
fs_err(sdp, "can't lookup journal index: %d\n", error);
return PTR_ERR(sdp->sd_jindex);
}
- ip = sdp->sd_jindex->u.generic_ip;
+ ip = GFS2_I(sdp->sd_jindex);
set_bit(GLF_STICKY, &ip->i_gl->gl_flags);
/* Load in the journal index special file */
}
sdp->sd_jdesc = gfs2_jdesc_find(sdp, sdp->sd_lockstruct.ls_jid);
- error = gfs2_glock_nq_num(sdp,
- sdp->sd_lockstruct.ls_jid,
+ error = gfs2_glock_nq_num(sdp, sdp->sd_lockstruct.ls_jid,
&gfs2_journal_glops,
LM_ST_EXCLUSIVE, LM_FLAG_NOEXP,
&sdp->sd_journal_gh);
goto fail_jindex;
}
- ip = sdp->sd_jdesc->jd_inode->u.generic_ip;
- error = gfs2_glock_nq_init(ip->i_gl,
- LM_ST_SHARED,
+ ip = GFS2_I(sdp->sd_jdesc->jd_inode);
+ error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
LM_FLAG_NOEXP | GL_EXACT,
&sdp->sd_jinode_gh);
if (error) {
if (undo)
goto fail_qinode;
- inode = gfs2_lookup_root(sdp, &sdp->sd_sb.sb_master_dir);
+ inode = gfs2_lookup_root(sdp->sd_vfs, &sdp->sd_sb.sb_master_dir);
if (IS_ERR(inode)) {
error = PTR_ERR(inode);
fs_err(sdp, "can't read in master directory: %d\n", error);
fs_err(sdp, "can't get resource index inode: %d\n", error);
goto fail_statfs;
}
- ip = sdp->sd_rindex->u.generic_ip;
+ ip = GFS2_I(sdp->sd_rindex);
set_bit(GLF_STICKY, &ip->i_gl->gl_flags);
sdp->sd_rindex_vn = ip->i_gl->gl_vn - 1;
goto fail_ir_i;
}
- sprintf(buf, "unlinked_tag%u", sdp->sd_jdesc->jd_jid);
- sdp->sd_ut_inode = gfs2_lookup_simple(pn, buf);
- if (IS_ERR(sdp->sd_ut_inode)) {
- error = PTR_ERR(sdp->sd_ut_inode);
- fs_err(sdp, "can't find local \"ut\" file: %d\n", error);
- goto fail_sc_i;
- }
-
sprintf(buf, "quota_change%u", sdp->sd_jdesc->jd_jid);
sdp->sd_qc_inode = gfs2_lookup_simple(pn, buf);
if (IS_ERR(sdp->sd_qc_inode)) {
iput(pn);
pn = NULL;
- ip = sdp->sd_ir_inode->u.generic_ip;
+ ip = GFS2_I(sdp->sd_ir_inode);
error = gfs2_glock_nq_init(ip->i_gl,
LM_ST_EXCLUSIVE, 0,
&sdp->sd_ir_gh);
goto fail_qc_i;
}
- ip = sdp->sd_sc_inode->u.generic_ip;
+ ip = GFS2_I(sdp->sd_sc_inode);
error = gfs2_glock_nq_init(ip->i_gl,
LM_ST_EXCLUSIVE, 0,
&sdp->sd_sc_gh);
goto fail_ir_gh;
}
- ip = sdp->sd_ut_inode->u.generic_ip;
- error = gfs2_glock_nq_init(ip->i_gl,
- LM_ST_EXCLUSIVE, 0,
- &sdp->sd_ut_gh);
- if (error) {
- fs_err(sdp, "can't lock local \"ut\" file: %d\n", error);
- goto fail_sc_gh;
- }
-
- ip = sdp->sd_qc_inode->u.generic_ip;
+ ip = GFS2_I(sdp->sd_qc_inode);
error = gfs2_glock_nq_init(ip->i_gl,
LM_ST_EXCLUSIVE, 0,
&sdp->sd_qc_gh);
gfs2_glock_dq_uninit(&sdp->sd_qc_gh);
fail_ut_gh:
- gfs2_glock_dq_uninit(&sdp->sd_ut_gh);
- fail_sc_gh:
gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
fail_ir_gh:
iput(sdp->sd_qc_inode);
fail_ut_i:
- iput(sdp->sd_ut_inode);
- fail_sc_i:
iput(sdp->sd_sc_inode);
fail_ir_i:
int error = 0;
if (undo)
- goto fail_inoded;
+ goto fail_quotad;
sdp->sd_log_flush_time = jiffies;
sdp->sd_jindex_refresh_time = jiffies;
}
sdp->sd_quotad_process = p;
- p = kthread_run(gfs2_inoded, sdp, "gfs2_inoded");
- error = IS_ERR(p);
- if (error) {
- fs_err(sdp, "can't start inoded thread: %d\n", error);
- goto fail_quotad;
- }
- sdp->sd_inoded_process = p;
-
return 0;
- fail_inoded:
- kthread_stop(sdp->sd_inoded_process);
- fail_quotad:
+fail_quotad:
kthread_stop(sdp->sd_quotad_process);
-
- fail:
+fail:
kthread_stop(sdp->sd_logd_process);
-
return error;
}
#include "quota.h"
#include "rgrp.h"
#include "trans.h"
-#include "unlinked.h"
#include "util.h"
/**
static int gfs2_create(struct inode *dir, struct dentry *dentry,
int mode, struct nameidata *nd)
{
- struct gfs2_inode *dip = dir->u.generic_ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_inode *dip = GFS2_I(dir);
+ struct gfs2_sbd *sdp = GFS2_SB(dir);
struct gfs2_holder ghs[2];
struct inode *inode;
int new = 1;
static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *dentry)
{
- struct gfs2_inode *dip = dir->u.generic_ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_inode *dip = GFS2_I(dir);
+ struct gfs2_sbd *sdp = GFS2_SB(dir);
struct inode *inode = old_dentry->d_inode;
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder ghs[2];
int alloc_required;
int error;
error = gfs2_change_nlink(ip, +1);
- out_end_trans:
+out_end_trans:
gfs2_trans_end(sdp);
- out_ipres:
+out_ipres:
if (alloc_required)
gfs2_inplace_release(dip);
- out_gunlock_q:
+out_gunlock_q:
if (alloc_required)
gfs2_quota_unlock(dip);
- out_alloc:
+out_alloc:
if (alloc_required)
gfs2_alloc_put(dip);
- out_gunlock:
+out_gunlock:
gfs2_glock_dq_m(2, ghs);
- out:
+out:
gfs2_holder_uninit(ghs);
gfs2_holder_uninit(ghs + 1);
if (!error) {
- atomic_inc(&inode->i_count);
d_instantiate(dentry, inode);
mark_inode_dirty(inode);
}
static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
{
- struct gfs2_inode *dip = dir->u.generic_ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
- struct gfs2_inode *ip = dentry->d_inode->u.generic_ip;
- struct gfs2_unlinked *ul;
+ struct gfs2_inode *dip = GFS2_I(dir);
+ struct gfs2_sbd *sdp = GFS2_SB(dir);
+ struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
struct gfs2_holder ghs[2];
int error;
- error = gfs2_unlinked_get(sdp, &ul);
- if (error)
- return error;
-
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
if (error)
goto out_gunlock;
- error = gfs2_trans_begin(sdp, 2 * RES_DINODE + RES_LEAF +
- RES_UNLINKED, 0);
+ error = gfs2_trans_begin(sdp, 2*RES_DINODE + RES_LEAF + RES_RG_BIT, 0);
if (error)
goto out_gunlock;
- error = gfs2_unlinki(dip, &dentry->d_name, ip, ul);
+ error = gfs2_dir_del(dip, &dentry->d_name);
+ if (error)
+ goto out_end_trans;
- gfs2_trans_end(sdp);
+ error = gfs2_change_nlink(ip, -1);
- out_gunlock:
+out_end_trans:
+ gfs2_trans_end(sdp);
+out_gunlock:
gfs2_glock_dq_m(2, ghs);
-
- out:
+out:
gfs2_holder_uninit(ghs);
gfs2_holder_uninit(ghs + 1);
-
- gfs2_unlinked_put(sdp, ul);
-
return error;
}
static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
const char *symname)
{
- struct gfs2_inode *dip = dir->u.generic_ip, *ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_inode *dip = GFS2_I(dir), *ip;
+ struct gfs2_sbd *sdp = GFS2_SB(dir);
struct gfs2_holder ghs[2];
struct inode *inode;
struct buffer_head *dibh;
static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
- struct gfs2_inode *dip = dir->u.generic_ip, *ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_inode *dip = GFS2_I(dir), *ip;
+ struct gfs2_sbd *sdp = GFS2_SB(dir);
struct gfs2_holder ghs[2];
struct inode *inode;
struct buffer_head *dibh;
static int gfs2_rmdir(struct inode *dir, struct dentry *dentry)
{
- struct gfs2_inode *dip = dir->u.generic_ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
- struct gfs2_inode *ip = dentry->d_inode->u.generic_ip;
- struct gfs2_unlinked *ul;
+ struct gfs2_inode *dip = GFS2_I(dir);
+ struct gfs2_sbd *sdp = GFS2_SB(dir);
+ struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
struct gfs2_holder ghs[2];
int error;
- error = gfs2_unlinked_get(sdp, &ul);
- if (error)
- return error;
-
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
goto out_gunlock;
}
- error = gfs2_trans_begin(sdp, 2 * RES_DINODE + 3 * RES_LEAF +
- RES_UNLINKED, 0);
+ error = gfs2_trans_begin(sdp, 2 * RES_DINODE + 3 * RES_LEAF + RES_RG_BIT, 0);
if (error)
goto out_gunlock;
- error = gfs2_rmdiri(dip, &dentry->d_name, ip, ul);
+ error = gfs2_rmdiri(dip, &dentry->d_name, ip);
gfs2_trans_end(sdp);
gfs2_holder_uninit(ghs);
gfs2_holder_uninit(ghs + 1);
- gfs2_unlinked_put(sdp, ul);
-
return error;
}
static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode,
dev_t dev)
{
- struct gfs2_inode *dip = dir->u.generic_ip, *ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_inode *dip = GFS2_I(dir), *ip;
+ struct gfs2_sbd *sdp = GFS2_SB(dir);
struct gfs2_holder ghs[2];
struct inode *inode;
struct buffer_head *dibh;
static int gfs2_rename(struct inode *odir, struct dentry *odentry,
struct inode *ndir, struct dentry *ndentry)
{
- struct gfs2_inode *odip = odir->u.generic_ip;
- struct gfs2_inode *ndip = ndir->u.generic_ip;
- struct gfs2_inode *ip = odentry->d_inode->u.generic_ip;
+ struct gfs2_inode *odip = GFS2_I(odir);
+ struct gfs2_inode *ndip = GFS2_I(ndir);
+ struct gfs2_inode *ip = GFS2_I(odentry->d_inode);
struct gfs2_inode *nip = NULL;
- struct gfs2_sbd *sdp = odip->i_sbd;
- struct gfs2_unlinked *ul;
+ struct gfs2_sbd *sdp = GFS2_SB(odir);
struct gfs2_holder ghs[4], r_gh;
unsigned int num_gh;
int dir_rename = 0;
int error;
if (ndentry->d_inode) {
- nip = ndentry->d_inode->u.generic_ip;
+ nip = GFS2_I(ndentry->d_inode);
if (ip == nip)
return 0;
}
- error = gfs2_unlinked_get(sdp, &ul);
- if (error)
- return error;
-
/* Make sure we aren't trying to move a dirctory into it's subdir */
if (S_ISDIR(ip->i_di.di_mode) && odip != ndip) {
error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
al->al_rgd->rd_ri.ri_length +
4 * RES_DINODE + 4 * RES_LEAF +
- RES_UNLINKED + RES_STATFS +
- RES_QUOTA, 0);
+ RES_STATFS + RES_QUOTA, 0);
if (error)
goto out_ipreserv;
} else {
error = gfs2_trans_begin(sdp, 4 * RES_DINODE +
- 5 * RES_LEAF +
- RES_UNLINKED, 0);
+ 5 * RES_LEAF, 0);
if (error)
goto out_gunlock;
}
if (nip) {
if (S_ISDIR(nip->i_di.di_mode))
- error = gfs2_rmdiri(ndip, &ndentry->d_name, nip, ul);
- else
- error = gfs2_unlinki(ndip, &ndentry->d_name, nip, ul);
+ error = gfs2_rmdiri(ndip, &ndentry->d_name, nip);
+ else {
+ error = gfs2_dir_del(ndip, &ndentry->d_name);
+ if (error)
+ goto out_end_trans;
+ error = gfs2_change_nlink(nip, -1);
+ }
if (error)
goto out_end_trans;
}
if (error)
goto out_end_trans;
- out_end_trans:
+out_end_trans:
gfs2_trans_end(sdp);
-
- out_ipreserv:
+out_ipreserv:
if (alloc_required)
gfs2_inplace_release(ndip);
-
- out_gunlock_q:
+out_gunlock_q:
if (alloc_required)
gfs2_quota_unlock(ndip);
-
- out_alloc:
+out_alloc:
if (alloc_required)
gfs2_alloc_put(ndip);
-
- out_gunlock:
+out_gunlock:
gfs2_glock_dq_m(num_gh, ghs);
-
- out_uninit:
+out_uninit:
for (x = 0; x < num_gh; x++)
gfs2_holder_uninit(ghs + x);
-
- out_gunlock_r:
+out_gunlock_r:
if (dir_rename)
gfs2_glock_dq_uninit(&r_gh);
-
- out:
- gfs2_unlinked_put(sdp, ul);
-
+out:
return error;
}
static int gfs2_readlink(struct dentry *dentry, char __user *user_buf,
int user_size)
{
- struct gfs2_inode *ip = dentry->d_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
char array[GFS2_FAST_NAME_SIZE], *buf = array;
unsigned int len = GFS2_FAST_NAME_SIZE;
int error;
static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
{
- struct gfs2_inode *ip = dentry->d_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
char array[GFS2_FAST_NAME_SIZE], *buf = array;
unsigned int len = GFS2_FAST_NAME_SIZE;
int error;
static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder i_gh;
int error;
static int setattr_size(struct inode *inode, struct iattr *attr)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
int error;
if (attr->ia_size != ip->i_di.di_size) {
static int setattr_chown(struct inode *inode, struct iattr *attr)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
struct buffer_head *dibh;
uint32_t ouid, ogid, nuid, ngid;
int error;
static int gfs2_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder i_gh;
int error;
struct kstat *stat)
{
struct inode *inode = dentry->d_inode;
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder gh;
int error;
static int gfs2_setxattr(struct dentry *dentry, const char *name,
const void *data, size_t size, int flags)
{
- struct gfs2_inode *ip = dentry->d_inode->u.generic_ip;
+ struct inode *inode = dentry->d_inode;
struct gfs2_ea_request er;
memset(&er, 0, sizeof(struct gfs2_ea_request));
er.er_data_len = size;
er.er_flags = flags;
- gfs2_assert_warn(ip->i_sbd, !(er.er_flags & GFS2_ERF_MODE));
+ gfs2_assert_warn(GFS2_SB(inode), !(er.er_flags & GFS2_ERF_MODE));
- return gfs2_ea_set(ip, &er);
+ return gfs2_ea_set(GFS2_I(inode), &er);
}
static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
er.er_name_len = strlen(er.er_name);
er.er_data_len = size;
- return gfs2_ea_get(dentry->d_inode->u.generic_ip, &er);
+ return gfs2_ea_get(GFS2_I(dentry->d_inode), &er);
}
static ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
er.er_data = (size) ? buffer : NULL;
er.er_data_len = size;
- return gfs2_ea_list(dentry->d_inode->u.generic_ip, &er);
+ return gfs2_ea_list(GFS2_I(dentry->d_inode), &er);
}
static int gfs2_removexattr(struct dentry *dentry, const char *name)
return -EOPNOTSUPP;
er.er_name_len = strlen(er.er_name);
- return gfs2_ea_remove(dentry->d_inode->u.generic_ip, &er);
+ return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er);
}
struct inode_operations gfs2_file_iops = {
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/gfs2_ondisk.h>
+#include <linux/crc32.h>
#include "gfs2.h"
#include "lm_interface.h"
#include "super.h"
#include "sys.h"
#include "util.h"
+#include "trans.h"
+#include "dir.h"
+#include "eattr.h"
+#include "bmap.h"
/**
* gfs2_write_inode - Make sure the inode is stable on the disk
static int gfs2_write_inode(struct inode *inode, int sync)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
-
- if (current->flags & PF_MEMALLOC)
- return 0;
- if (ip && sync)
- gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl);
+ struct gfs2_inode *ip = GFS2_I(inode);
+
+ /* Check this is a "normal" inode */
+ if (inode->u.generic_ip) {
+ if (current->flags & PF_MEMALLOC)
+ return 0;
+ if (sync)
+ gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl);
+ }
return 0;
}
gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
mutex_unlock(&sdp->sd_freeze_lock);
- kthread_stop(sdp->sd_inoded_process);
kthread_stop(sdp->sd_quotad_process);
kthread_stop(sdp->sd_logd_process);
kthread_stop(sdp->sd_recoverd_process);
gfs2_glock_dq_uninit(&sdp->sd_jinode_gh);
gfs2_glock_dq_uninit(&sdp->sd_ir_gh);
gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
- gfs2_glock_dq_uninit(&sdp->sd_ut_gh);
gfs2_glock_dq_uninit(&sdp->sd_qc_gh);
iput(sdp->sd_ir_inode);
iput(sdp->sd_sc_inode);
- iput(sdp->sd_ut_inode);
iput(sdp->sd_qc_inode);
}
static void gfs2_clear_inode(struct inode *inode)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
-
- if (ip) {
- spin_lock(&ip->i_spin);
- ip->i_vnode = NULL;
- inode->u.generic_ip = NULL;
- spin_unlock(&ip->i_spin);
-
+ /* This tells us its a "real" inode and not one which only
+ * serves to contain an address space (see rgrp.c, meta_io.c)
+ * which therefore doesn't have its own glocks.
+ */
+ if (inode->u.generic_ip) {
+ struct gfs2_inode *ip = GFS2_I(inode);
+ gfs2_glock_inode_squish(inode);
+ gfs2_assert(inode->i_sb->s_fs_info, ip->i_gl->gl_state == LM_ST_UNLOCKED);
+ ip->i_gl->gl_object = NULL;
gfs2_glock_schedule_for_reclaim(ip->i_gl);
- gfs2_inode_put(ip);
+ gfs2_glock_put(ip->i_gl);
+ ip->i_gl = NULL;
+ if (ip->i_iopen_gh.gh_gl)
+ gfs2_glock_dq_uninit(&ip->i_iopen_gh);
}
}
return 0;
}
+/*
+ * We have to (at the moment) hold the inodes main lock to cover
+ * the gap between unlocking the shared lock on the iopen lock and
+ * taking the exclusive lock. I'd rather do a shared -> exclusive
+ * conversion on the iopen lock, but we can change that later. This
+ * is safe, just less efficient.
+ */
+static void gfs2_delete_inode(struct inode *inode)
+{
+ struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_holder gh;
+ int error;
+
+ if (!inode->u.generic_ip)
+ goto out;
+
+ error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &gh);
+ if (unlikely(error)) {
+ gfs2_glock_dq_uninit(&ip->i_iopen_gh);
+ goto out;
+ }
+
+ gfs2_glock_dq(&ip->i_iopen_gh);
+ gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh);
+ error = gfs2_glock_nq(&ip->i_iopen_gh);
+ if (error)
+ goto out_uninit;
+
+ if (S_ISDIR(ip->i_di.di_mode) &&
+ (ip->i_di.di_flags & GFS2_DIF_EXHASH)) {
+ error = gfs2_dir_exhash_dealloc(ip);
+ if (error)
+ goto out_unlock;
+ }
+
+ if (ip->i_di.di_eattr) {
+ error = gfs2_ea_dealloc(ip);
+ if (error)
+ goto out_unlock;
+ }
+
+ if (!gfs2_is_stuffed(ip)) {
+ error = gfs2_file_dealloc(ip);
+ if (error)
+ goto out_unlock;
+ }
+
+ error = gfs2_dinode_dealloc(ip);
+
+out_unlock:
+ gfs2_glock_dq(&ip->i_iopen_gh);
+out_uninit:
+ gfs2_holder_uninit(&ip->i_iopen_gh);
+ gfs2_glock_dq_uninit(&gh);
+ if (error)
+ fs_warn(sdp, "gfs2_delete_inode: %d\n", error);
+out:
+ truncate_inode_pages(&inode->i_data, 0);
+ clear_inode(inode);
+}
+
+
+
static struct inode *gfs2_alloc_inode(struct super_block *sb)
{
struct gfs2_sbd *sdp = sb->s_fs_info;
if (ip) {
ip->i_flags = 0;
ip->i_gl = NULL;
- ip->i_sbd = sdp;
- ip->i_vnode = &ip->i_inode;
ip->i_greedy = gfs2_tune_get(sdp, gt_greedy_default);
ip->i_last_pfault = jiffies;
}
.alloc_inode = gfs2_alloc_inode,
.destroy_inode = gfs2_destroy_inode,
.write_inode = gfs2_write_inode,
+ .delete_inode = gfs2_delete_inode,
.put_super = gfs2_put_super,
.write_super = gfs2_write_super,
.write_super_lockfs = gfs2_write_super_lockfs,
ip->i_last_pfault = jiffies;
spin_unlock(&ip->i_spin);
- gfs2_inode_hold(ip);
+ igrab(&ip->i_inode);
if (gfs2_glock_be_greedy(ip->i_gl, time))
- gfs2_inode_put(ip);
+ iput(&ip->i_inode);
}
static struct page *gfs2_private_nopage(struct vm_area_struct *area,
unsigned long address, int *type)
{
- struct gfs2_inode *ip = area->vm_file->f_mapping->host->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(area->vm_file->f_mapping->host);
struct gfs2_holder i_gh;
struct page *result;
int error;
static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
unsigned long index = page->index;
uint64_t lblock = index << (PAGE_CACHE_SHIFT -
sdp->sd_sb.sb_bsize_shift);
unsigned int extlen;
int new = 1;
- error = gfs2_extent_map(ip->i_vnode, lblock, &new, &dblock, &extlen);
+ error = gfs2_extent_map(&ip->i_inode, lblock, &new, &dblock, &extlen);
if (error)
goto out_trans;
static struct page *gfs2_sharewrite_nopage(struct vm_area_struct *area,
unsigned long address, int *type)
{
- struct gfs2_inode *ip = area->vm_file->f_mapping->host->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(area->vm_file->f_mapping->host);
struct gfs2_holder i_gh;
struct page *result = NULL;
unsigned long index = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) +
struct inode *inode;
ip = gl->gl_object;
+ inode = &ip->i_inode;
if (!ip || !S_ISREG(ip->i_di.di_mode))
return;
if (!test_bit(GIF_PAGED, &ip->i_flags))
return;
- inode = gfs2_ip2v_lookup(ip);
- if (inode) {
- unmap_shared_mapping_range(inode->i_mapping, 0, 0);
- iput(inode);
+ unmap_shared_mapping_range(inode->i_mapping, 0, 0);
- if (test_bit(GIF_SW_PAGED, &ip->i_flags))
- set_bit(GLF_DIRTY, &gl->gl_flags);
- }
+ if (test_bit(GIF_SW_PAGED, &ip->i_flags))
+ set_bit(GLF_DIRTY, &gl->gl_flags);
clear_bit(GIF_SW_PAGED, &ip->i_flags);
}
struct inode *inode;
ip = gl->gl_object;
+ inode = &ip->i_inode;
if (!ip || !S_ISREG(ip->i_di.di_mode))
return;
- inode = gfs2_ip2v_lookup(ip);
- if (inode) {
- struct address_space *mapping = inode->i_mapping;
-
- truncate_inode_pages(mapping, 0);
- gfs2_assert_withdraw(ip->i_sbd, !mapping->nrpages);
-
- iput(inode);
- }
-
+ truncate_inode_pages(inode->i_mapping, 0);
+ gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !inode->i_mapping->nrpages);
clear_bit(GIF_PAGED, &ip->i_flags);
}
{
struct gfs2_inode *ip;
struct inode *inode;
+ struct address_space *mapping;
+ int error = 0;
ip = gl->gl_object;
+ inode = &ip->i_inode;
if (!ip || !S_ISREG(ip->i_di.di_mode))
return;
- inode = gfs2_ip2v_lookup(ip);
- if (inode) {
- struct address_space *mapping = inode->i_mapping;
- int error = 0;
+ mapping = inode->i_mapping;
- if (flags & DIO_START)
- filemap_fdatawrite(mapping);
- if (!error && (flags & DIO_WAIT))
- error = filemap_fdatawait(mapping);
+ if (flags & DIO_START)
+ filemap_fdatawrite(mapping);
+ if (!error && (flags & DIO_WAIT))
+ error = filemap_fdatawait(mapping);
- /* Put back any errors cleared by filemap_fdatawait()
- so they can be caught by someone who can pass them
- up to user space. */
+ /* Put back any errors cleared by filemap_fdatawait()
+ so they can be caught by someone who can pass them
+ up to user space. */
- if (error == -ENOSPC)
- set_bit(AS_ENOSPC, &mapping->flags);
- else if (error)
- set_bit(AS_EIO, &mapping->flags);
+ if (error == -ENOSPC)
+ set_bit(AS_ENOSPC, &mapping->flags);
+ else if (error)
+ set_bit(AS_EIO, &mapping->flags);
- iput(inode);
- }
}
/**
int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
uint64_t block, void *private)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct inode *inode = ip->i_vnode;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ struct inode *inode = &ip->i_inode;
struct page *page = (struct page *)private;
struct buffer_head *bh;
int release = 0;
int gfs2_block_truncate_page(struct address_space *mapping)
{
struct inode *inode = mapping->host;
- struct gfs2_inode *ip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
loff_t from = inode->i_size;
unsigned long index = from >> PAGE_CACHE_SHIFT;
unsigned offset = from & (PAGE_CACHE_SIZE-1);
static int bh_get(struct gfs2_quota_data *qd)
{
struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
- struct gfs2_inode *ip = sdp->sd_qc_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
unsigned int block, offset;
uint64_t dblock;
int new = 0;
block = qd->qd_slot / sdp->sd_qc_per_block;
offset = qd->qd_slot % sdp->sd_qc_per_block;;
- error = gfs2_block_map(ip->i_vnode, block, &new, &dblock, &boundary);
+ error = gfs2_block_map(&ip->i_inode, block, &new, &dblock, &boundary);
if (error)
goto fail;
error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT, &bh);
int gfs2_quota_hold(struct gfs2_inode *ip, uint32_t uid, uint32_t gid)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc;
struct gfs2_quota_data **qd = al->al_qd;
int error;
void gfs2_quota_unhold(struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc;
unsigned int x;
static void do_qc(struct gfs2_quota_data *qd, int64_t change)
{
struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
- struct gfs2_inode *ip = sdp->sd_qc_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
struct gfs2_quota_change *qc = qd->qd_bh_qc;
int64_t x;
static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
int64_t change, struct gfs2_quota_data *qd)
{
- struct inode *inode = ip->i_vnode;
+ struct inode *inode = &ip->i_inode;
struct address_space *mapping = inode->i_mapping;
unsigned long index = loc >> PAGE_CACHE_SHIFT;
unsigned offset = loc & (PAGE_CACHE_SHIFT - 1);
static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
{
struct gfs2_sbd *sdp = (*qda)->qd_gl->gl_sbd;
- struct gfs2_inode *ip = sdp->sd_quota_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
unsigned int data_blocks, ind_blocks;
struct file_ra_state ra_state;
struct gfs2_holder *ghs, i_gh;
goto out_gunlock;
}
- file_ra_state_init(&ra_state, ip->i_vnode->i_mapping);
+ file_ra_state_init(&ra_state, ip->i_inode.i_mapping);
for (x = 0; x < num_qd; x++) {
qd = qda[x];
offset = qd2offset(qd);
struct gfs2_holder *q_gh)
{
struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
- struct gfs2_inode *ip = sdp->sd_quota_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
struct gfs2_holder i_gh;
struct gfs2_quota q;
char buf[sizeof(struct gfs2_quota)];
int gfs2_quota_lock(struct gfs2_inode *ip, uint32_t uid, uint32_t gid)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc;
unsigned int x;
int error = 0;
int gfs2_quota_check(struct gfs2_inode *ip, uint32_t uid, uint32_t gid)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc;
struct gfs2_quota_data *qd;
int64_t value;
unsigned int x;
unsigned int found = 0;
- if (gfs2_assert_warn(ip->i_sbd, change))
+ if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change))
return;
if (ip->i_di.di_flags & GFS2_DIF_SYSTEM)
return;
int gfs2_quota_init(struct gfs2_sbd *sdp)
{
- struct gfs2_inode *ip = sdp->sd_qc_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
unsigned int blocks = ip->i_di.di_size >> sdp->sd_sb.sb_bsize_shift;
unsigned int x, slot = 0;
unsigned int found = 0;
if (!extlen) {
int new = 0;
- error = gfs2_extent_map(ip->i_vnode, x, &new, &dblock, &extlen);
+ error = gfs2_extent_map(&ip->i_inode, x, &new, &dblock, &extlen);
if (error)
goto fail;
}
int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
struct buffer_head **bh)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
struct gfs2_glock *gl = ip->i_gl;
int new = 0;
uint64_t dblock;
uint32_t extlen;
int error;
- error = gfs2_extent_map(ip->i_vnode, blk, &new, &dblock, &extlen);
+ error = gfs2_extent_map(&ip->i_inode, blk, &new, &dblock, &extlen);
if (error)
return error;
if (!dblock) {
*blk = 0;
if (*blk == orig_blk) {
- gfs2_consist_inode(jd->jd_inode->u.generic_ip);
+ gfs2_consist_inode(GFS2_I(jd->jd_inode));
return -EIO;
}
}
continue;
if (lh.lh_sequence == head->lh_sequence) {
- gfs2_consist_inode(jd->jd_inode->u.generic_ip);
+ gfs2_consist_inode(GFS2_I(jd->jd_inode));
return -EIO;
}
if (lh.lh_sequence < head->lh_sequence)
static int foreach_descriptor(struct gfs2_jdesc *jd, unsigned int start,
unsigned int end, int pass)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
struct buffer_head *bh;
struct gfs2_log_descriptor *ld;
int error = 0;
continue;
}
if (error == 1) {
- gfs2_consist_inode(jd->jd_inode->u.generic_ip);
+ gfs2_consist_inode(GFS2_I(jd->jd_inode));
error = -EIO;
}
brelse(bh);
static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header *head)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
unsigned int lblock;
int new = 0;
uint64_t dblock;
lblock = head->lh_blkno;
gfs2_replay_incr_blk(sdp, &lblock);
- error = gfs2_block_map(ip->i_vnode, lblock, &new, &dblock, &boundary);
+ error = gfs2_block_map(&ip->i_inode, lblock, &new, &dblock, &boundary);
if (error)
return error;
if (!dblock) {
int gfs2_recover_journal(struct gfs2_jdesc *jd)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
struct gfs2_log_header head;
struct gfs2_holder j_gh, ji_gh, t_gh;
unsigned long t;
/*
* These routines are used by the resource group routines (rgrp.c)
* to keep track of block allocation. Each block is represented by two
- * bits. One bit indicates whether or not the block is used. (1=used,
- * 0=free) The other bit indicates whether or not the block contains a
- * dinode or not. (1=dinode, 0=not-dinode) So, each byte represents
- * GFS2_NBBY (i.e. 4) blocks.
+ * bits. So, each byte represents GFS2_NBBY (i.e. 4) blocks.
+ *
+ * 0 = Free
+ * 1 = Used (not metadata)
+ * 2 = Unlinked (still in use) inode
+ * 3 = Used (metadata)
*/
static const char valid_change[16] = {
/* current */
- /* n */ 0, 1, 0, 1,
+ /* n */ 0, 1, 1, 1,
/* e */ 1, 0, 0, 0,
- /* w */ 0, 0, 0, 0,
+ /* w */ 0, 0, 0, 1,
1, 0, 0, 0
};
tmp = rgd->rd_ri.ri_data -
rgd->rd_rg.rg_free -
rgd->rd_rg.rg_dinodes;
- if (count[1] != tmp) {
+ if (count[1] + count[2] != tmp) {
if (gfs2_consist_rgrpd(rgd))
fs_err(sdp, "used data mismatch: %u != %u\n",
count[1], tmp);
return;
}
- if (count[2]) {
+ if (count[3] != rgd->rd_rg.rg_dinodes) {
if (gfs2_consist_rgrpd(rgd))
- fs_err(sdp, "free metadata mismatch: %u != 0\n",
- count[2]);
+ fs_err(sdp, "used metadata mismatch: %u != %u\n",
+ count[3], rgd->rd_rg.rg_dinodes);
return;
}
- if (count[3] != rgd->rd_rg.rg_dinodes) {
+ if (count[2] > count[3]) {
if (gfs2_consist_rgrpd(rgd))
- fs_err(sdp, "used metadata mismatch: %u != %u\n",
- count[3], rgd->rd_rg.rg_dinodes);
+ fs_err(sdp, "unlinked inodes > inodes: %u\n",
+ count[2]);
return;
}
+
}
static inline int rgrp_contains_block(struct gfs2_rindex *ri, uint64_t block)
uint32_t bytes_left, bytes;
int x;
+ if (!length)
+ return -EINVAL;
+
rgd->rd_bits = kcalloc(length, sizeof(struct gfs2_bitmap), GFP_KERNEL);
if (!rgd->rd_bits)
return -ENOMEM;
static int gfs2_ri_update(struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct inode *inode = ip->i_vnode;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ struct inode *inode = &ip->i_inode;
struct gfs2_rgrpd *rgd;
char buf[sizeof(struct gfs2_rindex)];
struct file_ra_state ra_state;
uint64_t junk = ip->i_di.di_size;
int error;
+ printk(KERN_INFO "gfs2_ri_update inode=%p\n", inode);
+
if (do_div(junk, sizeof(struct gfs2_rindex))) {
gfs2_consist_inode(ip);
return -EIO;
clear_rgrpdi(sdp);
+ printk(KERN_INFO "rgrps cleared\n");
+
file_ra_state_init(&ra_state, inode->i_mapping);
for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
+ printk(KERN_INFO "reading rgrp %d\n", sdp->sd_rgrps);
error = gfs2_internal_read(ip, &ra_state, buf, &pos,
sizeof(struct gfs2_rindex));
if (!error)
list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
gfs2_rindex_in(&rgd->rd_ri, buf);
-
+ printk(KERN_INFO "compute bitstructs\n");
error = compute_bitstructs(rgd);
if (error)
goto fail;
+ printk(KERN_INFO "gfs2_glock_get\n");
error = gfs2_glock_get(sdp, rgd->rd_ri.ri_addr,
&gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
+ printk(KERN_INFO "gfs2_glock_got one\n");
if (error)
goto fail;
rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
}
+ printk(KERN_INFO "ok, finished\n");
sdp->sd_rindex_vn = ip->i_gl->gl_vn;
-
return 0;
- fail:
+fail:
+ printk(KERN_INFO "fail\n");
clear_rgrpdi(sdp);
-
+ printk(KERN_INFO "cleared rgrps\n");
return error;
}
int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh)
{
- struct gfs2_inode *ip = sdp->sd_rindex->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(sdp->sd_rindex);
struct gfs2_glock *gl = ip->i_gl;
int error;
error = gfs2_meta_reread(sdp, bi->bi_bh, DIO_WAIT);
if (error)
goto fail;
- if (gfs2_metatype_check(sdp, bi->bi_bh,
- (y) ? GFS2_METATYPE_RB :
+ if (gfs2_metatype_check(sdp, bi->bi_bh, y ? GFS2_METATYPE_RB :
GFS2_METATYPE_RG)) {
error = -EIO;
goto fail;
return 0;
- fail:
+fail:
while (x--) {
bi = rgd->rd_bits + x;
brelse(bi->bi_bh);
if (!bi->bi_clone)
continue;
memcpy(bi->bi_clone + bi->bi_offset,
- bi->bi_bh->b_data + bi->bi_offset,
- bi->bi_len);
+ bi->bi_bh->b_data + bi->bi_offset, bi->bi_len);
}
spin_lock(&sdp->sd_rindex_spin);
goto out;
}
- first:
+first:
rgd = list_entry(sdp->sd_rindex_recent_list.next, struct gfs2_rgrpd,
rd_recent);
-
- out:
+out:
spin_unlock(&sdp->sd_rindex_spin);
-
return rgd;
}
if (!list_empty(head))
rgd = list_entry(head->next, struct gfs2_rgrpd, rd_recent);
- out:
+out:
spin_unlock(&sdp->sd_rindex_spin);
-
return rgd;
}
}
list_add_tail(&new_rgd->rd_recent, &sdp->sd_rindex_recent_list);
- out:
+out:
spin_unlock(&sdp->sd_rindex_spin);
}
static int get_local_rgrp(struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrpd *rgd, *begin = NULL;
struct gfs2_alloc *al = &ip->i_alloc;
int flags = LM_FLAG_TRY;
}
}
- out:
+out:
ip->i_last_rg_alloc = rgd->rd_ri.ri_addr;
if (begin) {
int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc;
int error;
void gfs2_inplace_release(struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc;
if (gfs2_assert_warn(sdp, al->al_alloced <= al->al_requested) == -1)
gfs2_assert(rgd->rd_sbd, buf < length);
buf_block = rgrp_block - bi->bi_start * GFS2_NBBY;
- type = gfs2_testbit(rgd,
- bi->bi_bh->b_data + bi->bi_offset,
+ type = gfs2_testbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
bi->bi_len, buf_block);
return type;
uint64_t gfs2_alloc_data(struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc;
struct gfs2_rgrpd *rgd = al->al_rgd;
uint32_t goal, blk;
uint64_t gfs2_alloc_meta(struct gfs2_inode *ip)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc;
struct gfs2_rgrpd *rgd = al->al_rgd;
uint32_t goal, blk;
uint64_t gfs2_alloc_di(struct gfs2_inode *dip)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_alloc *al = &dip->i_alloc;
struct gfs2_rgrpd *rgd = al->al_rgd;
uint32_t blk;
void gfs2_free_data(struct gfs2_inode *ip, uint64_t bstart, uint32_t blen)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrpd *rgd;
rgd = rgblk_free(sdp, bstart, blen, GFS2_BLKST_FREE);
void gfs2_free_meta(struct gfs2_inode *ip, uint64_t bstart, uint32_t blen)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrpd *rgd;
rgd = rgblk_free(sdp, bstart, blen, GFS2_BLKST_FREE);
gfs2_trans_add_rg(rgd);
gfs2_statfs_change(sdp, 0, +blen, 0);
- gfs2_quota_change(ip, -(int64_t)blen,
- ip->i_di.di_uid, ip->i_di.di_gid);
+ gfs2_quota_change(ip, -(int64_t)blen, ip->i_di.di_uid, ip->i_di.di_gid);
gfs2_meta_wipe(ip, bstart, blen);
}
+void gfs2_unlink_di(struct inode *inode)
+{
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
+ struct gfs2_rgrpd *rgd;
+ u64 blkno = ip->i_num.no_addr;
+
+ rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED);
+ if (!rgd)
+ return;
+ gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+ gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
+ gfs2_trans_add_rg(rgd);
+}
+
void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, uint64_t blkno)
{
struct gfs2_sbd *sdp = rgd->rd_sbd;
gfs2_trans_add_rg(rgd);
}
-/**
- * gfs2_free_uninit_di - free a dinode block
- * @rgd: the resource group that contains the dinode
- * @ip: the inode
- *
- */
void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip)
{
void gfs2_free_meta(struct gfs2_inode *ip, uint64_t bstart, uint32_t blen);
void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, uint64_t blkno);
void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip);
+void gfs2_unlink_di(struct inode *inode);
struct gfs2_rgrp_list {
unsigned int rl_rgrps;
#include "rgrp.h"
#include "super.h"
#include "trans.h"
-#include "unlinked.h"
#include "util.h"
/**
gt->gt_recoverd_secs = 60;
gt->gt_logd_secs = 1;
gt->gt_quotad_secs = 5;
- gt->gt_inoded_secs = 15;
gt->gt_quota_simul_sync = 64;
gt->gt_quota_warn_period = 10;
gt->gt_quota_scale_num = 1;
sdp->sd_hash_bsize = sdp->sd_sb.sb_bsize / 2;
sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1;
sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
- sdp->sd_ut_per_block = (sdp->sd_sb.sb_bsize -
- sizeof(struct gfs2_meta_header)) /
- sizeof(struct gfs2_unlinked_tag);
sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize -
sizeof(struct gfs2_meta_header)) /
sizeof(struct gfs2_quota_change);
int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
{
- struct gfs2_inode *dip = sdp->sd_jindex->u.generic_ip;
+ struct gfs2_inode *dip = GFS2_I(sdp->sd_jindex);
struct qstr name;
char buf[20];
struct gfs2_jdesc *jd;
name.len = sprintf(buf, "journal%u", sdp->sd_journals);
name.hash = gfs2_disk_hash(name.name, name.len);
- error = gfs2_dir_search(sdp->sd_jindex,
- &name, NULL, NULL);
+ error = gfs2_dir_search(sdp->sd_jindex, &name, NULL, NULL);
if (error == -ENOENT) {
error = 0;
break;
int gfs2_jdesc_check(struct gfs2_jdesc *jd)
{
- struct gfs2_inode *ip = jd->jd_inode->u.generic_ip;
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
+ struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
int ar;
int error;
- if (ip->i_di.di_size < (8 << 20) ||
- ip->i_di.di_size > (1 << 30) ||
+ if (ip->i_di.di_size < (8 << 20) || ip->i_di.di_size > (1 << 30) ||
(ip->i_di.di_size & (sdp->sd_sb.sb_bsize - 1))) {
gfs2_consist_inode(ip);
return -EIO;
}
jd->jd_blocks = ip->i_di.di_size >> sdp->sd_sb.sb_bsize_shift;
- error = gfs2_write_alloc_required(ip,
- 0, ip->i_di.di_size,
- &ar);
+ error = gfs2_write_alloc_required(ip, 0, ip->i_di.di_size, &ar);
if (!error && ar) {
gfs2_consist_inode(ip);
error = -EIO;
int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
{
- struct gfs2_inode *ip = sdp->sd_jdesc->jd_inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode);
struct gfs2_glock *j_gl = ip->i_gl;
struct gfs2_holder t_gh;
struct gfs2_log_header head;
sdp->sd_log_sequence = head.lh_sequence + 1;
gfs2_log_pointers_init(sdp, head.lh_blkno);
- error = gfs2_unlinked_init(sdp);
- if (error)
- goto fail;
error = gfs2_quota_init(sdp);
if (error)
goto fail_unlinked;
return 0;
fail_unlinked:
- gfs2_unlinked_cleanup(sdp);
fail:
t_gh.gh_flags |= GL_NOCACHE;
struct gfs2_holder t_gh;
int error;
- gfs2_unlinked_dealloc(sdp);
gfs2_quota_sync(sdp);
gfs2_statfs_sync(sdp);
if (t_gh.gh_gl)
gfs2_glock_dq_uninit(&t_gh);
- gfs2_unlinked_cleanup(sdp);
gfs2_quota_cleanup(sdp);
return error;
int gfs2_statfs_init(struct gfs2_sbd *sdp)
{
- struct gfs2_inode *m_ip = sdp->sd_statfs_inode->u.generic_ip;
+ struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
struct gfs2_statfs_change *m_sc = &sdp->sd_statfs_master;
- struct gfs2_inode *l_ip = sdp->sd_sc_inode->u.generic_ip;
+ struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
struct gfs2_statfs_change *l_sc = &sdp->sd_statfs_local;
struct buffer_head *m_bh, *l_bh;
struct gfs2_holder gh;
void gfs2_statfs_change(struct gfs2_sbd *sdp, int64_t total, int64_t free,
int64_t dinodes)
{
- struct gfs2_inode *l_ip = sdp->sd_sc_inode->u.generic_ip;
+ struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
struct gfs2_statfs_change *l_sc = &sdp->sd_statfs_local;
struct buffer_head *l_bh;
int error;
int gfs2_statfs_sync(struct gfs2_sbd *sdp)
{
- struct gfs2_inode *m_ip = sdp->sd_statfs_inode->u.generic_ip;
- struct gfs2_inode *l_ip = sdp->sd_sc_inode->u.generic_ip;
+ struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
+ struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
struct gfs2_statfs_change *m_sc = &sdp->sd_statfs_master;
struct gfs2_statfs_change *l_sc = &sdp->sd_statfs_local;
struct gfs2_holder gh;
error = -ENOMEM;
goto out;
}
- ip = jd->jd_inode->u.generic_ip;
- error = gfs2_glock_nq_init(ip->i_gl,
- LM_ST_SHARED, 0,
- &lfcc->gh);
+ ip = GFS2_I(jd->jd_inode);
+ error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &lfcc->gh);
if (error) {
kfree(lfcc);
goto out;
TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process);
TUNE_ATTR_DAEMON(logd_secs, logd_process);
TUNE_ATTR_DAEMON(quotad_secs, quotad_process);
-TUNE_ATTR_DAEMON(inoded_secs, inoded_process);
TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
static struct attribute *tune_attrs[] = {
&tune_attr_recoverd_secs.attr,
&tune_attr_logd_secs.attr,
&tune_attr_quotad_secs.attr,
- &tune_attr_inoded_secs.attr,
&tune_attr_quota_scale.attr,
&tune_attr_new_files_jdata.attr,
&tune_attr_new_files_directio.attr,
#define RES_LEAF 1
#define RES_RG_BIT 2
#define RES_EATTR 1
-#define RES_UNLINKED 1
#define RES_STATFS 1
#define RES_QUOTA 2
+++ /dev/null
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License v.2.
- */
-
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/kthread.h>
-#include <linux/gfs2_ondisk.h>
-
-#include "gfs2.h"
-#include "lm_interface.h"
-#include "incore.h"
-#include "bmap.h"
-#include "inode.h"
-#include "meta_io.h"
-#include "trans.h"
-#include "unlinked.h"
-#include "util.h"
-
-static int munge_ondisk(struct gfs2_sbd *sdp, unsigned int slot,
- struct gfs2_unlinked_tag *ut)
-{
- struct gfs2_inode *ip = sdp->sd_ut_inode->u.generic_ip;
- unsigned int block, offset;
- uint64_t dblock;
- int new = 0;
- struct buffer_head *bh;
- int error;
- int boundary;
-
- block = slot / sdp->sd_ut_per_block;
- offset = slot % sdp->sd_ut_per_block;
-
- error = gfs2_block_map(ip->i_vnode, block, &new, &dblock, &boundary);
- if (error)
- return error;
- error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
- if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_UT)) {
- error = -EIO;
- goto out;
- }
-
- mutex_lock(&sdp->sd_unlinked_mutex);
- gfs2_trans_add_bh(ip->i_gl, bh, 1);
- gfs2_unlinked_tag_out(ut, bh->b_data +
- sizeof(struct gfs2_meta_header) +
- offset * sizeof(struct gfs2_unlinked_tag));
- mutex_unlock(&sdp->sd_unlinked_mutex);
-
- out:
- brelse(bh);
-
- return error;
-}
-
-static void ul_hash(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- spin_lock(&sdp->sd_unlinked_spin);
- list_add(&ul->ul_list, &sdp->sd_unlinked_list);
- gfs2_assert(sdp, ul->ul_count);
- ul->ul_count++;
- atomic_inc(&sdp->sd_unlinked_count);
- spin_unlock(&sdp->sd_unlinked_spin);
-}
-
-static void ul_unhash(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- spin_lock(&sdp->sd_unlinked_spin);
- list_del_init(&ul->ul_list);
- gfs2_assert(sdp, ul->ul_count > 1);
- ul->ul_count--;
- gfs2_assert_warn(sdp, atomic_read(&sdp->sd_unlinked_count) > 0);
- atomic_dec(&sdp->sd_unlinked_count);
- spin_unlock(&sdp->sd_unlinked_spin);
-}
-
-static struct gfs2_unlinked *ul_fish(struct gfs2_sbd *sdp)
-{
- struct list_head *head;
- struct gfs2_unlinked *ul;
- int found = 0;
-
- if (sdp->sd_vfs->s_flags & MS_RDONLY)
- return NULL;
-
- spin_lock(&sdp->sd_unlinked_spin);
-
- head = &sdp->sd_unlinked_list;
-
- list_for_each_entry(ul, head, ul_list) {
- if (test_bit(ULF_LOCKED, &ul->ul_flags))
- continue;
-
- list_move_tail(&ul->ul_list, head);
- ul->ul_count++;
- set_bit(ULF_LOCKED, &ul->ul_flags);
- found = 1;
-
- break;
- }
-
- if (!found)
- ul = NULL;
-
- spin_unlock(&sdp->sd_unlinked_spin);
-
- return ul;
-}
-
-/**
- * enforce_limit - limit the number of inodes waiting to be deallocated
- * @sdp: the filesystem
- *
- * Returns: errno
- */
-
-static void enforce_limit(struct gfs2_sbd *sdp)
-{
- unsigned int tries = 0, min = 0;
- int error;
-
- if (atomic_read(&sdp->sd_unlinked_count) <
- gfs2_tune_get(sdp, gt_ilimit))
- return;
-
- tries = gfs2_tune_get(sdp, gt_ilimit_tries);
- min = gfs2_tune_get(sdp, gt_ilimit_min);
-
- while (tries--) {
- struct gfs2_unlinked *ul = ul_fish(sdp);
- if (!ul)
- break;
- error = gfs2_inode_dealloc(sdp, ul);
- gfs2_unlinked_put(sdp, ul);
-
- if (!error) {
- if (!--min)
- break;
- } else if (error != 1)
- break;
- }
-}
-
-static struct gfs2_unlinked *ul_alloc(struct gfs2_sbd *sdp)
-{
- struct gfs2_unlinked *ul;
-
- ul = kzalloc(sizeof(struct gfs2_unlinked), GFP_KERNEL);
- if (ul) {
- INIT_LIST_HEAD(&ul->ul_list);
- ul->ul_count = 1;
- set_bit(ULF_LOCKED, &ul->ul_flags);
- }
-
- return ul;
-}
-
-int gfs2_unlinked_get(struct gfs2_sbd *sdp, struct gfs2_unlinked **ul)
-{
- unsigned int c, o = 0, b;
- unsigned char byte = 0;
-
- enforce_limit(sdp);
-
- *ul = ul_alloc(sdp);
- if (!*ul)
- return -ENOMEM;
-
- spin_lock(&sdp->sd_unlinked_spin);
-
- for (c = 0; c < sdp->sd_unlinked_chunks; c++)
- for (o = 0; o < PAGE_SIZE; o++) {
- byte = sdp->sd_unlinked_bitmap[c][o];
- if (byte != 0xFF)
- goto found;
- }
-
- goto fail;
-
-found:
- for (b = 0; b < 8; b++)
- if (!(byte & (1 << b)))
- break;
- (*ul)->ul_slot = c * (8 * PAGE_SIZE) + o * 8 + b;
-
- if ((*ul)->ul_slot >= sdp->sd_unlinked_slots)
- goto fail;
-
- sdp->sd_unlinked_bitmap[c][o] |= 1 << b;
-
- spin_unlock(&sdp->sd_unlinked_spin);
-
- return 0;
-
-fail:
- spin_unlock(&sdp->sd_unlinked_spin);
- kfree(*ul);
- return -ENOSPC;
-}
-
-void gfs2_unlinked_put(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- gfs2_assert_warn(sdp, test_and_clear_bit(ULF_LOCKED, &ul->ul_flags));
-
- spin_lock(&sdp->sd_unlinked_spin);
- gfs2_assert(sdp, ul->ul_count);
- ul->ul_count--;
- if (!ul->ul_count) {
- gfs2_icbit_munge(sdp, sdp->sd_unlinked_bitmap, ul->ul_slot, 0);
- spin_unlock(&sdp->sd_unlinked_spin);
- kfree(ul);
- } else
- spin_unlock(&sdp->sd_unlinked_spin);
-}
-
-int gfs2_unlinked_ondisk_add(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- int error;
-
- gfs2_assert_warn(sdp, test_bit(ULF_LOCKED, &ul->ul_flags));
- gfs2_assert_warn(sdp, list_empty(&ul->ul_list));
-
- error = munge_ondisk(sdp, ul->ul_slot, &ul->ul_ut);
- if (!error)
- ul_hash(sdp, ul);
-
- return error;
-}
-
-int gfs2_unlinked_ondisk_munge(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- int error;
-
- gfs2_assert_warn(sdp, test_bit(ULF_LOCKED, &ul->ul_flags));
- gfs2_assert_warn(sdp, !list_empty(&ul->ul_list));
-
- error = munge_ondisk(sdp, ul->ul_slot, &ul->ul_ut);
-
- return error;
-}
-
-int gfs2_unlinked_ondisk_rm(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- struct gfs2_unlinked_tag ut;
- int error;
-
- gfs2_assert_warn(sdp, test_bit(ULF_LOCKED, &ul->ul_flags));
- gfs2_assert_warn(sdp, !list_empty(&ul->ul_list));
-
- memset(&ut, 0, sizeof(struct gfs2_unlinked_tag));
-
- error = munge_ondisk(sdp, ul->ul_slot, &ut);
- if (error)
- return error;
-
- ul_unhash(sdp, ul);
-
- return 0;
-}
-
-/**
- * gfs2_unlinked_dealloc - Go through the list of inodes to be deallocated
- * @sdp: the filesystem
- *
- * Returns: errno
- */
-
-int gfs2_unlinked_dealloc(struct gfs2_sbd *sdp)
-{
- unsigned int hits, strikes;
- int error;
-
- for (;;) {
- hits = 0;
- strikes = 0;
-
- for (;;) {
- struct gfs2_unlinked *ul = ul_fish(sdp);
- if (!ul)
- return 0;
- error = gfs2_inode_dealloc(sdp, ul);
- gfs2_unlinked_put(sdp, ul);
-
- if (!error) {
- hits++;
- if (strikes)
- strikes--;
- } else if (error == 1) {
- strikes++;
- if (strikes >=
- atomic_read(&sdp->sd_unlinked_count)) {
- error = 0;
- break;
- }
- } else
- return error;
- }
-
- if (!hits || kthread_should_stop())
- break;
-
- cond_resched();
- }
-
- return 0;
-}
-
-int gfs2_unlinked_init(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *ip = sdp->sd_ut_inode->u.generic_ip;
- unsigned int blocks = ip->i_di.di_size >> sdp->sd_sb.sb_bsize_shift;
- unsigned int x, slot = 0;
- unsigned int found = 0;
- uint64_t dblock;
- uint32_t extlen = 0;
- int error;
-
- if (!ip->i_di.di_size ||
- ip->i_di.di_size > (64 << 20) ||
- ip->i_di.di_size & (sdp->sd_sb.sb_bsize - 1)) {
- gfs2_consist_inode(ip);
- return -EIO;
- }
- sdp->sd_unlinked_slots = blocks * sdp->sd_ut_per_block;
- sdp->sd_unlinked_chunks = DIV_ROUND_UP(sdp->sd_unlinked_slots,
- 8 * PAGE_SIZE);
-
- error = -ENOMEM;
-
- sdp->sd_unlinked_bitmap = kcalloc(sdp->sd_unlinked_chunks,
- sizeof(unsigned char *),
- GFP_KERNEL);
- if (!sdp->sd_unlinked_bitmap)
- return error;
-
- for (x = 0; x < sdp->sd_unlinked_chunks; x++) {
- sdp->sd_unlinked_bitmap[x] = kzalloc(PAGE_SIZE, GFP_KERNEL);
- if (!sdp->sd_unlinked_bitmap[x])
- goto fail;
- }
-
- for (x = 0; x < blocks; x++) {
- struct buffer_head *bh;
- unsigned int y;
-
- if (!extlen) {
- int new = 0;
- error = gfs2_extent_map(ip->i_vnode, x, &new, &dblock, &extlen);
- if (error)
- goto fail;
- }
- gfs2_meta_ra(ip->i_gl, dblock, extlen);
- error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT,
- &bh);
- if (error)
- goto fail;
- error = -EIO;
- if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_UT)) {
- brelse(bh);
- goto fail;
- }
-
- for (y = 0;
- y < sdp->sd_ut_per_block && slot < sdp->sd_unlinked_slots;
- y++, slot++) {
- struct gfs2_unlinked_tag ut;
- struct gfs2_unlinked *ul;
-
- gfs2_unlinked_tag_in(&ut, bh->b_data +
- sizeof(struct gfs2_meta_header) +
- y * sizeof(struct gfs2_unlinked_tag));
- if (!ut.ut_inum.no_addr)
- continue;
-
- error = -ENOMEM;
- ul = ul_alloc(sdp);
- if (!ul) {
- brelse(bh);
- goto fail;
- }
- ul->ul_ut = ut;
- ul->ul_slot = slot;
-
- spin_lock(&sdp->sd_unlinked_spin);
- gfs2_icbit_munge(sdp, sdp->sd_unlinked_bitmap, slot, 1);
- spin_unlock(&sdp->sd_unlinked_spin);
- ul_hash(sdp, ul);
-
- gfs2_unlinked_put(sdp, ul);
- found++;
- }
-
- brelse(bh);
- dblock++;
- extlen--;
- }
-
- if (found)
- fs_info(sdp, "found %u unlinked inodes\n", found);
-
- return 0;
-
-fail:
- gfs2_unlinked_cleanup(sdp);
- return error;
-}
-
-/**
- * gfs2_unlinked_cleanup - get rid of any extra struct gfs2_unlinked structures
- * @sdp: the filesystem
- *
- */
-
-void gfs2_unlinked_cleanup(struct gfs2_sbd *sdp)
-{
- struct list_head *head = &sdp->sd_unlinked_list;
- struct gfs2_unlinked *ul;
- unsigned int x;
-
- spin_lock(&sdp->sd_unlinked_spin);
- while (!list_empty(head)) {
- ul = list_entry(head->next, struct gfs2_unlinked, ul_list);
-
- if (ul->ul_count > 1) {
- list_move_tail(&ul->ul_list, head);
- spin_unlock(&sdp->sd_unlinked_spin);
- schedule();
- spin_lock(&sdp->sd_unlinked_spin);
- continue;
- }
-
- list_del_init(&ul->ul_list);
- atomic_dec(&sdp->sd_unlinked_count);
-
- gfs2_assert_warn(sdp, ul->ul_count == 1);
- gfs2_assert_warn(sdp, !test_bit(ULF_LOCKED, &ul->ul_flags));
- kfree(ul);
- }
- spin_unlock(&sdp->sd_unlinked_spin);
-
- gfs2_assert_warn(sdp, !atomic_read(&sdp->sd_unlinked_count));
-
- if (sdp->sd_unlinked_bitmap) {
- for (x = 0; x < sdp->sd_unlinked_chunks; x++)
- kfree(sdp->sd_unlinked_bitmap[x]);
- kfree(sdp->sd_unlinked_bitmap);
- }
-}
-
+++ /dev/null
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License v.2.
- */
-
-#ifndef __UNLINKED_DOT_H__
-#define __UNLINKED_DOT_H__
-
-int gfs2_unlinked_get(struct gfs2_sbd *sdp, struct gfs2_unlinked **ul);
-void gfs2_unlinked_put(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul);
-
-int gfs2_unlinked_ondisk_add(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul);
-int gfs2_unlinked_ondisk_munge(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul);
-int gfs2_unlinked_ondisk_rm(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul);
-
-int gfs2_unlinked_dealloc(struct gfs2_sbd *sdp);
-
-int gfs2_unlinked_init(struct gfs2_sbd *sdp);
-void gfs2_unlinked_cleanup(struct gfs2_sbd *sdp);
-
-#endif /* __UNLINKED_DOT_H__ */
int gfs2_consist_inode_i(struct gfs2_inode *ip, int cluster_wide,
const char *function, char *file, unsigned int line)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
int rv;
rv = gfs2_lm_withdraw(sdp,
"GFS2: fsid=%s: fatal: filesystem consistency error\n"
/*
-* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
-*
-* This copyrighted material is made available to anyone wishing to use,
-* modify, copy, or redistribute it subject to the terms and conditions
-* of the GNU General Public License v.2.
-*/
+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
#ifndef __GFS2_ONDISK_DOT_H__
#define __GFS2_ONDISK_DOT_H__
#define GFS2_FORMAT_LB 1000
#define GFS2_FORMAT_EA 1600
#define GFS2_FORMAT_ED 1700
-#define GFS2_FORMAT_UT 1300
#define GFS2_FORMAT_QC 1400
/* These are format numbers for entities contained in files */
#define GFS2_FORMAT_RI 1100
#define GFS2_METATYPE_LB 12
#define GFS2_METATYPE_EA 10
#define GFS2_METATYPE_ED 11
-#define GFS2_METATYPE_UT 13
#define GFS2_METATYPE_QC 14
struct gfs2_meta_header {
#define GFS2_BLKST_FREE 0
#define GFS2_BLKST_USED 1
-#define GFS2_BLKST_INVALID 2
+#define GFS2_BLKST_UNLINKED 2
#define GFS2_BLKST_DINODE 3
#define GFS2_RGF_JOURNAL 0x00000001
};
/*
- * Unlinked Tag
- * Describes an allocated inode that isn't linked into
- * the directory tree and might need to be deallocated.
- */
-
-#define GFS2_UTF_UNINIT 0x00000001
-
-struct gfs2_unlinked_tag {
- struct gfs2_inum ut_inum;
- __be32 ut_flags; /* GFS2_UTF_... */
- __u32 __pad;
-};
-
-/*
* Quota change
* Describes an allocation change for a particular
* user or group.
extern void gfs2_inum_range_out(struct gfs2_inum_range *ir, char *buf);
extern void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, char *buf);
extern void gfs2_statfs_change_out(struct gfs2_statfs_change *sc, char *buf);
-extern void gfs2_unlinked_tag_in(struct gfs2_unlinked_tag *ut, char *buf);
-extern void gfs2_unlinked_tag_out(struct gfs2_unlinked_tag *ut, char *buf);
extern void gfs2_quota_change_in(struct gfs2_quota_change *qc, char *buf);
/* Printing functions */