提交 b3b94faa 编写于 作者: D David Teigland 提交者: Steven Whitehouse

[GFS2] The core of GFS2

This patch contains all the core files for GFS2.
Signed-off-by: NDavid Teigland <teigland@redhat.com>
Signed-off-by: NSteven Whitehouse <swhiteho@redhat.com>
上级 f7825dcf
config GFS2_FS
tristate "GFS2 file system support"
default m
depends on EXPERIMENTAL
select FS_POSIX_ACL
select SYSFS
help
A cluster filesystem.
Allows a cluster of computers to simultaneously use a block device
that is shared between them (with FC, iSCSI, NBD, etc...). GFS reads
and writes to the block device like a local filesystem, but also uses
a lock module to allow the computers coordinate their I/O so
filesystem consistency is maintained. One of the nifty features of
GFS is perfect consistency -- changes made to the filesystem on one
machine show up immediately on all other machines in the cluster.
To use the GFS2 filesystem, you will need to enable one or more of
the below locking modules. Documentation and utilities for GFS2 can
be found here: http://sources.redhat.com/cluster/gfs/
config GFS2_FS_LOCKING_NOLOCK
tristate "GFS2 \"nolock\" locking module"
depends on GFS2_FS
help
Single node locking module for GFS2.
Use this module if you want to use GFS2 on a single node without
its clustering features. You can still take advantage of the
large file support, and upgrade to running a full cluster later on
if required.
If you will only be using GFS2 in cluster mode, you do not need this
module.
config GFS2_FS_LOCKING_DLM
tristate "GFS2 DLM locking module"
depends on GFS2_FS
select DLM
help
Multiple node locking module for GFS2
Most users of GFS2 will require this module. It provides the locking
interface between GFS2 and the DLM, which is required to use GFS2
in a cluster environment.
obj-$(CONFIG_GFS2_FS) += gfs2.o
gfs2-y := \
acl.o \
bits.o \
bmap.o \
daemon.o \
dir.o \
eaops.o \
eattr.o \
glock.o \
glops.o \
inode.o \
jdata.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 \
resize.o \
recovery.o \
rgrp.o \
super.o \
sys.o \
trans.o \
unlinked.o \
util.o
obj-$(CONFIG_GFS2_LOCKING_NOLOCK) += locking/nolock/
obj-$(CONFIG_GFS2_LOCKING_DLM) += locking/dlm/
/*
* 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.
*/
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/posix_acl.h>
#include <linux/posix_acl_xattr.h>
#include <asm/semaphore.h>
#include "gfs2.h"
#include "acl.h"
#include "eaops.h"
#include "eattr.h"
#include "glock.h"
#include "inode.h"
#include "meta_io.h"
#include "trans.h"
#define ACL_ACCESS 1
#define ACL_DEFAULT 0
int gfs2_acl_validate_set(struct gfs2_inode *ip, int access,
struct gfs2_ea_request *er,
int *remove, mode_t *mode)
{
struct posix_acl *acl;
int error;
error = gfs2_acl_validate_remove(ip, access);
if (error)
return error;
if (!er->er_data)
return -EINVAL;
acl = posix_acl_from_xattr(er->er_data, er->er_data_len);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (!acl) {
*remove = 1;
return 0;
}
error = posix_acl_valid(acl);
if (error)
goto out;
if (access) {
error = posix_acl_equiv_mode(acl, mode);
if (!error)
*remove = 1;
else if (error > 0)
error = 0;
}
out:
posix_acl_release(acl);
return error;
}
int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access)
{
if (!ip->i_sbd->sd_args.ar_posix_acl)
return -EOPNOTSUPP;
if (current->fsuid != ip->i_di.di_uid && !capable(CAP_FOWNER))
return -EPERM;
if (S_ISLNK(ip->i_di.di_mode))
return -EOPNOTSUPP;
if (!access && !S_ISDIR(ip->i_di.di_mode))
return -EACCES;
return 0;
}
static int acl_get(struct gfs2_inode *ip, int access, struct posix_acl **acl,
struct gfs2_ea_location *el, char **data, unsigned int *len)
{
struct gfs2_ea_request er;
struct gfs2_ea_location el_this;
int error;
if (!ip->i_di.di_eattr)
return 0;
memset(&er, 0, sizeof(struct gfs2_ea_request));
if (access) {
er.er_name = GFS2_POSIX_ACL_ACCESS;
er.er_name_len = GFS2_POSIX_ACL_ACCESS_LEN;
} else {
er.er_name = GFS2_POSIX_ACL_DEFAULT;
er.er_name_len = GFS2_POSIX_ACL_DEFAULT_LEN;
}
er.er_type = GFS2_EATYPE_SYS;
if (!el)
el = &el_this;
error = gfs2_ea_find(ip, &er, el);
if (error)
return error;
if (!el->el_ea)
return 0;
if (!GFS2_EA_DATA_LEN(el->el_ea))
goto out;
er.er_data_len = GFS2_EA_DATA_LEN(el->el_ea);
er.er_data = kmalloc(er.er_data_len, GFP_KERNEL);
error = -ENOMEM;
if (!er.er_data)
goto out;
error = gfs2_ea_get_copy(ip, el, er.er_data);
if (error)
goto out_kfree;
if (acl) {
*acl = posix_acl_from_xattr(er.er_data, er.er_data_len);
if (IS_ERR(*acl))
error = PTR_ERR(*acl);
}
out_kfree:
if (error || !data)
kfree(er.er_data);
else {
*data = er.er_data;
*len = er.er_data_len;
}
out:
if (error || el == &el_this)
brelse(el->el_bh);
return error;
}
/**
* gfs2_check_acl_locked - Check an ACL to see if we're allowed to do something
* @inode: the file we want to do something to
* @mask: what we want to do
*
* Returns: errno
*/
int gfs2_check_acl_locked(struct inode *inode, int mask)
{
struct posix_acl *acl = NULL;
int error;
error = acl_get(get_v2ip(inode), ACL_ACCESS, &acl, NULL, NULL, NULL);
if (error)
return error;
if (acl) {
error = posix_acl_permission(inode, acl, mask);
posix_acl_release(acl);
return error;
}
return -EAGAIN;
}
int gfs2_check_acl(struct inode *inode, int mask)
{
struct gfs2_inode *ip = get_v2ip(inode);
struct gfs2_holder i_gh;
int error;
error = gfs2_glock_nq_init(ip->i_gl,
LM_ST_SHARED, LM_FLAG_ANY,
&i_gh);
if (!error) {
error = gfs2_check_acl_locked(inode, mask);
gfs2_glock_dq_uninit(&i_gh);
}
return error;
}
static int munge_mode(struct gfs2_inode *ip, mode_t mode)
{
struct gfs2_sbd *sdp = ip->i_sbd;
struct buffer_head *dibh;
int error;
error = gfs2_trans_begin(sdp, RES_DINODE, 0);
if (error)
return error;
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
gfs2_assert_withdraw(sdp,
(ip->i_di.di_mode & S_IFMT) == (mode & S_IFMT));
ip->i_di.di_mode = mode;
gfs2_trans_add_bh(ip->i_gl, dibh);
gfs2_dinode_out(&ip->i_di, dibh->b_data);
brelse(dibh);
}
gfs2_trans_end(sdp);
return 0;
}
int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
{
struct gfs2_sbd *sdp = dip->i_sbd;
struct posix_acl *acl = NULL, *clone;
struct gfs2_ea_request er;
mode_t mode = ip->i_di.di_mode;
int error;
if (!sdp->sd_args.ar_posix_acl)
return 0;
if (S_ISLNK(ip->i_di.di_mode))
return 0;
memset(&er, 0, sizeof(struct gfs2_ea_request));
er.er_type = GFS2_EATYPE_SYS;
error = acl_get(dip, ACL_DEFAULT, &acl, NULL,
&er.er_data, &er.er_data_len);
if (error)
return error;
if (!acl) {
mode &= ~current->fs->umask;
if (mode != ip->i_di.di_mode)
error = munge_mode(ip, mode);
return error;
}
clone = posix_acl_clone(acl, GFP_KERNEL);
error = -ENOMEM;
if (!clone)
goto out;
posix_acl_release(acl);
acl = clone;
if (S_ISDIR(ip->i_di.di_mode)) {
er.er_name = GFS2_POSIX_ACL_DEFAULT;
er.er_name_len = GFS2_POSIX_ACL_DEFAULT_LEN;
error = gfs2_system_eaops.eo_set(ip, &er);
if (error)
goto out;
}
error = posix_acl_create_masq(acl, &mode);
if (error < 0)
goto out;
if (error > 0) {
er.er_name = GFS2_POSIX_ACL_ACCESS;
er.er_name_len = GFS2_POSIX_ACL_ACCESS_LEN;
posix_acl_to_xattr(acl, er.er_data, er.er_data_len);
er.er_mode = mode;
er.er_flags = GFS2_ERF_MODE;
error = gfs2_system_eaops.eo_set(ip, &er);
if (error)
goto out;
} else
munge_mode(ip, mode);
out:
posix_acl_release(acl);
kfree(er.er_data);
return error;
}
int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
{
struct posix_acl *acl = NULL, *clone;
struct gfs2_ea_location el;
char *data;
unsigned int len;
int error;
error = acl_get(ip, ACL_ACCESS, &acl, &el, &data, &len);
if (error)
return error;
if (!acl)
return gfs2_setattr_simple(ip, attr);
clone = posix_acl_clone(acl, GFP_KERNEL);
error = -ENOMEM;
if (!clone)
goto out;
posix_acl_release(acl);
acl = clone;
error = posix_acl_chmod_masq(acl, attr->ia_mode);
if (!error) {
posix_acl_to_xattr(acl, data, len);
error = gfs2_ea_acl_chmod(ip, &el, attr, data);
}
out:
posix_acl_release(acl);
brelse(el.el_bh);
kfree(data);
return error;
}
/*
* 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.
*/
#ifndef __ACL_DOT_H__
#define __ACL_DOT_H__
#define GFS2_POSIX_ACL_ACCESS "posix_acl_access"
#define GFS2_POSIX_ACL_ACCESS_LEN 16
#define GFS2_POSIX_ACL_DEFAULT "posix_acl_default"
#define GFS2_POSIX_ACL_DEFAULT_LEN 17
#define GFS2_ACL_IS_ACCESS(name, len) \
((len) == GFS2_POSIX_ACL_ACCESS_LEN && \
!memcmp(GFS2_POSIX_ACL_ACCESS, (name), (len)))
#define GFS2_ACL_IS_DEFAULT(name, len) \
((len) == GFS2_POSIX_ACL_DEFAULT_LEN && \
!memcmp(GFS2_POSIX_ACL_DEFAULT, (name), (len)))
struct gfs2_ea_request;
int gfs2_acl_validate_set(struct gfs2_inode *ip, int access,
struct gfs2_ea_request *er,
int *remove, mode_t *mode);
int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access);
int gfs2_check_acl_locked(struct inode *inode, int mask);
int gfs2_check_acl(struct inode *inode, int mask);
int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip);
int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
#endif /* __ACL_DOT_H__ */
/*
* 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.
*/
/*
* 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.
*/
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <asm/semaphore.h>
#include "gfs2.h"
#include "bits.h"
static const char valid_change[16] = {
/* current */
/* n */ 0, 1, 0, 1,
/* e */ 1, 0, 0, 0,
/* w */ 0, 0, 0, 0,
1, 0, 0, 0
};
/**
* gfs2_setbit - Set a bit in the bitmaps
* @buffer: the buffer that holds the bitmaps
* @buflen: the length (in bytes) of the buffer
* @block: the block to set
* @new_state: the new state of the block
*
*/
void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
unsigned int buflen, uint32_t block, unsigned char new_state)
{
unsigned char *byte, *end, cur_state;
unsigned int bit;
byte = buffer + (block / GFS2_NBBY);
bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
end = buffer + buflen;
gfs2_assert(rgd->rd_sbd, byte < end);
cur_state = (*byte >> bit) & GFS2_BIT_MASK;
if (valid_change[new_state * 4 + cur_state]) {
*byte ^= cur_state << bit;
*byte |= new_state << bit;
} else
gfs2_consist_rgrpd(rgd);
}
/**
* gfs2_testbit - test a bit in the bitmaps
* @buffer: the buffer that holds the bitmaps
* @buflen: the length (in bytes) of the buffer
* @block: the block to read
*
*/
unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
unsigned int buflen, uint32_t block)
{
unsigned char *byte, *end, cur_state;
unsigned int bit;
byte = buffer + (block / GFS2_NBBY);
bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
end = buffer + buflen;
gfs2_assert(rgd->rd_sbd, byte < end);
cur_state = (*byte >> bit) & GFS2_BIT_MASK;
return cur_state;
}
/**
* gfs2_bitfit - Search an rgrp's bitmap buffer to find a bit-pair representing
* a block in a given allocation state.
* @buffer: the buffer that holds the bitmaps
* @buflen: the length (in bytes) of the buffer
* @goal: start search at this block's bit-pair (within @buffer)
* @old_state: GFS2_BLKST_XXX the state of the block we're looking for;
* bit 0 = alloc(1)/free(0), bit 1 = meta(1)/data(0)
*
* Scope of @goal and returned block number is only within this bitmap buffer,
* not entire rgrp or filesystem. @buffer will be offset from the actual
* beginning of a bitmap block buffer, skipping any header structures.
*
* Return: the block number (bitmap buffer scope) that was found
*/
uint32_t gfs2_bitfit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
unsigned int buflen, uint32_t goal,
unsigned char old_state)
{
unsigned char *byte, *end, alloc;
uint32_t blk = goal;
unsigned int bit;
byte = buffer + (goal / GFS2_NBBY);
bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE;
end = buffer + buflen;
alloc = (old_state & 1) ? 0 : 0x55;
while (byte < end) {
if ((*byte & 0x55) == alloc) {
blk += (8 - bit) >> 1;
bit = 0;
byte++;
continue;
}
if (((*byte >> bit) & GFS2_BIT_MASK) == old_state)
return blk;
bit += GFS2_BIT_SIZE;
if (bit >= 8) {
bit = 0;
byte++;
}
blk++;
}
return BFITNOENT;
}
/**
* gfs2_bitcount - count the number of bits in a certain state
* @buffer: the buffer that holds the bitmaps
* @buflen: the length (in bytes) of the buffer
* @state: the state of the block we're looking for
*
* Returns: The number of bits
*/
uint32_t gfs2_bitcount(struct gfs2_rgrpd *rgd, unsigned char *buffer,
unsigned int buflen, unsigned char state)
{
unsigned char *byte = buffer;
unsigned char *end = buffer + buflen;
unsigned char state1 = state << 2;
unsigned char state2 = state << 4;
unsigned char state3 = state << 6;
uint32_t count = 0;
for (; byte < end; byte++) {
if (((*byte) & 0x03) == state)
count++;
if (((*byte) & 0x0C) == state1)
count++;
if (((*byte) & 0x30) == state2)
count++;
if (((*byte) & 0xC0) == state3)
count++;
}
return count;
}
/*
* 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.
*/
#ifndef __BITS_DOT_H__
#define __BITS_DOT_H__
#define BFITNOENT 0xFFFFFFFF
void gfs2_setbit(struct gfs2_rgrpd *rgd,
unsigned char *buffer, unsigned int buflen,
uint32_t block, unsigned char new_state);
unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd,
unsigned char *buffer, unsigned int buflen,
uint32_t block);
uint32_t gfs2_bitfit(struct gfs2_rgrpd *rgd,
unsigned char *buffer, unsigned int buflen,
uint32_t goal, unsigned char old_state);
uint32_t gfs2_bitcount(struct gfs2_rgrpd *rgd,
unsigned char *buffer, unsigned int buflen,
unsigned char state);
#endif /* __BITS_DOT_H__ */
此差异已折叠。
/*
* 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.
*/
#ifndef __BMAP_DOT_H__
#define __BMAP_DOT_H__
typedef int (*gfs2_unstuffer_t) (struct gfs2_inode * ip,
struct buffer_head * dibh, uint64_t block,
void *private);
int gfs2_unstuffer_sync(struct gfs2_inode *ip, struct buffer_head *dibh,
uint64_t block, void *private);
int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer,
void *private);
int gfs2_block_map(struct gfs2_inode *ip,
uint64_t lblock, int *new,
uint64_t *dblock, uint32_t *extlen);
typedef int (*gfs2_truncator_t) (struct gfs2_inode * ip, uint64_t size);
int gfs2_truncatei(struct gfs2_inode *ip, uint64_t size,
gfs2_truncator_t truncator);
int gfs2_truncatei_resume(struct gfs2_inode *ip);
int gfs2_file_dealloc(struct gfs2_inode *ip);
void gfs2_write_calc_reserv(struct gfs2_inode *ip, unsigned int len,
unsigned int *data_blocks,
unsigned int *ind_blocks);
int gfs2_write_alloc_required(struct gfs2_inode *ip, uint64_t offset,
unsigned int len, int *alloc_required);
int gfs2_get_file_meta(struct gfs2_inode *ip, struct gfs2_user_buffer *ub);
#endif /* __BMAP_DOT_H__ */
/*
* 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.
*/
#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/delay.h>
#include <asm/semaphore.h>
#include "gfs2.h"
#include "daemon.h"
#include "glock.h"
#include "log.h"
#include "quota.h"
#include "recovery.h"
#include "super.h"
#include "unlinked.h"
/* This uses schedule_timeout() instead of msleep() because it's good for
the daemons to wake up more often than the timeout when unmounting so
the user's unmount doesn't sit there forever.
The kthread functions used to start these daemons block and flush signals. */
/**
* gfs2_scand - Look for cached glocks and inodes to toss from memory
* @sdp: Pointer to GFS2 superblock
*
* One of these daemons runs, finding candidates to add to sd_reclaim_list.
* See gfs2_glockd()
*/
int gfs2_scand(void *data)
{
struct gfs2_sbd *sdp = (struct gfs2_sbd *)data;
unsigned long t;
while (!kthread_should_stop()) {
gfs2_scand_internal(sdp);
t = gfs2_tune_get(sdp, gt_scand_secs) * HZ;
schedule_timeout_interruptible(t);
}
return 0;
}
/**
* gfs2_glockd - Reclaim unused glock structures
* @sdp: Pointer to GFS2 superblock
*
* One or more of these daemons run, reclaiming glocks on sd_reclaim_list.
* Number of daemons can be set by user, with num_glockd mount option.
*/
int gfs2_glockd(void *data)
{
struct gfs2_sbd *sdp = (struct gfs2_sbd *)data;
DECLARE_WAITQUEUE(wait_chan, current);
while (!kthread_should_stop()) {
while (atomic_read(&sdp->sd_reclaim_count))
gfs2_reclaim_glock(sdp);
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&sdp->sd_reclaim_wq, &wait_chan);
if (!atomic_read(&sdp->sd_reclaim_count) &&
!kthread_should_stop())
schedule();
remove_wait_queue(&sdp->sd_reclaim_wq, &wait_chan);
set_current_state(TASK_RUNNING);
}
return 0;
}
/**
* gfs2_recoverd - Recover dead machine's journals
* @sdp: Pointer to GFS2 superblock
*
*/
int gfs2_recoverd(void *data)
{
struct gfs2_sbd *sdp = (struct gfs2_sbd *)data;
unsigned long t;
while (!kthread_should_stop()) {
gfs2_check_journals(sdp);
t = gfs2_tune_get(sdp, gt_recoverd_secs) * HZ;
schedule_timeout_interruptible(t);
}
return 0;
}
/**
* gfs2_logd - Update log tail as Active Items get flushed to in-place blocks
* @sdp: Pointer to GFS2 superblock
*
* Also, periodically check to make sure that we're using the most recent
* journal index.
*/
int gfs2_logd(void *data)
{
struct gfs2_sbd *sdp = (struct gfs2_sbd *)data;
struct gfs2_holder ji_gh;
unsigned long t;
while (!kthread_should_stop()) {
/* Advance the log tail */
t = sdp->sd_log_flush_time +
gfs2_tune_get(sdp, gt_log_flush_secs) * HZ;
gfs2_ail1_empty(sdp, DIO_ALL);
if (time_after_eq(jiffies, t)) {
gfs2_log_flush(sdp);
sdp->sd_log_flush_time = jiffies;
}
/* Check for latest journal index */
t = sdp->sd_jindex_refresh_time +
gfs2_tune_get(sdp, gt_jindex_refresh_secs) * HZ;
if (time_after_eq(jiffies, t)) {
if (!gfs2_jindex_hold(sdp, &ji_gh))
gfs2_glock_dq_uninit(&ji_gh);
sdp->sd_jindex_refresh_time = jiffies;
}
t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
schedule_timeout_interruptible(t);
}
return 0;
}
/**
* gfs2_quotad - Write cached quota changes into the quota file
* @sdp: Pointer to GFS2 superblock
*
*/
int gfs2_quotad(void *data)
{
struct gfs2_sbd *sdp = (struct gfs2_sbd *)data;
unsigned long t;
int error;
while (!kthread_should_stop()) {
/* Update the master statfs file */
t = sdp->sd_statfs_sync_time +
gfs2_tune_get(sdp, gt_statfs_quantum) * HZ;
if (time_after_eq(jiffies, t)) {
error = gfs2_statfs_sync(sdp);
if (error &&
error != -EROFS &&
!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
fs_err(sdp, "quotad: (1) error=%d\n", error);
sdp->sd_statfs_sync_time = jiffies;
}
/* Update quota file */
t = sdp->sd_quota_sync_time +
gfs2_tune_get(sdp, gt_quota_quantum) * HZ;
if (time_after_eq(jiffies, t)) {
error = gfs2_quota_sync(sdp);
if (error &&
error != -EROFS &&
!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
fs_err(sdp, "quotad: (2) error=%d\n", error);
sdp->sd_quota_sync_time = jiffies;
}
gfs2_quota_scan(sdp);
t = gfs2_tune_get(sdp, gt_quotad_secs) * HZ;
schedule_timeout_interruptible(t);
}
return 0;
}
/**
* gfs2_inoded - Deallocate unlinked inodes
* @sdp: Pointer to GFS2 superblock
*
*/
int gfs2_inoded(void *data)
{
struct gfs2_sbd *sdp = (struct gfs2_sbd *)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;
}
/*
* 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.
*/
#ifndef __DAEMON_DOT_H__
#define __DAEMON_DOT_H__
int gfs2_scand(void *data);
int gfs2_glockd(void *data);
int gfs2_recoverd(void *data);
int gfs2_logd(void *data);
int gfs2_quotad(void *data);
int gfs2_inoded(void *data);
#endif /* __DAEMON_DOT_H__ */
此差异已折叠。
/*
* 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.
*/
#ifndef __DIR_DOT_H__
#define __DIR_DOT_H__
/**
* gfs2_filldir_t - Report a directory entry to the caller of gfs2_dir_read()
* @opaque: opaque data used by the function
* @name: the name of the directory entry
* @length: the length of the name
* @offset: the entry's offset in the directory
* @inum: the inode number the entry points to
* @type: the type of inode the entry points to
*
* Returns: 0 on success, 1 if buffer full
*/
typedef int (*gfs2_filldir_t) (void *opaque,
const char *name, unsigned int length,
uint64_t offset,
struct gfs2_inum *inum, unsigned int type);
int gfs2_filecmp(struct qstr *file1, char *file2, int len_of_file2);
int gfs2_dirent_alloc(struct gfs2_inode *dip, struct buffer_head *bh,
int name_len, struct gfs2_dirent **dent_out);
int gfs2_dir_search(struct gfs2_inode *dip, struct qstr *filename,
struct gfs2_inum *inum, unsigned int *type);
int gfs2_dir_add(struct gfs2_inode *dip, struct qstr *filename,
struct gfs2_inum *inum, unsigned int type);
int gfs2_dir_del(struct gfs2_inode *dip, struct qstr *filename);
int gfs2_dir_read(struct gfs2_inode *dip, uint64_t * offset, void *opaque,
gfs2_filldir_t filldir);
int gfs2_dir_mvino(struct gfs2_inode *dip, struct qstr *filename,
struct gfs2_inum *new_inum, unsigned int new_type);
int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
int gfs2_diradd_alloc_required(struct gfs2_inode *dip, struct qstr *filename,
int *alloc_required);
int gfs2_get_dir_meta(struct gfs2_inode *ip, struct gfs2_user_buffer *ub);
#endif /* __DIR_DOT_H__ */
/*
* 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.
*/
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/xattr.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
#include "gfs2.h"
#include "acl.h"
#include "eaops.h"
#include "eattr.h"
/**
* gfs2_ea_name2type - get the type of the ea, and truncate type from the name
* @namep: ea name, possibly with type appended
*
* Returns: GFS2_EATYPE_XXX
*/
unsigned int gfs2_ea_name2type(const char *name, char **truncated_name)
{
unsigned int type;
if (strncmp(name, "system.", 7) == 0) {
type = GFS2_EATYPE_SYS;
if (truncated_name)
*truncated_name = strchr(name, '.') + 1;
} else if (strncmp(name, "user.", 5) == 0) {
type = GFS2_EATYPE_USR;
if (truncated_name)
*truncated_name = strchr(name, '.') + 1;
} else {
type = GFS2_EATYPE_UNUSED;
if (truncated_name)
*truncated_name = NULL;
}
return type;
}
static int user_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
struct inode *inode = ip->i_vnode;
int error = permission(inode, MAY_READ, NULL);
if (error)
return error;
return gfs2_ea_get_i(ip, er);
}
static int user_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
struct inode *inode = ip->i_vnode;
if (S_ISREG(inode->i_mode) ||
(S_ISDIR(inode->i_mode) && !(inode->i_mode & S_ISVTX))) {
int error = permission(inode, MAY_WRITE, NULL);
if (error)
return error;
} else
return -EPERM;
return gfs2_ea_set_i(ip, er);
}
static int user_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
struct inode *inode = ip->i_vnode;
if (S_ISREG(inode->i_mode) ||
(S_ISDIR(inode->i_mode) && !(inode->i_mode & S_ISVTX))) {
int error = permission(inode, MAY_WRITE, NULL);
if (error)
return error;
} else
return -EPERM;
return gfs2_ea_remove_i(ip, er);
}
static int system_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
if (!GFS2_ACL_IS_ACCESS(er->er_name, er->er_name_len) &&
!GFS2_ACL_IS_DEFAULT(er->er_name, er->er_name_len) &&
!capable(CAP_SYS_ADMIN))
return -EPERM;
if (ip->i_sbd->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;
return gfs2_ea_get_i(ip, er);
}
static int system_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
int remove = 0;
int error;
if (GFS2_ACL_IS_ACCESS(er->er_name, er->er_name_len)) {
if (!(er->er_flags & GFS2_ERF_MODE)) {
er->er_mode = ip->i_di.di_mode;
er->er_flags |= GFS2_ERF_MODE;
}
error = gfs2_acl_validate_set(ip, 1, er,
&remove, &er->er_mode);
if (error)
return error;
error = gfs2_ea_set_i(ip, er);
if (error)
return error;
if (remove)
gfs2_ea_remove_i(ip, er);
return 0;
} else if (GFS2_ACL_IS_DEFAULT(er->er_name, er->er_name_len)) {
error = gfs2_acl_validate_set(ip, 0, er,
&remove, NULL);
if (error)
return error;
if (!remove)
error = gfs2_ea_set_i(ip, er);
else {
error = gfs2_ea_remove_i(ip, er);
if (error == -ENODATA)
error = 0;
}
return error;
}
return -EPERM;
}
static int system_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er)
{
if (GFS2_ACL_IS_ACCESS(er->er_name, er->er_name_len)) {
int error = gfs2_acl_validate_remove(ip, 1);
if (error)
return error;
} else if (GFS2_ACL_IS_DEFAULT(er->er_name, er->er_name_len)) {
int error = gfs2_acl_validate_remove(ip, 0);
if (error)
return error;
} else
return -EPERM;
return gfs2_ea_remove_i(ip, er);
}
struct gfs2_eattr_operations gfs2_user_eaops = {
.eo_get = user_eo_get,
.eo_set = user_eo_set,
.eo_remove = user_eo_remove,
.eo_name = "user",
};
struct gfs2_eattr_operations gfs2_system_eaops = {
.eo_get = system_eo_get,
.eo_set = system_eo_set,
.eo_remove = system_eo_remove,
.eo_name = "system",
};
struct gfs2_eattr_operations *gfs2_ea_ops[] = {
NULL,
&gfs2_user_eaops,
&gfs2_system_eaops,
};
/*
* 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.
*/
#ifndef __EAOPS_DOT_H__
#define __EAOPS_DOT_H__
struct gfs2_ea_request;
struct gfs2_eattr_operations {
int (*eo_get) (struct gfs2_inode *ip, struct gfs2_ea_request *er);
int (*eo_set) (struct gfs2_inode *ip, struct gfs2_ea_request *er);
int (*eo_remove) (struct gfs2_inode *ip, struct gfs2_ea_request *er);
char *eo_name;
};
unsigned int gfs2_ea_name2type(const char *name, char **truncated_name);
extern struct gfs2_eattr_operations gfs2_user_eaops;
extern struct gfs2_eattr_operations gfs2_system_eaops;
extern struct gfs2_eattr_operations *gfs2_ea_ops[];
#endif /* __EAOPS_DOT_H__ */
此差异已折叠。
/*
* 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.
*/
#ifndef __EATTR_DOT_H__
#define __EATTR_DOT_H__
#define GFS2_EA_REC_LEN(ea) be32_to_cpu((ea)->ea_rec_len)
#define GFS2_EA_DATA_LEN(ea) be32_to_cpu((ea)->ea_data_len)
#define GFS2_EA_SIZE(ea) \
ALIGN(sizeof(struct gfs2_ea_header) + (ea)->ea_name_len + \
((GFS2_EA_IS_STUFFED(ea)) ? GFS2_EA_DATA_LEN(ea) : \
(sizeof(uint64_t) * (ea)->ea_num_ptrs)), 8)
#define GFS2_EA_STRLEN(ea) \
((((ea)->ea_type == GFS2_EATYPE_USR) ? 5 : 7) + (ea)->ea_name_len + 1)
#define GFS2_EA_IS_STUFFED(ea) (!(ea)->ea_num_ptrs)
#define GFS2_EA_IS_LAST(ea) ((ea)->ea_flags & GFS2_EAFLAG_LAST)
#define GFS2_EAREQ_SIZE_STUFFED(er) \
ALIGN(sizeof(struct gfs2_ea_header) + (er)->er_name_len + (er)->er_data_len, 8)
#define GFS2_EAREQ_SIZE_UNSTUFFED(sdp, er) \
ALIGN(sizeof(struct gfs2_ea_header) + (er)->er_name_len + \
sizeof(uint64_t) * DIV_RU((er)->er_data_len, (sdp)->sd_jbsize), 8)
#define GFS2_EA2NAME(ea) ((char *)((struct gfs2_ea_header *)(ea) + 1))
#define GFS2_EA2DATA(ea) (GFS2_EA2NAME(ea) + (ea)->ea_name_len)
#define GFS2_EA2DATAPTRS(ea) \
((uint64_t *)(GFS2_EA2NAME(ea) + ALIGN((ea)->ea_name_len, 8)))
#define GFS2_EA2NEXT(ea) \
((struct gfs2_ea_header *)((char *)(ea) + GFS2_EA_REC_LEN(ea)))
#define GFS2_EA_BH2FIRST(bh) \
((struct gfs2_ea_header *)((bh)->b_data + sizeof(struct gfs2_meta_header)))
#define GFS2_ERF_MODE 0x80000000
struct gfs2_ea_request {
char *er_name;
char *er_data;
unsigned int er_name_len;
unsigned int er_data_len;
unsigned int er_type; /* GFS2_EATYPE_... */
int er_flags;
mode_t er_mode;
};
struct gfs2_ea_location {
struct buffer_head *el_bh;
struct gfs2_ea_header *el_ea;
struct gfs2_ea_header *el_prev;
};
int gfs2_ea_repack(struct gfs2_inode *ip);
int gfs2_ea_get_i(struct gfs2_inode *ip, struct gfs2_ea_request *er);
int gfs2_ea_set_i(struct gfs2_inode *ip, struct gfs2_ea_request *er);
int gfs2_ea_remove_i(struct gfs2_inode *ip, struct gfs2_ea_request *er);
int gfs2_ea_list(struct gfs2_inode *ip, struct gfs2_ea_request *er);
int gfs2_ea_get(struct gfs2_inode *ip, struct gfs2_ea_request *er);
int gfs2_ea_set(struct gfs2_inode *ip, struct gfs2_ea_request *er);
int gfs2_ea_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er);
int gfs2_ea_dealloc(struct gfs2_inode *ip);
int gfs2_get_eattr_meta(struct gfs2_inode *ip, struct gfs2_user_buffer *ub);
/* Exported to acl.c */
int gfs2_ea_find(struct gfs2_inode *ip,
struct gfs2_ea_request *er,
struct gfs2_ea_location *el);
int gfs2_ea_get_copy(struct gfs2_inode *ip,
struct gfs2_ea_location *el,
char *data);
int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el,
struct iattr *attr, char *data);
#endif /* __EATTR_DOT_H__ */
/*
* 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.
*/
#ifndef __FORMAT_DOT_H__
#define __FORMAT_DOT_H__
static const uint32_t gfs2_old_fs_formats[] = {
0
};
static const uint32_t gfs2_old_multihost_formats[] = {
0
};
#endif /* __FORMAT_DOT_H__ */
/*
* 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.
*/
#ifndef __GFS2_DOT_H__
#define __GFS2_DOT_H__
#include <linux/gfs2_ondisk.h>
#include "lm_interface.h"
#include "lvb.h"
#include "incore.h"
#include "util.h"
enum {
NO_CREATE = 0,
CREATE = 1,
};
enum {
NO_WAIT = 0,
WAIT = 1,
};
enum {
NO_FORCE = 0,
FORCE = 1,
};
/* Divide num by den. Round up if there is a remainder. */
#define DIV_RU(num, den) (((num) + (den) - 1) / (den))
#define GFS2_FAST_NAME_SIZE 8
#define get_v2sdp(sb) ((struct gfs2_sbd *)(sb)->s_fs_info)
#define set_v2sdp(sb, sdp) (sb)->s_fs_info = (sdp)
#define get_v2ip(inode) ((struct gfs2_inode *)(inode)->u.generic_ip)
#define set_v2ip(inode, ip) (inode)->u.generic_ip = (ip)
#define get_v2fp(file) ((struct gfs2_file *)(file)->private_data)
#define set_v2fp(file, fp) (file)->private_data = (fp)
#define get_v2bd(bh) ((struct gfs2_bufdata *)(bh)->b_private)
#define set_v2bd(bh, bd) (bh)->b_private = (bd)
#define get_v2db(bh) ((struct gfs2_databuf *)(bh)->b_private)
#define set_v2db(bh, db) (bh)->b_private = (db)
#define get_transaction ((struct gfs2_trans *)(current->journal_info))
#define set_transaction(tr) (current->journal_info) = (tr)
#define get_gl2ip(gl) ((struct gfs2_inode *)(gl)->gl_object)
#define set_gl2ip(gl, ip) (gl)->gl_object = (ip)
#define get_gl2rgd(gl) ((struct gfs2_rgrpd *)(gl)->gl_object)
#define set_gl2rgd(gl, rgd) (gl)->gl_object = (rgd)
#define get_gl2gl(gl) ((struct gfs2_glock *)(gl)->gl_object)
#define set_gl2gl(gl, gl2) (gl)->gl_object = (gl2)
#endif /* __GFS2_DOT_H__ */
此差异已折叠。
/*
* 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.
*/
#ifndef __GLOCK_DOT_H__
#define __GLOCK_DOT_H__
/* Flags for lock requests; used in gfs2_holder gh_flag field.
From lm_interface.h:
#define LM_FLAG_TRY 0x00000001
#define LM_FLAG_TRY_1CB 0x00000002
#define LM_FLAG_NOEXP 0x00000004
#define LM_FLAG_ANY 0x00000008
#define LM_FLAG_PRIORITY 0x00000010 */
#define GL_LOCAL_EXCL 0x00000020
#define GL_ASYNC 0x00000040
#define GL_EXACT 0x00000080
#define GL_SKIP 0x00000100
#define GL_ATIME 0x00000200
#define GL_NOCACHE 0x00000400
#define GL_SYNC 0x00000800
#define GL_NOCANCEL 0x00001000
#define GL_NEVER_RECURSE 0x00002000
#define GLR_TRYFAILED 13
#define GLR_CANCELED 14
static inline int gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
{
struct gfs2_holder *gh;
int locked = 0;
/* Look in glock's list of holders for one with current task as owner */
spin_lock(&gl->gl_spin);
list_for_each_entry(gh, &gl->gl_holders, gh_list) {
if (gh->gh_owner == current) {
locked = 1;
break;
}
}
spin_unlock(&gl->gl_spin);
return locked;
}
static inline int gfs2_glock_is_held_excl(struct gfs2_glock *gl)
{
return (gl->gl_state == LM_ST_EXCLUSIVE);
}
static inline int gfs2_glock_is_held_dfrd(struct gfs2_glock *gl)
{
return (gl->gl_state == LM_ST_DEFERRED);
}
static inline int gfs2_glock_is_held_shrd(struct gfs2_glock *gl)
{
return (gl->gl_state == LM_ST_SHARED);
}
static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl)
{
int ret;
spin_lock(&gl->gl_spin);
ret = !list_empty(&gl->gl_waiters2) || !list_empty(&gl->gl_waiters3);
spin_unlock(&gl->gl_spin);
return ret;
}
struct gfs2_glock *gfs2_glock_find(struct gfs2_sbd *sdp,
struct lm_lockname *name);
int gfs2_glock_get(struct gfs2_sbd *sdp,
uint64_t number, struct gfs2_glock_operations *glops,
int create, struct gfs2_glock **glp);
void gfs2_glock_hold(struct gfs2_glock *gl);
int gfs2_glock_put(struct gfs2_glock *gl);
void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, int flags,
struct gfs2_holder *gh);
void gfs2_holder_reinit(unsigned int state, int flags, struct gfs2_holder *gh);
void gfs2_holder_uninit(struct gfs2_holder *gh);
struct gfs2_holder *gfs2_holder_get(struct gfs2_glock *gl, unsigned int state,
int flags, gfp_t gfp_flags);
void gfs2_holder_put(struct gfs2_holder *gh);
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);
int gfs2_glmutex_trylock(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_dq(struct gfs2_holder *gh);
void gfs2_glock_prefetch(struct gfs2_glock *gl, unsigned int state, int flags);
void gfs2_glock_force_drop(struct gfs2_glock *gl);
int gfs2_glock_be_greedy(struct gfs2_glock *gl, unsigned int time);
int gfs2_glock_nq_init(struct gfs2_glock *gl, unsigned int state, int flags,
struct gfs2_holder *gh);
void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
uint64_t number, struct gfs2_glock_operations *glops,
unsigned int state, int flags, struct gfs2_holder *gh);
int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
void gfs2_glock_prefetch_num(struct gfs2_sbd *sdp, uint64_t number,
struct gfs2_glock_operations *glops,
unsigned int state, int flags);
/* Lock Value Block functions */
int gfs2_lvb_hold(struct gfs2_glock *gl);
void gfs2_lvb_unhold(struct gfs2_glock *gl);
void gfs2_lvb_sync(struct gfs2_glock *gl);
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);
void gfs2_reclaim_glock(struct gfs2_sbd *sdp);
void gfs2_scand_internal(struct gfs2_sbd *sdp);
void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait);
int gfs2_dump_lockstate(struct gfs2_sbd *sdp);
#endif /* __GLOCK_DOT_H__ */
此差异已折叠。
/*
* 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.
*/
#ifndef __GLOPS_DOT_H__
#define __GLOPS_DOT_H__
extern struct gfs2_glock_operations gfs2_meta_glops;
extern struct gfs2_glock_operations gfs2_inode_glops;
extern struct gfs2_glock_operations gfs2_rgrp_glops;
extern struct gfs2_glock_operations gfs2_trans_glops;
extern struct gfs2_glock_operations gfs2_iopen_glops;
extern struct gfs2_glock_operations gfs2_flock_glops;
extern struct gfs2_glock_operations gfs2_nondisk_glops;
extern struct gfs2_glock_operations gfs2_quota_glops;
extern struct gfs2_glock_operations gfs2_journal_glops;
#endif /* __GLOPS_DOT_H__ */
此差异已折叠。
此差异已折叠。
/*
* 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.
*/
#ifndef __INODE_DOT_H__
#define __INODE_DOT_H__
static inline int gfs2_is_stuffed(struct gfs2_inode *ip)
{
return !ip->i_di.di_height;
}
static inline int gfs2_is_jdata(struct gfs2_inode *ip)
{
return ip->i_di.di_flags & GFS2_DIF_JDATA;
}
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);
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,
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 gfs2_inode_dealloc(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul);
int gfs2_change_nlink(struct gfs2_inode *ip, int diff);
int gfs2_lookupi(struct gfs2_inode *dip, struct qstr *name, int is_root,
struct gfs2_inode **ipp);
int gfs2_createi(struct gfs2_holder *ghs, 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,
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);
static inline int gfs2_lookup_simple(struct gfs2_inode *dip, char *name,
struct gfs2_inode **ipp)
{
struct qstr qstr;
memset(&qstr, 0, sizeof(struct qstr));
qstr.name = name;
qstr.len = strlen(name);
return gfs2_lookupi(dip, &qstr, 1, ipp);
}
#endif /* __INODE_DOT_H__ */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* 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.
*/
#ifndef __LVB_DOT_H__
#define __LVB_DOT_H__
#define GFS2_MIN_LVB_SIZE 32
struct gfs2_quota_lvb {
uint32_t qb_magic;
uint32_t __pad;
uint64_t qb_limit; /* Hard limit of # blocks to alloc */
uint64_t qb_warn; /* Warn user when alloc is above this # */
int64_t qb_value; /* Current # blocks allocated */
};
void gfs2_quota_lvb_in(struct gfs2_quota_lvb *qb, char *lvb);
void gfs2_quota_lvb_out(struct gfs2_quota_lvb *qb, char *lvb);
void gfs2_quota_lvb_print(struct gfs2_quota_lvb *qb);
#endif /* __LVB_DOT_H__ */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册