You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
[GFS2] The core of GFS2
This patch contains all the core files for GFS2. Signed-off-by: David Teigland <teigland@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
committed by
Steven Whitehouse
parent
f7825dcf8c
commit
b3b94faa5f
@@ -0,0 +1,46 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
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/
|
||||||
|
|
||||||
+312
@@ -0,0 +1,312 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
||||||
+178
@@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
||||||
+1206
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
||||||
@@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
||||||
+2157
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
||||||
+185
@@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
* 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,
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
||||||
|
|
||||||
+1620
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
||||||
|
|
||||||
+2513
File diff suppressed because it is too large
Load Diff
+143
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user