cluster: STABLE31 - Drop gfs* from cluster
Fabio M. Di Nitto
fabbione at fedoraproject.org
Wed Oct 6 18:19:06 UTC 2010
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=803f7abd0eafacb4c888e821f1b70ed5a4ec2a46
Commit: 803f7abd0eafacb4c888e821f1b70ed5a4ec2a46
Parent: 2b2f061a4751d1a2ae1039b7d77297a45781b43b
Author: Fabio M. Di Nitto <fdinitto at redhat.com>
AuthorDate: Wed Oct 6 20:17:31 2010 +0200
Committer: Fabio M. Di Nitto <fdinitto at redhat.com>
CommitterDate: Wed Oct 6 20:17:31 2010 +0200
Drop gfs* from cluster
See https://www.redhat.com/archives/linux-cluster/2010-October/msg00012.html
Signed-off-by: Fabio M. Di Nitto <fdinitto at redhat.com>
---
Makefile | 15 +-
cman/init.d/cman.in | 21 -
configure | 68 -
doc/COPYRIGHT | 19 -
doc/usage.txt | 23 -
gfs-kernel/src/gfs/Makefile | 72 -
gfs-kernel/src/gfs/acl.c | 398 ----
gfs-kernel/src/gfs/acl.h | 34 -
gfs-kernel/src/gfs/bits.c | 211 --
gfs-kernel/src/gfs/bits.h | 18 -
gfs-kernel/src/gfs/bmap.c | 1393 -------------
gfs-kernel/src/gfs/bmap.h | 35 -
gfs-kernel/src/gfs/daemon.c | 181 --
gfs-kernel/src/gfs/daemon.h | 11 -
gfs-kernel/src/gfs/dio.c | 1342 ------------
gfs-kernel/src/gfs/dio.h | 157 --
gfs-kernel/src/gfs/dir.c | 2394 ----------------------
gfs-kernel/src/gfs/dir.h | 42 -
gfs-kernel/src/gfs/eaops.c | 173 --
gfs-kernel/src/gfs/eaops.h | 21 -
gfs-kernel/src/gfs/eattr.c | 2007 ------------------
gfs-kernel/src/gfs/eattr.h | 97 -
gfs-kernel/src/gfs/file.c | 437 ----
gfs-kernel/src/gfs/file.h | 42 -
gfs-kernel/src/gfs/fixed_div64.h | 107 -
gfs-kernel/src/gfs/format.h | 17 -
gfs-kernel/src/gfs/gfs.h | 65 -
gfs-kernel/src/gfs/gfs_ioctl.h | 31 -
gfs-kernel/src/gfs/gfs_ondisk.h | 1904 -----------------
gfs-kernel/src/gfs/glock.c | 3035 ---------------------------
gfs-kernel/src/gfs/glock.h | 140 --
gfs-kernel/src/gfs/glops.c | 664 ------
gfs-kernel/src/gfs/glops.h | 13 -
gfs-kernel/src/gfs/incore.h | 1218 -----------
gfs-kernel/src/gfs/inode.c | 2224 --------------------
gfs-kernel/src/gfs/inode.h | 57 -
gfs-kernel/src/gfs/ioctl.c | 1607 ---------------
gfs-kernel/src/gfs/ioctl.h | 9 -
gfs-kernel/src/gfs/lm.c | 237 ---
gfs-kernel/src/gfs/lm.h | 32 -
gfs-kernel/src/gfs/lm_interface.h | 269 ---
gfs-kernel/src/gfs/lock_dlm.h | 173 --
gfs-kernel/src/gfs/lock_dlm_lock.c | 518 -----
gfs-kernel/src/gfs/lock_dlm_main.c | 31 -
gfs-kernel/src/gfs/lock_dlm_mount.c | 278 ---
gfs-kernel/src/gfs/lock_dlm_sysfs.c | 229 ---
gfs-kernel/src/gfs/lock_dlm_thread.c | 358 ----
gfs-kernel/src/gfs/lock_nolock_main.c | 221 --
gfs-kernel/src/gfs/locking.c | 171 --
gfs-kernel/src/gfs/log.c | 1424 -------------
gfs-kernel/src/gfs/log.h | 66 -
gfs-kernel/src/gfs/lops.c | 1649 ---------------
gfs-kernel/src/gfs/lops.h | 166 --
gfs-kernel/src/gfs/lvb.c | 135 --
gfs-kernel/src/gfs/lvb.h | 53 -
gfs-kernel/src/gfs/main.c | 134 --
gfs-kernel/src/gfs/mount.c | 209 --
gfs-kernel/src/gfs/mount.h | 6 -
gfs-kernel/src/gfs/ondisk.c | 15 -
gfs-kernel/src/gfs/ops_address.c | 504 -----
gfs-kernel/src/gfs/ops_address.h | 6 -
gfs-kernel/src/gfs/ops_dentry.c | 111 -
gfs-kernel/src/gfs/ops_dentry.h | 6 -
gfs-kernel/src/gfs/ops_export.c | 395 ----
gfs-kernel/src/gfs/ops_export.h | 6 -
gfs-kernel/src/gfs/ops_file.c | 1913 -----------------
gfs-kernel/src/gfs/ops_file.h | 11 -
gfs-kernel/src/gfs/ops_fstype.c | 828 --------
gfs-kernel/src/gfs/ops_fstype.h | 13 -
gfs-kernel/src/gfs/ops_inode.c | 1680 ---------------
gfs-kernel/src/gfs/ops_inode.h | 9 -
gfs-kernel/src/gfs/ops_super.c | 463 -----
gfs-kernel/src/gfs/ops_super.h | 6 -
gfs-kernel/src/gfs/ops_vm.c | 233 ---
gfs-kernel/src/gfs/ops_vm.h | 7 -
gfs-kernel/src/gfs/page.c | 266 ---
gfs-kernel/src/gfs/page.h | 13 -
gfs-kernel/src/gfs/proc.c | 490 -----
gfs-kernel/src/gfs/proc.h | 14 -
gfs-kernel/src/gfs/quota.c | 1140 -----------
gfs-kernel/src/gfs/quota.h | 28 -
gfs-kernel/src/gfs/recovery.c | 780 -------
gfs-kernel/src/gfs/recovery.h | 23 -
gfs-kernel/src/gfs/rgrp.c | 2152 -------------------
gfs-kernel/src/gfs/rgrp.h | 75 -
gfs-kernel/src/gfs/super.c | 1274 ------------
gfs-kernel/src/gfs/super.h | 54 -
gfs-kernel/src/gfs/sys.c | 145 --
gfs-kernel/src/gfs/sys.h | 14 -
gfs-kernel/src/gfs/trans.c | 453 ----
gfs-kernel/src/gfs/trans.h | 24 -
gfs-kernel/src/gfs/unlinked.c | 432 ----
gfs-kernel/src/gfs/unlinked.h | 19 -
gfs-kernel/src/gfs/util.c | 590 ------
gfs-kernel/src/gfs/util.h | 330 ---
gfs/Makefile | 23 -
gfs/gfs_debug/Makefile | 32 -
gfs/gfs_debug/basic.c | 436 ----
gfs/gfs_debug/basic.h | 26 -
gfs/gfs_debug/block_device.c | 117 --
gfs/gfs_debug/block_device.h | 14 -
gfs/gfs_debug/gfs_debug.h | 83 -
gfs/gfs_debug/main.c | 179 --
gfs/gfs_debug/ondisk.c | 18 -
gfs/gfs_debug/readfile.c | 236 ---
gfs/gfs_debug/readfile.h | 14 -
gfs/gfs_debug/util.c | 334 ---
gfs/gfs_debug/util.h | 29 -
gfs/gfs_fsck/FEATURES | 25 -
gfs/gfs_fsck/Makefile | 60 -
gfs/gfs_fsck/TODO | 49 -
gfs/gfs_fsck/bio.c | 168 --
gfs/gfs_fsck/bio.h | 23 -
gfs/gfs_fsck/bitmap.c | 118 --
gfs/gfs_fsck/bitmap.h | 20 -
gfs/gfs_fsck/block_list.c | 283 ---
gfs/gfs_fsck/block_list.h | 89 -
gfs/gfs_fsck/eattr.c | 100 -
gfs/gfs_fsck/eattr.h | 21 -
gfs/gfs_fsck/file.c | 231 ---
gfs/gfs_fsck/file.h | 10 -
gfs/gfs_fsck/fs_bits.c | 350 ----
gfs/gfs_fsck/fs_bits.h | 34 -
gfs/gfs_fsck/fs_bmap.c | 529 -----
gfs/gfs_fsck/fs_bmap.h | 10 -
gfs/gfs_fsck/fs_dir.c | 1775 ----------------
gfs/gfs_fsck/fs_dir.h | 35 -
gfs/gfs_fsck/fs_inode.c | 602 ------
gfs/gfs_fsck/fs_inode.h | 22 -
gfs/gfs_fsck/fs_recovery.c | 75 -
gfs/gfs_fsck/fs_recovery.h | 9 -
gfs/gfs_fsck/fsck.h | 49 -
gfs/gfs_fsck/fsck_incore.h | 137 --
gfs/gfs_fsck/hash.c | 91 -
gfs/gfs_fsck/hash.h | 7 -
gfs/gfs_fsck/initialize.c | 421 ----
gfs/gfs_fsck/inode.c | 335 ---
gfs/gfs_fsck/inode.h | 13 -
gfs/gfs_fsck/inode_hash.c | 74 -
gfs/gfs_fsck/inode_hash.h | 7 -
gfs/gfs_fsck/link.c | 94 -
gfs/gfs_fsck/link.h | 8 -
gfs/gfs_fsck/log.c | 148 --
gfs/gfs_fsck/log.h | 87 -
gfs/gfs_fsck/lost_n_found.c | 133 --
gfs/gfs_fsck/lost_n_found.h | 8 -
gfs/gfs_fsck/main.c | 290 ---
gfs/gfs_fsck/metawalk.c | 1088 ----------
gfs/gfs_fsck/metawalk.h | 78 -
gfs/gfs_fsck/ondisk.c | 1342 ------------
gfs/gfs_fsck/ondisk.h | 2045 ------------------
gfs/gfs_fsck/pass1.c | 1124 ----------
gfs/gfs_fsck/pass1b.c | 563 -----
gfs/gfs_fsck/pass1c.c | 290 ---
gfs/gfs_fsck/pass2.c | 962 ---------
gfs/gfs_fsck/pass3.c | 281 ---
gfs/gfs_fsck/pass4.c | 233 ---
gfs/gfs_fsck/pass5.c | 394 ----
gfs/gfs_fsck/rgrp.c | 633 ------
gfs/gfs_fsck/rgrp.h | 20 -
gfs/gfs_fsck/super.c | 1435 -------------
gfs/gfs_fsck/super.h | 11 -
gfs/gfs_fsck/util.c | 333 ---
gfs/gfs_fsck/util.h | 27 -
gfs/gfs_grow/Makefile | 34 -
gfs/gfs_grow/main.c | 974 ---------
gfs/gfs_grow/ondisk.c | 18 -
gfs/gfs_jadd/Makefile | 34 -
gfs/gfs_jadd/main.c | 928 ---------
gfs/gfs_jadd/ondisk.c | 18 -
gfs/gfs_mkfs/Makefile | 38 -
gfs/gfs_mkfs/device_geometry.c | 153 --
gfs/gfs_mkfs/fs_geometry.c | 180 --
gfs/gfs_mkfs/locking.c | 102 -
gfs/gfs_mkfs/main.c | 504 -----
gfs/gfs_mkfs/mkfs_gfs.h | 181 --
gfs/gfs_mkfs/ondisk.c | 17 -
gfs/gfs_mkfs/structures.c | 845 --------
gfs/gfs_quota/Makefile | 31 -
gfs/gfs_quota/check.c | 651 ------
gfs/gfs_quota/gfs_quota.h | 98 -
gfs/gfs_quota/layout.c | 601 ------
gfs/gfs_quota/main.c | 759 -------
gfs/gfs_quota/names.c | 84 -
gfs/gfs_quota/ondisk.c | 18 -
gfs/gfs_tool/Makefile | 35 -
gfs/gfs_tool/counters.c | 204 --
gfs/gfs_tool/decipher_lockstate_dump | 172 --
gfs/gfs_tool/df.c | 318 ---
gfs/gfs_tool/gfs_tool.h | 94 -
gfs/gfs_tool/layout.c | 845 --------
gfs/gfs_tool/main.c | 274 ---
gfs/gfs_tool/misc.c | 755 -------
gfs/gfs_tool/ondisk.c | 21 -
gfs/gfs_tool/parse_lockdump | 158 --
gfs/gfs_tool/sb.c | 152 --
gfs/gfs_tool/tune.c | 141 --
gfs/gfs_tool/util.c | 272 ---
gfs/include/global.h | 42 -
gfs/include/linux_endian.h | 68 -
gfs/include/list.h | 325 ---
gfs/include/osi_list.h | 84 -
gfs/include/osi_user.h | 421 ----
gfs/init.d/Makefile | 18 -
gfs/init.d/gfs.in | 148 --
gfs/libgfs/Makefile | 33 -
gfs/libgfs/bio.c | 167 --
gfs/libgfs/bitmap.c | 116 --
gfs/libgfs/block_list.c | 267 ---
gfs/libgfs/file.c | 233 ---
gfs/libgfs/fs_bits.c | 348 ----
gfs/libgfs/fs_bmap.c | 522 -----
gfs/libgfs/fs_dir.c | 1683 ---------------
gfs/libgfs/fs_inode.c | 470 -----
gfs/libgfs/incore.h | 1271 ------------
gfs/libgfs/inode.c | 322 ---
gfs/libgfs/libgfs.h | 398 ----
gfs/libgfs/log.c | 139 --
gfs/libgfs/ondisk.c | 1282 ------------
gfs/libgfs/rgrp.c | 593 ------
gfs/libgfs/size.c | 81 -
gfs/libgfs/super.c | 530 -----
gfs/libgfs/util.c | 271 ---
gfs/man/Makefile | 18 -
gfs/man/fsck.gfs.8 | 59 -
gfs/man/gfs.8 | 37 -
gfs/man/gfs_edit.8 | 1 -
gfs/man/gfs_grow.8 | 63 -
gfs/man/gfs_jadd.8 | 75 -
gfs/man/gfs_quota.8 | 101 -
gfs/man/gfs_tool.8 | 145 --
gfs/man/mkfs.gfs.8 | 82 -
gfs/man/mount.gfs.8 | 193 --
gfs/tests/Makefile | 4 -
gfs/tests/filecon2/Makefile | 19 -
gfs/tests/filecon2/filecon2.h | 146 --
gfs/tests/filecon2/filecon2_client.c | 841 --------
gfs/tests/filecon2/filecon2_server.c | 597 ------
gfs/tests/mmdd/Makefile | 25 -
gfs/tests/mmdd/mmdd.c | 703 -------
gfs2/Makefile | 4 -
gfs2/convert/Makefile | 33 -
gfs2/convert/gfs2_convert.c | 2318 ---------------------
gfs2/edit/Makefile | 37 -
gfs2/edit/gfs2hex.c | 692 -------
gfs2/edit/gfs2hex.h | 14 -
gfs2/edit/hexedit.c | 3581 --------------------------------
gfs2/edit/hexedit.h | 316 ---
gfs2/edit/savemeta.c | 913 ---------
gfs2/fsck/FEATURES | 25 -
gfs2/fsck/Makefile | 56 -
gfs2/fsck/eattr.c | 61 -
gfs2/fsck/eattr.h | 18 -
gfs2/fsck/fs_bits.h | 17 -
gfs2/fsck/fs_recovery.c | 655 ------
gfs2/fsck/fs_recovery.h | 12 -
gfs2/fsck/fsck.h | 135 --
gfs2/fsck/hash.c | 91 -
gfs2/fsck/hash.h | 7 -
gfs2/fsck/initialize.c | 1163 -----------
gfs2/fsck/inode_hash.c | 68 -
gfs2/fsck/inode_hash.h | 10 -
gfs2/fsck/link.c | 94 -
gfs2/fsck/link.h | 10 -
gfs2/fsck/lost_n_found.c | 199 --
gfs2/fsck/lost_n_found.h | 8 -
gfs2/fsck/main.c | 368 ----
gfs2/fsck/metawalk.c | 1580 --------------
gfs2/fsck/metawalk.h | 95 -
gfs2/fsck/pass1.c | 1480 -------------
gfs2/fsck/pass1b.c | 668 ------
gfs2/fsck/pass1c.c | 271 ---
gfs2/fsck/pass2.c | 821 --------
gfs2/fsck/pass3.c | 301 ---
gfs2/fsck/pass4.c | 204 --
gfs2/fsck/pass5.c | 217 --
gfs2/fsck/rgrepair.c | 617 ------
gfs2/fsck/util.c | 373 ----
gfs2/fsck/util.h | 32 -
gfs2/include/osi_list.h | 84 -
gfs2/include/osi_tree.h | 395 ----
gfs2/init.d/Makefile | 18 -
gfs2/init.d/gfs2.in | 172 --
gfs2/libgfs2/Makefile | 33 -
gfs2/libgfs2/block_list.c | 137 --
gfs2/libgfs2/buf.c | 89 -
gfs2/libgfs2/device_geometry.c | 126 --
gfs2/libgfs2/fs_bits.c | 240 ---
gfs2/libgfs2/fs_geometry.c | 233 ---
gfs2/libgfs2/fs_ops.c | 1743 ----------------
gfs2/libgfs2/gfs1.c | 446 ----
gfs2/libgfs2/gfs2_disk_hash.c | 72 -
gfs2/libgfs2/gfs2_log.c | 192 --
gfs2/libgfs2/libgfs2.h | 745 -------
gfs2/libgfs2/misc.c | 459 -----
gfs2/libgfs2/ondisk.c | 630 ------
gfs2/libgfs2/recovery.c | 244 ---
gfs2/libgfs2/rgrp.c | 193 --
gfs2/libgfs2/size.c | 67 -
gfs2/libgfs2/structures.c | 514 -----
gfs2/libgfs2/super.c | 251 ---
gfs2/man/Makefile | 19 -
gfs2/man/fsck.gfs2.8 | 88 -
gfs2/man/gfs2.8 | 40 -
gfs2/man/gfs2_convert.8 | 68 -
gfs2/man/gfs2_edit.8 | 415 ----
gfs2/man/gfs2_grow.8 | 66 -
gfs2/man/gfs2_jadd.8 | 60 -
gfs2/man/gfs2_quota.8 | 105 -
gfs2/man/gfs2_tool.8 | 117 --
gfs2/man/mkfs.gfs2.8 | 95 -
gfs2/man/mount.gfs2.8 | 233 ---
gfs2/mkfs/Makefile | 46 -
gfs2/mkfs/README | 25 -
gfs2/mkfs/gfs2_mkfs.h | 67 -
gfs2/mkfs/main.c | 54 -
gfs2/mkfs/main_grow.c | 357 ----
gfs2/mkfs/main_jadd.c | 536 -----
gfs2/mkfs/main_mkfs.c | 662 ------
gfs2/mount/Makefile | 35 -
gfs2/mount/mount.gfs2.c | 237 ---
gfs2/mount/mtab.c | 197 --
gfs2/mount/ondisk1.c | 59 -
gfs2/mount/util.c | 692 -------
gfs2/mount/util.h | 85 -
gfs2/quota/Makefile | 35 -
gfs2/quota/check.c | 599 ------
gfs2/quota/gfs2_quota.h | 82 -
gfs2/quota/main.c | 909 --------
gfs2/quota/names.c | 81 -
gfs2/tool/Makefile | 37 -
gfs2/tool/gfs2_tool.h | 51 -
gfs2/tool/iflags.h | 40 -
gfs2/tool/main.c | 196 --
gfs2/tool/misc.c | 341 ---
gfs2/tool/ondisk.c | 11 -
gfs2/tool/sb.c | 227 --
gfs2/tool/tune.c | 144 --
group/Makefile | 3 +-
group/gfs_control/Makefile | 31 -
group/gfs_control/main.c | 463 -----
group/gfs_controld/Makefile | 75 -
group/gfs_controld/config.c | 229 ---
group/gfs_controld/config.h | 38 -
group/gfs_controld/cpg-new.c | 3643 ---------------------------------
group/gfs_controld/cpg-old.c | 2452 ----------------------
group/gfs_controld/cpg-old.h | 73 -
group/gfs_controld/crc.c | 72 -
group/gfs_controld/gfs_controld.h | 37 -
group/gfs_controld/gfs_daemon.h | 338 ---
group/gfs_controld/group.c | 372 ----
group/gfs_controld/logging.c | 61 -
group/gfs_controld/main.c | 1593 --------------
group/gfs_controld/member_cman.c | 212 --
group/gfs_controld/member_pcmk.c | 113 -
group/gfs_controld/plock.c | 2372 ---------------------
group/gfs_controld/util.c | 289 ---
group/libgfscontrol/Makefile | 16 -
group/libgfscontrol/libgfscontrol.h | 122 --
group/libgfscontrol/main.c | 426 ----
group/man/Makefile | 3 -
group/man/gfs_control.8 | 44 -
group/man/gfs_controld.8 | 184 --
group/man/gfs_controld.pcmk.8 | 1 -
make/defines.mk.input | 8 -
make/install.mk | 8 -
make/release.mk | 9 +-
make/uninstall.mk | 6 -
368 files changed, 7 insertions(+), 127817 deletions(-)
diff --git a/Makefile b/Makefile
index 3e3cab9..3cf0730 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,7 @@
include make/defines.mk
-REALSUBDIRS = gfs-kernel/src/gfs \
- common config cman dlm fence/libfenced group \
- fence gfs gfs2 rgmanager bindings doc \
- contrib
+REALSUBDIRS = common config cman dlm fence/libfenced group \
+ fence rgmanager bindings doc contrib
SUBDIRS = $(filter-out \
$(if ${without_common},common) \
@@ -13,11 +11,8 @@ SUBDIRS = $(filter-out \
$(if ${without_fence},fence/libfenced) \
$(if ${without_group},group) \
$(if ${without_fence},fence) \
- $(if ${without_gfs2},gfs2) \
$(if ${without_rgmanager},rgmanager) \
$(if ${without_bindings},bindings) \
- $(if ${enable_gfs},,gfs) \
- $(if ${enable_gfs-kernel/src/gfs},,gfs-kernel/src/gfs) \
, $(REALSUBDIRS))
all: ${SUBDIRS}
@@ -25,10 +20,6 @@ all: ${SUBDIRS}
${SUBDIRS}:
${MAKE} -C $@ all
-# Kernel
-
-gfs-kernel: gfs-kernel/src/gfs
-
# Dependencies
common:
@@ -38,8 +29,6 @@ dlm: config
fence/libfenced:
group: cman dlm fence/libfenced
fence: group
-gfs:
-gfs2: group
rgmanager: cman dlm
bindings: cman
contrib: dlm
diff --git a/cman/init.d/cman.in b/cman/init.d/cman.in
index ae69e4b..8314673 100644
--- a/cman/init.d/cman.in
+++ b/cman/init.d/cman.in
@@ -498,12 +498,10 @@ load_kernel_modules()
{
errmsg=$( modprobe configfs 2>&1 ) || return 1
errmsg=$( modprobe dlm 2>&1 ) || return 1
- errmsg=$( modprobe lock_dlm 2>&1 ) || true
}
unload_kernel_modules()
{
- modprobe -r lock_dlm > /dev/null 2>&1 || true
modprobe -r dlm > /dev/null 2>&1 || true
}
@@ -667,16 +665,6 @@ stop_dlm_controld()
stop_daemon dlm_controld
}
-start_gfs_controld()
-{
- start_daemon gfs_controld
-}
-
-stop_gfs_controld()
-{
- stop_daemon gfs_controld
-}
-
start_ocfs2_controld()
{
start_daemon ocfs2_controld.cman
@@ -805,10 +793,6 @@ start()
none \
"Starting dlm_controld"
- runwrap start_gfs_controld \
- none \
- "Starting gfs_controld"
-
runwrap start_ocfs2_controld \
ocfs2_enabled \
"Starting ocfs2_controld"
@@ -854,10 +838,6 @@ stop()
fence_join_enabled \
"Leaving fence domain"
- runwrap stop_gfs_controld \
- none \
- "Stopping gfs_controld"
-
runwrap stop_dlm_controld \
none \
"Stopping dlm_controld"
@@ -927,7 +907,6 @@ cmanstatus()
errmsg=$( status fenced 2>&1 ) || return $?
errmsg=$( status dlm_controld 2>&1 ) || return $?
- errmsg=$( status gfs_controld 2>&1 ) || return $?
if cmannotifyd_enabled; then
errmsg=$( status cmannotifyd 2>&1 ) || return $?
diff --git a/configure b/configure
index cde3be6..735f248 100755
--- a/configure
+++ b/configure
@@ -29,10 +29,7 @@ my %options = (
ldflags => \$ldflags,
extraldflags => \$extraldflags,
objdir => \$objdir,
- kernel_build => \$kernel_build,
kernel_src => \$kernel_src,
- module_dir => \$module_dir,
- gfskincdir => \$gfskincdir,
incdir => \$incdir,
libdir => \$libdir,
ccsincdir => \$ccsincdir,
@@ -84,8 +81,6 @@ my %options = (
conffile => \$conffile,
fence_agents => \$fence_agents,
fenceagentslibdir => \$fenceagentslibdir,
- enable_crack_of_the_day => \$enable_crack_of_the_day,
- enable_legacy_code => \$enable_legacy_code,
enable_contrib => \$enable_contrib,
enable_pacemaker => \$enable_pacemaker,
somajor => \$somajor,
@@ -98,12 +93,9 @@ my %options = (
without_group => \$without_group,
without_fence => \$without_fence,
without_fence_agents => \$without_fence_agents,
- enable_gfs => \$enable_gfs,
- without_gfs2 => \$without_gfs2,
without_rgmanager => \$without_rgmanager,
without_resource_agents => \$without_resource_agents,
without_bindings => \$without_bindings,
- without_kernel_modules => \$without_kernel_modules,
disable_kernel_check => \$disable_kernel_check,
);
@@ -117,10 +109,7 @@ my $err = &GetOptions (\%options,
'ldflags=s',
'extraldflags=s',
'objdir=s',
- 'kernel_build=s',
'kernel_src=s',
- 'module_dir=s',
- 'gfskincdir=s',
'incdir=s',
'libdir=s',
'ccsincdir=s',
@@ -175,8 +164,6 @@ my $err = &GetOptions (\%options,
'release_version=s',
'fence_agents=s',
'fenceagentslibdir=s',
- 'enable_crack_of_the_day',
- 'enable_legacy_code',
'enable_contrib',
'enable_pacemaker',
'without_common',
@@ -186,12 +173,9 @@ my $err = &GetOptions (\%options,
'without_group',
'without_fence',
'without_fence_agents',
- 'enable_gfs',
- 'without_gfs2',
'without_rgmanager',
'without_resource_agents',
'without_bindings',
- 'without_kernel_modules',
'disable_kernel_check');
if(!$err) {
@@ -221,7 +205,6 @@ if ($help || !$err) {
print "--confdir=\tthe cluster config directory. (Default: /etc/cluster)\n";
print "--conffile=\tthe cluster config file. (Default: cluster.conf)\n";
print "--mandir=\tthe base directory for man pages. (Default: {prefix}/share/man)\n";
- print "--module_dir=\tthe base directory for kernel modules. (Default: /lib/modules/`uname -r`/kernel\n";
print "\nbuild flags:\n";
print "--cc=\t\tcompiler to use. (Default: gcc)\n";
print "--debug\t\tEnable debugging build. Changes default optimization CFLAGS to -O0 -DDEBUG -ggdb3\n";
@@ -231,7 +214,6 @@ if ($help || !$err) {
print "--ldflags=\toverride default LDFLAGS settings. (Default: none)\n";
print "--extraldflags=\tadd extra linking options to default LDFLAGS settings. (Default: none)\n";
print "--objdir=\tspecify directory where to store object files. (Defaults: current build dir)\n";
- print "--kernel_build=\tthe directory containing the kernel object tree you wish to\n\t\tcompile against. (Default: /lib/modules/`uname -r`/build\n\t\tif available or /usr/src/linux as fallback)\n";
print "--kernel_src=\tthe directory containing the kernel source you wish to\n\t\tcompile against. (Default: /lib/modules/`uname -r`/source\n\t\tif available or \$kernel_build as fallback)\n";
print "--incdir=\tthe base directory for include files. (Default: {prefix}/include)\n";
print "--ccsincdir=\tthe base directory for ccs include files. (Default: ./config/libs/libccsconfdb)\n";
@@ -270,9 +252,7 @@ if ($help || !$err) {
print "--fence_agents=\tlist of fence agents to configure. (Default: all)\n";
print "\t\tUse --fence_agents=help for a list\n";
print "--fenceagentslibdir=\tspecify directory where to install common fence python lib. (Default: {prefix}/share/fence)\n";
- print "--enable_crack_of_the_day\tEnable build of highly experimental features that rely on code that is not yet available for general use. (Default: no)\n";
print "--enable_contrib\tEnable build of community contributed code/tools. (Default: no)\n";
- print "--enable_legacy_code\tEnable build of old/obsolete/unsupported code/tools. (Default: no)\n";
print "--enable_pacemaker\tEnable building of Pacemaker-specific pieces\n";
print "--without_common\tDisable common building (Default: enabled)\n";
print "--without_config\tDisable config building (Default: enabled)\n";
@@ -281,12 +261,9 @@ if ($help || !$err) {
print "--without_group\tDisable group building (Default: enabled)\n";
print "--without_fence\tDisable fence building (Default: enabled)\n";
print "--without_fence_agents\tDisable fence_agents building (Default: enabled)\n";
- print "--enable_gfs\tEnable gfs building (Default: disabled)\n";
- print "--without_gfs2\tDisable gfs2 building (Default: enabled)\n";
print "--without_rgmanager\tDisable rgmanager building (Default: enabled)\n";
print "--without_resource_agents\tDisable resource agents building (Default: enabled)\n";
print "--without_bindings\tDisable perl/python bindings building (Default: enabled)\n";
- print "--without_kernel_modules\tDisable kernel modules building (Default: enabled)\n";
print "--disable_kernel_check\tDisable kernel version check (Default: enabled)\n";
exit $ret;
}
@@ -406,8 +383,6 @@ if (! -d "$objdir/make") {
mkdir "$objdir";
symlinks(".","Makefile");
symlinks(".","*.mk");
- symlinks("gfs-kernel","*.c");
- symlinks("gfs-kernel","*.h");
symlinks("bindings","*.bindings");
symlinks("bindings","*.pl");
symlinks("bindings","*.xs");
@@ -436,12 +411,6 @@ if (!$kernel_src) {
if (not $disable_kernel_check and !kernel_version($kernel_src,$required_kernelversion)) {
exit 1;
}
-if (!$module_dir) {
- $module_dir="/lib/modules/$un[2]/kernel";
-}
-if (!$gfskincdir) {
- $gfskincdir="${cdir}/gfs-kernel/src/gfs";
-}
if (!$incdir) {
$incdir="${prefix}/include";
}
@@ -596,27 +565,9 @@ if (!$fence_agents) {
if (!$fenceagentslibdir) {
$fenceagentslibdir="${prefix}/share/fence";
}
-if (!$enable_crack_of_the_day) {
- $enable_crack_of_the_day="";
-} else {
- print "\n********************************************************************************************\n";
- print "WARNING: *you* have explicitly enabled all possible experimental features under development!\n";
- print " This code will have no mercy for your data and your machines. You have been warned!\n";
- print "\n********************************************************************************************\n";
- $cflags="${cflags} -DEXPERIMENTAL_BUILD";
-}
if (!$enable_contrib) {
$enable_contrib="";
}
-if (!$enable_legacy_code) {
- $enable_legacy_code="";
-} else {
- print "\n********************************************************************************************\n";
- print "WARNING: *you* have explicitly enabled the build of old/obsoleted/unsupported code/tools\n";
- print " This code is provided *only* for backward compatibility\n";
- print "\n********************************************************************************************\n";
- $cflags="${cflags} -DLEGACY_CODE";
-}
if (!$enable_pacemaker) {
$enable_pacemaker="";
}
@@ -643,12 +594,6 @@ if (!$without_fence_agents) {
} else {
$fence_agents="none";
}
-if (!$enable_gfs) {
- $enable_gfs="";
-}
-if (!$without_gfs2) {
- $without_gfs2="";
-}
if (!$without_rgmanager) {
$without_rgmanager="";
}
@@ -658,11 +603,6 @@ if (!$without_resource_agents) {
if (!$without_bindings) {
$without_bindings="";
}
-if (!$without_kernel_modules) {
- $enable_gfskernel=$enable_gfs;
-} else {
- $enable_gfskernel="";
-}
if (!$disable_kernel_check) {
$disable_kernel_check=0;
}
@@ -715,10 +655,7 @@ while (<IFILE>) {
$_ =~ s/\@CFLAGS\@/$cflags/;
$_ =~ s/\@LDFLAGS\@/$ldflags/;
$_ =~ s/\@OBJDIR\@/$objdir/;
- $_ =~ s/\@KERNEL_BUILD\@/$kernel_build/;
$_ =~ s/\@KERNEL_SRC\@/$kernel_src/;
- $_ =~ s/\@MODULE_DIR\@/$module_dir/;
- $_ =~ s/\@GFSKINCDIR\@/$gfskincdir/;
$_ =~ s/\@INCDIR\@/$incdir/;
$_ =~ s/\@LIBDIR\@/$libdir/;
$_ =~ s/\@CCSINCDIR\@/$ccsincdir/;
@@ -771,8 +708,6 @@ while (<IFILE>) {
$_ =~ s/\@CONFFILE\@/$conffile/;
$_ =~ s/\@FENCE_AGENTS\@/$fence_agents/;
$_ =~ s/\@FENCEAGENTSLIBDIR\@/$fenceagentslibdir/;
- $_ =~ s/\@ENABLE_CRACK_OF_THE_DAY\@/$enable_crack_of_the_day/;
- $_ =~ s/\@ENABLE_LEGACY_CODE\@/$enable_legacy_code/;
$_ =~ s/\@ENABLE_CONTRIB\@/$enable_contrib/;
$_ =~ s/\@ENABLE_PACEMAKER\@/$enable_pacemaker/;
$_ =~ s/\@DISABLE_COMMON\@/$without_common/;
@@ -781,9 +716,6 @@ while (<IFILE>) {
$_ =~ s/\@DISABLE_DLM\@/$without_dlm/;
$_ =~ s/\@DISABLE_GROUP\@/$without_group/;
$_ =~ s/\@DISABLE_FENCE\@/$without_fence/;
- $_ =~ s/\@ENABLE_GFS\@/$enable_gfs/;
- $_ =~ s/\@ENABLE_GFSKERNEL\@/$enable_gfskernel/;
- $_ =~ s/\@DISABLE_GFS2\@/$without_gfs2/;
$_ =~ s/\@DISABLE_RGMANAGER\@/$without_rgmanager/;
$_ =~ s/\@DISABLE_RESOURCE_AGENTS\@/$without_resource_agents/;
$_ =~ s/\@DISABLE_BINDINGS\@/$without_bindings/;
diff --git a/doc/COPYRIGHT b/doc/COPYRIGHT
index e61a585..6881eb6 100644
--- a/doc/COPYRIGHT
+++ b/doc/COPYRIGHT
@@ -60,25 +60,6 @@ fence/man/fence_ifmib.8:
Copyright (C) 2008-2010 Ross Vandegrift.
Written by Ross Vandegrift <ross at kallisti.us>
-gfs/man/gfs_mount.8:
- Portions copyright (C) 2001-2003 The OpenGFS Project
- Portions copyright (C) 2004 <ben.m.cahill at intel.com>
- Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
-
-gfs2/man/gfs2_mount.8:
- Portions copyright (C) 2001-2003 The OpenGFS2 Project
- Portions copyright (C) 2004 <ben.m.cahill at intel.com>
- Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
-
-gfs-kernel/src/gfs/fixed_div64.h:
- Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
- Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- Mountain View, CA 94043, or:
- http://www.sgi.com
- For further information regarding this notice, see:
- http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
-
From rgmanager/AUTHORS:
Lon Hohberger lhh at redhat.com
diff --git a/doc/usage.txt b/doc/usage.txt
index ad53a95..2cc9df7 100644
--- a/doc/usage.txt
+++ b/doc/usage.txt
@@ -32,12 +32,10 @@ Or, minimal manual steps:
> modprobe configfs
> modprobe dlm
-> modprobe gfs2 (if using gfs2)
> mount -t configfs none /sys/kernel/config
> cman_tool join
> fenced
> dlm_controld
-> gfs_controld (if using gfs2)
> fence_tool join
@@ -67,24 +65,3 @@ Or, manually:
> rgmanager
Create services/resources to be managed in cluster.conf.
-
-
-using gfs2
-----------
-
-Create new file systems, using the cluster name from cluster.conf. Pick a
-unique name for each fs and select a number of journals greater than or equal
-to the number of nodes that will mount the fs.
-
-> mkfs.gfs2 -p lock_dlm -t <clustername>:<fsname> -j <#journals> <blockdev>
-
-Use the gfs2 init script to automate mounting gfs2 fs's listed in /etc/fstab:
-
-> service gfs2 start
-
-Or, manually:
-
-> mount -t gfs2 <blockdev> <mountpoint>
-
-(Replace "gfs2" with "gfs" everywhere above to use gfs instead of gfs2.)
-
diff --git a/gfs-kernel/src/gfs/Makefile b/gfs-kernel/src/gfs/Makefile
deleted file mode 100644
index 5bf891d..0000000
--- a/gfs-kernel/src/gfs/Makefile
+++ /dev/null
@@ -1,72 +0,0 @@
-TARGET= gfs.ko
-
-KMODT=$(TARGET)
-KDIRT=fs/gfs
-KHEADT=gfs_ondisk.h gfs_ioctl.h
-
-all: ${TARGET}
-
-ifndef USING_KBUILD
-include ../../../make/defines.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-endif
-
-PWD := $(shell pwd)
-
-SYMVERFILE := ${KERNEL_BUILD}/Module.symvers
-
-obj-m := gfs.o
-gfs-objs := acl.o \
- bits.o \
- bmap.o \
- daemon.o \
- dio.o \
- dir.o \
- eaops.o \
- eattr.o \
- file.o \
- glock.o \
- glops.o \
- inode.o \
- ioctl.o \
- lm.o \
- locking.o \
- lock_nolock_main.o \
- lock_dlm_lock.o \
- lock_dlm_main.o \
- lock_dlm_mount.o \
- lock_dlm_sysfs.o \
- lock_dlm_thread.o \
- log.o \
- lops.o \
- lvb.o \
- main.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 \
- proc.o \
- quota.o \
- recovery.o \
- rgrp.o \
- super.o \
- sys.o \
- trans.o \
- unlinked.o \
- util.o
-
-${TARGET}:
- ${MAKE} -C ${KERNEL_BUILD} M=${PWD} symverfile=${SYMVERFILE} modules USING_KBUILD=yes
-
-clean: generalclean
-
-.PHONY: gfs.ko
diff --git a/gfs-kernel/src/gfs/acl.c b/gfs-kernel/src/gfs/acl.c
deleted file mode 100644
index 3e9d358..0000000
--- a/gfs-kernel/src/gfs/acl.c
+++ /dev/null
@@ -1,398 +0,0 @@
-#include <linux/sched.h>
-#include <linux/fs_struct.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/posix_acl.h>
-#include <linux/posix_acl_xattr.h>
-#include <linux/cred.h>
-
-#include "gfs.h"
-#include "acl.h"
-#include "eattr.h"
-#include "inode.h"
-
-/**
- * gfs_acl_validate_set -
- * @ip:
- * @access:
- * @er:
- * @mode:
- * @remove:
- *
- * Returns: errno
- */
-
-int
-gfs_acl_validate_set(struct gfs_inode *ip, int access,
- struct gfs_ea_request *er,
- int *remove, mode_t *mode)
-{
- struct posix_acl *acl;
- int error;
-
- error = gfs_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 = TRUE;
- return 0;
- }
-
- error = posix_acl_valid(acl);
- if (error)
- goto out;
-
- if (access) {
- error = posix_acl_equiv_mode(acl, mode);
- if (!error)
- *remove = TRUE;
- else if (error > 0)
- error = 0;
- }
-
- out:
- posix_acl_release(acl);
-
- return error;
-}
-
-/**
- * gfs_acl_validate_remove -
- * @ip:
- * @access:
- *
- * Returns: errno
- */
-
-int
-gfs_acl_validate_remove(struct gfs_inode *ip, int access)
-{
- if (!ip->i_sbd->sd_args.ar_posix_acls)
- return -EOPNOTSUPP;
- if (current_fsuid() != ip->i_di.di_uid && !capable(CAP_FOWNER))
- return -EPERM;
- if (ip->i_di.di_type == GFS_FILE_LNK)
- return -EOPNOTSUPP;
- if (!access && ip->i_di.di_type != GFS_FILE_DIR)
- return -EACCES;
-
- return 0;
-}
-
-/**
- * gfs_acl_get -
- * @ip:
- * @access:
- * @acl:
- *
- * Returns: errno
- */
-
-int
-gfs_acl_get(struct gfs_inode *ip, int access, struct posix_acl **acl)
-{
- struct gfs_ea_request er;
- struct gfs_ea_location el;
- int error;
-
- if (!ip->i_di.di_eattr)
- return 0;
-
- memset(&er, 0, sizeof(struct gfs_ea_request));
- if (access) {
- er.er_name = GFS_POSIX_ACL_ACCESS;
- er.er_name_len = GFS_POSIX_ACL_ACCESS_LEN;
- } else {
- er.er_name = GFS_POSIX_ACL_DEFAULT;
- er.er_name_len = GFS_POSIX_ACL_DEFAULT_LEN;
- }
- er.er_type = GFS_EATYPE_SYS;
-
- error = gfs_ea_find(ip, &er, &el);
- if (error)
- return error;
- if (!el.el_ea)
- return 0;
- if (!GFS_EA_DATA_LEN(el.el_ea))
- goto out;
-
- er.er_data = kmalloc(GFS_EA_DATA_LEN(el.el_ea), GFP_NOFS);
- error = -ENOMEM;
- if (!er.er_data)
- goto out;
-
- error = gfs_ea_get_copy(ip, &el, er.er_data);
- if (error)
- goto out_kfree;
-
- *acl = posix_acl_from_xattr(er.er_data, GFS_EA_DATA_LEN(el.el_ea));
- if (IS_ERR(*acl))
- error = PTR_ERR(*acl);
-
- out_kfree:
- kfree(er.er_data);
-
- out:
- brelse(el.el_bh);
-
- return error;
-}
-
-/**
- * gfs_check_acl - Check an ACL for 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
-gfs_check_acl(struct inode *inode, int mask)
-{
- struct posix_acl *acl = NULL;
- int error;
-
- error = gfs_acl_get(get_v2ip(inode), TRUE, &acl);
- if (error)
- return error;
-
- if (acl) {
- error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- return error;
- }
-
- return -EAGAIN;
-}
-
-/**
- * gfs_acl_new_prep -
- * @dip:
- * @type:
- * @mode:
- * @a_acl:
- * @d_acl:
- * @blocks:
- * @data:
- *
- * Returns: errno
- */
-
-int
-gfs_acl_new_prep(struct gfs_inode *dip,
- unsigned int type, mode_t *mode,
- void **a_data, void **d_data,
- unsigned int *size,
- unsigned int *blocks)
-{
- struct posix_acl *acl = NULL;
- int set_a = FALSE, set_d = FALSE;
- int error;
-
- if (!dip->i_sbd->sd_args.ar_posix_acls)
- return 0;
- if (type == GFS_FILE_LNK)
- return 0;
-
- error = gfs_acl_get(dip, FALSE, &acl);
- if (error)
- return error;
- if (!acl) {
- (*mode) &= ~current->fs->umask;
- return 0;
- }
-
- {
- struct posix_acl *clone = posix_acl_clone(acl, GFP_NOFS);
- error = -ENOMEM;
- if (!clone)
- goto out;
- posix_acl_release(acl);
- acl = clone;
- }
-
- error = posix_acl_create_masq(acl, mode);
- if (error < 0)
- goto out;
- if (error > 0) {
- set_a = TRUE;
- error = 0;
- }
- if (type == GFS_FILE_DIR)
- set_d = TRUE;
-
- if (set_a || set_d) {
- struct gfs_ea_request er;
- void *d;
- unsigned int s = posix_acl_xattr_size(acl->a_count);
- unsigned int b;
-
- memset(&er, 0, sizeof(struct gfs_ea_request));
- er.er_name_len = GFS_POSIX_ACL_DEFAULT_LEN;
- er.er_data_len = s;
- error = gfs_ea_check_size(dip->i_sbd, &er);
- if (error)
- goto out;
-
- b = DIV_RU(er.er_data_len, dip->i_sbd->sd_jbsize);
- if (set_a && set_d)
- b *= 2;
- b++;
-
- d = kmalloc(s, GFP_NOFS);
- error = -ENOMEM;
- if (!d)
- goto out;
- posix_acl_to_xattr(acl, d, s);
-
- if (set_a)
- *a_data = d;
- if (set_d)
- *d_data = d;
- *size = s;
- *blocks = b;
-
- error = 0;
- }
-
- out:
- posix_acl_release(acl);
-
- return error;
-}
-
-/**
- * gfs_acl_new_init -
- * @dip:
- * @ip:
- * @a_data:
- * @d_data:
- * @size:
- *
- * Returns: errno
- */
-
-int gfs_acl_new_init(struct gfs_inode *dip, struct gfs_inode *ip,
- void *a_data, void *d_data, unsigned int size)
-{
- void *data = (a_data) ? a_data : d_data;
- unsigned int x;
- int error = 0;
-
- ip->i_alloc = dip->i_alloc; /* Cheesy, but it works. */
-
- for (x = 0; x < 2; x++) {
- struct gfs_ea_request er;
-
- memset(&er, 0, sizeof(struct gfs_ea_request));
- if (x) {
- if (!a_data)
- continue;
- er.er_name = GFS_POSIX_ACL_ACCESS;
- er.er_name_len = GFS_POSIX_ACL_ACCESS_LEN;
- } else {
- if (!d_data)
- continue;
- er.er_name = GFS_POSIX_ACL_DEFAULT;
- er.er_name_len = GFS_POSIX_ACL_DEFAULT_LEN;
- }
- er.er_data = data;
- er.er_data_len = size;
- er.er_type = GFS_EATYPE_SYS;
-
- error = gfs_ea_acl_init(ip, &er);
- if (error)
- break;
- }
-
- ip->i_alloc = NULL;
-
- kfree(data);
-
- return error;
-}
-
-/**
- * gfs_acl_chmod -
- * @ip:
- * @attr:
- *
- * Returns: errno
- */
-
-int
-gfs_acl_chmod(struct gfs_inode *ip, struct iattr *attr)
-{
- struct gfs_ea_request er;
- struct gfs_ea_location el;
- struct posix_acl *acl;
- int error;
-
- if (!ip->i_di.di_eattr)
- goto simple;
-
- memset(&er, 0, sizeof(struct gfs_ea_request));
- er.er_name = GFS_POSIX_ACL_ACCESS;
- er.er_name_len = GFS_POSIX_ACL_ACCESS_LEN;
- er.er_type = GFS_EATYPE_SYS;
-
- error = gfs_ea_find(ip, &er, &el);
- if (error)
- return error;
- if (!el.el_ea)
- goto simple;
- if (!GFS_EA_DATA_LEN(el.el_ea))
- goto simple;
-
- er.er_data = kmalloc(GFS_EA_DATA_LEN(el.el_ea), GFP_NOFS);
- error = -ENOMEM;
- if (!er.er_data)
- goto out;
-
- error = gfs_ea_get_copy(ip, &el, er.er_data);
- if (error)
- goto out_kfree;
-
- acl = posix_acl_from_xattr(er.er_data, GFS_EA_DATA_LEN(el.el_ea));
- if (IS_ERR(acl)) {
- error = PTR_ERR(acl);
- goto out_kfree;
- } else if (!acl) {
- kfree(er.er_data);
- brelse(el.el_bh);
- goto simple;
- }
-
- error = posix_acl_chmod_masq(acl, attr->ia_mode);
- if (error)
- goto out_acl;
-
- posix_acl_to_xattr(acl, er.er_data, GFS_EA_DATA_LEN(el.el_ea));
-
- error = gfs_ea_acl_chmod(ip, &el, attr, er.er_data);
-
- out_acl:
- posix_acl_release(acl);
-
- out_kfree:
- kfree(er.er_data);
-
- out:
- brelse(el.el_bh);
-
- return error;
-
- simple:
- return gfs_setattr_simple(ip, attr);
-}
diff --git a/gfs-kernel/src/gfs/acl.h b/gfs-kernel/src/gfs/acl.h
deleted file mode 100644
index d28fa9c..0000000
--- a/gfs-kernel/src/gfs/acl.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __ACL_DOT_H__
-#define __ACL_DOT_H__
-
-#define GFS_POSIX_ACL_ACCESS "posix_acl_access"
-#define GFS_POSIX_ACL_ACCESS_LEN (16)
-#define GFS_POSIX_ACL_DEFAULT "posix_acl_default"
-#define GFS_POSIX_ACL_DEFAULT_LEN (17)
-
-#define GFS_ACL_IS_ACCESS(name, len) \
- ((len) == GFS_POSIX_ACL_ACCESS_LEN && \
- !memcmp(GFS_POSIX_ACL_ACCESS, (name), (len)))
-
-#define GFS_ACL_IS_DEFAULT(name, len) \
- ((len) == GFS_POSIX_ACL_DEFAULT_LEN && \
- !memcmp(GFS_POSIX_ACL_DEFAULT, (name), (len)))
-
-struct gfs_ea_request;
-
-int gfs_acl_validate_set(struct gfs_inode *ip, int access,
- struct gfs_ea_request *er,
- int *remove, mode_t *mode);
-int gfs_acl_validate_remove(struct gfs_inode *ip, int access);
-int gfs_acl_get(struct gfs_inode *ip, int access, struct posix_acl **acl);
-int gfs_check_acl(struct inode *inode, int mask);
-int gfs_acl_new_prep(struct gfs_inode *dip,
- unsigned int type, mode_t *mode,
- void **a_data, void **d_data,
- unsigned int *size,
- unsigned int *blocks);
-int gfs_acl_new_init(struct gfs_inode *dip, struct gfs_inode *ip,
- void *a_data, void *d_data, unsigned int size);
-int gfs_acl_chmod(struct gfs_inode *ip, struct iattr *attr);
-
-#endif /* __ACL_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/bits.c b/gfs-kernel/src/gfs/bits.c
deleted file mode 100644
index af84bf0..0000000
--- a/gfs-kernel/src/gfs/bits.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * 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=data block) So, each byte represents
- * GFS_NBBY (i.e. 4) blocks.
- */
-
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "bits.h"
-
-#if BITS_PER_LONG == 32
-#define LBITMASK (0x55555555UL)
-#define LBITSKIP55 (0x55555555UL)
-#define LBITSKIP00 (0x00000000UL)
-#else
-#define LBITMASK (0x5555555555555555UL)
-#define LBITSKIP55 (0x5555555555555555UL)
-#define LBITSKIP00 (0x0000000000000000UL)
-#endif
-
-static const char valid_change[16] = {
- /* current */
- /* n */ 0, 1, 1, 1,
- /* e */ 1, 0, 0, 0,
- /* w */ 1, 0, 0, 1,
- 0, 0, 1, 0
-};
-
-/**
- * gfs_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
-gfs_setbit(struct gfs_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 / GFS_NBBY);
- bit = (block % GFS_NBBY) * GFS_BIT_SIZE;
- end = buffer + buflen;
-
- gfs_assert(rgd->rd_sbd, byte < end,);
-
- cur_state = (*byte >> bit) & GFS_BIT_MASK;
-
- if (valid_change[new_state * 4 + cur_state]) {
- *byte ^= cur_state << bit;
- *byte |= new_state << bit;
- } else
- gfs_consist_rgrpd(rgd);
-}
-
-/**
- * gfs_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
-gfs_testbit(struct gfs_rgrpd *rgd,
- unsigned char *buffer, unsigned int buflen, uint32_t block)
-{
- unsigned char *byte, *end, cur_state;
- unsigned int bit;
-
- byte = buffer + (block / GFS_NBBY);
- bit = (block % GFS_NBBY) * GFS_BIT_SIZE;
- end = buffer + buflen;
-
- gfs_assert(rgd->rd_sbd, byte < end,);
-
- cur_state = (*byte >> bit) & GFS_BIT_MASK;
-
- return cur_state;
-}
-
-/**
- * gfs_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: GFS_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
-gfs_bitfit(unsigned char *buffer, unsigned int buflen,
- uint32_t goal, unsigned char old_state)
-{
- const u8 *byte, *start, *end;
- int bit, startbit;
- u32 g1, g2, misaligned;
- unsigned long *plong;
- unsigned long lskipval;
-
- lskipval = (old_state & GFS_BLKST_USED) ? LBITSKIP00 : LBITSKIP55;
- g1 = (goal / GFS_NBBY);
- start = buffer + g1;
- byte = start;
- end = buffer + buflen;
- g2 = ALIGN(g1, sizeof(unsigned long));
- plong = (unsigned long *)(buffer + g2);
- startbit = bit = (goal % GFS_NBBY) * GFS_BIT_SIZE;
- misaligned = g2 - g1;
- if (!misaligned)
- goto ulong_aligned;
-/* parse the bitmap a byte at a time */
-misaligned:
- while (byte < end) {
- if (((*byte >> bit) & GFS_BIT_MASK) == old_state) {
- return goal +
- (((byte - start) * GFS_NBBY) +
- ((bit - startbit) >> 1));
- }
- bit += GFS_BIT_SIZE;
- if (bit >= GFS_NBBY * GFS_BIT_SIZE) {
- bit = 0;
- byte++;
- misaligned--;
- if (!misaligned) {
- plong = (unsigned long *)byte;
- goto ulong_aligned;
- }
- }
- }
- return BFITNOENT;
-
-/* parse the bitmap a unsigned long at a time */
-ulong_aligned:
- /* Stop at "end - 1" or else prefetch can go past the end and segfault.
- We could "if" it but we'd lose some of the performance gained.
- This way will only slow down searching the very last 4/8 bytes
- depending on architecture. I've experimented with several ways
- of writing this section such as using an else before the goto
- but this one seems to be the fastest. */
- while ((unsigned char *)plong < end - sizeof(unsigned long)) {
- prefetch(plong + 1);
- if (((*plong) & LBITMASK) != lskipval)
- break;
- plong++;
- }
- if ((unsigned char *)plong < end) {
- byte = (const u8 *)plong;
- misaligned += sizeof(unsigned long) - 1;
- goto misaligned;
- }
- return BFITNOENT;
-}
-
-/**
- * gfs_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
-gfs_bitcount(struct gfs_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;
-}
diff --git a/gfs-kernel/src/gfs/bits.h b/gfs-kernel/src/gfs/bits.h
deleted file mode 100644
index 2a2372c..0000000
--- a/gfs-kernel/src/gfs/bits.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef __BITS_DOT_H__
-#define __BITS_DOT_H__
-
-#define BFITNOENT (0xFFFFFFFF)
-
-void gfs_setbit(struct gfs_rgrpd *rgd,
- unsigned char *buffer, unsigned int buflen,
- uint32_t block, unsigned char new_state);
-unsigned char gfs_testbit(struct gfs_rgrpd *rgd,
- unsigned char *buffer, unsigned int buflen,
- uint32_t block);
-uint32_t gfs_bitfit(unsigned char *buffer, unsigned int buflen,
- uint32_t goal, unsigned char old_state);
-uint32_t gfs_bitcount(struct gfs_rgrpd *rgd,
- unsigned char *buffer, unsigned int buflen,
- unsigned char state);
-
-#endif /* __BITS_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/bmap.c b/gfs-kernel/src/gfs/bmap.c
deleted file mode 100644
index 0efd1d1..0000000
--- a/gfs-kernel/src/gfs/bmap.c
+++ /dev/null
@@ -1,1393 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "bmap.h"
-#include "dio.h"
-#include "glock.h"
-#include "inode.h"
-#include "quota.h"
-#include "rgrp.h"
-#include "trans.h"
-
-struct metapath {
- unsigned int mp_list[GFS_MAX_META_HEIGHT];
-};
-
-typedef int (*block_call_t) (struct gfs_inode *ip, struct buffer_head *dibh,
- struct buffer_head *bh, uint64_t *top,
- uint64_t *bottom, unsigned int height,
- void *data);
-
-struct strip_mine {
- int sm_first;
- unsigned int sm_height;
-};
-
-/**
- * gfs_unstuffer_sync - unstuff a dinode synchronously
- * @ip: the inode
- * @dibh: the dinode buffer
- * @block: the block number that was allocated
- * @private: not used
- *
- * Returns: errno
- */
-
-int
-gfs_unstuffer_sync(struct gfs_inode *ip, struct buffer_head *dibh,
- uint64_t block, void *private)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *bh;
- int error;
-
- error = gfs_get_data_buffer(ip, block, TRUE, &bh);
- if (error)
- return error;
-
- gfs_buffer_copy_tail(bh, 0, dibh, sizeof(struct gfs_dinode));
-
- error = gfs_dwrite(sdp, bh, DIO_DIRTY | DIO_START | DIO_WAIT);
-
- brelse(bh);
-
- return error;
-}
-
-/**
- * gfs_unstuffer_async - unstuff a dinode asynchronously
- * @ip: the inode
- * @dibh: the dinode buffer
- * @block: the block number that was allocated
- * @private: not used
- *
- * Returns: errno
- */
-
-int
-gfs_unstuffer_async(struct gfs_inode *ip, struct buffer_head *dibh,
- uint64_t block, void *private)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *bh;
- int error;
-
- error = gfs_get_data_buffer(ip, block, TRUE, &bh);
- if (error)
- return error;
-
- gfs_buffer_copy_tail(bh, 0, dibh, sizeof(struct gfs_dinode));
-
- error = gfs_dwrite(sdp, bh, DIO_DIRTY);
-
- brelse(bh);
-
- return error;
-}
-
-/**
- * gfs_unstuff_dinode - Unstuff a dinode when the data has grown too big
- * @ip: The GFS inode to unstuff
- * @unstuffer: the routine that handles unstuffing a non-zero length file
- * @private: private data for the unstuffer
- *
- * This routine unstuffs a dinode and returns it to a "normal" state such
- * that the height can be grown in the traditional way.
- *
- * Returns: errno
- */
-
-int
-gfs_unstuff_dinode(struct gfs_inode *ip, gfs_unstuffer_t unstuffer,
- void *private)
-{
- struct buffer_head *bh, *dibh;
- uint64_t block = 0;
- int journaled = gfs_is_jdata(ip);
- int error;
-
- down_write(&ip->i_rw_mutex);
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto out;
-
- if (ip->i_di.di_size) {
- /* Get a free block, fill it with the stuffed data,
- and write it out to disk */
-
- if (journaled) {
- error = gfs_metaalloc(ip, &block);
- if (error)
- goto out_brelse;
-
- error = gfs_get_data_buffer(ip, block, TRUE, &bh);
- if (error)
- goto out_brelse;
-
- gfs_buffer_copy_tail(bh, sizeof(struct gfs_meta_header),
- dibh, sizeof(struct gfs_dinode));
-
- brelse(bh);
- } else {
- gfs_blkalloc(ip, &block);
-
- error = unstuffer(ip, dibh, block, private);
- if (error)
- goto out_brelse;
- }
- }
-
- /* Set up the pointer to the new block */
-
- gfs_trans_add_bh(ip->i_gl, dibh);
-
- gfs_buffer_clear_tail(dibh, sizeof(struct gfs_dinode));
-
- if (ip->i_di.di_size) {
- *(uint64_t *)(dibh->b_data + sizeof(struct gfs_dinode)) = cpu_to_gfs64(block);
- ip->i_di.di_blocks++;
- }
-
- ip->i_di.di_height = 1;
-
- gfs_dinode_out(&ip->i_di, dibh->b_data);
-
- out_brelse:
- brelse(dibh);
-
- out:
- up_write(&ip->i_rw_mutex);
-
- return error;
-}
-
-/**
- * calc_tree_height - Calculate the height of a metadata tree
- * @ip: The GFS inode
- * @size: The proposed size of the file
- *
- * Work out how tall a metadata tree needs to be in order to accommodate a
- * file of a particular size. If size is less than the current size of
- * the inode, then the current size of the inode is used instead of the
- * supplied one.
- *
- * Returns: the height the tree should be
- */
-
-static unsigned int
-calc_tree_height(struct gfs_inode *ip, uint64_t size)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- uint64_t *arr;
- unsigned int max, height;
-
- if (ip->i_di.di_size > size)
- size = ip->i_di.di_size;
-
- if (gfs_is_jdata(ip)) {
- arr = sdp->sd_jheightsize;
- max = sdp->sd_max_jheight;
- } else {
- arr = sdp->sd_heightsize;
- max = sdp->sd_max_height;
- }
-
- for (height = 0; height < max; height++)
- if (arr[height] >= size)
- break;
-
- return height;
-}
-
-/**
- * build_height - Build a metadata tree of the requested height
- * @ip: The GFS inode
- * @height: The height to build to
- *
- * This routine makes sure that the metadata tree is tall enough to hold
- * "size" bytes of data.
- *
- * Returns: errno
- */
-
-static int
-build_height(struct gfs_inode *ip, int height)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *bh, *dibh;
- uint64_t block, *bp;
- unsigned int x;
- int new_block;
- int error;
-
- while (ip->i_di.di_height < height) {
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- return error;
-
- new_block = FALSE;
- bp = (uint64_t *)(dibh->b_data + sizeof(struct gfs_dinode));
- for (x = 0; x < sdp->sd_diptrs; x++, bp++)
- if (*bp) {
- new_block = TRUE;
- break;
- }
-
- if (new_block) {
- /* Get a new block, fill it with the old direct pointers,
- and write it out */
-
- error = gfs_metaalloc(ip, &block);
- if (error)
- goto fail;
-
- error = gfs_dread(ip->i_gl, block,
- DIO_NEW | DIO_START | DIO_WAIT, &bh);
- if (error)
- goto fail;
-
- gfs_trans_add_bh(ip->i_gl, bh);
- gfs_metatype_set(bh,
- GFS_METATYPE_IN,
- GFS_FORMAT_IN);
- memset(bh->b_data + sizeof(struct gfs_meta_header),
- 0,
- sizeof(struct gfs_indirect) -
- sizeof(struct gfs_meta_header));
- gfs_buffer_copy_tail(bh, sizeof(struct gfs_indirect),
- dibh, sizeof(struct gfs_dinode));
-
- brelse(bh);
- }
-
- /* Set up the new direct pointer and write it out to disk */
-
- gfs_trans_add_bh(ip->i_gl, dibh);
-
- gfs_buffer_clear_tail(dibh, sizeof(struct gfs_dinode));
-
- if (new_block) {
- *(uint64_t *)(dibh->b_data + sizeof(struct gfs_dinode)) = cpu_to_gfs64(block);
- ip->i_di.di_blocks++;
- }
-
- ip->i_di.di_height++;
-
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- return 0;
-
- fail:
- brelse(dibh);
-
- return error;
-}
-
-/**
- * find_metapath - Find path through the metadata tree
- * @ip: The inode pointer
- * @mp: The metapath to return the result in
- * @block: The disk block to look up
- *
- * This routine returns a struct metapath structure that defines a path through
- * the metadata of inode "ip" to get to block "block".
- *
- * Example:
- * Given: "ip" is a height 3 file, "offset" is 101342453, and this is a
- * filesystem with a blocksize of 4096.
- *
- * find_metapath() would return a struct metapath structure set to:
- * mp_offset = 101342453, mp_height = 3, mp_list[0] = 0, mp_list[1] = 48,
- * and mp_list[2] = 165.
- *
- * That means that in order to get to the block containing the byte at
- * offset 101342453, we would load the indirect block pointed to by pointer
- * 0 in the dinode. We would then load the indirect block pointed to by
- * pointer 48 in that indirect block. We would then load the data block
- * pointed to by pointer 165 in that indirect block.
- *
- * ----------------------------------------
- * | Dinode | |
- * | | 4|
- * | |0 1 2 3 4 5 9|
- * | | 6|
- * ----------------------------------------
- * |
- * |
- * V
- * ----------------------------------------
- * | Indirect Block |
- * | 5|
- * | 4 4 4 4 4 5 5 1|
- * |0 5 6 7 8 9 0 1 2|
- * ----------------------------------------
- * |
- * |
- * V
- * ----------------------------------------
- * | Indirect Block |
- * | 1 1 1 1 1 5|
- * | 6 6 6 6 6 1|
- * |0 3 4 5 6 7 2|
- * ----------------------------------------
- * |
- * |
- * V
- * ----------------------------------------
- * | Data block containing offset |
- * | 101342453 |
- * | |
- * | |
- * ----------------------------------------
- *
- */
-
-static struct metapath *
-find_metapath(struct gfs_inode *ip, uint64_t block)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct metapath *mp;
- uint64_t b = block;
- unsigned int i;
-
- mp = gmalloc(sizeof(struct metapath));
- memset(mp, 0, sizeof(struct metapath));
-
- for (i = ip->i_di.di_height; i--;)
- mp->mp_list[i] = do_div(b, sdp->sd_inptrs);
-
- return mp;
-}
-
-/**
- * metapointer - Return pointer to start of metadata in a buffer
- * @bh: The buffer
- * @height: The metadata height (0 = dinode)
- * @mp: The metapath
- *
- * Return a pointer to the block number of the next height of the metadata
- * tree given a buffer containing the pointer to the current height of the
- * metadata tree.
- */
-
-static __inline__ uint64_t *
-metapointer(struct buffer_head *bh, unsigned int height, struct metapath *mp)
-{
- unsigned int head_size = (height > 0) ?
- sizeof(struct gfs_indirect) : sizeof(struct gfs_dinode);
-
- return ((uint64_t *)(bh->b_data + head_size)) + mp->mp_list[height];
-}
-
-/**
- * get_metablock - Get the next metadata block in metadata tree
- * @ip: The GFS inode
- * @bh: Buffer containing the pointers to metadata blocks
- * @height: The height of the tree (0 = dinode)
- * @mp: The metapath
- * @create: Non-zero if we may create a new meatdata block
- * @new: Used to indicate if we did create a new metadata block
- * @block: the returned disk block number
- *
- * Given a metatree, complete to a particular height, checks to see if the next
- * height of the tree exists. If not the next height of the tree is created.
- * The block number of the next height of the metadata tree is returned.
- *
- * Returns: errno
- */
-
-static int
-get_metablock(struct gfs_inode *ip,
- struct buffer_head *bh, unsigned int height, struct metapath *mp,
- int create, int *new, uint64_t *block)
-{
- uint64_t *ptr = metapointer(bh, height, mp);
- int error;
-
- if (*ptr) {
- *block = gfs64_to_cpu(*ptr);
- return 0;
- }
-
- *block = 0;
-
- if (!create)
- return 0;
-
- error = gfs_metaalloc(ip, block);
- if (error)
- return error;
-
- gfs_trans_add_bh(ip->i_gl, bh);
-
- *ptr = cpu_to_gfs64(*block);
- ip->i_di.di_blocks++;
-
- *new = 1;
-
- return 0;
-}
-
-/**
- * get_datablock - Get datablock number from metadata block
- * @ip: The GFS inode
- * @bh: The buffer containing pointers to datablocks
- * @mp: The metapath
- * @create: Non-zero if we may create a new data block
- * @new: Used to indicate if we created a new data block
- * @block: the returned disk block number
- *
- * Given a fully built metadata tree, checks to see if a particular data
- * block exists. It is created if it does not exist and the block number
- * on disk is returned.
- *
- * Returns: errno
- */
-
-static int
-get_datablock(struct gfs_inode *ip,
- struct buffer_head *bh, struct metapath *mp,
- int create, int *new, uint64_t *block)
-{
- uint64_t *ptr = metapointer(bh, ip->i_di.di_height - 1, mp);
-
- if (*ptr) {
- *block = gfs64_to_cpu(*ptr);
- return 0;
- }
-
- *block = 0;
-
- if (!create)
- return 0;
-
- if (gfs_is_jdata(ip)) {
- int error;
- error = gfs_metaalloc(ip, block);
- if (error)
- return error;
- } else
- gfs_blkalloc(ip, block);
-
- gfs_trans_add_bh(ip->i_gl, bh);
-
- *ptr = cpu_to_gfs64(*block);
- ip->i_di.di_blocks++;
-
- *new = 1;
-
- return 0;
-}
-
-/**
- * gfs_block_map - Map a block from an inode to a disk block
- * @ip: The GFS inode
- * @lblock: The logical block number
- * @new: Value/Result argument (1 = may create/did create new blocks)
- * @dblock: the disk block number of the start of an extent
- * @extlen: the size of the extent
- *
- * Find the block number on the current device which corresponds to an
- * inode's block. If the block had to be created, "new" will be set.
- *
- * Returns: errno
- */
-
-int
-gfs_block_map(struct gfs_inode *ip,
- uint64_t lblock, int *new,
- uint64_t *dblock, uint32_t *extlen)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *bh;
- struct metapath *mp;
- int create = *new;
- unsigned int bsize;
- unsigned int height;
- unsigned int end_of_metadata;
- unsigned int x;
- int error = 0;
-
- *new = 0;
- *dblock = 0;
- if (extlen)
- *extlen = 0;
-
- if (create)
- down_write(&ip->i_rw_mutex);
- else
- down_read(&ip->i_rw_mutex);
-
- if (gfs_assert_warn(sdp, !gfs_is_stuffed(ip)))
- goto out;
-
- bsize = (gfs_is_jdata(ip)) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize;
-
- height = calc_tree_height(ip, (lblock + 1) * bsize);
- if (ip->i_di.di_height < height) {
- if (!create)
- goto out;
-
- error = build_height(ip, height);
- if (error)
- goto out;
- }
-
- mp = find_metapath(ip, lblock);
- end_of_metadata = ip->i_di.di_height - 1;
-
- error = gfs_get_inode_buffer(ip, &bh);
- if (error)
- goto out_kfree;
-
- for (x = 0; x < end_of_metadata; x++) {
- error = get_metablock(ip, bh, x, mp, create, new, dblock);
- brelse(bh);
- if (error || !*dblock)
- goto out_kfree;
-
- error = gfs_get_meta_buffer(ip, x + 1, *dblock, *new, &bh);
- if (error)
- goto out_kfree;
- }
-
- error = get_datablock(ip, bh, mp, create, new, dblock);
- if (error) {
- brelse(bh);
- goto out_kfree;
- }
-
- if (extlen && *dblock) {
- *extlen = 1;
-
- if (!*new) {
- uint64_t tmp_dblock;
- int tmp_new;
- unsigned int nptrs;
-
- nptrs = (end_of_metadata) ? sdp->sd_inptrs : sdp->sd_diptrs;
-
- while (++mp->mp_list[end_of_metadata] < nptrs) {
- get_datablock(ip, bh, mp,
- FALSE, &tmp_new,
- &tmp_dblock);
-
- if (*dblock + *extlen != tmp_dblock)
- break;
-
- (*extlen)++;
- }
- }
- }
-
- brelse(bh);
-
- if (*new) {
- error = gfs_get_inode_buffer(ip, &bh);
- if (!error) {
- gfs_trans_add_bh(ip->i_gl, bh);
- gfs_dinode_out(&ip->i_di, bh->b_data);
- brelse(bh);
- }
- }
-
- out_kfree:
- kfree(mp);
-
- out:
- if (create)
- up_write(&ip->i_rw_mutex);
- else
- up_read(&ip->i_rw_mutex);
-
- return error;
-}
-
-/**
- * do_grow - Make a file look bigger than it is
- * @ip: the inode
- * @size: the size to set the file to
- *
- * Called with an exclusive lock on @ip.
- *
- * Returns: errno
- */
-
-static int
-do_grow(struct gfs_inode *ip, uint64_t size)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al;
- struct buffer_head *dibh;
- unsigned int h;
- int journaled = gfs_is_jdata(ip);
- int error;
-
- al = gfs_alloc_get(ip);
-
- error = gfs_quota_lock_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error)
- goto out;
-
- error = gfs_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid);
- if (error)
- goto out_gunlock_q;
-
- if (journaled)
- al->al_requested_meta = sdp->sd_max_height + 1;
- else {
- al->al_requested_meta = sdp->sd_max_height;
- al->al_requested_data = 1;
- }
-
- error = gfs_inplace_reserve(ip);
- if (error)
- goto out_gunlock_q;
-
- /* Trans may require:
- Full extention of the metadata tree, block allocation,
- a dinode modification, and a quota change */
-
- error = gfs_trans_begin(sdp,
- sdp->sd_max_height + al->al_rgd->rd_ri.ri_length +
- 1 + !!journaled,
- 1);
- if (error)
- goto out_ipres;
-
- if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode)) {
- if (gfs_is_stuffed(ip)) {
- error = gfs_unstuff_dinode(ip, gfs_unstuffer_sync, NULL);
- if (error)
- goto out_end_trans;
- }
-
- h = calc_tree_height(ip, size);
- if (ip->i_di.di_height < h) {
- down_write(&ip->i_rw_mutex);
- error = build_height(ip, h);
- up_write(&ip->i_rw_mutex);
- if (error)
- goto out_end_trans;
- }
- }
-
- ip->i_di.di_size = size;
- ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto out_end_trans;
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
-
- out_end_trans:
- gfs_trans_end(sdp);
-
- out_ipres:
- gfs_inplace_release(ip);
-
- out_gunlock_q:
- gfs_quota_unlock_m(ip);
-
- out:
- gfs_alloc_put(ip);
-
- return error;
-}
-
-/**
- * recursive_scan - recursively scan through the end of a file
- * @ip: the inode
- * @dibh: the dinode buffer
- * @mp: the path through the metadata to the point to start
- * @height: the height the recursion is at
- * @block: the indirect block to look at
- * @first: TRUE if this is the first block
- * @bc: the call to make for each piece of metadata
- * @data: data opaque to this function to pass to @bc
- *
- * When this is first called @height and @block should be zero and
- * @first should be TRUE.
- *
- * Returns: errno
- */
-
-static int
-recursive_scan(struct gfs_inode *ip, struct buffer_head *dibh,
- struct metapath *mp, unsigned int height, uint64_t block,
- int first, block_call_t bc, void *data)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *bh = NULL;
- uint64_t *top, *bottom;
- uint64_t bn;
- int error;
-
- if (!height) {
- error = gfs_get_inode_buffer(ip, &bh);
- if (error)
- goto fail;
- dibh = bh;
-
- top = (uint64_t *)(bh->b_data + sizeof(struct gfs_dinode)) +
- mp->mp_list[0];
- bottom = (uint64_t *)(bh->b_data + sizeof(struct gfs_dinode)) +
- sdp->sd_diptrs;
- } else {
- error = gfs_get_meta_buffer(ip, height, block, FALSE, &bh);
- if (error)
- goto fail;
-
- top = (uint64_t *)(bh->b_data + sizeof(struct gfs_indirect)) +
- ((first) ? mp->mp_list[height] : 0);
- bottom = (uint64_t *)(bh->b_data + sizeof(struct gfs_indirect)) +
- sdp->sd_inptrs;
- }
-
- error = bc(ip, dibh, bh, top, bottom, height, data);
- if (error)
- goto fail;
-
- if (height < ip->i_di.di_height - 1)
- for (; top < bottom; top++, first = FALSE) {
- if (!*top)
- continue;
-
- bn = gfs64_to_cpu(*top);
-
- error = recursive_scan(ip, dibh, mp,
- height + 1, bn, first,
- bc, data);
- if (error)
- goto fail;
- }
-
- brelse(bh);
-
- return 0;
-
- fail:
- if (bh)
- brelse(bh);
-
- return error;
-}
-
-/**
- * do_strip - Look for a layer a particular layer of the file and strip it off
- * @ip: the inode
- * @dibh: the dinode buffer
- * @bh: A buffer of pointers
- * @top: The first pointer in the buffer
- * @bottom: One more than the last pointer
- * @height: the height this buffer is at
- * @data: a pointer to a struct strip_mine
- *
- * Returns: errno
- */
-
-static int
-do_strip(struct gfs_inode *ip, struct buffer_head *dibh,
- struct buffer_head *bh, uint64_t *top, uint64_t *bottom,
- unsigned int height, void *data)
-{
- struct strip_mine *sm = (struct strip_mine *)data;
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_rgrp_list rlist;
- uint64_t bn, bstart;
- uint32_t blen;
- uint64_t *p;
- unsigned int rg_blocks = 0;
- int metadata;
- int x;
- int error;
-
- if (!*top)
- sm->sm_first = FALSE;
-
- if (height != sm->sm_height)
- return 0;
-
- if (sm->sm_first) {
- top++;
- sm->sm_first = FALSE;
- }
-
- metadata = (height != ip->i_di.di_height - 1) || gfs_is_jdata(ip);
-
- error = gfs_rindex_hold(sdp, &ip->i_alloc->al_ri_gh);
- if (error)
- return error;
-
- memset(&rlist, 0, sizeof(struct gfs_rgrp_list));
- bstart = 0;
- blen = 0;
-
- for (p = top; p < bottom; p++) {
- if (!*p)
- continue;
-
- bn = gfs64_to_cpu(*p);
-
- if (bstart + blen == bn)
- blen++;
- else {
- if (bstart)
- gfs_rlist_add(sdp, &rlist, bstart);
-
- bstart = bn;
- blen = 1;
- }
- }
-
- if (bstart)
- gfs_rlist_add(sdp, &rlist, bstart);
- else
- goto out; /* Nothing to do */
-
- gfs_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
-
- for (x = 0; x < rlist.rl_rgrps; x++) {
- struct gfs_rgrpd *rgd;
- rgd = get_gl2rgd(rlist.rl_ghs[x].gh_gl);
- rg_blocks += rgd->rd_ri.ri_length;
- }
-
- error = gfs_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
- if (error)
- goto out_rlist;
-
- /* Trans may require:
- All the bitmaps that were reserved.
- One block for the dinode.
- One block for the indirect block being cleared.
- One block for a quota change. */
-
- error = gfs_trans_begin(sdp, rg_blocks + 2, 1);
- if (error)
- goto out_rg_gunlock;
-
- down_write(&ip->i_rw_mutex);
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_trans_add_bh(ip->i_gl, bh);
-
- bstart = 0;
- blen = 0;
-
- for (p = top; p < bottom; p++) {
- if (!*p)
- continue;
-
- bn = gfs64_to_cpu(*p);
-
- if (bstart + blen == bn)
- blen++;
- else {
- if (bstart) {
- if (metadata)
- gfs_metafree(ip, bstart, blen);
- else
- gfs_blkfree(ip, bstart, blen);
- }
-
- bstart = bn;
- blen = 1;
- }
-
- *p = 0;
- if (!ip->i_di.di_blocks)
- gfs_consist_inode(ip);
- ip->i_di.di_blocks--;
- }
- if (bstart) {
- if (metadata)
- gfs_metafree(ip, bstart, blen);
- else
- gfs_blkfree(ip, bstart, blen);
- }
-
- ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
-
- gfs_dinode_out(&ip->i_di, dibh->b_data);
-
- up_write(&ip->i_rw_mutex);
-
- gfs_trans_end(sdp);
-
- out_rg_gunlock:
- gfs_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs);
-
- out_rlist:
- gfs_rlist_free(&rlist);
-
- out:
- gfs_glock_dq_uninit(&ip->i_alloc->al_ri_gh);
-
- return error;
-}
-
-/**
- * gfs_truncator_default - truncate a partial data block
- * @ip: the inode
- * @size: the size the file should be
- *
- * Returns: errno
- */
-
-int
-gfs_truncator_default(struct gfs_inode *ip, uint64_t size)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *bh;
- uint64_t bn;
- int not_new = 0;
- int error;
-
- error = gfs_block_map(ip, size >> sdp->sd_sb.sb_bsize_shift, ¬_new,
- &bn, NULL);
- if (error)
- return error;
- if (!bn)
- return 0;
-
- error = gfs_get_data_buffer(ip, bn, FALSE, &bh);
- if (error)
- return error;
-
- gfs_buffer_clear_tail(bh, size & (sdp->sd_sb.sb_bsize - 1));
-
- error = gfs_dwrite(sdp, bh, DIO_DIRTY);
-
- brelse(bh);
-
- return error;
-}
-
-/**
- * truncator_journaled - truncate a partial data block
- * @ip: the inode
- * @size: the size the file should be
- *
- * Returns: errno
- */
-
-static int
-truncator_journaled(struct gfs_inode *ip, uint64_t size)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *bh;
- uint64_t lbn, dbn;
- uint32_t off;
- int not_new = 0;
- int error;
-
- lbn = size;
- off = do_div(lbn, sdp->sd_jbsize);
-
- error = gfs_block_map(ip, lbn, ¬_new, &dbn, NULL);
- if (error)
- return error;
- if (!dbn)
- return 0;
-
- error = gfs_trans_begin(sdp, 1, 0);
- if (error)
- return error;
-
- error = gfs_get_data_buffer(ip, dbn, FALSE, &bh);
- if (!error) {
- gfs_trans_add_bh(ip->i_gl, bh);
- gfs_buffer_clear_tail(bh,
- sizeof(struct gfs_meta_header) +
- off);
- brelse(bh);
- }
-
- gfs_trans_end(sdp);
-
- return error;
-}
-
-/**
- * gfs_shrink - make a file smaller
- * @ip: the inode
- * @size: the size to make the file
- * @truncator: function to truncate the last partial block
- *
- * Called with an exclusive lock on @ip.
- *
- * Returns: errno
- */
-
-int
-gfs_shrink(struct gfs_inode *ip, uint64_t size, gfs_truncator_t truncator)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_holder ri_gh;
- struct gfs_rgrpd *rgd;
- struct buffer_head *dibh;
- uint64_t block;
- unsigned int height;
- int journaled = gfs_is_jdata(ip);
- int error;
-
- if (!size)
- block = 0;
- else if (journaled) {
- block = size - 1;
- do_div(block, sdp->sd_jbsize);
- }
- else
- block = (size - 1) >> sdp->sd_sb.sb_bsize_shift;
-
- /* Get rid of all the data/metadata blocks */
-
- height = ip->i_di.di_height;
- if (height) {
- struct metapath *mp = find_metapath(ip, block);
- gfs_alloc_get(ip);
-
- error = gfs_quota_hold_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error) {
- gfs_alloc_put(ip);
- kfree(mp);
- return error;
- }
-
- while (height--) {
- struct strip_mine sm;
-
- sm.sm_first = (size) ? TRUE : FALSE;
- sm.sm_height = height;
-
- error = recursive_scan(ip, NULL, mp, 0, 0, TRUE,
- do_strip, &sm);
- if (error) {
- gfs_quota_unhold_m(ip);
- gfs_alloc_put(ip);
- kfree(mp);
- return error;
- }
- }
-
- gfs_quota_unhold_m(ip);
- gfs_alloc_put(ip);
- kfree(mp);
- }
-
- /* If we truncated in the middle of a block, zero out the leftovers. */
-
- if (gfs_is_stuffed(ip)) {
- /* Do nothing */
- } else if (journaled) {
- if (do_mod(size, sdp->sd_jbsize)) {
- error = truncator_journaled(ip, size);
- if (error)
- return error;
- }
- } else if (size & (uint64_t)(sdp->sd_sb.sb_bsize - 1)) {
- error = truncator(ip, size);
- if (error)
- return error;
- }
-
- /* Set the new size (and possibly the height) */
-
- if (!size) {
- error = gfs_rindex_hold(sdp, &ri_gh);
- if (error)
- return error;
- }
-
- error = gfs_trans_begin(sdp, 1, 0);
- if (error)
- goto out;
-
- down_write(&ip->i_rw_mutex);
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto out_end_trans;
-
- if (!size) {
- ip->i_di.di_height = 0;
-
- rgd = gfs_blk2rgrpd(sdp, ip->i_num.no_addr);
- if (!rgd) {
- gfs_consist_inode(ip);
- error = -EIO;
- goto out_end_trans;
- }
-
- ip->i_di.di_goal_rgrp = rgd->rd_ri.ri_addr;
- ip->i_di.di_goal_dblk =
- ip->i_di.di_goal_mblk =
- ip->i_num.no_addr - rgd->rd_ri.ri_data1;
- }
-
- ip->i_di.di_size = size;
- ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
-
- gfs_trans_add_bh(ip->i_gl, dibh);
-
- if (!ip->i_di.di_height &&
- size < sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode))
- gfs_buffer_clear_tail(dibh, sizeof(struct gfs_dinode) + size);
-
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
-
- out_end_trans:
- up_write(&ip->i_rw_mutex);
-
- gfs_trans_end(sdp);
-
- out:
- if (!size)
- gfs_glock_dq_uninit(&ri_gh);
-
- return error;
-}
-
-/**
- * do_same - truncate to same size (update time stamps)
- * @ip:
- *
- * Returns: errno
- */
-
-static int
-do_same(struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *dibh;
- int error;
-
- error = gfs_trans_begin(sdp, 1, 0);
- if (error)
- return error;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto out;
-
- ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
-
- brelse(dibh);
-
- out:
- gfs_trans_end(sdp);
-
- return error;
-}
-
-/**
- * gfs_truncatei - make a file a give size
- * @ip: the inode
- * @size: the size to make the file
- * @truncator: function to truncate the last partial block
- *
- * The file size can grow, shrink, or stay the same size.
- *
- * Returns: errno
- */
-
-int
-gfs_truncatei(struct gfs_inode *ip, uint64_t size,
- gfs_truncator_t truncator)
-{
- if (gfs_assert_warn(ip->i_sbd, ip->i_di.di_type == GFS_FILE_REG))
- return -EINVAL;
-
- if (size == ip->i_di.di_size)
- return do_same(ip);
- else if (size > ip->i_di.di_size)
- return do_grow(ip, size);
- else
- return gfs_shrink(ip, size, truncator);
-}
-
-/**
- * gfs_write_calc_reserv - calculate the number of blocks needed to write to a file
- * @ip: the file
- * @len: the number of bytes to be written to the file
- * @data_blocks: returns the number of data blocks required
- * @ind_blocks: returns the number of indirect blocks required
- *
- */
-
-void
-gfs_write_calc_reserv(struct gfs_inode *ip, unsigned int len,
- unsigned int *data_blocks, unsigned int *ind_blocks)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- unsigned int tmp;
-
- if (gfs_is_jdata(ip)) {
- *data_blocks = DIV_RU(len, sdp->sd_jbsize) + 2;
- *ind_blocks = 3 * (sdp->sd_max_jheight - 1);
- } else {
- *data_blocks = (len >> sdp->sd_sb.sb_bsize_shift) + 3;
- *ind_blocks = 3 * (sdp->sd_max_height - 1);
- }
-
- for (tmp = *data_blocks; tmp > sdp->sd_diptrs;) {
- tmp = DIV_RU(tmp, sdp->sd_inptrs);
- *ind_blocks += tmp;
- }
-}
-
-/**
- * gfs_write_alloc_required - figure out if a write is going to require an allocation
- * @ip: the file being written to
- * @offset: the offset to write to
- * @len: the number of bytes being written
- * @alloc_required: the int is set to TRUE if an alloc is required, FALSE otherwise
- *
- * Returns: errno
- */
-
-int
-gfs_write_alloc_required(struct gfs_inode *ip,
- uint64_t offset, unsigned int len,
- int *alloc_required)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- uint64_t lblock, lblock_stop, dblock;
- uint32_t extlen;
- int not_new = FALSE;
- int error = 0;
-
- *alloc_required = FALSE;
-
- if (!len)
- return 0;
-
- if (gfs_is_stuffed(ip)) {
- if (offset + len > sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode))
- *alloc_required = TRUE;
- return 0;
- }
-
- if (gfs_is_jdata(ip)) {
- unsigned int bsize = sdp->sd_jbsize;
- lblock = offset;
- do_div(lblock, bsize);
- lblock_stop = offset + len + bsize - 1;
- do_div(lblock_stop, bsize);
- } else {
- unsigned int shift = sdp->sd_sb.sb_bsize_shift;
- lblock = offset >> shift;
- lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
- }
-
- for (; lblock < lblock_stop; lblock += extlen) {
- error = gfs_block_map(ip, lblock, ¬_new, &dblock, &extlen);
- if (error)
- return error;
-
- if (!dblock) {
- *alloc_required = TRUE;
- return 0;
- }
- }
-
- return 0;
-}
-
-/**
- * do_gfm - Copy out the dinode/indirect blocks of a file
- * @ip: the file
- * @dibh: the dinode buffer
- * @bh: the indirect buffer we're looking at
- * @top: the first pointer in the block
- * @bottom: one more than the last pointer in the block
- * @height: the height the block is at
- * @data: a pointer to a struct gfs_user_buffer structure
- *
- * If this is a journaled file, copy out the data too.
- *
- * Returns: errno
- */
-
-static int
-do_gfm(struct gfs_inode *ip, struct buffer_head *dibh,
- struct buffer_head *bh, uint64_t *top, uint64_t *bottom,
- unsigned int height, void *data)
-{
- struct gfs_user_buffer *ub = (struct gfs_user_buffer *)data;
- int error;
-
- error = gfs_add_bh_to_ub(ub, bh);
- if (error)
- return error;
-
- if (ip->i_di.di_type != GFS_FILE_DIR ||
- height + 1 != ip->i_di.di_height)
- return 0;
-
- for (; top < bottom; top++)
- if (*top) {
- struct buffer_head *data_bh;
-
- error = gfs_dread(ip->i_gl, gfs64_to_cpu(*top),
- DIO_START | DIO_WAIT,
- &data_bh);
- if (error)
- return error;
-
- error = gfs_add_bh_to_ub(ub, data_bh);
-
- brelse(data_bh);
-
- if (error)
- return error;
- }
-
- return 0;
-}
-
-/**
- * gfs_get_file_meta - return all the metadata for a file
- * @ip: the file
- * @ub: the structure representing the meta
- *
- * Returns: errno
- */
-
-int
-gfs_get_file_meta(struct gfs_inode *ip, struct gfs_user_buffer *ub)
-{
- int error;
-
- if (gfs_is_stuffed(ip)) {
- struct buffer_head *dibh;
- error = gfs_get_inode_buffer(ip, &dibh);
- if (!error) {
- error = gfs_add_bh_to_ub(ub, dibh);
- brelse(dibh);
- }
- } else {
- struct metapath *mp = find_metapath(ip, 0);
- error = recursive_scan(ip, NULL, mp, 0, 0, TRUE, do_gfm, ub);
- kfree(mp);
- }
-
- return error;
-}
diff --git a/gfs-kernel/src/gfs/bmap.h b/gfs-kernel/src/gfs/bmap.h
deleted file mode 100644
index b9ce2e7..0000000
--- a/gfs-kernel/src/gfs/bmap.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __BMAP_DOT_H__
-#define __BMAP_DOT_H__
-
-typedef int (*gfs_unstuffer_t) (struct gfs_inode * ip,
- struct buffer_head * dibh, uint64_t block,
- void *private);
-
-int gfs_unstuffer_sync(struct gfs_inode *ip, struct buffer_head *dibh,
- uint64_t block, void *private);
-int gfs_unstuffer_async(struct gfs_inode *ip, struct buffer_head *dibh,
- uint64_t block, void *private);
-
-int gfs_unstuff_dinode(struct gfs_inode *ip, gfs_unstuffer_t unstuffer,
- void *private);
-
-int gfs_block_map(struct gfs_inode *ip,
- uint64_t lblock, int *new,
- uint64_t *dblock, uint32_t *extlen);
-
-typedef int (*gfs_truncator_t) (struct gfs_inode * ip, uint64_t size);
-
-int gfs_truncator_default(struct gfs_inode *ip, uint64_t size);
-
-int gfs_shrink(struct gfs_inode *ip, uint64_t size, gfs_truncator_t truncator);
-int gfs_truncatei(struct gfs_inode *ip, uint64_t size,
- gfs_truncator_t truncator);
-
-void gfs_write_calc_reserv(struct gfs_inode *ip, unsigned int len,
- unsigned int *data_blocks, unsigned int *ind_blocks);
-int gfs_write_alloc_required(struct gfs_inode *ip, uint64_t offset,
- unsigned int len, int *alloc_required);
-
-int gfs_get_file_meta(struct gfs_inode *ip, struct gfs_user_buffer *ub);
-
-#endif /* __BMAP_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/daemon.c b/gfs-kernel/src/gfs/daemon.c
deleted file mode 100644
index 378e0a7..0000000
--- a/gfs-kernel/src/gfs/daemon.c
+++ /dev/null
@@ -1,181 +0,0 @@
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "daemon.h"
-#include "glock.h"
-#include "log.h"
-#include "quota.h"
-#include "recovery.h"
-#include "super.h"
-#include "unlinked.h"
-
-/**
- * gfs_scand - Look for cached glocks and inodes to toss from memory
- * @sdp: Pointer to GFS superblock
- *
- * One of these daemons runs, finding candidates to add to sd_reclaim_list.
- * See gfs_glockd()
- */
-
-int
-gfs_scand(void *data)
-{
- struct gfs_sbd *sdp = (struct gfs_sbd *)data;
-
- while (!kthread_should_stop()) {
- gfs_scand_internal(sdp);
- schedule_timeout_interruptible(gfs_tune_get(sdp, gt_scand_secs) * HZ);
- }
-
- return 0;
-}
-
-/**
- * gfs_glockd - Reclaim unused glock structures
- * @sdp: Pointer to GFS superblock
- *
- * One or more of these daemons run, reclaiming glocks on sd_reclaim_list.
- * sd_glockd_num says how many daemons are running now.
- * Number of daemons can be set by user, with num_glockd mount option.
- * See gfs_scand()
- */
-
-int
-gfs_glockd(void *data)
-{
- struct gfs_sbd *sdp = (struct gfs_sbd *)data;
-
- while (!kthread_should_stop()) {
- while (atomic_read(&sdp->sd_reclaim_count))
- gfs_reclaim_glock(sdp);
-
- wait_event_interruptible(sdp->sd_reclaim_wchan,
- (atomic_read(&sdp->sd_reclaim_count) ||
- kthread_should_stop()));
- }
-
- return 0;
-}
-
-/**
- * gfs_recoverd - Recover dead machine's journals
- * @sdp: Pointer to GFS superblock
- *
- */
-
-int
-gfs_recoverd(void *data)
-{
- struct gfs_sbd *sdp = (struct gfs_sbd *)data;
-
- while (!kthread_should_stop()) {
- gfs_check_journals(sdp);
- schedule_timeout_interruptible(gfs_tune_get(sdp, gt_recoverd_secs) * HZ);
- }
-
- return 0;
-}
-
-/**
- * gfs_logd - Update log tail as Active Items get flushed to in-place blocks
- * @sdp: Pointer to GFS superblock
- *
- * Also, periodically check to make sure that we're using the most recent
- * journal index.
- */
-
-int
-gfs_logd(void *data)
-{
- struct gfs_sbd *sdp = (struct gfs_sbd *)data;
- struct gfs_holder ji_gh;
-
- while (!kthread_should_stop()) {
- /* Advance the log tail */
- gfs_ail_empty(sdp);
-
- /* Check for latest journal index */
- if (time_after_eq(jiffies,
- sdp->sd_jindex_refresh_time +
- gfs_tune_get(sdp, gt_jindex_refresh_secs) * HZ)) {
- if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags) &&
- !gfs_jindex_hold(sdp, &ji_gh))
- gfs_glock_dq_uninit(&ji_gh);
- sdp->sd_jindex_refresh_time = jiffies;
- }
-
- schedule_timeout_interruptible(gfs_tune_get(sdp, gt_logd_secs) * HZ);
- }
-
- return 0;
-}
-
-/**
- * gfs_quotad - Write cached quota changes into the quota file
- * @sdp: Pointer to GFS superblock
- *
- */
-
-int
-gfs_quotad(void *data)
-{
- struct gfs_sbd *sdp = (struct gfs_sbd *)data;
- int error;
-
- while (!kthread_should_stop()) {
- /* Update statfs file */
- if (gfs_tune_get(sdp, gt_statfs_fast) &&
- time_after_eq(jiffies,
- sdp->sd_statfs_sync_time +
- gfs_tune_get(sdp, gt_statfs_fast) * HZ)) {
- error = gfs_statfs_sync(sdp);
- if (error && error != -EROFS &&
- !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
- printk("GFS: fsid=%s: statfs: error = %d\n",
- sdp->sd_fsname, error);
- sdp->sd_statfs_sync_time = jiffies;
- }
- /* Update quota file */
- if (time_after_eq(jiffies,
- sdp->sd_quota_sync_time +
- gfs_tune_get(sdp, gt_quota_quantum) * HZ)) {
- error = gfs_quota_sync(sdp);
- if (error &&
- error != -EROFS &&
- !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
- printk("GFS: fsid=%s: quotad: error = %d\n",
- sdp->sd_fsname, error);
- sdp->sd_quota_sync_time = jiffies;
- }
-
- /* Clean up */
- gfs_quota_scan(sdp);
- schedule_timeout_interruptible(gfs_tune_get(sdp, gt_quotad_secs) * HZ);
- }
-
- return 0;
-}
-
-/**
- * gfs_inoded - Deallocate unlinked inodes
- * @sdp: Pointer to GFS superblock
- *
- */
-
-int
-gfs_inoded(void *data)
-{
- struct gfs_sbd *sdp = (struct gfs_sbd *)data;
-
- while (!kthread_should_stop()) {
- gfs_unlinked_dealloc(sdp);
- schedule_timeout_interruptible(gfs_tune_get(sdp, gt_inoded_secs) * HZ);
- }
-
- return 0;
-}
diff --git a/gfs-kernel/src/gfs/daemon.h b/gfs-kernel/src/gfs/daemon.h
deleted file mode 100644
index 882c72f..0000000
--- a/gfs-kernel/src/gfs/daemon.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __DAEMON_DOT_H__
-#define __DAEMON_DOT_H__
-
-int gfs_scand(void *data);
-int gfs_glockd(void *data);
-int gfs_recoverd(void *data);
-int gfs_logd(void *data);
-int gfs_quotad(void *data);
-int gfs_inoded(void *data);
-
-#endif /* __DAEMON_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/dio.c b/gfs-kernel/src/gfs/dio.c
deleted file mode 100644
index 56cb185..0000000
--- a/gfs-kernel/src/gfs/dio.c
+++ /dev/null
@@ -1,1342 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/writeback.h>
-
-#include "gfs.h"
-#include "dio.h"
-#include "glock.h"
-#include "glops.h"
-#include "inode.h"
-#include "log.h"
-#include "lops.h"
-#include "rgrp.h"
-#include "trans.h"
-
-#define buffer_busy(bh) ((bh)->b_state & ((1ul << BH_Dirty) | (1ul << BH_Lock)))
-
-/**
- * aspace_get_block -
- * @inode:
- * @lblock:
- * @bh_result:
- * @create:
- *
- * Returns: errno
- */
-
-static int
-aspace_get_block(struct inode *inode, sector_t lblock,
- struct buffer_head *bh_result, int create)
-{
- gfs_assert_warn(get_v2sdp(inode->i_sb), FALSE);
- return -ENOSYS;
-}
-
-/**
- * gfs_aspace_writepage - write an aspace page
- * @page: the page
- * @wbc:
- *
- * Returns: errno
- */
-
-static int
-gfs_aspace_writepage(struct page *page, struct writeback_control *wbc)
-{
- return block_write_full_page(page, aspace_get_block, wbc);
-}
-
-/**
- * stuck_releasepage - We're stuck in gfs_releasepage(). Print stuff out.
- * @bh: the buffer we're stuck on
- *
- */
-
-static void
-stuck_releasepage(struct buffer_head *bh)
-{
- struct gfs_sbd *sdp = get_v2sdp(bh->b_page->mapping->host->i_sb);
- struct gfs_bufdata *bd = get_v2bd(bh);
-
- printk("GFS: fsid=%s: stuck in gfs_releasepage()...\n", sdp->sd_fsname);
- printk("GFS: fsid=%s: blkno = %llu, bh->b_count = %d\n",
- sdp->sd_fsname,
- (unsigned long long)bh->b_blocknr,
- atomic_read(&bh->b_count));
- printk("GFS: fsid=%s: get_v2bd(bh) = %s\n",
- sdp->sd_fsname,
- (bd) ? "!NULL" : "NULL");
-
- if (bd) {
- struct gfs_glock *gl = bd->bd_gl;
-
- printk("GFS: fsid=%s: gl = (%u, %llu)\n",
- sdp->sd_fsname,
- gl->gl_name.ln_type,
- (unsigned long long)gl->gl_name.ln_number);
-
- printk("GFS: fsid=%s: bd_new_le.le_trans = %s\n",
- sdp->sd_fsname,
- (bd->bd_new_le.le_trans) ? "!NULL" : "NULL");
- printk("GFS: fsid=%s: bd_incore_le.le_trans = %s\n",
- sdp->sd_fsname,
- (bd->bd_incore_le.le_trans) ? "!NULL" : "NULL");
- printk("GFS: fsid=%s: bd_frozen = %s\n",
- sdp->sd_fsname,
- (bd->bd_frozen) ? "!NULL" : "NULL");
- printk("GFS: fsid=%s: bd_pinned = %u\n",
- sdp->sd_fsname, bd->bd_pinned);
- printk("GFS: fsid=%s: bd_ail_tr_list = %s\n",
- sdp->sd_fsname,
- (list_empty(&bd->bd_ail_tr_list)) ? "Empty" : "!Empty");
-
- if (gl->gl_ops == &gfs_inode_glops) {
- struct gfs_inode *ip = get_gl2ip(gl);
-
- if (ip) {
- unsigned int x;
-
- printk("GFS: fsid=%s: ip = %llu/%llu\n",
- sdp->sd_fsname,
- (unsigned long long)ip->i_num.no_formal_ino,
- (unsigned long long)ip->i_num.no_addr);
- printk("GFS: fsid=%s: ip->i_count = %d, ip->i_vnode = %s\n",
- sdp->sd_fsname,
- atomic_read(&ip->i_count),
- (ip->i_vnode) ? "!NULL" : "NULL");
- for (x = 0; x < GFS_MAX_META_HEIGHT; x++)
- printk("GFS: fsid=%s: ip->i_cache[%u] = %s\n",
- sdp->sd_fsname, x,
- (ip->i_cache[x]) ? "!NULL" : "NULL");
- }
- }
- }
-}
-
-/**
- * gfs_aspace_releasepage - free the metadata associated with a page
- * @page: the page that's being released
- * @gfp_mask: passed from Linux VFS, ignored by us
- *
- * Call try_to_free_buffers() if the buffers in this page can be
- * released.
- *
- * Returns: 0
- */
-
-static int
-gfs_aspace_releasepage(struct page *page, gfp_t gfp_mask)
-{
- struct inode *aspace = page->mapping->host;
- struct gfs_sbd *sdp = get_v2sdp(aspace->i_sb);
- struct buffer_head *bh, *head;
- struct gfs_bufdata *bd;
- unsigned long t;
-
- if (!page_has_buffers(page))
- goto out;
-
- head = bh = page_buffers(page);
- do {
- t = jiffies;
-
- while (atomic_read(&bh->b_count)) {
- if (atomic_read(&aspace->i_writecount)) {
- if (time_after_eq(jiffies,
- t +
- gfs_tune_get(sdp, gt_stall_secs) * HZ)) {
- stuck_releasepage(bh);
- t = jiffies;
- }
-
- yield();
- continue;
- }
-
- return 0;
- }
-
- bd = get_v2bd(bh);
- if (bd) {
- gfs_assert_warn(sdp, bd->bd_bh == bh);
- gfs_assert_warn(sdp, !bd->bd_new_le.le_trans);
- gfs_assert_warn(sdp, !bd->bd_incore_le.le_trans);
- gfs_assert_warn(sdp, !bd->bd_frozen);
- gfs_assert_warn(sdp, !bd->bd_pinned);
- gfs_assert_warn(sdp, list_empty(&bd->bd_ail_tr_list));
- kmem_cache_free(gfs_bufdata_cachep, bd);
- atomic_dec(&sdp->sd_bufdata_count);
- set_v2bd(bh, NULL);
- }
-
- bh = bh->b_this_page;
- }
- while (bh != head);
-
- out:
- return try_to_free_buffers(page);
-}
-
-static struct address_space_operations aspace_aops = {
- .writepage = gfs_aspace_writepage,
- .releasepage = gfs_aspace_releasepage,
-};
-
-/**
- * gfs_aspace_get - Create and initialize a struct inode structure
- * @sdp: the filesystem the aspace is in
- *
- * Right now a struct inode is just a struct inode. Maybe Linux
- * will supply a more lightweight address space construct (that works)
- * in the future.
- *
- * Make sure pages/buffers in this aspace aren't in high memory.
- *
- * Returns: the aspace
- */
-
-struct inode *
-gfs_aspace_get(struct gfs_sbd *sdp)
-{
- struct inode *aspace;
-
- aspace = new_inode(sdp->sd_vfs);
- if (aspace) {
- mapping_set_gfp_mask(aspace->i_mapping, GFP_KERNEL);
- aspace->i_mapping->a_ops = &aspace_aops;
- aspace->i_size = ~0ULL;
- set_v2ip(aspace, NULL);
- insert_inode_hash(aspace);
- }
-
- return aspace;
-}
-
-/**
- * gfs_aspace_put - get rid of an aspace
- * @aspace:
- *
- */
-
-void
-gfs_aspace_put(struct inode *aspace)
-{
- remove_inode_hash(aspace);
- iput(aspace);
-}
-
-/**
- * gfs_ail_start_trans - Start I/O on a part of the AIL
- * @sdp: the filesystem
- * @tr: the part of the AIL
- *
- */
-
-void
-gfs_ail_start_trans(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct list_head *head, *tmp, *prev;
- struct gfs_bufdata *bd;
- struct buffer_head *bh;
- int retry;
-
- do {
- retry = FALSE;
-
- spin_lock(&sdp->sd_ail_lock);
-
- for (head = &tr->tr_ail_bufs, tmp = head->prev, prev = tmp->prev;
- tmp != head;
- tmp = prev, prev = tmp->prev) {
- bd = list_entry(tmp, struct gfs_bufdata, bd_ail_tr_list);
- bh = bd->bd_bh;
-
- if (gfs_trylock_buffer(bh))
- continue;
-
- if (bd->bd_pinned) {
- gfs_unlock_buffer(bh);
- continue;
- }
-
- if (!buffer_busy(bh)) {
- if (!buffer_uptodate(bh))
- gfs_io_error_bh(sdp, bh);
-
- list_del_init(&bd->bd_ail_tr_list);
- list_del(&bd->bd_ail_gl_list);
-
- gfs_unlock_buffer(bh);
- brelse(bh);
- continue;
- }
-
- if (buffer_dirty(bh)) {
- list_move(&bd->bd_ail_tr_list, head);
-
- spin_unlock(&sdp->sd_ail_lock);
- wait_on_buffer(bh);
- ll_rw_block(WRITE, 1, &bh);
- spin_lock(&sdp->sd_ail_lock);
-
- gfs_unlock_buffer(bh);
- retry = TRUE;
- break;
- }
-
- gfs_unlock_buffer(bh);
- }
-
- spin_unlock(&sdp->sd_ail_lock);
- } while (retry);
-}
-
-/**
- * gfs_ail_empty_trans - Check whether or not a trans in the AIL has been synced
- * @sdp: the filesystem
- * @tr: the transaction
- *
- */
-
-int
-gfs_ail_empty_trans(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct list_head *head, *tmp, *prev;
- struct gfs_bufdata *bd;
- struct buffer_head *bh;
- int ret;
-
- spin_lock(&sdp->sd_ail_lock);
-
- for (head = &tr->tr_ail_bufs, tmp = head->prev, prev = tmp->prev;
- tmp != head;
- tmp = prev, prev = tmp->prev) {
- bd = list_entry(tmp, struct gfs_bufdata, bd_ail_tr_list);
- bh = bd->bd_bh;
-
- if (gfs_trylock_buffer(bh))
- continue;
-
- if (bd->bd_pinned || buffer_busy(bh)) {
- gfs_unlock_buffer(bh);
- continue;
- }
-
- if (!buffer_uptodate(bh))
- gfs_io_error_bh(sdp, bh);
-
- list_del_init(&bd->bd_ail_tr_list);
- list_del(&bd->bd_ail_gl_list);
-
- gfs_unlock_buffer(bh);
- brelse(bh);
- }
-
- ret = list_empty(head);
-
- spin_unlock(&sdp->sd_ail_lock);
-
- return ret;
-}
-
-/**
- * ail_empty_gl - remove all buffers for a given lock from the AIL
- * @gl: the glock
- *
- * None of the buffers should be dirty, locked, or pinned.
- */
-
-static void
-ail_empty_gl(struct gfs_glock *gl)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_bufdata *bd;
- struct buffer_head *bh;
-
- spin_lock(&sdp->sd_ail_lock);
-
- while (!list_empty(&gl->gl_ail_bufs)) {
- bd = list_entry(gl->gl_ail_bufs.next,
- struct gfs_bufdata, bd_ail_gl_list);
- bh = bd->bd_bh;
-
- gfs_assert_withdraw(sdp, !bd->bd_pinned && !buffer_busy(bh));
- if (!buffer_uptodate(bh))
- gfs_io_error_bh(sdp, bh);
-
- list_del_init(&bd->bd_ail_tr_list);
- list_del(&bd->bd_ail_gl_list);
-
- brelse(bh);
- }
-
- spin_unlock(&sdp->sd_ail_lock);
-}
-
-/**
- * gfs_inval_buf - Invalidate all buffers associated with a glock
- * @gl: the glock
- *
- */
-
-void
-gfs_inval_buf(struct gfs_glock *gl)
-{
- struct inode *aspace = gl->gl_aspace;
- struct address_space *mapping = gl->gl_aspace->i_mapping;
-
- ail_empty_gl(gl);
-
- atomic_inc(&aspace->i_writecount);
- truncate_inode_pages(mapping, 0);
- atomic_dec(&aspace->i_writecount);
-
- gfs_assert_withdraw(gl->gl_sbd, !mapping->nrpages);
-}
-
-/**
- * gfs_sync_buf - Sync all buffers associated with a glock
- * @gl: The glock
- * @flags: DIO_START | DIO_WAIT | DIO_CHECK
- *
- */
-
-void
-gfs_sync_buf(struct gfs_glock *gl, int flags)
-{
- struct address_space *mapping = gl->gl_aspace->i_mapping;
- int error = 0;
-
- if (flags & DIO_START)
- error = filemap_fdatawrite(mapping);
- if (!error && (flags & DIO_WAIT))
- error = filemap_fdatawait(mapping);
- if (!error && (flags & (DIO_INVISIBLE | DIO_CHECK)) == DIO_CHECK)
- ail_empty_gl(gl);
-
- if (error)
- gfs_io_error(gl->gl_sbd);
-}
-
-/**
- * getbuf - Get a buffer with a given address space
- * @sdp: the filesystem
- * @aspace: the address space
- * @blkno: the block number (filesystem scope)
- * @create: TRUE if the buffer should be created
- *
- * Returns: the buffer
- */
-
-static struct buffer_head *
-getbuf(struct gfs_sbd *sdp, struct inode *aspace, uint64_t blkno, int create)
-{
- struct page *page;
- struct buffer_head *bh;
- unsigned int shift;
- unsigned long index;
- unsigned int bufnum;
-
- shift = PAGE_CACHE_SHIFT - sdp->sd_sb.sb_bsize_shift;
- index = blkno >> shift; /* convert block to page */
- bufnum = blkno - (index << shift); /* block buf index within page */
-
- if (create) {
- RETRY_MALLOC(page = grab_cache_page(aspace->i_mapping, index), page);
- } else {
- page = find_lock_page(aspace->i_mapping, index);
- if (!page)
- return NULL;
- }
-
- if (!page_has_buffers(page))
- create_empty_buffers(page, sdp->sd_sb.sb_bsize, 0);
-
- /* Locate header for our buffer within our page */
- for (bh = page_buffers(page); bufnum--; bh = bh->b_this_page)
- /* Do nothing */;
- get_bh(bh);
-
- if (!buffer_mapped(bh))
- map_bh(bh, sdp->sd_vfs, blkno);
- else if (gfs_assert_warn(sdp, bh->b_bdev == sdp->sd_vfs->s_bdev &&
- bh->b_blocknr == blkno))
- map_bh(bh, sdp->sd_vfs, blkno);
-
- unlock_page(page);
- page_cache_release(page);
-
- return bh;
-}
-
-/**
- * gfs_dgetblk - Get a block
- * @gl: The glock associated with this block
- * @blkno: The block number
- *
- * Returns: The buffer
- */
-
-struct buffer_head *
-gfs_dgetblk(struct gfs_glock *gl, uint64_t blkno)
-{
- return getbuf(gl->gl_sbd, gl->gl_aspace, blkno, CREATE);
-}
-
-/**
- * gfs_dread - Read a block from disk
- * @gl: The glock covering the block
- * @blkno: The block number
- * @flags: flags to gfs_dreread()
- * @bhp: the place where the buffer is returned (NULL on failure)
- *
- * Returns: errno
- */
-
-int
-gfs_dread(struct gfs_glock *gl, uint64_t blkno,
- int flags, struct buffer_head **bhp)
-{
- int error;
-
- *bhp = gfs_dgetblk(gl, blkno);
- error = gfs_dreread(gl->gl_sbd, *bhp, flags);
- if (error)
- brelse(*bhp);
-
- return error;
-}
-
-/**
- * gfs_prep_new_buffer - Mark a new buffer we just gfs_dgetblk()ed uptodate
- * @bh: the buffer
- *
- */
-
-void
-gfs_prep_new_buffer(struct buffer_head *bh)
-{
- wait_on_buffer(bh);
- clear_buffer_dirty(bh);
- set_buffer_uptodate(bh);
-}
-
-/**
- * gfs_dreread - Reread a block from disk
- * @sdp: the filesystem
- * @bh: The block to read
- * @flags: Flags that control the read
- *
- * Returns: errno
- */
-
-int
-gfs_dreread(struct gfs_sbd *sdp, struct buffer_head *bh, int flags)
-{
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- return -EIO;
-
- /* Fill in meta-header if we have a cached copy, else read from disk */
- if (flags & DIO_NEW) {
- if (gfs_mhc_fish(sdp, bh))
- return 0;
- clear_buffer_uptodate(bh);
- }
-
- if (flags & DIO_FORCE)
- clear_buffer_uptodate(bh);
-
- if ((flags & DIO_START) && !buffer_uptodate(bh))
- ll_rw_block(READ, 1, &bh);
-
- if (flags & DIO_WAIT) {
- wait_on_buffer(bh);
-
- if (!buffer_uptodate(bh)) {
- gfs_io_error_bh(sdp, bh);
- return -EIO;
- }
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- return -EIO;
- }
-
- return 0;
-}
-
-/**
- * gfs_dwrite - Write a buffer to disk (and/or wait for write to complete)
- * @sdp: the filesystem
- * @bh: The buffer to write
- * @flags: DIO_XXX The type of write/wait operation to do
- *
- * Returns: errno
- */
-
-int
-gfs_dwrite(struct gfs_sbd *sdp, struct buffer_head *bh, int flags)
-{
- if (gfs_assert_warn(sdp, !test_bit(SDF_ROFS, &sdp->sd_flags)))
- return -EIO;
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- return -EIO;
-
- if (flags & DIO_CLEAN) {
- lock_buffer(bh);
- clear_buffer_dirty(bh);
- unlock_buffer(bh);
- }
-
- if (flags & DIO_DIRTY) {
- if (gfs_assert_warn(sdp, buffer_uptodate(bh)))
- return -EIO;
- mark_buffer_dirty(bh);
- }
-
- if ((flags & DIO_START) && buffer_dirty(bh)) {
- wait_on_buffer(bh);
- ll_rw_block(WRITE, 1, &bh);
- }
-
- if (flags & DIO_WAIT) {
- wait_on_buffer(bh);
-
- if (!buffer_uptodate(bh) || buffer_dirty(bh)) {
- gfs_io_error_bh(sdp, bh);
- return -EIO;
- }
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- return -EIO;
- }
-
- return 0;
-}
-
-/**
- * gfs_attach_bufdata - attach a struct gfs_bufdata structure to a buffer
- * @bh: The buffer to be attached to
- * @gl: the glock the buffer belongs to
- *
- */
-
-void
-gfs_attach_bufdata(struct buffer_head *bh, struct gfs_glock *gl)
-{
- struct gfs_bufdata *bd;
-
- lock_page(bh->b_page);
-
- /* If there's one attached already, we're done */
- if (get_v2bd(bh)) {
- unlock_page(bh->b_page);
- return;
- }
-
- RETRY_MALLOC(bd = kmem_cache_alloc(gfs_bufdata_cachep, GFP_KERNEL), bd);
- atomic_inc(&gl->gl_sbd->sd_bufdata_count);
-
- memset(bd, 0, sizeof(struct gfs_bufdata));
-
- bd->bd_bh = bh;
- bd->bd_gl = gl;
-
- INIT_LE(&bd->bd_new_le, &gfs_buf_lops);
- INIT_LE(&bd->bd_incore_le, &gfs_buf_lops);
-
- init_MUTEX(&bd->bd_lock);
-
- INIT_LIST_HEAD(&bd->bd_ail_tr_list);
-
- set_v2bd(bh, bd);
-
- unlock_page(bh->b_page);
-}
-
-/**
- * gfs_is_pinned - Figure out if a buffer is pinned or not
- * @sdp: the filesystem the buffer belongs to
- * @bh: The buffer to be pinned
- *
- * Returns: TRUE if the buffer is pinned, FALSE otherwise
- */
-
-int
-gfs_is_pinned(struct gfs_sbd *sdp, struct buffer_head *bh)
-{
- struct gfs_bufdata *bd = get_v2bd(bh);
- int ret = FALSE;
-
- if (bd) {
- gfs_lock_buffer(bh);
- if (bd->bd_pinned)
- ret = TRUE;
- gfs_unlock_buffer(bh);
- }
-
- return ret;
-}
-
-/**
- * gfs_dpin - Pin a metadata buffer in memory
- * @sdp: the filesystem the buffer belongs to
- * @bh: The buffer to be pinned
- *
- * "Pinning" means keeping buffer from being written to its in-place location.
- * A buffer should be pinned from the time it is added to a new transaction,
- * until after it has been written to the log.
- * If an earlier change to this buffer is still pinned, waiting to be written
- * to on-disk log, we need to keep a "frozen" copy of the old data while this
- * transaction is modifying the real data. We keep the frozen copy until
- * this transaction's incore_commit(), i.e. until the transaction has
- * finished modifying the real data, at which point we can use the real
- * buffer for logging, even if the frozen copy didn't get written to the log.
- *
- */
-
-void
-gfs_dpin(struct gfs_sbd *sdp, struct buffer_head *bh)
-{
- struct gfs_bufdata *bd = get_v2bd(bh);
- char *data;
-
- gfs_assert_withdraw(sdp, !test_bit(SDF_ROFS, &sdp->sd_flags));
-
- gfs_lock_buffer(bh);
-
- gfs_assert_warn(sdp, !bd->bd_frozen);
-
- if (!bd->bd_pinned++) {
- wait_on_buffer(bh);
-
- /* If this buffer is in the AIL and it has already been written
- to in-place disk block, remove it from the AIL. */
-
- spin_lock(&sdp->sd_ail_lock);
- if (!list_empty(&bd->bd_ail_tr_list) && !buffer_busy(bh)) {
- list_del_init(&bd->bd_ail_tr_list);
- list_del(&bd->bd_ail_gl_list);
- brelse(bh);
- }
- spin_unlock(&sdp->sd_ail_lock);
-
- clear_buffer_dirty(bh);
- wait_on_buffer(bh);
-
- if (!buffer_uptodate(bh))
- gfs_io_error_bh(sdp, bh);
- } else {
- gfs_unlock_buffer(bh);
-
- gfs_assert_withdraw(sdp, buffer_uptodate(bh));
-
- data = gmalloc(sdp->sd_sb.sb_bsize);
-
- gfs_lock_buffer(bh);
-
- /* Create frozen copy, if needed. */
- if (bd->bd_pinned > 1) {
- memcpy(data, bh->b_data, sdp->sd_sb.sb_bsize);
- bd->bd_frozen = data;
- } else
- kfree(data);
- }
-
- gfs_unlock_buffer(bh);
-
- get_bh(bh);
-}
-
-/**
- * gfs_dunpin - Unpin a buffer
- * @sdp: the filesystem the buffer belongs to
- * @bh: The buffer to unpin
- * @tr: The transaction in the AIL that contains this buffer
- * If NULL, don't attach buffer to any AIL list
- * (i.e. when dropping a pin reference when merging a new transaction
- * with an already existing incore transaction)
- *
- * Called for (meta) buffers, after they've been logged to on-disk journal.
- * Make a (meta) buffer writeable to in-place location on-disk, if recursive
- * pin count is 1 (i.e. no other, later transaction is modifying this buffer).
- * Add buffer to AIL lists of 1) the latest transaction that's modified and
- * logged (on-disk) the buffer, and of 2) the glock that protects the buffer.
- * A single buffer might have been modified by more than one transaction
- * since the buffer's previous write to disk (in-place location). We keep
- * the buffer on only one transaction's AIL list, i.e. that of the latest
- * transaction that's completed logging this buffer (no need to write it to
- * in-place block multiple times for multiple transactions, only once with
- * the most up-to-date data).
- * A single buffer will be protected by one and only one glock. If buffer is
- * already on a (previous) transaction's AIL, we know that we're already
- * on buffer's glock's AIL.
- *
- */
-
-void
-gfs_dunpin(struct gfs_sbd *sdp, struct buffer_head *bh, struct gfs_trans *tr)
-{
- struct gfs_bufdata *bd = get_v2bd(bh);
-
- gfs_assert_withdraw(sdp, buffer_uptodate(bh));
-
- gfs_lock_buffer(bh);
-
- if (gfs_assert_warn(sdp, bd->bd_pinned)) {
- gfs_unlock_buffer(bh);
- return;
- }
-
- /* No other (later) transaction is modifying buffer; ready to write */
- if (bd->bd_pinned == 1)
- mark_buffer_dirty(bh);
-
- bd->bd_pinned--;
-
- gfs_unlock_buffer(bh);
-
- if (tr) {
- spin_lock(&sdp->sd_ail_lock);
-
- if (list_empty(&bd->bd_ail_tr_list)) {
- /* Buffer not attached to any earlier transaction. Add
- it to glock's AIL, and this trans' AIL (below). */
- list_add(&bd->bd_ail_gl_list, &bd->bd_gl->gl_ail_bufs);
- } else {
- /* Was part of earlier transaction.
- Move from that trans' AIL to this newer one's AIL.
- Buf is already on glock's AIL. */
- list_del_init(&bd->bd_ail_tr_list);
- brelse(bh);
- }
- list_add(&bd->bd_ail_tr_list, &tr->tr_ail_bufs);
-
- spin_unlock(&sdp->sd_ail_lock);
- } else
- brelse(bh);
-}
-
-/**
- * logbh_end_io - Called by OS at the end of a logbh ("fake" bh) write to log
- * @bh: the buffer
- * @uptodate: whether or not the write succeeded
- *
- * Interrupt context, no ENTER/RETURN
- *
- */
-
-static void
-logbh_end_io(struct buffer_head *bh, int uptodate)
-{
- if (uptodate)
- set_buffer_uptodate(bh);
- else
- clear_buffer_uptodate(bh);
- unlock_buffer(bh);
-}
-
-/**
- * gfs_logbh_init - Initialize a fake buffer head
- * @sdp: the filesystem
- * @bh: the buffer to initialize
- * @blkno: the block address of the buffer
- * @data: the data to be written
- *
- */
-
-void
-gfs_logbh_init(struct gfs_sbd *sdp, struct buffer_head *bh,
- uint64_t blkno, char *data)
-{
- memset(bh, 0, sizeof(struct buffer_head));
- bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate) | (1 << BH_Lock);
- atomic_set(&bh->b_count, 1);
- set_bh_page(bh, virt_to_page(data), ((unsigned long)data) & (PAGE_SIZE - 1));
- bh->b_blocknr = blkno;
- bh->b_size = sdp->sd_sb.sb_bsize;
- bh->b_bdev = sdp->sd_vfs->s_bdev;
- init_buffer(bh, logbh_end_io, NULL);
- INIT_LIST_HEAD(&bh->b_assoc_buffers);
-}
-
-/**
- * gfs_logbh_uninit - Clean up a fake buffer head
- * @sdp: the filesystem
- * @bh: the buffer to clean
- *
- */
-
-void
-gfs_logbh_uninit(struct gfs_sbd *sdp, struct buffer_head *bh)
-{
- gfs_assert_warn(sdp, test_bit(SDF_SHUTDOWN, &sdp->sd_flags) ||
- !buffer_busy(bh));
- gfs_assert_warn(sdp, atomic_read(&bh->b_count) == 1);
-}
-
-/**
- * gfs_logbh_start - Start writing a fake buffer head
- * @sdp: the filesystem
- * @bh: the buffer to write
- *
- * This starts a block write to our journal.
- */
-
-void
-gfs_logbh_start(struct gfs_sbd *sdp, struct buffer_head *bh)
-{
- submit_bh(WRITE, bh);
-}
-
-/**
- * gfs_logbh_wait - Wait for the write of a fake buffer head to complete
- * @sdp: the filesystem
- * @bh: the buffer to write
- *
- * This waits for a block write to our journal to complete.
- *
- * Returns: errno
- */
-
-int
-gfs_logbh_wait(struct gfs_sbd *sdp, struct buffer_head *bh)
-{
- wait_on_buffer(bh);
-
- if (!buffer_uptodate(bh) || buffer_dirty(bh)) {
- gfs_io_error_bh(sdp, bh);
- return -EIO;
- }
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- return -EIO;
-
- return 0;
-}
-
-/**
- * gfs_replay_buf - write a log buffer to its inplace location
- * @gl: the journal's glock
- * @bh: the buffer
- *
- * Returns: errno
- */
-
-int
-gfs_replay_buf(struct gfs_glock *gl, struct buffer_head *bh)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_bufdata *bd;
-
- bd = get_v2bd(bh);
- if (!bd) {
- gfs_attach_bufdata(bh, gl);
- bd = get_v2bd(bh);
- }
-
- mark_buffer_dirty(bh);
-
- if (list_empty(&bd->bd_ail_tr_list)) {
- get_bh(bh);
- list_add(&bd->bd_ail_tr_list, &sdp->sd_recovery_bufs);
- }
-
- return 0;
-}
-
-/**
- * gfs_replay_check - Check up on journal replay
- * @sdp: the filesystem
- *
- */
-
-void
-gfs_replay_check(struct gfs_sbd *sdp)
-{
- struct buffer_head *bh;
- struct gfs_bufdata *bd;
-
- while (!list_empty(&sdp->sd_recovery_bufs)) {
- bd = list_entry(sdp->sd_recovery_bufs.prev,
- struct gfs_bufdata, bd_ail_tr_list);
- bh = bd->bd_bh;
-
- if (buffer_busy(bh)) {
- list_move(&bd->bd_ail_tr_list,
- &sdp->sd_recovery_bufs);
- break;
- } else {
- list_del_init(&bd->bd_ail_tr_list);
- if (!buffer_uptodate(bh))
- gfs_io_error_bh(sdp, bh);
- brelse(bh);
- }
- }
-}
-
-/**
- * gfs_replay_wait - Wait for all replayed buffers to hit the disk
- * @sdp: the filesystem
- *
- */
-
-void
-gfs_replay_wait(struct gfs_sbd *sdp)
-{
- struct list_head *head, *tmp, *prev;
- struct buffer_head *bh;
- struct gfs_bufdata *bd;
-
- for (head = &sdp->sd_recovery_bufs, tmp = head->prev, prev = tmp->prev;
- tmp != head;
- tmp = prev, prev = tmp->prev) {
- bd = list_entry(tmp, struct gfs_bufdata, bd_ail_tr_list);
- bh = bd->bd_bh;
-
- if (!buffer_busy(bh)) {
- list_del_init(&bd->bd_ail_tr_list);
- if (!buffer_uptodate(bh))
- gfs_io_error_bh(sdp, bh);
- brelse(bh);
- continue;
- }
-
- if (buffer_dirty(bh)) {
- wait_on_buffer(bh);
- ll_rw_block(WRITE, 1, &bh);
- }
- }
-
- while (!list_empty(head)) {
- bd = list_entry(head->prev, struct gfs_bufdata, bd_ail_tr_list);
- bh = bd->bd_bh;
-
- wait_on_buffer(bh);
-
- gfs_assert_withdraw(sdp, !buffer_busy(bh));
-
- list_del_init(&bd->bd_ail_tr_list);
- if (!buffer_uptodate(bh))
- gfs_io_error_bh(sdp, bh);
- brelse(bh);
- }
-}
-
-/**
- * gfs_wipe_buffers - make inode's buffers so they aren't dirty/AILed anymore
- * @ip: the inode who owns the buffers
- * @rgd: the resource group
- * @bstart: the first buffer in the run
- * @blen: the number of buffers in the run
- *
- * Called when de-allocating a contiguous run of meta blocks within an rgrp.
- * Make sure all buffers for de-alloc'd blocks are removed from the AIL, if
- * they can be. Dirty or pinned blocks are left alone. Add relevant
- * meta-headers to meta-header cache, so we don't need to read disk
- * if we re-allocate blocks.
- */
-
-void
-gfs_wipe_buffers(struct gfs_inode *ip, struct gfs_rgrpd *rgd,
- uint64_t bstart, uint32_t blen)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct inode *aspace = ip->i_gl->gl_aspace;
- struct buffer_head *bh;
- struct gfs_bufdata *bd;
- int busy;
- int add = FALSE;
-
- while (blen) {
- bh = getbuf(sdp, aspace, bstart, NO_CREATE);
- if (bh) {
-
- bd = get_v2bd(bh);
-
- if (buffer_uptodate(bh)) {
- if (bd) {
- gfs_lock_buffer(bh);
- gfs_mhc_add(rgd, &bh, 1);
- busy = bd->bd_pinned || buffer_busy(bh);
- gfs_unlock_buffer(bh);
-
- if (busy)
- add = TRUE;
- else {
- spin_lock(&sdp->sd_ail_lock);
- if (!list_empty(&bd->bd_ail_tr_list)) {
- list_del_init(&bd->bd_ail_tr_list);
- list_del(&bd->bd_ail_gl_list);
- brelse(bh);
- }
- spin_unlock(&sdp->sd_ail_lock);
- }
- } else {
- gfs_assert_withdraw(sdp, !buffer_dirty(bh));
- wait_on_buffer(bh);
- gfs_assert_withdraw(sdp, !buffer_busy(bh));
- gfs_mhc_add(rgd, &bh, 1);
- }
- } else {
- gfs_assert_withdraw(sdp, !bd || !bd->bd_pinned);
- gfs_assert_withdraw(sdp, !buffer_dirty(bh));
- wait_on_buffer(bh);
- gfs_assert_withdraw(sdp, !buffer_busy(bh));
- }
-
- brelse(bh);
- }
-
- bstart++;
- blen--;
- }
-
- if (add)
- gfs_depend_add(rgd, ip->i_num.no_formal_ino);
-}
-
-/**
- * gfs_sync_meta - sync all the buffers in a filesystem
- * @sdp: the filesystem
- *
- * Flush metadata blocks to on-disk journal, then
- * Flush metadata blocks (now in AIL) to on-disk in-place locations
- * Periodically keep checking until done (AIL empty)
- */
-
-void
-gfs_sync_meta(struct gfs_sbd *sdp)
-{
- gfs_log_flush(sdp);
- for (;;) {
- gfs_ail_start(sdp, DIO_ALL);
- if (gfs_ail_empty(sdp))
- break;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 10);
- }
-}
-
-/**
- * gfs_flush_meta_cache - get rid of any references on buffers for this inode
- * @ip: The GFS inode
- *
- * This releases buffers that are in the most-recently-used array of
- * blocks used for indirect block addressing for this inode.
- * Don't confuse this with the meta-HEADER cache (mhc)!
- */
-
-void
-gfs_flush_meta_cache(struct gfs_inode *ip)
-{
- struct buffer_head **bh_slot;
- unsigned int x;
-
- spin_lock(&ip->i_spin);
-
- for (x = 0; x < GFS_MAX_META_HEIGHT; x++) {
- bh_slot = &ip->i_cache[x];
- if (*bh_slot) {
- brelse(*bh_slot);
- *bh_slot = NULL;
- }
- }
-
- spin_unlock(&ip->i_spin);
-}
-
-/**
- * gfs_get_meta_buffer - Get a metadata buffer
- * @ip: The GFS inode
- * @height: The level of this buf in the metadata (indir addr) tree (if any)
- * @num: The block number (device relative) of the buffer
- * @new: Non-zero if we may create a new buffer
- * @bhp: the buffer is returned here
- *
- * Returns: errno
- */
-
-int
-gfs_get_meta_buffer(struct gfs_inode *ip, int height, uint64_t num, int new,
- struct buffer_head **bhp)
-{
- struct buffer_head *bh, **bh_slot = &ip->i_cache[height];
- int flags = ((new) ? DIO_NEW : 0) | DIO_START | DIO_WAIT;
- int error;
-
- /* Try to use the gfs_inode's MRU metadata tree cache */
- spin_lock(&ip->i_spin);
- bh = *bh_slot;
- if (bh) {
- if (bh->b_blocknr == num)
- get_bh(bh);
- else
- bh = NULL;
- }
- spin_unlock(&ip->i_spin);
-
- if (bh) {
- error = gfs_dreread(ip->i_sbd, bh, flags);
- if (error) {
- brelse(bh);
- return error;
- }
- } else {
- error = gfs_dread(ip->i_gl, num, flags, &bh);
- if (error)
- return error;
-
- spin_lock(&ip->i_spin);
- if (*bh_slot != bh) {
- if (*bh_slot)
- brelse(*bh_slot);
- *bh_slot = bh;
- get_bh(bh);
- }
- spin_unlock(&ip->i_spin);
- }
-
- if (new) {
- if (gfs_assert_warn(ip->i_sbd, height)) {
- brelse(bh);
- return -EIO;
- }
- gfs_trans_add_bh(ip->i_gl, bh);
- gfs_metatype_set(bh, GFS_METATYPE_IN, GFS_FORMAT_IN);
- gfs_buffer_clear_tail(bh, sizeof(struct gfs_meta_header));
- } else if (gfs_metatype_check(ip->i_sbd, bh,
- (height) ? GFS_METATYPE_IN : GFS_METATYPE_DI)) {
- brelse(bh);
- return -EIO;
- }
-
- *bhp = bh;
-
- return 0;
-}
-
-/**
- * gfs_get_data_buffer - Get a data buffer
- * @ip: The GFS inode
- * @num: The block number (device relative) of the data block
- * @new: Non-zero if this is a new allocation
- * @bhp: the buffer is returned here
- *
- * Returns: errno
- */
-
-int
-gfs_get_data_buffer(struct gfs_inode *ip, uint64_t block, int new,
- struct buffer_head **bhp)
-{
- struct buffer_head *bh;
- int error = 0;
-
- if (block == ip->i_num.no_addr) {
- if (gfs_assert_warn(ip->i_sbd, !new))
- return -EIO;
- error = gfs_dread(ip->i_gl, block, DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
- if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_DI)) {
- brelse(bh);
- return -EIO;
- }
- } else if (gfs_is_jdata(ip)) {
- if (new) {
- error = gfs_dread(ip->i_gl, block,
- DIO_NEW | DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
- gfs_trans_add_bh(ip->i_gl, bh);
- gfs_metatype_set(bh, GFS_METATYPE_JD, GFS_FORMAT_JD);
- gfs_buffer_clear_tail(bh, sizeof(struct gfs_meta_header));
- } else {
- error = gfs_dread(ip->i_gl, block,
- DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
- if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_JD)) {
- brelse(bh);
- return -EIO;
- }
- }
- } else {
- if (new) {
- bh = gfs_dgetblk(ip->i_gl, block);
- gfs_prep_new_buffer(bh);
- } else {
- error = gfs_dread(ip->i_gl, block,
- DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
- }
- }
-
- *bhp = bh;
-
- return 0;
-}
-
-/**
- * gfs_start_ra - start readahead on an extent of a file
- * @gl: the glock the blocks belong to
- * @dblock: the starting disk block
- * @extlen: the number of blocks in the extent
- *
- */
-
-void
-gfs_start_ra(struct gfs_glock *gl, uint64_t dblock, uint32_t extlen)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct inode *aspace = gl->gl_aspace;
- struct buffer_head *first_bh, *bh;
- uint32_t max_ra = gfs_tune_get(sdp, gt_max_readahead) >> sdp->sd_sb.sb_bsize_shift;
- int error;
-
- if (!extlen)
- return;
- if (!max_ra)
- return;
- if (extlen > max_ra)
- extlen = max_ra;
-
- first_bh = getbuf(sdp, aspace, dblock, CREATE);
-
- if (buffer_uptodate(first_bh))
- goto out;
- if (!buffer_locked(first_bh)) {
- error = gfs_dreread(sdp, first_bh, DIO_START);
- if (error)
- goto out;
- }
-
- dblock++;
- extlen--;
-
- while (extlen) {
- bh = getbuf(sdp, aspace, dblock, CREATE);
-
- if (!buffer_uptodate(bh) && !buffer_locked(bh)) {
- error = gfs_dreread(sdp, bh, DIO_START);
- brelse(bh);
- if (error)
- goto out;
- } else
- brelse(bh);
-
- dblock++;
- extlen--;
-
- if (buffer_uptodate(first_bh))
- break;
- }
-
- out:
- brelse(first_bh);
-}
diff --git a/gfs-kernel/src/gfs/dio.h b/gfs-kernel/src/gfs/dio.h
deleted file mode 100644
index 279642e..0000000
--- a/gfs-kernel/src/gfs/dio.h
+++ /dev/null
@@ -1,157 +0,0 @@
-#ifndef __DIO_DOT_H__
-#define __DIO_DOT_H__
-
-void gfs_ail_start_trans(struct gfs_sbd *sdp, struct gfs_trans *tr);
-int gfs_ail_empty_trans(struct gfs_sbd *sdp, struct gfs_trans *tr);
-
-/* Asynchronous I/O Routines */
-
-struct buffer_head *gfs_dgetblk(struct gfs_glock *gl, uint64_t blkno);
-int gfs_dread(struct gfs_glock *gl, uint64_t blkno,
- int flags, struct buffer_head **bhp);
-
-void gfs_prep_new_buffer(struct buffer_head *bh);
-int gfs_dreread(struct gfs_sbd *sdp, struct buffer_head *bh, int flags);
-int gfs_dwrite(struct gfs_sbd *sdp, struct buffer_head *bh, int flags);
-
-void gfs_attach_bufdata(struct buffer_head *bh, struct gfs_glock *gl);
-int gfs_is_pinned(struct gfs_sbd *sdp, struct buffer_head *bh);
-void gfs_dpin(struct gfs_sbd *sdp, struct buffer_head *bh);
-void gfs_dunpin(struct gfs_sbd *sdp, struct buffer_head *bh,
- struct gfs_trans *tr);
-
-static __inline__
-void gfs_lock_buffer(struct buffer_head *bh)
-{
- struct gfs_bufdata *bd = get_v2bd(bh);
- down(&bd->bd_lock);
-}
-static __inline__
-int gfs_trylock_buffer(struct buffer_head *bh)
-{
- struct gfs_bufdata *bd = get_v2bd(bh);
- return down_trylock(&bd->bd_lock);
-}
-static __inline__
-void gfs_unlock_buffer(struct buffer_head *bh)
-{
- struct gfs_bufdata *bd = get_v2bd(bh);
- up(&bd->bd_lock);
-}
-
-void gfs_logbh_init(struct gfs_sbd *sdp, struct buffer_head *bh, uint64_t blkno,
- char *data);
-void gfs_logbh_uninit(struct gfs_sbd *sdp, struct buffer_head *bh);
-void gfs_logbh_start(struct gfs_sbd *sdp, struct buffer_head *bh);
-int gfs_logbh_wait(struct gfs_sbd *sdp, struct buffer_head *bh);
-
-int gfs_replay_buf(struct gfs_glock *gl, struct buffer_head *bh);
-void gfs_replay_check(struct gfs_sbd *sdp);
-void gfs_replay_wait(struct gfs_sbd *sdp);
-
-void gfs_wipe_buffers(struct gfs_inode *ip, struct gfs_rgrpd *rgd,
- uint64_t bstart, uint32_t blen);
-
-void gfs_sync_meta(struct gfs_sbd *sdp);
-
-/* Buffer Caching routines */
-
-int gfs_get_meta_buffer(struct gfs_inode *ip, int height, uint64_t num, int new,
- struct buffer_head **bhp);
-int gfs_get_data_buffer(struct gfs_inode *ip, uint64_t block, int new,
- struct buffer_head **bhp);
-void gfs_start_ra(struct gfs_glock *gl, uint64_t dblock, uint32_t extlen);
-
-static __inline__ int
-gfs_get_inode_buffer(struct gfs_inode *ip, struct buffer_head **bhp)
-{
- return gfs_get_meta_buffer(ip, 0, ip->i_num.no_addr, FALSE, bhp);
-}
-
-struct inode *gfs_aspace_get(struct gfs_sbd *sdp);
-void gfs_aspace_put(struct inode *aspace);
-
-void gfs_inval_buf(struct gfs_glock *gl);
-void gfs_sync_buf(struct gfs_glock *gl, int flags);
-
-void gfs_flush_meta_cache(struct gfs_inode *ip);
-
-/* Buffer Content Functions */
-
-/**
- * gfs_buffer_clear - Zeros out a buffer
- * @ip: The GFS inode
- * @bh: The buffer to zero
- *
- */
-
-static __inline__ void
-gfs_buffer_clear(struct buffer_head *bh)
-{
- memset(bh->b_data, 0, bh->b_size);
-}
-
-/**
- * gfs_buffer_clear_tail - Clear buffer beyond the dinode
- * @bh: The buffer containing the on-disk inode
- * @head: the size of the head of the buffer
- *
- * Clears the remaining part of an on-disk inode that is not a dinode.
- * i.e. The data part of a stuffed inode, or the top level of metadata
- * of a non-stuffed inode.
- */
-
-static __inline__ void
-gfs_buffer_clear_tail(struct buffer_head *bh, int head)
-{
- memset(bh->b_data + head, 0, bh->b_size - head);
-}
-
-/**
- * gfs_buffer_clear_ends - Zero out any bits of a buffer which are not being written
- * @bh: The buffer
- * @offset: Offset in buffer where write starts
- * @amount: Amount of data being written
- * @journaled: TRUE if this is a journaled buffer
- *
- */
-
-static __inline__ void
-gfs_buffer_clear_ends(struct buffer_head *bh, int offset, int amount,
- int journaled)
-{
- int z_off1 = (journaled) ? sizeof(struct gfs_meta_header) : 0;
- int z_len1 = offset - z_off1;
- int z_off2 = offset + amount;
- int z_len2 = (bh)->b_size - z_off2;
-
- if (z_len1)
- memset(bh->b_data + z_off1, 0, z_len1);
-
- if (z_len2)
- memset(bh->b_data + z_off2, 0, z_len2);
-}
-
-/**
- * gfs_buffer_copy_tail - copies the tail of one buffer to another
- * @to_bh: the buffer to copy to
- * @to_head: the size of the head of to_bh
- * @from_bh: the buffer to copy from
- * @from_head: the size of the head of from_bh
- *
- * from_head is guaranteed to bigger than to_head
- */
-
-static __inline__ void
-gfs_buffer_copy_tail(struct buffer_head *to_bh, int to_head,
- struct buffer_head *from_bh, int from_head)
-{
- memcpy(to_bh->b_data + to_head,
- from_bh->b_data + from_head,
- from_bh->b_size - from_head);
- memset(to_bh->b_data + to_bh->b_size + to_head - from_head,
- 0,
- from_head - to_head);
-}
-
-#endif /* __DIO_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/dir.c b/gfs-kernel/src/gfs/dir.c
deleted file mode 100644
index 7dadf7f..0000000
--- a/gfs-kernel/src/gfs/dir.c
+++ /dev/null
@@ -1,2394 +0,0 @@
-/*
-* Implements Extendible Hashing as described in:
-* "Extendible Hashing" by Fagin, et al in
-* __ACM Trans. on Database Systems__, Sept 1979.
-*
-*
-* Here's the layout of dirents which is essentially the same as that of ext2
-* within a single block. The field de_name_len is the number of bytes
-* actually required for the name (no null terminator). The field de_rec_len
-* is the number of bytes allocated to the dirent. The offset of the next
-* dirent in the block is (dirent + dirent->de_rec_len). When a dirent is
-* deleted, the preceding dirent inherits its allocated space, ie
-* prev->de_rec_len += deleted->de_rec_len. Since the next dirent is obtained
-* by adding de_rec_len to the current dirent, this essentially causes the
-* deleted dirent to get jumped over when iterating through all the dirents.
-*
-* When deleting the first dirent in a block, there is no previous dirent so
-* the field de_ino is set to zero to designate it as deleted. When allocating
-* a dirent, gfs_dirent_alloc iterates through the dirents in a block. If the
-* first dirent has (de_ino == 0) and de_rec_len is large enough, this first
-* dirent is allocated. Otherwise it must go through all the 'used' dirents
-* searching for one in which the amount of total space minus the amount of
-* used space will provide enough space for the new dirent.
-*
-* There are two types of blocks in which dirents reside. In a stuffed dinode,
-* the dirents begin at offset sizeof(struct gfs_dinode) from the beginning of
-* the block. In leaves, they begin at offset sizeof (struct gfs_leaf) from the
-* beginning of the leaf block. The dirents reside in leaves when
-*
-* dip->i_di.di_flags & GFS_DIF_EXHASH is true
-*
-* Otherwise, the dirents are "linear", within a single stuffed dinode block.
-*
-* When the dirents are in leaves, the actual contents of the directory file are
-* used as an array of 64-bit block pointers pointing to the leaf blocks. The
-* dirents are NOT in the directory file itself. There can be more than one block
-* pointer in the array that points to the same leaf. In fact, when a directory
-* is first converted from linear to exhash, all of the pointers point to the
-* same leaf.
-*
-* When a leaf is completely full, the size of the hash table can be
-* doubled unless it is already at the maximum size which is hard coded into
-* GFS_DIR_MAX_DEPTH. After that, leaves are chained together in a linked list,
-* but never before the maximum hash table size has been reached.
-*/
-
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/vmalloc.h>
-
-#include "gfs.h"
-#include "dio.h"
-#include "dir.h"
-#include "file.h"
-#include "glock.h"
-#include "inode.h"
-#include "quota.h"
-#include "rgrp.h"
-#include "trans.h"
-
-#if 1
-#define gfs_dir_hash2offset(h) (((uint64_t)(h)) >> 1)
-#define gfs_dir_offset2hash(p) ((uint32_t)(((uint64_t)(p)) << 1))
-#else
-#define gfs_dir_hash2offset(h) (((uint64_t)(h)))
-#define gfs_dir_offset2hash(p) ((uint32_t)(((uint64_t)(p))))
-#endif
-
-typedef int (*leaf_call_t) (struct gfs_inode *dip,
- uint32_t index, uint32_t len, uint64_t leaf_no,
- void *data);
-
-/**
- * int gfs_filecmp - Compare two filenames
- * @file1: The first filename
- * @file2: The second filename
- * @len_of_file2: The length of the second file
- *
- * This routine compares two filenames and returns TRUE if they are equal.
- *
- * Returns: TRUE (!=0) if the files are the same, otherwise FALSE (0).
- */
-
-int
-gfs_filecmp(struct qstr *file1, char *file2, int len_of_file2)
-{
- if (file1->len != len_of_file2)
- return FALSE;
- if (memcmp(file1->name, file2, file1->len))
- return FALSE;
- return TRUE;
-}
-
-/**
- * dirent_first - Return the first dirent
- * @dip: the directory
- * @bh: The buffer
- * @dent: Pointer to list of dirents
- *
- * return first dirent whether bh points to leaf or stuffed dinode
- *
- * Returns: IS_LEAF, IS_DINODE, or -errno
- */
-
-static int
-dirent_first(struct gfs_inode *dip, struct buffer_head *bh,
- struct gfs_dirent **dent)
-{
- struct gfs_meta_header *h = (struct gfs_meta_header *)bh->b_data;
-
- if (gfs32_to_cpu(h->mh_type) == GFS_METATYPE_LF) {
- if (gfs_meta_check(dip->i_sbd, bh))
- return -EIO;
- *dent = (struct gfs_dirent *)(bh->b_data + sizeof(struct gfs_leaf));
- return IS_LEAF;
- } else {
- if (gfs_metatype_check(dip->i_sbd, bh, GFS_METATYPE_DI))
- return -EIO;
- *dent = (struct gfs_dirent *)(bh->b_data + sizeof(struct gfs_dinode));
- return IS_DINODE;
- }
-}
-
-/**
- * dirent_next - Next dirent
- * @dip: the directory
- * @bh: The buffer
- * @dent: Pointer to list of dirents
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int
-dirent_next(struct gfs_inode *dip, struct buffer_head *bh,
- struct gfs_dirent **dent)
-{
- struct gfs_dirent *tmp, *cur;
- char *bh_end;
- uint32_t cur_rec_len;
-
- cur = *dent;
- bh_end = bh->b_data + bh->b_size;
- cur_rec_len = gfs16_to_cpu(cur->de_rec_len);
-
- if ((char *)cur + cur_rec_len >= bh_end) {
- if ((char *)cur + cur_rec_len > bh_end) {
- gfs_consist_inode(dip);
- return -EIO;
- }
- return -ENOENT;
- }
-
- tmp = (struct gfs_dirent *)((char *)cur + cur_rec_len);
-
- if ((char *)tmp + gfs16_to_cpu(tmp->de_rec_len) > bh_end) {
- gfs_consist_inode(dip);
- return -EIO;
- }
- /* Only the first dent could ever have de_ino == 0 */
- if (!tmp->de_inum.no_formal_ino) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- *dent = tmp;
-
- return 0;
-}
-
-/**
- * dirent_del - Delete a dirent
- * @dip: The GFS inode
- * @bh: The buffer
- * @prev: The previous dirent
- * @cur: The current dirent
- *
- */
-
-static void
-dirent_del(struct gfs_inode *dip, struct buffer_head *bh,
- struct gfs_dirent *prev, struct gfs_dirent *cur)
-{
- uint32_t cur_rec_len, prev_rec_len;
-
- if (!cur->de_inum.no_formal_ino) {
- gfs_consist_inode(dip);
- return;
- }
-
- gfs_trans_add_bh(dip->i_gl, bh);
-
- /* If there is no prev entry, this is the first entry in the block.
- The de_rec_len is already as big as it needs to be. Just zero
- out the inode number and return. */
-
- if (!prev) {
- cur->de_inum.no_formal_ino = 0; /* No endianess worries */
- return;
- }
-
- /* Combine this dentry with the previous one. */
-
- prev_rec_len = gfs16_to_cpu(prev->de_rec_len);
- cur_rec_len = gfs16_to_cpu(cur->de_rec_len);
-
- if ((char *)prev + prev_rec_len != (char *)cur)
- gfs_consist_inode(dip);
- if ((char *)cur + cur_rec_len > bh->b_data + bh->b_size)
- gfs_consist_inode(dip);
-
- prev_rec_len += cur_rec_len;
- prev->de_rec_len = cpu_to_gfs16(prev_rec_len);
-}
-
-/**
- * gfs_dirent_alloc - Allocate a directory entry
- * @dip: The GFS inode
- * @bh: The buffer
- * @name_len: The length of the name
- * @dent_out: Pointer to list of dirents
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int
-gfs_dirent_alloc(struct gfs_inode *dip, struct buffer_head *bh, int name_len,
- struct gfs_dirent **dent_out)
-{
- struct gfs_dirent *dent, *new;
- unsigned int rec_len = GFS_DIRENT_SIZE(name_len);
- unsigned int entries = 0, offset = 0;
- int type;
-
- type = dirent_first(dip, bh, &dent);
- if (type < 0)
- return type;
-
- if (type == IS_LEAF) {
- struct gfs_leaf *leaf = (struct gfs_leaf *)bh->b_data;
- entries = gfs16_to_cpu(leaf->lf_entries);
- offset = sizeof(struct gfs_leaf);
- } else {
- struct gfs_dinode *dinode = (struct gfs_dinode *)bh->b_data;
- entries = gfs32_to_cpu(dinode->di_entries);
- offset = sizeof(struct gfs_dinode);
- }
-
- if (!entries) {
- if (dent->de_inum.no_formal_ino) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- gfs_trans_add_bh(dip->i_gl, bh);
-
- dent->de_rec_len = bh->b_size - offset;
- dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len);
- dent->de_name_len = cpu_to_gfs16(name_len);
-
- *dent_out = dent;
- return 0;
- }
-
- do {
- uint32_t cur_rec_len, cur_name_len;
-
- cur_rec_len = gfs16_to_cpu(dent->de_rec_len);
- cur_name_len = gfs16_to_cpu(dent->de_name_len);
-
- if ((!dent->de_inum.no_formal_ino && cur_rec_len >= rec_len) ||
- (cur_rec_len >= GFS_DIRENT_SIZE(cur_name_len) + rec_len)) {
- gfs_trans_add_bh(dip->i_gl, bh);
-
- if (dent->de_inum.no_formal_ino) {
- new = (struct gfs_dirent *)((char *)dent +
- GFS_DIRENT_SIZE(cur_name_len));
- memset(new, 0, sizeof(struct gfs_dirent));
-
- new->de_rec_len = cpu_to_gfs16(cur_rec_len -
- GFS_DIRENT_SIZE(cur_name_len));
- new->de_name_len = cpu_to_gfs16(name_len);
-
- dent->de_rec_len = cur_rec_len - gfs16_to_cpu(new->de_rec_len);
- dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len);
-
- *dent_out = new;
- return 0;
- }
-
- dent->de_name_len = cpu_to_gfs16(name_len);
-
- *dent_out = dent;
- return 0;
- }
- } while (dirent_next(dip, bh, &dent) == 0);
-
- return -ENOSPC;
-}
-
-/**
- * dirent_fits - See if we can fit a entry in this buffer
- * @dip: The GFS inode
- * @bh: The buffer
- * @name_len: The length of the name
- *
- * Returns: TRUE if it can fit, FALSE otherwise
- */
-
-static int
-dirent_fits(struct gfs_inode *dip, struct buffer_head *bh, int name_len)
-{
- struct gfs_dirent *dent;
- unsigned int rec_len = GFS_DIRENT_SIZE(name_len);
- unsigned int entries = 0;
- int type;
-
- type = dirent_first(dip, bh, &dent);
- if (type < 0)
- return type;
-
- if (type == IS_LEAF) {
- struct gfs_leaf *leaf = (struct gfs_leaf *)bh->b_data;
- entries = gfs16_to_cpu(leaf->lf_entries);
- } else {
- struct gfs_dinode *dinode = (struct gfs_dinode *)bh->b_data;
- entries = gfs32_to_cpu(dinode->di_entries);
- }
-
- if (!entries)
- return TRUE;
-
- do {
- uint32_t cur_rec_len, cur_name_len;
-
- cur_rec_len = gfs16_to_cpu(dent->de_rec_len);
- cur_name_len = gfs16_to_cpu(dent->de_name_len);
-
- if ((!dent->de_inum.no_formal_ino && cur_rec_len >= rec_len) ||
- (cur_rec_len >= GFS_DIRENT_SIZE(cur_name_len) + rec_len))
- return TRUE;
- } while (dirent_next(dip, bh, &dent) == 0);
-
- return FALSE;
-}
-
-/**
- * leaf_search
- * @bh:
- * @filename:
- * @dent_out:
- * @dent_prev:
- *
- * Returns:
- */
-
-static int
-leaf_search(struct gfs_inode *dip,
- struct buffer_head *bh, struct qstr *filename,
- struct gfs_dirent **dent_out, struct gfs_dirent **dent_prev)
-{
- uint32_t hash;
- struct gfs_dirent *dent, *prev = NULL;
- unsigned int entries = 0;
- int type;
-
- type = dirent_first(dip, bh, &dent);
- if (type < 0)
- return type;
-
- if (type == IS_LEAF) {
- struct gfs_leaf *leaf = (struct gfs_leaf *)bh->b_data;
- entries = gfs16_to_cpu(leaf->lf_entries);
- } else if (type == IS_DINODE) {
- struct gfs_dinode *dinode = (struct gfs_dinode *)bh->b_data;
- entries = gfs32_to_cpu(dinode->di_entries);
- }
-
- hash = gfs_dir_hash(filename->name, filename->len);
-
- do {
- if (!dent->de_inum.no_formal_ino) {
- prev = dent;
- continue;
- }
-
- if (gfs32_to_cpu(dent->de_hash) == hash &&
- gfs_filecmp(filename, (char *)(dent + 1),
- gfs16_to_cpu(dent->de_name_len))) {
- *dent_out = dent;
- if (dent_prev)
- *dent_prev = prev;
-
- return 0;
- }
-
- prev = dent;
- } while (dirent_next(dip, bh, &dent) == 0);
-
- return -ENOENT;
-}
-
-/**
- * get_leaf - Get leaf
- * @dip:
- * @leaf_no:
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int
-get_leaf(struct gfs_inode *dip, uint64_t leaf_no, struct buffer_head **bhp)
-{
- int error;
-
- error = gfs_dread(dip->i_gl, leaf_no, DIO_START | DIO_WAIT, bhp);
- if (!error && gfs_metatype_check(dip->i_sbd, *bhp, GFS_METATYPE_LF))
- error = -EIO;
-
- return error;
-}
-
-/**
- * get_leaf_nr - Get a leaf number associated with the index
- * @dip: The GFS inode
- * @index:
- * @leaf_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int
-get_leaf_nr(struct gfs_inode *dip, uint32_t index, uint64_t *leaf_out)
-{
- uint64_t leaf_no;
- int error;
-
- error = gfs_internal_read(dip, (char *)&leaf_no,
- index * sizeof(uint64_t),
- sizeof(uint64_t));
- if (error != sizeof(uint64_t))
- return (error < 0) ? error : -EIO;
-
- *leaf_out = gfs64_to_cpu(leaf_no);
-
- return 0;
-}
-
-/**
- * get_first_leaf - Get first leaf
- * @dip: The GFS inode
- * @index:
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int
-get_first_leaf(struct gfs_inode *dip, uint32_t index,
- struct buffer_head **bh_out)
-{
- uint64_t leaf_no;
- int error;
-
- error = get_leaf_nr(dip, index, &leaf_no);
- if (!error)
- error = get_leaf(dip, leaf_no, bh_out);
-
- return error;
-}
-
-/**
- * get_next_leaf - Get next leaf
- * @dip: The GFS inode
- * @bh_in: The buffer
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int
-get_next_leaf(struct gfs_inode *dip, struct buffer_head *bh_in,
- struct buffer_head **bh_out)
-{
- struct gfs_leaf *leaf;
- int error;
-
- leaf = (struct gfs_leaf *)bh_in->b_data;
-
- if (!leaf->lf_next)
- error = -ENOENT;
- else
- error = get_leaf(dip, gfs64_to_cpu(leaf->lf_next), bh_out);
-
- return error;
-}
-
-/**
- * linked_leaf_search - Linked leaf search
- * @dip: The GFS inode
- * @filename: The filename to search for
- * @dent_out:
- * @dent_prev:
- * @bh_out:
- *
- * Returns: 0 on sucess, error code otherwise
- */
-
-static int
-linked_leaf_search(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_dirent **dent_out, struct gfs_dirent **dent_prev,
- struct buffer_head **bh_out)
-{
- struct buffer_head *bh = NULL, *bh_next;
- uint32_t hsize, index;
- uint32_t hash;
- int error;
-
- hsize = 1 << dip->i_di.di_depth;
- if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- /* Figure out the address of the leaf node. */
-
- hash = gfs_dir_hash(filename->name, filename->len);
- index = hash >> (32 - dip->i_di.di_depth);
-
- error = get_first_leaf(dip, index, &bh_next);
- if (error)
- return error;
-
- /* Find the entry */
-
- do {
- if (bh)
- brelse(bh);
-
- bh = bh_next;
-
- error = leaf_search(dip, bh, filename, dent_out, dent_prev);
- switch (error) {
- case 0:
- *bh_out = bh;
- return 0;
-
- case -ENOENT:
- break;
-
- default:
- brelse(bh);
- return error;
- }
-
- error = get_next_leaf(dip, bh, &bh_next);
- }
- while (!error);
-
- brelse(bh);
-
- return error;
-}
-
-/**
- * dir_make_exhash - Convert a stuffed directory into an ExHash directory
- * @dip: The GFS inode
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int
-dir_make_exhash(struct gfs_inode *dip)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_dirent *dent;
- struct buffer_head *bh, *dibh;
- struct gfs_leaf *leaf;
- int y;
- uint32_t x;
- uint64_t *lp, bn;
- int error;
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- /* Allocate a new block for the first leaf node */
-
- error = gfs_metaalloc(dip, &bn);
- if (error)
- goto fail;
-
- /* Turn over a new leaf */
-
- error = gfs_dread(dip->i_gl, bn, DIO_NEW | DIO_START | DIO_WAIT, &bh);
- if (error)
- goto fail;
-
- gfs_trans_add_bh(dip->i_gl, bh);
- gfs_metatype_set(bh, GFS_METATYPE_LF, GFS_FORMAT_LF);
- gfs_buffer_clear_tail(bh, sizeof(struct gfs_meta_header));
-
- /* Fill in the leaf structure */
-
- leaf = (struct gfs_leaf *)bh->b_data;
-
- gfs_assert(sdp, dip->i_di.di_entries < (1 << 16),);
-
- leaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE);
- leaf->lf_entries = cpu_to_gfs16(dip->i_di.di_entries);
-
- /* Copy dirents */
-
- gfs_buffer_copy_tail(bh, sizeof(struct gfs_leaf), dibh,
- sizeof(struct gfs_dinode));
-
- /* Find last entry */
-
- x = 0;
- dirent_first(dip, bh, &dent);
-
- do {
- if (!dent->de_inum.no_formal_ino)
- continue;
- if (++x == dip->i_di.di_entries)
- break;
- }
- while (dirent_next(dip, bh, &dent) == 0);
-
- /* Adjust the last dirent's record length
- (Remember that dent still points to the last entry.) */
-
- dent->de_rec_len = gfs16_to_cpu(dent->de_rec_len) +
- sizeof(struct gfs_dinode) -
- sizeof(struct gfs_leaf);
- dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len);
-
- brelse(bh);
-
- /* We're done with the new leaf block, now setup the new
- hash table. */
-
- gfs_trans_add_bh(dip->i_gl, dibh);
- gfs_buffer_clear_tail(dibh, sizeof (struct gfs_dinode));
-
- lp = (uint64_t *)(dibh->b_data + sizeof(struct gfs_dinode));
-
- for (x = sdp->sd_hash_ptrs; x--; lp++)
- *lp = cpu_to_gfs64(bn);
-
- dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2;
- dip->i_di.di_blocks++;
- dip->i_di.di_flags |= GFS_DIF_EXHASH;
- dip->i_di.di_payload_format = 0;
-
- for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ;
- dip->i_di.di_depth = y;
-
- gfs_dinode_out(&dip->i_di, dibh->b_data);
-
- brelse(dibh);
-
- return 0;
-
- fail:
- brelse(dibh);
- return error;
-}
-
-/**
- * dir_split_leaf - Split a leaf block into two
- * @dip: The GFS inode
- * @index:
- * @leaf_no:
- *
- * Returns: 0 on success, error code on failure
- */
-
-static int
-dir_split_leaf(struct gfs_inode *dip, uint32_t index, uint64_t leaf_no)
-{
- struct buffer_head *nbh, *obh, *dibh;
- struct gfs_leaf *nleaf, *oleaf;
- struct gfs_dirent *dent, *prev = NULL, *next = NULL, *new;
- uint32_t start, len, half_len, divider;
- uint64_t bn, *lp;
- uint32_t name_len;
- int x, moved = FALSE;
- int error, lp_vfree=0;
-
- /* Allocate the new leaf block */
-
- error = gfs_metaalloc(dip, &bn);
- if (error)
- return error;
-
- /* Get the new leaf block */
-
- error = gfs_dread(dip->i_gl, bn,
- DIO_NEW | DIO_START | DIO_WAIT, &nbh);
- if (error)
- return error;
-
- gfs_trans_add_bh(dip->i_gl, nbh);
- gfs_metatype_set(nbh, GFS_METATYPE_LF, GFS_FORMAT_LF);
- gfs_buffer_clear_tail(nbh, sizeof (struct gfs_meta_header));
-
- nleaf = (struct gfs_leaf *)nbh->b_data;
-
- nleaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE);
-
- /* Get the old leaf block */
-
- error = get_leaf(dip, leaf_no, &obh);
- if (error)
- goto fail;
-
- gfs_trans_add_bh(dip->i_gl, obh);
-
- oleaf = (struct gfs_leaf *)obh->b_data;
-
- /* Compute the start and len of leaf pointers in the hash table. */
-
- len = 1 << (dip->i_di.di_depth - gfs16_to_cpu(oleaf->lf_depth));
- half_len = len >> 1;
- if (!half_len) {
- gfs_consist_inode(dip);
- error = -EIO;
- goto fail_brelse;
- }
-
- start = (index & ~(len - 1));
-
- /* Change the pointers.
- Don't bother distinguishing stuffed from non-stuffed.
- This code is complicated enough already. */
-
- lp = kmalloc(half_len * sizeof (uint64_t), GFP_KERNEL);
- if (unlikely(!lp)) {
- lp = vmalloc(half_len * sizeof (uint64_t));
- if (!lp) {
- printk("GFS: dir_split_leaf vmalloc fail - half_len=%d\n", half_len);
- error = -ENOMEM;
- goto fail_brelse;
- } else
- lp_vfree = 1;
- }
-
- error = gfs_internal_read(dip, (char *)lp, start * sizeof(uint64_t),
- half_len * sizeof(uint64_t));
- if (error != half_len * sizeof(uint64_t)) {
- if (error >= 0)
- error = -EIO;
- goto fail_lpfree;
- }
-
- /* Change the pointers */
-
- for (x = 0; x < half_len; x++)
- lp[x] = cpu_to_gfs64(bn);
-
- error = gfs_internal_write(dip, (char *)lp, start * sizeof(uint64_t),
- half_len * sizeof(uint64_t));
- if (error != half_len * sizeof(uint64_t)) {
- if (error >= 0)
- error = -EIO;
- goto fail_lpfree;
- }
-
- if (unlikely(lp_vfree))
- vfree(lp);
- else
- kfree(lp);
-
- /* Compute the divider */
-
- divider = (start + half_len) << (32 - dip->i_di.di_depth);
-
- /* Copy the entries */
-
- dirent_first(dip, obh, &dent);
-
- do {
- next = dent;
- if (dirent_next(dip, obh, &next))
- next = NULL;
-
- if (dent->de_inum.no_formal_ino &&
- gfs32_to_cpu(dent->de_hash) < divider) {
- name_len = gfs16_to_cpu(dent->de_name_len);
-
- gfs_dirent_alloc(dip, nbh, name_len, &new);
-
- new->de_inum = dent->de_inum; /* No endianness worries */
- new->de_hash = dent->de_hash; /* No endianness worries */
- new->de_type = dent->de_type; /* No endianness worries */
- memcpy((char *)(new + 1), (char *)(dent + 1),
- name_len);
-
- nleaf->lf_entries = gfs16_to_cpu(nleaf->lf_entries) + 1;
- nleaf->lf_entries = cpu_to_gfs16(nleaf->lf_entries);
-
- dirent_del(dip, obh, prev, dent);
-
- if (!oleaf->lf_entries)
- gfs_consist_inode(dip);
- oleaf->lf_entries = gfs16_to_cpu(oleaf->lf_entries) - 1;
- oleaf->lf_entries = cpu_to_gfs16(oleaf->lf_entries);
-
- if (!prev)
- prev = dent;
-
- moved = TRUE;
- } else
- prev = dent;
-
- dent = next;
- }
- while (dent);
-
- /* If none of the entries got moved into the new leaf,
- artificially fill in the first entry. */
-
- if (!moved) {
- gfs_dirent_alloc(dip, nbh, 0, &new);
- new->de_inum.no_formal_ino = 0;
- }
-
- oleaf->lf_depth = gfs16_to_cpu(oleaf->lf_depth) + 1;
- oleaf->lf_depth = cpu_to_gfs16(oleaf->lf_depth);
- nleaf->lf_depth = oleaf->lf_depth;
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (!gfs_assert_withdraw(dip->i_sbd, !error)) {
- dip->i_di.di_blocks++;
- gfs_dinode_out(&dip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- brelse(obh);
- brelse(nbh);
-
- return error;
-
- fail_lpfree:
- if (unlikely(lp_vfree))
- vfree(lp);
- else
- kfree(lp);
-
- fail_brelse:
- brelse(obh);
-
- fail:
- brelse(nbh);
- return error;
-}
-
-/**
- * dir_double_exhash - Double size of ExHash table
- * @dip: The GFS dinode
- *
- * Returns: 0 on success, error code on failure
- */
-
-static int
-dir_double_exhash(struct gfs_inode *dip)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct buffer_head *dibh;
- uint32_t hsize;
- uint64_t *buf;
- uint64_t *from, *to;
- uint64_t block;
- int x;
- int error = 0;
-
- hsize = 1 << dip->i_di.di_depth;
- if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- /* Allocate both the "from" and "to" buffers in one big chunk */
-
- buf = gmalloc(3 * sdp->sd_hash_bsize);
-
- for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) {
- error = gfs_internal_read(dip, (char *)buf,
- block * sdp->sd_hash_bsize,
- sdp->sd_hash_bsize);
- if (error != sdp->sd_hash_bsize) {
- if (error >= 0)
- error = -EIO;
- goto fail;
- }
-
- from = buf;
- to = (uint64_t *)((char *)buf + sdp->sd_hash_bsize);
-
- for (x = sdp->sd_hash_ptrs; x--; from++) {
- *to++ = *from; /* No endianess worries */
- *to++ = *from;
- }
-
- error = gfs_internal_write(dip, (char *)buf + sdp->sd_hash_bsize,
- block * sdp->sd_sb.sb_bsize,
- sdp->sd_sb.sb_bsize);
- if (error != sdp->sd_sb.sb_bsize) {
- if (error >= 0)
- error = -EIO;
- goto fail;
- }
- }
-
- kfree(buf);
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (!gfs_assert_withdraw(sdp, !error)) {
- dip->i_di.di_depth++;
- gfs_dinode_out(&dip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- return error;
-
- fail:
- kfree(buf);
-
- return error;
-}
-
-/**
- * compare_dents - compare directory entries by hash value
- * @a: first dent
- * @b: second dent
- *
- * When comparing the hash entries of @a to @b:
- * gt: returns 1
- * lt: returns -1
- * eq: returns 0
- */
-
-static int
-compare_dents(const void *a, const void *b)
-{
- struct gfs_dirent *dent_a, *dent_b;
- uint32_t hash_a, hash_b;
- int ret = 0;
-
- dent_a = *(struct gfs_dirent **)a;
- hash_a = dent_a->de_hash;
- hash_a = gfs32_to_cpu(hash_a);
-
- dent_b = *(struct gfs_dirent **)b;
- hash_b = dent_b->de_hash;
- hash_b = gfs32_to_cpu(hash_b);
-
- if (hash_a > hash_b)
- ret = 1;
- else if (hash_a < hash_b)
- ret = -1;
- else {
- unsigned int len_a = gfs16_to_cpu(dent_a->de_name_len);
- unsigned int len_b = gfs16_to_cpu(dent_b->de_name_len);
-
- if (len_a > len_b)
- ret = 1;
- else if (len_a < len_b)
- ret = -1;
- else
- ret = memcmp((char *)(dent_a + 1),
- (char *)(dent_b + 1),
- len_a);
- }
-
- return ret;
-}
-
-/**
- * do_filldir_main - read out directory entries
- * @dip: The GFS inode
- * @offset: The offset in the file to read from
- * @opaque: opaque data to pass to filldir
- * @filldir: The function to pass entries to
- * @darr: an array of struct gfs_dirent pointers to read
- * @entries: the number of entries in darr
- * @copied: pointer to int that's non-zero if a entry has been copied out
- *
- * Jump through some hoops to make sure that if there are hash collsions,
- * they are read out at the beginning of a buffer. We want to minimize
- * the possibility that they will fall into different readdir buffers or
- * that someone will want to seek to that location.
- *
- * Returns: errno, >0 on exception from filldir
- */
-
-static int
-do_filldir_main(struct gfs_inode *dip, uint64_t *offset,
- void *opaque, gfs_filldir_t filldir,
- struct gfs_dirent **darr, uint32_t entries, int *copied)
-{
- struct gfs_dirent *dent, *dent_next;
- struct gfs_inum inum;
- uint64_t off, off_next;
- unsigned int x, y;
- int run = FALSE;
- int error = 0;
-
- gfs_sort(darr, entries, sizeof(struct gfs_dirent *), compare_dents);
-
- dent_next = darr[0];
- off_next = gfs32_to_cpu(dent_next->de_hash);
- off_next = gfs_dir_hash2offset(off_next);
-
- for (x = 0, y = 1; x < entries; x++, y++) {
- dent = dent_next;
- off = off_next;
-
- if (y < entries) {
- dent_next = darr[y];
- off_next = gfs32_to_cpu(dent_next->de_hash);
- off_next = gfs_dir_hash2offset(off_next);
-
- if (off < *offset)
- continue;
- *offset = off;
-
- if (off_next == off) {
- if (*copied && !run)
- return 1;
- run = TRUE;
- } else
- run = FALSE;
- } else {
- if (off < *offset)
- continue;
- *offset = off;
- }
-
- gfs_inum_in(&inum, (char *)&dent->de_inum);
-
- error = filldir(opaque, (char *)(dent + 1),
- gfs16_to_cpu(dent->de_name_len),
- off, &inum,
- gfs16_to_cpu(dent->de_type));
- if (error)
- return 1;
-
- *copied = TRUE;
- }
-
- /* Increment the *offset by one, so the next time we come into the do_filldir fxn,
- we get the next entry instead of the last one in the current leaf */
-
- (*offset)++;
-
- return 0;
-}
-
-/**
- * do_filldir_single - Read directory entries out of a single block
- * @dip: The GFS inode
- * @offset: The offset in the file to read from
- * @opaque: opaque data to pass to filldir
- * @filldir: The function to pass entries to
- * @bh: the block
- * @entries: the number of entries in the block
- * @copied: pointer to int that's non-zero if a entry has been copied out
- *
- * Returns: errno, >0 on exception from filldir
- */
-
-static int
-do_filldir_single(struct gfs_inode *dip, uint64_t *offset,
- void *opaque, gfs_filldir_t filldir,
- struct buffer_head *bh, uint32_t entries, int *copied)
-{
- struct gfs_dirent **darr;
- struct gfs_dirent *de;
- unsigned int e = 0;
- int error, do_vfree=0;
-
- if (!entries)
- return 0;
-
- darr = kmalloc(entries * sizeof(struct gfs_dirent *), GFP_KERNEL);
- if (unlikely(!darr)) {
- darr = vmalloc(entries * sizeof (struct gfs_dirent *));
- if (!darr) {
- printk("GFS: do_filldir_single vmalloc fails, entries=%d\n", entries);
- return -ENOMEM;
- }
- else
- do_vfree = 1;
- }
-
- dirent_first(dip, bh, &de);
- do {
- if (!de->de_inum.no_formal_ino)
- continue;
- if (e >= entries) {
- gfs_consist_inode(dip);
- error = -EIO;
- goto out;
- }
- darr[e++] = de;
- }
- while (dirent_next(dip, bh, &de) == 0);
-
- if (e != entries) {
- gfs_consist_inode(dip);
- error = -EIO;
- goto out;
- }
-
- error = do_filldir_main(dip, offset, opaque, filldir, darr,
- entries, copied);
-
- out:
- if (unlikely(do_vfree))
- vfree(darr);
- else
- kfree(darr);
-
- return error;
-}
-
-/**
- * do_filldir_multi - Read directory entries out of a linked leaf list
- * @dip: The GFS inode
- * @offset: The offset in the file to read from
- * @opaque: opaque data to pass to filldir
- * @filldir: The function to pass entries to
- * @bh: the first leaf in the list
- * @copied: pointer to int that's non-zero if a entry has been copied out
- *
- * Returns: errno, >0 on exception from filldir
- */
-
-static int
-do_filldir_multi(struct gfs_inode *dip, uint64_t *offset,
- void *opaque, gfs_filldir_t filldir,
- struct buffer_head *bh, int *copied)
-{
- struct buffer_head **larr = NULL;
- struct gfs_dirent **darr;
- struct gfs_leaf *leaf;
- struct buffer_head *tmp_bh;
- struct gfs_dirent *de;
- unsigned int entries, e = 0;
- unsigned int leaves = 0, l = 0;
- unsigned int x;
- uint64_t ln;
- int error = 0, leaves_vfree=0, entries_vfree=0;
-
- /* Count leaves and entries */
-
- leaf = (struct gfs_leaf *)bh->b_data;
- entries = gfs16_to_cpu(leaf->lf_entries);
- ln = leaf->lf_next;
-
- while (ln) {
- ln = gfs64_to_cpu(ln);
-
- error = get_leaf(dip, ln, &tmp_bh);
- if (error)
- return error;
-
- leaf = (struct gfs_leaf *)tmp_bh->b_data;
- if (leaf->lf_entries) {
- entries += gfs16_to_cpu(leaf->lf_entries);
- leaves++;
- }
- ln = leaf->lf_next;
-
- brelse(tmp_bh);
- }
-
- /* Bail out if there's nothing to do */
-
- if (!entries)
- return 0;
-
- /* Alloc arrays */
-
- if (leaves) {
- larr = kmalloc(leaves * sizeof(struct buffer_head *), GFP_KERNEL);
- if (unlikely(!larr)) {
- larr = vmalloc(leaves * sizeof (struct buffer_head *));
- if (!larr) {
- printk("GFS: do_filldir_multi vmalloc fails leaves=%d\n", leaves);
- return -ENOMEM;
- } else
- leaves_vfree = 1;
- }
- }
-
- darr = kmalloc(entries * sizeof(struct gfs_dirent *), GFP_KERNEL);
- if (unlikely(!darr)) {
- darr = vmalloc(entries * sizeof (struct gfs_dirent *));
- if (!darr) {
- printk("GFS: do_filldir_multi vmalloc fails entries=%d\n", entries);
- if (larr) {
- if (leaves_vfree)
- vfree(larr);
- else
- kfree(larr);
- }
- return -ENOMEM;
- } else
- entries_vfree = 1;
- }
- if (!darr) {
- if (larr)
- kfree(larr);
- return -ENOMEM;
- }
-
- /* Fill in arrays */
-
- leaf = (struct gfs_leaf *)bh->b_data;
- if (leaf->lf_entries) {
- dirent_first(dip, bh, &de);
- do {
- if (!de->de_inum.no_formal_ino)
- continue;
- if (e >= entries) {
- gfs_consist_inode(dip);
- error = -EIO;
- goto out;
- }
- darr[e++] = de;
- }
- while (dirent_next(dip, bh, &de) == 0);
- }
- ln = leaf->lf_next;
-
- while (ln) {
- ln = gfs64_to_cpu(ln);
-
- error = get_leaf(dip, ln, &tmp_bh);
- if (error)
- goto out;
-
- leaf = (struct gfs_leaf *)tmp_bh->b_data;
- if (leaf->lf_entries) {
- dirent_first(dip, tmp_bh, &de);
- do {
- if (!de->de_inum.no_formal_ino)
- continue;
- if (e >= entries) {
- gfs_consist_inode(dip);
- error = -EIO;
- goto out;
- }
- darr[e++] = de;
- }
- while (dirent_next(dip, tmp_bh, &de) == 0);
-
- larr[l++] = tmp_bh;
-
- ln = leaf->lf_next;
- } else {
- ln = leaf->lf_next;
- brelse(tmp_bh);
- }
- }
-
- if (gfs_assert_withdraw(dip->i_sbd, l == leaves)) {
- error = -EIO;
- goto out;
- }
- if (e != entries) {
- gfs_consist_inode(dip);
- error = -EIO;
- goto out;
- }
-
- /* Do work */
-
- error = do_filldir_main(dip, offset, opaque, filldir, darr,
- entries, copied);
-
- /* Clean up */
-
- out:
- if (unlikely(entries_vfree))
- vfree(darr);
- else
- kfree(darr);
-
- for (x = 0; x < l; x++)
- brelse(larr[x]);
-
- if (leaves) {
- if (unlikely(leaves_vfree))
- vfree(larr);
- else
- kfree(larr);
- }
-
- return error;
-}
-
-/**
- * dir_e_search - Search exhash (leaf) dir for inode matching name
- * @dip: The GFS inode
- * @filename: Filename string
- * @inode: If non-NULL, function fills with formal inode # and block address
- * @type: If non-NULL, function fills with GFS_FILE_... dinode type
- *
- * Returns:
- */
-
-static int
-dir_e_search(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *inum, unsigned int *type)
-{
- struct buffer_head *bh;
- struct gfs_dirent *dent;
- int error;
-
- error = linked_leaf_search(dip, filename, &dent, NULL, &bh);
- if (error)
- return error;
-
- if (inum)
- gfs_inum_in(inum, (char *)&dent->de_inum);
- if (type)
- *type = gfs16_to_cpu(dent->de_type);
-
- brelse(bh);
-
- return 0;
-}
-
-/**
- * dir_e_add -
- * @dip: The GFS inode
- * @filename:
- * @inode:
- * @type:
- *
- */
-
-static int
-dir_e_add(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *inum, unsigned int type)
-{
- struct buffer_head *bh, *nbh, *dibh;
- struct gfs_leaf *leaf, *nleaf;
- struct gfs_dirent *dent;
- uint32_t hsize, index;
- uint32_t hash;
- uint64_t leaf_no, bn;
- int error;
-
- restart:
- hsize = 1 << dip->i_di.di_depth;
- if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- /* Figure out the address of the leaf node. */
-
- hash = gfs_dir_hash(filename->name, filename->len);
- index = hash >> (32 - dip->i_di.di_depth);
-
- error = get_leaf_nr(dip, index, &leaf_no);
- if (error)
- return error;
-
- /* Add entry to the leaf */
-
- for (;;) {
- error = get_leaf(dip, leaf_no, &bh);
- if (error)
- return error;
-
- leaf = (struct gfs_leaf *)bh->b_data;
-
- if (gfs_dirent_alloc(dip, bh, filename->len, &dent)) {
-
- if (gfs16_to_cpu(leaf->lf_depth) < dip->i_di.di_depth) {
- /* Can we split the leaf? */
-
- brelse(bh);
-
- error = dir_split_leaf(dip, index, leaf_no);
- if (error)
- return error;
-
- goto restart;
-
- } else if (dip->i_di.di_depth < GFS_DIR_MAX_DEPTH) {
- /* Can we double the hash table? */
-
- brelse(bh);
-
- error = dir_double_exhash(dip);
- if (error)
- return error;
-
- goto restart;
-
- } else if (leaf->lf_next) {
- /* Can we try the next leaf in the list? */
- leaf_no = gfs64_to_cpu(leaf->lf_next);
- brelse(bh);
- continue;
-
- } else {
- /* Create a new leaf and add it to the list. */
-
- error = gfs_metaalloc(dip, &bn);
- if (error) {
- brelse(bh);
- return error;
- }
-
- error = gfs_dread(dip->i_gl, bn,
- DIO_NEW | DIO_START | DIO_WAIT,
- &nbh);
- if (error) {
- brelse(bh);
- return error;
- }
-
- gfs_trans_add_bh(dip->i_gl, nbh);
- gfs_metatype_set(nbh,
- GFS_METATYPE_LF,
- GFS_FORMAT_LF);
- gfs_buffer_clear_tail(nbh,
- sizeof(struct gfs_meta_header));
-
- gfs_trans_add_bh(dip->i_gl, bh);
- leaf->lf_next = cpu_to_gfs64(bn);
-
- nleaf = (struct gfs_leaf *)nbh->b_data;
- nleaf->lf_depth = leaf->lf_depth;
- nleaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE);
-
- gfs_dirent_alloc(dip, nbh, filename->len, &dent);
-
- dip->i_di.di_blocks++;
-
- brelse(bh);
-
- bh = nbh;
- leaf = nleaf;
- }
- }
-
- /* If the gfs_dirent_alloc() succeeded, it pinned the "bh". */
-
- gfs_inum_out(inum, (char *)&dent->de_inum);
- dent->de_hash = cpu_to_gfs32(hash);
- dent->de_type = cpu_to_gfs16(type);
- memcpy((char *)(dent + 1), filename->name, filename->len);
-
- leaf->lf_entries = gfs16_to_cpu(leaf->lf_entries) + 1;
- leaf->lf_entries = cpu_to_gfs16(leaf->lf_entries);
-
- brelse(bh);
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- dip->i_di.di_entries++;
- dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
-
- gfs_trans_add_bh(dip->i_gl, dibh);
- gfs_dinode_out(&dip->i_di, dibh->b_data);
- brelse(dibh);
-
- return 0;
- }
-
- return -ENOENT;
-}
-
-/**
- * dir_e_del -
- * @dip: The GFS inode
- * @filename:
- *
- * Returns:
- */
-
-static int
-dir_e_del(struct gfs_inode *dip, struct qstr *filename)
-{
- struct buffer_head *bh, *dibh;
- struct gfs_dirent *dent, *prev;
- struct gfs_leaf *leaf;
- unsigned int entries;
- int error;
-
- error = linked_leaf_search(dip, filename, &dent, &prev, &bh);
- if (error == -ENOENT) {
- gfs_consist_inode(dip);
- return -EIO;
- }
- if (error)
- return error;
-
- dirent_del(dip, bh, prev, dent); /* Pins bh */
-
- leaf = (struct gfs_leaf *)bh->b_data;
- entries = gfs16_to_cpu(leaf->lf_entries);
- if (!entries)
- gfs_consist_inode(dip);
- entries--;
- leaf->lf_entries = cpu_to_gfs16(entries);
-
- brelse(bh);
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- if (!dip->i_di.di_entries)
- gfs_consist_inode(dip);
- dip->i_di.di_entries--;
- dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
-
- gfs_trans_add_bh(dip->i_gl, dibh);
- gfs_dinode_out(&dip->i_di, dibh->b_data);
- brelse(dibh);
-
- return 0;
-}
-
-/**
- * dir_e_read - Reads the entries from a directory into a filldir buffer
- * @dip: dinode pointer
- * @offset: the hash of the last entry read shifted to the right once
- * @opaque: buffer for the filldir function to fill
- * @filldir: points to the filldir function to use
- *
- * Returns: errno
- */
-
-static int
-dir_e_read(struct gfs_inode *dip, uint64_t *offset, void *opaque,
- gfs_filldir_t filldir)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct buffer_head *bh;
- struct gfs_leaf leaf;
- uint32_t hsize, len;
- uint32_t ht_offset, lp_offset, ht_offset_cur = -1;
- uint32_t hash, index;
- uint64_t *lp;
- int copied = FALSE;
- int error = 0;
-
- hsize = 1 << dip->i_di.di_depth;
- if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- hash = gfs_dir_offset2hash(*offset);
- index = hash >> (32 - dip->i_di.di_depth);
-
- lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL);
- if (!lp)
- return -ENOMEM;
-
- while (index < hsize) {
- lp_offset = index & (sdp->sd_hash_ptrs - 1);
- ht_offset = index - lp_offset;
-
- if (ht_offset_cur != ht_offset) {
- error = gfs_internal_read(dip, (char *)lp,
- ht_offset * sizeof(uint64_t),
- sdp->sd_hash_bsize);
- if (error != sdp->sd_hash_bsize) {
- if (error >= 0)
- error = -EIO;
- goto out;
- }
- ht_offset_cur = ht_offset;
- }
-
- error = get_leaf(dip, gfs64_to_cpu(lp[lp_offset]), &bh);
- if (error)
- goto out;
-
- gfs_leaf_in(&leaf, bh->b_data);
-
- if (leaf.lf_next)
- error = do_filldir_multi(dip, offset,
- opaque, filldir,
- bh, &copied);
- else
- error = do_filldir_single(dip, offset,
- opaque, filldir,
- bh, leaf.lf_entries,
- &copied);
-
- brelse(bh);
-
- if (error) {
- if (error > 0)
- error = 0;
- goto out;
- }
-
- len = 1 << (dip->i_di.di_depth - leaf.lf_depth);
- index = (index & ~(len - 1)) + len;
- }
-
- out:
- kfree(lp);
-
- return error;
-}
-
-/**
- * dir_e_mvino -
- * @dip: The GFS inode
- * @filename:
- * @new_inode:
- *
- * Returns:
- */
-
-static int
-dir_e_mvino(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *inum, unsigned int new_type)
-{
- struct buffer_head *bh, *dibh;
- struct gfs_dirent *dent;
- int error;
-
- error = linked_leaf_search(dip, filename, &dent, NULL, &bh);
- if (error == -ENOENT) {
- gfs_consist_inode(dip);
- return -EIO;
- }
- if (error)
- return error;
-
- gfs_trans_add_bh(dip->i_gl, bh);
-
- gfs_inum_out(inum, (char *)&dent->de_inum);
- dent->de_type = cpu_to_gfs16(new_type);
-
- brelse(bh);
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
-
- gfs_trans_add_bh(dip->i_gl, dibh);
- gfs_dinode_out(&dip->i_di, dibh->b_data);
- brelse(dibh);
-
- return 0;
-}
-
-/**
- * dir_l_search - Search linear (stuffed dinode) dir for inode matching name
- * @dip: The GFS inode
- * @filename: Filename string
- * @inode: If non-NULL, function fills with formal inode # and block address
- * @type: If non-NULL, function fills with GFS_FILE_... dinode type
- *
- * Returns:
- */
-
-static int
-dir_l_search(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *inum, unsigned int *type)
-{
- struct buffer_head *dibh;
- struct gfs_dirent *dent;
- int error;
-
- if (!gfs_is_stuffed(dip)) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- error = leaf_search(dip, dibh, filename, &dent, NULL);
- if (!error) {
- if (inum)
- gfs_inum_in(inum, (char *)&dent->de_inum);
- if (type)
- *type = gfs16_to_cpu(dent->de_type);
- }
-
- brelse(dibh);
-
- return error;
-}
-
-/**
- * dir_l_add -
- * @dip: The GFS inode
- * @filename:
- * @inode:
- * @type:
- *
- * Returns:
- */
-
-static int
-dir_l_add(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *inum, unsigned int type)
-{
- struct buffer_head *dibh;
- struct gfs_dirent *dent;
- int error;
-
- if (!gfs_is_stuffed(dip)) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- if (gfs_dirent_alloc(dip, dibh, filename->len, &dent)) {
- brelse(dibh);
-
- error = dir_make_exhash(dip);
- if (!error)
- error = dir_e_add(dip, filename, inum, type);
-
- return error;
- }
-
- /* gfs_dirent_alloc() pins */
-
- gfs_inum_out(inum, (char *)&dent->de_inum);
- dent->de_hash = gfs_dir_hash(filename->name, filename->len);
- dent->de_hash = cpu_to_gfs32(dent->de_hash);
- dent->de_type = cpu_to_gfs16(type);
- memcpy((char *)(dent + 1), filename->name, filename->len);
-
- dip->i_di.di_entries++;
- dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
-
- gfs_dinode_out(&dip->i_di, dibh->b_data);
- brelse(dibh);
-
- return 0;
-}
-
-/**
- * dir_l_del -
- * @dip: The GFS inode
- * @filename:
- *
- * Returns:
- */
-
-static int
-dir_l_del(struct gfs_inode *dip, struct qstr *filename)
-{
- struct buffer_head *dibh;
- struct gfs_dirent *dent, *prev;
- int error;
-
- if (!gfs_is_stuffed(dip)) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- error = leaf_search(dip, dibh, filename, &dent, &prev);
- if (error == -ENOENT) {
- gfs_consist_inode(dip);
- error = -EIO;
- goto out;
- }
- if (error)
- goto out;
-
- dirent_del(dip, dibh, prev, dent);
-
- /* dirent_del() pins */
-
- if (!dip->i_di.di_entries)
- gfs_consist_inode(dip);
- dip->i_di.di_entries--;
-
- dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
-
- gfs_dinode_out(&dip->i_di, dibh->b_data);
-
- out:
- brelse(dibh);
-
- return error;
-}
-
-/**
- * dir_l_read -
- * @dip:
- * @offset:
- * @opaque:
- * @filldir:
- *
- * Returns:
- */
-
-static int
-dir_l_read(struct gfs_inode *dip, uint64_t *offset, void *opaque,
- gfs_filldir_t filldir)
-{
- struct buffer_head *dibh;
- int copied = FALSE;
- int error;
-
- if (!gfs_is_stuffed(dip)) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- if (!dip->i_di.di_entries)
- return 0;
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- error = do_filldir_single(dip, offset,
- opaque, filldir,
- dibh, dip->i_di.di_entries,
- &copied);
- if (error > 0)
- error = 0;
-
- brelse(dibh);
-
- return error;
-}
-
-/**
- * dir_l_mvino -
- * @dip:
- * @filename:
- * @new_inode:
- *
- * Returns:
- */
-
-static int
-dir_l_mvino(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *inum, unsigned int new_type)
-{
- struct buffer_head *dibh;
- struct gfs_dirent *dent;
- int error;
-
- if (!gfs_is_stuffed(dip)) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- error = leaf_search(dip, dibh, filename, &dent, NULL);
- if (error == -ENOENT) {
- gfs_consist_inode(dip);
- error = -EIO;
- goto out;
- }
- if (error)
- goto out;
-
- gfs_trans_add_bh(dip->i_gl, dibh);
-
- gfs_inum_out(inum, (char *)&dent->de_inum);
- dent->de_type = cpu_to_gfs16(new_type);
-
- dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
-
- gfs_dinode_out(&dip->i_di, dibh->b_data);
-
- out:
- brelse(dibh);
-
- return error;
-}
-
-/**
- * gfs_dir_search - Search a directory
- * @dip: The GFS inode
- * @filename:
- * @inode:
- *
- * This routine searches a directory for a file or another directory.
- * Assumes a glock is held on dip.
- *
- * Returns: errno
- */
-
-int
-gfs_dir_search(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *inum, unsigned int *type)
-{
- int error;
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH)
- error = dir_e_search(dip, filename, inum, type);
- else
- error = dir_l_search(dip, filename, inum, type);
-
- return error;
-}
-
-/**
- * gfs_dir_add - Add new filename into directory
- * @dip: The GFS inode
- * @filename: The new name
- * @inode: The inode number of the entry
- * @type: The type of the entry
- *
- * Returns: 0 on success, error code on failure
- */
-
-int
-gfs_dir_add(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *inum, unsigned int type)
-{
- int error;
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH)
- error = dir_e_add(dip, filename, inum, type);
- else
- error = dir_l_add(dip, filename, inum, type);
-
- return error;
-}
-
-/**
- * gfs_dir_del - Delete a directory entry
- * @dip: The GFS inode
- * @filename: The filename
- *
- * Returns: 0 on success, error code on failure
- */
-
-int
-gfs_dir_del(struct gfs_inode *dip, struct qstr *filename)
-{
- int error;
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH)
- error = dir_e_del(dip, filename);
- else
- error = dir_l_del(dip, filename);
-
- return error;
-}
-
-/**
- * gfs_dir_read - Translate a GFS filename
- * @dip: The GFS inode
- * @offset:
- * @opaque:
- * @filldir:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int
-gfs_dir_read(struct gfs_inode *dip, uint64_t * offset, void *opaque,
- gfs_filldir_t filldir)
-{
- int error;
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH)
- error = dir_e_read(dip, offset, opaque, filldir);
- else
- error = dir_l_read(dip, offset, opaque, filldir);
-
- return error;
-}
-
-/**
- * gfs_dir_mvino - Change inode number of directory entry
- * @dip: The GFS inode
- * @filename:
- * @new_inode:
- *
- * This routine changes the inode number of a directory entry. It's used
- * by rename to change ".." when a directory is moved.
- * Assumes a glock is held on dvp.
- *
- * Returns: errno
- */
-
-int
-gfs_dir_mvino(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *inum, unsigned int new_type)
-{
- int error;
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH)
- error = dir_e_mvino(dip, filename, inum, new_type);
- else
- error = dir_l_mvino(dip, filename, inum, new_type);
-
- return error;
-}
-
-/**
- * foreach_leaf - call a function for each leaf in a directory
- * @dip: the directory
- * @lc: the function to call for each each
- * @data: private data to pass to it
- *
- * Returns: errno
- */
-
-static int
-foreach_leaf(struct gfs_inode *dip, leaf_call_t lc, void *data)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct buffer_head *bh;
- struct gfs_leaf leaf;
- uint32_t hsize, len;
- uint32_t ht_offset, lp_offset, ht_offset_cur = -1;
- uint32_t index = 0;
- uint64_t *lp;
- uint64_t leaf_no;
- int error = 0;
-
- hsize = 1 << dip->i_di.di_depth;
- if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL);
- if (!lp)
- return -ENOMEM;
-
- while (index < hsize) {
- lp_offset = index & (sdp->sd_hash_ptrs - 1);
- ht_offset = index - lp_offset;
-
- if (ht_offset_cur != ht_offset) {
- error = gfs_internal_read(dip, (char *)lp,
- ht_offset * sizeof(uint64_t),
- sdp->sd_hash_bsize);
- if (error != sdp->sd_hash_bsize) {
- if (error >= 0)
- error = -EIO;
- goto out;
- }
- ht_offset_cur = ht_offset;
- }
-
- leaf_no = gfs64_to_cpu(lp[lp_offset]);
- if (leaf_no) {
- error = get_leaf(dip, leaf_no, &bh);
- if (error)
- goto out;
- gfs_leaf_in(&leaf, bh->b_data);
- brelse(bh);
-
- len = 1 << (dip->i_di.di_depth - leaf.lf_depth);
-
- error = lc(dip, index, len, leaf_no, data);
- if (error)
- goto out;
-
- index = (index & ~(len - 1)) + len;
- } else
- index++;
- }
-
- if (index != hsize) {
- gfs_consist_inode(dip);
- error = -EIO;
- }
-
- out:
- kfree(lp);
-
- return error;
-}
-
-/**
- * leaf_free - Deallocate a directory leaf
- * @dip: the directory
- * @index: the hash table offset in the directory
- * @len: the number of pointers to this leaf
- * @leaf_no: the leaf number
- * @data: not used
- *
- * Returns: errno
- */
-
-static int
-leaf_free(struct gfs_inode *dip,
- uint32_t index, uint32_t len,
- uint64_t leaf_no, void *data)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_leaf tmp_leaf;
- struct gfs_rgrp_list rlist;
- struct buffer_head *bh, *dibh;
- uint64_t blk;
- unsigned int rg_blocks = 0;
- char *ht=0;
- unsigned int x, size = len * sizeof(uint64_t);
- int error;
-
- memset(&rlist, 0, sizeof(struct gfs_rgrp_list));
-
- gfs_alloc_get(dip);
-
- error = gfs_quota_hold_m(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error)
- goto out;
-
- error = gfs_rindex_hold(sdp, &dip->i_alloc->al_ri_gh);
- if (error)
- goto out_qs;
-
- /* Count the number of leaves */
-
- for (blk = leaf_no; blk; blk = tmp_leaf.lf_next) {
- error = get_leaf(dip, blk, &bh);
- if (error)
- goto out_rlist;
- gfs_leaf_in(&tmp_leaf, (bh)->b_data);
- brelse(bh);
-
- gfs_rlist_add(sdp, &rlist, blk);
- }
-
- gfs_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
-
- for (x = 0; x < rlist.rl_rgrps; x++) {
- struct gfs_rgrpd *rgd;
- rgd = get_gl2rgd(rlist.rl_ghs[x].gh_gl);
- rg_blocks += rgd->rd_ri.ri_length;
- }
-
- error = gfs_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
- if (error)
- goto out_rlist;
-
- /* Trans may require:
- All the bitmaps that were reserved.
- One block for the dinode.
- All the hash blocks that will be changed.
- One block for a quota change. */
-
- error = gfs_trans_begin(sdp,
- rg_blocks + 1 + (DIV_RU(size, sdp->sd_jbsize) + 1),
- 1);
- if (error)
- goto out_rg_gunlock;
-
- for (blk = leaf_no; blk; blk = tmp_leaf.lf_next) {
- error = get_leaf(dip, blk, &bh);
- if (error)
- goto out_end_trans;
- gfs_leaf_in(&tmp_leaf, bh->b_data);
- brelse(bh);
-
- gfs_metafree(dip, blk, 1);
-
- if (!dip->i_di.di_blocks)
- gfs_consist_inode(dip);
- dip->i_di.di_blocks--;
- }
-
- error = gfs_writei(dip, ht, index * sizeof (uint64_t), size, gfs_zero_blocks, NULL);
-
- if (error != size) {
- if (error >= 0)
- error = -EIO;
- goto out_end_trans;
- }
-
- error = gfs_get_inode_buffer(dip, &dibh);
- if (error)
- goto out_end_trans;
-
- gfs_trans_add_bh(dip->i_gl, dibh);
- gfs_dinode_out(&dip->i_di, dibh->b_data);
- brelse(dibh);
-
- out_end_trans:
- gfs_trans_end(sdp);
-
- out_rg_gunlock:
- gfs_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs);
-
- out_rlist:
- gfs_rlist_free(&rlist);
- gfs_glock_dq_uninit(&dip->i_alloc->al_ri_gh);
-
- out_qs:
- gfs_quota_unhold_m(dip);
-
- out:
- gfs_alloc_put(dip);
-
- return error;
-}
-
-/**
- * gfs_dir_exhash_free - free all the leaf blocks in a directory
- * @dip: the directory
- *
- * Dealloc all on-disk directory leaves to FREEMETA state
- * Change on-disk inode type to "regular file"
- *
- * Returns: errno
- */
-
-int
-gfs_dir_exhash_free(struct gfs_inode *dip)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct buffer_head *bh;
- int error;
-
- /* Dealloc on-disk leaves to FREEMETA state */
- error = foreach_leaf(dip, leaf_free, NULL);
- if (error)
- return error;
-
- /* Make this a regular file in case we crash.
- (We don't want to free these blocks a second time.) */
-
- error = gfs_trans_begin(sdp, 1, 0);
- if (error)
- return error;
-
- error = gfs_get_inode_buffer(dip, &bh);
- if (!error) {
- gfs_trans_add_bh(dip->i_gl, bh);
- ((struct gfs_dinode *)bh->b_data)->di_type = cpu_to_gfs16(GFS_FILE_REG);
- brelse(bh);
- }
-
- gfs_trans_end(sdp);
-
- return error;
-}
-
-/**
- * gfs_diradd_alloc_required - figure out if an entry addition is going to require an allocation
- * @ip: the file being written to
- * @filname: the filename that's going to be added
- * @alloc_required: the int is set to TRUE if an alloc is required, FALSE otherwise
- *
- * Returns: errno
- */
-
-int
-gfs_diradd_alloc_required(struct gfs_inode *dip, struct qstr *filename,
- int *alloc_required)
-{
- struct buffer_head *bh = NULL, *bh_next;
- uint32_t hsize, hash, index;
- int error = 0;
-
- *alloc_required = FALSE;
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH) {
- hsize = 1 << dip->i_di.di_depth;
- if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- hash = gfs_dir_hash(filename->name, filename->len);
- index = hash >> (32 - dip->i_di.di_depth);
-
- error = get_first_leaf(dip, index, &bh_next);
- if (error)
- return error;
-
- do {
- if (bh)
- brelse(bh);
-
- bh = bh_next;
-
- if (dirent_fits(dip, bh, filename->len))
- break;
-
- error = get_next_leaf(dip, bh, &bh_next);
- if (error == -ENOENT) {
- *alloc_required = TRUE;
- error = 0;
- break;
- }
- }
- while (!error);
-
- brelse(bh);
- } else {
- error = gfs_get_inode_buffer(dip, &bh);
- if (error)
- return error;
-
- if (!dirent_fits(dip, bh, filename->len))
- *alloc_required = TRUE;
-
- brelse(bh);
- }
-
- return error;
-}
-
-/**
- * do_gdm - copy out one leaf (or list of leaves)
- * @dip: the directory
- * @index: the hash table offset in the directory
- * @len: the number of pointers to this leaf
- * @leaf_no: the leaf number
- * @data: a pointer to a struct gfs_user_buffer structure
- *
- * Returns: errno
- */
-
-static int
-do_gdm(struct gfs_inode *dip,
- uint32_t index, uint32_t len, uint64_t leaf_no,
- void *data)
-{
- struct gfs_user_buffer *ub = (struct gfs_user_buffer *)data;
- struct gfs_leaf leaf;
- struct buffer_head *bh;
- uint64_t blk;
- int error = 0;
-
- for (blk = leaf_no; blk; blk = leaf.lf_next) {
- error = get_leaf(dip, blk, &bh);
- if (error)
- break;
-
- gfs_leaf_in(&leaf, bh->b_data);
-
- error = gfs_add_bh_to_ub(ub, bh);
-
- brelse(bh);
-
- if (error)
- break;
- }
-
- return error;
-}
-
-/**
- * gfs_get_dir_meta - return all the leaf blocks of a directory
- * @dip: the directory
- * @ub: the structure representing the meta
- *
- * Returns: errno
- */
-
-int
-gfs_get_dir_meta(struct gfs_inode *dip, struct gfs_user_buffer *ub)
-{
- return foreach_leaf(dip, do_gdm, ub);
-}
diff --git a/gfs-kernel/src/gfs/dir.h b/gfs-kernel/src/gfs/dir.h
deleted file mode 100644
index bbde532..0000000
--- a/gfs-kernel/src/gfs/dir.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef __DIR_DOT_H__
-#define __DIR_DOT_H__
-
-/**
- * gfs_filldir_t - Report a directory entry to the caller of gfs_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 (*gfs_filldir_t) (void *opaque,
- const char *name, unsigned int length,
- uint64_t offset,
- struct gfs_inum *inum, unsigned int type);
-
-int gfs_filecmp(struct qstr *file1, char *file2, int len_of_file2);
-int gfs_dirent_alloc(struct gfs_inode *dip, struct buffer_head *bh,
- int name_len, struct gfs_dirent **dent_out);
-
-int gfs_dir_search(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *inum, unsigned int *type);
-int gfs_dir_add(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *inum, unsigned int type);
-int gfs_dir_del(struct gfs_inode *dip, struct qstr *filename);
-int gfs_dir_read(struct gfs_inode *dip, uint64_t * offset, void *opaque,
- gfs_filldir_t filldir);
-int gfs_dir_mvino(struct gfs_inode *dip, struct qstr *filename,
- struct gfs_inum *new_inum, unsigned int new_type);
-
-int gfs_dir_exhash_free(struct gfs_inode *dip);
-
-int gfs_diradd_alloc_required(struct gfs_inode *dip, struct qstr *filename,
- int *alloc_required);
-
-int gfs_get_dir_meta(struct gfs_inode *ip, struct gfs_user_buffer *ub);
-
-#endif /* __DIR_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/eaops.c b/gfs-kernel/src/gfs/eaops.c
deleted file mode 100644
index dbd0254..0000000
--- a/gfs-kernel/src/gfs/eaops.c
+++ /dev/null
@@ -1,173 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <asm/uaccess.h>
-#include <linux/xattr.h>
-#include <linux/posix_acl.h>
-
-#include "gfs.h"
-#include "acl.h"
-#include "eaops.h"
-#include "eattr.h"
-
-/**
- * gfs_ea_name2type - get the type of the ea, and trucate the type from the name
- * @namep: ea name, possibly with type appended
- *
- * Returns: GFS_EATYPE_XXX
- */
-
-unsigned int
-gfs_ea_name2type(const char *name, char **truncated_name)
-{
- unsigned int type;
-
- if (strncmp(name, "system.", 7) == 0) {
- type = GFS_EATYPE_SYS;
- if (truncated_name)
- *truncated_name = strchr(name, '.') + 1;
- } else if (strncmp(name, "user.", 5) == 0) {
- type = GFS_EATYPE_USR;
- if (truncated_name)
- *truncated_name = strchr(name, '.') + 1;
- } else if (strncmp(name, "security.", 9) == 0) {
- type = GFS_EATYPE_SECURITY;
- if (truncated_name)
- *truncated_name = strchr(name, '.') + 1;
- } else {
- type = GFS_EATYPE_UNUSED;
- if (truncated_name)
- *truncated_name = NULL;
- }
-
- return type;
-}
-
-/**
- * system_eo_get -
- * @ip:
- * @er:
- *
- * Returns: errno
- */
-
-static int
-system_eo_get(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- if (!GFS_ACL_IS_ACCESS(er->er_name, er->er_name_len) &&
- !GFS_ACL_IS_DEFAULT(er->er_name, er->er_name_len) &&
- !capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (ip->i_sbd->sd_args.ar_posix_acls == FALSE &&
- (GFS_ACL_IS_ACCESS(er->er_name, er->er_name_len) ||
- GFS_ACL_IS_DEFAULT(er->er_name, er->er_name_len)))
- return -EOPNOTSUPP;
-
- return gfs_ea_get_i(ip, er);
-}
-
-/**
- * system_eo_set -
- * @ip:
- * @er:
- *
- * Returns: errno
- */
-
-static int
-system_eo_set(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- int remove = FALSE;
- int error;
-
- if (GFS_ACL_IS_ACCESS(er->er_name, er->er_name_len)) {
- er->er_mode = ip->i_vnode->i_mode;
- error = gfs_acl_validate_set(ip, TRUE, er,
- &remove, &er->er_mode);
- if (error)
- return error;
- error = gfs_ea_set_i(ip, er);
- if (error)
- return error;
- if (remove)
- gfs_ea_remove_i(ip, er);
- return 0;
-
- } else if (GFS_ACL_IS_DEFAULT(er->er_name, er->er_name_len)) {
- int error = gfs_acl_validate_set(ip, FALSE, er,
- &remove, NULL);
- if (error)
- return error;
- if (!remove)
- error = gfs_ea_set_i(ip, er);
- else {
- error = gfs_ea_remove_i(ip, er);
- if (error == -ENODATA)
- error = 0;
- }
- return error;
- }
-
- return -EPERM;
-}
-
-/**
- * system_eo_remove -
- * @ip:
- * @er:
- *
- * Returns: errno
- */
-
-static int
-system_eo_remove(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- if (GFS_ACL_IS_ACCESS(er->er_name, er->er_name_len)) {
- int error = gfs_acl_validate_remove(ip, TRUE);
- if (error)
- return error;
-
- } else if (GFS_ACL_IS_DEFAULT(er->er_name, er->er_name_len)) {
- int error = gfs_acl_validate_remove(ip, FALSE);
- if (error)
- return error;
-
- } else
- return -EPERM;
-
- return gfs_ea_remove_i(ip, er);
-}
-
-struct gfs_eattr_operations gfs_user_eaops = {
- .eo_get = gfs_ea_get_i,
- .eo_set = gfs_ea_set_i,
- .eo_remove = gfs_ea_remove_i,
- .eo_name = "user",
-};
-
-struct gfs_eattr_operations gfs_system_eaops = {
- .eo_get = system_eo_get,
- .eo_set = system_eo_set,
- .eo_remove = system_eo_remove,
- .eo_name = "system",
-};
-
-struct gfs_eattr_operations gfs_security_eaops = {
- .eo_get = gfs_ea_get_i,
- .eo_set = gfs_ea_set_i,
- .eo_remove = gfs_ea_remove_i,
- .eo_name = "security",
-};
-
-struct gfs_eattr_operations *gfs_ea_ops[] = {
- NULL,
- &gfs_user_eaops,
- &gfs_system_eaops,
- &gfs_security_eaops,
-};
-
diff --git a/gfs-kernel/src/gfs/eaops.h b/gfs-kernel/src/gfs/eaops.h
deleted file mode 100644
index 6ea9123..0000000
--- a/gfs-kernel/src/gfs/eaops.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __EAOPS_DOT_H__
-#define __EAOPS_DOT_H__
-
-struct gfs_ea_request;
-
-struct gfs_eattr_operations {
- int (*eo_get) (struct gfs_inode *ip, struct gfs_ea_request *er);
- int (*eo_set) (struct gfs_inode *ip, struct gfs_ea_request *er);
- int (*eo_remove) (struct gfs_inode *ip, struct gfs_ea_request *er);
- char *eo_name;
-};
-
-unsigned int gfs_ea_name2type(const char *name, char **truncated_name);
-
-extern struct gfs_eattr_operations gfs_user_eaops;
-extern struct gfs_eattr_operations gfs_system_eaops;
-
-extern struct gfs_eattr_operations *gfs_ea_ops[];
-
-#endif /* __EAOPS_DOT_H__ */
-
diff --git a/gfs-kernel/src/gfs/eattr.c b/gfs-kernel/src/gfs/eattr.c
deleted file mode 100644
index 71f7e70..0000000
--- a/gfs-kernel/src/gfs/eattr.c
+++ /dev/null
@@ -1,2007 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <asm/uaccess.h>
-#include <linux/xattr.h>
-#include <linux/posix_acl.h>
-
-#include "gfs.h"
-#include "acl.h"
-#include "dio.h"
-#include "eaops.h"
-#include "eattr.h"
-#include "glock.h"
-#include "inode.h"
-#include "quota.h"
-#include "rgrp.h"
-#include "trans.h"
-
-/**
- * ea_calc_size - returns the acutal number of bytes the request will take up
- * (not counting any unstuffed data blocks)
- * @sdp:
- * @er:
- * @size:
- *
- * Returns: TRUE if the EA should be stuffed
- */
-
-static int
-ea_calc_size(struct gfs_sbd *sdp,
- struct gfs_ea_request *er,
- unsigned int *size)
-{
- *size = GFS_EAREQ_SIZE_STUFFED(er);
- if (*size <= sdp->sd_jbsize)
- return TRUE;
-
- *size = GFS_EAREQ_SIZE_UNSTUFFED(sdp, er);
- return FALSE;
-}
-
-/**
- * gfs_ea_check_size -
- * @ip:
- * @er:
- *
- * Returns: errno
- */
-
-int
-gfs_ea_check_size(struct gfs_sbd *sdp, struct gfs_ea_request *er)
-{
- unsigned int size;
-
- if (er->er_data_len > GFS_EA_MAX_DATA_LEN)
- return -ERANGE;
-
- ea_calc_size(sdp, er, &size);
- if (size > sdp->sd_jbsize)
- return -ERANGE; /* This can only happen with 512 byte blocks */
-
- return 0;
-}
-
-typedef int (*ea_call_t) (struct gfs_inode *ip,
- struct buffer_head *bh,
- struct gfs_ea_header *ea,
- struct gfs_ea_header *prev,
- void *private);
-
-/**
- * ea_foreach_i -
- * @ip:
- * @bh:
- * @eabc:
- * @data:
- *
- * Returns: errno
- */
-
-static int
-ea_foreach_i(struct gfs_inode *ip,
- struct buffer_head *bh,
- ea_call_t ea_call, void *data)
-{
- struct gfs_ea_header *ea, *prev = NULL;
- int error = 0;
-
- if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_EA))
- return -EIO;
-
- for (ea = GFS_EA_BH2FIRST(bh);; prev = ea, ea = GFS_EA2NEXT(ea)) {
- if (!GFS_EA_REC_LEN(ea))
- goto fail;
- if (!(bh->b_data <= (char *)ea &&
- (char *)GFS_EA2NEXT(ea) <=
- bh->b_data + bh->b_size))
- goto fail;
- if (!GFS_EATYPE_VALID(ea->ea_type))
- goto fail;
-
- error = ea_call(ip, bh, ea, prev, data);
- if (error)
- return error;
-
- if (GFS_EA_IS_LAST(ea)) {
- if ((char *)GFS_EA2NEXT(ea) !=
- bh->b_data + bh->b_size)
- goto fail;
- break;
- }
- }
-
- return error;
-
- fail:
- gfs_consist_inode(ip);
- return -EIO;
-}
-
-/**
- * ea_foreach -
- * @ip:
- * @ea_call:
- * @data:
- *
- * Returns: errno
- */
-
-static int
-ea_foreach(struct gfs_inode *ip,
- ea_call_t ea_call,
- void *data)
-{
- struct buffer_head *bh;
- int error;
-
- error = gfs_dread(ip->i_gl, ip->i_di.di_eattr,
- DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
-
- if (!(ip->i_di.di_flags & GFS_DIF_EA_INDIRECT))
- error = ea_foreach_i(ip, bh, ea_call, data);
- else {
- struct buffer_head *eabh;
- uint64_t *eablk, *end;
-
- if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_IN)) {
- error = -EIO;
- goto out;
- }
-
- eablk = (uint64_t *)(bh->b_data + sizeof(struct gfs_indirect));
- end = eablk + ip->i_sbd->sd_inptrs;
-
- for (; eablk < end; eablk++) {
- uint64_t bn;
-
- if (!*eablk)
- break;
- bn = gfs64_to_cpu(*eablk);
-
- error = gfs_dread(ip->i_gl, bn,
- DIO_START | DIO_WAIT, &eabh);
- if (error)
- break;
- error = ea_foreach_i(ip, eabh, ea_call, data);
- brelse(eabh);
- if (error)
- break;
- }
- }
-
- out:
- brelse(bh);
-
- return error;
-}
-
-struct ea_find {
- struct gfs_ea_request *ef_er;
- struct gfs_ea_location *ef_el;
-};
-
-/**
- * ea_find_i -
- * @ip:
- * @bh:
- * @ea:
- * @prev:
- * @private:
- *
- * Returns: -errno on error, 1 if search is over,
- * 0 if search should continue
- */
-
-static int
-ea_find_i(struct gfs_inode *ip,
- struct buffer_head *bh,
- struct gfs_ea_header *ea,
- struct gfs_ea_header *prev,
- void *private)
-{
- struct ea_find *ef = (struct ea_find *)private;
- struct gfs_ea_request *er = ef->ef_er;
-
- if (ea->ea_type == GFS_EATYPE_UNUSED)
- return 0;
-
- if (ea->ea_type == er->er_type) {
- if (ea->ea_name_len == er->er_name_len &&
- !memcmp(GFS_EA2NAME(ea), er->er_name, ea->ea_name_len)) {
- struct gfs_ea_location *el = ef->ef_el;
- get_bh(bh);
- el->el_bh = bh;
- el->el_ea = ea;
- el->el_prev = prev;
- return 1;
- }
- }
-
-#if 0
- else if ((ip->i_di.di_flags & GFS_DIF_EA_PACKED) &&
- er->er_type == GFS_EATYPE_SYS)
- return 1;
-#endif
-
- return 0;
-}
-
-/**
- * gfs_ea_find - find a matching eattr
- * @ip:
- * @er:
- * @el:
- *
- * Returns: errno
- */
-
-int
-gfs_ea_find(struct gfs_inode *ip,
- struct gfs_ea_request *er,
- struct gfs_ea_location *el)
-{
- struct ea_find ef;
- int error;
-
- ef.ef_er = er;
- ef.ef_el = el;
-
- memset(el, 0, sizeof(struct gfs_ea_location));
-
- error = ea_foreach(ip, ea_find_i, &ef);
- if (error > 0)
- return 0;
-
- return error;
-}
-
-/**
- * ea_dealloc_unstuffed -
- * @ip:
- * @bh:
- * @ea:
- * @prev:
- * @private:
- *
- * Take advantage of the fact that all unstuffed blocks are
- * allocated from the same RG. But watch, this may not always
- * be true.
- *
- * Returns: errno
- */
-
-static int
-ea_dealloc_unstuffed(struct gfs_inode *ip,
- struct buffer_head *bh,
- struct gfs_ea_header *ea,
- struct gfs_ea_header *prev,
- void *private)
-{
- int *leave = (int *)private;
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_rgrpd *rgd;
- struct gfs_holder rg_gh;
- struct buffer_head *dibh;
- uint64_t *dataptrs, bn = 0;
- uint64_t bstart = 0;
- unsigned int blen = 0;
- unsigned int x;
- int error;
-
- if (GFS_EA_IS_STUFFED(ea))
- return 0;
-
- dataptrs = GFS_EA2DATAPTRS(ea);
- for (x = 0; x < ea->ea_num_ptrs; x++, dataptrs++)
- if (*dataptrs) {
- bn = gfs64_to_cpu(*dataptrs);
- break;
- }
- if (!bn)
- return 0;
-
- rgd = gfs_blk2rgrpd(sdp, bn);
- if (!rgd) {
- gfs_consist_inode(ip);
- return -EIO;
- }
-
- error = gfs_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rg_gh);
- if (error)
- return error;
-
- error = gfs_trans_begin(sdp, 2 + rgd->rd_ri.ri_length, 1);
- if (error)
- goto out_gunlock;
-
- gfs_trans_add_bh(ip->i_gl, bh);
-
- dataptrs = GFS_EA2DATAPTRS(ea);
- for (x = 0; x < ea->ea_num_ptrs; x++, dataptrs++) {
- if (!*dataptrs)
- break;
- bn = gfs64_to_cpu(*dataptrs);
-
- if (bstart + blen == bn)
- blen++;
- else {
- if (bstart)
- gfs_metafree(ip, bstart, blen);
- bstart = bn;
- blen = 1;
- }
-
- *dataptrs = 0;
- if (!ip->i_di.di_blocks)
- gfs_consist_inode(ip);
- ip->i_di.di_blocks--;
- }
- if (bstart)
- gfs_metafree(ip, bstart, blen);
-
- if (prev && !leave) {
- uint32_t len;
-
- len = GFS_EA_REC_LEN(prev) + GFS_EA_REC_LEN(ea);
- prev->ea_rec_len = cpu_to_gfs32(len);
-
- if (GFS_EA_IS_LAST(ea))
- prev->ea_flags |= GFS_EAFLAG_LAST;
- } else {
- ea->ea_type = GFS_EATYPE_UNUSED;
- ea->ea_num_ptrs = 0;
- }
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (!error) {
- ip->i_di.di_ctime = get_seconds();
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- gfs_trans_end(sdp);
-
- out_gunlock:
- gfs_glock_dq_uninit(&rg_gh);
-
- return error;
-}
-
-/**
- * ea_remove_unstuffed -
- * @ip:
- * @bh:
- * @ea:
- * @prev:
- * @leave:
- *
- * Returns: errno
- */
-
-static int
-ea_remove_unstuffed(struct gfs_inode *ip,
- struct buffer_head *bh,
- struct gfs_ea_header *ea,
- struct gfs_ea_header *prev,
- int leave)
-{
- struct gfs_alloc *al;
- int error;
-
- al = gfs_alloc_get(ip);
-
- error = gfs_quota_hold_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error)
- goto out_alloc;
-
- error = gfs_rindex_hold(ip->i_sbd, &al->al_ri_gh);
- if (error)
- goto out_quota;
-
- error = ea_dealloc_unstuffed(ip,
- bh, ea, prev,
- (leave) ? &error : NULL);
-
- gfs_glock_dq_uninit(&al->al_ri_gh);
-
- out_quota:
- gfs_quota_unhold_m(ip);
-
- out_alloc:
- gfs_alloc_put(ip);
-
- return error;
-}
-
-/**************************************************************************************************/
-
-/**
- * gfs_ea_repack_i -
- * @ip:
- *
- * Returns: errno
- */
-
-int
-gfs_ea_repack_i(struct gfs_inode *ip)
-{
- return -ENOSYS;
-}
-
-/**
- * gfs_ea_repack -
- * @ip:
- *
- * Returns: errno
- */
-
-int gfs_ea_repack(struct gfs_inode *ip)
-{
- struct gfs_holder gh;
- int error;
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
- if (error)
- return error;
-
- /* Some sort of permissions checking would be nice */
-
- error = gfs_ea_repack_i(ip);
-
- gfs_glock_dq_uninit(&gh);
-
- return error;
-}
-
-struct ea_list {
- struct gfs_ea_request *ei_er;
- unsigned int ei_size;
-};
-
-/**
- * ea_list_i -
- * @ip:
- * @bh:
- * @ea:
- * @prev:
- * @private:
- *
- * Returns: errno
- */
-
-static int
-ea_list_i(struct gfs_inode *ip,
- struct buffer_head *bh,
- struct gfs_ea_header *ea,
- struct gfs_ea_header *prev,
- void *private)
-{
- struct ea_list *ei = (struct ea_list *)private;
- struct gfs_ea_request *er = ei->ei_er;
- unsigned int ea_size = gfs_ea_strlen(ea);
-
- if (ea->ea_type == GFS_EATYPE_UNUSED)
- return 0;
-
- if (er->er_data_len) {
- char *prefix;
- unsigned int l;
- char c = 0;
-
- if (ei->ei_size + ea_size > er->er_data_len)
- return -ERANGE;
-
- switch (ea->ea_type) {
- case GFS_EATYPE_USR:
- prefix = "user.";
- l = 5;
- break;
- case GFS_EATYPE_SYS:
- prefix = "system.";
- l = 7;
- break;
- case GFS_EATYPE_SECURITY:
- prefix = "security.";
- l = 9;
- break;
- default:
- prefix = NULL;
- l = 0;
- break;
- }
-
- if (prefix == NULL || l == 0)
- return -EIO;
-
- memcpy(er->er_data + ei->ei_size,
- prefix, l);
- memcpy(er->er_data + ei->ei_size + l,
- GFS_EA2NAME(ea),
- ea->ea_name_len);
- memcpy(er->er_data + ei->ei_size +
- ea_size - 1,
- &c, 1);
- }
-
- ei->ei_size += ea_size;
-
- return 0;
-}
-
-/**
- * gfs_ea_list -
- * @ip:
- * @er:
- *
- * Returns: actual size of data on success, -errno on error
- */
-
-int
-gfs_ea_list(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- struct gfs_holder i_gh;
- int error;
-
- if (!er->er_data || !er->er_data_len) {
- er->er_data = NULL;
- er->er_data_len = 0;
- }
-
- error = gfs_glock_nq_init(ip->i_gl,
- LM_ST_SHARED, LM_FLAG_ANY,
- &i_gh);
- if (error)
- return error;
-
- if (ip->i_di.di_eattr) {
- struct ea_list ei = { .ei_er = er, .ei_size = 0 };
-
- error = ea_foreach(ip, ea_list_i, &ei);
- if (!error)
- error = ei.ei_size;
- }
-
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * ea_get_unstuffed - actually copies the unstuffed data into the
- * request buffer
- * @ip:
- * @ea:
- * @data:
- *
- * Returns: errno
- */
-
-static int
-ea_get_unstuffed(struct gfs_inode *ip, struct gfs_ea_header *ea,
- char *data)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head **bh;
- unsigned int amount = GFS_EA_DATA_LEN(ea);
- unsigned int nptrs = DIV_RU(amount, sdp->sd_jbsize);
- uint64_t *dataptrs = GFS_EA2DATAPTRS(ea);
- unsigned int x;
- int error = 0;
-
- bh = kmalloc(nptrs * sizeof(struct buffer_head *), GFP_NOFS);
- if (!bh)
- return -ENOMEM;
-
- for (x = 0; x < nptrs; x++) {
- error = gfs_dread(ip->i_gl, gfs64_to_cpu(*dataptrs),
- DIO_START, bh + x);
- if (error) {
- while (x--)
- brelse(bh[x]);
- goto out;
- }
- dataptrs++;
- }
-
- for (x = 0; x < nptrs; x++) {
- error = gfs_dreread(sdp, bh[x], DIO_WAIT);
- if (error) {
- for (; x < nptrs; x++)
- brelse(bh[x]);
- goto out;
- }
- if (gfs_metatype_check2(sdp, bh[x],
- GFS_METATYPE_ED, GFS_METATYPE_EA)) {
- for (; x < nptrs; x++)
- brelse(bh[x]);
- error = -EIO;
- goto out;
- }
-
- memcpy(data,
- bh[x]->b_data + sizeof(struct gfs_meta_header),
- (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize);
-
- amount -= sdp->sd_jbsize;
- data += sdp->sd_jbsize;
-
- brelse(bh[x]);
- }
-
- out:
- kfree(bh);
-
- return error;
-}
-
-/**
- * gfs_ea_get_copy -
- * @ip:
- * @el:
- * @data:
- *
- * Returns: errno
- */
-
-int
-gfs_ea_get_copy(struct gfs_inode *ip,
- struct gfs_ea_location *el,
- char *data)
-{
- if (GFS_EA_IS_STUFFED(el->el_ea)) {
- memcpy(data,
- GFS_EA2DATA(el->el_ea),
- GFS_EA_DATA_LEN(el->el_ea));
- return 0;
- } else
- return ea_get_unstuffed(ip, el->el_ea, data);
-}
-
-/**
- * gfs_ea_get_i -
- * @ip:
- * @er:
- *
- * Returns: actual size of data on success, -errno on error
- */
-
-int
-gfs_ea_get_i(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- struct gfs_ea_location el;
- int error;
-
- if (!ip->i_di.di_eattr)
- return -ENODATA;
-
- error = gfs_ea_find(ip, er, &el);
- if (error)
- return error;
- if (!el.el_ea)
- return -ENODATA;
-
- if (er->er_data_len) {
- if (GFS_EA_DATA_LEN(el.el_ea) > er->er_data_len)
- error = -ERANGE;
- else
- error = gfs_ea_get_copy(ip, &el, er->er_data);
- }
- if (!error)
- error = GFS_EA_DATA_LEN(el.el_ea);
-
- brelse(el.el_bh);
-
- return error;
-}
-
-/**
- * gfs_ea_get -
- * @ip:
- * @er:
- *
- * Returns: actual size of data on success, -errno on error
- */
-
-int
-gfs_ea_get(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- struct gfs_holder i_gh;
- int error;
-
- if (!er->er_name_len ||
- er->er_name_len > GFS_EA_MAX_NAME_LEN)
- return -EINVAL;
- if (!er->er_data || !er->er_data_len) {
- er->er_data = NULL;
- er->er_data_len = 0;
- }
-
- error = gfs_glock_nq_init(ip->i_gl,
- LM_ST_SHARED, LM_FLAG_ANY,
- &i_gh);
- if (error)
- return error;
-
- error = gfs_ea_ops[er->er_type]->eo_get(ip, er);
-
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * ea_alloc_blk - allocates a new block for extended attributes.
- * @ip: A pointer to the inode that's getting extended attributes
- * @bhp:
- *
- * Returns: errno
- */
-
-static int
-ea_alloc_blk(struct gfs_inode *ip,
- struct buffer_head **bhp)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_ea_header *ea;
- uint64_t block;
- int error;
-
- error = gfs_metaalloc(ip, &block);
- if (error)
- return error;
-
- error = gfs_dread(ip->i_gl, block,
- DIO_NEW | DIO_START | DIO_WAIT, bhp);
- if (error)
- return error;
-
- gfs_trans_add_bh(ip->i_gl, *bhp);
- gfs_metatype_set(*bhp, GFS_METATYPE_EA, GFS_FORMAT_EA);
-
- ea = GFS_EA_BH2FIRST(*bhp);
- ea->ea_rec_len = cpu_to_gfs32(sdp->sd_jbsize);
- ea->ea_type = GFS_EATYPE_UNUSED;
- ea->ea_flags = GFS_EAFLAG_LAST;
- ea->ea_num_ptrs = 0;
-
- ip->i_di.di_blocks++;
-
- return 0;
-}
-
-/**
- * ea_write - writes the request info to an ea, creating new blocks if
- * necessary
- * @ip: inode that is being modified
- * @ea: the location of the new ea in a block
- * @er: the write request
- *
- * Note: does not update ea_rec_len or the GFS_EAFLAG_LAST bin of ea_flags
- *
- * returns : errno
- */
-
-static int
-ea_write(struct gfs_inode *ip,
- struct gfs_ea_header *ea,
- struct gfs_ea_request *er)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
-
- ea->ea_data_len = cpu_to_gfs32(er->er_data_len);
- ea->ea_name_len = er->er_name_len;
- ea->ea_type = er->er_type;
- ea->ea_pad = 0;
-
- memcpy(GFS_EA2NAME(ea), er->er_name, er->er_name_len);
-
- if (GFS_EAREQ_SIZE_STUFFED(er) <= sdp->sd_jbsize) {
- ea->ea_num_ptrs = 0;
- memcpy(GFS_EA2DATA(ea), er->er_data, er->er_data_len);
- } else {
- uint64_t *dataptr = GFS_EA2DATAPTRS(ea);
- const char *data = er->er_data;
- unsigned int data_len = er->er_data_len;
- unsigned int copy;
- unsigned int x;
-
- ea->ea_num_ptrs = DIV_RU(er->er_data_len, sdp->sd_jbsize);
- for (x = 0; x < ea->ea_num_ptrs; x++) {
- struct buffer_head *bh;
- uint64_t block;
- int error;
-
- error = gfs_metaalloc(ip, &block);
- if (error)
- return error;
-
- error = gfs_dread(ip->i_gl, block,
- DIO_NEW | DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
-
- gfs_trans_add_bh(ip->i_gl, bh);
- gfs_metatype_set(bh, GFS_METATYPE_ED, GFS_FORMAT_ED);
- ip->i_di.di_blocks++;
-
- copy = (data_len > sdp->sd_jbsize) ? sdp->sd_jbsize : data_len;
- memcpy(bh->b_data + sizeof(struct gfs_meta_header),
- data,
- copy);
-
- *dataptr++ = cpu_to_gfs64((uint64_t)bh->b_blocknr);
- data += copy;
- data_len -= copy;
-
- brelse(bh);
- }
-
- gfs_assert_withdraw(sdp, !data_len);
- }
-
- return 0;
-}
-
-typedef int (*ea_skeleton_call_t) (struct gfs_inode *ip,
- struct gfs_ea_request *er,
- void *private);
-/**
- * ea_alloc_skeleton -
- * @ip:
- * @er:
- * @blks:
- * @skeleton_call:
- * @private:
- *
- * Returns: errno
- */
-
-static int
-ea_alloc_skeleton(struct gfs_inode *ip, struct gfs_ea_request *er,
- unsigned int blks,
- ea_skeleton_call_t skeleton_call, void *private)
-{
- struct gfs_alloc *al;
- struct buffer_head *dibh;
- int error;
-
- al = gfs_alloc_get(ip);
-
- error = gfs_quota_lock_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error)
- goto out;
-
- error = gfs_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid);
- if (error)
- goto out_gunlock_q;
-
- al->al_requested_meta = blks;
-
- error = gfs_inplace_reserve(ip);
- if (error)
- goto out_gunlock_q;
-
- /* Trans may require:
- A modified dinode, multiple EA metadata blocks, and all blocks for a RG
- bitmap */
-
- error = gfs_trans_begin(ip->i_sbd,
- 1 + blks + al->al_rgd->rd_ri.ri_length, 1);
- if (error)
- goto out_ipres;
-
- error = skeleton_call(ip, er, private);
- if (error)
- goto out_end_trans;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (!error) {
- if (er->er_mode) {
- ip->i_vnode->i_mode = er->er_mode;
- gfs_inode_attr_out(ip);
- }
- ip->i_di.di_ctime = get_seconds();
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- out_end_trans:
- gfs_trans_end(ip->i_sbd);
-
- out_ipres:
- gfs_inplace_release(ip);
-
- out_gunlock_q:
- gfs_quota_unlock_m(ip);
-
- out:
- gfs_alloc_put(ip);
-
- return error;
-}
-
-/**
- * ea_init_i - initializes a new eattr block
- * @ip:
- * @er:
- * @private:
- *
- * Returns: errno
- */
-
-static int
-ea_init_i(struct gfs_inode *ip,
- struct gfs_ea_request *er,
- void *private)
-{
- struct buffer_head *bh;
- int error;
-
- error = ea_alloc_blk(ip, &bh);
- if (error)
- return error;
-
- ip->i_di.di_eattr = bh->b_blocknr;
- error = ea_write(ip, GFS_EA_BH2FIRST(bh), er);
-
- brelse(bh);
-
- return error;
-}
-
-/**
- * ea_init - initializes a new eattr block
- * @ip:
- * @er:
- *
- * Returns: errno
- */
-
-static int
-ea_init(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- unsigned int jbsize = ip->i_sbd->sd_jbsize;
- unsigned int blks = 1;
-
- if (GFS_EAREQ_SIZE_STUFFED(er) > jbsize)
- blks += DIV_RU(er->er_data_len, jbsize);
-
- return ea_alloc_skeleton(ip, er,
- blks,
- ea_init_i, NULL);
-}
-
-/**
- * ea_split_ea -
- * @ea:
- *
- * Returns: the new ea
- */
-
-static struct gfs_ea_header *
-ea_split_ea(struct gfs_ea_header *ea)
-{
- uint32_t ea_size = GFS_EA_SIZE(ea);
- struct gfs_ea_header *new = (struct gfs_ea_header *)((char *)ea + ea_size);
- uint32_t new_size = GFS_EA_REC_LEN(ea) - ea_size;
- int last = ea->ea_flags & GFS_EAFLAG_LAST;
-
- ea->ea_rec_len = cpu_to_gfs32(ea_size);
- ea->ea_flags ^= last;
-
- new->ea_rec_len = cpu_to_gfs32(new_size);
- new->ea_flags = last;
-
- return new;
-}
-
-/**
- * ea_set_remove_stuffed -
- * @ip:
- * @ea:
- *
- */
-
-static void
-ea_set_remove_stuffed(struct gfs_inode *ip, struct gfs_ea_location *el)
-{
- struct gfs_ea_header *ea = el->el_ea;
- struct gfs_ea_header *prev = el->el_prev;
- uint32_t len;
-
- gfs_trans_add_bh(ip->i_gl, el->el_bh);
-
- if (!prev || !GFS_EA_IS_STUFFED(ea)) {
- ea->ea_type = GFS_EATYPE_UNUSED;
- return;
- } else if (GFS_EA2NEXT(prev) != ea) {
- prev = GFS_EA2NEXT(prev);
- gfs_assert_withdraw(ip->i_sbd, GFS_EA2NEXT(prev) == ea);
- }
-
- len = GFS_EA_REC_LEN(prev) + GFS_EA_REC_LEN(ea);
- prev->ea_rec_len = cpu_to_gfs32(len);
-
- if (GFS_EA_IS_LAST(ea))
- prev->ea_flags |= GFS_EAFLAG_LAST;
-}
-
-struct ea_set {
- int ea_split;
-
- struct gfs_ea_request *es_er;
- struct gfs_ea_location *es_el;
-
- struct buffer_head *es_bh;
- struct gfs_ea_header *es_ea;
-};
-
-/**
- * ea_set_simple_noalloc -
- * @ip:
- * @ea:
- * @es:
- *
- * Returns: errno
- */
-
-static int
-ea_set_simple_noalloc(struct gfs_inode *ip,
- struct buffer_head *bh,
- struct gfs_ea_header *ea,
- struct ea_set *es)
-{
- struct gfs_ea_request *er = es->es_er;
- int error;
-
- error = gfs_trans_begin(ip->i_sbd, 3, 0);
- if (error)
- return error;
-
- gfs_trans_add_bh(ip->i_gl, bh);
-
- if (es->ea_split)
- ea = ea_split_ea(ea);
-
- ea_write(ip, ea, er);
-
- if (es->es_el)
- ea_set_remove_stuffed(ip, es->es_el);
-
- {
- struct buffer_head *dibh;
- error = gfs_get_inode_buffer(ip, &dibh);
- if (!error) {
- if (er->er_mode) {
- ip->i_vnode->i_mode = er->er_mode;
- gfs_inode_attr_out(ip);
- }
- ip->i_di.di_ctime = get_seconds();
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
- }
-
- gfs_trans_end(ip->i_sbd);
-
- return error;
-}
-
-/**
- * ea_set_simple_alloc -
- * @ip:
- * @er:
- * @private:
- *
- * Returns: errno
- */
-
-static int
-ea_set_simple_alloc(struct gfs_inode *ip,
- struct gfs_ea_request *er,
- void *private)
-{
- struct ea_set *es = (struct ea_set *)private;
- struct gfs_ea_header *ea = es->es_ea;
- int error;
-
- gfs_trans_add_bh(ip->i_gl, es->es_bh);
-
- if (es->ea_split)
- ea = ea_split_ea(ea);
-
- error = ea_write(ip, ea, er);
- if (error)
- return error;
-
- if (es->es_el)
- ea_set_remove_stuffed(ip, es->es_el);
-
- return 0;
-}
-
-/**
- * ea_set_simple -
- * @ip:
- * @el:
- *
- * Returns: errno
- */
-
-static int
-ea_set_simple(struct gfs_inode *ip,
- struct buffer_head *bh,
- struct gfs_ea_header *ea,
- struct gfs_ea_header *prev,
- void *private)
-{
- struct ea_set *es = (struct ea_set *)private;
- unsigned int size;
- int stuffed;
- int error;
-
- stuffed = ea_calc_size(ip->i_sbd, es->es_er, &size);
-
- if (ea->ea_type == GFS_EATYPE_UNUSED) {
- if (GFS_EA_REC_LEN(ea) < size)
- return 0;
- if (!GFS_EA_IS_STUFFED(ea)) {
- error = ea_remove_unstuffed(ip, bh, ea, prev, TRUE);
- if (error)
- return error;
- }
- es->ea_split = FALSE;
- } else if (GFS_EA_REC_LEN(ea) - GFS_EA_SIZE(ea) >= size)
- es->ea_split = TRUE;
- else
- return 0;
-
- if (stuffed) {
- error = ea_set_simple_noalloc(ip, bh, ea, es);
- if (error)
- return error;
- } else {
- unsigned int blks;
-
- es->es_bh = bh;
- es->es_ea = ea;
- blks = 2 + DIV_RU(es->es_er->er_data_len,
- ip->i_sbd->sd_jbsize);
-
- error = ea_alloc_skeleton(ip, es->es_er,
- blks,
- ea_set_simple_alloc, es);
- if (error)
- return error;
- }
-
- return 1;
-}
-
-/**
- * ea_set_block -
- * @ip:
- * @er:
- * @private:
- *
- * Returns: errno
- */
-
-static int
-ea_set_block(struct gfs_inode *ip,
- struct gfs_ea_request *er,
- void *private)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *indbh, *newbh;
- uint64_t *eablk;
- int error;
-
- if (ip->i_di.di_flags & GFS_DIF_EA_INDIRECT) {
- uint64_t *end;
-
- error = gfs_dread(ip->i_gl, ip->i_di.di_eattr,
- DIO_START | DIO_WAIT, &indbh);
- if (error)
- return error;
-
- if (gfs_metatype_check(sdp, indbh, GFS_METATYPE_IN)) {
- error = -EIO;
- goto out;
- }
-
- eablk = (uint64_t *)(indbh->b_data + sizeof(struct gfs_indirect));
- end = eablk + sdp->sd_inptrs;
-
- for (; eablk < end; eablk++)
- if (!*eablk)
- break;
-
- if (eablk == end) {
- error = -ENOSPC;
- goto out;
- }
-
- gfs_trans_add_bh(ip->i_gl, indbh);
- } else {
- uint64_t blk;
-
- error = gfs_metaalloc(ip, &blk);
- if (error)
- return error;
-
- error = gfs_dread(ip->i_gl, blk,
- DIO_NEW | DIO_START | DIO_WAIT, &indbh);
- if (error)
- return error;
-
- gfs_trans_add_bh(ip->i_gl, indbh);
- gfs_metatype_set(indbh, GFS_METATYPE_IN, GFS_FORMAT_IN);
- gfs_buffer_clear_tail(indbh, sizeof(struct gfs_meta_header));
-
- eablk = (uint64_t *)(indbh->b_data + sizeof(struct gfs_indirect));
- *eablk = cpu_to_gfs64(ip->i_di.di_eattr);
- ip->i_di.di_eattr = blk;
- ip->i_di.di_flags |= GFS_DIF_EA_INDIRECT;
- ip->i_di.di_blocks++;
-
- eablk++;
- }
-
- error = ea_alloc_blk(ip, &newbh);
- if (error)
- goto out;
-
- *eablk = cpu_to_gfs64((uint64_t)newbh->b_blocknr);
- error = ea_write(ip, GFS_EA_BH2FIRST(newbh), er);
- brelse(newbh);
- if (error)
- goto out;
-
- if (private)
- ea_set_remove_stuffed(ip, (struct gfs_ea_location *)private);
-
- out:
- brelse(indbh);
-
- return error;
-}
-
-/**
- * ea_set_i -
- * @ip:
- * @el:
- *
- * Returns: errno
- */
-
-static int
-ea_set_i(struct gfs_inode *ip,
- struct gfs_ea_request *er,
- struct gfs_ea_location *el)
-{
- {
- struct ea_set es;
- int error;
-
- memset(&es, 0, sizeof(struct ea_set));
- es.es_er = er;
- es.es_el = el;
-
- error = ea_foreach(ip, ea_set_simple, &es);
- if (error > 0)
- return 0;
- if (error)
- return error;
- }
- {
- unsigned int blks = 2;
- if (!(ip->i_di.di_flags & GFS_DIF_EA_INDIRECT))
- blks++;
- if (GFS_EAREQ_SIZE_STUFFED(er) > ip->i_sbd->sd_jbsize)
- blks += DIV_RU(er->er_data_len,
- ip->i_sbd->sd_jbsize);
-
- return ea_alloc_skeleton(ip, er, blks, ea_set_block, el);
- }
-}
-
-/**
- * ea_set_remove_unstuffed -
- * @ip:
- * @el:
- *
- * Returns: errno
- */
-
-static int
-ea_set_remove_unstuffed(struct gfs_inode *ip, struct gfs_ea_location *el)
-{
- if (el->el_prev && GFS_EA2NEXT(el->el_prev) != el->el_ea) {
- el->el_prev = GFS_EA2NEXT(el->el_prev);
- gfs_assert_withdraw(ip->i_sbd,
- GFS_EA2NEXT(el->el_prev) == el->el_ea);
- }
-
- return ea_remove_unstuffed(ip, el->el_bh, el->el_ea, el->el_prev, FALSE);
-}
-
-/**
- * gfs_ea_set_i -
- * @ip:
- * @er:
- *
- * Returns: errno
- */
-
-int
-gfs_ea_set_i(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- struct gfs_ea_location el;
- int error;
-
- if (!ip->i_di.di_eattr) {
- if (er->er_flags & XATTR_REPLACE)
- return -ENODATA;
- return ea_init(ip, er);
- }
-
- error = gfs_ea_find(ip, er, &el);
- if (error)
- return error;
-
- if (el.el_ea) {
- if (IS_APPEND(ip->i_vnode)) {
- brelse(el.el_bh);
- return -EPERM;
- }
-
- error = -EEXIST;
- if (!(er->er_flags & XATTR_CREATE)) {
- int unstuffed = !GFS_EA_IS_STUFFED(el.el_ea);
- error = ea_set_i(ip, er, &el);
- if (!error && unstuffed)
- ea_set_remove_unstuffed(ip, &el);
- }
-
- brelse(el.el_bh);
- } else {
- error = -ENODATA;
- if (!(er->er_flags & XATTR_REPLACE))
- error = ea_set_i(ip, er, NULL);
- }
-
- return error;
-}
-
-/**
- * gfs_ea_set -
- * @ip:
- * @er:
- *
- * Returns: errno
- */
-
-int
-gfs_ea_set(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- struct gfs_holder i_gh;
- int error;
-
- if (!er->er_name_len ||
- er->er_name_len > GFS_EA_MAX_NAME_LEN)
- return -EINVAL;
- if (!er->er_data || !er->er_data_len) {
- er->er_data = NULL;
- er->er_data_len = 0;
- }
- error = gfs_ea_check_size(ip->i_sbd, er);
- if (error)
- return error;
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
- if (error)
- return error;
-
- if (IS_IMMUTABLE(ip->i_vnode))
- error = -EPERM;
- else
- error = gfs_ea_ops[er->er_type]->eo_set(ip, er);
-
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * ea_remove_stuffed -
- * @ip:
- * @el:
- * @mode:
- *
- * Returns: errno
- */
-
-static int
-ea_remove_stuffed(struct gfs_inode *ip,
- struct gfs_ea_location *el)
-{
- struct gfs_ea_header *ea = el->el_ea;
- struct gfs_ea_header *prev = el->el_prev;
- int error;
-
- error = gfs_trans_begin(ip->i_sbd, 2, 0);
- if (error)
- return error;
-
- gfs_trans_add_bh(ip->i_gl, el->el_bh);
-
- if (prev) {
- uint32_t len;
-
- len = GFS_EA_REC_LEN(prev) + GFS_EA_REC_LEN(ea);
- prev->ea_rec_len = cpu_to_gfs32(len);
-
- if (GFS_EA_IS_LAST(ea))
- prev->ea_flags |= GFS_EAFLAG_LAST;
- } else
- ea->ea_type = GFS_EATYPE_UNUSED;
-
- {
- struct buffer_head *dibh;
- error = gfs_get_inode_buffer(ip, &dibh);
- if (!error) {
- ip->i_di.di_ctime = get_seconds();
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
- }
-
- gfs_trans_end(ip->i_sbd);
-
- return error;
-}
-
-/**
- * gfs_ea_remove_i -
- * @ip:
- * @er:
- *
- * Returns: errno
- */
-
-int
-gfs_ea_remove_i(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- struct gfs_ea_location el;
- int error;
-
- if (!ip->i_di.di_eattr)
- return -ENODATA;
-
- error = gfs_ea_find(ip, er, &el);
- if (error)
- return error;
- if (!el.el_ea)
- return -ENODATA;
-
- if (GFS_EA_IS_STUFFED(el.el_ea))
- error = ea_remove_stuffed(ip, &el);
- else
- error = ea_remove_unstuffed(ip, el.el_bh, el.el_ea, el.el_prev, FALSE);
-
- brelse(el.el_bh);
-
- return error;
-}
-
-/**
- * gfs_ea_remove - sets (or creates or replaces) an extended attribute
- * @ip: pointer to the inode of the target file
- * @er: request information
- *
- * Returns: errno
- */
-
-int
-gfs_ea_remove(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- struct gfs_holder i_gh;
- int error;
-
- if (!er->er_name_len ||
- er->er_name_len > GFS_EA_MAX_NAME_LEN)
- return -EINVAL;
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
- if (error)
- return error;
-
- if (IS_IMMUTABLE(ip->i_vnode) || IS_APPEND(ip->i_vnode))
- error = -EPERM;
- else
- error = gfs_ea_ops[er->er_type]->eo_remove(ip, er);
-
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gfs_ea_acl_init -
- * @ip:
- * @er:
- *
- * Returns: errno
- */
-
-int gfs_ea_acl_init(struct gfs_inode *ip, struct gfs_ea_request *er)
-{
- struct buffer_head *bh;
- struct gfs_ea_header *ea;
- unsigned int size;
- struct buffer_head *dibh;
- int error;
-
- if (!ip->i_di.di_eattr)
- return ea_init_i(ip, er, NULL);
-
- ea_calc_size(ip->i_sbd, er, &size);
-
- error = gfs_dread(ip->i_gl, ip->i_di.di_eattr,
- DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
-
- if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_EA)) {
- brelse(bh);
- return -EIO;
- }
-
- ea = GFS_EA_BH2FIRST(bh);
- if (GFS_EA_REC_LEN(ea) - GFS_EA_SIZE(ea) >= size) {
- ea = ea_split_ea(ea);
- ea_write(ip, ea, er);
- brelse(bh);
- return 0;
- }
-
- brelse(bh);
-
- error = ea_set_block(ip, er, NULL);
- gfs_assert_withdraw(ip->i_sbd, error != -ENOSPC);
- if (error)
- return error;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- return error;
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- return error;
-}
-
-/**
- * ea_acl_chmod_unstuffed -
- * @ip:
- * @ea:
- * @data:
- *
- * Returns: errno
- */
-
-static int ea_acl_chmod_unstuffed(struct gfs_inode *ip,
- struct gfs_ea_header *ea, char *data,
- int *trans)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head **bh;
- unsigned int amount = GFS_EA_DATA_LEN(ea);
- unsigned int nptrs = DIV_RU(amount, sdp->sd_jbsize);
- uint64_t *dataptrs = GFS_EA2DATAPTRS(ea);
- unsigned int x;
- int error;
-
- bh = kmalloc(nptrs * sizeof(struct buffer_head *), GFP_NOFS);
- if (!bh)
- return -ENOMEM;
-
- if (get_transaction == NULL) {
- error = gfs_trans_begin(sdp, 1 + nptrs, 0);
- if (error)
- goto out;
- *trans = 1;
- }
-
- for (x = 0; x < nptrs; x++) {
- error = gfs_dread(ip->i_gl, gfs64_to_cpu(*dataptrs),
- DIO_START, bh + x);
- if (error) {
- while (x--)
- brelse(bh[x]);
- goto fail;
- }
- dataptrs++;
- }
-
- for (x = 0; x < nptrs; x++) {
- error = gfs_dreread(sdp, bh[x], DIO_WAIT);
- if (error) {
- for (; x < nptrs; x++)
- brelse(bh[x]);
- goto fail;
- }
- if (gfs_metatype_check2(sdp, bh[x],
- GFS_METATYPE_ED, GFS_METATYPE_EA)) {
- for (; x < nptrs; x++)
- brelse(bh[x]);
- error = -EIO;
- goto fail;
- }
-
- gfs_trans_add_bh(ip->i_gl, bh[x]);
-
- memcpy(bh[x]->b_data + sizeof(struct gfs_meta_header),
- data,
- (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize);
-
- amount -= sdp->sd_jbsize;
- data += sdp->sd_jbsize;
-
- brelse(bh[x]);
- }
-
-out:
- kfree(bh);
- return error;
-
-fail:
- gfs_trans_end(sdp);
- *trans = 0;
- kfree(bh);
- return error;
-}
-
-/**
- * gfs_ea_acl_chmod -
- * @ip:
- * @el:
- * @attr:
- * @data:
- *
- * Returns: errno
- */
-
-int gfs_ea_acl_chmod(struct gfs_inode *ip, struct gfs_ea_location *el,
- struct iattr *attr, char *data)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *dibh;
- int error;
- int trans = 0;
-
- if (GFS_EA_IS_STUFFED(el->el_ea)) {
- if (get_transaction == NULL) {
- error = gfs_trans_begin(ip->i_sbd, 2, 0);
- if (error)
- return error;
- trans = 1;
- }
-
- gfs_trans_add_bh(ip->i_gl, el->el_bh);
- memcpy(GFS_EA2DATA(el->el_ea), data,
- GFS_EA_DATA_LEN(el->el_ea));
- } else {
- error = ea_acl_chmod_unstuffed(ip, el->el_ea, data, &trans);
- }
-
- if (error)
- return error;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (!error) {
- error = inode_setattr(ip->i_vnode, attr);
- gfs_assert_warn(ip->i_sbd, !error);
- gfs_inode_attr_out(ip);
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- if (trans)
- gfs_trans_end(ip->i_sbd);
-
- return error;
-}
-
-/**
- * ea_dealloc_indirect -
- * @ip:
- *
- * Returns: errno
- */
-
-static int
-ea_dealloc_indirect(struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_rgrp_list rlist;
- struct buffer_head *indbh, *dibh;
- uint64_t *eablk, *end;
- unsigned int rg_blocks = 0;
- uint64_t bstart = 0;
- unsigned int blen = 0;
- unsigned int x;
- int error;
-
- memset(&rlist, 0, sizeof(struct gfs_rgrp_list));
-
- error = gfs_dread(ip->i_gl, ip->i_di.di_eattr,
- DIO_START | DIO_WAIT, &indbh);
- if (error)
- return error;
-
- if (gfs_metatype_check(sdp, indbh, GFS_METATYPE_IN)) {
- error = -EIO;
- goto out;
- }
-
- eablk = (uint64_t *)(indbh->b_data + sizeof(struct gfs_indirect));
- end = eablk + sdp->sd_inptrs;
-
- for (; eablk < end; eablk++) {
- uint64_t bn;
-
- if (!*eablk)
- break;
- bn = gfs64_to_cpu(*eablk);
-
- if (bstart + blen == bn)
- blen++;
- else {
- if (bstart)
- gfs_rlist_add(sdp, &rlist, bstart);
- bstart = bn;
- blen = 1;
- }
- }
- if (bstart)
- gfs_rlist_add(sdp, &rlist, bstart);
- else
- goto out;
-
- gfs_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
-
- for (x = 0; x < rlist.rl_rgrps; x++) {
- struct gfs_rgrpd *rgd;
- rgd = get_gl2rgd(rlist.rl_ghs[x].gh_gl);
- rg_blocks += rgd->rd_ri.ri_length;
- }
-
- error = gfs_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
- if (error)
- goto out_rlist_free;
-
- error = gfs_trans_begin(sdp, 2 + rg_blocks, 1);
- if (error)
- goto out_gunlock;
-
- gfs_trans_add_bh(ip->i_gl, indbh);
-
- eablk = (uint64_t *)(indbh->b_data + sizeof(struct gfs_indirect));
- bstart = 0;
- blen = 0;
-
- for (; eablk < end; eablk++) {
- uint64_t bn;
-
- if (!*eablk)
- break;
- bn = gfs64_to_cpu(*eablk);
-
- if (bstart + blen == bn)
- blen++;
- else {
- if (bstart)
- gfs_metafree(ip, bstart, blen);
- bstart = bn;
- blen = 1;
- }
-
- *eablk = 0;
- if (!ip->i_di.di_blocks)
- gfs_consist_inode(ip);
- ip->i_di.di_blocks--;
- }
- if (bstart)
- gfs_metafree(ip, bstart, blen);
-
- ip->i_di.di_flags &= ~GFS_DIF_EA_INDIRECT;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (!error) {
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- gfs_trans_end(sdp);
-
- out_gunlock:
- gfs_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs);
-
- out_rlist_free:
- gfs_rlist_free(&rlist);
-
- out:
- brelse(indbh);
-
- return error;
-}
-
-/**
- * ea_dealloc_block -
- * @ip:
- *
- * Returns: errno
- */
-
-static int
-ea_dealloc_block(struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = ip->i_alloc;
- struct gfs_rgrpd *rgd;
- struct buffer_head *dibh;
- int error;
-
- rgd = gfs_blk2rgrpd(sdp, ip->i_di.di_eattr);
- if (!rgd) {
- gfs_consist_inode(ip);
- return -EIO;
- }
-
- error = gfs_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &al->al_rgd_gh);
- if (error)
- return error;
-
- error = gfs_trans_begin(sdp, 1 + rgd->rd_ri.ri_length, 1);
- if (error)
- goto out_gunlock;
-
- gfs_metafree(ip, ip->i_di.di_eattr, 1);
-
- ip->i_di.di_eattr = 0;
- if (!ip->i_di.di_blocks)
- gfs_consist_inode(ip);
- ip->i_di.di_blocks--;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (!error) {
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- gfs_trans_end(sdp);
-
- out_gunlock:
- gfs_glock_dq_uninit(&al->al_rgd_gh);
-
- return error;
-}
-
-/**
- * gfs_ea_dealloc - deallocate the extended attribute fork
- * @ip: the inode
- *
- * Returns: errno
- */
-
-int
-gfs_ea_dealloc(struct gfs_inode *ip)
-{
- struct gfs_alloc *al;
- int error;
-
- al = gfs_alloc_get(ip);
-
- error = gfs_quota_hold_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error)
- goto out_alloc;
-
- error = gfs_rindex_hold(ip->i_sbd, &al->al_ri_gh);
- if (error)
- goto out_quota;
-
- error = ea_foreach(ip, ea_dealloc_unstuffed, NULL);
- if (error)
- goto out_rindex;
-
- if (ip->i_di.di_flags & GFS_DIF_EA_INDIRECT) {
- error = ea_dealloc_indirect(ip);
- if (error)
- goto out_rindex;
- }
-
- error = ea_dealloc_block(ip);
-
- out_rindex:
- gfs_glock_dq_uninit(&al->al_ri_gh);
-
- out_quota:
- gfs_quota_unhold_m(ip);
-
- out_alloc:
- gfs_alloc_put(ip);
-
- return error;
-}
-
-/**
- * gfs_get_eattr_meta - return all the eattr blocks of a file
- * @dip: the directory
- * @ub: the structure representing the user buffer to copy to
- *
- * Returns: errno
- */
-
-int
-gfs_get_eattr_meta(struct gfs_inode *ip, struct gfs_user_buffer *ub)
-{
- struct buffer_head *bh;
- int error;
-
- error = gfs_dread(ip->i_gl, ip->i_di.di_eattr,
- DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
-
- gfs_add_bh_to_ub(ub, bh);
-
- if (ip->i_di.di_flags & GFS_DIF_EA_INDIRECT) {
- struct buffer_head *eabh;
- uint64_t *eablk, *end;
-
- if (gfs_metatype_check(ip->i_sbd, bh, GFS_METATYPE_IN)) {
- error = -EIO;
- goto out;
- }
-
- eablk = (uint64_t *)(bh->b_data + sizeof(struct gfs_indirect));
- end = eablk + ip->i_sbd->sd_inptrs;
-
- for (; eablk < end; eablk++) {
- uint64_t bn;
-
- if (!*eablk)
- break;
- bn = gfs64_to_cpu(*eablk);
-
- error = gfs_dread(ip->i_gl, bn,
- DIO_START | DIO_WAIT, &eabh);
- if (error)
- break;
- gfs_add_bh_to_ub(ub, eabh);
- brelse(eabh);
- if (error)
- break;
- }
- }
-
- out:
- brelse(bh);
-
- return error;
-}
diff --git a/gfs-kernel/src/gfs/eattr.h b/gfs-kernel/src/gfs/eattr.h
deleted file mode 100644
index b370c2a..0000000
--- a/gfs-kernel/src/gfs/eattr.h
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef __EATTR_DOT_H__
-#define __EATTR_DOT_H__
-
-#define GFS_EA_REC_LEN(ea) gfs32_to_cpu((ea)->ea_rec_len)
-#define GFS_EA_DATA_LEN(ea) gfs32_to_cpu((ea)->ea_data_len)
-
-#define GFS_EA_SIZE(ea) \
-MAKE_MULT8(sizeof(struct gfs_ea_header) + \
- (ea)->ea_name_len + \
- ((GFS_EA_IS_STUFFED(ea)) ? \
- GFS_EA_DATA_LEN(ea) : \
- (sizeof(uint64_t) * (ea)->ea_num_ptrs)))
-#define GFS_EA_STRLEN(ea) \
-((((ea)->ea_type == GFS_EATYPE_USR) ? 5 : 7) + \
- (ea)->ea_name_len + 1)
-
-#define GFS_EA_IS_STUFFED(ea) (!(ea)->ea_num_ptrs)
-#define GFS_EA_IS_LAST(ea) ((ea)->ea_flags & GFS_EAFLAG_LAST)
-
-#define GFS_EAREQ_SIZE_STUFFED(er) \
-MAKE_MULT8(sizeof(struct gfs_ea_header) + \
- (er)->er_name_len + (er)->er_data_len)
-#define GFS_EAREQ_SIZE_UNSTUFFED(sdp, er) \
-MAKE_MULT8(sizeof(struct gfs_ea_header) + \
- (er)->er_name_len + \
- sizeof(uint64_t) * DIV_RU((er)->er_data_len, (sdp)->sd_jbsize))
-
-#define GFS_EA2NAME(ea) ((char *)((struct gfs_ea_header *)(ea) + 1))
-#define GFS_EA2DATA(ea) (GFS_EA2NAME(ea) + (ea)->ea_name_len)
-#define GFS_EA2DATAPTRS(ea) \
-((uint64_t *)(GFS_EA2NAME(ea) + MAKE_MULT8((ea)->ea_name_len)))
-#define GFS_EA2NEXT(ea) \
-((struct gfs_ea_header *)((char *)(ea) + GFS_EA_REC_LEN(ea)))
-#define GFS_EA_BH2FIRST(bh) \
-((struct gfs_ea_header *)((bh)->b_data + \
- sizeof(struct gfs_meta_header)))
-
-struct gfs_ea_request {
- char *er_name;
- char *er_data;
- unsigned int er_name_len;
- unsigned int er_data_len;
- unsigned int er_type; /* GFS_EATYPE_... */
- int er_flags;
- mode_t er_mode;
-};
-
-struct gfs_ea_location {
- struct buffer_head *el_bh;
- struct gfs_ea_header *el_ea;
- struct gfs_ea_header *el_prev;
-};
-
-static inline unsigned int
-gfs_ea_strlen(struct gfs_ea_header *ea)
-{
- switch (ea->ea_type) {
- case GFS_EATYPE_USR:
- return (5 + (ea->ea_name_len + 1));
- case GFS_EATYPE_SYS:
- return (7 + (ea->ea_name_len + 1));
- case GFS_EATYPE_SECURITY:
- return (9 + (ea->ea_name_len + 1));
- default:
- return (0);
- }
-}
-
-int gfs_ea_repack(struct gfs_inode *ip);
-
-int gfs_ea_get_i(struct gfs_inode *ip, struct gfs_ea_request *er);
-int gfs_ea_set_i(struct gfs_inode *ip, struct gfs_ea_request *er);
-int gfs_ea_remove_i(struct gfs_inode *ip, struct gfs_ea_request *er);
-
-int gfs_ea_list(struct gfs_inode *ip, struct gfs_ea_request *er);
-int gfs_ea_get(struct gfs_inode *ip, struct gfs_ea_request *er);
-int gfs_ea_set(struct gfs_inode *ip, struct gfs_ea_request *er);
-int gfs_ea_remove(struct gfs_inode *ip, struct gfs_ea_request *er);
-
-int gfs_ea_dealloc(struct gfs_inode *ip);
-
-int gfs_get_eattr_meta(struct gfs_inode *ip, struct gfs_user_buffer *ub);
-
-/* Exported to acl.c */
-
-int gfs_ea_check_size(struct gfs_sbd *sdp, struct gfs_ea_request *er);
-int gfs_ea_find(struct gfs_inode *ip,
- struct gfs_ea_request *er,
- struct gfs_ea_location *el);
-int gfs_ea_get_copy(struct gfs_inode *ip,
- struct gfs_ea_location *el,
- char *data);
-int gfs_ea_acl_init(struct gfs_inode *ip, struct gfs_ea_request *er);
-int gfs_ea_acl_chmod(struct gfs_inode *ip, struct gfs_ea_location *el,
- struct iattr *attr, char *data);
-
-#endif /* __EATTR_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/file.c b/gfs-kernel/src/gfs/file.c
deleted file mode 100644
index 3f8e5b9..0000000
--- a/gfs-kernel/src/gfs/file.c
+++ /dev/null
@@ -1,437 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <asm/uaccess.h>
-
-#include "gfs.h"
-#include "bmap.h"
-#include "dio.h"
-#include "file.h"
-#include "inode.h"
-#include "trans.h"
-
-/**
- * gfs_copy2mem - Trivial copy function for gfs_readi()
- * @bh: The buffer to copy from, or NULL meaning zero the buffer
- * @buf: The buffer to copy/zero
- * @offset: The offset in the buffer to copy from
- * @size: The amount of data to copy/zero
- *
- * Returns: errno
- */
-
-int
-gfs_copy2mem(struct buffer_head *bh, void **buf, unsigned int offset,
- unsigned int size)
-{
- char **p = (char **)buf;
-
- if (bh)
- memcpy(*p, bh->b_data + offset, size);
- else
- memset(*p, 0, size);
-
- *p += size;
-
- return 0;
-}
-
-/**
- * gfs_copy2user - Copy data to user space
- * @bh: The buffer
- * @buf: The destination of the data
- * @offset: The offset into the buffer
- * @size: The amount of data to copy
- *
- * Returns: errno
- */
-
-int
-gfs_copy2user(struct buffer_head *bh, void **buf,
- unsigned int offset, unsigned int size)
-{
- char **p = (char **)buf;
- int error;
-
- if (bh)
- error = copy_to_user(*p, bh->b_data + offset, size);
- else
- error = clear_user(*p, size);
-
- if (error)
- error = -EFAULT;
- else
- *p += size;
-
- return error;
-}
-
-/**
- * gfs_readi - Read a file
- * @ip: The GFS Inode
- * @buf: The buffer to place result into
- * @offset: File offset to begin reading from
- * @size: Amount of data to transfer
- * @copy_fn: Function to actually perform the copy
- *
- * The @copy_fn only copies a maximum of a single block at once so
- * we are safe calling it with int arguments. It is done so that
- * we don't needlessly put 64bit arguments on the stack and it
- * also makes the code in the @copy_fn nicer too.
- *
- * Returns: The amount of data actually copied or the error
- */
-
-int
-gfs_readi(struct gfs_inode *ip, void *buf,
- uint64_t offset, unsigned int size,
- read_copy_fn_t copy_fn)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *bh;
- uint64_t lblock, dblock;
- unsigned int o;
- uint32_t extlen = 0;
- unsigned int amount;
- int not_new = 0;
- int journaled = gfs_is_jdata(ip);
- int copied = 0;
- int error = 0;
-
- if (offset >= ip->i_di.di_size)
- return 0;
-
- if ((offset + size) > ip->i_di.di_size)
- size = ip->i_di.di_size - offset;
-
- if (!size)
- return 0;
-
- if (journaled) {
- lblock = offset;
- o = do_div(lblock, sdp->sd_jbsize);
- } else {
- lblock = offset >> sdp->sd_sb.sb_bsize_shift;
- o = offset & (sdp->sd_sb.sb_bsize - 1);
- }
-
- if (gfs_is_stuffed(ip))
- o += sizeof(struct gfs_dinode);
- else if (journaled)
- o += sizeof(struct gfs_meta_header);
-
- while (copied < size) {
- amount = size - copied;
- if (amount > sdp->sd_sb.sb_bsize - o)
- amount = sdp->sd_sb.sb_bsize - o;
-
- if (!extlen) {
- if (!gfs_is_stuffed(ip)) {
- error = gfs_block_map(ip, lblock, ¬_new,
- &dblock, &extlen);
- if (error)
- goto fail;
- } else if (!lblock) {
- dblock = ip->i_num.no_addr;
- extlen = 1;
- } else
- dblock = 0;
- }
-
- if (extlen > 1)
- gfs_start_ra(ip->i_gl, dblock, extlen);
-
- if (dblock) {
- error = gfs_get_data_buffer(ip, dblock, not_new, &bh);
- if (error)
- goto fail;
-
- dblock++;
- extlen--;
- } else
- bh = NULL;
-
- error = copy_fn(bh, &buf, o, amount);
- if (bh)
- brelse(bh);
- if (error)
- goto fail;
-
- copied += amount;
- lblock++;
-
- o = (journaled) ? sizeof(struct gfs_meta_header) : 0;
- }
-
- return copied;
-
- fail:
- return (copied) ? copied : error;
-}
-
-/**
- * gfs_copy_from_mem - Trivial copy function for gfs_writei()
- * @ip: The file to write to
- * @bh: The buffer to copy to or clear
- * @buf: The buffer to copy from
- * @offset: The offset in the buffer to write to
- * @size: The amount of data to write
- * @new: Flag indicating that remaining space in the buffer should be zeroed
- *
- * Returns: errno
- */
-
-int
-gfs_copy_from_mem(struct gfs_inode *ip, struct buffer_head *bh, void **buf,
- unsigned int offset, unsigned int size, int new)
-{
- char **p = (char **)buf;
- int error = 0;
-
- /* The dinode block always gets journaled */
- if (bh->b_blocknr == ip->i_num.no_addr) {
- if (gfs_assert_warn(ip->i_sbd, !new))
- return -EIO;
- gfs_trans_add_bh(ip->i_gl, bh);
- memcpy(bh->b_data + offset, *p, size);
-
- /* Data blocks for journaled files get written added to the journal */
- } else if (gfs_is_jdata(ip)) {
- gfs_trans_add_bh(ip->i_gl, bh);
- memcpy(bh->b_data + offset, *p, size);
- if (new)
- gfs_buffer_clear_ends(bh, offset, size, TRUE);
-
- /* Non-journaled data blocks get written to in-place disk blocks */
- } else {
- memcpy(bh->b_data + offset, *p, size);
- if (new)
- gfs_buffer_clear_ends(bh, offset, size, FALSE);
- error = gfs_dwrite(ip->i_sbd, bh, DIO_DIRTY);
- }
-
- if (!error)
- *p += size;
-
- return error;
-}
-
-/**
- * gfs_copy_from_user - Copy bytes from user space for gfs_writei()
- * @ip: The file to write to
- * @bh: The buffer to copy to or clear
- * @buf: The buffer to copy from
- * @offset: The offset in the buffer to write to
- * @size: The amount of data to write
- * @new: Flag indicating that remaining space in the buffer should be zeroed
- *
- * Returns: errno
- */
-
-int
-gfs_copy_from_user(struct gfs_inode *ip, struct buffer_head *bh, void **buf,
- unsigned int offset, unsigned int size, int new)
-{
- char **p = (char **)buf;
- int error = 0;
-
- /* the dinode block always gets journaled */
- if (bh->b_blocknr == ip->i_num.no_addr) {
- if (gfs_assert_warn(ip->i_sbd, !new))
- return -EIO;
- gfs_trans_add_bh(ip->i_gl, bh);
- if (copy_from_user(bh->b_data + offset, *p, size))
- error = -EFAULT;
-
- /* Data blocks for journaled files get written added to the journal */
- } else if (gfs_is_jdata(ip)) {
- gfs_trans_add_bh(ip->i_gl, bh);
- if (copy_from_user(bh->b_data + offset, *p, size))
- error = -EFAULT;
- if (new) {
- gfs_buffer_clear_ends(bh, offset, size, TRUE);
- if (error)
- memset(bh->b_data + offset, 0, size);
- }
-
- /* non-journaled data blocks get written to in-place disk blocks */
- } else {
- if (copy_from_user(bh->b_data + offset, *p, size))
- error = -EFAULT;
- if (error) {
- if (new)
- gfs_buffer_clear(bh);
- gfs_dwrite(ip->i_sbd, bh, DIO_DIRTY);
- } else {
- if (new)
- gfs_buffer_clear_ends(bh, offset, size, FALSE);
- error = gfs_dwrite(ip->i_sbd, bh, DIO_DIRTY);
- }
- }
-
- if (!error)
- *p += size;
-
- return error;
-}
-
-/**
- * gfs_writei - Write bytes to a file
- * @ip: The GFS inode
- * @buf: The buffer containing information to be written
- * @offset: The file offset to start writing at
- * @size: The amount of data to write
- * @copy_fn: Function to do the actual copying
- *
- * Returns: The number of bytes correctly written or error code
- */
-
-int
-gfs_writei(struct gfs_inode *ip, void *buf,
- uint64_t offset, unsigned int size,
- write_copy_fn_t copy_fn,
- struct kiocb *iocb)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct buffer_head *dibh, *bh;
- uint64_t lblock, dblock;
- unsigned int o;
- uint32_t extlen = 0;
- unsigned int amount;
- int new;
- int journaled = gfs_is_jdata(ip);
- const uint64_t start = offset;
- int copied = 0;
- int error = 0;
-
- if (!size)
- return 0;
-
- if (gfs_is_stuffed(ip) &&
- ((start + size) > (sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode)))) {
- error = gfs_unstuff_dinode(ip, gfs_unstuffer_async, NULL);
- if (error)
- return error;
- }
-
- if (journaled) {
- lblock = offset;
- o = do_div(lblock, sdp->sd_jbsize);
- } else {
- lblock = offset >> sdp->sd_sb.sb_bsize_shift;
- o = offset & (sdp->sd_sb.sb_bsize - 1);
- }
-
- if (gfs_is_stuffed(ip))
- o += sizeof(struct gfs_dinode);
- else if (journaled)
- o += sizeof(struct gfs_meta_header);
-
- while (copied < size) {
- amount = size - copied;
- if (amount > sdp->sd_sb.sb_bsize - o)
- amount = sdp->sd_sb.sb_bsize - o;
-
- if (!extlen) {
- if (!gfs_is_stuffed(ip)) {
- new = TRUE;
- error = gfs_block_map(ip, lblock, &new, &dblock, &extlen);
- if (error)
- goto fail;
- } else {
- new = FALSE;
- dblock = ip->i_num.no_addr;
- extlen = 1;
- }
- }
-
- if (journaled && extlen > 1)
- gfs_start_ra(ip->i_gl, dblock, extlen);
-
- error = gfs_get_data_buffer(ip, dblock,
- (amount == sdp->sd_sb.sb_bsize) ? TRUE : new,
- &bh);
- if (error)
- goto fail;
-
- error = copy_fn(ip, bh, &buf, o, amount, new);
- brelse(bh);
- if (error)
- goto fail;
-
- copied += amount;
- lblock++;
- dblock++;
- extlen--;
-
- o = (journaled) ? sizeof(struct gfs_meta_header) : 0;
- }
-
- out:
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- return error;
-
- if (ip->i_di.di_size < start + copied)
- ip->i_di.di_size = start + copied;
- ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
-
- return copied;
-
- fail:
- if (copied)
- goto out;
- return error;
-}
-
-/*
- * gfs_zero_blocks - zero out disk blocks via gfs_writei()
- * @ip: The file to write to
- * @bh: The buffer to clear
- * @buf: The pseudo buffer (not used but added to keep interface unchanged)
- * @offset: The offset in the buffer to write to
- * @size: The size to zero out
- * @new: Flag indicating that remaining space in the buffer should be zeroed
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-int
-gfs_zero_blocks(struct gfs_inode *ip, struct buffer_head *bh, void **buf,
- unsigned int offset, unsigned int size, int new)
-{
- int error = 0;
-
- /* The dinode block always gets journaled */
- if (bh->b_blocknr == ip->i_num.no_addr) {
- if (gfs_assert_warn(ip->i_sbd, !new))
- return -EIO;
- gfs_trans_add_bh(ip->i_gl, bh);
- memset((bh)->b_data + offset, 0, size);
-
- /* Data blocks for journaled files get written added to the journal */
- } else if (gfs_is_jdata(ip)) {
- gfs_trans_add_bh(ip->i_gl, bh);
- memset((bh)->b_data + offset, 0, size);
- if (new)
- gfs_buffer_clear_ends(bh, offset, size, TRUE);
-
- /* Non-journaled data blocks get written to in-place disk blocks */
- } else {
- memset((bh)->b_data + offset, 0, size);
- if (new)
- gfs_buffer_clear_ends(bh, offset, size, FALSE);
- error = gfs_dwrite(ip->i_sbd, bh, DIO_DIRTY);
- }
-
- return error;
-}
-
diff --git a/gfs-kernel/src/gfs/file.h b/gfs-kernel/src/gfs/file.h
deleted file mode 100644
index ef19dc1..0000000
--- a/gfs-kernel/src/gfs/file.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef __FILE_DOT_H__
-#define __FILE_DOT_H__
-
-typedef int (*read_copy_fn_t) (struct buffer_head *bh, void **buf,
- unsigned int offset, unsigned int size);
-typedef int (*write_copy_fn_t) (struct gfs_inode *ip, struct buffer_head *bh,
- void **buf, unsigned int offset,
- unsigned int size, int new);
-
-int gfs_copy2mem(struct buffer_head *bh, void **buf,
- unsigned int offset, unsigned int size);
-int gfs_copy2user(struct buffer_head *bh, void **buf,
- unsigned int offset, unsigned int size);
-int gfs_readi(struct gfs_inode *ip, void *buf, uint64_t offset,
- unsigned int size, read_copy_fn_t copy_fn);
-
-int gfs_copy_from_mem(struct gfs_inode *ip, struct buffer_head *bh, void **buf,
- unsigned int offset, unsigned int size, int new);
-int gfs_copy_from_user(struct gfs_inode *ip, struct buffer_head *bh, void **buf,
- unsigned int offset, unsigned int size, int new);
-int gfs_writei(struct gfs_inode *ip, void *buf, uint64_t offset,
- unsigned int size, write_copy_fn_t copy_fn,
- struct kiocb *iocb);
-
-int gfs_zero_blocks(struct gfs_inode *ip, struct buffer_head *bh, void **buf,
- unsigned int offset, unsigned int size, int new);
-
-static __inline__ int
-gfs_internal_read(struct gfs_inode *ip, char *buf, uint64_t offset,
- unsigned int size)
-{
- return gfs_readi(ip, buf, offset, size, gfs_copy2mem);
-}
-
-static __inline__ int
-gfs_internal_write(struct gfs_inode *ip, char *buf, uint64_t offset,
- unsigned int size)
-{
- return gfs_writei(ip, buf, offset, size, gfs_copy_from_mem, NULL);
-}
-
-#endif /* __FILE_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/fixed_div64.h b/gfs-kernel/src/gfs/fixed_div64.h
deleted file mode 100644
index 7cc9e71..0000000
--- a/gfs-kernel/src/gfs/fixed_div64.h
+++ /dev/null
@@ -1,107 +0,0 @@
-#ifndef __FIXED_DIV64_DOT_H__
-#define __FIXED_DIV64_DOT_H__
-
-#include <asm/div64.h>
-
-#if defined __i386__
-/* For ia32 we need to pull some tricks to get past various versions
- * of the compiler which do not like us using do_div in the middle
- * of large functions.
- */
-static inline __u32 fixed_div64_do_div(void *a, __u32 b, int n)
-{
- __u32 mod;
-
- switch (n) {
- case 4:
- mod = *(__u32 *)a % b;
- *(__u32 *)a = *(__u32 *)a / b;
- return mod;
- case 8:
- {
- unsigned long __upper, __low, __high, __mod;
- __u64 c = *(__u64 *)a;
- __upper = __high = c >> 32;
- __low = c;
- if (__high) {
- __upper = __high % (b);
- __high = __high / (b);
- }
- asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (b), "0" (__low), "1" (__upper));
- asm("":"=A" (c):"a" (__low),"d" (__high));
- *(__u64 *)a = c;
- return __mod;
- }
- }
-
- /* NOTREACHED */
- return 0;
-}
-
-/* Side effect free 64 bit mod operation */
-static inline __u32 fixed_div64_do_mod(void *a, __u32 b, int n)
-{
- switch (n) {
- case 4:
- return *(__u32 *)a % b;
- case 8:
- {
- unsigned long __upper, __low, __high, __mod;
- __u64 c = *(__u64 *)a;
- __upper = __high = c >> 32;
- __low = c;
- if (__high) {
- __upper = __high % (b);
- __high = __high / (b);
- }
- asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (b), "0" (__low), "1" (__upper));
- asm("":"=A" (c):"a" (__low),"d" (__high));
- return __mod;
- }
- }
-
- /* NOTREACHED */
- return 0;
-}
-#else
-static inline __u32 fixed_div64_do_div(void *a, __u32 b, int n)
-{
- __u32 mod;
-
- switch (n) {
- case 4:
- mod = *(__u32 *)a % b;
- *(__u32 *)a = *(__u32 *)a / b;
- return mod;
- case 8:
- mod = do_div(*(__u64 *)a, b);
- return mod;
- }
-
- /* NOTREACHED */
- return 0;
-}
-
-/* Side effect free 64 bit mod operation */
-static inline __u32 fixed_div64_do_mod(void *a, __u32 b, int n)
-{
- switch (n) {
- case 4:
- return *(__u32 *)a % b;
- case 8:
- {
- __u64 c = *(__u64 *)a;
- return do_div(c, b);
- }
- }
-
- /* NOTREACHED */
- return 0;
-}
-#endif
-
-#undef do_div
-#define do_div(a, b) fixed_div64_do_div(&(a), (b), sizeof(a))
-#define do_mod(a, b) fixed_div64_do_mod(&(a), (b), sizeof(a))
-
-#endif /* __FIXED_DIV64_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/format.h b/gfs-kernel/src/gfs/format.h
deleted file mode 100644
index 578ca2d..0000000
--- a/gfs-kernel/src/gfs/format.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __FORMAT_DOT_H__
-#define __FORMAT_DOT_H__
-
-static const uint32_t gfs_old_fs_formats[] = {
- 1308,
- 1307,
- 1306,
- 1305,
- 0
-};
-
-static const uint32_t gfs_old_multihost_formats[] = {
- 1400,
- 0
-};
-
-#endif /* __FORMAT_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/gfs.h b/gfs-kernel/src/gfs/gfs.h
deleted file mode 100644
index 3229308..0000000
--- a/gfs-kernel/src/gfs/gfs.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef __GFS_DOT_H__
-#define __GFS_DOT_H__
-
-#define RELEASE_VERSION "<CVS>"
-
-#include "lm_interface.h"
-
-#include "gfs_ondisk.h"
-#include "fixed_div64.h"
-#include "lvb.h"
-#include "incore.h"
-#include "util.h"
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#define NO_CREATE (0)
-#define CREATE (1)
-
-/* Divide num by den. Round up if there is a remainder. */
-#define DIV_RU(num, den) (((num) + (den) - 1) / (den))
-#define MAKE_MULT8(x) (((x) + 7) & ~7)
-
-#define GFS_FAST_NAME_SIZE (8)
-
-#define get_v2sdp(sb) ((struct gfs_sbd *)(sb)->s_fs_info)
-#define set_v2sdp(sb, sdp) (sb)->s_fs_info = (sdp)
-#define get_v2ip(inode) ((struct gfs_inode *)(inode)->i_private)
-#define set_v2ip(inode, ip) (inode)->i_private = (ip)
-#define get_v2fp(file) ((struct gfs_file *)(file)->private_data)
-#define set_v2fp(file, fp) (file)->private_data = (fp)
-#define get_v2bd(bh) ((struct gfs_bufdata *)(bh)->b_private)
-#define set_v2bd(bh, bd) (bh)->b_private = (bd)
-
-#define get_transaction ((struct gfs_trans *)(current->journal_info))
-#define set_transaction(tr) (current->journal_info) = (tr)
-
-#define get_gl2ip(gl) ((struct gfs_inode *)(gl)->gl_object)
-#define set_gl2ip(gl, ip) (gl)->gl_object = (ip)
-#define get_gl2rgd(gl) ((struct gfs_rgrpd *)(gl)->gl_object)
-#define set_gl2rgd(gl, rgd) (gl)->gl_object = (rgd)
-#define get_gl2gl(gl) ((struct gfs_glock *)(gl)->gl_object)
-#define set_gl2gl(gl, gl2) (gl)->gl_object = (gl2)
-
-#define gfs_printf(fmt, args...) \
-do { \
- if (buf) { \
- int gspf_left = size - *count, gspf_out; \
- if (gspf_left <= 0) \
- goto out; \
- gspf_out = snprintf(buf + *count, gspf_left, fmt, ##args); \
- if (gspf_out < gspf_left) \
- *count += gspf_out; \
- else \
- goto out; \
- } else \
- printk(fmt, ##args); \
-} while (0)
-
-#endif /* __GFS_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/gfs_ioctl.h b/gfs-kernel/src/gfs/gfs_ioctl.h
deleted file mode 100644
index e090cec..0000000
--- a/gfs-kernel/src/gfs/gfs_ioctl.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef __GFS_IOCTL_DOT_H__
-#define __GFS_IOCTL_DOT_H__
-
-#define _GFSC_(x) (('G' << 8) | (x))
-
-/* Ioctls implemented */
-
-#define GFS_IOCTL_IDENTIFY _GFSC_(35)
-#define GFS_IOCTL_SUPER _GFSC_(45)
-
-struct gfs_ioctl {
- unsigned int gi_argc;
- char **gi_argv;
-
- char __user *gi_data;
- unsigned int gi_size;
- uint64_t gi_offset;
-};
-
-#ifdef CONFIG_COMPAT
-struct gfs_ioctl_compat {
- unsigned int gi_argc;
- uint32_t gi_argv;
-
- uint32_t gi_data;
- unsigned int gi_size;
- uint64_t gi_offset;
-};
-#endif
-
-#endif /* ___GFS_IOCTL_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/gfs_ondisk.h b/gfs-kernel/src/gfs/gfs_ondisk.h
deleted file mode 100644
index 11637c6..0000000
--- a/gfs-kernel/src/gfs/gfs_ondisk.h
+++ /dev/null
@@ -1,1904 +0,0 @@
-/*
- * On-disk structures.
- *
- * THE BIG PICTURE of on-disk layout:
- *
- * GFS filesystem code views the entire filesystem, including journals, as
- * one contiguous group of blocks on one (perhaps virtual) storage device.
- * The filesystem space is shared, not distributed; each node in the cluster
- * must see the entire filesystem space.
- *
- * If the filesystem is spread across multiple physical storage devices,
- * volume management (device mapping) must be used to present the fileystem
- * space to GFS as one (virtual) device, with contiguous blocks.
- *
- * The superblock contains basic information about the filesytem, and appears
- * at a location 64 KBytes into the filesystem. The first 64 KBytes of the
- * filesystem are empty, providing a safety buffer against wayward volume
- * management software (that sometimes write data into the first few bytes of
- * a device) or administrators.
- *
- * After the superblock, the rest of the filesystem is divided into multiple
- * Resource Groups and several journals.
- *
- * The Resource Groups (RGs or rgrps) contain the allocatable blocks that are
- * used for storing files, directories, etc., and all of the associated
- * metadata. Each RG has its own set of block allocation statistics (within
- * the RG header), a number of blocks containing the block allocation bitmap,
- * and a large number of allocatable blocks for file data and metadata.
- * Multiple RGs allow multiple nodes to simultaneously allocate blocks from the
- * filesystem (using different RGs), enhancing parallel access. RG size and
- * number of RGs are determined by gfs_mkfs when creating the filesystem.
- * An administrator can specify RG size (see man gfs_mkfs).
- *
- * The journals contain temporary copies of metadata blocks, along with
- * other data, that allow GFS to recover the filesystem to a consistent state
- * (at least as far as metadata is concerned) if a node fails in the midst
- * of performing a write transaction. There must be one journal for each node
- * in the cluster. Since access to the entire filesystem space is shared,
- * if a node crashes, another node will be able to read the crashed node's
- * journal, and perform recovery.
- *
- * Currently, gfs_mkfs places the journals right in the middle of a freshly
- * created filesystem space, between 2 large groups of RGs. From a filesystem
- * layout perspective, this placement is not a requirement; the journals
- * could be placed anywhere within the filesystem space.
- *
- * New Resource Groups and Journals may be added to the filesystem after the
- * filesystem has been created, if the filesystem's (virtual) device is made
- * larger. See man gfs_grow and gfs_jadd.
- *
- * A few special hidden inodes are contained in a GFS filesystem. They do
- * not appear in any directories; instead, the superblock points to them
- * using block numbers for their location. The special inodes are:
- *
- * Root inode: Root directory of the filesystem
- * Resource Group Index: A file containing block numbers and sizes of all RGs
- * Journal Index: A file containing block numbers and sizes of all journals
- * Quota: A file containing all quota information for the filesystem
- * License: A file containing license information
- *
- * Note that there is NOTHING RELATED TO INTER-NODE LOCK MANAGEMENT ON-DISK.
- * Locking is handled completely off-disk, typically via LAN.
- *
- * NOTE:
- * If you add 8 byte fields to these structures, they must be 8 byte
- * aligned. 4 byte field must be 4 byte aligned, etc...
- *
- * All structures must be a multiple of 8 bytes long.
- *
- * GRIPES:
- * We should have forgetten about supporting 512B FS block sizes
- * and made the di_reserved field in the struct gfs_dinode structure
- * much bigger.
- *
- * de_rec_len in struct gfs_dirent should really have been a 32-bit value
- * as it now limits us to a 64k FS block size (with the current code
- * in dir.c).
- */
-
-#ifndef __GFS_ONDISK_DOT_H__
-#define __GFS_ONDISK_DOT_H__
-
-#define GFS_MAGIC (0x01161970) /* for all on-disk headers */
-#define GFS_BASIC_BLOCK (512) /* "basic block" = "sector" = 512B */
-#define GFS_BASIC_BLOCK_SHIFT (9)
-
-/* Controls how much data can be logged in-core before dumping log to disk */
-
-#define GFS_DUMPS_PER_LOG (4) /* 1/4 of on-disk journal size*/
-
-/* Lock numbers of the LM_TYPE_NONDISK type. These protect certain
- * cluster-wide operations (rather than on-disk entities).
- * Currently, the LIVE lock is not used for any real purpose. */
-
-#define GFS_MOUNT_LOCK (0) /* only one node can Mount at a time */
-#define GFS_LIVE_LOCK (1) /* shared by all mounted nodes */
-#define GFS_TRANS_LOCK (2) /* Transaction, protects jrnl recovery */
-#define GFS_RENAME_LOCK (3) /* only one node can Rename at a time */
-
-/* On-disk format (version) numbers for various metadata types,
- * used in gfs_meta_header */
-
-#define GFS_FORMAT_SB (100) /* Super-Block */
-#define GFS_FORMAT_RG (200) /* Resource Group Header */
-#define GFS_FORMAT_RB (300) /* Resource Group Block Alloc BitBlock */
-#define GFS_FORMAT_DI (400) /* "Disk" inode (dinode) */
-#define GFS_FORMAT_IN (500) /* Indirect dinode block list */
-#define GFS_FORMAT_LF (600) /* Leaf dinode block list */
-#define GFS_FORMAT_JD (700) /* Journal Data */
-#define GFS_FORMAT_LH (800) /* Log Header */
-#define GFS_FORMAT_LD (900) /* Log Descriptor */
-/* These don't have actual struct gfs_meta_header structures to go with them */
-#define GFS_FORMAT_JI (1000) /* Journal Index */
-#define GFS_FORMAT_RI (1100) /* Resource Group Index */
-#define GFS_FORMAT_DE (1200) /* Directory Entry */
-#define GFS_FORMAT_QU (1500) /* Quota */
-#define GFS_FORMAT_EA (1600) /* Extended Attribute */
-#define GFS_FORMAT_ED (1700) /* Extended Attribute data */
-/* These version #s are embedded in the superblock */
-#define GFS_FORMAT_FS (1309) /* Filesystem (all-encompassing) */
-#define GFS_FORMAT_MULTI (1401) /* Multi-Host */
-
-/*
- * An on-disk inode number
- * Initially, the on-disk block address of the inode block is assigned as the
- * formal (permanent) ID as well. Block address can change (to move inode
- * on-disk), but formal ID must stay unchanged once assigned.
- */
-
-#define gfs_inum_equal(ino1, ino2) \
-(((ino1)->no_formal_ino == (ino2)->no_formal_ino) && \
- ((ino1)->no_addr == (ino2)->no_addr))
-
-struct gfs_inum {
- uint64_t no_formal_ino; /* inode identifier */
- uint64_t no_addr; /* block # of dinode block */
-};
-
-/*
- * Generic metadata head structure
- *
- * Every inplace buffer logged in the journal must start
- * with a struct gfs_meta_header.
- *
- * In addition to telling what kind of metadata is in the block,
- * the metaheader contains the important generation and incarnation
- * numbers.
- *
- * The generation number is used during journal recovery to determine
- * whether an in-place block on-disk is older than an on-disk journaled copy
- * of the block. If so, GFS overwrites the in-place block with the journaled
- * version of the block.
- *
- * A meta block's generation number must increment monotonically across the
- * cluster, each time new contents are committed to the block. This means
- * that whenever GFS allocates a pre-existing metadata block, GFS must read
- * that block from disk (in case another node has incremented it). It also
- * means that GFS must sync the block (with incremented generation number)
- * to disk (both log and in-place blocks), not only after changing contents
- * of the block, but also after de-allocating the block (GFS can't just throw
- * away incore metadata for a file that it's just erased).
- *
- * The incarnation number is used only for on-disk (d)inodes. GFS increments
- * it each time it de-allocates a dinode block (i.e. each time the dinode
- * loses its identity with a particular file, directory, etc.). When the
- * dinode is later allocated (i.e. to be identified with a new file, etc.),
- * GFS copies the incarnation number into the VFS inode's i_generation member.
- * If GFS is used as the backing store for an NFS server, GFS uses this
- * i_generation number as part of the NFS filehandle, which differentiates
- * it from the previous identity of the dinode, and helps protect against
- * filesystem corruption that could happen with the use of outdated,
- * invalid, or malicious filehandles. See ops_export.c.
- *
- * GFS caches de-allocated meta-headers, to minimize disk reads.
- * See struct gfs_meta_header_cache.
- */
-
-#define GFS_METATYPE_NONE (0)
-#define GFS_METATYPE_SB (1) /* Super-Block */
-#define GFS_METATYPE_RG (2) /* Resource Group Header */
-#define GFS_METATYPE_RB (3) /* Resource Group Block Alloc BitBlock */
-#define GFS_METATYPE_DI (4) /* "Disk" inode (dinode) */
-#define GFS_METATYPE_IN (5) /* Indirect dinode block list */
-#define GFS_METATYPE_LF (6) /* Leaf dinode block list */
-#define GFS_METATYPE_JD (7) /* Journal Data */
-#define GFS_METATYPE_LH (8) /* Log Header (gfs_log_header) */
-#define GFS_METATYPE_LD (9) /* Log Descriptor (gfs_log_descriptor) */
-#define GFS_METATYPE_EA (10) /* Extended Attribute */
-#define GFS_METATYPE_ED (11) /* Extended Attribute data */
-
-#define GFS_META_CLUMP (64) /* # blocks to convert fm data to meta */
-
-struct gfs_meta_header {
- uint32_t mh_magic; /* GFS_MAGIC sanity check magic number */
- uint32_t mh_type; /* GFS_METATYPE_XX type of metadata block */
- uint64_t mh_generation; /* increment before writing to journal */
- uint32_t mh_format; /* GFS_FORMAT_XX (version # for this type) */
- uint32_t mh_incarn; /* increment when marking dinode "unused" */
-};
-
-/*
- * super-block structure
- *
- * One of these is at beginning of filesystem.
- * It's probably good if SIZEOF_SB <= GFS_BASIC_BLOCK (512 bytes)
- */
-
-/* Address of SuperBlock in GFS basic blocks. 1st 64K of filesystem is empty
- for safety against getting clobbered by wayward volume managers, etc.
- 64k was chosen because it's the largest GFS-supported fs block size. */
-#define GFS_SB_ADDR (128)
-
-/* The lock number for the superblock (must be zero) */
-#define GFS_SB_LOCK (0)
-#define GFS_CRAP_LOCK (1)
-
-/* Requirement: GFS_LOCKNAME_LEN % 8 == 0
- Includes: the fencing zero at the end */
-#define GFS_LOCKNAME_LEN (64)
-
-struct gfs_sb {
- /* Order is important; need to be able to read old superblocks
- in order to support on-disk version upgrades */
- struct gfs_meta_header sb_header;
-
- uint32_t sb_fs_format; /* GFS_FORMAT_FS (on-disk version) */
- uint32_t sb_multihost_format; /* GFS_FORMAT_MULTI */
- uint32_t sb_flags; /* ?? */
-
- uint32_t sb_bsize; /* fundamental FS block size in bytes */
- uint32_t sb_bsize_shift; /* log2(sb_bsize) */
- uint32_t sb_seg_size; /* Journal segment size in FS blocks */
-
- /* These special inodes do not appear in any on-disk directory. */
- struct gfs_inum sb_jindex_di; /* journal index inode */
- struct gfs_inum sb_rindex_di; /* resource group index inode */
- struct gfs_inum sb_root_di; /* root directory inode */
-
- /* Default inter-node locking protocol (lock module) and namespace */
- char sb_lockproto[GFS_LOCKNAME_LEN]; /* lock protocol name */
- char sb_locktable[GFS_LOCKNAME_LEN]; /* unique name for this FS */
-
- /* More special inodes */
- struct gfs_inum sb_quota_di; /* quota inode */
- struct gfs_inum sb_license_di; /* license inode */
-
- char sb_reserved[96];
-};
-
-/*
- * journal index structure
- *
- * One for each journal used by the filesystem.
- * These descriptors are packed contiguously within the jindex inode (file).
- */
-
-struct gfs_jindex {
- uint64_t ji_addr; /* starting block of the journal */
- uint32_t ji_nsegment; /* number (quantity) of segments in journal */
- uint32_t ji_pad;
-
- char ji_reserved[64];
-};
-
-/*
- * resource index structure
- *
- * One of these for each resource group in the filesystem.
- * These descriptors are packed contiguously within the rindex inode (file).
- * Also see struct gfs_rgrp.
- */
-
-struct gfs_rindex {
- uint64_t ri_addr; /* block # of 1st block (header) in rgrp */
- uint32_t ri_length; /* # fs blocks containing rgrp header & bitmap */
- uint32_t ri_pad;
-
- uint64_t ri_data1; /* block # of first data/meta block in rgrp */
- uint32_t ri_data; /* number (qty) of data/meta blocks in rgrp */
-
- uint32_t ri_bitbytes; /* total # bytes used by block alloc bitmap */
-
- char ri_reserved[64];
-};
-
-/*
- * resource group header structure
- *
- * One of these at beginning of the first block of an rgrp,
- * followed by block alloc bitmap data in remainder of first block.
- * Each resource group contains:
- * Header block, including block allocation statistics (struct gfs_rgrp)
- * and first part of block alloc bitmap.
- * Bitmap block(s), continuing block alloc bitmap started in header block.
- * Data/meta blocks, allocatable blocks containing file data and metadata.
- *
- * In older versions, now-unused (but previously allocated) dinodes were
- * saved for re-use in an on-disk linked list (chain). This is no longer
- * done, but support still exists for reclaiming dinodes from this list,
- * to support upgrades from older on-disk formats.
- */
-
-/* Each data block within rgrp is represented by 2 bits in the alloc bitmap */
-#define GFS_NBBY (4) /* # blocks represented by 1 bitmap byte */
-#define GFS_BIT_SIZE (2)
-#define GFS_BIT_MASK (0x00000003)
-
-/*
- * 4 possible block allocation states:
- * bit 0 = alloc(1)/free(0)
- * bit 1 = metadata(1)/data(0)
- */
-#define GFS_BLKST_FREE (0)
-#define GFS_BLKST_USED (1)
-#define GFS_BLKST_FREEMETA (2)
-#define GFS_BLKST_USEDMETA (3)
-
-struct gfs_rgrp {
- struct gfs_meta_header rg_header;
-
- uint32_t rg_flags; /* ?? */
-
- uint32_t rg_free; /* Number (qty) of free data blocks */
-
- /* Dinodes are USEDMETA, but are handled separately from other METAs */
- uint32_t rg_useddi; /* Number (qty) of dinodes (used or free) */
- uint32_t rg_freedi; /* Number (qty) of unused (free) dinodes */
- struct gfs_inum rg_freedi_list; /* 1st block in chain of free dinodes */
-
- /* These META statistics do not include dinodes (used or free) */
- uint32_t rg_usedmeta; /* Number (qty) of used metadata blocks */
- uint32_t rg_freemeta; /* Number (qty) of unused metadata blocks */
-
- char rg_reserved[64];
-};
-
-/*
- * quota structure
- */
-
-struct gfs_quota {
- uint64_t qu_limit;
- uint64_t qu_warn;
- int64_t qu_value;
-
- char qu_reserved[64];
-};
-
-/*
- * dinode (disk inode) structure
- * The ondisk representation of inodes
- * One for each file, directory, etc.
- * GFS does not put more than one inode in a single block.
- * The inode may be "stuffed", carrying file data along with metadata,
- * if the file data is small enough.
- * Otherwise, the inode block contains pointers to other blocks that contain
- * either file data or other pointers to other blocks (indirect addressing
- * via a metadata tree).
- */
-
-#define GFS_MAX_META_HEIGHT (10)
-#define GFS_DIR_MAX_DEPTH (17)
-
-/* Dinode types */
-#define GFS_FILE_NON (0)
-#define GFS_FILE_REG (1) /* regular file */
-#define GFS_FILE_DIR (2) /* directory */
-#define GFS_FILE_LNK (5) /* link */
-#define GFS_FILE_BLK (7) /* block device node */
-#define GFS_FILE_CHR (8) /* character device node */
-#define GFS_FILE_FIFO (101) /* fifo/pipe */
-#define GFS_FILE_SOCK (102) /* socket */
-
-/* Dinode flags */
-#define GFS_DIF_JDATA (0x00000001) /* jrnl all data for this file */
-#define GFS_DIF_EXHASH (0x00000002) /* hashed directory (leaves) */
-#define GFS_DIF_UNUSED (0x00000004) /* unused dinode */
-#define GFS_DIF_EA_INDIRECT (0x00000008) /* extended attribute, indirect*/
-#define GFS_DIF_DIRECTIO (0x00000010)
-#define GFS_DIF_IMMUTABLE (0x00000020) /* Can't change file */
-#define GFS_DIF_APPENDONLY (0x00000040) /* Can only add to end of file */
-#define GFS_DIF_NOATIME (0x00000080) /* Don't update access time
- (currently unused/ignored) */
-#define GFS_DIF_SYNC (0x00000100) /* Flush to disk, don't cache
- (currently unused/ignored) */
-#define GFS_DIF_INHERIT_DIRECTIO (0x40000000) /* new files get DIRECTIO flag */
-#define GFS_DIF_INHERIT_JDATA (0x80000000) /* new files get JDATA flag */
-
-struct gfs_dinode {
- struct gfs_meta_header di_header;
-
- struct gfs_inum di_num; /* formal inode # and block address */
-
- uint32_t di_mode; /* mode of file */
- uint32_t di_uid; /* owner's user id */
- uint32_t di_gid; /* owner's group id */
- uint32_t di_nlink; /* number (qty) of links to this file */
- uint64_t di_size; /* number (qty) of bytes in file */
- uint64_t di_blocks; /* number (qty) of blocks in file */
- int64_t di_atime; /* time last accessed */
- int64_t di_mtime; /* time last modified */
- int64_t di_ctime; /* time last changed */
-
- /* Non-zero only for character or block device nodes */
- uint32_t di_major; /* device major number */
- uint32_t di_minor; /* device minor number */
-
- /* Block allocation strategy */
- uint64_t di_rgrp; /* dinode rgrp block number */
- uint64_t di_goal_rgrp; /* rgrp to alloc from next */
- uint32_t di_goal_dblk; /* data block goal */
- uint32_t di_goal_mblk; /* metadata block goal */
-
- uint32_t di_flags; /* GFS_DIF_... */
-
- /* struct gfs_rindex, struct gfs_jindex, or struct gfs_dirent */
- uint32_t di_payload_format; /* GFS_FORMAT_... */
- uint16_t di_type; /* GFS_FILE_... type of file */
- uint16_t di_height; /* height of metadata (0 == stuffed) */
- uint32_t di_incarn; /* incarnation (unused, see gfs_meta_header) */
- uint16_t di_pad;
-
- /* These only apply to directories */
- uint16_t di_depth; /* Number of bits in the table */
- uint32_t di_entries; /* The # (qty) of entries in the directory */
-
- /* This formed an on-disk chain of unused dinodes */
- struct gfs_inum di_next_unused; /* used in old versions only */
-
- uint64_t di_eattr; /* extended attribute block number */
-
- char di_reserved[56];
-};
-
-/*
- * indirect block header
- *
- * A component of a dinode's indirect addressing metadata tree.
- * These are pointed to by pointers in dinodes or other indirect blocks.
- */
-
-struct gfs_indirect {
- struct gfs_meta_header in_header;
-
- char in_reserved[64];
-};
-
-/*
- * directory structure - many of these per directory file
- *
- * See comments at beginning of dir.c
- */
-
-#define GFS_FNAMESIZE (255)
-#define GFS_DIRENT_SIZE(name_len) ((sizeof(struct gfs_dirent) + (name_len) + 7) & ~7)
-#define IS_LEAF (1) /* Hashed (leaf) directory */
-#define IS_DINODE (2) /* Linear (stuffed dinode block) directory */
-
-struct gfs_dirent {
- struct gfs_inum de_inum; /* formal inode number and block address */
- uint32_t de_hash; /* hash of the filename */
- uint16_t de_rec_len; /* the length of the dirent */
- uint16_t de_name_len; /* the length of the name */
- uint16_t de_type; /* GFS_FILE_... type of dinode this points to */
-
- char de_reserved[14];
-};
-
-/*
- * Header of leaf directory nodes
- *
- * See comments at beginning of dir.c
- */
-
-struct gfs_leaf {
- struct gfs_meta_header lf_header;
-
- uint16_t lf_depth; /* Depth of leaf */
- uint16_t lf_entries; /* Number of dirents in leaf */
- uint32_t lf_dirent_format; /* GFS_FORMAT_DE (version #) */
- uint64_t lf_next; /* Next leaf, if overflow */
-
- char lf_reserved[64];
-};
-
-/*
- * Log header structure
- *
- * Two of these are in the first block of a transaction log:
- * 1) at beginning of block
- * 2) at end of first 512-byte sector within block
- */
-
-#define GFS_LOG_HEAD_UNMOUNT (0x00000001) /* log is clean, can unmount fs */
-
-struct gfs_log_header {
- struct gfs_meta_header lh_header;
-
- uint32_t lh_flags; /* GFS_LOG_HEAD_... */
- uint32_t lh_pad;
-
- uint64_t lh_first; /* Block number of first header in this trans */
- uint64_t lh_sequence; /* Sequence number of this transaction */
-
- uint64_t lh_tail; /* Block number of log tail */
- uint64_t lh_last_dump; /* Block number of last dump */
-
- char lh_reserved[64];
-};
-
-/*
- * Log type descriptor
- *
- * One of these for each chunk in a transaction
- */
-
-#define GFS_LOG_DESC_METADATA (300) /* metadata */
-/* ld_data1 is the number (quantity) of metadata blocks in the descriptor.
- ld_data2 is unused.
- */
-
-#define GFS_LOG_DESC_IUL (400) /* unlinked inode */
-/* ld_data1 is TRUE if this is a dump.
- ld_data2 is unused.
- FixMe!!! ld_data1 should be the number (quantity) of entries.
- ld_data2 should be "TRUE if this is a dump".
- */
-
-#define GFS_LOG_DESC_IDA (401) /* de-allocated inode */
-/* ld_data1 is unused.
- ld_data2 is unused.
- FixMe!!! ld_data1 should be the number (quantity) of entries.
- */
-
-#define GFS_LOG_DESC_Q (402) /* quota */
-/* ld_data1 is the number of quota changes in the descriptor.
- ld_data2 is TRUE if this is a dump.
- */
-
-#define GFS_LOG_DESC_LAST (500) /* final in a logged transaction */
-/* ld_data1 is unused.
- ld_data2 is unused.
- */
-
-struct gfs_log_descriptor {
- struct gfs_meta_header ld_header;
-
- uint32_t ld_type; /* GFS_LOG_DESC_... Type of this log chunk */
- uint32_t ld_length; /* Number of buffers in this chunk */
- uint32_t ld_data1; /* descriptor-specific field */
- uint32_t ld_data2; /* descriptor-specific field */
-
- char ld_reserved[64];
-};
-
-/*
- * Metadata block tags
- *
- * One for each logged block. Tells where block really belongs on-disk.
- * These descriptor tags are packed contiguously after a gfs_log_descriptor.
- */
-
-struct gfs_block_tag {
- uint64_t bt_blkno; /* inplace block number */
- uint32_t bt_flags; /* ?? */
- uint32_t bt_pad;
-};
-
-/*
- * Quota Journal Tag
- */
-
-#define GFS_QTF_USER (0x00000001)
-
-struct gfs_quota_tag {
- int64_t qt_change;
- uint32_t qt_flags; /* GFS_QTF_... */
- uint32_t qt_id;
-};
-
-/*
- * Extended attribute header format
- */
-
-#define GFS_EA_MAX_NAME_LEN (255)
-#define GFS_EA_MAX_DATA_LEN (65536)
-
-#define GFS_EATYPE_UNUSED (0)
-#define GFS_EATYPE_USR (1) /* user attribute */
-#define GFS_EATYPE_SYS (2) /* system attribute */
-#define GFS_EATYPE_SECURITY (3) /* security attribute */
-
-#define GFS_EATYPE_LAST (3)
-#define GFS_EATYPE_VALID(x) ((x) <= GFS_EATYPE_LAST)
-
-#define GFS_EAFLAG_LAST (0x01) /* last ea in block */
-
-struct gfs_ea_header {
- uint32_t ea_rec_len; /* total record length: hdr + name + data */
- uint32_t ea_data_len; /* data length, in bytes */
- uint8_t ea_name_len; /* no NULL pointer after the string */
- uint8_t ea_type; /* GFS_EATYPE_... */
- uint8_t ea_flags; /* GFS_EAFLAG_... */
- uint8_t ea_num_ptrs; /* # fs blocks needed for EA */
- uint32_t ea_pad;
-};
-
-/*
- * Statfs change
- * Describes an change to the pool of free and allocated
- * blocks.
- */
-
-struct gfs_statfs_change {
- uint64_t sc_total;
- uint64_t sc_free;
- uint64_t sc_dinodes;
-};
-
-struct gfs_statfs_change_host {
- int64_t sc_total;
- int64_t sc_free;
- int64_t sc_dinodes;
-};
-
-/* Endian functions */
-
-#define GFS_ENDIAN_BIG
-
-#ifdef GFS_ENDIAN_BIG
-
-#define gfs16_to_cpu be16_to_cpu
-#define gfs32_to_cpu be32_to_cpu
-#define gfs64_to_cpu be64_to_cpu
-
-#define cpu_to_gfs16 cpu_to_be16
-#define cpu_to_gfs32 cpu_to_be32
-#define cpu_to_gfs64 cpu_to_be64
-
-#else /* GFS_ENDIAN_BIG */
-
-#define gfs16_to_cpu le16_to_cpu
-#define gfs32_to_cpu le32_to_cpu
-#define gfs64_to_cpu le64_to_cpu
-
-#define cpu_to_gfs16 cpu_to_le16
-#define cpu_to_gfs32 cpu_to_le32
-#define cpu_to_gfs64 cpu_to_le64
-
-#endif /* GFS_ENDIAN_BIG */
-
-/* Translation functions */
-
-void gfs_inum_in(struct gfs_inum *no, char *buf);
-void gfs_inum_out(struct gfs_inum *no, char *buf);
-void gfs_meta_header_in(struct gfs_meta_header *mh, char *buf);
-void gfs_meta_header_out(struct gfs_meta_header *mh, char *buf);
-void gfs_sb_in(struct gfs_sb *sb, char *buf);
-void gfs_sb_out(struct gfs_sb *sb, char *buf);
-void gfs_jindex_in(struct gfs_jindex *jindex, char *buf);
-void gfs_jindex_out(struct gfs_jindex *jindex, char *buf);
-void gfs_rindex_in(struct gfs_rindex *rindex, char *buf);
-void gfs_rindex_out(struct gfs_rindex *rindex, char *buf);
-void gfs_rgrp_in(struct gfs_rgrp *rgrp, char *buf);
-void gfs_rgrp_out(struct gfs_rgrp *rgrp, char *buf);
-void gfs_quota_in(struct gfs_quota *quota, char *buf);
-void gfs_quota_out(struct gfs_quota *quota, char *buf);
-void gfs_dinode_in(struct gfs_dinode *dinode, char *buf);
-void gfs_dinode_out(struct gfs_dinode *dinode, char *buf);
-void gfs_indirect_in(struct gfs_indirect *indirect, char *buf);
-void gfs_indirect_out(struct gfs_indirect *indirect, char *buf);
-void gfs_dirent_in(struct gfs_dirent *dirent, char *buf);
-void gfs_dirent_out(struct gfs_dirent *dirent, char *buf);
-void gfs_leaf_in(struct gfs_leaf *leaf, char *buf);
-void gfs_leaf_out(struct gfs_leaf *leaf, char *buf);
-void gfs_log_header_in(struct gfs_log_header *head, char *buf);
-void gfs_log_header_out(struct gfs_log_header *head, char *buf);
-void gfs_desc_in(struct gfs_log_descriptor *desc, char *buf);
-void gfs_desc_out(struct gfs_log_descriptor *desc, char *buf);
-void gfs_block_tag_in(struct gfs_block_tag *btag, char *buf);
-void gfs_block_tag_out(struct gfs_block_tag *btag, char *buf);
-void gfs_quota_tag_in(struct gfs_quota_tag *qtag, char *buf);
-void gfs_quota_tag_out(struct gfs_quota_tag *qtag, char *buf);
-void gfs_ea_header_in(struct gfs_ea_header *qtag, char *buf);
-void gfs_ea_header_out(struct gfs_ea_header *qtag, char *buf);
-
-/* Printing functions */
-
-void gfs_inum_print(struct gfs_inum *no);
-void gfs_meta_header_print(struct gfs_meta_header *mh);
-void gfs_sb_print(struct gfs_sb *sb);
-void gfs_jindex_print(struct gfs_jindex *jindex);
-void gfs_rindex_print(struct gfs_rindex *rindex);
-void gfs_rgrp_print(struct gfs_rgrp *rgrp);
-void gfs_quota_print(struct gfs_quota *quota);
-void gfs_dinode_print(struct gfs_dinode *dinode);
-void gfs_indirect_print(struct gfs_indirect *indirect);
-void gfs_dirent_print(struct gfs_dirent *dirent, const char *name);
-void gfs_leaf_print(struct gfs_leaf *leaf);
-void gfs_log_header_print(struct gfs_log_header *head);
-void gfs_desc_print(struct gfs_log_descriptor *desc);
-void gfs_block_tag_print(struct gfs_block_tag *tag);
-void gfs_quota_tag_print(struct gfs_quota_tag *tag);
-void gfs_ea_header_print(struct gfs_ea_header *ea, char *name);
-
-/* The hash function for ExHash directories */
-
-uint32_t gfs_dir_hash(const char *data, int len);
-
-#endif /* __GFS_ONDISK_DOT_H__ */
-
-
-
-#ifdef WANT_GFS_CONVERSION_FUNCTIONS
-
-#define CPIN_08(s1, s2, member, count) {memcpy((s1->member), (s2->member), (count));}
-#define CPOUT_08(s1, s2, member, count) {memcpy((s2->member), (s1->member), (count));}
-#define CPIN_16(s1, s2, member) {(s1->member) = gfs16_to_cpu((s2->member));}
-#define CPOUT_16(s1, s2, member) {(s2->member) = cpu_to_gfs16((s1->member));}
-#define CPIN_32(s1, s2, member) {(s1->member) = gfs32_to_cpu((s2->member));}
-#define CPOUT_32(s1, s2, member) {(s2->member) = cpu_to_gfs32((s1->member));}
-#define CPIN_64(s1, s2, member) {(s1->member) = gfs64_to_cpu((s2->member));}
-#define CPOUT_64(s1, s2, member) {(s2->member) = cpu_to_gfs64((s1->member));}
-
-#define pa(struct, member, count) print_array(#member, struct->member, count);
-
-/**
- * print_array - Print out an array of bytes
- * @title: what to print before the array
- * @buf: the array
- * @count: the number of bytes
- *
- */
-
-static void
-print_array(const char *title, char *buf, int count)
-{
- int x;
-
- printk(" %s =\n", title);
- for (x = 0; x < count; x++) {
- printk("%.2X ", (unsigned char)buf[x]);
- if (x % 16 == 15)
- printk("\n");
- }
- if (x % 16)
- printk("\n");
-}
-
-/**
- * gfs_inum_in - Read in an inode number
- * @no: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_inum_in(struct gfs_inum *no, char *buf)
-{
- struct gfs_inum *str = (struct gfs_inum *)buf;
-
- CPIN_64(no, str, no_formal_ino);
- CPIN_64(no, str, no_addr);
-}
-
-/**
- * gfs_inum_out - Write out an inode number
- * @no: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_inum_out(struct gfs_inum *no, char *buf)
-{
- struct gfs_inum *str = (struct gfs_inum *)buf;
-
- CPOUT_64(no, str, no_formal_ino);
- CPOUT_64(no, str, no_addr);
-}
-
-/**
- * gfs_inum_print - Print out a inode number
- * @no: the cpu-order buffer
- *
- */
-
-void
-gfs_inum_print(struct gfs_inum *no)
-{
- pv(no, no_formal_ino, "%llu");
- pv(no, no_addr, "%llu");
-}
-
-/**
- * gfs_meta_header_in - Read in a metadata header
- * @mh: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_meta_header_in(struct gfs_meta_header *mh, char *buf)
-{
- struct gfs_meta_header *str = (struct gfs_meta_header *)buf;
-
- CPIN_32(mh, str, mh_magic);
- CPIN_32(mh, str, mh_type);
- CPIN_64(mh, str, mh_generation);
- CPIN_32(mh, str, mh_format);
- CPIN_32(mh, str, mh_incarn);
-}
-
-/**
- * gfs_meta_header_in - Write out a metadata header
- * @mh: the cpu-order structure
- * @buf: the disk-order buffer
- *
- * Don't ever change the generation number in this routine.
- * It's done manually in increment_generation().
- */
-
-void
-gfs_meta_header_out(struct gfs_meta_header *mh, char *buf)
-{
- struct gfs_meta_header *str = (struct gfs_meta_header *)buf;
-
- CPOUT_32(mh, str, mh_magic);
- CPOUT_32(mh, str, mh_type);
-#if 0
- /* Don't do this!
- Mh_generation should only be change manually. */
- CPOUT_64(mh, str, mh_generation);
-#endif
- CPOUT_32(mh, str, mh_format);
- CPOUT_32(mh, str, mh_incarn);
-}
-
-/**
- * gfs_meta_header_print - Print out a metadata header
- * @mh: the cpu-order buffer
- *
- */
-
-void
-gfs_meta_header_print(struct gfs_meta_header *mh)
-{
- pv(mh, mh_magic, "0x%.8X");
- pv(mh, mh_type, "%u");
- pv(mh, mh_generation, "%llu");
- pv(mh, mh_format, "%u");
- pv(mh, mh_incarn, "%u");
-}
-
-/**
- * gfs_sb_in - Read in a superblock
- * @sb: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_sb_in(struct gfs_sb *sb, char *buf)
-{
- struct gfs_sb *str = (struct gfs_sb *)buf;
-
- gfs_meta_header_in(&sb->sb_header, buf);
-
- CPIN_32(sb, str, sb_fs_format);
- CPIN_32(sb, str, sb_multihost_format);
- CPIN_32(sb, str, sb_flags);
-
- CPIN_32(sb, str, sb_bsize);
- CPIN_32(sb, str, sb_bsize_shift);
- CPIN_32(sb, str, sb_seg_size);
-
- gfs_inum_in(&sb->sb_jindex_di, (char *)&str->sb_jindex_di);
- gfs_inum_in(&sb->sb_rindex_di, (char *)&str->sb_rindex_di);
- gfs_inum_in(&sb->sb_root_di, (char *)&str->sb_root_di);
-
- CPIN_08(sb, str, sb_lockproto, GFS_LOCKNAME_LEN);
- CPIN_08(sb, str, sb_locktable, GFS_LOCKNAME_LEN);
-
- gfs_inum_in(&sb->sb_quota_di, (char *)&str->sb_quota_di);
- gfs_inum_in(&sb->sb_license_di, (char *)&str->sb_license_di);
-
- CPIN_08(sb, str, sb_reserved, 96);
-}
-
-/**
- * gfs_sb_out - Write out a superblock
- * @sb: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_sb_out(struct gfs_sb *sb, char *buf)
-{
- struct gfs_sb *str = (struct gfs_sb *)buf;
-
- gfs_meta_header_out(&sb->sb_header, buf);
-
- CPOUT_32(sb, str, sb_fs_format);
- CPOUT_32(sb, str, sb_multihost_format);
- CPOUT_32(sb, str, sb_flags);
-
- CPOUT_32(sb, str, sb_bsize);
- CPOUT_32(sb, str, sb_bsize_shift);
- CPOUT_32(sb, str, sb_seg_size);
-
- gfs_inum_out(&sb->sb_jindex_di, (char *)&str->sb_jindex_di);
- gfs_inum_out(&sb->sb_rindex_di, (char *)&str->sb_rindex_di);
- gfs_inum_out(&sb->sb_root_di, (char *)&str->sb_root_di);
-
- CPOUT_08(sb, str, sb_lockproto, GFS_LOCKNAME_LEN);
- CPOUT_08(sb, str, sb_locktable, GFS_LOCKNAME_LEN);
-
- gfs_inum_out(&sb->sb_quota_di, (char *)&str->sb_quota_di);
- gfs_inum_out(&sb->sb_license_di, (char *)&str->sb_license_di);
-
- CPOUT_08(sb, str, sb_reserved, 96);
-}
-
-/**
- * gfs_sb_print - Print out a superblock
- * @sb: the cpu-order buffer
- *
- */
-
-void
-gfs_sb_print(struct gfs_sb *sb)
-{
- gfs_meta_header_print(&sb->sb_header);
-
- pv(sb, sb_fs_format, "%u");
- pv(sb, sb_multihost_format, "%u");
- pv(sb, sb_flags, "%u");
-
- pv(sb, sb_bsize, "%u");
- pv(sb, sb_bsize_shift, "%u");
- pv(sb, sb_seg_size, "%u");
-
- gfs_inum_print(&sb->sb_jindex_di);
- gfs_inum_print(&sb->sb_rindex_di);
- gfs_inum_print(&sb->sb_root_di);
-
- pv(sb, sb_lockproto, "%s");
- pv(sb, sb_locktable, "%s");
-
- gfs_inum_print(&sb->sb_quota_di);
- gfs_inum_print(&sb->sb_license_di);
-
- pa(sb, sb_reserved, 96);
-}
-
-/**
- * gfs_jindex_in - Read in a journal index structure
- * @jindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_jindex_in(struct gfs_jindex *jindex, char *buf)
-{
- struct gfs_jindex *str = (struct gfs_jindex *)buf;
-
- CPIN_64(jindex, str, ji_addr);
- CPIN_32(jindex, str, ji_nsegment);
- CPIN_32(jindex, str, ji_pad);
-
- CPIN_08(jindex, str, ji_reserved, 64);
-}
-
-/**
- * gfs_jindex_out - Write out a journal index structure
- * @jindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_jindex_out(struct gfs_jindex *jindex, char *buf)
-{
- struct gfs_jindex *str = (struct gfs_jindex *)buf;
-
- CPOUT_64(jindex, str, ji_addr);
- CPOUT_32(jindex, str, ji_nsegment);
- CPOUT_32(jindex, str, ji_pad);
-
- CPOUT_08(jindex, str, ji_reserved, 64);
-}
-
-/**
- * gfs_jindex_print - Print out a journal index structure
- * @ji: the cpu-order buffer
- *
- */
-
-void
-gfs_jindex_print(struct gfs_jindex *ji)
-{
- pv(ji, ji_addr, "%llu");
- pv(ji, ji_nsegment, "%u");
- pv(ji, ji_pad, "%u");
-
- pa(ji, ji_reserved, 64);
-}
-
-/**
- * gfs_rindex_in - Read in a resource index structure
- * @rindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rindex_in(struct gfs_rindex *grindex, char *buf)
-{
- struct gfs_rindex *str = (struct gfs_rindex *)buf;
-
- CPIN_64(grindex, str, ri_addr);
- CPIN_32(grindex, str, ri_length);
- CPIN_32(grindex, str, ri_pad);
-
- CPIN_64(grindex, str, ri_data1);
- CPIN_32(grindex, str, ri_data);
-
- CPIN_32(grindex, str, ri_bitbytes);
-
- CPIN_08(grindex, str, ri_reserved, 64);
-}
-
-/**
- * gfs_rindex_out - Write out a resource index structure
- * @rindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rindex_out(struct gfs_rindex *grindex, char *buf)
-{
- struct gfs_rindex *str = (struct gfs_rindex *)buf;
-
- CPOUT_64(grindex, str, ri_addr);
- CPOUT_32(grindex, str, ri_length);
- CPOUT_32(grindex, str, ri_pad);
-
- CPOUT_64(grindex, str, ri_data1);
- CPOUT_32(grindex, str, ri_data);
-
- CPOUT_32(grindex, str, ri_bitbytes);
-
- CPOUT_08(grindex, str, ri_reserved, 64);
-}
-
-/**
- * gfs_rindex_print - Print out a resource index structure
- * @ri: the cpu-order buffer
- *
- */
-
-void
-gfs_rindex_print(struct gfs_rindex *ri)
-{
- pv(ri, ri_addr, "%llu");
- pv(ri, ri_length, "%u");
- pv(ri, ri_pad, "%u");
-
- pv(ri, ri_data1, "%llu");
- pv(ri, ri_data, "%u");
-
- pv(ri, ri_bitbytes, "%u");
-
- pa(ri, ri_reserved, 64);
-}
-
-/**
- * gfs_rgrp_in - Read in a resource group header
- * @rgrp: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rgrp_in(struct gfs_rgrp *rgrp, char *buf)
-{
- struct gfs_rgrp *str = (struct gfs_rgrp *)buf;
-
- gfs_meta_header_in(&rgrp->rg_header, buf);
-
- CPIN_32(rgrp, str, rg_flags);
-
- CPIN_32(rgrp, str, rg_free);
-
- CPIN_32(rgrp, str, rg_useddi);
- CPIN_32(rgrp, str, rg_freedi);
- gfs_inum_in(&rgrp->rg_freedi_list, (char *)&str->rg_freedi_list);
-
- CPIN_32(rgrp, str, rg_usedmeta);
- CPIN_32(rgrp, str, rg_freemeta);
-
- CPIN_08(rgrp, str, rg_reserved, 64);
-}
-
-/**
- * gfs_rgrp_out - Write out a resource group header
- * @rgrp: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rgrp_out(struct gfs_rgrp *rgrp, char *buf)
-{
- struct gfs_rgrp *str = (struct gfs_rgrp *)buf;
-
- gfs_meta_header_out(&rgrp->rg_header, buf);
-
- CPOUT_32(rgrp, str, rg_flags);
-
- CPOUT_32(rgrp, str, rg_free);
-
- CPOUT_32(rgrp, str, rg_useddi);
- CPOUT_32(rgrp, str, rg_freedi);
- gfs_inum_out(&rgrp->rg_freedi_list, (char *)&str->rg_freedi_list);
-
- CPOUT_32(rgrp, str, rg_usedmeta);
- CPOUT_32(rgrp, str, rg_freemeta);
-
- CPOUT_08(rgrp, str, rg_reserved, 64);
-}
-
-/**
- * gfs_rgrp_print - Print out a resource group header
- * @rg: the cpu-order buffer
- *
- */
-
-void
-gfs_rgrp_print(struct gfs_rgrp *rg)
-{
- gfs_meta_header_print(&rg->rg_header);
-
- pv(rg, rg_flags, "%u");
-
- pv(rg, rg_free, "%u");
-
- pv(rg, rg_useddi, "%u");
- pv(rg, rg_freedi, "%u");
- gfs_inum_print(&rg->rg_freedi_list);
-
- pv(rg, rg_usedmeta, "%u");
- pv(rg, rg_freemeta, "%u");
-
- pa(rg, rg_reserved, 64);
-}
-
-/**
- * gfs_quota_in - Read in a quota structures
- * @quota: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_in(struct gfs_quota *quota, char *buf)
-{
- struct gfs_quota *str = (struct gfs_quota *)buf;
-
- CPIN_64(quota, str, qu_limit);
- CPIN_64(quota, str, qu_warn);
- CPIN_64(quota, str, qu_value);
-
- CPIN_08(quota, str, qu_reserved, 64);
-}
-
-/**
- * gfs_quota_out - Write out a quota structure
- * @quota: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_out(struct gfs_quota *quota, char *buf)
-{
- struct gfs_quota *str = (struct gfs_quota *)buf;
-
- CPOUT_64(quota, str, qu_limit);
- CPOUT_64(quota, str, qu_warn);
- CPOUT_64(quota, str, qu_value);
-
- CPOUT_08(quota, str, qu_reserved, 64);
-}
-
-/**
- * gfs_quota_print - Print out a quota structure
- * @quota: the cpu-order buffer
- *
- */
-
-void
-gfs_quota_print(struct gfs_quota *quota)
-{
- pv(quota, qu_limit, "%llu");
- pv(quota, qu_warn, "%llu");
- pv(quota, qu_value, "%llu");
-
- pa(quota, qu_reserved, 64);
-}
-
-/**
- * gfs_dinode_in - Read in a dinode
- * @dinode: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dinode_in(struct gfs_dinode *dinode, char *buf)
-{
- struct gfs_dinode *str = (struct gfs_dinode *)buf;
-
- gfs_meta_header_in(&dinode->di_header, buf);
-
- gfs_inum_in(&dinode->di_num, (char *)&str->di_num);
-
- CPIN_32(dinode, str, di_mode);
- CPIN_32(dinode, str, di_uid);
- CPIN_32(dinode, str, di_gid);
- CPIN_32(dinode, str, di_nlink);
- CPIN_64(dinode, str, di_size);
- CPIN_64(dinode, str, di_blocks);
- CPIN_64(dinode, str, di_atime);
- CPIN_64(dinode, str, di_mtime);
- CPIN_64(dinode, str, di_ctime);
- CPIN_32(dinode, str, di_major);
- CPIN_32(dinode, str, di_minor);
-
- CPIN_64(dinode, str, di_rgrp);
- CPIN_64(dinode, str, di_goal_rgrp);
- CPIN_32(dinode, str, di_goal_dblk);
- CPIN_32(dinode, str, di_goal_mblk);
- CPIN_32(dinode, str, di_flags);
- CPIN_32(dinode, str, di_payload_format);
- CPIN_16(dinode, str, di_type);
- CPIN_16(dinode, str, di_height);
- CPIN_32(dinode, str, di_incarn);
- CPIN_16(dinode, str, di_pad);
-
- CPIN_16(dinode, str, di_depth);
- CPIN_32(dinode, str, di_entries);
-
- gfs_inum_in(&dinode->di_next_unused, (char *)&str->di_next_unused);
-
- CPIN_64(dinode, str, di_eattr);
-
- CPIN_08(dinode, str, di_reserved, 56);
-}
-
-/**
- * gfs_dinode_out - Write out a dinode
- * @dinode: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dinode_out(struct gfs_dinode *dinode, char *buf)
-{
- struct gfs_dinode *str = (struct gfs_dinode *)buf;
-
- gfs_meta_header_out(&dinode->di_header, buf);
-
- gfs_inum_out(&dinode->di_num, (char *)&str->di_num);
-
- CPOUT_32(dinode, str, di_mode);
- CPOUT_32(dinode, str, di_uid);
- CPOUT_32(dinode, str, di_gid);
- CPOUT_32(dinode, str, di_nlink);
- CPOUT_64(dinode, str, di_size);
- CPOUT_64(dinode, str, di_blocks);
- CPOUT_64(dinode, str, di_atime);
- CPOUT_64(dinode, str, di_mtime);
- CPOUT_64(dinode, str, di_ctime);
- CPOUT_32(dinode, str, di_major);
- CPOUT_32(dinode, str, di_minor);
-
- CPOUT_64(dinode, str, di_rgrp);
- CPOUT_64(dinode, str, di_goal_rgrp);
- CPOUT_32(dinode, str, di_goal_dblk);
- CPOUT_32(dinode, str, di_goal_mblk);
- CPOUT_32(dinode, str, di_flags);
- CPOUT_32(dinode, str, di_payload_format);
- CPOUT_16(dinode, str, di_type);
- CPOUT_16(dinode, str, di_height);
- CPOUT_32(dinode, str, di_incarn);
- CPOUT_16(dinode, str, di_pad);
-
- CPOUT_16(dinode, str, di_depth);
- CPOUT_32(dinode, str, di_entries);
-
- gfs_inum_out(&dinode->di_next_unused, (char *)&str->di_next_unused);
-
- CPOUT_64(dinode, str, di_eattr);
-
- CPOUT_08(dinode, str, di_reserved, 56);
-}
-
-/**
- * gfs_dinode_print - Print out a dinode
- * @di: the cpu-order buffer
- *
- */
-
-void
-gfs_dinode_print(struct gfs_dinode *di)
-{
- gfs_meta_header_print(&di->di_header);
-
- gfs_inum_print(&di->di_num);
-
- pv(di, di_mode, "0%o");
- pv(di, di_uid, "%u");
- pv(di, di_gid, "%u");
- pv(di, di_nlink, "%u");
- pv(di, di_size, "%llu");
- pv(di, di_blocks, "%llu");
- pv(di, di_atime, "%lld");
- pv(di, di_mtime, "%llu");
- pv(di, di_ctime, "%llu");
- pv(di, di_major, "%u");
- pv(di, di_minor, "%u");
-
- pv(di, di_rgrp, "%llu");
- pv(di, di_goal_rgrp, "%llu");
- pv(di, di_goal_dblk, "%u");
- pv(di, di_goal_mblk, "%u");
- pv(di, di_flags, "0x%.8X");
- pv(di, di_payload_format, "%u");
- pv(di, di_type, "%u");
- pv(di, di_height, "%u");
- pv(di, di_incarn, "%u");
- pv(di, di_pad, "%u");
-
- pv(di, di_depth, "%u");
- pv(di, di_entries, "%u");
-
- gfs_inum_print(&di->di_next_unused);
-
- pv(di, di_eattr, "%llu");
-
- pa(di, di_reserved, 56);
-}
-
-/**
- * gfs_indirect_in - copy in the header of an indirect block
- * @indirect: the in memory copy
- * @buf: the buffer copy
- *
- */
-
-void
-gfs_indirect_in(struct gfs_indirect *indirect, char *buf)
-{
- struct gfs_indirect *str = (struct gfs_indirect *)buf;
-
- gfs_meta_header_in(&indirect->in_header, buf);
-
- CPIN_08(indirect, str, in_reserved, 64);
-}
-
-/**
- * gfs_indirect_out - copy out the header of an indirect block
- * @indirect: the in memory copy
- * @buf: the buffer copy
- *
- */
-
-void
-gfs_indirect_out(struct gfs_indirect *indirect, char *buf)
-{
- struct gfs_indirect *str = (struct gfs_indirect *)buf;
-
- gfs_meta_header_out(&indirect->in_header, buf);
-
- CPOUT_08(indirect, str, in_reserved, 64);
-}
-
-/**
- * gfs_indirect_print - Print out a indirect block header
- * @indirect: the cpu-order buffer
- *
- */
-
-void
-gfs_indirect_print(struct gfs_indirect *indirect)
-{
- gfs_meta_header_print(&indirect->in_header);
-
- pa(indirect, in_reserved, 64);
-}
-
-/**
- * gfs_dirent_in - Read in a directory entry
- * @dirent: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dirent_in(struct gfs_dirent *dirent, char *buf)
-{
- struct gfs_dirent *str = (struct gfs_dirent *)buf;
-
- gfs_inum_in(&dirent->de_inum, (char *)&str->de_inum);
- CPIN_32(dirent, str, de_hash);
- CPIN_16(dirent, str, de_rec_len);
- CPIN_16(dirent, str, de_name_len);
- CPIN_16(dirent, str, de_type);
-
- CPIN_08(dirent, str, de_reserved, 14);
-}
-
-/**
- * gfs_dirent_out - Write out a directory entry
- * @dirent: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dirent_out(struct gfs_dirent *dirent, char *buf)
-{
- struct gfs_dirent *str = (struct gfs_dirent *)buf;
-
- gfs_inum_out(&dirent->de_inum, (char *)&str->de_inum);
- CPOUT_32(dirent, str, de_hash);
- CPOUT_16(dirent, str, de_rec_len);
- CPOUT_16(dirent, str, de_name_len);
- CPOUT_16(dirent, str, de_type);
-
- CPOUT_08(dirent, str, de_reserved, 14);
-}
-
-/**
- * gfs_dirent_print - Print out a directory entry
- * @de: the cpu-order buffer
- * @name: the filename
- *
- */
-
-void
-gfs_dirent_print(struct gfs_dirent *de, const char *name)
-{
- char buf[GFS_FNAMESIZE + 1];
-
- gfs_inum_print(&de->de_inum);
- pv(de, de_hash, "0x%.8X");
- pv(de, de_rec_len, "%u");
- pv(de, de_name_len, "%u");
- pv(de, de_type, "%u");
-
- pa(de, de_reserved, 14);
-
- memset(buf, 0, GFS_FNAMESIZE + 1);
- memcpy(buf, name, de->de_name_len);
- printk(" name = %s\n", buf);
-}
-
-/**
- * gfs_leaf_in - Read in a directory leaf header
- * @leaf: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_leaf_in(struct gfs_leaf *leaf, char *buf)
-{
- struct gfs_leaf *str = (struct gfs_leaf *)buf;
-
- gfs_meta_header_in(&leaf->lf_header, buf);
-
- CPIN_16(leaf, str, lf_depth);
- CPIN_16(leaf, str, lf_entries);
- CPIN_32(leaf, str, lf_dirent_format);
- CPIN_64(leaf, str, lf_next);
-
- CPIN_08(leaf, str, lf_reserved, 64);
-}
-
-/**
- * gfs_leaf_out - Write out a directory leaf header
- * @leaf: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_leaf_out(struct gfs_leaf *leaf, char *buf)
-{
- struct gfs_leaf *str = (struct gfs_leaf *)buf;
-
- gfs_meta_header_out(&leaf->lf_header, buf);
-
- CPOUT_16(leaf, str, lf_depth);
- CPOUT_16(leaf, str, lf_entries);
- CPOUT_32(leaf, str, lf_dirent_format);
- CPOUT_64(leaf, str, lf_next);
-
- CPOUT_08(leaf, str, lf_reserved, 64);
-}
-
-/**
- * gfs_leaf_print - Print out a directory leaf header
- * @lf: the cpu-order buffer
- *
- */
-
-void
-gfs_leaf_print(struct gfs_leaf *lf)
-{
- gfs_meta_header_print(&lf->lf_header);
-
- pv(lf, lf_depth, "%u");
- pv(lf, lf_entries, "%u");
- pv(lf, lf_dirent_format, "%u");
- pv(lf, lf_next, "%llu");
-
- pa(lf, lf_reserved, 64);
-}
-
-/**
- * gfs_log_header_in - Read in a log header
- * @head: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_log_header_in(struct gfs_log_header *head, char *buf)
-{
- struct gfs_log_header *str = (struct gfs_log_header *)buf;
-
- gfs_meta_header_in(&head->lh_header, buf);
-
- CPIN_32(head, str, lh_flags);
- CPIN_32(head, str, lh_pad);
-
- CPIN_64(head, str, lh_first);
- CPIN_64(head, str, lh_sequence);
-
- CPIN_64(head, str, lh_tail);
- CPIN_64(head, str, lh_last_dump);
-
- CPIN_08(head, str, lh_reserved, 64);
-}
-
-/**
- * gfs_log_header_out - Write out a log header
- * @head: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_log_header_out(struct gfs_log_header *head, char *buf)
-{
- struct gfs_log_header *str = (struct gfs_log_header *)buf;
-
- gfs_meta_header_out(&head->lh_header, buf);
-
- CPOUT_32(head, str, lh_flags);
- CPOUT_32(head, str, lh_pad);
-
- CPOUT_64(head, str, lh_first);
- CPOUT_64(head, str, lh_sequence);
-
- CPOUT_64(head, str, lh_tail);
- CPOUT_64(head, str, lh_last_dump);
-
- CPOUT_08(head, str, lh_reserved, 64);
-}
-
-/**
- * gfs_log_header_print - Print out a log header
- * @head: the cpu-order buffer
- *
- */
-
-void
-gfs_log_header_print(struct gfs_log_header *lh)
-{
- gfs_meta_header_print(&lh->lh_header);
-
- pv(lh, lh_flags, "0x%.8X");
- pv(lh, lh_pad, "%u");
-
- pv(lh, lh_first, "%llu");
- pv(lh, lh_sequence, "%llu");
-
- pv(lh, lh_tail, "%llu");
- pv(lh, lh_last_dump, "%llu");
-
- pa(lh, lh_reserved, 64);
-}
-
-/**
- * gfs_desc_in - Read in a log descriptor
- * @desc: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_desc_in(struct gfs_log_descriptor *desc, char *buf)
-{
- struct gfs_log_descriptor *str = (struct gfs_log_descriptor *)buf;
-
- gfs_meta_header_in(&desc->ld_header, buf);
-
- CPIN_32(desc, str, ld_type);
- CPIN_32(desc, str, ld_length);
- CPIN_32(desc, str, ld_data1);
- CPIN_32(desc, str, ld_data2);
-
- CPIN_08(desc, str, ld_reserved, 64);
-}
-
-/**
- * gfs_desc_out - Write out a log descriptor
- * @desc: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_desc_out(struct gfs_log_descriptor *desc, char *buf)
-{
- struct gfs_log_descriptor *str = (struct gfs_log_descriptor *)buf;
-
- gfs_meta_header_out(&desc->ld_header, buf);
-
- CPOUT_32(desc, str, ld_type);
- CPOUT_32(desc, str, ld_length);
- CPOUT_32(desc, str, ld_data1);
- CPOUT_32(desc, str, ld_data2);
-
- CPOUT_08(desc, str, ld_reserved, 64);
-}
-
-/**
- * gfs_desc_print - Print out a log descriptor
- * @ld: the cpu-order buffer
- *
- */
-
-void
-gfs_desc_print(struct gfs_log_descriptor *ld)
-{
- gfs_meta_header_print(&ld->ld_header);
-
- pv(ld, ld_type, "%u");
- pv(ld, ld_length, "%u");
- pv(ld, ld_data1, "%u");
- pv(ld, ld_data2, "%u");
-
- pa(ld, ld_reserved, 64);
-}
-
-/**
- * gfs_block_tag_in - Read in a block tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_block_tag_in(struct gfs_block_tag *tag, char *buf)
-{
- struct gfs_block_tag *str = (struct gfs_block_tag *)buf;
-
- CPIN_64(tag, str, bt_blkno);
- CPIN_32(tag, str, bt_flags);
- CPIN_32(tag, str, bt_pad);
-}
-
-/**
- * gfs_block_tag_out - Write out a block tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_block_tag_out(struct gfs_block_tag *tag, char *buf)
-{
- struct gfs_block_tag *str = (struct gfs_block_tag *)buf;
-
- CPOUT_64(tag, str, bt_blkno);
- CPOUT_32(tag, str, bt_flags);
- CPOUT_32(tag, str, bt_pad);
-}
-
-/**
- * gfs_block_tag_print - Print out a block tag
- * @tag: the cpu-order buffer
- *
- */
-
-void
-gfs_block_tag_print(struct gfs_block_tag *tag)
-{
- pv(tag, bt_blkno, "%llu");
- pv(tag, bt_flags, "%u");
- pv(tag, bt_pad, "%u");
-}
-
-/**
- * gfs_quota_tag_in - Read in a quota tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_tag_in(struct gfs_quota_tag *tag, char *buf)
-{
- struct gfs_quota_tag *str = (struct gfs_quota_tag *)buf;
-
- CPIN_64(tag, str, qt_change);
- CPIN_32(tag, str, qt_flags);
- CPIN_32(tag, str, qt_id);
-}
-
-/**
- * gfs_quota_tag_out - Write out a quota tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_tag_out(struct gfs_quota_tag *tag, char *buf)
-{
- struct gfs_quota_tag *str = (struct gfs_quota_tag *)buf;
-
- CPOUT_64(tag, str, qt_change);
- CPOUT_32(tag, str, qt_flags);
- CPOUT_32(tag, str, qt_id);
-}
-
-/**
- * gfs_quota_tag_print - Print out a quota tag
- * @tag: the cpu-order buffer
- *
- */
-
-void
-gfs_quota_tag_print(struct gfs_quota_tag *tag)
-{
- pv(tag, qt_change, "%llu");
- pv(tag, qt_flags, "0x%.8X");
- pv(tag, qt_id, "%u");
-}
-
-/**
- * gfs_ea_header_in - Read in a Extended Attribute header
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_ea_header_in(struct gfs_ea_header *ea, char *buf)
-{
- struct gfs_ea_header *str = (struct gfs_ea_header *)buf;
-
- CPIN_32(ea, str, ea_rec_len);
- CPIN_32(ea, str, ea_data_len);
- ea->ea_name_len = str->ea_name_len;
- ea->ea_type = str->ea_type;
- ea->ea_flags = str->ea_flags;
- ea->ea_num_ptrs = str->ea_num_ptrs;
- CPIN_32(ea, str, ea_pad);
-}
-
-/**
- * gfs_ea_header_out - Write out a Extended Attribute header
- * @ea: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_ea_header_out(struct gfs_ea_header *ea, char *buf)
-{
- struct gfs_ea_header *str = (struct gfs_ea_header *)buf;
-
- CPOUT_32(ea, str, ea_rec_len);
- CPOUT_32(ea, str, ea_data_len);
- str->ea_name_len = ea->ea_name_len;
- str->ea_type = ea->ea_type;
- str->ea_flags = ea->ea_flags;
- str->ea_num_ptrs = ea->ea_num_ptrs;
- CPOUT_32(ea, str, ea_pad);
-}
-
-/**
- * gfs_ea_header_printt - Print out a Extended Attribute header
- * @ea: the cpu-order buffer
- *
- */
-
-void
-gfs_ea_header_print(struct gfs_ea_header *ea, char *name)
-{
- char buf[GFS_EA_MAX_NAME_LEN + 1];
-
- pv(ea, ea_rec_len, "%u");
- pv(ea, ea_data_len, "%u");
- pv(ea, ea_name_len, "%u");
- pv(ea, ea_type, "%u");
- pv(ea, ea_flags, "%u");
- pv(ea, ea_num_ptrs, "%u");
- pv(ea, ea_pad, "%u");
-
- memset(buf, 0, GFS_EA_MAX_NAME_LEN + 1);
- memcpy(buf, name, ea->ea_name_len);
- printk(" name = %s\n", buf);
-}
-
-static const uint32_t crc_32_tab[] =
-{
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-/**
- * gfs_dir_hash - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * The hash function is a 32-bit CRC of the data. The algorithm uses
- * the crc_32_tab table above.
- *
- * This may not be the fastest hash function, but it does a fair bit better
- * at providing uniform results than the others I've looked at. That's
- * really important for efficient directories.
- *
- * Returns: the hash
- */
-
-uint32_t
-gfs_dir_hash(const char *data, int len)
-{
- uint32_t hash = 0xFFFFFFFF;
-
- for (; len--; data++)
- hash = crc_32_tab[(hash ^ *data) & 0xFF] ^ (hash >> 8);
-
- hash = ~hash;
-
- return hash;
-}
-
-#endif /* WANT_GFS_CONVERSION_FUNCTIONS */
-
diff --git a/gfs-kernel/src/gfs/glock.c b/gfs-kernel/src/gfs/glock.c
deleted file mode 100644
index 80f4466..0000000
--- a/gfs-kernel/src/gfs/glock.c
+++ /dev/null
@@ -1,3035 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <asm/uaccess.h>
-
-#include "gfs.h"
-#include "dio.h"
-#include "glock.h"
-#include "glops.h"
-#include "inode.h"
-#include "lm.h"
-#include "lops.h"
-#include "quota.h"
-#include "recovery.h"
-
-/* Must be kept in sync with the beginning of struct gfs_glock */
-struct glock_plug {
- struct list_head gl_list;
- unsigned long gl_flags;
-};
-
-struct greedy {
- struct gfs_holder gr_gh;
- struct delayed_work gr_work;
-};
-
-typedef void (*glock_examiner) (struct gfs_glock * gl, unsigned int *cnt);
-
-/**
- * relaxed_state_ok - is a requested lock compatible with the current lock mode?
- * @actual: the current state of the lock
- * @requested: the lock state that was requested by the caller
- * @flags: the modifier flags passed in by the caller
- *
- * Returns: TRUE if the locks are compatible, FALSE otherwise
- *
- * It's often possible that a holder B may request the lock in SHARED mode,
- * while another holder A (on this same node) has the lock in EXCLUSIVE mode
- * (node must hold the glock in EXCLUSIVE mode for this situation, of course).
- * This is okay to grant, in some cases, since both holders would have access
- * to the in-core up-to-date cached data that the EX holder would write to disk.
- * This is the default behavior.
- *
- * The EXACT flag disallows this behavior, though. A SHARED request would
- * compatible only with a SHARED lock with this flag.
- *
- * The ANY flag provides broader permission to grant the lock to a holder,
- * whatever the requested state is, as long as the lock is locked in any mode.
- */
-
-static __inline__ int
-relaxed_state_ok(unsigned int actual, unsigned requested, int flags)
-{
- if (actual == requested)
- return TRUE;
-
- if (flags & GL_EXACT)
- return FALSE;
-
- if (actual == LM_ST_EXCLUSIVE && requested == LM_ST_SHARED)
- return TRUE;
-
- if (actual != LM_ST_UNLOCKED && (flags & LM_FLAG_ANY))
- return TRUE;
-
- return FALSE;
-}
-
-/**
- * gl_hash() - Turn glock number into hash bucket number
- * @lock: The glock number
- *
- * Returns: The number of the corresponding hash bucket
- */
-
-static unsigned int
-gl_hash(struct lm_lockname *name)
-{
- unsigned int h;
-
- h = gfs_hash(&name->ln_number, sizeof(uint64_t));
- h = gfs_hash_more(&name->ln_type, sizeof(unsigned int), h);
- h &= GFS_GL_HASH_MASK;
-
- return h;
-}
-
-/**
- * glock_hold() - increment reference count on glock
- * @gl: The glock to hold
- *
- */
-
-static __inline__ void
-glock_hold(struct gfs_glock *gl)
-{
- gfs_assert(gl->gl_sbd, atomic_read(&gl->gl_count) > 0,);
- atomic_inc(&gl->gl_count);
-}
-
-/**
- * glock_put() - Decrement reference count on glock
- * @gl: The glock to put
- *
- */
-
-static __inline__ void
-glock_put(struct gfs_glock *gl)
-{
- if (atomic_read(&gl->gl_count) == 1)
- gfs_glock_schedule_for_reclaim(gl);
- gfs_assert(gl->gl_sbd, atomic_read(&gl->gl_count) > 0,);
- atomic_dec(&gl->gl_count);
-}
-
-/**
- * queue_empty - check to see if a glock's queue is empty
- * @gl: the glock
- * @head: the head of the queue to check
- *
- * Returns: TRUE if the queue is empty
- */
-
-static __inline__ int
-queue_empty(struct gfs_glock *gl, struct list_head *head)
-{
- int empty;
- spin_lock(&gl->gl_spin);
- empty = list_empty(head);
- spin_unlock(&gl->gl_spin);
- return empty;
-}
-
-/**
- * search_bucket() - Find struct gfs_glock by lock number
- * @bucket: the bucket to search
- * @name: The lock name
- *
- * Returns: NULL, or the struct gfs_glock with the requested number
- */
-
-static struct gfs_glock *
-search_bucket(struct gfs_gl_hash_bucket *bucket, struct lm_lockname *name)
-{
- struct list_head *tmp, *head;
- struct gfs_glock *gl;
-
- for (head = &bucket->hb_list, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- gl = list_entry(tmp, struct gfs_glock, gl_list);
-
- if (test_bit(GLF_PLUG, &gl->gl_flags))
- continue;
- if (!lm_name_equal(&gl->gl_name, name))
- continue;
-
- atomic_inc(&gl->gl_count);
-
- return gl;
- }
-
- return NULL;
-}
-
-/**
- * gfs_glock_find() - Find glock by lock number
- * @sdp: The GFS superblock
- * @name: The lock name
- *
- * Figure out what bucket the lock is in, acquire the read lock on
- * it and call search_bucket().
- *
- * Returns: NULL, or the struct gfs_glock with the requested number
- */
-
-struct gfs_glock *
-gfs_glock_find(struct gfs_sbd *sdp, struct lm_lockname *name)
-{
- struct gfs_gl_hash_bucket *bucket = &sdp->sd_gl_hash[gl_hash(name)];
- struct gfs_glock *gl;
-
- read_lock(&bucket->hb_lock);
- gl = search_bucket(bucket, name);
- read_unlock(&bucket->hb_lock);
-
- return gl;
-}
-
-/**
- * glock_free() - Perform a few checks and then release struct gfs_glock
- * @gl: The glock to release
- *
- * Also calls lock module to release its internal structure for this glock.
- *
- */
-
-static void
-glock_free(struct gfs_glock *gl)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct inode *aspace = gl->gl_aspace;
-
- gfs_assert_warn(sdp, list_empty(&gl->gl_list));
- gfs_assert_warn(sdp, atomic_read(&gl->gl_count) == 1);
- gfs_assert_warn(sdp, list_empty(&gl->gl_holders));
- gfs_assert_warn(sdp, list_empty(&gl->gl_waiters1));
- gfs_assert_warn(sdp, list_empty(&gl->gl_waiters2));
- gfs_assert_warn(sdp, list_empty(&gl->gl_waiters3));
- gfs_assert_warn(sdp, gl->gl_state == LM_ST_UNLOCKED);
- gfs_assert_warn(sdp, !gl->gl_object);
- gfs_assert_warn(sdp, !gl->gl_lvb);
- gfs_assert_warn(sdp, list_empty(&gl->gl_reclaim));
-
- gfs_lm_put_lock(sdp, gl->gl_lock);
-
- if (aspace)
- gfs_aspace_put(aspace);
-
- kmem_cache_free(gfs_glock_cachep, gl);
-
- atomic_dec(&sdp->sd_glock_count);
-}
-
-/**
- * gfs_glock_get() - Get a glock, or create one if one doesn't exist
- * @sdp: The GFS superblock
- * @number: the lock number
- * @glops: The glock_operations to use
- * @create: If FALSE, don't create the glock if it doesn't exist
- * @glp: the glock is returned here
- *
- * This does not lock a glock, just finds/creates structures for one.
- *
- * Returns: errno
- */
-
-int
-gfs_glock_get(struct gfs_sbd *sdp,
- uint64_t number, struct gfs_glock_operations *glops,
- int create, struct gfs_glock **glp)
-{
- struct lm_lockname name;
- struct gfs_glock *gl, *tmp;
- struct gfs_gl_hash_bucket *bucket;
- int error;
-
- /* Look for pre-existing glock in hash table */
- name.ln_number = number;
- name.ln_type = glops->go_type;
- bucket = &sdp->sd_gl_hash[gl_hash(&name)];
-
- read_lock(&bucket->hb_lock);
- gl = search_bucket(bucket, &name);
- read_unlock(&bucket->hb_lock);
-
- if (gl || !create) {
- *glp = gl;
- return 0;
- }
-
- /* None found; create a new one */
- gl = kmem_cache_alloc(gfs_glock_cachep, GFP_KERNEL);
- if (!gl)
- return -ENOMEM;
-
- memset(gl, 0, sizeof(struct gfs_glock));
-
- INIT_LIST_HEAD(&gl->gl_list);
- gl->gl_name = name;
- atomic_set(&gl->gl_count, 1);
-
- spin_lock_init(&gl->gl_spin);
-
- gl->gl_state = LM_ST_UNLOCKED;
- INIT_LIST_HEAD(&gl->gl_holders);
- INIT_LIST_HEAD(&gl->gl_waiters1);
- INIT_LIST_HEAD(&gl->gl_waiters2);
- INIT_LIST_HEAD(&gl->gl_waiters3);
-
- gl->gl_ops = glops;
-
- INIT_LE(&gl->gl_new_le, &gfs_glock_lops);
- INIT_LE(&gl->gl_incore_le, &gfs_glock_lops);
-
- gl->gl_bucket = bucket;
- INIT_LIST_HEAD(&gl->gl_reclaim);
-
- gl->gl_sbd = sdp;
-
- INIT_LIST_HEAD(&gl->gl_ail_bufs);
-
- /* If this glock protects actual on-disk data or metadata blocks,
- create a VFS inode to manage the pages/buffers holding them. */
- if (glops == &gfs_inode_glops ||
- glops == &gfs_rgrp_glops ||
- glops == &gfs_meta_glops) {
- gl->gl_aspace = gfs_aspace_get(sdp);
- if (!gl->gl_aspace) {
- error = -ENOMEM;
- goto fail;
- }
- }
-
- /* Ask lock module to find/create its structure for this lock
- (but this doesn't lock the inter-node lock yet) */
- error = gfs_lm_get_lock(sdp, &name, &gl->gl_lock);
- if (error)
- goto fail_aspace;
-
- atomic_inc(&sdp->sd_glock_count);
-
- /* Double-check, in case another process created the glock, and has
- put it in the hash table while we were preparing this one */
- write_lock(&bucket->hb_lock);
- tmp = search_bucket(bucket, &name);
- if (tmp) {
- /* Somebody beat us to it; forget the one we prepared */
- write_unlock(&bucket->hb_lock);
- glock_free(gl);
- gl = tmp;
- } else {
- /* Add our glock to hash table */
- list_add_tail(&gl->gl_list, &bucket->hb_list);
- write_unlock(&bucket->hb_lock);
- }
-
- *glp = gl;
-
- return 0;
-
- fail_aspace:
- if (gl->gl_aspace)
- gfs_aspace_put(gl->gl_aspace);
-
- fail:
- kmem_cache_free(gfs_glock_cachep, gl);
-
- return error;
-}
-
-/**
- * gfs_glock_hold() - As glock_hold(), but suitable for exporting
- * @gl: The glock to hold
- *
- */
-
-void
-gfs_glock_hold(struct gfs_glock *gl)
-{
- glock_hold(gl);
-}
-
-/**
- * gfs_glock_put() - As glock_put(), but suitable for exporting
- * @gl: The glock to put
- *
- */
-
-void
-gfs_glock_put(struct gfs_glock *gl)
-{
- glock_put(gl);
-}
-
-/**
- * gfs_holder_init - initialize a struct gfs_holder in the default way
- * @gl: the glock
- * @state: the state we're requesting
- * @flags: the modifier flags
- * @gh: the holder structure
- *
- */
-
-void
-gfs_holder_init(struct gfs_glock *gl, unsigned int state, int flags,
- struct gfs_holder *gh)
-{
- memset(gh, 0, sizeof(struct gfs_holder));
-
- INIT_LIST_HEAD(&gh->gh_list);
- gh->gh_gl = gl;
- gh->gh_owner = current;
- gh->gh_state = state;
- gh->gh_flags = flags;
-
- if (gh->gh_state == LM_ST_EXCLUSIVE)
- gh->gh_flags |= GL_LOCAL_EXCL;
-
- init_completion(&gh->gh_wait);
-
- glock_hold(gl);
-}
-
-/**
- * gfs_holder_reinit - reinitialize a struct gfs_holder so we can requeue it
- * @state: the state we're requesting
- * @flags: the modifier flags
- * @gh: the holder structure
- *
- * Preserve holder's associated glock and owning process.
- * Reset all holder state flags (we're starting a new request from scratch),
- * except for HIF_ALLOCED.
- * Don't do glock_hold() again (it was done in gfs_holder_init()).
- * Don't mess with the glock.
- *
- * Rules:
- * Holder must have been gfs_holder_init()d already
- * Holder must *not* be in glock's holder list or wait queues now
- */
-
-void
-gfs_holder_reinit(unsigned int state, int flags, struct gfs_holder *gh)
-{
- int alloced;
-
- gfs_assert_warn(gh->gh_gl->gl_sbd,
- list_empty(&gh->gh_list));
-
- gh->gh_state = state;
- gh->gh_flags = flags;
-
- if (gh->gh_state == LM_ST_EXCLUSIVE)
- gh->gh_flags |= GL_LOCAL_EXCL;
-
- alloced = test_bit(HIF_ALLOCED, &gh->gh_iflags);
- memset(&gh->gh_iflags, 0, sizeof(unsigned long));
- if (alloced)
- set_bit(HIF_ALLOCED, &gh->gh_iflags);
-}
-
-/**
- * gfs_holder_uninit - uninitialize a holder structure (drop reference on glock)
- * @gh: the holder structure
- *
- */
-
-void
-gfs_holder_uninit(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
-
- gfs_assert_warn(gl->gl_sbd, list_empty(&gh->gh_list));
- gh->gh_gl = NULL;
-
- glock_put(gl);
-}
-
-/**
- * gfs_holder_get - get a struct gfs_holder structure
- * @gl: the glock
- * @state: the state we're requesting
- * @flags: the modifier flags
- *
- * Figure out how big an impact this function has. Either:
- * 1) Replace it with a cache of structures hanging off the struct gfs_sbd
- * 2) Leave it like it is
- *
- * Returns: the holder structure, NULL on ENOMEM
- */
-
-struct gfs_holder *
-gfs_holder_get(struct gfs_glock *gl, unsigned int state, int flags)
-{
- struct gfs_holder *gh;
-
- gh = kmalloc(sizeof(struct gfs_holder), GFP_KERNEL);
- if (!gh)
- return NULL;
-
- gfs_holder_init(gl, state, flags, gh);
- set_bit(HIF_ALLOCED, &gh->gh_iflags);
-
- return gh;
-}
-
-/**
- * gfs_holder_put - get rid of a struct gfs_holder structure
- * @gh: the holder structure
- *
- */
-
-void
-gfs_holder_put(struct gfs_holder *gh)
-{
- if (gfs_assert_warn(gh->gh_gl->gl_sbd,
- test_bit(HIF_ALLOCED, &gh->gh_iflags)))
- return;
- gfs_holder_uninit(gh);
- kfree(gh);
-}
-
-/**
- * handle_recurse - put other holder structures (marked recursive) into the holders list
- * @gh: the holder structure
- *
- */
-
-static void
-handle_recurse(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct list_head *tmp, *head, *next;
- struct gfs_holder *tmp_gh;
- int found = FALSE;
-
- if (gfs_assert_warn(sdp, gh->gh_owner))
- return;
-
- for (head = &gl->gl_waiters3, tmp = head->next, next = tmp->next;
- tmp != head;
- tmp = next, next = tmp->next) {
- tmp_gh = list_entry(tmp, struct gfs_holder, gh_list);
- if (tmp_gh->gh_owner != gh->gh_owner)
- continue;
-
- gfs_assert_warn(sdp, test_bit(HIF_RECURSE, &tmp_gh->gh_iflags));
-
- list_move_tail(&tmp_gh->gh_list, &gl->gl_holders);
- tmp_gh->gh_error = 0;
- set_bit(HIF_HOLDER, &tmp_gh->gh_iflags);
-
- complete(&tmp_gh->gh_wait);
-
- found = TRUE;
- }
-
- gfs_assert_warn(sdp, found);
-}
-
-/**
- * do_unrecurse - a recursive holder was just dropped of the waiters3 list
- * @gh: the holder
- *
- * If there is only one other recursive holder, clear its HIF_RECURSE bit
- * (it's no longer a recursive request).
- * If there is more than one, leave them alone (they're recursive!).
- *
- */
-
-static void
-do_unrecurse(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct list_head *tmp, *head;
- struct gfs_holder *tmp_gh, *last_gh = NULL;
- int found = FALSE;
-
- if (gfs_assert_warn(sdp, gh->gh_owner))
- return;
-
- for (head = &gl->gl_waiters3, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- tmp_gh = list_entry(tmp, struct gfs_holder, gh_list);
- if (tmp_gh->gh_owner != gh->gh_owner)
- continue;
-
- gfs_assert_warn(sdp, test_bit(HIF_RECURSE, &tmp_gh->gh_iflags));
-
- /* found more than one */
- if (found)
- return;
-
- found = TRUE;
- last_gh = tmp_gh;
- }
-
- /* found just one */
- if (!gfs_assert_warn(sdp, found))
- clear_bit(HIF_RECURSE, &last_gh->gh_iflags);
-}
-
-/**
- * rq_mutex - process a mutex request in the queue
- * @gh: the glock holder
- *
- * Returns: TRUE if the queue is blocked (always, since there can be only one
- * holder of the mutex).
- *
- * See lock_on_glock()
- */
-
-static int
-rq_mutex(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
-
- list_del_init(&gh->gh_list);
- /* gh->gh_error never examined. */
- set_bit(GLF_LOCK, &gl->gl_flags);
- complete(&gh->gh_wait);
-
- return TRUE;
-}
-
-/**
- * rq_promote - process a promote request in the queue
- * @gh: the glock holder
- *
- * Acquire a new inter-node lock, or change a lock state to more restrictive.
- *
- * Returns: TRUE if the queue is blocked
- */
-
-static int
-rq_promote(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_glock_operations *glops = gl->gl_ops;
- int recurse;
-
- if (!relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
- if (list_empty(&gl->gl_holders)) {
- gl->gl_req_gh = gh;
- set_bit(GLF_LOCK, &gl->gl_flags);
- spin_unlock(&gl->gl_spin);
-
- /* If we notice a lot of glocks in reclaim list, free
- up memory for 2 of them before locking a new one */
- if (atomic_read(&sdp->sd_reclaim_count) >
- gfs_tune_get(sdp, gt_reclaim_limit) &&
- !(gh->gh_flags & LM_FLAG_PRIORITY)) {
- gfs_reclaim_glock(sdp);
- gfs_reclaim_glock(sdp);
- }
-
- glops->go_xmote_th(gl, gh->gh_state,
- gh->gh_flags);
-
- spin_lock(&gl->gl_spin);
- }
- return TRUE;
- }
-
- if (list_empty(&gl->gl_holders)) {
- set_bit(HIF_FIRST, &gh->gh_iflags);
- set_bit(GLF_LOCK, &gl->gl_flags);
- recurse = FALSE;
- } else {
- struct gfs_holder *next_gh;
- if (gh->gh_flags & GL_LOCAL_EXCL)
- return TRUE;
- next_gh = list_entry(gl->gl_holders.next, struct gfs_holder, gh_list);
- if (next_gh->gh_flags & GL_LOCAL_EXCL)
- return TRUE;
- recurse = test_bit(HIF_RECURSE, &gh->gh_iflags);
- }
-
- list_move_tail(&gh->gh_list, &gl->gl_holders);
- gh->gh_error = 0;
- set_bit(HIF_HOLDER, &gh->gh_iflags);
-
- if (recurse)
- handle_recurse(gh);
-
- complete(&gh->gh_wait);
-
- return FALSE;
-}
-
-/**
- * rq_demote - process a demote request in the queue
- * @gh: the glock holder
- *
- * Returns: TRUE if the queue is blocked
- *
- * Unlock an inter-node lock, or change a lock state to less restrictive.
- * If the glock is already the same as the holder's requested state, or is
- * UNLOCKED, no lock module request is required.
- * Otherwise, we need to ask lock module to unlock or change locked state
- * of the glock.
- * If requested state is UNLOCKED, or current glock state is SHARED or
- * DEFERRED (neither of which have a less restrictive state other than
- * UNLOCK), we call go_drop_th() to unlock the lock.
- * Otherwise (i.e. requested is SHARED or DEFERRED, and current is EXCLUSIVE),
- * we can continue to hold the lock, and just ask for a new state;
- * we call go_xmote_th() to change state.
- *
- * Must be called with glock's gl->gl_spin locked.
- */
-
-static int
-rq_demote(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- struct gfs_glock_operations *glops = gl->gl_ops;
-
- if (!list_empty(&gl->gl_holders))
- return TRUE;
-
- if (gl->gl_state == gh->gh_state || gl->gl_state == LM_ST_UNLOCKED) {
- list_del_init(&gh->gh_list);
- gh->gh_error = 0;
- spin_unlock(&gl->gl_spin);
- if (test_bit(HIF_DEALLOC, &gh->gh_iflags))
- gfs_holder_put(gh);
- else
- complete(&gh->gh_wait);
- spin_lock(&gl->gl_spin);
- } else {
- gl->gl_req_gh = gh;
- set_bit(GLF_LOCK, &gl->gl_flags);
- spin_unlock(&gl->gl_spin);
-
- if (gh->gh_state == LM_ST_UNLOCKED ||
- gl->gl_state != LM_ST_EXCLUSIVE)
- /* Unlock */
- glops->go_drop_th(gl);
- else
- /* Change state while holding lock */
- glops->go_xmote_th(gl, gh->gh_state, gh->gh_flags);
-
- spin_lock(&gl->gl_spin);
- }
-
- return FALSE;
-}
-
-/**
- * rq_greedy - process a queued request to drop greedy status
- * @gh: the glock holder
- *
- * Returns: TRUE if the queue is blocked
- */
-
-static int
-rq_greedy(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
-
- list_del_init(&gh->gh_list);
- /* gh->gh_error never examined. */
- clear_bit(GLF_GREEDY, &gl->gl_flags);
- spin_unlock(&gl->gl_spin);
-
- gfs_holder_uninit(gh);
- kfree(container_of(gh, struct greedy, gr_gh));
-
- spin_lock(&gl->gl_spin);
-
- return FALSE;
-}
-
-/**
- * run_queue - process holder structures on the glock's wait queues
- * @gl: the glock
- *
- * Rules:
- * Caller must hold gl->gl_spin.
- */
-
-static void
-run_queue(struct gfs_glock *gl)
-{
- struct gfs_holder *gh;
- int blocked = TRUE;
-
- for (;;) {
- /* Another process is manipulating the glock structure;
- we can't do anything now */
- if (test_bit(GLF_LOCK, &gl->gl_flags))
- break;
-
- /* Waiting to manipulate the glock structure */
- if (!list_empty(&gl->gl_waiters1)) {
- gh = list_entry(gl->gl_waiters1.next,
- struct gfs_holder, gh_list);
-
- if (test_bit(HIF_MUTEX, &gh->gh_iflags))
- blocked = rq_mutex(gh);
- else
- gfs_assert_warn(gl->gl_sbd, FALSE);
-
- /* Waiting to demote the lock, or drop greedy status */
- } else if (!list_empty(&gl->gl_waiters2) &&
- !test_bit(GLF_SKIP_WAITERS2, &gl->gl_flags)) {
- gh = list_entry(gl->gl_waiters2.next,
- struct gfs_holder, gh_list);
-
- if (test_bit(HIF_DEMOTE, &gh->gh_iflags))
- blocked = rq_demote(gh);
- else if (test_bit(HIF_GREEDY, &gh->gh_iflags))
- blocked = rq_greedy(gh);
- else
- gfs_assert_warn(gl->gl_sbd, FALSE);
-
- /* Waiting to promote the lock */
- } else if (!list_empty(&gl->gl_waiters3)) {
- gh = list_entry(gl->gl_waiters3.next,
- struct gfs_holder, gh_list);
-
- if (test_bit(HIF_PROMOTE, &gh->gh_iflags))
- blocked = rq_promote(gh);
- else
- gfs_assert_warn(gl->gl_sbd, FALSE);
-
- } else
- break;
-
- if (blocked)
- break;
- }
-}
-
-/**
- * lock_on_glock - acquire a local lock on a glock (structure)
- * @gl: the glock
- *
- * Gives caller exclusive access to manipulate a glock structure.
- * Has nothing to do with inter-node lock state or GL_LOCAL_EXCL!
- *
- * If structure already locked, places temporary holder structure on glock's
- * wait-for-exclusive-access queue, and blocks until exclusive access granted.
- */
-
-static void
-lock_on_glock(struct gfs_glock *gl)
-{
- struct gfs_holder gh;
-
- gfs_holder_init(gl, 0, 0, &gh);
- set_bit(HIF_MUTEX, &gh.gh_iflags);
-
- spin_lock(&gl->gl_spin);
- if (test_and_set_bit(GLF_LOCK, &gl->gl_flags))
- list_add_tail(&gh.gh_list, &gl->gl_waiters1);
- else
- complete(&gh.gh_wait);
- spin_unlock(&gl->gl_spin);
-
- wait_for_completion(&gh.gh_wait);
- gfs_holder_uninit(&gh);
-}
-
-/**
- * trylock_on_glock - try to acquire a local lock on a glock (structure)
- * @gl: the glock
- *
- * Returns: TRUE if the glock is acquired
- *
- * Tries to give caller exclusive access to manipulate a glock structure.
- * Has nothing to do with inter-node lock state or LOCAL_EXCL!
- *
- * If structure already locked, does not block to wait; returns FALSE.
- */
-
-static int
-trylock_on_glock(struct gfs_glock *gl)
-{
- int acquired = TRUE;
-
- spin_lock(&gl->gl_spin);
- if (test_and_set_bit(GLF_LOCK, &gl->gl_flags))
- acquired = FALSE;
- spin_unlock(&gl->gl_spin);
-
- return acquired;
-}
-
-/**
- * unlock_on_glock - release a local lock on a glock (structure)
- * @gl: the glock
- *
- * Caller is done manipulating glock structure.
- * Service any others waiting for exclusive access.
- */
-
-static void
-unlock_on_glock(struct gfs_glock *gl)
-{
- spin_lock(&gl->gl_spin);
- clear_bit(GLF_LOCK, &gl->gl_flags);
- run_queue(gl);
- spin_unlock(&gl->gl_spin);
-}
-
-/**
- * handle_callback - add a demote request to a lock's queue
- * @gl: the glock
- * @state: the state the caller wants us to change to
- *
- * Called when we learn that another node needs a lock held by this node,
- * or when this node simply wants to drop a lock as soon as it's done with
- * it (NOCACHE flag), or dump a glock out of glock cache (reclaim it).
- *
- * We are told the @state that will satisfy the needs of the caller, so
- * we can ask for a demote to that state.
- *
- * If another demote request is already on the queue for a different state, just
- * set its request to UNLOCK (and don't bother queueing a request for us).
- * This consolidates LM requests and moves the lock to the least restrictive
- * state, so it will be compatible with whatever reason we were called.
- * No need to be too smart here. Demotes between the shared and deferred
- * states will often fail, so don't even try.
- *
- * Otherwise, queue a demote request to the requested state.
- */
-
-static void
-handle_callback(struct gfs_glock *gl, unsigned int state)
-{
- struct list_head *tmp, *head;
- struct gfs_holder *gh, *new_gh = NULL;
-
- if (gfs_assert_warn(gl->gl_sbd, state != LM_ST_EXCLUSIVE))
- return;
-
- restart:
- spin_lock(&gl->gl_spin);
-
- /* If another queued demote request is for a different state,
- set its request to UNLOCKED */
- for (head = &gl->gl_waiters2, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- gh = list_entry(tmp, struct gfs_holder, gh_list);
- if (test_bit(HIF_DEMOTE, &gh->gh_iflags) &&
- gl->gl_req_gh != gh) {
- if (gh->gh_state != state)
- gh->gh_state = LM_ST_UNLOCKED;
- goto out;
- }
- }
-
- /* pass 2; add new holder to glock's demote request queue */
- if (new_gh) {
- list_add_tail(&new_gh->gh_list, &gl->gl_waiters2);
- new_gh = NULL;
-
- /* pass 1; set up a new holder struct for a demote request, then
- check again to see if another process added a demote request
- while we were preparing this one. */
- } else {
- spin_unlock(&gl->gl_spin);
-
- RETRY_MALLOC(new_gh = gfs_holder_get(gl, state, LM_FLAG_TRY),
- new_gh);
- set_bit(HIF_DEMOTE, &new_gh->gh_iflags);
- set_bit(HIF_DEALLOC, &new_gh->gh_iflags);
- new_gh->gh_owner = NULL;
-
- goto restart;
- }
-
- out:
- spin_unlock(&gl->gl_spin);
-
- if (new_gh)
- gfs_holder_put(new_gh);
-}
-
-/**
- * state_change - record that the glock is now in a different state
- * @gl: the glock
- * @new_state the new state
- *
- */
-
-static void
-state_change(struct gfs_glock *gl, unsigned int new_state)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- int held1, held2;
-
- held1 = (gl->gl_state != LM_ST_UNLOCKED);
- held2 = (new_state != LM_ST_UNLOCKED);
-
- if (held1 != held2) {
- if (held2) {
- atomic_inc(&sdp->sd_glock_held_count);
- glock_hold(gl);
- } else {
- atomic_dec(&sdp->sd_glock_held_count);
- glock_put(gl);
- }
- }
-
- gl->gl_state = new_state;
-}
-
-static int gfs_glock_demote_wait(void *word)
-{
- schedule();
- return 0;
-}
-
-static void gfs_wait_on_demote(struct gfs_glock *gl)
-{
- might_sleep();
- wait_on_bit(&gl->gl_flags, GLF_DEMOTE, gfs_glock_demote_wait, TASK_UNINTERRUPTIBLE);
-}
-
-static void gfs_demote_wake(struct gfs_glock *gl)
-{
- clear_bit(GLF_DEMOTE, &gl->gl_flags);
- smp_mb__after_clear_bit();
- wake_up_bit(&gl->gl_flags, GLF_DEMOTE);
-}
-
-void gfs_glock_dq_wait(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- set_bit(GLF_DEMOTE, &gl->gl_flags);
- gfs_glock_dq(gh);
- gfs_wait_on_demote(gl);
-}
-
-/**
- * xmote_bh - Called after the lock module is done acquiring a lock
- * @gl: The glock in question
- * @ret: the int returned from the lock module
- *
- */
-
-static void
-xmote_bh(struct gfs_glock *gl, unsigned int ret)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_glock_operations *glops = gl->gl_ops;
- struct gfs_holder *gh = gl->gl_req_gh;
- int prev_state = gl->gl_state;
- int op_done = TRUE;
-
- gfs_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
- gfs_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
- gfs_assert_warn(sdp, !(ret & LM_OUT_ASYNC));
-
- state_change(gl, ret & LM_OUT_ST_MASK);
-
- if (prev_state != LM_ST_UNLOCKED && !(ret & LM_OUT_CACHEABLE)) {
- if (glops->go_inval)
- glops->go_inval(gl, DIO_METADATA | DIO_DATA);
- } else if (gl->gl_state == LM_ST_DEFERRED) {
- /* We might not want to do this here.
- Look at moving to the inode glops. */
- if (glops->go_inval)
- glops->go_inval(gl, DIO_DATA);
- }
-
- /* Deal with each possible exit condition */
-
- if (!gh)
- gl->gl_stamp = jiffies;
-
- else if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
- spin_lock(&gl->gl_spin);
- list_del_init(&gh->gh_list);
- gh->gh_error = -EIO;
- if (test_bit(HIF_RECURSE, &gh->gh_iflags))
- do_unrecurse(gh);
- spin_unlock(&gl->gl_spin);
-
- } else if (test_bit(HIF_DEMOTE, &gh->gh_iflags)) {
- spin_lock(&gl->gl_spin);
- list_del_init(&gh->gh_list);
- if (gl->gl_state == gh->gh_state ||
- gl->gl_state == LM_ST_UNLOCKED)
- gh->gh_error = 0;
- else {
- if (gfs_assert_warn(sdp, gh->gh_flags &
- (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) == -1)
- printk("GFS: fsid=%s: ret = 0x%.8X\n",
- sdp->sd_fsname, ret);
- gh->gh_error = GLR_TRYFAILED;
- }
- spin_unlock(&gl->gl_spin);
-
- if (ret & LM_OUT_CANCELED)
- handle_callback(gl, LM_ST_UNLOCKED); /* Lame */
-
- } else if (ret & LM_OUT_CANCELED) {
- spin_lock(&gl->gl_spin);
- list_del_init(&gh->gh_list);
- gh->gh_error = GLR_CANCELED;
- if (test_bit(HIF_RECURSE, &gh->gh_iflags))
- do_unrecurse(gh);
- spin_unlock(&gl->gl_spin);
-
- } else if (relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
- spin_lock(&gl->gl_spin);
- list_move_tail(&gh->gh_list, &gl->gl_holders);
- gh->gh_error = 0;
- set_bit(HIF_HOLDER, &gh->gh_iflags);
- spin_unlock(&gl->gl_spin);
-
- set_bit(HIF_FIRST, &gh->gh_iflags);
-
- op_done = FALSE;
-
- } else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) {
- spin_lock(&gl->gl_spin);
- list_del_init(&gh->gh_list);
- gh->gh_error = GLR_TRYFAILED;
- if (test_bit(HIF_RECURSE, &gh->gh_iflags))
- do_unrecurse(gh);
- spin_unlock(&gl->gl_spin);
-
- } else {
- if (gfs_assert_withdraw(sdp, FALSE) == -1)
- printk("GFS: fsid=%s: ret = 0x%.8X\n",
- sdp->sd_fsname, ret);
- }
-
- if (glops->go_xmote_bh)
- glops->go_xmote_bh(gl);
-
- if (op_done) {
- spin_lock(&gl->gl_spin);
- gl->gl_req_gh = NULL;
- gl->gl_req_bh = NULL;
- clear_bit(GLF_LOCK, &gl->gl_flags);
- run_queue(gl);
- if (test_bit(GLF_DEMOTE, &gl->gl_flags))
- gfs_demote_wake(gl);
- spin_unlock(&gl->gl_spin);
- }
-
- glock_put(gl);
-
- if (gh) {
- if (test_bit(HIF_DEALLOC, &gh->gh_iflags))
- gfs_holder_put(gh);
- else
- complete(&gh->gh_wait);
- }
-}
-
-/**
- * gfs_glock_xmote_th - Call into the lock module to acquire or change a glock
- * @gl: The glock in question
- * @state: the requested state
- * @flags: modifier flags to the lock call
- *
- * Used to acquire a new glock, or to change an already-acquired glock to
- * more/less restrictive state (other than LM_ST_UNLOCKED).
- *
- * *Not* used to unlock a glock; use gfs_glock_drop_th() for that.
- */
-
-void
-gfs_glock_xmote_th(struct gfs_glock *gl, unsigned int state, int flags)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_glock_operations *glops = gl->gl_ops;
- int lck_flags = flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB |
- LM_FLAG_NOEXP | LM_FLAG_ANY |
- LM_FLAG_PRIORITY);
- unsigned int lck_ret;
-
- gfs_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
- gfs_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
- gfs_assert_warn(sdp, state != LM_ST_UNLOCKED);
- gfs_assert_warn(sdp, state != gl->gl_state);
-
- /* Current state EX, may need to sync log/data/metadata to disk */
- if (gl->gl_state == LM_ST_EXCLUSIVE) {
- if (glops->go_sync)
- glops->go_sync(gl, DIO_METADATA | DIO_DATA);
- }
-
- glock_hold(gl);
- gl->gl_req_bh = xmote_bh;
-
- atomic_inc(&sdp->sd_lm_lock_calls);
-
- lck_ret = gfs_lm_lock(sdp, gl->gl_lock,
- gl->gl_state, state,
- lck_flags);
-
- if (gfs_assert_withdraw(sdp, !(lck_ret & LM_OUT_ERROR)))
- goto out;
-
- if (lck_ret & LM_OUT_ASYNC)
- gfs_assert_warn(sdp, lck_ret == LM_OUT_ASYNC);
- else
- xmote_bh(gl, lck_ret);
- out:
- return;
-}
-
-/**
- * drop_bh - Called after a lock module unlock completes
- * @gl: the glock
- * @ret: the return status
- *
- * Doesn't wake up the process waiting on the struct gfs_holder (if any)
- * Doesn't drop the reference on the glock the top half took out
- *
- */
-
-static void
-drop_bh(struct gfs_glock *gl, unsigned int ret)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_glock_operations *glops = gl->gl_ops;
- struct gfs_holder *gh = gl->gl_req_gh;
-
- clear_bit(GLF_PREFETCH, &gl->gl_flags);
-
- gfs_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
- gfs_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
- gfs_assert_warn(sdp, !ret);
-
- state_change(gl, LM_ST_UNLOCKED);
-
- if (glops->go_inval)
- glops->go_inval(gl, DIO_METADATA | DIO_DATA);
-
- if (gh) {
- spin_lock(&gl->gl_spin);
- list_del_init(&gh->gh_list);
- gh->gh_error = 0;
- spin_unlock(&gl->gl_spin);
- }
-
- if (glops->go_drop_bh)
- glops->go_drop_bh(gl);
-
- spin_lock(&gl->gl_spin);
- gl->gl_req_gh = NULL;
- gl->gl_req_bh = NULL;
- clear_bit(GLF_LOCK, &gl->gl_flags);
- run_queue(gl);
- if (test_bit(GLF_DEMOTE, &gl->gl_flags))
- gfs_demote_wake(gl);
- spin_unlock(&gl->gl_spin);
- glock_put(gl);
-
- if (gh) {
- if (test_bit(HIF_DEALLOC, &gh->gh_iflags))
- gfs_holder_put(gh);
- else
- complete(&gh->gh_wait);
- }
-}
-
-/**
- * gfs_glock_drop_th - call into the lock module to unlock a lock
- * @gl: the glock
- *
- */
-
-void
-gfs_glock_drop_th(struct gfs_glock *gl)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_glock_operations *glops = gl->gl_ops;
- unsigned int ret;
-
- gfs_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
- gfs_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
- gfs_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED);
-
- /* Leaving state EX, may need to sync log/data/metadata to disk */
- if (gl->gl_state == LM_ST_EXCLUSIVE) {
- if (glops->go_sync)
- glops->go_sync(gl, DIO_METADATA | DIO_DATA);
- }
-
- glock_hold(gl);
- gl->gl_req_bh = drop_bh;
-
- atomic_inc(&sdp->sd_lm_unlock_calls);
-
- ret = gfs_lm_unlock(sdp, gl->gl_lock, gl->gl_state);
-
- if (gfs_assert_withdraw(sdp, !(ret & LM_OUT_ERROR)))
- goto out;
-
- if (!ret)
- drop_bh(gl, ret);
- else
- gfs_assert_warn(sdp, ret == LM_OUT_ASYNC);
- out:
- return;
-}
-
-/**
- * do_cancels - cancel requests for locks stuck waiting on an expire flag
- * @gh: the LM_FLAG_PRIORITY holder waiting to acquire the lock
- *
- * Don't cancel GL_NOCANCEL requests.
- */
-
-static void
-do_cancels(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
-
- spin_lock(&gl->gl_spin);
-
- while (gl->gl_req_gh != gh &&
- !test_bit(HIF_HOLDER, &gh->gh_iflags) &&
- !list_empty(&gh->gh_list)) {
- if (gl->gl_req_bh &&
- !(gl->gl_req_gh &&
- (gl->gl_req_gh->gh_flags & GL_NOCANCEL))) {
- spin_unlock(&gl->gl_spin);
- gfs_lm_cancel(gl->gl_sbd, gl->gl_lock);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 10);
- spin_lock(&gl->gl_spin);
- } else {
- spin_unlock(&gl->gl_spin);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 10);
- spin_lock(&gl->gl_spin);
- }
- }
-
- spin_unlock(&gl->gl_spin);
-}
-
-/**
- * glock_wait_internal - wait on a glock acquisition
- * @gh: the glock holder
- *
- * Returns: 0 on success
- */
-
-static int
-glock_wait_internal(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_glock_operations *glops = gl->gl_ops;
- int error = 0;
-
- if (test_bit(HIF_ABORTED, &gh->gh_iflags))
- return -EIO;
-
- if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) {
- spin_lock(&gl->gl_spin);
- if (gl->gl_req_gh != gh &&
- !test_bit(HIF_HOLDER, &gh->gh_iflags) &&
- !list_empty(&gh->gh_list)) {
- if (gh->gh_flags & GL_FLOCK &&
- list_empty(&gl->gl_holders)) {
- spin_unlock(&gl->gl_spin);
- goto skip_try_flag;
- }
- list_del_init(&gh->gh_list);
- gh->gh_error = GLR_TRYFAILED;
- if (test_bit(HIF_RECURSE, &gh->gh_iflags))
- do_unrecurse(gh);
- run_queue(gl);
- spin_unlock(&gl->gl_spin);
- return GLR_TRYFAILED;
- }
- spin_unlock(&gl->gl_spin);
- }
-
-skip_try_flag:
- if ((gh->gh_flags & LM_FLAG_PRIORITY) &&
- !(gh->gh_flags & GL_NOCANCEL_OTHER))
- do_cancels(gh);
-
- wait_for_completion(&gh->gh_wait);
-
- if (gh->gh_error)
- return gh->gh_error;
-
- gfs_assert_withdraw(sdp, test_bit(HIF_HOLDER, &gh->gh_iflags));
- gfs_assert_withdraw(sdp, relaxed_state_ok(gl->gl_state,
- gh->gh_state,
- gh->gh_flags));
-
- if (test_bit(HIF_FIRST, &gh->gh_iflags)) {
- gfs_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
-
- if (glops->go_lock) {
- error = glops->go_lock(gl, gh->gh_flags);
- if (error) {
- spin_lock(&gl->gl_spin);
- list_del_init(&gh->gh_list);
- gh->gh_error = error;
- if (test_and_clear_bit(HIF_RECURSE, &gh->gh_iflags))
- do_unrecurse(gh);
- spin_unlock(&gl->gl_spin);
- }
- }
-
- spin_lock(&gl->gl_spin);
- gl->gl_req_gh = NULL;
- gl->gl_req_bh = NULL;
- clear_bit(GLF_LOCK, &gl->gl_flags);
- if (test_bit(HIF_RECURSE, &gh->gh_iflags))
- handle_recurse(gh);
- run_queue(gl);
- spin_unlock(&gl->gl_spin);
- }
-
- return error;
-}
-
-/**
- * add_to_queue - Add a holder to the wait-for-promotion queue or holder list
- * (according to recursion)
- * @gh: the holder structure to add
- *
- * If the hold requestor's process already has a granted lock (on holder list),
- * and this new request is compatible, go ahead and grant it, adding this
- * new holder to the glock's holder list.
- *
- * If the hold requestor's process has earlier requested a lock, and is still
- * waiting for it to be granted, and this new request is compatible with
- * the earlier one, they can be handled at the same time when the request
- * is finally granted. Mark both (all) with RECURSE flags, and add new
- * holder to wait-for-promotion queue.
- *
- * If there is no previous holder from this process (on holder list or wait-
- * for-promotion queue), simply add new holder to wait-for-promotion queue.
- */
-
-static void
-add_to_queue(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct list_head *tmp, *head;
- struct gfs_holder *tmp_gh;
-
- if (gh->gh_owner) {
- /* Search through glock's holders list to see if this process
- already holds a granted lock. */
- for (head = &gl->gl_holders, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- tmp_gh = list_entry(tmp, struct gfs_holder, gh_list);
- if (tmp_gh->gh_owner == gh->gh_owner) {
- /* Make sure pre-existing holder is compatible
- with this new one. */
- if (!(gh->gh_flags & GL_FLOCK) &&
- (gfs_assert_warn(sdp, (gh->gh_flags & LM_FLAG_ANY) ||
- !(tmp_gh->gh_flags & LM_FLAG_ANY)) ||
- gfs_assert_warn(sdp, (tmp_gh->gh_flags & GL_LOCAL_EXCL) ||
- !(gh->gh_flags & GL_LOCAL_EXCL)) ||
- gfs_assert_warn(sdp, relaxed_state_ok(gl->gl_state,
- gh->gh_state,
- gh->gh_flags))))
- goto fail;
-
- /* We're good! Grant the hold. */
- list_add_tail(&gh->gh_list, &gl->gl_holders);
- set_bit(HIF_HOLDER, &gh->gh_iflags);
-
- gh->gh_error = 0;
- complete(&gh->gh_wait);
-
- return;
- }
- }
-
- /* If not, Search through glock's wait-for-promotion list to
- see if this process already is waiting for a grant. */
- for (head = &gl->gl_waiters3, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- tmp_gh = list_entry(tmp, struct gfs_holder, gh_list);
- if (tmp_gh->gh_owner == gh->gh_owner) {
- /* Yes, make sure it is compatible with new */
- if (!(gh->gh_flags & GL_FLOCK) &&
- (gfs_assert_warn(sdp, test_bit(HIF_PROMOTE,
- &tmp_gh->gh_iflags)) ||
- gfs_assert_warn(sdp, (gh->gh_flags & LM_FLAG_ANY) ||
- !(tmp_gh->gh_flags & LM_FLAG_ANY)) ||
- gfs_assert_warn(sdp, (tmp_gh->gh_flags & GL_LOCAL_EXCL) ||
- !(gh->gh_flags & GL_LOCAL_EXCL)) ||
- gfs_assert_warn(sdp, relaxed_state_ok(tmp_gh->gh_state,
- gh->gh_state,
- gh->gh_flags))))
- goto fail;
-
- /* OK, make sure they're marked, so
- * when one gets granted, the other will too. */
- set_bit(HIF_RECURSE, &gh->gh_iflags);
- set_bit(HIF_RECURSE, &tmp_gh->gh_iflags);
-
- list_add_tail(&gh->gh_list, &gl->gl_waiters3);
-
- return;
- }
- }
- }
-
- /* Else, no recursion ...
- If high priority request, add to head of promote queue, else tail */
- if (gh->gh_flags & LM_FLAG_PRIORITY)
- list_add(&gh->gh_list, &gl->gl_waiters3);
- else
- list_add_tail(&gh->gh_list, &gl->gl_waiters3);
-
- return;
-
- fail:
- set_bit(HIF_ABORTED, &gh->gh_iflags);
-}
-
-/**
- * gfs_glock_nq - enqueue a struct gfs_holder onto a glock (acquire a glock)
- * @gh: the holder structure
- *
- * if (gh->gh_flags & GL_ASYNC), this never returns an error
- *
- * Returns: 0, GLR_TRYFAILED, or errno on failure
- *
- * Rules:
- * @gh must not be already attached to a glock.
- * Don't ask for UNLOCKED state (use gfs_glock_dq() for that).
- * LM_FLAG_ANY (liberal) and GL_EXACT (restrictive) are mutually exclusive.
- */
-
-int
-gfs_glock_nq(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- struct gfs_sbd *sdp = gl->gl_sbd;
- int error = 0;
-
- atomic_inc(&sdp->sd_glock_nq_calls);
-
- restart:
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) ||
- gfs_assert_warn(sdp, list_empty(&gh->gh_list)) ||
- gfs_assert_warn(sdp, gh->gh_state != LM_ST_UNLOCKED) ||
- gfs_assert_warn(sdp, (gh->gh_flags & (LM_FLAG_ANY | GL_EXACT)) !=
- (LM_FLAG_ANY | GL_EXACT))) {
- set_bit(HIF_ABORTED, &gh->gh_iflags);
- return -EIO;
- }
-
- set_bit(HIF_PROMOTE, &gh->gh_iflags);
-
- spin_lock(&gl->gl_spin);
- add_to_queue(gh);
- run_queue(gl);
- spin_unlock(&gl->gl_spin);
-
- if (!(gh->gh_flags & GL_ASYNC)) {
- error = glock_wait_internal(gh);
- if (error == GLR_CANCELED) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
- goto restart;
- }
- }
-
- clear_bit(GLF_PREFETCH, &gl->gl_flags);
-
- return error;
-}
-
-/**
- * gfs_glock_poll - poll to see if an async request has been completed
- * @gh: the holder
- *
- * Returns: TRUE if the request is ready to be gfs_glock_wait()ed on
- */
-
-int
-gfs_glock_poll(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- int ready = FALSE;
-
- gfs_assert_warn(gl->gl_sbd, gh->gh_flags & GL_ASYNC);
-
- spin_lock(&gl->gl_spin);
-
- if (test_bit(HIF_HOLDER, &gh->gh_iflags))
- ready = TRUE;
- else if (list_empty(&gh->gh_list)) {
- if (gh->gh_error == GLR_CANCELED) {
- spin_unlock(&gl->gl_spin);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
- if (gfs_glock_nq(gh))
- return TRUE;
- return FALSE;
- } else
- ready = TRUE;
- }
-
- spin_unlock(&gl->gl_spin);
-
- return ready;
-}
-
-/**
- * gfs_glock_wait - wait for a lock acquisition that ended in a GLR_ASYNC
- * @gh: the holder structure
- *
- * Returns: 0, GLR_TRYFAILED, or errno on failure
- */
-
-int
-gfs_glock_wait(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- int error;
-
- gfs_assert_warn(gl->gl_sbd, gh->gh_flags & GL_ASYNC);
-
- error = glock_wait_internal(gh);
- if (error == GLR_CANCELED) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
- gh->gh_flags &= ~GL_ASYNC;
- error = gfs_glock_nq(gh);
- }
-
- return error;
-}
-
-/**
- * gfs_glock_dq - dequeue a struct gfs_holder from a glock (release a glock)
- * @gh: the glock holder
- *
- * This releases a local process' hold on a glock, and services other waiters.
- * If this is the last holder on this node, calls glock operation go_unlock(),
- * and go_sync() if requested by glock's GL_SYNC flag.
- * If glock's GL_NOCACHE flag is set, requests demotion to unlock the inter-
- * node lock now, rather than caching the glock for later use.
- * Otherwise, this function does *not* release the glock at inter-node scope.
- * The glock will stay in glock cache until:
- * -- This node uses it again (extending residence in glock cache), or
- * -- Another node asks (via callback) for the lock, or
- * -- The glock sits unused in glock cache for a while, and the cleanup
- * daemons (gfs_scand and gfs_glockd) reclaim it.
- */
-
-void
-gfs_glock_dq(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_glock_operations *glops = gl->gl_ops;
-
- atomic_inc(&gl->gl_sbd->sd_glock_dq_calls);
-
- gfs_assert_withdraw(sdp, !queue_empty(gl, &gh->gh_list));
- gfs_assert_withdraw(sdp, test_bit(HIF_HOLDER, &gh->gh_iflags));
-
- if (gh->gh_flags & GL_SYNC)
- set_bit(GLF_SYNC, &gl->gl_flags);
-
- /* Don't cache glock; request demote to unlock at inter-node scope */
- if (gh->gh_flags & GL_NOCACHE && gl->gl_holders.next == &gh->gh_list &&
- gl->gl_holders.prev == &gh->gh_list)
- /* There's a race here. If there are two holders, and both
- * are dq'ed at almost the same time, you can't guarantee that
- * you will call handle_callback. Fixing this will require
- * some refactoring */
- handle_callback(gl, LM_ST_UNLOCKED);
-
- lock_on_glock(gl);
-
- spin_lock(&gl->gl_spin);
- list_del_init(&gh->gh_list);
-
- /* If last holder, do appropriate glock operations, set cache timer */
- if (list_empty(&gl->gl_holders)) {
- spin_unlock(&gl->gl_spin);
-
- if (glops->go_unlock)
- glops->go_unlock(gl, gh->gh_flags);
-
- /* Do "early" sync, if requested by holder */
- if (test_bit(GLF_SYNC, &gl->gl_flags)) {
- if (glops->go_sync)
- glops->go_sync(gl,
- DIO_METADATA |
- DIO_DATA |
- DIO_INVISIBLE);
- }
-
- gl->gl_stamp = jiffies;
-
- spin_lock(&gl->gl_spin);
- }
-
- clear_bit(GLF_LOCK, &gl->gl_flags);
- run_queue(gl);
- spin_unlock(&gl->gl_spin);
-}
-
-/**
- * gfs_glock_prefetch - Try to prefetch a glock
- * @gl: the glock
- * @state: the state to prefetch in
- * @flags: flags passed to go_xmote_th()
- *
- * Bypass request queues of glock (i.e. no holder involved), and directly call
- * go_xmote_th() to ask lock module for lock, to put in glock cache for
- * later use.
- *
- * Will not prefetch the lock (no need to) if a process on this node is already
- * interested in the lock, or if it's sitting in glock cache in a compatible
- * state.
- *
- * Rules:
- * Don't ask for UNLOCKED state (use gfs_glock_dq() for that).
- * LM_FLAG_ANY (liberal) and GL_EXACT (restrictive) are mutually exclusive.
- */
-
-void
-gfs_glock_prefetch(struct gfs_glock *gl, unsigned int state, int flags)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_glock_operations *glops = gl->gl_ops;
-
- if (gfs_assert_warn(sdp, state != LM_ST_UNLOCKED) ||
- gfs_assert_warn(sdp, (flags & (LM_FLAG_ANY | GL_EXACT)) !=
- (LM_FLAG_ANY | GL_EXACT)))
- return;
-
- spin_lock(&gl->gl_spin);
-
- /* Should we prefetch? */
- if (test_bit(GLF_LOCK, &gl->gl_flags) ||
- !list_empty(&gl->gl_holders) ||
- !list_empty(&gl->gl_waiters1) ||
- !list_empty(&gl->gl_waiters2) ||
- !list_empty(&gl->gl_waiters3) ||
- relaxed_state_ok(gl->gl_state, state, flags)) {
- spin_unlock(&gl->gl_spin);
- return;
- }
-
- /* Let bottom half know we're prefetching, ask lock module for lock */
- set_bit(GLF_PREFETCH, &gl->gl_flags);
-
- if (gfs_assert_warn(sdp, !gl->gl_req_gh))
- gl->gl_req_gh = NULL;
- set_bit(GLF_LOCK, &gl->gl_flags);
- spin_unlock(&gl->gl_spin);
-
- glops->go_xmote_th(gl, state, flags);
-
- atomic_inc(&gl->gl_sbd->sd_glock_prefetch_calls);
-}
-
-/**
- * gfs_glock_force_drop - Force a glock to be uncached
- * @gl: the glock
- *
- */
-
-void
-gfs_glock_force_drop(struct gfs_glock *gl)
-{
- struct gfs_holder gh;
-
- gfs_holder_init(gl, LM_ST_UNLOCKED, 0, &gh);
- set_bit(HIF_DEMOTE, &gh.gh_iflags);
- gh.gh_owner = NULL;
-
- spin_lock(&gl->gl_spin);
- list_add_tail(&gh.gh_list, &gl->gl_waiters2);
- run_queue(gl);
- spin_unlock(&gl->gl_spin);
-
- wait_for_completion(&gh.gh_wait);
- gfs_holder_uninit(&gh);
-}
-
-/**
- * greedy_work -
- * @data:
- *
- */
-
-static void
-greedy_work(struct work_struct *work)
-{
- struct greedy *gr = container_of(work, struct greedy, gr_work.work);
- struct gfs_holder *gh = &gr->gr_gh;
- struct gfs_glock *gl = gh->gh_gl;
- struct gfs_glock_operations *glops = gl->gl_ops;
-
- clear_bit(GLF_SKIP_WAITERS2, &gl->gl_flags);
-
- if (glops->go_greedy)
- glops->go_greedy(gl);
-
- spin_lock(&gl->gl_spin);
-
- if (list_empty(&gl->gl_waiters2)) {
- clear_bit(GLF_GREEDY, &gl->gl_flags);
- spin_unlock(&gl->gl_spin);
- gfs_holder_uninit(gh);
- kfree(gr);
- } else {
- glock_hold(gl);
- list_add_tail(&gh->gh_list, &gl->gl_waiters2);
- run_queue(gl);
- spin_unlock(&gl->gl_spin);
- glock_put(gl);
- }
-}
-
-/**
- * gfs_glock_be_greedy -
- * @gl:
- * @time:
- *
- * Returns: 0 if go_greedy will be called, 1 otherwise
- */
-
-int
-gfs_glock_be_greedy(struct gfs_glock *gl, unsigned int time)
-{
- struct greedy *gr;
- struct gfs_holder *gh;
-
- if (!time ||
- gl->gl_sbd->sd_args.ar_localcaching ||
- test_and_set_bit(GLF_GREEDY, &gl->gl_flags))
- return 1;
-
- gr = kmalloc(sizeof(struct greedy), GFP_KERNEL);
- if (!gr) {
- clear_bit(GLF_GREEDY, &gl->gl_flags);
- return 1;
- }
- gh = &gr->gr_gh;
-
- gfs_holder_init(gl, 0, 0, gh);
- set_bit(HIF_GREEDY, &gh->gh_iflags);
- gh->gh_owner = NULL;
- INIT_DELAYED_WORK(&gr->gr_work, greedy_work);
-
- set_bit(GLF_SKIP_WAITERS2, &gl->gl_flags);
- schedule_delayed_work(&gr->gr_work, time);
-
- return 0;
-}
-
-/**
- * gfs_glock_nq_init - intialize a holder and enqueue it on a glock
- * @gl: the glock
- * @state: the state we're requesting
- * @flags: the modifier flags
- * @gh: the holder structure
- *
- * Returns: 0, GLR_*, or errno
- */
-
-int
-gfs_glock_nq_init(struct gfs_glock *gl, unsigned int state, int flags,
- struct gfs_holder *gh)
-{
- int error;
-
- gfs_holder_init(gl, state, flags, gh);
-
- error = gfs_glock_nq(gh);
- if (error)
- gfs_holder_uninit(gh);
-
- return error;
-}
-
-/**
- * gfs_glock_dq_uninit - dequeue a holder from a glock and initialize it
- * @gh: the holder structure
- *
- */
-
-void
-gfs_glock_dq_uninit(struct gfs_holder *gh)
-{
- gfs_glock_dq(gh);
- gfs_holder_uninit(gh);
-}
-
-/**
- * gfs_glock_nq_num - acquire a glock based on lock number
- * @sdp: the filesystem
- * @number: the lock number
- * @glops: the glock operations for the type of glock
- * @state: the state to acquire the glock in
- * @flags: modifier flags for the aquisition
- * @gh: the struct gfs_holder
- *
- * Returns: errno
- */
-
-int
-gfs_glock_nq_num(struct gfs_sbd *sdp,
- uint64_t number, struct gfs_glock_operations *glops,
- unsigned int state, int flags, struct gfs_holder *gh)
-{
- struct gfs_glock *gl;
- int error;
-
- error = gfs_glock_get(sdp, number, glops, CREATE, &gl);
- if (!error) {
- error = gfs_glock_nq_init(gl, state, flags, gh);
- glock_put(gl);
- }
-
- return error;
-}
-
-/**
- * glock_compare - Compare two struct gfs_glock structures for sorting
- * @arg_a: the first structure
- * @arg_b: the second structure
- *
- */
-
-static int
-glock_compare(const void *arg_a, const void *arg_b)
-{
- struct gfs_holder *gh_a = *(struct gfs_holder **)arg_a;
- struct gfs_holder *gh_b = *(struct gfs_holder **)arg_b;
- struct lm_lockname *a = &gh_a->gh_gl->gl_name;
- struct lm_lockname *b = &gh_b->gh_gl->gl_name;
- int ret = 0;
-
- if (a->ln_number > b->ln_number)
- ret = 1;
- else if (a->ln_number < b->ln_number)
- ret = -1;
- else {
- if (gh_a->gh_state == LM_ST_SHARED &&
- gh_b->gh_state == LM_ST_EXCLUSIVE)
- ret = 1;
- else if (!(gh_a->gh_flags & GL_LOCAL_EXCL) &&
- (gh_b->gh_flags & GL_LOCAL_EXCL))
- ret = 1;
- }
-
- return ret;
-}
-
-/**
- * nq_m_sync - synchonously acquire more than one glock in deadlock free order
- * @num_gh: the number of structures
- * @ghs: an array of struct gfs_holder structures
- *
- * Returns: 0 on success (all glocks acquired), errno on failure (no glocks acquired)
- */
-
-static int
-nq_m_sync(unsigned int num_gh, struct gfs_holder *ghs, struct gfs_holder **p)
-{
- unsigned int x;
- int error = 0;
-
- for (x = 0; x < num_gh; x++)
- p[x] = &ghs[x];
-
- gfs_sort(p, num_gh, sizeof(struct gfs_holder *), glock_compare);
-
- for (x = 0; x < num_gh; x++) {
- p[x]->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
-
- error = gfs_glock_nq(p[x]);
- if (error) {
- while (x--)
- gfs_glock_dq(p[x]);
- break;
- }
- }
-
- return error;
-}
-
-/**
- * gfs_glock_nq_m - acquire multiple glocks
- * @num_gh: the number of structures
- * @ghs: an array of struct gfs_holder structures
- *
- * Figure out how big an impact this function has. Either:
- * 1) Replace this code with code that calls gfs_glock_prefetch()
- * 2) Forget async stuff and just call nq_m_sync()
- * 3) Leave it like it is
- *
- * Returns: 0 on success (all glocks acquired), errno on failure (no glocks acquired)
- */
-
-int
-gfs_glock_nq_m(unsigned int num_gh, struct gfs_holder *ghs)
-{
- int *e;
- unsigned int x;
- int borked = FALSE, serious = 0;
- int error = 0;
-
- if (!num_gh)
- return 0;
-
- /* For just one gh, do request synchronously */
- if (num_gh == 1) {
- ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
- return gfs_glock_nq(ghs);
- }
-
- /* using sizeof(struct gfs_holder *) instead of sizeof(int), because
- * we're also using this memory for nq_m_sync and ints should never be
- * larger than pointers.... I hope
- */
- e = kmalloc(num_gh * sizeof(struct gfs_holder *), GFP_KERNEL);
- if (!e)
- return -ENOMEM;
-
- /* Send off asynchronous requests */
- for (x = 0; x < num_gh; x++) {
- ghs[x].gh_flags |= LM_FLAG_TRY | GL_ASYNC;
- error = gfs_glock_nq(&ghs[x]);
- if (error) {
- borked = TRUE;
- serious = error;
- num_gh = x;
- break;
- }
- }
-
- /* Wait for all to complete */
- for (x = 0; x < num_gh; x++) {
- error = e[x] = glock_wait_internal(&ghs[x]);
- if (error) {
- borked = TRUE;
- if (error != GLR_TRYFAILED && error != GLR_CANCELED)
- serious = error;
- }
- }
-
- /* If all good, done! */
- if (!borked) {
- kfree(e);
- return 0;
- }
-
- for (x = 0; x < num_gh; x++)
- if (!e[x])
- gfs_glock_dq(&ghs[x]);
-
- if (serious)
- error = serious;
- else {
- for (x = 0; x < num_gh; x++)
- gfs_holder_reinit(ghs[x].gh_state, ghs[x].gh_flags,
- &ghs[x]);
- error = nq_m_sync(num_gh, ghs, (struct gfs_holder **)e);
- }
-
- kfree(e);
- return error;
-}
-
-/**
- * gfs_glock_dq_m - release multiple glocks
- * @num_gh: the number of structures
- * @ghs: an array of struct gfs_holder structures
- *
- */
-
-void
-gfs_glock_dq_m(unsigned int num_gh, struct gfs_holder *ghs)
-{
- unsigned int x;
-
- for (x = 0; x < num_gh; x++)
- gfs_glock_dq(&ghs[x]);
-}
-
-/**
- * gfs_glock_prefetch_num - prefetch a glock based on lock number
- * @sdp: the filesystem
- * @number: the lock number
- * @glops: the glock operations for the type of glock
- * @state: the state to acquire the glock in
- * @flags: modifier flags for the aquisition
- *
- * Returns: errno
- */
-
-void
-gfs_glock_prefetch_num(struct gfs_sbd *sdp,
- uint64_t number, struct gfs_glock_operations *glops,
- unsigned int state, int flags)
-{
- struct gfs_glock *gl;
- int error;
-
- if (atomic_read(&sdp->sd_reclaim_count) < gfs_tune_get(sdp, gt_reclaim_limit)) {
- error = gfs_glock_get(sdp, number, glops, CREATE, &gl);
- if (!error) {
- gfs_glock_prefetch(gl, state, flags);
- glock_put(gl);
- }
- }
-}
-
-/**
- * gfs_lvb_hold - attach a LVB from a glock
- * @gl: The glock in question
- *
- */
-
-int
-gfs_lvb_hold(struct gfs_glock *gl)
-{
- int error;
-
- lock_on_glock(gl);
-
- if (!atomic_read(&gl->gl_lvb_count)) {
- gfs_assert_warn(gl->gl_sbd, !gl->gl_lvb);
- error = gfs_lm_hold_lvb(gl->gl_sbd, gl->gl_lock, &gl->gl_lvb);
- if (error) {
- unlock_on_glock(gl);
- return error;
- }
- glock_hold(gl);
- }
- atomic_inc(&gl->gl_lvb_count);
-
- unlock_on_glock(gl);
-
- return 0;
-}
-
-/**
- * gfs_lvb_unhold - detach a LVB from a glock
- * @gl: The glock in question
- *
- */
-
-void
-gfs_lvb_unhold(struct gfs_glock *gl)
-{
- glock_hold(gl);
-
- lock_on_glock(gl);
-
- if (!gfs_assert_warn(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0) &&
- atomic_dec_and_test(&gl->gl_lvb_count)) {
- gfs_assert_warn(gl->gl_sbd, gl->gl_lvb);
- gfs_lm_unhold_lvb(gl->gl_sbd, gl->gl_lock, gl->gl_lvb);
- gl->gl_lvb = NULL;
- glock_put(gl);
- }
-
- unlock_on_glock(gl);
-
- glock_put(gl);
-}
-
-#if 0
-/**
- * gfs_lvb_sync - sync a LVB
- * @gl: The glock in question
- *
- */
-
-void
-gfs_lvb_sync(struct gfs_glock *gl)
-{
- if (gfs_assert_warn(gl->gl_sbd, atomic_read(&gl->gl_lvb_count)))
- return;
-
- lock_on_glock(gl);
-
- if (!gfs_assert_warn(gl->gl_sbd, gfs_glock_is_held_excl(gl)))
- gfs_lm_sync_lvb(gl->gl_sbd, gl->gl_lock, gl->gl_lvb);
-
- unlock_on_glock(gl);
-}
-#endif
-
-/**
- * blocking_cb -
- * @sdp:
- * @name:
- * @state:
- *
- */
-
-void
-blocking_cb(struct gfs_sbd *sdp, struct lm_lockname *name, unsigned int state)
-{
- struct gfs_glock *gl;
-
- gl = gfs_glock_find(sdp, name);
- if (!gl)
- return;
-
- if (gl->gl_ops->go_callback)
- gl->gl_ops->go_callback(gl, state);
- handle_callback(gl, state);
-
- spin_lock(&gl->gl_spin);
- run_queue(gl);
- spin_unlock(&gl->gl_spin);
-
- glock_put(gl);
-}
-
-/**
- * gfs_glock_cb - Callback used by locking module
- * @fsdata: Pointer to the superblock
- * @type: Type of callback
- * @data: Type dependent data pointer
- *
- * Called by the locking module when it wants to tell us something.
- * Either we need to drop a lock, one of our ASYNC requests completed, or
- * another client expired (crashed/died) and we need to recover its journal.
- * If another node needs a lock held by this node, we queue a request to demote
- * our lock to a state compatible with that needed by the other node.
- * For example, if the other node needs EXCLUSIVE, we request UNLOCKED.
- * SHARED and DEFERRED modes can be shared with other nodes, so we request
- * accordingly.
- * Once all incompatible holders on this node are done with the lock, the
- * queued request will cause run_queue() to call the lock module to demote
- * our lock to a compatible state, allowing the other node to grab the lock.
- */
-
-void
-gfs_glock_cb(void *fsdata, unsigned int type, void *data)
-{
- struct gfs_sbd *sdp = fsdata;
-
- atomic_inc(&sdp->sd_lm_callbacks);
-
- switch (type) {
- case LM_CB_NEED_E:
- blocking_cb(sdp, (struct lm_lockname *)data, LM_ST_UNLOCKED);
- return;
-
- case LM_CB_NEED_D:
- blocking_cb(sdp, (struct lm_lockname *)data, LM_ST_DEFERRED);
- return;
-
- case LM_CB_NEED_S:
- blocking_cb(sdp, (struct lm_lockname *)data, LM_ST_SHARED);
- return;
-
- case LM_CB_ASYNC: {
- struct lm_async_cb *async = (struct lm_async_cb *)data;
- struct gfs_glock *gl;
-
- gl = gfs_glock_find(sdp, &async->lc_name);
- if (gfs_assert_warn(sdp, gl))
- return;
- if (!gfs_assert_warn(sdp, gl->gl_req_bh))
- gl->gl_req_bh(gl, async->lc_ret);
- glock_put(gl);
-
- return;
- }
-
- case LM_CB_NEED_RECOVERY:
- gfs_add_dirty_j(sdp, *(unsigned int *)data);
- if (sdp->sd_recoverd_process)
- wake_up_process(sdp->sd_recoverd_process);
- return;
-
- case LM_CB_DROPLOCKS:
- gfs_gl_hash_clear(sdp, FALSE);
- gfs_quota_scan(sdp);
- return;
-
- default:
- gfs_assert_warn(sdp, FALSE);
- return;
- }
-}
-
-/**
- * gfs_try_toss_inode - try to remove a particular GFS inode struct from cache
- * sdp: the filesystem
- * inum: the inode number
- *
- * Look for the glock protecting the inode of interest.
- * If no process is manipulating or holding the glock, see if the glock
- * has a gfs_inode attached.
- * If gfs_inode has no references, unhold its iopen glock, release any
- * indirect addressing buffers, and destroy the gfs_inode.
- */
-
-void
-gfs_try_toss_inode(struct gfs_sbd *sdp, struct gfs_inum *inum)
-{
- struct gfs_glock *gl;
- struct gfs_inode *ip;
- int error;
-
- error = gfs_glock_get(sdp,
- inum->no_formal_ino, &gfs_inode_glops,
- NO_CREATE, &gl);
- if (error || !gl)
- return;
-
- if (!trylock_on_glock(gl))
- goto out;
-
- if (!queue_empty(gl, &gl->gl_holders))
- goto out_unlock;
-
- ip = get_gl2ip(gl);
- if (!ip)
- goto out_unlock;
-
- if (atomic_read(&ip->i_count))
- goto out_unlock;
-
- gfs_inode_destroy(ip);
-
- out_unlock:
- unlock_on_glock(gl);
-
- out:
- glock_put(gl);
-}
-
-/**
- * gfs_iopen_go_callback - Try to kick the inode/vnode associated with an iopen glock from memory
- * @io_gl: the iopen glock
- * @state: the state into which the glock should be put
- *
- */
-
-void
-gfs_iopen_go_callback(struct gfs_glock *io_gl, unsigned int state)
-{
- struct gfs_glock *i_gl;
- struct gfs_inode *ip;
-
- if (state != LM_ST_UNLOCKED)
- return;
-
- spin_lock(&io_gl->gl_spin);
- i_gl = get_gl2gl(io_gl);
- if (i_gl) {
- glock_hold(i_gl);
- spin_unlock(&io_gl->gl_spin);
- } else {
- spin_unlock(&io_gl->gl_spin);
- return;
- }
-
- if (trylock_on_glock(i_gl)) {
- if (queue_empty(i_gl, &i_gl->gl_holders)) {
- ip = get_gl2ip(i_gl);
- if (ip) {
- gfs_try_toss_vnode(ip);
- unlock_on_glock(i_gl);
- gfs_glock_schedule_for_reclaim(i_gl);
- goto out;
- }
- }
- unlock_on_glock(i_gl);
- }
-
- out:
- glock_put(i_gl);
-}
-
-/**
- * demote_ok - Check to see if it's ok to unlock a glock (to remove it
- * from glock cache)
- * @gl: the glock
- *
- * Called when trying to reclaim glocks, once it's determined that the glock
- * has no holders on this node.
- *
- * Returns: TRUE if it's ok
- *
- * It's not okay if:
- * -- glock is STICKY
- * -- PREFETCHed glock has not been given enough chance to be used
- * -- glock-type-specific test says "no"
- */
-
-static int
-demote_ok(struct gfs_glock *gl)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_glock_operations *glops = gl->gl_ops;
- int demote = TRUE;
-
- if (test_bit(GLF_STICKY, &gl->gl_flags))
- demote = FALSE;
- else if (test_bit(GLF_PREFETCH, &gl->gl_flags))
- demote = time_after_eq(jiffies,
- gl->gl_stamp +
- gfs_tune_get(sdp, gt_prefetch_secs) * HZ);
- else if (glops->go_demote_ok)
- demote = glops->go_demote_ok(gl);
-
- return demote;
-}
-
-/**
- * gfs_glock_schedule_for_reclaim - Add a glock to the reclaim list
- * @gl: the glock
- *
- */
-
-void
-gfs_glock_schedule_for_reclaim(struct gfs_glock *gl)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
-
- spin_lock(&sdp->sd_reclaim_lock);
- if (list_empty(&gl->gl_reclaim)) {
- glock_hold(gl);
- list_add(&gl->gl_reclaim, &sdp->sd_reclaim_list);
- atomic_inc(&sdp->sd_reclaim_count);
- }
- spin_unlock(&sdp->sd_reclaim_lock);
-
- wake_up(&sdp->sd_reclaim_wchan);
-}
-
-/**
- * gfs_reclaim_glock - process the next glock on the filesystem's reclaim list
- * @sdp: the filesystem
- *
- * Called from gfs_glockd() glock reclaim daemon, or when promoting a
- * (different) glock and we notice that there are a lot of glocks in the
- * reclaim list.
- *
- * Remove glock from filesystem's reclaim list, update reclaim statistics.
- * If no holders (might have gotten added since glock was placed on reclaim
- * list):
- * -- Destroy any now-unused inode protected by glock
- * (and release hold on iopen glock).
- * -- Ask for demote to UNLOCKED to enable removal of glock from glock cache.
- *
- * If no further interest in glock struct, remove it from glock cache, and
- * free it from memory. (During normal operation, this is the only place
- * that this is done).
- *
- * Glock-type-specific considerations for permission to demote are handled
- * in demote_ok(). This includes how long to retain a glock in cache after it
- * is no longer held by any process.
- */
-
-void
-gfs_reclaim_glock(struct gfs_sbd *sdp)
-{
- struct gfs_glock *gl;
- struct gfs_gl_hash_bucket *bucket;
-
- spin_lock(&sdp->sd_reclaim_lock);
-
- /* Nothing to reclaim? Done! */
- if (list_empty(&sdp->sd_reclaim_list)) {
- spin_unlock(&sdp->sd_reclaim_lock);
- return;
- }
-
- /* Remove next victim from reclaim list */
- gl = list_entry(sdp->sd_reclaim_list.next,
- struct gfs_glock, gl_reclaim);
- list_del_init(&gl->gl_reclaim);
-
- spin_unlock(&sdp->sd_reclaim_lock);
-
- atomic_dec(&sdp->sd_reclaim_count);
- atomic_inc(&sdp->sd_reclaimed);
-
- if (trylock_on_glock(gl)) {
- if (queue_empty(gl, &gl->gl_holders)) {
- /* Inode glock-type-specific; free unused gfs inode,
- and release hold on iopen glock */
- if (gl->gl_ops == &gfs_inode_glops) {
- struct gfs_inode *ip = get_gl2ip(gl);
- if (ip && !atomic_read(&ip->i_count))
- gfs_inode_destroy(ip);
- }
- /* Generic (including inodes); try to unlock glock */
- if (gl->gl_state != LM_ST_UNLOCKED &&
- demote_ok(gl))
- handle_callback(gl, LM_ST_UNLOCKED);
- }
- unlock_on_glock(gl);
- }
-
- bucket = gl->gl_bucket;
-
- /* If glock struct's only remaining reference is from being put on
- the reclaim list, remove glock from hash table (sd_gl_hash),
- and free the glock's memory */
- write_lock(&bucket->hb_lock);
- if (atomic_read(&gl->gl_count) == 1) {
- list_del_init(&gl->gl_list);
- write_unlock(&bucket->hb_lock);
- glock_free(gl);
- } else {
- write_unlock(&bucket->hb_lock);
- glock_put(gl); /* see gfs_glock_schedule_for_reclaim() */
- }
-}
-
-/**
- * examine_bucket - Call a function for glock in a hash bucket
- * @examiner: the function
- * @sdp: the filesystem
- * @bucket: the bucket
- *
- * Returns: TRUE if the bucket has entries
- */
-
-static int
-examine_bucket(glock_examiner examiner,
- struct gfs_sbd *sdp, struct gfs_gl_hash_bucket *bucket,
- unsigned int *purge_nr)
-{
- struct glock_plug plug;
- struct list_head *tmp;
- struct gfs_glock *gl;
- int entries;
-
- /* Add "plug" to end of bucket list, work back up list from there */
- memset(&plug.gl_flags, 0, sizeof(unsigned long));
- set_bit(GLF_PLUG, &plug.gl_flags);
-
- write_lock(&bucket->hb_lock);
- list_add(&plug.gl_list, &bucket->hb_list);
- write_unlock(&bucket->hb_lock);
-
- /* Look at each bucket entry */
- for (;;) {
- write_lock(&bucket->hb_lock);
-
- /* Work back up list from plug */
- for (;;) {
- tmp = plug.gl_list.next;
-
- /* Top of list; we're done */
- if (tmp == &bucket->hb_list) {
- list_del(&plug.gl_list);
- entries = !list_empty(&bucket->hb_list);
- write_unlock(&bucket->hb_lock);
- return entries;
- }
- gl = list_entry(tmp, struct gfs_glock, gl_list);
-
- /* Move plug up list */
- list_move(&plug.gl_list, &gl->gl_list);
-
- if (test_bit(GLF_PLUG, &gl->gl_flags))
- continue;
-
- /* glock_hold; examiner must glock_put() */
- atomic_inc(&gl->gl_count);
-
- break;
- }
-
- write_unlock(&bucket->hb_lock);
-
- examiner(gl, purge_nr);
- }
-}
-
-static void
-try_purge_iopen(struct gfs_glock *gl, unsigned int *p_count)
-{
- struct gfs_glock *i_gl;
-
- if (*p_count == 0)
- return;
-
- /* find the associated inode glock */
- i_gl = get_gl2gl(gl);
- if (!i_gl)
- return;
-
- /*
- * If the associated inode glock has been in unlocked
- * state, try to purge it.
- */
- if (trylock_on_glock(i_gl)) {
- if (i_gl->gl_state == LM_ST_UNLOCKED) {
- *p_count = *p_count - 1;
- unlock_on_glock(i_gl);
- atomic_inc(&gl->gl_count);
- gfs_iopen_go_callback(gl, LM_ST_UNLOCKED);
- handle_callback(gl, LM_ST_UNLOCKED);
- spin_lock(&gl->gl_spin);
- run_queue(gl);
- spin_unlock(&gl->gl_spin);
- glock_put(gl);
- } else
- unlock_on_glock(i_gl);
- }
-
- return;
-}
-
-/**
- * scan_glock - look at a glock and see if we can reclaim it
- * @gl: the glock to look at
- *
- * Called via examine_bucket() when trying to release glocks from glock cache,
- * during normal operation (i.e. not unmount time).
- *
- * Place glock on filesystem's reclaim list if, on this node:
- * -- No process is manipulating glock struct, and
- * -- No current holders, and either:
- * -- GFS incore inode, protected by glock, is no longer in use, or
- * -- Glock-type-specific demote_ok glops gives permission
- */
-
-static void
-scan_glock(struct gfs_glock *gl, unsigned int *p_count)
-{
- if (trylock_on_glock(gl)) {
- if (queue_empty(gl, &gl->gl_holders)) {
- /* Inode glock-type-specific; reclaim glock if gfs inode
- no longer in use. */
- if (gl->gl_ops == &gfs_inode_glops) {
- struct gfs_inode *ip = get_gl2ip(gl);
- if (ip && !atomic_read(&ip->i_count)) {
- unlock_on_glock(gl);
- gfs_glock_schedule_for_reclaim(gl);
- goto out;
- }
- }
- /* Generic (including inodes not scheduled above) */
- if (gl->gl_state != LM_ST_UNLOCKED &&
- demote_ok(gl)) {
- unlock_on_glock(gl);
- gfs_glock_schedule_for_reclaim(gl);
- goto out;
- }
- }
- /* iopen always has holder(s) */
- if (gl->gl_name.ln_type == LM_TYPE_IOPEN) {
- unlock_on_glock(gl);
- try_purge_iopen(gl, p_count);
- goto out;
- }
- unlock_on_glock(gl);
- }
-
- out:
- glock_put(gl); /* see examine_bucket() */
-}
-
-/**
- * gfs_scand_internal - Look for glocks and inodes to toss from memory
- * @sdp: the filesystem
- *
- * Invokes scan_glock() for each glock in each cache bucket.
- *
- * Steps of reclaiming a glock:
- * -- scan_glock() places eligible glocks on filesystem's reclaim list.
- * -- gfs_reclaim_glock() processes list members, attaches demotion requests
- * to wait queues of glocks still locked at inter-node scope.
- * -- Demote to UNLOCKED state (if not already unlocked).
- * -- gfs_reclaim_lock() cleans up glock structure.
- */
-
-void
-gfs_scand_internal(struct gfs_sbd *sdp)
-{
- unsigned int x, purge_nr;
-
- if (!sdp->sd_tune.gt_glock_purge)
- purge_nr = 0;
- else
- purge_nr = atomic_read(&sdp->sd_glock_count) *
- sdp->sd_tune.gt_glock_purge / 100;
-
- for (x = 0; x < GFS_GL_HASH_SIZE; x++) {
- examine_bucket(scan_glock, sdp, &sdp->sd_gl_hash[x], &purge_nr);
- cond_resched();
- }
-}
-
-/**
- * clear_glock - look at a glock and see if we can free it from glock cache
- * @gl: the glock to look at
- *
- * Called via examine_bucket() when unmounting the filesystem, or
- * when inter-node lock manager requests DROPLOCKS because it is running
- * out of capacity.
- *
- * Similar to gfs_reclaim_glock(), except does *not*:
- * -- Consult demote_ok() for permission
- * -- Increment sdp->sd_reclaimed statistic
- *
- */
-
-static void
-clear_glock(struct gfs_glock *gl, unsigned int *unused)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_gl_hash_bucket *bucket = gl->gl_bucket;
-
- spin_lock(&sdp->sd_reclaim_lock);
- if (!list_empty(&gl->gl_reclaim)) {
- list_del_init(&gl->gl_reclaim);
- atomic_dec(&sdp->sd_reclaim_count);
- glock_put(gl); /* see gfs_glock_schedule_for_reclaim() */
- }
- spin_unlock(&sdp->sd_reclaim_lock);
-
- if (trylock_on_glock(gl)) {
- if (queue_empty(gl, &gl->gl_holders)) {
- /* Inode glock-type-specific; free unused gfs inode,
- and release hold on iopen glock */
- if (gl->gl_ops == &gfs_inode_glops) {
- struct gfs_inode *ip = get_gl2ip(gl);
- if (ip && !atomic_read(&ip->i_count))
- gfs_inode_destroy(ip);
- }
- /* Generic (including inodes); unlock glock */
- if (gl->gl_state != LM_ST_UNLOCKED)
- handle_callback(gl, LM_ST_UNLOCKED);
- }
-
- unlock_on_glock(gl);
- }
-
- /* If glock struct's only remaining reference is from examine_bucket(),
- remove glock from hash table (sd_gl_hash), and free glock's memory */
- write_lock(&bucket->hb_lock);
- if (atomic_read(&gl->gl_count) == 1) {
- list_del_init(&gl->gl_list);
- write_unlock(&bucket->hb_lock);
- glock_free(gl);
- } else {
- write_unlock(&bucket->hb_lock);
- glock_put(gl); /* see examine_bucket() */
- }
-}
-
-/**
- * gfs_gl_hash_clear - Empty out the glock hash table
- * @sdp: the filesystem
- * @wait: wait until it's all gone
- *
- * Called when unmounting the filesystem, or when inter-node lock manager
- * requests DROPLOCKS because it is running out of capacity.
- */
-
-void
-gfs_gl_hash_clear(struct gfs_sbd *sdp, int wait)
-{
- unsigned long t;
- unsigned int x;
- int cont;
-
- t = jiffies;
-
- for (;;) {
- cont = FALSE;
-
- for (x = 0; x < GFS_GL_HASH_SIZE; x++)
- if (examine_bucket(clear_glock, sdp, &sdp->sd_gl_hash[x], 0))
- cont = TRUE;
-
- if (!wait || !cont)
- break;
-
- if (time_after_eq(jiffies, t + gfs_tune_get(sdp, gt_stall_secs) * HZ)) {
- printk("GFS: fsid=%s: Unmount seems to be stalled. Dumping lock state...\n",
- sdp->sd_fsname);
- gfs_dump_lockstate(sdp, NULL);
- t = jiffies;
- }
-
- invalidate_inodes(sdp->sd_vfs);
- schedule_timeout_interruptible(HZ / 10);
- }
-}
-
-/*
- * Diagnostic routines to help debug distributed deadlock
- */
-
-/**
- * dump_holder - print information about a glock holder
- * @str: a string naming the type of holder
- * @gh: the glock holder
- * @buf: the buffer
- * @size: the size of the buffer
- * @count: where we are in the buffer
- *
- * Returns: 0 on success, -ENOBUFS when we run out of space
- */
-
-static int
-dump_holder(char *str, struct gfs_holder *gh,
- char *buf, unsigned int size, unsigned int *count)
-{
- unsigned int x;
- int error = -ENOBUFS;
-
- gfs_printf(" %s\n", str);
- gfs_printf(" owner = %ld\n",
- (gh->gh_owner) ? (long)gh->gh_owner->pid : -1);
- gfs_printf(" gh_state = %u\n", gh->gh_state);
- gfs_printf(" gh_flags =");
- for (x = 0; x < 32; x++)
- if (gh->gh_flags & (1 << x))
- gfs_printf(" %u", x);
- gfs_printf(" \n");
- gfs_printf(" error = %d\n", gh->gh_error);
- gfs_printf(" gh_iflags =");
- for (x = 0; x < 32; x++)
- if (test_bit(x, &gh->gh_iflags))
- gfs_printf(" %u", x);
- gfs_printf(" \n");
-
- error = 0;
-
- out:
- return error;
-}
-
-/**
- * dump_inode - print information about an inode
- * @ip: the inode
- * @buf: the buffer
- * @size: the size of the buffer
- * @count: where we are in the buffer
- *
- * Returns: 0 on success, -ENOBUFS when we run out of space
- */
-
-static int
-dump_inode(struct gfs_inode *ip,
- char *buf, unsigned int size, unsigned int *count)
-{
- unsigned int x;
- int error = -ENOBUFS;
-
- gfs_printf(" Inode:\n");
- gfs_printf(" num = %llu/%llu\n",
- (unsigned long long)ip->i_num.no_formal_ino,
- (unsigned long long)ip->i_num.no_addr);
- gfs_printf(" type = %u\n", ip->i_di.di_type);
- gfs_printf(" i_count = %d\n", atomic_read(&ip->i_count));
- gfs_printf(" i_flags =");
- for (x = 0; x < 32; x++)
- if (test_bit(x, &ip->i_flags))
- gfs_printf(" %u", x);
- gfs_printf(" \n");
- gfs_printf(" vnode = %s\n", (ip->i_vnode) ? "yes" : "no");
-
- error = 0;
-
- out:
- return error;
-}
-
-/**
- * dump_glock - print information about a glock
- * @gl: the glock
- * @buf: the buffer
- * @size: the size of the buffer
- * @count: where we are in the buffer
- *
- * Returns: 0 on success, -ENOBUFS when we run out of space
- */
-
-static int
-dump_glock(struct gfs_glock *gl,
- char *buf, unsigned int size, unsigned int *count)
-{
- struct list_head *head, *tmp;
- struct gfs_holder *gh;
- unsigned int x;
- int error = -ENOBUFS;
-
- spin_lock(&gl->gl_spin);
-
- gfs_printf("Glock (%u, %llu)\n",
- gl->gl_name.ln_type,
- (unsigned long long)gl->gl_name.ln_number);
- gfs_printf(" gl_flags =");
- for (x = 0; x < 32; x++)
- if (test_bit(x, &gl->gl_flags))
- gfs_printf(" %u", x);
- gfs_printf(" \n");
- gfs_printf(" gl_count = %d\n", atomic_read(&gl->gl_count));
- gfs_printf(" gl_state = %u\n", gl->gl_state);
- gfs_printf(" req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no");
- gfs_printf(" req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no");
- gfs_printf(" lvb_count = %d\n", atomic_read(&gl->gl_lvb_count));
- gfs_printf(" object = %s\n", (gl->gl_object) ? "yes" : "no");
- gfs_printf(" new_le = %s\n", (gl->gl_new_le.le_trans) ? "yes" : "no");
- gfs_printf(" incore_le = %s\n", (gl->gl_incore_le.le_trans) ? "yes" : "no");
- gfs_printf(" reclaim = %s\n",
- (list_empty(&gl->gl_reclaim)) ? "no" : "yes");
- if (gl->gl_aspace)
- gfs_printf(" aspace = %lu\n",
- gl->gl_aspace->i_mapping->nrpages);
- else
- gfs_printf(" aspace = no\n");
- gfs_printf(" ail_bufs = %s\n",
- (list_empty(&gl->gl_ail_bufs)) ? "no" : "yes");
- if (gl->gl_req_gh) {
- error = dump_holder("Request", gl->gl_req_gh, buf, size, count);
- if (error)
- goto out;
- }
- for (head = &gl->gl_holders, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- gh = list_entry(tmp, struct gfs_holder, gh_list);
- error = dump_holder("Holder", gh, buf, size, count);
- if (error)
- goto out;
- }
- for (head = &gl->gl_waiters1, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- gh = list_entry(tmp, struct gfs_holder, gh_list);
- error = dump_holder("Waiter1", gh, buf, size, count);
- if (error)
- goto out;
- }
- for (head = &gl->gl_waiters2, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- gh = list_entry(tmp, struct gfs_holder, gh_list);
- error = dump_holder("Waiter2", gh, buf, size, count);
- if (error)
- goto out;
- }
- for (head = &gl->gl_waiters3, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- gh = list_entry(tmp, struct gfs_holder, gh_list);
- error = dump_holder("Waiter3", gh, buf, size, count);
- if (error)
- goto out;
- }
- if (gl->gl_ops == &gfs_inode_glops && get_gl2ip(gl)) {
- if (!test_bit(GLF_LOCK, &gl->gl_flags) &&
- list_empty(&gl->gl_holders)) {
- error = dump_inode(get_gl2ip(gl), buf, size, count);
- if (error)
- goto out;
- } else {
- error = -ENOBUFS;
- gfs_printf(" Inode: busy\n");
- }
- }
-
- error = 0;
-
- out:
- spin_unlock(&gl->gl_spin);
-
- return error;
-}
-
-/**
- * gfs_dump_lockstate - print out the current lockstate
- * @sdp: the filesystem
- * @ub: the buffer to copy the information into
- *
- * If @ub is NULL, dump the lockstate to the console.
- *
- */
-
-int
-gfs_dump_lockstate(struct gfs_sbd *sdp, struct gfs_user_buffer *ub)
-{
- struct gfs_gl_hash_bucket *bucket;
- struct list_head *tmp, *head;
- struct gfs_glock *gl;
- char *buf = NULL;
- unsigned int size = gfs_tune_get(sdp, gt_lockdump_size);
- unsigned int x, count;
- int error = 0;
-
- if (ub) {
- buf = kmalloc(size, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- }
-
- for (x = 0; x < GFS_GL_HASH_SIZE; x++) {
- bucket = &sdp->sd_gl_hash[x];
- count = 0;
-
- read_lock(&bucket->hb_lock);
-
- for (head = &bucket->hb_list, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- gl = list_entry(tmp, struct gfs_glock, gl_list);
-
- if (test_bit(GLF_PLUG, &gl->gl_flags))
- continue;
-
- error = dump_glock(gl, buf, size, &count);
- if (error)
- break;
- }
-
- read_unlock(&bucket->hb_lock);
-
- if (error)
- break;
-
- if (ub) {
- if (ub->ub_count + count > ub->ub_size) {
- error = -ENOMEM;
- break;
- }
- if (copy_to_user(ub->ub_data + ub->ub_count, buf, count)) {
- error = -EFAULT;
- break;
- }
- ub->ub_count += count;
- }
- }
-
- if (ub)
- kfree(buf);
-
- return error;
-}
diff --git a/gfs-kernel/src/gfs/glock.h b/gfs-kernel/src/gfs/glock.h
deleted file mode 100644
index 9de5e94..0000000
--- a/gfs-kernel/src/gfs/glock.h
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef __GFS_GLOCK_DOT_H__
-#define __GFS_GLOCK_DOT_H__
-
-/* Flags for lock requests; used in gfs_holder gh_flag field. */
-/* These are defined in lm_interface.h, commented out here.
-#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)
- These are defined here. */
-#define GL_LOCAL_EXCL (0x00000020) /* Only one holder may be granted the
- * lock on this node, even if SHARED */
-#define GL_ASYNC (0x00000040) /* Don't block waiting for lock ...
- * must poll to wait for grant */
-#define GL_EXACT (0x00000080) /* Requested state must == current state
- * for lock to be granted */
-#define GL_SKIP (0x00000100) /* Don't read from disk after grant */
-#define GL_ATIME (0x00000200) /* Update inode's ATIME after grant */
-#define GL_NOCACHE (0x00000400) /* Release glock when done, don't cache */
-#define GL_SYNC (0x00000800) /* Sync to disk when no more holders */
-#define GL_NOCANCEL (0x00001000) /* Don't ever cancel this request */
-#define GL_NOCANCEL_OTHER (0x00004000) /* Don't cancel other locks for this */
-#define GL_FLOCK (0x00008000) /* This is an flock */
-
-#define GLR_TRYFAILED (13)
-#define GLR_CANCELED (14)
-
-static __inline__ int
-gfs_glock_is_locked_by_me(struct gfs_glock *gl)
-{
- struct list_head *tmp, *head;
- struct gfs_holder *gh;
- int locked = FALSE;
-
- /* Look in glock's list of holders for one with current task as owner */
- spin_lock(&gl->gl_spin);
- for (head = &gl->gl_holders, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- gh = list_entry(tmp, struct gfs_holder, gh_list);
- if (gh->gh_owner == current) {
- locked = TRUE;
- break;
- }
- }
- spin_unlock(&gl->gl_spin);
-
- return locked;
-}
-static __inline__ int
-gfs_glock_is_held_excl(struct gfs_glock *gl)
-{
- return (gl->gl_state == LM_ST_EXCLUSIVE);
-}
-static __inline__ int
-gfs_glock_is_held_dfrd(struct gfs_glock *gl)
-{
- return (gl->gl_state == LM_ST_DEFERRED);
-}
-static __inline__ int
-gfs_glock_is_held_shrd(struct gfs_glock *gl)
-{
- return (gl->gl_state == LM_ST_SHARED);
-}
-
-static __inline__ int
-gfs_glock_is_blocking(struct gfs_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 gfs_glock *gfs_glock_find(struct gfs_sbd *sdp,
- struct lm_lockname *name);
-int gfs_glock_get(struct gfs_sbd *sdp,
- uint64_t number, struct gfs_glock_operations *glops,
- int create, struct gfs_glock **glp);
-void gfs_glock_hold(struct gfs_glock *gl);
-void gfs_glock_put(struct gfs_glock *gl);
-
-void gfs_holder_init(struct gfs_glock *gl, unsigned int state, int flags,
- struct gfs_holder *gh);
-void gfs_holder_reinit(unsigned int state, int flags, struct gfs_holder *gh);
-void gfs_holder_uninit(struct gfs_holder *gh);
-struct gfs_holder *gfs_holder_get(struct gfs_glock *gl, unsigned int state,
- int flags);
-void gfs_holder_put(struct gfs_holder *gh);
-
-void gfs_glock_xmote_th(struct gfs_glock *gl, unsigned int state, int flags);
-void gfs_glock_drop_th(struct gfs_glock *gl);
-
-int gfs_glock_nq(struct gfs_holder *gh);
-int gfs_glock_poll(struct gfs_holder *gh);
-int gfs_glock_wait(struct gfs_holder *gh);
-void gfs_glock_dq(struct gfs_holder *gh);
-void gfs_glock_dq_wait(struct gfs_holder *gh);
-
-void gfs_glock_prefetch(struct gfs_glock *gl, unsigned int state, int flags);
-void gfs_glock_force_drop(struct gfs_glock *gl);
-
-int gfs_glock_be_greedy(struct gfs_glock *gl, unsigned int time);
-
-int gfs_glock_nq_init(struct gfs_glock *gl, unsigned int state, int flags,
- struct gfs_holder *gh);
-void gfs_glock_dq_uninit(struct gfs_holder *gh);
-int gfs_glock_nq_num(struct gfs_sbd *sdp,
- uint64_t number, struct gfs_glock_operations *glops,
- unsigned int state, int flags, struct gfs_holder *gh);
-
-int gfs_glock_nq_m(unsigned int num_gh, struct gfs_holder *ghs);
-void gfs_glock_dq_m(unsigned int num_gh, struct gfs_holder *ghs);
-
-void gfs_glock_prefetch_num(struct gfs_sbd *sdp,
- uint64_t number, struct gfs_glock_operations *glops,
- unsigned int state, int flags);
-
-/* Lock Value Block functions */
-
-int gfs_lvb_hold(struct gfs_glock *gl);
-void gfs_lvb_unhold(struct gfs_glock *gl);
-void gfs_lvb_sync(struct gfs_glock *gl);
-
-void gfs_glock_cb(void *fsdata, unsigned int type, void *data);
-
-void gfs_try_toss_inode(struct gfs_sbd *sdp, struct gfs_inum *inum);
-void gfs_iopen_go_callback(struct gfs_glock *gl, unsigned int state);
-
-void gfs_glock_schedule_for_reclaim(struct gfs_glock *gl);
-void gfs_reclaim_glock(struct gfs_sbd *sdp);
-
-void gfs_scand_internal(struct gfs_sbd *sdp);
-void gfs_gl_hash_clear(struct gfs_sbd *sdp, int wait);
-
-int gfs_dump_lockstate(struct gfs_sbd *sdp, struct gfs_user_buffer *ub);
-
-#endif /* __GFS_GLOCK_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/glops.c b/gfs-kernel/src/gfs/glops.c
deleted file mode 100644
index 708291d..0000000
--- a/gfs-kernel/src/gfs/glops.c
+++ /dev/null
@@ -1,664 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "dio.h"
-#include "glock.h"
-#include "glops.h"
-#include "inode.h"
-#include "log.h"
-#include "page.h"
-#include "recovery.h"
-#include "rgrp.h"
-
-/**
- * meta_go_sync - sync out the metadata for this glock
- * @gl: the glock
- * @flags: DIO_*
- *
- * Used for meta and rgrp glocks.
- *
- * Called when demoting (gfs_glock_xmote_th()) or unlocking
- * (gfs_glock_drop_th() an EX glock at inter-node scope. We must flush
- * to disk all dirty buffers/pages relating to this glock, and must not
- * not return to caller to demote/unlock the glock until I/O is complete.
- *
- * This is *not* called from gfs_glock_dq(), because GL_SYNC flag is not
- * currently used for anything but inode glocks.
- */
-
-static void
-meta_go_sync(struct gfs_glock *gl, int flags)
-{
- if (!(flags & DIO_METADATA))
- return;
-
- if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
- gfs_log_flush_glock(gl);
- gfs_sync_buf(gl, flags | DIO_START | DIO_WAIT | DIO_CHECK);
- }
-
- /* We've synced everything, clear SYNC request and DIRTY flags */
- clear_bit(GLF_DIRTY, &gl->gl_flags);
- clear_bit(GLF_SYNC, &gl->gl_flags);
-}
-
-/**
- * meta_go_inval - invalidate the metadata for this glock
- * @gl: the glock
- * @flags:
- *
- */
-
-static void
-meta_go_inval(struct gfs_glock *gl, int flags)
-{
- if (!(flags & DIO_METADATA))
- return;
-
- gfs_inval_buf(gl);
- gl->gl_vn++;
-}
-
-/**
- * meta_go_demote_ok - Check to see if it's ok to unlock a meta glock
- * @gl: the glock
- *
- * Returns: TRUE if we have no cached data; ok to demote meta glock
- *
- * Called when trying to dump (reclaim) a glock from the glock cache, after
- * determining that there is currently no holder on this node for this glock,
- * and before placing LM_ST_UNLOCKED request on glock's wait-for-demote queue.
- * Note that callbacks from other nodes that need a lock do *not*
- * seek permission from this function before requesting a demote.
- * Nor do glocks obtained with the following flags (see demote_ok()):
- * -- GL_NOCACHE: gets unlocked (and not cached) immediately after use
- * -- GLF_STICKY: equivalent to always getting "FALSE" from this function
- * -- GLF_PREFETCH: uses its own timeout
- *
- * For glocks that protect on-disk data (meta, inode, and rgrp glocks), disk
- * accesses are slow, while lock manipulation is usually fast. Releasing
- * a lock means that we:
- * -- Must sync memory-cached write data to disk immediately, before another
- * node can be granted the lock (at which point that node must read the
- * data from disk).
- * -- Must invalidate memory-cached data that we had read from or written
- * to disk. Another node can change it if we don't have a lock, so it's
- * now useless to us.
- *
- * Then, if we re-acquire the lock again in the future, we:
- * -- Must (re-)read (perhaps unchanged) data from disk into memory.
- *
- * All of these are painful, so it pays to retain a glock in our glock cache
- * as long as we have cached data (even though we have no active holders
- * for this lock on this node currently), unless/until another node needs
- * to change it. This allows Linux block I/O to sync write data to disk in
- * a "lazy" way, rather than forcing an immediate sync (and resultant WAIT),
- * and retains current data in memory as long as possible.
- *
- * This also helps GFS respond to memory pressure. There is no mechanism for
- * the Linux virtual memory manager to directly call into GFS to ask it to
- * drop locks. So, we take a hint from what the VM does to the page cache.
- * When that cache is trimmed (and we see no more pages relating to this
- * glock), we trim the glock cache as well, by releasing this lock.
- */
-
-static int
-meta_go_demote_ok(struct gfs_glock *gl)
-{
- return (gl->gl_aspace->i_mapping->nrpages) ? FALSE : TRUE;
-}
-
-/**
- * inode_go_xmote_th - promote/demote (but don't unlock) an inode glock
- * @gl: the glock
- * @state: the requested state
- * @flags: the flags passed into gfs_glock()
- *
- * Acquire a new glock, or change an already-acquired glock to
- * more/less restrictive state (other than LM_ST_UNLOCKED).
- */
-
-static void
-inode_go_xmote_th(struct gfs_glock *gl, unsigned int state, int flags)
-{
- if (gl->gl_state != LM_ST_UNLOCKED)
- gfs_inval_pte(gl);
- gfs_glock_xmote_th(gl, state, flags);
-}
-
-/**
- * inode_go_xmote_bh - After promoting/demoting (but not unlocking)
- * an inode glock
- * @gl: the glock
- *
- * FIXME: This will be really broken when (no_formal_ino != no_addr)
- * and gl_name.ln_number no longer refers to the dinode block #.
- *
- * If we've just acquired the inter-node lock for an inode,
- * read the dinode block from disk (but don't wait for I/O completion).
- * Exceptions (don't read if):
- * Glock state is UNLOCKED.
- * Glock's requesting holder's GL_SKIP flag is set.
- */
-
-static void
-inode_go_xmote_bh(struct gfs_glock *gl)
-{
- struct gfs_holder *gh = gl->gl_req_gh;
- struct buffer_head *bh;
- int error;
-
- if (gl->gl_state != LM_ST_UNLOCKED &&
- (!gh || !(gh->gh_flags & GL_SKIP))) {
- error = gfs_dread(gl, gl->gl_name.ln_number, DIO_START, &bh);
- if (!error)
- brelse(bh);
- }
-}
-
-/**
- * inode_go_drop_th - unlock an inode glock
- * @gl: the glock
- *
- * Invoked from rq_demote().
- * Another node needs the lock in EXCLUSIVE mode, or lock (unused for too long)
- * is being purged from our node's glock cache; we're dropping lock.
- */
-
-static void
-inode_go_drop_th(struct gfs_glock *gl)
-{
- gfs_inval_pte(gl);
- gfs_glock_drop_th(gl);
-}
-
-/**
- * inode_go_sync - Sync the dirty data and/or metadata for an inode glock
- * @gl: the glock protecting the inode
- * @flags: DIO_METADATA -- sync inode's metadata
- * DIO_DATA -- sync inode's data
- * DIO_INVISIBLE -- don't clear glock's DIRTY flag when done
- *
- * If DIO_INVISIBLE:
- * 1) Called from gfs_glock_dq(), when releasing the last holder for an EX
- * glock (but glock is still in our glock cache in EX state, and might
- * stay there for a few minutes). Holder had GL_SYNC flag set, asking
- * for early sync (i.e. now, instead of later when we release the EX at
- * inter-node scope). GL_SYNC is currently used only for inodes in
- * special cases, so inode is the only type of glock for which
- * DIO_INVISIBLE would apply.
- * 2) Called from depend_sync_one() to sync deallocated inode metadata
- * before it can be reallocated by another process or machine. Since
- * this call can happen at any time during the lifetime of the
- * glock, don't clear the sync bit (more data might be dirtied
- * momentarily).
- * Else (later):
- * Called when demoting (gfs_glock_xmote_th()) or unlocking
- * (gfs_glock_drop_th() an EX glock at inter-node scope. We must flush
- * to disk all dirty buffers/pages relating to this glock, and must not
- * return to caller to demote/unlock the glock until I/O is complete.
- *
- * Syncs go in following order:
- * Start data page writes
- * Sync metadata to log (wait to complete I/O)
- * Sync metadata to in-place location (wait to complete I/O)
- * Wait for data page I/O to complete
- *
- */
-
-static void
-inode_go_sync(struct gfs_glock *gl, int flags)
-{
- int meta = (flags & DIO_METADATA);
- int data = (flags & DIO_DATA);
-
- if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
- if (meta && data) {
- gfs_sync_page(gl, flags | DIO_START);
- gfs_log_flush_glock(gl);
- gfs_sync_buf(gl, flags | DIO_START | DIO_WAIT | DIO_CHECK);
- gfs_sync_page(gl, flags | DIO_WAIT | DIO_CHECK);
- } else if (meta) {
- gfs_log_flush_glock(gl);
- gfs_sync_buf(gl, flags | DIO_START | DIO_WAIT | DIO_CHECK);
- } else if (data)
- gfs_sync_page(gl, flags | DIO_START | DIO_WAIT | DIO_CHECK);
- }
-
- /* If we've synced everything, clear the SYNC request.
- If we're doing the final (not early) sync, clear DIRTY */
- if (meta && data) {
- if (!(flags & DIO_INVISIBLE))
- clear_bit(GLF_DIRTY, &gl->gl_flags);
- clear_bit(GLF_SYNC, &gl->gl_flags);
- }
-}
-
-/**
- * inode_go_inval - prepare a inode glock to be released
- * @gl: the glock
- * @flags:
- *
- */
-
-static void
-inode_go_inval(struct gfs_glock *gl, int flags)
-{
- int meta = (flags & DIO_METADATA);
- int data = (flags & DIO_DATA);
-
- if (meta) {
- gfs_inval_buf(gl);
- gl->gl_vn++;
- }
- if (data)
- gfs_inval_page(gl);
-}
-
-/**
- * inode_go_demote_ok - Check to see if it's ok to unlock an inode glock
- * @gl: the glock
- *
- * See comments for meta_go_demote_ok().
- *
- * While other glock types (meta, rgrp) that protect disk data can be retained
- * indefinitely, GFS imposes a timeout (overridden when using no_lock lock
- * module) for inode glocks, even if there is still data in page cache for
- * this inode.
- *
- * Returns: TRUE if it's ok
- */
-
-static int
-inode_go_demote_ok(struct gfs_glock *gl)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- int demote = FALSE;
-
- if (!get_gl2ip(gl) && !gl->gl_aspace->i_mapping->nrpages)
- demote = TRUE;
- else if (!sdp->sd_args.ar_localcaching &&
- time_after_eq(jiffies, gl->gl_stamp + gfs_tune_get(sdp, gt_demote_secs) * HZ))
- demote = TRUE;
-
- return demote;
-}
-
-/**
- * inode_go_lock - operation done after an inode lock is locked by
- * a first holder on this node
- * @gl: the glock
- * @flags: the flags passed into gfs_glock()
- *
- * Returns: errno
- */
-
-static int
-inode_go_lock(struct gfs_glock *gl, int flags)
-{
- struct gfs_inode *ip = get_gl2ip(gl);
- int error = 0;
-
- if (ip && ip->i_vn != gl->gl_vn) {
- error = gfs_copyin_dinode(ip);
- if (!error)
- gfs_inode_attr_in(ip);
- }
-
- return error;
-}
-
-/**
- * inode_go_unlock - operation done when an inode lock is unlocked by
- * a last holder on this node
- * @gl: the glock
- * @flags: the flags passed into gfs_gunlock()
- *
- */
-
-static void
-inode_go_unlock(struct gfs_glock *gl, int flags)
-{
- struct gfs_inode *ip = get_gl2ip(gl);
-
- if (ip && test_bit(GLF_DIRTY, &gl->gl_flags))
- gfs_inode_attr_in(ip);
-
- if (ip)
- gfs_flush_meta_cache(ip);
-}
-
-/**
- * inode_greedy -
- * @gl: the glock
- *
- */
-
-static void
-inode_greedy(struct gfs_glock *gl)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_inode *ip = get_gl2ip(gl);
- unsigned int quantum = gfs_tune_get(sdp, gt_greedy_quantum);
- unsigned int max = gfs_tune_get(sdp, gt_greedy_max);
- unsigned int new_time;
-
- spin_lock(&ip->i_spin);
-
- if (time_after(ip->i_last_pfault + quantum, jiffies)) {
- new_time = ip->i_greedy + quantum;
- if (new_time > max)
- new_time = max;
- } else {
- new_time = ip->i_greedy - quantum;
- if (!new_time || new_time > max)
- new_time = 1;
- }
-
- ip->i_greedy = new_time;
-
- spin_unlock(&ip->i_spin);
-
- gfs_inode_put(ip);
-}
-
-/**
- * rgrp_go_xmote_th - promote/demote (but don't unlock) a resource group glock
- * @gl: the glock
- * @state: the requested state
- * @flags: the flags passed into gfs_glock()
- *
- * Acquire a new glock, or change an already-acquired glock to
- * more/less restrictive state (other than LM_ST_UNLOCKED).
- *
- * We're going to lock the lock in SHARED or EXCLUSIVE state, or
- * demote it from EXCLUSIVE to SHARED (because another node needs it SHARED).
- * When locking, gfs_mhc_zap() and gfs_depend_sync() are basically no-ops;
- * meta-header cache and dependency lists should be empty.
- *
- */
-
-static void
-rgrp_go_xmote_th(struct gfs_glock *gl, unsigned int state, int flags)
-{
- struct gfs_rgrpd *rgd = get_gl2rgd(gl);
-
- gfs_mhc_zap(rgd);
- gfs_depend_sync(rgd);
- gfs_glock_xmote_th(gl, state, flags);
-}
-
-/**
- * rgrp_go_drop_th - unlock a resource group glock
- * @gl: the glock
- *
- * Invoked from rq_demote().
- * Another node needs the lock in EXCLUSIVE mode, or lock (unused for too long)
- * is being purged from our node's glock cache; we're dropping lock.
- */
-
-static void
-rgrp_go_drop_th(struct gfs_glock *gl)
-{
- struct gfs_rgrpd *rgd = get_gl2rgd(gl);
-
- gfs_mhc_zap(rgd);
- gfs_depend_sync(rgd);
- gfs_glock_drop_th(gl);
-}
-
-/**
- * rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock
- * @gl: the glock
- *
- * See comments for meta_go_demote_ok().
- *
- * In addition to Linux page cache, we also check GFS meta-header-cache.
- *
- * Returns: TRUE if it's ok
- */
-
-static int
-rgrp_go_demote_ok(struct gfs_glock *gl)
-{
- struct gfs_rgrpd *rgd = get_gl2rgd(gl);
- int demote = TRUE;
-
- if (gl->gl_aspace->i_mapping->nrpages)
- demote = FALSE;
- else if (rgd && !list_empty(&rgd->rd_mhc)) /* Don't bother with lock here */
- demote = FALSE;
-
- return demote;
-}
-
-/**
- * rgrp_go_lock - operation done after an rgrp lock is locked by
- * a first holder on this node.
- * @gl: the glock
- * @flags: the flags passed into gfs_glock()
- *
- * Returns: errno
- *
- * Read rgrp's header and block allocation bitmaps from disk.
- */
-
-static int
-rgrp_go_lock(struct gfs_glock *gl, int flags)
-{
- if (flags & GL_SKIP)
- return 0;
- return gfs_rgrp_read(get_gl2rgd(gl));
-}
-
-/**
- * rgrp_go_unlock - operation done when an rgrp lock is unlocked by
- * a last holder on this node.
- * @gl: the glock
- * @flags: the flags passed into gfs_gunlock()
- *
- * Release rgrp's bitmap buffers (read in when lock was first obtained).
- * Make sure rgrp's glock's Lock Value Block has up-to-date block usage stats,
- * so other nodes can see them.
- */
-
-static void
-rgrp_go_unlock(struct gfs_glock *gl, int flags)
-{
- struct gfs_rgrpd *rgd = get_gl2rgd(gl);
- if (flags & GL_SKIP)
- return;
- gfs_rgrp_relse(rgd);
- if (test_bit(GLF_DIRTY, &gl->gl_flags))
- gfs_rgrp_lvb_fill(rgd);
-}
-
-/**
- * trans_go_xmote_th - promote/demote (but don't unlock) the transaction glock
- * @gl: the glock
- * @state: the requested state
- * @flags: the flags passed into gfs_glock()
- *
- * Acquire a new glock, or change an already-acquired glock to
- * more/less restrictive state (other than LM_ST_UNLOCKED).
- */
-
-static void
-trans_go_xmote_th(struct gfs_glock *gl, unsigned int state, int flags)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
-
- if (gl->gl_state != LM_ST_UNLOCKED &&
- test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
- gfs_sync_meta(sdp);
- gfs_log_shutdown(sdp);
- }
-
- gfs_glock_xmote_th(gl, state, flags);
-}
-
-/**
- * trans_go_xmote_bh - After promoting/demoting (but not unlocking)
- * the transaction glock
- * @gl: the glock
- *
- */
-
-static void
-trans_go_xmote_bh(struct gfs_glock *gl)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_glock *j_gl = sdp->sd_journal_gh.gh_gl;
- struct gfs_log_header head;
- int error;
-
- if (gl->gl_state != LM_ST_UNLOCKED &&
- test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
- j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA);
-
- error = gfs_find_jhead(sdp, &sdp->sd_jdesc, j_gl, &head);
- if (error)
- gfs_consist(sdp);
- if (!(head.lh_flags & GFS_LOG_HEAD_UNMOUNT))
- gfs_consist(sdp);
-
- /* Initialize some head of the log stuff */
- if (!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) {
- sdp->sd_sequence = head.lh_sequence;
- sdp->sd_log_head = head.lh_first + 1;
- }
- }
-}
-
-/**
- * trans_go_drop_th - unlock the transaction glock
- * @gl: the glock
- *
- * Invoked from rq_demote().
- * Another node needs the lock in EXCLUSIVE mode to quiesce the filesystem
- * (for journal replay, etc.).
- *
- * We want to sync the device even with localcaching. Remember
- * that localcaching journal replay only marks buffers dirty.
- */
-
-static void
-trans_go_drop_th(struct gfs_glock *gl)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
-
- if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
- gfs_sync_meta(sdp);
- gfs_log_shutdown(sdp);
- }
-
- gfs_glock_drop_th(gl);
-}
-
-/**
- * nondisk_go_demote_ok - Check to see if it's ok to unlock a non-disk glock
- * @gl: the glock
- *
- * See comments for meta_go_demote_ok().
- *
- * We never give up a non-disk glock (unless another node needs it).
- * Non-disk type used for GFS_MOUNT_LOCK, GFS_LIVE_LOCK, GFS_RENAME_LOCK.
- * GFS_MOUNT_LOCK is always requested GL_NOCACHE, however, so it never uses
- * this function.
- *
- * Returns: TRUE if it's ok
- */
-
-static int
-nondisk_go_demote_ok(struct gfs_glock *gl)
-{
- return FALSE;
-}
-
-/**
- * quota_go_demote_ok - Check to see if it's ok to unlock a quota glock
- * @gl: the glock
- *
- * See comments for meta_go_demote_ok().
- *
- * Returns: TRUE if it's ok
- */
-
-static int
-quota_go_demote_ok(struct gfs_glock *gl)
-{
- return !atomic_read(&gl->gl_lvb_count);
-}
-
-struct gfs_glock_operations gfs_meta_glops = {
- .go_xmote_th = gfs_glock_xmote_th,
- .go_drop_th = gfs_glock_drop_th,
- .go_sync = meta_go_sync,
- .go_inval = meta_go_inval,
- .go_demote_ok = meta_go_demote_ok,
- .go_type = LM_TYPE_META
-};
-
-struct gfs_glock_operations gfs_inode_glops = {
- .go_xmote_th = inode_go_xmote_th,
- .go_xmote_bh = inode_go_xmote_bh,
- .go_drop_th = inode_go_drop_th,
- .go_sync = inode_go_sync,
- .go_inval = inode_go_inval,
- .go_demote_ok = inode_go_demote_ok,
- .go_lock = inode_go_lock,
- .go_unlock = inode_go_unlock,
- .go_greedy = inode_greedy,
- .go_type = LM_TYPE_INODE
-};
-
-struct gfs_glock_operations gfs_rgrp_glops = {
- .go_xmote_th = rgrp_go_xmote_th,
- .go_drop_th = rgrp_go_drop_th,
- .go_sync = meta_go_sync,
- .go_inval = meta_go_inval,
- .go_demote_ok = rgrp_go_demote_ok,
- .go_lock = rgrp_go_lock,
- .go_unlock = rgrp_go_unlock,
- .go_type = LM_TYPE_RGRP
-};
-
-struct gfs_glock_operations gfs_trans_glops = {
- .go_xmote_th = trans_go_xmote_th,
- .go_xmote_bh = trans_go_xmote_bh,
- .go_drop_th = trans_go_drop_th,
- .go_type = LM_TYPE_NONDISK
-};
-
-struct gfs_glock_operations gfs_iopen_glops = {
- .go_xmote_th = gfs_glock_xmote_th,
- .go_drop_th = gfs_glock_drop_th,
- .go_callback = gfs_iopen_go_callback,
- .go_type = LM_TYPE_IOPEN
-};
-
-struct gfs_glock_operations gfs_flock_glops = {
- .go_xmote_th = gfs_glock_xmote_th,
- .go_drop_th = gfs_glock_drop_th,
- .go_type = LM_TYPE_FLOCK
-};
-
-struct gfs_glock_operations gfs_nondisk_glops = {
- .go_xmote_th = gfs_glock_xmote_th,
- .go_drop_th = gfs_glock_drop_th,
- .go_demote_ok = nondisk_go_demote_ok,
- .go_type = LM_TYPE_NONDISK
-};
-
-struct gfs_glock_operations gfs_quota_glops = {
- .go_xmote_th = gfs_glock_xmote_th,
- .go_drop_th = gfs_glock_drop_th,
- .go_demote_ok = quota_go_demote_ok,
- .go_type = LM_TYPE_QUOTA
-};
diff --git a/gfs-kernel/src/gfs/glops.h b/gfs-kernel/src/gfs/glops.h
deleted file mode 100644
index 4d897c8..0000000
--- a/gfs-kernel/src/gfs/glops.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __GLOPS_DOT_H__
-#define __GLOPS_DOT_H__
-
-extern struct gfs_glock_operations gfs_meta_glops;
-extern struct gfs_glock_operations gfs_inode_glops;
-extern struct gfs_glock_operations gfs_rgrp_glops;
-extern struct gfs_glock_operations gfs_trans_glops;
-extern struct gfs_glock_operations gfs_iopen_glops;
-extern struct gfs_glock_operations gfs_flock_glops;
-extern struct gfs_glock_operations gfs_nondisk_glops;
-extern struct gfs_glock_operations gfs_quota_glops;
-
-#endif /* __GLOPS_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/incore.h b/gfs-kernel/src/gfs/incore.h
deleted file mode 100644
index 921b79d..0000000
--- a/gfs-kernel/src/gfs/incore.h
+++ /dev/null
@@ -1,1218 +0,0 @@
-/*
- * In-core (memory/RAM) structures.
- * These do not appear on-disk. See gfs_ondisk.h for on-disk structures.
- */
-
-#ifndef __INCORE_DOT_H__
-#define __INCORE_DOT_H__
-
-/* flags used in function call parameters */
-
-#define DIO_NEW (0x00000001) /* Newly allocated metadata */
-#define DIO_FORCE (0x00000002) /* Force read of block from disk */
-#define DIO_CLEAN (0x00000004) /* Don't write to disk */
-#define DIO_DIRTY (0x00000008) /* Data changed, must write to disk */
-#define DIO_START (0x00000010) /* Start disk read or write */
-#define DIO_WAIT (0x00000020) /* Wait for disk r/w to complete */
-
-#define DIO_METADATA (0x00000040) /* Process glock's protected metadata */
-#define DIO_DATA (0x00000080) /* Process glock's protected filedata */
-#define DIO_INVISIBLE (0x00000100) /* Don't monkey with glock's dirty bit */
-#define DIO_CHECK (0x00000200) /* Make sure all metadata has been synced */
-#define DIO_ALL (0x00000400) /* Flush all AIL transactions to disk */
-
-/* Structure prototypes */
-
-struct gfs_log_operations;
-struct gfs_log_element;
-struct gfs_meta_header_cache;
-struct gfs_depend;
-struct gfs_bitmap;
-struct gfs_rgrpd;
-struct gfs_bufdata;
-struct gfs_glock_operations;
-struct gfs_holder;
-struct gfs_glock;
-struct gfs_alloc;
-struct gfs_inode;
-struct gfs_file;
-struct gfs_unlinked;
-struct gfs_quota_le;
-struct gfs_quota_data;
-struct gfs_log_buf;
-struct gfs_trans;
-struct gfs_gl_hash_bucket;
-struct gfs_sbd;
-
-typedef void (*gfs_glop_bh_t) (struct gfs_glock * gl, unsigned int ret);
-
-/*
- * Structure of operations that are associated with each
- * type of element in the log.
- */
-struct gfs_log_operations {
- /*
- * Operations specific to a given log element (LE).
- * These are typically executed individually via macros such as LO_ADD.
- */
-
- /* Add new LE to transaction */
- void (*lo_add) (struct gfs_sbd * sdp, struct gfs_log_element * le);
-
- /* Do any cleanup, etc., needed just before commit to incore log */
- void (*lo_trans_end) (struct gfs_sbd * sdp,
- struct gfs_log_element * le);
-
- /* Print LE-specific info via printk() */
- void (*lo_print) (struct gfs_sbd * sdp, struct gfs_log_element * le,
- unsigned int where);
-
- /* Find any incore transactions that overlap through this LE (e.g.
- * share glocks), to determine if any transactions can be combined. */
- struct gfs_trans *(*lo_overlap_trans) (struct gfs_sbd * sdp,
- struct gfs_log_element * le);
-
- /* Change LE from "new" to "incore" status, before write to log */
- void (*lo_incore_commit) (struct gfs_sbd * sdp, struct gfs_trans * tr,
- struct gfs_log_element * le);
-
- /* Allow writes to in-place locations, after log is on-disk */
- void (*lo_add_to_ail) (struct gfs_sbd * sdp,
- struct gfs_log_element * le);
-
- /* Clean up LE after log dump */
- void (*lo_clean_dump) (struct gfs_sbd * sdp,
- struct gfs_log_element * le);
-
- /*
- * Operations specific to a class of log elements.
- * These are typically executed over a whole transaction by
- * macros such as LO_TRANS_SIZE. Each LE-type-specific operation
- * for each LE contributes its part to the overall result.
- */
-
- /* Determine LE-type-specific quantities of blocks of various types
- * required for writing the log */
- void (*lo_trans_size) (struct gfs_sbd * sdp, struct gfs_trans * tr,
- unsigned int *mblks, unsigned int *eblks,
- unsigned int *blocks, unsigned int *bmem);
-
- /* Combine LE-type-specific values in new_tr and tr, result is in tr */
- void (*lo_trans_combine) (struct gfs_sbd * sdp, struct gfs_trans * tr,
- struct gfs_trans * new_tr);
-
- /* Create control and metadata buffers that will make up the log */
- void (*lo_build_bhlist) (struct gfs_sbd * sdp, struct gfs_trans * tr);
-
- /* Calculate log space needed for this LE in a log dump */
- void (*lo_dump_size) (struct gfs_sbd * sdp, unsigned int *elements,
- unsigned int *blocks, unsigned int *bmem);
-
- /* Add LE to log dump */
- void (*lo_build_dump) (struct gfs_sbd * sdp, struct gfs_trans * tr);
-
- /*
- * Operations that happen at recovery time
- */
-
- /* Reset/init whatever before doing recovery */
- void (*lo_before_scan) (struct gfs_sbd * sdp, unsigned int jid,
- struct gfs_log_header * head,
- unsigned int pass);
-
- /* LE-specific recovery procedure */
- int (*lo_scan_elements) (struct gfs_sbd * sdp,
- struct gfs_jindex * jdesc,
- struct gfs_glock * gl, uint64_t start,
- struct gfs_log_descriptor * desc,
- unsigned int pass);
-
- /* Verify and report recovery results/statistics */
- void (*lo_after_scan) (struct gfs_sbd * sdp, unsigned int jid,
- unsigned int pass);
-
-
- /*
- * Type of element (glock/buf/unlinked/quota)
- */
- char *lo_name;
-};
-
-/*
- * Structure that gets added to struct gfs_trans->tr_elements. They
- * make up the "stuff" in each transaction.
- */
-struct gfs_log_element {
- struct gfs_log_operations *le_ops; /* Vector of functions */
-
- struct gfs_trans *le_trans; /* We're part of this transaction */
- struct list_head le_list; /* Link to transaction's element list */
-};
-
-/*
- * Meta-header cache structure.
- * One for each metadata block that we've de-allocated.
- * Used to temporarily store gfs_meta_header structs for meta blocks that
- * have been freshly turned into FREEMETA (alloc'd or de-alloc'd). Storing
- * these (small) structures in-core allows us to release the (large) buffers,
- * and not need to re-read the header from disk if/when we re-allocate the
- * blocks to USEDMETA, as long as this node holds the EXCLUSIVE lock for the
- * resource group containing the blocks. If we release the EX lock, we must
- * throw away the rgrp's cached meta headers, since another node could change
- * the blocks' contents.
- * In-core superblock structure hosts the hashed cache, as well as a
- * linear list of all cached, in most-recently-added order.
- * Also, each resource group keeps a list of cached blocks within its scope.
- */
-struct gfs_meta_header_cache {
- /* Links to various lists */
- struct list_head mc_list_hash; /* Superblock's hashed list */
- struct list_head mc_list_single; /* Superblock's list, MRU order */
- struct list_head mc_list_rgd; /* Resource group's list */
-
- uint64_t mc_block; /* Block # (in-place address) */
- struct gfs_meta_header mc_mh; /* Payload: the block's meta-header */
-};
-
-/*
- * Dependency cache structure.
- * In-core superblock structure hosts the actual cache.
- * Also, each resource group keeps a list of dependency blocks within its scope.
- */
-struct gfs_depend {
- /* Links to various lists */
- struct list_head gd_list_hash; /* Superblock's hashed list */
- struct list_head gd_list_rgd; /* Resource group's list */
-
- struct gfs_rgrpd *gd_rgd; /* Resource group descriptor */
- uint64_t gd_formal_ino; /* Inode ID */
- unsigned long gd_time; /* Time (jiffies) when put on list */
-};
-
-/*
- * Block allocation bitmap descriptor structure.
- * One of these for each FS block that contains bitmap data
- * (i.e. the resource group header blocks and their following bitmap blocks).
- * Each allocatable FS data block is represented by 2 bits (4 alloc states).
- */
-struct gfs_bitmap {
- uint32_t bi_offset; /* Byte offset of bitmap within this bit block
- (non-zero only for an rgrp header block) */
- uint32_t bi_start; /* Data block (rgrp scope, 32-bit) represented
- by the first bit-pair in this bit block */
- uint32_t bi_len; /* The number of bitmap bytes in this bit block */
-};
-
-/*
- * Resource Group (Rgrp) descriptor structure.
- * There is one of these for each resource (block) group in the FS.
- * The filesystem is divided into a number of resource groups to allow
- * simultaneous block alloc operations by a number of nodes.
- */
-struct gfs_rgrpd {
- /* Links to superblock lists */
- struct list_head rd_list; /* On-disk-order list of all rgrps */
- struct list_head rd_list_mru; /* Most Recently Used list of all rgs */
- struct list_head rd_recent; /* recently used rgrps */
- uint32_t rd_try_counter; /* # of times we fail a try lock */
-
- struct gfs_glock *rd_gl; /* Glock for this rgrp */
-
- struct gfs_rindex rd_ri; /* Resource Index (on-disk) structure */
- struct gfs_rgrp rd_rg; /* Resource Group (on-disk) structure */
- uint64_t rd_rg_vn; /* Version #: if != glock's gl_vn,
- we need to read rgrp fm disk */
-
- /* Block alloc bitmap cache */
- struct gfs_bitmap *rd_bits; /* Array of block bitmap descriptors */
- struct buffer_head **rd_bh; /* Array of ptrs to block bitmap bh's */
-
- /* Block allocation strategy, rgrp scope. Start at these blocks when
- searching for next data/meta block to alloc */
- uint32_t rd_last_alloc_data; /* Most recent data block allocated */
- uint32_t rd_last_alloc_meta; /* Most recent meta block allocated */
-
- struct list_head rd_mhc; /* Cached meta-headers for this rgrp */
- struct list_head rd_depend; /* Dependent inodes (MRU order) */
-
- struct gfs_sbd *rd_sbd; /* FS incore superblock (fs instance) */
-};
-
-/*
- * Per-buffer data
- * One of these is attached as GFS private data to each FS block's buffer_head.
- * These keep track of a buffer's progress through the transaction pipeline,
- * using the "new" embedded log element to attach it to a being-built
- * transaction, and moving the attachment point to the "incore" LE once
- * the transaction completes (at which time the buffer becomes a candidate
- * to be written to the on-disk log).
- * A buffer may be attached simultaneously to a new and an incore transaction,
- * but no more than one of each: Only one new trans may be built at a time
- * for a given buffer, obviously, since the buffer's contents are protected
- * by an EXclusive glock when writing. And, when a transaction is completely
- * built, GFS combines incore transactions that share glocks (see
- * incore_commit()), i.e. the glock that protects the buffer, so a buffer
- * never needs to be attached to more than one (combined) incore trans.
- * Note that multiple transactions can modify the buffer since its most
- * recent writes to disk. This principle applies to both in-place and
- * journal block locations on-disk, allowing this node to keep modifying the
- * cached data without writing it to disk, unless/until another node needs
- * to access the data, or the Linux OS tells us to sync to disk.
- * If a transaction follows another transaction before the first transaction's
- * log completes (indicated by the in-place buffer head still being pinned
- * in RAM), GFS copies the first transaction's results to a "frozen"
- * image of the buffer, so the first transaction results (an atomic
- * snapshot) can be logged properly, while the second transaction is
- * modifying the "real" buffer. This frozen copy lives only until the new
- * transaction is complete, at which point one of two things has occurred:
- * 1). Buffer was logged successfully; frozen copy's job is done.
- * 2). Buffer was not yet logged; frozen copy no longer needed, newer
- * buffer becomes the log candidate.
- *
- * gfs_bufdata structs also link into the Active Items Lists (AIL) (buffers
- * flushed to on-disk log, but not yet flushed to on-disk in-place locations)
- * attached to:
- * 1). The latest transaction to modify and log (on-disk) the buffer, and
- * 2). The glock that protects the buffer's contents.
- * The buffer is attached to only the most recent transaction's AIL
- * list for a couple of reasons. One is that only the most up-to-date
- * buffer content needs to be written to the in-place block on-disk. The
- * other is that since there is a more recent copy of the block in
- * the log, we don't need to keep the older copies in the log. We can
- * remove them from the AIL and let the log space be reused for new
- * transactions (GFS advances the log tail when removing buffers from AIL).
- */
-struct gfs_bufdata {
- struct buffer_head *bd_bh; /* We belong to this Linux buffer_head */
- struct gfs_glock *bd_gl; /* This glock protects buffer's payload */
-
- /* Log elements map us to a particular set of log operations functions,
- and to a particular transaction */
- struct gfs_log_element bd_new_le; /* New, incomplete transaction */
- struct gfs_log_element bd_incore_le; /* Complete (committed) trans */
-
- char *bd_frozen; /* "Frozen" copy of buffer's data */
- struct semaphore bd_lock; /* Protects access to this structure */
-
- /* "Pin" means keep buffer in RAM, don't write to disk (yet) */
- unsigned int bd_pinned; /* Recursive pin count */
-
- /* Links to Active Items Lists */
- struct list_head bd_ail_tr_list; /* This buf's most recent trans' AIL */
- struct list_head bd_ail_gl_list; /* This buf's glock's AIL */
-};
-
-/*
- * Glock operations
- * One set of operations for each glock, the set selected by type of glock.
- * These functions get called at various points in a glock's lifetime.
- * "xmote" = promote or demote (change lock state) a glock at inter-node scope.
- * "th" = top half, "bh" = bottom half
- * Some operations/fields are required (GFS assumes they are there):
- * go_xmote_th
- * go_drop_th
- * go_type
- * Other operations are optional (GFS checks for presence before calling).
- */
-struct gfs_glock_operations {
-
- /* Acquire lock or change lock state at inter-node scope:
- Does type-specific preparation (if any)
- Uses gfs_glock_xmote_th to call lock module. */
- void (*go_xmote_th) (struct gfs_glock * gl, unsigned int state,
- int flags);
-
- /* After acquiring or changing a lock at inter-node scope */
- void (*go_xmote_bh) (struct gfs_glock * gl);
-
- /* Release (unlock) a lock at inter-node scope:
- Does type-specific preparation (if any)
- Uses gfs_glock_drop_th to call lock module. */
- void (*go_drop_th) (struct gfs_glock * gl);
-
- /* After releasing a lock at inter-node scope */
- void (*go_drop_bh) (struct gfs_glock * gl);
-
- /* Sync dirty data to disk (e.g. before demoting an EX inter-node lock)
- (another node needs to read the updated data from disk) */
- void (*go_sync) (struct gfs_glock * gl, int flags);
-
- /* Invalidate local cached data just after releasing an inter-node lock
- (another node may change the on-disk data, so it's no good to us) */
- void (*go_inval) (struct gfs_glock * gl, int flags);
-
- /* Lock-type-specific check to see if it's okay to unlock a glock
- at inter-node scope (and remove it from our glock cache) */
- int (*go_demote_ok) (struct gfs_glock * gl);
-
- /* After getting lock for first holder (within this node) */
- int (*go_lock) (struct gfs_glock * gl, int flags);
-
- /* After last holder (within this node) gives up lock (glock may
- remain in glock cache, though) */
- void (*go_unlock) (struct gfs_glock * gl, int flags);
-
- /* After receiving a callback: another node needs the lock */
- void (*go_callback) (struct gfs_glock * gl, unsigned int state);
-
- /* Called when the glock layer marks a lock as being not greedy
- anymore */
- void (*go_greedy) (struct gfs_glock * gl);
-
- /* Lock type: locks with same lock # (often an FS block #),
- but different types, are different locks */
- int go_type;
-};
-
-/*
- * Glock holder structure
- * One for each holder of a glock.
- * These coordinate the use, within this node, of an acquired inter-node glock.
- * Once a node has acquired a glock, it may be shared within that node by
- * several processes, or even by several recursive requests from the same
- * process. Each is a separate "holder". Different holders may co-exist
- * having requested different lock states, as long as the node holds the
- * glock in a state that is compatible. A hold requestor may select, via
- * flags, the rules by which sharing within the node is granted:
- * LM_FLAG_ANY: Grant if glock state is any other than UNLOCKED.
- * GL_EXACT: Grant only if glock state is exactly the requested state.
- * GL_LOCAL_EXCL: Grant only one holder at a time within this node.
- * With no flags, a hold will be granted to a SHARED request even if the
- * node holds the glock in EXCLUSIVE mode. See relaxed_state_ok().
- * When a process needs to manipulate a lock, it requests it via one of
- * these holder structures. If the request cannot be satisfied immediately,
- * the holder structure gets queued on one of these lists in gfs_glock:
- * 1) waiters1, for gaining exclusive access to the (local) glock structure.
- * 2) waiters2, for demoting a lock (unlocking a glock, or changing its state
- * to be less restrictive) or relenquishing "greedy" status.
- * 3) waiters3, for promoting (locking a new glock, or changing a glock state
- * to be more restrictive).
- * When holding a lock, gfs_holder struct stays on glock's holder list.
- * See gfs-kernel/src/harness/lm_interface.h for gh_state (LM_ST_...)
- * and gh_flags (LM_FLAG...) fields.
- * Also see glock.h for gh_flags field (GL_...) flags.
- */
-
-/* Action requests */
-#define HIF_MUTEX (0) /* Exclusive (local) access to glock struct */
-#define HIF_PROMOTE (1) /* Change lock to more restrictive state */
-#define HIF_DEMOTE (2) /* Change lock to less restrictive state */
-#define HIF_GREEDY (3) /* Wait for the glock to be unlocked */
-
-/* States */
-#define HIF_ALLOCED (4) /* Holder structure is or was in use */
-#define HIF_DEALLOC (5) /* Toss holder struct as soon as queued request
- * is satisfied */
-#define HIF_HOLDER (6) /* We have been granted a hold on the lock */
-#define HIF_FIRST (7) /* We are first holder to get the lock */
-#define HIF_RECURSE (8) /* >1 hold requests on same glock by same process*/
-#define HIF_ABORTED (9) /* Aborted before being submitted */
-
-struct gfs_holder {
- struct list_head gh_list; /* Link to one of glock's holder lists */
-
- struct gfs_glock *gh_gl; /* Glock that we're holding */
- struct task_struct *gh_owner; /* Linux process that is the holder */
-
- /* request to change lock state */
- unsigned int gh_state; /* LM_ST_... requested lock state */
- int gh_flags; /* GL_... or LM_FLAG_... req modifiers */
-
- int gh_error; /* GLR_... CANCELLED/TRYFAILED/-errno */
- unsigned long gh_iflags; /* HIF_... holder state, see above */
- struct completion gh_wait; /* Wait for completion of ... */
-};
-
-/*
- * Glock Structure
- * One for each inter-node lock held by this node.
- * A glock is a local representation/abstraction of an inter-node lock.
- * Inter-node locks are managed by a "lock module" (LM) which plugs in to
- * the lock harness / glock interface (see gfs-kernel/harness). Different
- * lock modules support different lock protocols (e.g. GULM, GDLM, no_lock).
- * A glock may have one or more holders within a node. See gfs_holder above.
- * Glocks are managed within a hash table hosted by the in-core superblock.
- * After all holders have released a glock, it will stay in the hash table
- * cache for a time (depending on lock type), during which the inter-node
- * lock will not be released unless another node needs the lock (lock
- * manager requests this via callback to GFS through LM on this node). This
- * provides better performance in case this node needs the glock again soon.
- * See comments for meta_go_demote_ok(), glops.c.
- * Each glock has an associated vector of lock-type-specific "glops" functions
- * which are called at important times during the life of a glock, and
- * which define the type of lock (e.g. dinode, rgrp, non-disk, etc).
- * See gfs_glock_operations above.
- * A glock, at inter-node scope, is identified by the following dimensions:
- * 1) lock number (usually a block # for on-disk protected entities,
- * or a fixed assigned number for non-disk locks, e.g. MOUNT).
- * 2) lock type (actually, the type of entity protected by the lock).
- * 3) lock namespace, to support multiple GFS filesystems simultaneously.
- * Namespace (usually cluster:filesystem) is specified when mounting.
- * See man page for gfs_mount.
- * Glocks require support of Lock Value Blocks (LVBs) by the inter-node lock
- * manager. LVBs are small (32-byte) chunks of data associated with a given
- * lock, that can be quickly shared between cluster nodes. Used for certain
- * purposes such as sharing an rgroup's block usage statistics without
- * requiring the overhead of:
- * -- sync-to-disk by one node, then a
- * -- read from disk by another node.
- *
- */
-
-#define GLF_PLUG (0) /* Dummy */
-#define GLF_LOCK (1) /* Exclusive (local) access to glock
- * structure */
-#define GLF_STICKY (2) /* Don't release this inter-node lock
- * unless another node explicitly asks */
-#define GLF_PREFETCH (3) /* This lock has been (speculatively)
- * prefetched, demote if not used soon */
-#define GLF_SYNC (4) /* Sync lock's protected data as soon as
- * there are no more holders */
-#define GLF_DIRTY (5) /* There is dirty data for this lock,
- * sync before releasing inter-node */
-#define GLF_SKIP_WAITERS2 (6) /* Make run_queue() ignore gl_waiters2
- * (demote/greedy) holders */
-#define GLF_GREEDY (7) /* This lock is ignoring callbacks
- * (requests from other nodes) for now */
-#define GLF_DEMOTE (8) /* This is used to check for unflock completion
- * different from HIF_DEMOTE */
-
-struct gfs_glock {
- struct list_head gl_list; /* Link to hb_list in one of superblock's
- * sd_gl_hash glock hash table buckets */
- unsigned long gl_flags; /* GLF_... see above */
- struct lm_lockname gl_name; /* Lock number and lock type */
- atomic_t gl_count; /* Usage count */
-
- spinlock_t gl_spin; /* Protects some members of this struct */
-
- /* Lock state reflects inter-node manager's lock state */
- unsigned int gl_state; /* LM_ST_... see harness/lm_interface.h */
-
- /* Lists of gfs_holders */
- struct list_head gl_holders; /* all current holders of the glock */
- struct list_head gl_waiters1; /* HIF_MUTEX */
- struct list_head gl_waiters2; /* HIF_DEMOTE, HIF_GREEDY */
- struct list_head gl_waiters3; /* HIF_PROMOTE */
-
- struct gfs_glock_operations *gl_ops; /* function vector, defines type */
-
- /* State to remember for async lock requests */
- struct gfs_holder *gl_req_gh; /* Holder for request being serviced */
- gfs_glop_bh_t gl_req_bh; /* The bottom half to execute */
-
- void *gl_lock; /* Lock module's private lock data */
- char *gl_lvb; /* Lock Value Block */
- atomic_t gl_lvb_count; /* LVB recursive usage (hold/unhold) count */
-
- uint64_t gl_vn; /* Incremented when protected data changes */
- unsigned long gl_stamp; /* Glock cache retention timer */
- void *gl_object; /* The protected entity (e.g. a dinode) */
-
- /* Incore transaction stuff */
- /* Log elements map us to a particular set of log operations functions,
- and to a particular transaction */
- struct gfs_log_element gl_new_le; /* New, incomplete transaction */
- struct gfs_log_element gl_incore_le; /* Complete (committed) trans */
-
- struct gfs_gl_hash_bucket *gl_bucket; /* Our bucket in sd_gl_hash */
- struct list_head gl_reclaim; /* Link to sd_reclaim_list */
-
- struct gfs_sbd *gl_sbd; /* Superblock (FS instance) */
-
- struct inode *gl_aspace; /* The buffers protected by this lock */
- struct list_head gl_ail_bufs; /* AIL buffers protected by us */
-};
-
-/*
- * In-Place Reservation structure
- * Coordinates allocation of "in-place" (as opposed to journal) FS blocks,
- * which contain persistent inode/file/directory data and metadata.
- * These blocks are the allocatable blocks within resource groups (i.e.
- * not including rgrp header and block alloc bitmap blocks).
- * gfs_inplace_reserve() calculates a fulfillment plan for allocating blocks,
- * based on block statistics in the resource group headers.
- * Then, gfs_blkalloc() or gfs_metaalloc() walks the block alloc bitmaps
- * to do the actual allocation.
- */
-struct gfs_alloc {
- /* Up to 4 quotas (including an inode's user and group quotas)
- can track changes in block allocation */
-
- unsigned int al_qd_num; /* # of quotas tracking changes */
- struct gfs_quota_data *al_qd[4]; /* Ptrs to quota structures */
- struct gfs_holder al_qd_ghs[4]; /* Holders for quota glocks */
-
- /* Request, filled in by the caller to gfs_inplace_reserve() */
-
- uint32_t al_requested_di; /* Number of dinodes to reserve */
- uint32_t al_requested_meta; /* Number of metadata blocks to reserve */
- uint32_t al_requested_data; /* Number of data blocks to reserve */
-
- /* Fulfillment plan, filled in by gfs_inplace_reserve() */
-
- char *al_file; /* Debug info, .c file making request */
- unsigned int al_line; /* Debug info, line of code making req */
- struct gfs_holder al_ri_gh; /* Glock holder for resource grp index */
- struct gfs_holder al_rgd_gh; /* Glock holder for al_rgd rgrp */
- struct gfs_rgrpd *al_rgd; /* Resource group from which to alloc */
- uint32_t al_reserved_meta; /* Alloc up to this # meta blocks from al_rgd */
- uint32_t al_reserved_data; /* Alloc up to this # data blocks from al_rgd */
-
- /* Actual alloc, filled in by gfs_blkalloc()/gfs_metaalloc(), etc. */
-
- uint32_t al_alloced_di; /* # dinode blocks allocated */
- uint32_t al_alloced_meta; /* # meta blocks allocated */
- uint32_t al_alloced_data; /* # data blocks allocated */
-
- /* Dinode allocation crap */
-
- struct gfs_unlinked *al_ul; /* Unlinked dinode log entry */
-};
-
-/*
- * Incore inode structure
- */
-
-#define GIF_QD_LOCKED (0)
-#define GIF_PAGED (1)
-#define GIF_SW_PAGED (2)
-
-struct gfs_inode {
- struct gfs_inum i_num; /* Formal inode # and block address */
-
- atomic_t i_count; /* Usage count */
- unsigned long i_flags; /* GIF_... see above */
-
- uint64_t i_vn; /* Version #: if different from glock's vn,
- we need to read inode from disk */
- struct gfs_dinode i_di; /* Dinode (on-disk) structure */
-
- struct gfs_glock *i_gl; /* This glock protects this inode */
- struct gfs_sbd *i_sbd; /* Superblock (fs instance structure) */
- struct inode *i_vnode; /* Linux VFS inode structure */
-
- struct gfs_holder i_iopen_gh; /* Glock holder for Inode Open lock */
-
- /* Block allocation strategy, inode scope */
- struct gfs_alloc *i_alloc; /* In-place block reservation structure */
- uint64_t i_last_rg_alloc; /* Most recent blk alloc was fm this rgrp */
-
- spinlock_t i_spin;
- struct rw_semaphore i_rw_mutex;
-
- /* Cache of most-recently used buffers in indirect addressing chain */
- struct buffer_head *i_cache[GFS_MAX_META_HEIGHT];
-
- unsigned int i_greedy; /* The amount of time to be greedy */
- unsigned long i_last_pfault; /* The time of the last page fault */
-
- struct timeval i_dir_stat_st; /* Start time of stat counter */
- unsigned long i_dir_stats; /* stat counter for this directory */
- struct address_space_operations gfs_file_aops;
-};
-
-/*
- * GFS per-fd structure
- */
-
-#define GFF_DID_DIRECT_ALLOC (0)
-
-struct gfs_file {
- unsigned long f_flags; /* GFF_... see above */
-
- struct semaphore f_fl_lock; /* Lock to protect flock operations */
- struct gfs_holder f_fl_gh; /* Holder for this f_vfile's flock */
-
- struct gfs_inode *f_inode; /* Incore GFS inode */
- struct file *f_vfile; /* Linux file struct */
-};
-
-/*
- * Unlinked inode log entry incore structure
- */
-
-#define ULF_NEW_UL (0) /* Part of new (being built) trans */
-#define ULF_INCORE_UL (1) /* Part of incore-committed trans */
-#define ULF_IC_LIST (2)
-#define ULF_OD_LIST (3)
-#define ULF_LOCK (4) /* Protects access to this structure */
-
-struct gfs_unlinked {
- struct list_head ul_list; /* Link to superblock's sd_unlinked_list */
- unsigned int ul_count; /* Usage count */
-
- struct gfs_inum ul_inum; /* Formal inode #, block addr */
- unsigned long ul_flags; /* ULF_... */
-
- /* Log elements map us to a particular set of log operations functions,
- and to a particular transaction */
- struct gfs_log_element ul_new_le; /* New, not yet committed */
- struct gfs_log_element ul_incore_le; /* Committed to incore log */
- struct gfs_log_element ul_ondisk_le; /* Committed to ondisk log */
-};
-
-/*
- * Quota log element
- * One for each logged change in a block alloc value affecting a given quota.
- * Only one of these for a given quota within a given transaction;
- * multiple changes, within one transaction, for a given quota will be
- * combined into one log element.
- */
-struct gfs_quota_le {
- /* Log element maps us to a particular set of log operations functions,
- and to a particular transaction */
- struct gfs_log_element ql_le; /* Generic log element structure */
-
- struct gfs_quota_data *ql_data; /* The quota we're changing */
- struct list_head ql_data_list; /* Link to quota's log element list */
-
- int64_t ql_change; /* # of blocks alloc'd (+) or freed (-) */
-};
-
-/*
- * Quota structure
- * One for each user or group quota.
- * Summarizes all block allocation activity for a given quota, and supports
- * recording updates of current block alloc values in GFS' special quota
- * file, including the journaling of these updates, encompassing
- * multiple transactions and log dumps.
- */
-
-#define QDF_USER (0) /* User (1) vs. group (0) quota */
-#define QDF_OD_LIST (1) /* Waiting for sync to quota file */
-#define QDF_LOCK (2) /* Protects access to this structure */
-
-struct gfs_quota_data {
- struct list_head qd_list; /* Link to superblock's sd_quota_list */
- unsigned int qd_count; /* Usage count */
-
- uint32_t qd_id; /* User or group ID number */
- unsigned long qd_flags; /* QDF_... */
-
- /* This list is for non-log-dump transactions */
- struct list_head qd_le_list; /* List of gfs_quota_le log elements */
-
- /* Summary of block alloc changes affecting this quota, in various
- stages of logging & syncing changes to the special quota file */
- int64_t qd_change_new; /* New, not yet committed to in-core log*/
- int64_t qd_change_ic; /* Committed to in-core log */
- int64_t qd_change_od; /* Committed to on-disk log */
- int64_t qd_change_sync; /* Being synced to the in-place quota file */
-
- struct gfs_quota_le qd_ondisk_ql; /* Log element for log dump */
- uint64_t qd_sync_gen; /* Sync-to-quota-file generation # */
-
- /* Glock provides protection for quota, *and* provides
- lock value block (LVB) communication, between nodes, of current
- quota values. Shared lock -> LVB read. EX lock -> LVB write. */
- struct gfs_glock *qd_gl; /* glock for this quota */
- struct gfs_quota_lvb qd_qb; /* LVB (limit/warn/value) */
-
- unsigned long qd_last_warn; /* Jiffies of last warning to user */
-};
-
-/*
- * Log Buffer descriptor structure.
- * One for each block buffer recorded in the log.
- * When beginning a new transaction, GFS pre-allocates a number of these,
- * and puts them on transaction's tr_free_bufs list.
- * Logged buffers are of two types:
- * 1). Exact copies of buffers to be written to in-place location in FS.
- * 2). Log-only buffers such as log headers and control blocks (e.g. tags).
- * A gfs_log_buf is required for both types; the ones for log-only buffers
- * contain NULL in lb_unlock, and get cleaned up after the log write.
- * lb_bh is a "fake" buffer head that directs Linux block I/O to write the buf
- * to the on-disk log location, rather than the on-disk in-place location.
- * Used for both types.
- * lb_unlock points to the "real" buffer head that directs Linux to write the
- * buf to its regular on-disk in-place filesystem location. Once the commit
- * to the on-disk log is finished, GFS unlocks the "real" buffer so it can be
- * written to in-place block, or modified by another transaction.
- * Used only for type 1).
- */
-struct gfs_log_buf {
- /* Link to one of the transaction structure's lists */
- struct list_head lb_list; /* Link to tr_free_bufs or tr_list */
-
- struct buffer_head lb_bh; /* "Fake" bh; for the log block */
- struct buffer_head *lb_unlock; /* "Real" bh; for the in-place block */
-};
-
-/*
- * Transaction structure
- * One for each transaction
- * This coordinates the logging and flushing of written metadata.
- */
-
-#define TRF_LOG_DUMP (0x00000001)
-#define TRF_DUMMY (0x00000002)
-
-struct gfs_trans {
-
- /* Link to various lists */
- struct list_head tr_list; /* Superblk's incore trans or AIL list*/
-
- /* Initial creation stuff */
-
- char *tr_file; /* Debug info: .c file creating trans */
- unsigned int tr_line; /* Debug info: codeline creating trans */
-
- /* Reservations for on-disk space in journal.
- Meta blocks are copies of in-place filesystem blocks.
- Extra blocks are log-only (log header and control blocks) */
- unsigned int tr_mblks_asked; /* # of meta log blocks requested */
- unsigned int tr_eblks_asked; /* # of extra log blocks requested */
- unsigned int tr_seg_reserved; /* # of segments actually reserved */
-
- struct gfs_holder *tr_t_gh; /* Glock holder for this transaction */
-
- /* Stuff filled in during creation */
-
- unsigned int tr_flags; /* TRF_... */
- struct list_head tr_elements; /* List of this trans' log elements */
-
- /* Stuff modified during the commit */
-
- /* When creating a new transaction, GFS pre-allocates as many of
- these buffers and descriptor structures as it might need for
- all loggable filesystem (meta)data, and log-control (log-only, not
- going to filesystem in-place location) data going to on-disk log.
- It keeps them on these "free" lists until they get used (and linked
- into tr_bufs list, below) or "refunded" if not needed. */
- unsigned int tr_num_free_bufs; /* List of free gfs_log_buf structs */
- struct list_head tr_free_bufs; /* .. 1 for each log block */
- unsigned int tr_num_free_bmem; /* List of free fs-block-size buffers */
- struct list_head tr_free_bmem; /* .. for log-only (e.g. tag) blocks */
-
- /* Logged transaction starts with a (first) log header at a segment
- boundary, and fills contiguous blocks after that. Each segment
- boundary block gets another log header. */
- uint64_t tr_log_head; /* The next log block # to fill */
- uint64_t tr_first_head; /* Trans' first log header's block # */
-
- /* gfs_log_buf structs move from tr_free_bufs to here when being used */
- struct list_head tr_bufs; /* List of buffers going to the log */
-
- /* Stuff that's part of the Active Items List (AIL) */
-
- struct list_head tr_ail_bufs; /* List of buffers on AIL list */
-
- /* # log elements of various types on tr_elements list */
-
- unsigned int tr_num_gl; /* Glocks */
- unsigned int tr_num_buf; /* Buffers */
- unsigned int tr_num_iul; /* Unlinked inodes */
- unsigned int tr_num_ida; /* De-allocated inodes */
- unsigned int tr_num_q; /* Quotas */
-};
-
-#define GFS_GLOCKD_DEFAULT (1)
-#define GFS_GLOCKD_MAX (32)
-
-#define GFS_QUOTA_DEFAULT GFS_QUOTA_OFF
-#define GFS_QUOTA_OFF 0
-#define GFS_QUOTA_ACCOUNT 1
-#define GFS_QUOTA_ON 2
-
-#define GFS_DATA_DEFAULT GFS_DATA_ORDERED
-#define GFS_DATA_WRITEBACK 1
-#define GFS_DATA_ORDERED 2
-
-#define GFS_ERRORS_WITHDRAW 0
-#define GFS_ERRORS_CONTINUE 1 /* place holder for future feature */
-#define GFS_ERRORS_RO 2 /* place holder for future feature */
-#define GFS_ERRORS_PANIC 3
-
-struct gfs_args {
- char ar_lockproto[GFS_LOCKNAME_LEN]; /* The name of the Lock Protocol */
- char ar_locktable[GFS_LOCKNAME_LEN]; /* The name of the Lock Table */
- char ar_hostdata[GFS_LOCKNAME_LEN]; /* The host specific data */
-
- int ar_spectator; /* Don't get a journal because we're always RO. */
- /*
- * GFS can invoke some flock and disk caching optimizations if it is
- * not in a cluster, i.e. is a local filesystem. The chosen lock
- * module tells GFS, at mount time, if it supports clustering.
- * The nolock module is the only one that does not support clustering;
- * it sets to TRUE the local_fs field in the struct lm_lockops.
- * GFS can either optimize, or ignore the opportunity.
- * The user controls behavior via the following mount options.
- */
- int ar_ignore_local_fs; /* Don't optimize even if local_fs is TRUE */
- int ar_localflocks; /* Let the VFS do flock|fcntl locks for us */
- int ar_localcaching; /* Local-style caching (dangerous on multihost) */
- int ar_oopses_ok; /* Allow oopses */
-
- int ar_debug; /* Oops on errors instead of trying to be graceful */
- int ar_errors; /* errors=default | panic */
- int ar_upgrade; /* Upgrade ondisk/multihost format */
-
- unsigned int ar_num_glockd; /* # of glock cleanup daemons to run
- (more daemons => faster cleanup) */
- int ar_posix_acls; /* Enable posix acls */
- int ar_suiddir; /* suiddir support */
- int ar_noquota; /* Turn off quota support */
- int ar_noatime; /* Turn off atime updates */
-};
-
-struct gfs_tune {
- spinlock_t gt_spin;
-
- unsigned int gt_ilimit1;
- unsigned int gt_ilimit1_tries;
- unsigned int gt_ilimit1_min;
- unsigned int gt_ilimit2;
- unsigned int gt_ilimit2_tries;
- unsigned int gt_ilimit2_min;
- unsigned int gt_demote_secs; /* Cache retention for unheld glock */
- unsigned int gt_incore_log_blocks;
- unsigned int gt_jindex_refresh_secs; /* Check for new journal index */
- unsigned int gt_depend_secs;
-
- /* How often various daemons run (seconds) */
- unsigned int gt_scand_secs; /* Find unused glocks and inodes */
- unsigned int gt_recoverd_secs; /* Recover journal of crashed node */
- unsigned int gt_logd_secs; /* Update log tail as AIL flushes */
- unsigned int gt_quotad_secs; /* Sync changes to quota file, clean*/
- unsigned int gt_inoded_secs; /* Toss unused inodes */
- unsigned int gt_glock_purge; /* Purge glock */
-
- unsigned int gt_quota_simul_sync; /* Max # quotavals to sync at once */
- unsigned int gt_quota_warn_period; /* Secs between quota warn msgs */
- unsigned int gt_atime_quantum; /* Min secs between atime updates */
- unsigned int gt_quota_quantum; /* Secs between syncs to quota file */
- unsigned int gt_quota_scale_num; /* Numerator */
- unsigned int gt_quota_scale_den; /* Denominator */
- unsigned int gt_quota_enforce;
- unsigned int gt_quota_account;
- unsigned int gt_new_files_jdata;
- unsigned int gt_new_files_directio;
- unsigned int gt_max_atomic_write; /* Split large writes into this size*/
- unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */
- unsigned int gt_lockdump_size;
- unsigned int gt_stall_secs; /* Detects trouble! */
- unsigned int gt_complain_secs;
- unsigned int gt_reclaim_limit; /* Max # glocks in reclaim list */
- unsigned int gt_entries_per_readdir;
- unsigned int gt_prefetch_secs; /* Usage window for prefetched glocks */
- unsigned int gt_statfs_slots;
- unsigned int gt_max_mhc; /* Max # of meta headers in mhc cache */
- unsigned int gt_greedy_default;
- unsigned int gt_greedy_quantum;
- unsigned int gt_greedy_max;
- unsigned int gt_rgrp_try_threshold;
- unsigned int gt_statfs_fast;
-};
-
-/*
- * One bucket of the filesystem's sd_gl_hash glock hash table.
- *
- * A gfs_glock links into a bucket's list via glock's gl_list member.
- *
- */
-struct gfs_gl_hash_bucket {
- rwlock_t hb_lock; /* Protects list */
- struct list_head hb_list; /* List of glocks in this bucket */
-};
-
-/*
- * "Super Block" Data Structure
- * One per mounted filesystem.
- * This is the big instance structure that ties everything together for
- * a given mounted filesystem. Each GFS mount has its own, supporting
- * mounts of multiple GFS filesystems on each node.
- * Pointer to this is usually seen as "sdp" throughout code.
- * This is a very large structure, as structures go, in part because it
- * contains arrays of hash buckets for various in-core caches.
- */
-
-#define SDF_JOURNAL_LIVE (0) /* Journaling is active (journal is writeable)*/
-#define SDF_SHUTDOWN (1) /* FS abnormaly shutdown */
-
-/* (Re)mount options from Linux VFS */
-#define SDF_NOATIME (8) /* Don't change access time */
-#define SDF_ROFS (9) /* Read-only mode */
-
-/* Journal log dump support */
-#define SDF_NEED_LOG_DUMP (10) /* Need to rewrite unlink and quota tags */
-#define SDF_FOUND_UL_DUMP (11) /* Recovery found unlinked tags */
-#define SDF_FOUND_Q_DUMP (12) /* Recovery found qutoa tags */
-#define SDF_IN_LOG_DUMP (13) /* Serializes log dumps */
-
-/* Glock cache */
-#define GFS_GL_HASH_SHIFT (13) /* # hash buckets = 8K */
-#define GFS_GL_HASH_SIZE (1 << GFS_GL_HASH_SHIFT)
-#define GFS_GL_HASH_MASK (GFS_GL_HASH_SIZE - 1)
-
-/* Meta header cache */
-#define GFS_MHC_HASH_SHIFT (10) /* # hash buckets = 1K */
-#define GFS_MHC_HASH_SIZE (1 << GFS_MHC_HASH_SHIFT)
-#define GFS_MHC_HASH_MASK (GFS_MHC_HASH_SIZE - 1)
-
-/* Dependency cache */
-#define GFS_DEPEND_HASH_SHIFT (10) /* # hash buckets = 1K */
-#define GFS_DEPEND_HASH_SIZE (1 << GFS_DEPEND_HASH_SHIFT)
-#define GFS_DEPEND_HASH_MASK (GFS_DEPEND_HASH_SIZE - 1)
-
-struct gfs_sbd {
- struct gfs_sb sd_sb; /* GFS on-disk Super Block image */
-
- struct super_block *sd_vfs; /* Linux VFS device independent sb */
-
- struct gfs_args sd_args; /* Mount arguments */
- unsigned long sd_flags; /* SDF_... see above */
-
- struct gfs_tune sd_tune; /* Filesystem tuning structure */
-
- /* statfs */
- struct inode *sd_statfs_inode;
- spinlock_t sd_statfs_spin;
- struct gfs_statfs_change_host sd_statfs_master;
- struct gfs_statfs_change_host sd_statfs_local;
- unsigned long sd_statfs_sync_time;
-
- /* Resource group stuff */
-
- struct gfs_inode *sd_riinode; /* Resource Index (rindex) inode */
- uint64_t sd_riinode_vn; /* Resource Index version # (detects
- whether new rgrps have been added) */
-
- struct list_head sd_rglist; /* List of all resource groups,
- on-disk order */
- struct semaphore sd_rindex_lock;/* Serializes RIndex rereads */
- struct list_head sd_rg_mru_list;/* List of all resource groups,
- most-recently-used (MRU) order */
- spinlock_t sd_rg_mru_lock; /* Protect mru list */
- struct list_head sd_rg_recent; /* List of rgrps from which blocks
- were recently allocated */
- spinlock_t sd_rg_recent_lock; /* Protect recent list */
- struct gfs_rgrpd *sd_rg_forward;/* Next rgrp from which to attempt
- a block alloc */
- spinlock_t sd_rg_forward_lock; /* Protect forward pointer */
-
- unsigned int sd_rgcount; /* Total # of resource groups */
-
- /* Constants computed on mount */
-
- /* "bb" == "basic block" == 512Byte sector */
- uint32_t sd_fsb2bb; /* # 512B basic blocks in a FS block */
- uint32_t sd_fsb2bb_shift; /* Shift sector # to the right by
- this to get FileSystem block addr */
- uint32_t sd_diptrs; /* Max # of block pointers in a dinode */
- uint32_t sd_inptrs; /* Max # of block pointers in an indirect blk */
- uint32_t sd_jbsize; /* Payload size (bytes) of a journaled metadata
- block (GFS journals all meta blocks) */
- uint32_t sd_hash_bsize; /* sizeof(exhash hash block) */
- uint32_t sd_hash_bsize_shift;
- uint32_t sd_hash_ptrs; /* Number of points in a hash block */
- uint32_t sd_max_dirres; /* Max blocks needed to add a directory entry */
- uint32_t sd_max_height; /* Max height of a file's tree */
- uint64_t sd_heightsize[GFS_MAX_META_HEIGHT];
- uint32_t sd_max_jheight; /* Max height, journaled file's tree */
- uint64_t sd_jheightsize[GFS_MAX_META_HEIGHT];
-
- /* Lock Stuff */
-
- /* Glock cache (all glocks currently held by this node for this FS) */
- struct gfs_gl_hash_bucket sd_gl_hash[GFS_GL_HASH_SIZE];
-
- /* Glock reclaim support for scand and glockd */
- struct list_head sd_reclaim_list; /* List of glocks to reclaim */
- spinlock_t sd_reclaim_lock;
- wait_queue_head_t sd_reclaim_wchan;
- atomic_t sd_reclaim_count; /* # glocks on reclaim list */
-
- /* Lock module tells us if we're first-to-mount,
- which journal to use, etc. */
- struct lm_lockstruct sd_lockstruct; /* Info provided by lock module */
-
- /* Other caches */
-
- /* Meta-header cache (incore copies of on-disk meta headers) */
- struct list_head sd_mhc[GFS_MHC_HASH_SIZE]; /* hash buckets */
- struct list_head sd_mhc_single; /* Non-hashed list of all MHCs */
- spinlock_t sd_mhc_lock;
- atomic_t sd_mhc_count; /* # MHCs in cache */
-
- /* Dependency cache */
- struct list_head sd_depend[GFS_DEPEND_HASH_SIZE]; /* Hash buckets */
- spinlock_t sd_depend_lock;
- atomic_t sd_depend_count; /* # dependencies in cache */
-
- /* LIVE inter-node lock indicates that FS is mounted on at least
- one node */
- struct gfs_holder sd_live_gh; /* Glock holder for LIVE lock */
-
- /* For quiescing the filesystem */
- struct gfs_holder sd_freeze_gh;
- struct semaphore sd_freeze_lock;
- unsigned int sd_freeze_count;
-
- /* Inode Stuff */
-
- struct gfs_inode *sd_rooti; /* FS's root inode */
-
- /* Only 1 node at a time may rename (e.g. mv) directory from
- one directory to another. */
- struct gfs_glock *sd_rename_gl; /* Rename glock */
-
- /* Daemon stuff */
-
- /* Scan for glocks and inodes to toss from memory */
- struct task_struct *sd_scand_process; /* Scand places on reclaim list*/
- struct task_struct *sd_glockd_process[GFS_GLOCKD_MAX];
- unsigned int sd_glockd_num; /* # of glockd procs to do reclaiming*/
-
- /* Recover journal of a crashed node */
- struct task_struct *sd_recoverd_process;
-
- /* Update log tail as AIL gets flushed to in-place on-disk blocks */
- struct task_struct *sd_logd_process;
-
- /* Sync quota updates to disk, and clean up unused quota structs */
- struct task_struct *sd_quotad_process;
-
- /* Clean up unused inode structures */
- struct task_struct *sd_inoded_process;
-
- /* Log stuff */
-
- /* Transaction lock protects the following from one another:
- normal write transaction, journal replay (recovery), fs upgrade,
- fs read-only => read/write and read/write => read-only conversions.
- Also, acquiring the transaction lock in a state other than shared
- causes all other machines in the cluster to sync out their dirty
- data, mark their journal as being clean, and prevent any new FS
- modifications from occuring (i.e. quiesces the FS). */
- struct gfs_glock *sd_trans_gl; /* Transaction glock structure */
-
- struct gfs_inode *sd_jiinode; /* Journal index inode */
- uint64_t sd_jiinode_vn; /* Journal index version # (detects
- if new journals have been added) */
-
- unsigned int sd_journals; /* Number of journals in the FS */
- struct gfs_jindex *sd_jindex; /* Array of journal descriptors */
- struct semaphore sd_jindex_lock;
- unsigned long sd_jindex_refresh_time; /* Poll for new journals (secs) */
-
- struct gfs_jindex sd_jdesc; /* This machine's journal descriptor */
- struct gfs_holder sd_journal_gh; /* This machine's jrnl glock holder */
-
- uint64_t sd_sequence; /* Assigned to xactions in order they commit */
- uint64_t sd_log_head; /* Block number of next journal write */
- uint64_t sd_log_wrap;
-
- spinlock_t sd_log_seg_lock;
- unsigned int sd_log_seg_free; /* # of free segments in the log */
- unsigned int sd_log_seg_ail2; /* # of freeable segments in the log */
- struct list_head sd_log_seg_list;
- wait_queue_head_t sd_log_seg_wait;
-
- /* "Active Items List" of transactions that have been flushed to
- on-disk log, and are waiting for flush to in-place on-disk blocks */
- struct list_head sd_log_ail; /* "next" is head, "prev" is tail */
-
- /* Transactions committed incore, but not yet flushed to on-disk log */
- struct list_head sd_log_incore; /* "Next" is newest, "prev" is oldest */
- unsigned int sd_log_buffers; /* # of buffers in the incore log */
-
- struct rw_semaphore sd_log_lock; /* Lock for access to log values */
-
- uint64_t sd_log_dump_last;
- uint64_t sd_log_dump_last_wrap;
-
- /*
- * Unlinked inode crap.
- * List includes newly created, not-yet-linked inodes,
- * as well as inodes that have been unlinked and are waiting
- * to be de-allocated.
- */
- struct list_head sd_unlinked_list; /* List of unlinked inodes */
- spinlock_t sd_unlinked_lock; /* Protects list and members */
-
- atomic_t sd_unlinked_ic_count;
- atomic_t sd_unlinked_od_count;
-
- /* Quota crap */
-
- struct list_head sd_quota_list; /* List of all gfs_quota_data structs */
- spinlock_t sd_quota_lock;
-
- atomic_t sd_quota_count; /* # quotas on sd_quota_list */
- atomic_t sd_quota_od_count; /* # quotas waiting for sync to
- special on-disk quota file */
-
- struct gfs_inode *sd_qinode; /* Special on-disk quota file */
-
- uint64_t sd_quota_sync_gen; /* Generation, incr when sync to file */
- unsigned long sd_quota_sync_time; /* Jiffies, last sync to quota file */
-
- /* License crap */
-
- struct gfs_inode *sd_linode; /* Special on-disk license file */
-
- /* Recovery stuff */
-
- /* Lock module tells GFS, via callback, when a journal needs recovery.
- It stays on this list until recovery daemon performs recovery. */
- struct list_head sd_dirty_j; /* List of dirty journals */
- spinlock_t sd_dirty_j_lock; /* Protects list */
-
- /* Statistics for 3 possible recovery actions for each buffer in log,
- determined by comparing generation #s of logged block and
- in-place block. Scope of stats is for one journal. */
- unsigned int sd_recovery_replays; /* newer than in-place; copy it */
- unsigned int sd_recovery_skips; /* older than in-place; ignore it */
- unsigned int sd_recovery_sames; /* same as in-place; ignore it */
-
- /* Counters */
-
- /* current quantities of various things */
- atomic_t sd_glock_count; /* # of gfs_glock structs alloc'd */
- atomic_t sd_glock_held_count; /* # of glocks locked by this node */
- atomic_t sd_inode_count; /* # of gfs_inode structs alloc'd */
- atomic_t sd_bufdata_count; /* # of gfs_bufdata structs alloc'd */
-
- atomic_t sd_fh2dentry_misses; /* total # get_dentry misses */
- atomic_t sd_reclaimed; /* total # glocks reclaimed since mount */
-
- /* total lock-related calls handled since mount */
- atomic_t sd_glock_nq_calls;
- atomic_t sd_glock_dq_calls;
- atomic_t sd_glock_prefetch_calls;
- atomic_t sd_lm_lock_calls;
- atomic_t sd_lm_unlock_calls;
- atomic_t sd_lm_callbacks;
-
- atomic_t sd_lm_outstanding;
- atomic_t sd_bio_reads;
- atomic_t sd_bio_writes;
- atomic_t sd_bio_outstanding;
-
- /* total calls from Linux VFS handled since mount */
- atomic_t sd_ops_address;
- atomic_t sd_ops_dentry;
- atomic_t sd_ops_export;
- atomic_t sd_ops_file;
- atomic_t sd_ops_inode;
- atomic_t sd_ops_super;
- atomic_t sd_ops_vm;
-
- char sd_fsname[256];
- char sd_table_name[256];
- char sd_proto_name[256];
-
- struct kobject sd_kobj;
-
- /* Debugging crud */
-
- unsigned long sd_last_warning;
-
- spinlock_t sd_ail_lock;
- struct list_head sd_recovery_bufs;
-
- struct list_head sd_list;
-};
-
-#endif /* __INCORE_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/inode.c b/gfs-kernel/src/gfs/inode.c
deleted file mode 100644
index 68c94e6..0000000
--- a/gfs-kernel/src/gfs/inode.c
+++ /dev/null
@@ -1,2224 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/posix_acl.h>
-#include <linux/cred.h>
-
-#include "gfs.h"
-#include "acl.h"
-#include "bmap.h"
-#include "dio.h"
-#include "dir.h"
-#include "eattr.h"
-#include "glock.h"
-#include "glops.h"
-#include "inode.h"
-#include "log.h"
-#include "ops_address.h"
-#include "ops_file.h"
-#include "ops_inode.h"
-#include "quota.h"
-#include "rgrp.h"
-#include "trans.h"
-#include "unlinked.h"
-
-/**
- * inode_attr_in - Copy attributes from the dinode into the VFS inode
- * @ip: The GFS inode (with embedded disk inode data)
- * @inode: The Linux VFS inode
- *
- */
-
-static void
-inode_attr_in(struct gfs_inode *ip, struct inode *inode)
-{
- unsigned int mode;
-
- inode->i_ino = ip->i_num.no_formal_ino;
-
- switch (ip->i_di.di_type) {
- case GFS_FILE_REG:
- mode = S_IFREG;
- inode->i_rdev = 0;
- break;
- case GFS_FILE_DIR:
- mode = S_IFDIR;
- inode->i_rdev = 0;
- break;
- case GFS_FILE_LNK:
- mode = S_IFLNK;
- inode->i_rdev = 0;
- break;
- case GFS_FILE_BLK:
- mode = S_IFBLK;
- inode->i_rdev = MKDEV(ip->i_di.di_major, ip->i_di.di_minor);
- break;
- case GFS_FILE_CHR:
- mode = S_IFCHR;
- inode->i_rdev = MKDEV(ip->i_di.di_major, ip->i_di.di_minor);
- break;
- case GFS_FILE_FIFO:
- mode = S_IFIFO;
- inode->i_rdev = 0;
- break;
- case GFS_FILE_SOCK:
- mode = S_IFSOCK;
- inode->i_rdev = 0;
- break;
- default:
- if (gfs_consist_inode(ip))
- printk("GFS: fsid=%s: type = %u\n",
- ip->i_sbd->sd_fsname, ip->i_di.di_type);
- return;
- };
-
- inode->i_mode = mode | (ip->i_di.di_mode & S_IALLUGO);
- inode->i_nlink = ip->i_di.di_nlink;
- inode->i_uid = ip->i_di.di_uid;
- inode->i_gid = ip->i_di.di_gid;
- i_size_write(inode, ip->i_di.di_size);
- inode->i_atime.tv_sec = ip->i_di.di_atime;
- inode->i_mtime.tv_sec = ip->i_di.di_mtime;
- inode->i_ctime.tv_sec = ip->i_di.di_ctime;
- inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
- inode->i_blocks = ip->i_di.di_blocks <<
- (ip->i_sbd->sd_sb.sb_bsize_shift - GFS_BASIC_BLOCK_SHIFT);
- inode->i_generation = ip->i_di.di_header.mh_incarn;
-
- if (ip->i_di.di_flags & GFS_DIF_IMMUTABLE)
- inode->i_flags |= S_IMMUTABLE;
- else
- inode->i_flags &= ~S_IMMUTABLE;
-
- if (ip->i_di.di_flags & GFS_DIF_APPENDONLY)
- inode->i_flags |= S_APPEND;
- else
- inode->i_flags &= ~S_APPEND;
-}
-
-/**
- * gfs_inode_attr_in - Copy attributes from the dinode into the VFS inode
- * @ip: The GFS inode (with embedded disk inode data)
- *
- */
-
-void
-gfs_inode_attr_in(struct gfs_inode *ip)
-{
- struct inode *inode;
-
- inode = gfs_iget(ip, NO_CREATE);
- if (inode) {
- inode_attr_in(ip, inode);
- iput(inode);
- }
-
-}
-
-/**
- * gfs_inode_attr_out - Copy attributes from VFS inode into the dinode
- * @ip: The GFS inode
- *
- * Only copy out the attributes that we want the VFS layer
- * to be able to modify.
- */
-
-void
-gfs_inode_attr_out(struct gfs_inode *ip)
-{
- struct inode *inode = ip->i_vnode;
-
- ip->i_di.di_mode = inode->i_mode & S_IALLUGO;
- ip->i_di.di_uid = inode->i_uid;
- ip->i_di.di_gid = inode->i_gid;
- ip->i_di.di_atime = inode->i_atime.tv_sec;
- ip->i_di.di_mtime = inode->i_mtime.tv_sec;
- ip->i_di.di_ctime = inode->i_ctime.tv_sec;
-}
-
-/**
- * gfs_iget - Get/Create a struct inode for a struct gfs_inode
- * @ip: the struct gfs_inode to get the struct inode for
- * @create: CREATE -- create a new struct inode if one does not already exist
- * NO_CREATE -- return NULL if inode doesn't exist
- *
- * Returns: A VFS inode, or NULL if NO_CREATE and none in existance
- *
- * If this function creates a new inode, it:
- * Copies fields from the GFS on-disk (d)inode to the VFS inode
- * Attaches the appropriate ops vectors to the VFS inode and address_space
- * Attaches the VFS inode to the gfs_inode
- * Inserts the new inode in the VFS inode hash, while avoiding races
- */
-
-struct inode *
-gfs_iget(struct gfs_inode *ip, int create)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct inode *inode = NULL, *tmp;
-
- spin_lock(&ip->i_spin);
- if (ip->i_vnode)
- inode = igrab(ip->i_vnode);
- spin_unlock(&ip->i_spin);
-
- if (inode || !create)
- return inode;
-
- tmp = new_inode(ip->i_sbd->sd_vfs);
- if (!tmp)
- return NULL;
-
- inode_attr_in(ip, tmp);
-
- /* Attach GFS-specific ops vectors */
- if (ip->i_di.di_type == GFS_FILE_REG) {
- tmp->i_op = &gfs_file_iops;
- memcpy(&ip->gfs_file_aops, &gfs_file_aops,
- sizeof(struct address_space_operations));
- tmp->i_mapping->a_ops = &ip->gfs_file_aops;
- if (sdp->sd_args.ar_localflocks) {
- if (gfs_is_jdata(ip))
- tmp->i_fop = &gfs_file_fops_nolock_jdata;
- else
- tmp->i_fop = &gfs_file_fops_nolock;
- } else {
- if (gfs_is_jdata(ip))
- tmp->i_fop = &gfs_file_fops_jdata;
- else
- tmp->i_fop = &gfs_file_fops;
- }
- } else if (ip->i_di.di_type == GFS_FILE_DIR) {
- tmp->i_op = &gfs_dir_iops;
- if (sdp->sd_args.ar_localflocks)
- tmp->i_fop = &gfs_dir_fops_nolock;
- else
- tmp->i_fop = &gfs_dir_fops;
- } else if (ip->i_di.di_type == GFS_FILE_LNK) {
- tmp->i_op = &gfs_symlink_iops;
- } else {
- tmp->i_op = &gfs_dev_iops;
- init_special_inode(tmp, tmp->i_mode, tmp->i_rdev);
- }
-
- set_v2ip(tmp, NULL);
-
- /* Did another process successfully create an inode while we were
- preparing this (tmp) one? If so, we can use that other one, and
- trash the one we were preparing.
- The other process might not be done inserting the inode in the
- VFS hash table. If so, we need to wait until it is done, then
- we can use it. */
- for (;;) {
- spin_lock(&ip->i_spin);
- if (!ip->i_vnode)
- break;
- inode = igrab(ip->i_vnode);
- spin_unlock(&ip->i_spin);
-
- if (inode) {
- iput(tmp);
- return inode;
- }
- yield();
- }
-
- inode = tmp;
-
- gfs_inode_hold(ip);
- ip->i_vnode = inode;
- set_v2ip(inode, ip);
-
- spin_unlock(&ip->i_spin);
-
- insert_inode_hash(inode);
-
- return inode;
-}
-
-/**
- * gfs_copyin_dinode - Refresh the incore copy of the dinode
- * @ip: The GFS inode
- *
- * Returns: errno
- */
-
-int
-gfs_copyin_dinode(struct gfs_inode *ip)
-{
- struct buffer_head *dibh;
- int error;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- return error;
-
- if (gfs_metatype_check(ip->i_sbd, dibh, GFS_METATYPE_DI)) {
- brelse(dibh);
- return -EIO;
- }
-
- gfs_dinode_in(&ip->i_di, dibh->b_data);
- brelse(dibh);
-
- if (ip->i_num.no_formal_ino != ip->i_di.di_num.no_formal_ino) {
- if (gfs_consist_inode(ip))
- gfs_dinode_print(&ip->i_di);
- return -EIO;
- }
-
- /* Handle a moved inode (not implemented yet) */
- if (ip->i_num.no_addr != ip->i_di.di_num.no_addr) {
- if (gfs_consist_inode(ip))
- gfs_dinode_print(&ip->i_di);
- return -EIO;
- }
-
- ip->i_vn = ip->i_gl->gl_vn;
-
- return 0;
-}
-
-/**
- * inode_create - create a struct gfs_inode, acquire Inode-Open (iopen) glock,
- * read dinode from disk
- * @i_gl: The (already held) glock covering the inode
- * @inum: The inode number
- * @io_gl: the iopen glock to acquire/hold (using holder in new gfs_inode)
- * @io_state: the state the iopen glock should be acquired in
- * @ipp: pointer to put the returned inode in
- *
- * Returns: errno
- */
-
-static int
-inode_create(struct gfs_glock *i_gl, struct gfs_inum *inum,
- struct gfs_glock *io_gl, unsigned int io_state,
- struct gfs_inode **ipp)
-{
- struct gfs_sbd *sdp = i_gl->gl_sbd;
- struct gfs_inode *ip;
- int error = 0;
-
- RETRY_MALLOC(ip = kmem_cache_alloc(gfs_inode_cachep, GFP_KERNEL), ip);
- memset(ip, 0, sizeof(struct gfs_inode));
-
- ip->i_num = *inum;
-
- atomic_set(&ip->i_count, 1);
-
- ip->i_gl = i_gl;
- ip->i_sbd = sdp;
-
- spin_lock_init(&ip->i_spin);
- init_rwsem(&ip->i_rw_mutex);
-
- ip->i_greedy = gfs_tune_get(sdp, gt_greedy_default);
-
- /* Lock the iopen glock (may be recursive) */
- error = gfs_glock_nq_init(io_gl,
- io_state, GL_LOCAL_EXCL | GL_EXACT,
- &ip->i_iopen_gh);
- if (error)
- goto fail;
-
- ip->i_iopen_gh.gh_owner = NULL;
-
- /* Assign the inode's glock as this iopen glock's protected object */
- spin_lock(&io_gl->gl_spin);
- gfs_glock_hold(i_gl);
- set_gl2gl(io_gl, i_gl);
- spin_unlock(&io_gl->gl_spin);
-
- /* Read dinode from disk */
- error = gfs_copyin_dinode(ip);
- if (error)
- goto fail_iopen;
-
- gfs_glock_hold(i_gl);
- set_gl2ip(i_gl, ip);
-
- /* initialize stat counter and timestamp */
- ip->i_dir_stats = 0;
- do_gettimeofday(&ip->i_dir_stat_st);
-
- atomic_inc(&sdp->sd_inode_count);
-
- *ipp = ip;
-
- return 0;
-
- fail_iopen:
- spin_lock(&io_gl->gl_spin);
- set_gl2gl(io_gl, NULL);
- gfs_glock_put(i_gl);
- spin_unlock(&io_gl->gl_spin);
-
- gfs_glock_dq_uninit(&ip->i_iopen_gh);
-
- fail:
- gfs_flush_meta_cache(ip);
- kmem_cache_free(gfs_inode_cachep, ip);
- *ipp = NULL;
-
- return error;
-}
-
-/**
- * gfs_inode_get - Get an inode given its number
- * @i_gl: The glock covering the inode
- * @inum: The inode number
- * @create: Flag to say if we are allowed to create a new struct gfs_inode
- * @ipp: pointer to put the returned inode in
- *
- * Returns: errno
- *
- * If creating a new gfs_inode structure, reads dinode from disk.
- */
-
-int
-gfs_inode_get(struct gfs_glock *i_gl, struct gfs_inum *inum, int create,
- struct gfs_inode **ipp)
-{
- struct gfs_glock *io_gl;
- int error = 0;
-
- *ipp = get_gl2ip(i_gl);
- if (*ipp) {
- atomic_inc(&(*ipp)->i_count);
- gfs_assert_warn(i_gl->gl_sbd,
- (*ipp)->i_num.no_formal_ino ==
- inum->no_formal_ino);
- } else if (create) {
- error = gfs_glock_get(i_gl->gl_sbd,
- inum->no_addr, &gfs_iopen_glops,
- CREATE, &io_gl);
- if (!error) {
- error = inode_create(i_gl, inum, io_gl,
- LM_ST_SHARED, ipp);
- gfs_glock_put(io_gl);
- }
- }
-
- return error;
-}
-
-/**
- * gfs_inode_hold - hold a struct gfs_inode structure
- * @ip: The GFS inode
- *
- */
-
-void
-gfs_inode_hold(struct gfs_inode *ip)
-{
- gfs_assert(ip->i_sbd, atomic_read(&ip->i_count) > 0,);
- atomic_inc(&ip->i_count);
-}
-
-/**
- * gfs_inode_put - put a struct gfs_inode structure
- * @ip: The GFS inode
- *
- */
-
-void
-gfs_inode_put(struct gfs_inode *ip)
-{
- gfs_assert(ip->i_sbd, atomic_read(&ip->i_count) > 0,);
- atomic_dec(&ip->i_count);
-}
-
-/**
- * gfs_inode_destroy - Destroy a GFS inode structure with no references on it
- * @ip: The GFS inode
- *
- * Also, unhold the iopen glock and release indirect addressing buffers.
- * This function must be called with a glocks held on the inode and
- * the associated iopen.
- *
- */
-
-void
-gfs_inode_destroy(struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_glock *io_gl = ip->i_iopen_gh.gh_gl;
- struct gfs_glock *i_gl = ip->i_gl;
-
- gfs_assert_warn(sdp, !atomic_read(&ip->i_count));
- gfs_assert(sdp, get_gl2gl(io_gl) == i_gl,);
-
- /* Unhold the iopen glock */
- spin_lock(&io_gl->gl_spin);
- set_gl2gl(io_gl, NULL);
- gfs_glock_put(i_gl);
- spin_unlock(&io_gl->gl_spin);
-
- gfs_glock_dq_uninit(&ip->i_iopen_gh);
-
- /* Release indirect addressing buffers, destroy the GFS inode struct */
- gfs_flush_meta_cache(ip);
- kmem_cache_free(gfs_inode_cachep, ip);
-
- set_gl2ip(i_gl, NULL);
- gfs_glock_put(i_gl);
-
- atomic_dec(&sdp->sd_inode_count);
-}
-
-/**
- * dinode_mark_unused - Set UNUSED flag in on-disk dinode
- * @ip:
- *
- * Also:
- * -- Increment incarnation number, to indicate that it no longer
- * represents the old inode.
- * -- Update change time (ctime)
- *
- * Returns: errno
- */
-
-static int
-dinode_mark_unused(struct gfs_inode *ip)
-{
- struct buffer_head *dibh;
- struct gfs_dinode *di;
- uint32_t incarn;
- uint64_t ctime;
- uint32_t flags;
- int error;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- return error;
-
- di = (struct gfs_dinode *)dibh->b_data;
-
- gfs_trans_add_bh(ip->i_gl, dibh);
-
- incarn = gfs32_to_cpu(di->di_header.mh_incarn) + 1;
- di->di_header.mh_incarn = cpu_to_gfs32(incarn);
-
- ctime = get_seconds();
- di->di_ctime = cpu_to_gfs64(ctime);
-
- flags = (gfs32_to_cpu(di->di_flags)) | GFS_DIF_UNUSED;
- di->di_flags = cpu_to_gfs32(flags);
-
- brelse(dibh);
-
- return 0;
-}
-
-/**
- * dinode_dealloc - Put deallocate a dinode
- * @ip: The GFS inode
- *
- * Returns: errno
- */
-
-static int
-dinode_dealloc(struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al;
- struct gfs_rgrpd *rgd;
- int error;
-
- if (ip->i_di.di_blocks != 1) {
- if (gfs_consist_inode(ip))
- gfs_dinode_print(&ip->i_di);
- return -EIO;
- }
-
- al = gfs_alloc_get(ip);
-
- error = gfs_quota_hold_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error)
- goto out;
-
- error = gfs_rindex_hold(sdp, &al->al_ri_gh);
- if (error)
- goto out_qs;
-
- rgd = gfs_blk2rgrpd(sdp, ip->i_num.no_addr);
- if (!rgd) {
- gfs_consist_inode(ip);
- error = -EIO;
- goto out_rindex_relse;
- }
-
- error = gfs_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &al->al_rgd_gh);
- if (error)
- goto out_rindex_relse;
-
- /* Trans may require:
- One block for the RG header.
- One block for the dinode bit.
- One block for the dinode.
- We also need a block for the unlinked change.
- One block for the quota change. */
-
- error = gfs_trans_begin(sdp, 3, 2);
- if (error)
- goto out_rg_gunlock;
-
- /* Set the UNUSED flag in the on-disk dinode block, increment incarn */
- error = dinode_mark_unused(ip);
- if (error)
- goto out_end_trans;
-
- /* De-allocate on-disk dinode block to FREEMETA */
- gfs_difree(rgd, ip);
-
- gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IDA, &ip->i_num);
- clear_bit(GLF_STICKY, &ip->i_gl->gl_flags);
-
- out_end_trans:
- gfs_trans_end(sdp);
-
- out_rg_gunlock:
- gfs_glock_dq_uninit(&al->al_rgd_gh);
-
- out_rindex_relse:
- gfs_glock_dq_uninit(&al->al_ri_gh);
-
- out_qs:
- gfs_quota_unhold_m(ip);
-
- out:
- gfs_alloc_put(ip);
-
- return error;
-}
-
-/**
- * inode_dealloc - Deallocate all on-disk blocks for an inode (dinode)
- * @sdp: the filesystem
- * @inum: the inode number to deallocate
- * @io_gh: a holder for the iopen glock for this inode
- *
- * De-allocates all on-disk blocks, data and metadata, associated with an inode.
- * All metadata blocks become GFS_BLKST_FREEMETA.
- * All data blocks become GFS_BLKST_FREE.
- * Also de-allocates incore gfs_inode structure.
- *
- * Returns: errno
- */
-
-static int
-inode_dealloc(struct gfs_sbd *sdp, struct gfs_inum *inum,
- struct gfs_holder *io_gh)
-{
- struct gfs_inode *ip;
- struct gfs_holder i_gh;
- int error;
-
- /* Lock the inode as we blow it away */
- error = gfs_glock_nq_num(sdp,
- inum->no_formal_ino, &gfs_inode_glops,
- LM_ST_EXCLUSIVE, 0, &i_gh);
- if (error)
- return error;
-
- /* We reacquire the iopen lock here to avoid a race with the NFS server
- calling gfs_read_inode() with the inode number of a inode we're in
- the process of deallocating. And we can't keep our hold on the lock
- from inode_dealloc_init() for deadlock reasons. We do, however,
- overlap this iopen lock with the one to be acquired EX within
- inode_create(), below (recursive EX locks will be granted to same
- holder process, i.e. this process). */
-
- gfs_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY, io_gh);
- error = gfs_glock_nq(io_gh);
- switch (error) {
- case 0:
- break;
- case GLR_TRYFAILED:
- error = 0;
- goto fail;
- default:
- goto fail;
- }
-
- gfs_assert_warn(sdp, !get_gl2ip(i_gh.gh_gl));
- error = inode_create(i_gh.gh_gl, inum, io_gh->gh_gl, LM_ST_EXCLUSIVE,
- &ip);
-
- gfs_glock_dq(io_gh);
-
- if (error)
- goto fail;
-
- /* Verify disk (d)inode, gfs inode, and VFS (v)inode are unused */
- if (ip->i_di.di_nlink) {
- if (gfs_consist_inode(ip))
- gfs_dinode_print(&ip->i_di);
- error = -EIO;
- goto fail_iput;
- }
- gfs_assert_warn(sdp, atomic_read(&ip->i_count) == 1);
- gfs_assert_warn(sdp, !ip->i_vnode);
-
- /* Free all on-disk directory leaves (if any) to FREEMETA state */
- if (ip->i_di.di_type == GFS_FILE_DIR &&
- (ip->i_di.di_flags & GFS_DIF_EXHASH)) {
- error = gfs_dir_exhash_free(ip);
- if (error)
- goto fail_iput;
- }
-
- /* Free all on-disk extended attribute blocks to FREEMETA state */
- if (ip->i_di.di_eattr) {
- error = gfs_ea_dealloc(ip);
- if (error)
- goto fail_iput;
- }
-
- /* Free all data blocks to FREE state, and meta blocks to FREEMETA */
- error = gfs_shrink(ip, 0, NULL);
- if (error)
- goto fail_iput;
-
- /* Set UNUSED flag and increment incarn # in on-disk dinode block,
- and de-alloc the block to FREEMETA */
- error = dinode_dealloc(ip);
- if (error)
- goto fail_iput;
-
- /* Free the GFS inode structure, unhold iopen and inode glocks */
- gfs_inode_put(ip);
- gfs_inode_destroy(ip);
-
- gfs_glock_dq_uninit(&i_gh);
-
- return 0;
-
- fail_iput:
- gfs_inode_put(ip);
- gfs_inode_destroy(ip);
-
- fail:
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * inode_dealloc_init - Try to deallocate an initialized on-disk inode (dinode)
- * and all of its associated data and meta blocks
- * @sdp: the filesystem
- *
- * Returns: 0 on success, -errno on error, 1 on busy (inode open)
- */
-
-static int
-inode_dealloc_init(struct gfs_sbd *sdp, struct gfs_inum *inum)
-{
- struct gfs_holder io_gh;
- int error = 0;
-
- /* If not busy (on this node), de-alloc GFS incore inode, releasing
- any indirect addressing buffers, and unholding iopen glock */
- gfs_try_toss_inode(sdp, inum);
-
- /* Does another process (cluster-wide) have this inode open? */
- error = gfs_glock_nq_num(sdp,
- inum->no_addr, &gfs_iopen_glops,
- LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &io_gh);
- switch (error) {
- case 0:
- break;
- case GLR_TRYFAILED:
- return 1;
- default:
- return error;
- }
-
- /* Unlock here to prevent deadlock */
- gfs_glock_dq(&io_gh);
-
- /* No other process in the entire cluster has this inode open;
- we can remove it and all of its associated blocks from disk */
- error = inode_dealloc(sdp, inum, &io_gh);
- gfs_holder_uninit(&io_gh);
-
- return error;
-}
-
-/**
- * inode_dealloc_uninit - dealloc an uninitialized on-disk inode (dinode) block
- * @sdp: the filesystem
- *
- * Create a transaction to change dinode block's alloc state to FREEMETA
- *
- * Returns: 0 on success, -errno on error, 1 on busy
- */
-
-static int
-inode_dealloc_uninit(struct gfs_sbd *sdp, struct gfs_inum *inum)
-{
- struct gfs_rgrpd *rgd;
- struct gfs_holder ri_gh, rgd_gh;
- int error;
-
- error = gfs_rindex_hold(sdp, &ri_gh);
- if (error)
- return error;
-
- rgd = gfs_blk2rgrpd(sdp, inum->no_addr);
- if (!rgd) {
- gfs_consist(sdp);
- error = -EIO;
- goto fail;
- }
-
- error = gfs_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rgd_gh);
- if (error)
- goto fail;
-
- /* Trans may require:
- One block for the RG header.
- One block for the dinode bit.
- We also need a block for the unlinked change. */
-
- error = gfs_trans_begin(sdp, 2, 1);
- if (error)
- goto fail_gunlock;
-
- gfs_difree_uninit(rgd, inum->no_addr);
- gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IDA, inum);
-
- gfs_trans_end(sdp);
-
- gfs_glock_dq_uninit(&rgd_gh);
- gfs_glock_dq_uninit(&ri_gh);
-
- return 0;
-
- fail_gunlock:
- gfs_glock_dq_uninit(&rgd_gh);
-
- fail:
- gfs_glock_dq_uninit(&ri_gh);
-
- return error;
-}
-
-/**
- * gfs_inode_dealloc - Grab an unlinked inode off the list and try to free it.
- * @sdp: the filesystem
- *
- * Returns: 0 on success, -errno on error, 1 on busy
- */
-
-int
-gfs_inode_dealloc(struct gfs_sbd *sdp, struct gfs_inum *inum)
-{
- if (inum->no_formal_ino)
- return inode_dealloc_init(sdp, inum);
- else
- return inode_dealloc_uninit(sdp, inum);
-}
-
-/**
- * gfs_change_nlink - Change nlink count on inode
- * @ip: The GFS inode
- * @diff: The change in the nlink count required
- *
- * Returns: errno
- */
-
-int
-gfs_change_nlink(struct gfs_inode *ip, int diff)
-{
- struct buffer_head *dibh;
- uint32_t nlink;
- int error;
-
- nlink = ip->i_di.di_nlink + diff;
-
- /* Tricky. If we are reducing the nlink count,
- but the new value ends up being bigger than the
- old one, we must have underflowed. */
- if (diff < 0 && nlink > ip->i_di.di_nlink) {
- if (gfs_consist_inode(ip))
- gfs_dinode_print(&ip->i_di);
- return -EIO;
- }
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- return error;
-
- ip->i_di.di_nlink = nlink;
- ip->i_di.di_ctime = get_seconds();
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
-
- return 0;
-}
-
-/**
- * gfs_lookupi - Look up a filename in a directory and return its inode
- * @d_gh: An initialized holder for the directory glock
- * @name: The name of the inode to look for
- * @is_root: If TRUE, ignore the caller's permissions
- * @i_gh: An uninitialized holder for the new inode glock
- *
- * There will always be a vnode (Linux VFS inode) for the d_gh inode unless
- * @is_root is true.
- *
- * Returns: errno
- */
-
-int
-gfs_lookupi(struct gfs_holder *d_gh, struct qstr *name,
- int is_root, struct gfs_holder *i_gh)
-{
- struct gfs_inode *dip = get_gl2ip(d_gh->gh_gl);
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_glock *gl;
- struct gfs_inode *ip;
- struct gfs_inum inum, inum2;
- unsigned int type;
- int error;
-
- i_gh->gh_gl = NULL;
-
- if (!name->len || name->len > GFS_FNAMESIZE)
- return -ENAMETOOLONG;
-
- if (gfs_filecmp(name, ".", 1) ||
- (gfs_filecmp(name, "..", 2) && dip == sdp->sd_rooti)) {
- gfs_holder_reinit(LM_ST_SHARED, 0, d_gh);
- error = gfs_glock_nq(d_gh);
- if (!error) {
- error = gfs_glock_nq_init(dip->i_gl,
- LM_ST_SHARED, 0,
- i_gh);
- if (error) {
- gfs_glock_dq(d_gh);
- return error;
- }
- gfs_inode_hold(dip);
- }
- return error;
- }
-
- if (gfs_assert_warn(sdp, !gfs_glock_is_locked_by_me(d_gh->gh_gl)))
- return -EINVAL;
-
- gfs_holder_reinit(LM_ST_SHARED, 0, d_gh);
- error = gfs_glock_nq(d_gh);
- if (error)
- return error;
-
- if (!is_root) {
- error = inode_permission(dip->i_vnode, MAY_EXEC);
- if (error) {
- gfs_glock_dq(d_gh);
- return error;
- }
- }
-
- error = gfs_dir_search(dip, name, &inum, &type);
- if (error) {
- gfs_glock_dq(d_gh);
- if (error == -ENOENT)
- error = 0;
- return error;
- }
-
- restart:
- error = gfs_glock_get(sdp, inum.no_formal_ino, &gfs_inode_glops,
- CREATE, &gl);
- if (error) {
- gfs_glock_dq(d_gh);
- return error;
- }
-
- /* Acquire the second lock */
-
- if (gl->gl_name.ln_number < dip->i_gl->gl_name.ln_number) {
- gfs_glock_dq(d_gh);
-
- error = gfs_glock_nq_init(gl, LM_ST_SHARED,
- LM_FLAG_ANY | GL_LOCAL_EXCL,
- i_gh);
- if (error)
- goto out;
-
- gfs_holder_reinit(LM_ST_SHARED, 0, d_gh);
- error = gfs_glock_nq(d_gh);
- if (error) {
- gfs_glock_dq_uninit(i_gh);
- goto out;
- }
-
- if (!is_root) {
- error = inode_permission(dip->i_vnode, MAY_EXEC);
- if (error) {
- gfs_glock_dq(d_gh);
- gfs_glock_dq_uninit(i_gh);
- goto out;
- }
- }
-
- error = gfs_dir_search(dip, name, &inum2, &type);
- if (error) {
- gfs_glock_dq(d_gh);
- gfs_glock_dq_uninit(i_gh);
- if (error == -ENOENT)
- error = 0;
- goto out;
- }
-
- if (!gfs_inum_equal(&inum, &inum2)) {
- gfs_glock_dq_uninit(i_gh);
- gfs_glock_put(gl);
- inum = inum2;
- goto restart;
- }
- } else {
- error = gfs_glock_nq_init(gl, LM_ST_SHARED,
- LM_FLAG_ANY | GL_LOCAL_EXCL,
- i_gh);
- if (error) {
- gfs_glock_dq(d_gh);
- goto out;
- }
- }
-
- error = gfs_inode_get(gl, &inum, CREATE, &ip);
- if (error) {
- gfs_glock_dq(d_gh);
- gfs_glock_dq_uninit(i_gh);
- } else if (ip->i_di.di_type != type) {
- gfs_consist_inode(dip);
- gfs_inode_put(ip);
- gfs_glock_dq(d_gh);
- gfs_glock_dq_uninit(i_gh);
- error = -EIO;
- }
-
- out:
- gfs_glock_put(gl);
-
- return error;
-}
-
-/**
- * create_ok - OK to create a new on-disk inode here?
- * @dip: Directory in which dinode is to be created
- * @name: Name of new dinode
- * @type: GFS_FILE_XXX (regular file, dir, etc.)
- *
- * Returns: errno
- */
-
-static int
-create_ok(struct gfs_inode *dip, struct qstr *name, unsigned int type)
-{
- int error;
-
- error = inode_permission(dip->i_vnode, MAY_WRITE | MAY_EXEC);
- if (error)
- return error;
-
- /* Don't create entries in an unlinked directory */
-
- if (!dip->i_di.di_nlink)
- return -EPERM;
-
- error = gfs_dir_search(dip, name, NULL, NULL);
- switch (error) {
- case -ENOENT:
- error = 0;
- break;
- case 0:
- return -EEXIST;
- default:
- return error;
- }
-
- if (dip->i_di.di_entries == (uint32_t)-1)
- return -EFBIG;
- if (type == GFS_FILE_DIR && dip->i_di.di_nlink == (uint32_t)-1)
- return -EMLINK;
-
- return 0;
-}
-
-/**
- * dinode_alloc - Create an on-disk inode
- * @dip: Directory in which to create the dinode
- * @ul:
- *
- * Since this dinode is not yet linked, we also create an unlinked inode
- * descriptor.
- *
- * Returns: errno
- */
-
-static int
-dinode_alloc(struct gfs_inode *dip, struct gfs_unlinked **ul)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_alloc *al;
- struct gfs_inum inum;
- int error;
-
- /* Create in-place allocation structure, reserve 1 dinode */
- al = gfs_alloc_get(dip);
- al->al_requested_di = 1;
- error = gfs_inplace_reserve(dip);
- if (error)
- goto out;
-
- error = gfs_trans_begin(sdp, al->al_rgd->rd_ri.ri_length, 1);
- if (error)
- goto out_inplace;
-
- inum.no_formal_ino = 0;
- error = gfs_dialloc(dip, &inum.no_addr);
- if (error)
- goto out_end_trans;
-
- *ul = gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IUL, &inum);
- gfs_unlinked_lock(sdp, *ul);
-
- gfs_trans_add_gl(dip->i_gl);
-
- out_end_trans:
- gfs_trans_end(sdp);
-
- out_inplace:
- gfs_inplace_release(dip);
-
- out:
- gfs_alloc_put(dip);
-
- return error;
-}
-
-/**
- * pick_formal_ino - Pick a formal inode number for a given inode
- * @sdp: the filesystem
- * @inum: the inode number structure
- *
- */
-
-static void
-pick_formal_ino(struct gfs_sbd *sdp, struct gfs_inum *inum)
-{
- /* This won't always be true */
- inum->no_formal_ino = inum->no_addr;
-}
-
-/**
- * make_dinode - Fill in a new dinode structure
- * @dip: the directory this inode is being created in
- * @gl: The glock covering the new inode
- * @inum: the inode number
- * @type: the file type
- * @mode: the file permissions
- * @uid:
- * @gid:
- *
- */
-
-static int
-make_dinode(struct gfs_inode *dip,
- struct gfs_glock *gl, struct gfs_inum *inum,
- unsigned int type, unsigned int mode,
- unsigned int uid, unsigned int gid)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_dinode di;
- struct buffer_head *dibh;
- struct gfs_rgrpd *rgd;
- int error;
-
- error = gfs_dread(gl, inum->no_addr,
- DIO_NEW | DIO_START | DIO_WAIT,
- &dibh);
- if (error)
- return error;
-
- gfs_trans_add_bh(gl, dibh);
- gfs_metatype_set(dibh, GFS_METATYPE_DI, GFS_FORMAT_DI);
- gfs_buffer_clear_tail(dibh, sizeof(struct gfs_dinode));
-
- memset(&di, 0, sizeof(struct gfs_dinode));
-
- gfs_meta_header_in(&di.di_header, dibh->b_data);
-
- di.di_num = *inum;
-
- di.di_mode = mode & S_IALLUGO;
- di.di_uid = uid;
- di.di_gid = gid;
- di.di_nlink = 1;
- di.di_blocks = 1;
- di.di_atime = di.di_mtime = di.di_ctime = get_seconds();
-
- rgd = gfs_blk2rgrpd(sdp, inum->no_addr);
- if (!rgd) {
- if (gfs_consist(sdp))
- printk("GFS: fsid=%s: block = %llu\n",
- sdp->sd_fsname,
- (unsigned long long)inum->no_addr);
- brelse(dibh);
- return -EIO;
- }
-
- di.di_rgrp = rgd->rd_ri.ri_addr;
- di.di_goal_rgrp = di.di_rgrp;
- di.di_goal_dblk = di.di_goal_mblk = inum->no_addr - rgd->rd_ri.ri_data1;
-
- if (type == GFS_FILE_REG) {
- if ((dip->i_di.di_flags & GFS_DIF_INHERIT_JDATA) ||
- gfs_tune_get(sdp, gt_new_files_jdata))
- di.di_flags |= GFS_DIF_JDATA;
- if ((dip->i_di.di_flags & GFS_DIF_INHERIT_DIRECTIO) ||
- gfs_tune_get(sdp, gt_new_files_directio))
- di.di_flags |= GFS_DIF_DIRECTIO;
- } else if (type == GFS_FILE_DIR) {
- di.di_flags |= (dip->i_di.di_flags & GFS_DIF_INHERIT_DIRECTIO);
- di.di_flags |= (dip->i_di.di_flags & GFS_DIF_INHERIT_JDATA);
- }
-
- di.di_type = type;
-
- gfs_dinode_out(&di, dibh->b_data);
- brelse(dibh);
-
- return 0;
-}
-
-/**
- * inode_init_and_link -
- * @dip:
- * @name:
- * @inum:
- * @gl:
- * @type:
- * @mode:
- *
- * Returns: errno
- */
-
-static int
-inode_init_and_link(struct gfs_inode *dip, struct qstr *name,
- struct gfs_inum *inum, struct gfs_glock *gl,
- unsigned int type, mode_t mode)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_alloc *al;
- struct gfs_inode *ip;
- unsigned int uid, gid;
- int alloc_required;
- void *acl_a_data = NULL, *acl_d_data = NULL;
- unsigned int acl_size = 0, acl_blocks = 0;
- int error;
-
- if (sdp->sd_args.ar_suiddir &&
- (dip->i_di.di_mode & S_ISUID) &&
- dip->i_di.di_uid) {
- if (type == GFS_FILE_DIR)
- mode |= S_ISUID;
- else if (dip->i_di.di_uid != current_fsuid())
- mode &= ~07111;
- uid = dip->i_di.di_uid;
- } else
- uid = current_fsuid();
- if (dip->i_di.di_mode & S_ISGID) {
- if (type == GFS_FILE_DIR)
- mode |= S_ISGID;
- gid = dip->i_di.di_gid;
- } else
- gid = current_fsgid();
-
- error = gfs_acl_new_prep(dip, type, &mode,
- &acl_a_data, &acl_d_data,
- &acl_size, &acl_blocks);
- if (error)
- return error;
-
- al = gfs_alloc_get(dip);
-
- error = gfs_quota_lock_m(dip, uid, gid);
- if (error)
- goto fail;
-
- error = gfs_quota_check(dip, uid, gid);
- if (error)
- goto fail_gunlock_q;
-
- if (acl_blocks)
- alloc_required = TRUE;
- else {
- error = gfs_diradd_alloc_required(dip, name, &alloc_required);
- if (error)
- goto fail_gunlock_q;
- }
-
- if (alloc_required) {
- error = gfs_quota_check(dip, dip->i_di.di_uid, dip->i_di.di_gid);
- if (error)
- goto fail_gunlock_q;
-
- al->al_requested_meta = sdp->sd_max_dirres + acl_blocks;
-
- error = gfs_inplace_reserve(dip);
- if (error)
- goto fail_gunlock_q;
-
- /* Trans may require:
- blocks for two dinodes, the directory blocks necessary for
- a new entry, RG bitmap blocks for an allocation,
- and one block for a quota change and
- one block for an unlinked tag. */
-
- error = gfs_trans_begin(sdp,
- 2 + sdp->sd_max_dirres + acl_blocks +
- al->al_rgd->rd_ri.ri_length, 2);
- if (error)
- goto fail_inplace;
- } else {
- error = gfs_rindex_hold(sdp, &al->al_ri_gh);
- if (error)
- goto fail_gunlock_q;
-
- /* Trans may require:
- blocks for two dinodes, a leaf block,
- and one block for a quota change and
- one block for an unlinked tag. */
-
- error = gfs_trans_begin(sdp, 3, 2);
- if (error)
- goto fail_inplace;
- }
-
- error = gfs_dir_add(dip, name, inum, type);
- if (error)
- goto fail_end_trans;
-
- error = make_dinode(dip, gl, inum, type, mode, uid, gid);
- if (error)
- goto fail_end_trans;
-
- al->al_ul = gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IDA,
- &(struct gfs_inum){0, inum->no_addr});
- gfs_trans_add_quota(sdp, +1, uid, gid);
-
- error = gfs_inode_get(gl, inum, CREATE, &ip);
-
- /* This should only fail if we are already shutdown. */
- if (gfs_assert_withdraw(sdp, !error))
- goto fail_end_trans;
-
- if (acl_blocks)
- error = gfs_acl_new_init(dip, ip,
- acl_a_data, acl_d_data,
- acl_size);
-
- if (!alloc_required)
- gfs_glock_dq_uninit(&al->al_ri_gh);
-
- return error;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail_inplace:
- if (alloc_required)
- gfs_inplace_release(dip);
- else
- gfs_glock_dq_uninit(&al->al_ri_gh);
-
- fail_gunlock_q:
- gfs_quota_unlock_m(dip);
-
- fail:
- gfs_alloc_put(dip);
- if (acl_a_data)
- kfree(acl_a_data);
- else if (acl_d_data)
- kfree(acl_d_data);
-
- return error;
-}
-
-/**
- * gfs_createi - Create a new inode
- * @d_gh: An initialized holder for the directory glock
- * @name: The name of the new file
- * @type: The type of dinode (GFS_FILE_REG, GFS_FILE_DIR, GFS_FILE_LNK, ...)
- * @mode: the permissions on the new inode
- * @i_gh: An uninitialized holder for the new inode glock
- *
- * If the return value is 0, the glocks on both the directory and the new
- * file are held. A transaction has been started and an inplace reservation
- * is held, as well.
- *
- * Returns: errno
- */
-
-int
-gfs_createi(struct gfs_holder *d_gh, struct qstr *name,
- unsigned int type, unsigned int mode,
- struct gfs_holder *i_gh)
-{
- struct gfs_inode *dip = get_gl2ip(d_gh->gh_gl);
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_unlinked *ul;
- struct gfs_inum inum;
- struct gfs_holder io_gh;
- int error;
-
- if (!name->len || name->len > GFS_FNAMESIZE)
- return -ENAMETOOLONG;
-
- gfs_holder_reinit(LM_ST_EXCLUSIVE, 0, d_gh);
- error = gfs_glock_nq(d_gh);
- if (error)
- return error;
-
- error = create_ok(dip, name, type);
- if (error)
- goto fail;
-
- error = dinode_alloc(dip, &ul);
- if (error)
- goto fail;
-
- inum.no_addr = ul->ul_inum.no_addr;
- pick_formal_ino(sdp, &inum);
-
- if (inum.no_formal_ino < dip->i_num.no_formal_ino) {
- gfs_glock_dq(d_gh);
-
- error = gfs_glock_nq_num(sdp,
- inum.no_formal_ino, &gfs_inode_glops,
- LM_ST_EXCLUSIVE, GL_SKIP, i_gh);
- if (error) {
- gfs_unlinked_unlock(sdp, ul);
- return error;
- }
-
- gfs_holder_reinit(LM_ST_EXCLUSIVE, 0, d_gh);
- error = gfs_glock_nq(d_gh);
- if (error) {
- gfs_glock_dq_uninit(i_gh);
- gfs_unlinked_unlock(sdp, ul);
- return error;
- }
-
- error = create_ok(dip, name, type);
- if (error)
- goto fail_gunlock_i;
- } else {
- error = gfs_glock_nq_num(sdp,
- inum.no_formal_ino, &gfs_inode_glops,
- LM_ST_EXCLUSIVE, GL_SKIP, i_gh);
- if (error)
- goto fail_ul;
- }
-
- error = gfs_glock_nq_num(sdp,
- inum.no_addr, &gfs_iopen_glops,
- LM_ST_SHARED, GL_LOCAL_EXCL | GL_EXACT,
- &io_gh);
- if (error)
- goto fail_gunlock_i;
-
- error = inode_init_and_link(dip, name, &inum, i_gh->gh_gl, type, mode);
- if (error)
- goto fail_gunlock_io;
-
- gfs_glock_dq_uninit(&io_gh);
-
- return 0;
-
- fail_gunlock_io:
- gfs_glock_dq_uninit(&io_gh);
-
- fail_gunlock_i:
- gfs_glock_dq_uninit(i_gh);
-
- fail_ul:
- gfs_unlinked_unlock(sdp, ul);
-
- fail:
- gfs_glock_dq(d_gh);
-
- return error;
-}
-
-/**
- * gfs_unlinki - Unlink a file
- * @dip: The inode of the directory
- * @name: The name of the file to be unlinked
- * @ip: The inode of the file to be removed
- *
- * Assumes Glocks on both dip and ip are held.
- *
- * Returns: errno
- */
-
-int
-gfs_unlinki(struct gfs_inode *dip, struct qstr *name, struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- int error;
-
- error = gfs_dir_del(dip, name);
- if (error)
- return error;
-
- error = gfs_change_nlink(ip, -1);
- if (error)
- return error;
-
- /* If this inode is being unlinked from the directory structure,
- we need to mark that in the log so that it isn't lost during
- a crash. */
-
- if (!ip->i_di.di_nlink) {
- gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IUL, &ip->i_num);
- set_bit(GLF_STICKY, &ip->i_gl->gl_flags);
- }
-
- return 0;
-}
-
-/**
- * gfs_rmdiri - Remove a directory
- * @dip: The parent directory of the directory to be removed
- * @name: The name of the directory to be removed
- * @ip: The GFS inode of the directory to be removed
- *
- * Assumes Glocks on dip and ip are held
- *
- * Returns: errno
- */
-
-int
-gfs_rmdiri(struct gfs_inode *dip, struct qstr *name, struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct qstr dotname;
- int error;
-
- if (ip->i_di.di_entries != 2) {
- if (gfs_consist_inode(ip))
- gfs_dinode_print(&ip->i_di);
- return -EIO;
- }
-
- error = gfs_dir_del(dip, name);
- if (error)
- return error;
-
- error = gfs_change_nlink(dip, -1);
- if (error)
- return error;
-
- dotname.len = 1;
- dotname.name = ".";
- error = gfs_dir_del(ip, &dotname);
- if (error)
- return error;
-
- dotname.len = 2;
- dotname.name = "..";
- error = gfs_dir_del(ip, &dotname);
- if (error)
- return error;
-
- error = gfs_change_nlink(ip, -2);
- if (error)
- return error;
-
- /* This inode is being unlinked from the directory structure and
- we need to mark that in the log so that it isn't lost during
- a crash. */
-
- gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IUL, &ip->i_num);
- set_bit(GLF_STICKY, &ip->i_gl->gl_flags);
-
- return 0;
-}
-
-/*
- * gfs_unlink_ok - check to see that a inode is still in a directory
- * @dip: the directory
- * @name: the name of the file
- * @ip: the inode
- *
- * Assumes that the lock on (at least) @dip is held.
- *
- * Returns: 0 if the parent/child relationship is correct, errno if it isn't
- */
-
-int
-gfs_unlink_ok(struct gfs_inode *dip, struct qstr *name, struct gfs_inode *ip)
-{
- struct gfs_inum inum;
- unsigned int type;
- int error;
-
- if (IS_IMMUTABLE(ip->i_vnode) || IS_APPEND(ip->i_vnode))
- return -EPERM;
-
- if ((dip->i_di.di_mode & S_ISVTX) &&
- dip->i_di.di_uid != current_fsuid() &&
- ip->i_di.di_uid != current_fsuid() &&
- !capable(CAP_FOWNER))
- return -EPERM;
-
- if (IS_APPEND(dip->i_vnode))
- return -EPERM;
-
- error = inode_permission(dip->i_vnode, MAY_WRITE | MAY_EXEC);
- if (error)
- return error;
-
- error = gfs_dir_search(dip, name, &inum, &type);
- if (error)
- return error;
-
- if (inum.no_formal_ino != ip->i_num.no_formal_ino)
- return -ENOENT;
-
- if (ip->i_di.di_type != type) {
- gfs_consist_inode(dip);
- return -EIO;
- }
-
- return 0;
-}
-
-/*
- * gfs_ok_to_move - check if it's ok to move a directory to another directory
- * @this: move this
- * @to: to here
- *
- * Follow @to back to the root and make sure we don't encounter @this
- * Assumes we already hold the rename lock.
- *
- * Returns: errno
- */
-
-int
-gfs_ok_to_move(struct gfs_inode *this, struct gfs_inode *to)
-{
- struct gfs_sbd *sdp = this->i_sbd;
- struct gfs_inode *tmp;
- struct gfs_holder to_gh, tmp_gh;
- struct qstr dotdot;
- int error = 0;
-
- memset(&dotdot, 0, sizeof (struct qstr));
- dotdot.name = "..";
- dotdot.len = 2;
-
- gfs_inode_hold(to);
-
- for (;;) {
- if (to == this) {
- error = -EINVAL;
- break;
- }
- if (to == sdp->sd_rooti) {
- error = 0;
- break;
- }
-
- gfs_holder_init(to->i_gl, 0, 0, &to_gh);
-
- error = gfs_lookupi(&to_gh, &dotdot, TRUE, &tmp_gh);
- if (error) {
- gfs_holder_uninit(&to_gh);
- break;
- }
- if (!tmp_gh.gh_gl) {
- gfs_holder_uninit(&to_gh);
- error = -ENOENT;
- break;
- }
-
- tmp = get_gl2ip(tmp_gh.gh_gl);
-
- gfs_glock_dq_uninit(&to_gh);
- gfs_glock_dq_uninit(&tmp_gh);
-
- gfs_inode_put(to);
- to = tmp;
- }
-
- gfs_inode_put(to);
-
- return error;
-}
-
-/**
- * gfs_readlinki - return the contents of a symlink
- * @ip: the symlink's inode
- * @buf: a pointer to the buffer to be filled
- * @len: a pointer to the length of @buf
- *
- * If @buf is too small, a piece of memory is kmalloc()ed and needs
- * to be freed by the caller.
- *
- * Returns: errno
- */
-
-int
-gfs_readlinki(struct gfs_inode *ip, char **buf, unsigned int *len)
-{
- struct gfs_holder i_gh;
- struct buffer_head *dibh;
- unsigned int x;
- int error;
-
- gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh);
- error = gfs_glock_nq_atime(&i_gh);
- if (error) {
- gfs_holder_uninit(&i_gh);
- return error;
- }
-
- if (!ip->i_di.di_size) {
- gfs_consist_inode(ip);
- error = -EIO;
- goto out;
- }
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto out;
-
- x = ip->i_di.di_size + 1;
- if (x > *len) {
- *buf = kmalloc(x, GFP_KERNEL);
- if (!*buf) {
- error = -ENOMEM;
- goto out_brelse;
- }
- }
-
- memcpy(*buf, dibh->b_data + sizeof(struct gfs_dinode), x);
- *len = x;
-
- out_brelse:
- brelse(dibh);
-
- out:
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gfs_glock_nq_atime - Acquire a hold on an inode's glock, and
- * conditionally update the inode's atime
- * @gh: the holder to acquire
- *
- * Tests atime (access time) for gfs_read, gfs_readdir and gfs_mmap
- * Update if the difference between the current time and the inode's current
- * atime is greater than an interval specified at mount (or default).
- *
- * Will not update if GFS mounted NOATIME (this is *the* place where NOATIME
- * has an effect) or Read-Only.
- *
- * Returns: errno
- */
-
-int
-gfs_glock_nq_atime(struct gfs_holder *gh)
-{
- struct gfs_glock *gl = gh->gh_gl;
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_inode *ip = get_gl2ip(gl);
- int64_t curtime, quantum = gfs_tune_get(sdp, gt_atime_quantum);
- unsigned int state;
- int flags;
- int error;
-
- if (gfs_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||
- gfs_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||
- gfs_assert_warn(sdp, gl->gl_ops == &gfs_inode_glops))
- return -EINVAL;
-
- /* Save original request state of lock holder */
- state = gh->gh_state;
- flags = gh->gh_flags;
-
- error = gfs_glock_nq(gh);
- if (error)
- return error;
-
- if (test_bit(SDF_NOATIME, &sdp->sd_flags) ||
- test_bit(SDF_ROFS, &sdp->sd_flags))
- return 0;
-
- curtime = get_seconds();
- if (curtime - ip->i_di.di_atime >= quantum) {
- /* Get EX hold (force EX glock via !ANY) to write the dinode */
- gfs_glock_dq(gh);
- gfs_holder_reinit(LM_ST_EXCLUSIVE,
- gh->gh_flags & ~LM_FLAG_ANY,
- gh);
- error = gfs_glock_nq(gh);
- if (error)
- return error;
-
- /* Verify that atime hasn't been updated while we were
- trying to get exclusive lock. */
-
- curtime = get_seconds();
- if (curtime - ip->i_di.di_atime >= quantum) {
- struct buffer_head *dibh;
-
- error = gfs_trans_begin(sdp, 1, 0);
- if (error == -EROFS)
- return 0;
- if (error)
- goto fail;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto fail_end_trans;
-
- ip->i_di.di_atime = curtime;
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
-
- gfs_trans_end(sdp);
- }
-
- /* If someone else has asked for the glock,
- unlock and let them have it. Then reacquire
- in the original state. */
- if (gfs_glock_is_blocking(gl)) {
- gfs_glock_dq(gh);
- gfs_holder_reinit(state, flags, gh);
- return gfs_glock_nq(gh);
- }
- }
-
- return 0;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail:
- gfs_glock_dq(gh);
-
- return error;
-}
-
-/**
- * glock_compare_atime - Compare two struct gfs_glock structures for gfs_sort()
- * @arg_a: the first structure
- * @arg_b: the second structure
- *
- * Sort order determined by (in order of priority):
- * -- lock number
- * -- lock state (SHARED > EXCLUSIVE or GL_ATIME, which can demand EXCLUSIVE)
- *
- * Returns: 1 if A > B
- * -1 if A < B
- * 0 if A = B
- */
-
-static int
-glock_compare_atime(const void *arg_a, const void *arg_b)
-{
- struct gfs_holder *gh_a = *(struct gfs_holder **)arg_a;
- struct gfs_holder *gh_b = *(struct gfs_holder **)arg_b;
- struct lm_lockname *a = &gh_a->gh_gl->gl_name;
- struct lm_lockname *b = &gh_b->gh_gl->gl_name;
- int ret = 0;
-
- if (a->ln_number > b->ln_number)
- ret = 1;
- else if (a->ln_number < b->ln_number)
- ret = -1;
- else {
- if (gh_a->gh_state == LM_ST_SHARED &&
- gh_b->gh_state == LM_ST_EXCLUSIVE)
- ret = 1;
- else if (gh_a->gh_state == LM_ST_SHARED &&
- (gh_b->gh_flags & GL_ATIME))
- ret = 1;
- }
-
- return ret;
-}
-
-/**
- * gfs_glock_nq_m_atime - acquire multiple glocks where one may need an
- * atime update
- * @num_gh: the number of structures
- * @ghs: an array of struct gfs_holder structures
- *
- * Returns: 0 on success (all glocks acquired),
- * errno on failure (no glocks acquired)
- */
-
-int
-gfs_glock_nq_m_atime(unsigned int num_gh, struct gfs_holder *ghs)
-{
- struct gfs_holder **p;
- unsigned int x;
- int error = 0;
-
- if (!num_gh)
- return 0;
-
- if (num_gh == 1) {
- ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
- if (ghs->gh_flags & GL_ATIME)
- error = gfs_glock_nq_atime(ghs);
- else
- error = gfs_glock_nq(ghs);
- return error;
- }
-
- p = kmalloc(num_gh * sizeof(struct gfs_holder *), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
-
- for (x = 0; x < num_gh; x++)
- p[x] = &ghs[x];
-
- gfs_sort(p, num_gh, sizeof(struct gfs_holder *), glock_compare_atime);
-
- for (x = 0; x < num_gh; x++) {
- p[x]->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
-
- if (p[x]->gh_flags & GL_ATIME)
- error = gfs_glock_nq_atime(p[x]);
- else
- error = gfs_glock_nq(p[x]);
-
- if (error) {
- while (x--)
- gfs_glock_dq(p[x]);
- break;
- }
- }
-
- kfree(p);
- return error;
-}
-
-/**
- * gfs_try_toss_vnode - See if we can toss a vnode from memory
- * @ip: the inode
- *
- * Returns: TRUE if the vnode was tossed
- */
-
-void
-gfs_try_toss_vnode(struct gfs_inode *ip)
-{
- struct inode *inode;
-
- inode = gfs_iget(ip, NO_CREATE);
- if (!inode)
- return;
-
- d_prune_aliases(inode);
-
- if (ip->i_di.di_type == GFS_FILE_DIR) {
- struct list_head *head = &inode->i_dentry;
- struct dentry *d = NULL;
-
- spin_lock(&dcache_lock);
- if (list_empty(head))
- spin_unlock(&dcache_lock);
- else {
- d = list_entry(head->next, struct dentry, d_alias);
- dget_locked(d);
- spin_unlock(&dcache_lock);
-
- if (have_submounts(d))
- dput(d);
- else {
- shrink_dcache_parent(d);
- dput(d);
- d_prune_aliases(inode);
- }
- }
- }
-
- inode->i_nlink = 0;
- iput(inode);
-}
-
-
-static int
-__gfs_setattr_simple(struct gfs_inode *ip, struct iattr *attr)
-{
- struct buffer_head *dibh;
- int error;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (!error) {
- error = inode_setattr(ip->i_vnode, attr);
- gfs_assert_warn(ip->i_sbd, !error);
- gfs_inode_attr_out(ip);
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- return error;
-}
-
-/**
- * gfs_setattr_simple -
- * @ip:
- * @attr:
- *
- * Called with a reference on the vnode.
- *
- * Returns: errno
- */
-
-int
-gfs_setattr_simple(struct gfs_inode *ip, struct iattr *attr)
-{
- int error;
-
- if (get_transaction)
- return __gfs_setattr_simple(ip, attr);
-
- /* Trans may require:
- one dinode block. */
-
- error = gfs_trans_begin(ip->i_sbd, 1, 0);
- if (error)
- return error;
-
- error = __gfs_setattr_simple(ip, attr);
-
- gfs_trans_end(ip->i_sbd);
-
- return error;
-}
-
-/**
- * iah_make_jdata -
- * @gl:
- * @inum:
- *
- */
-
-static void
-iah_make_jdata(struct gfs_glock *gl, struct gfs_inum *inum)
-{
- struct buffer_head *bh;
- struct gfs_dinode *di;
- uint32_t flags;
- int error;
-
- error = gfs_dread(gl, inum->no_addr, DIO_START | DIO_WAIT, &bh);
-
- /* This should only fail if we are already shutdown. */
- if (gfs_assert_withdraw(gl->gl_sbd, !error))
- return;
-
- di = (struct gfs_dinode *)bh->b_data;
-
- flags = di->di_flags;
- flags = gfs32_to_cpu(flags) | GFS_DIF_JDATA;
- di->di_flags = cpu_to_gfs32(flags);
-
- brelse(bh);
-}
-
-/**
- * iah_super_update - Write superblock to disk
- * @sdp: filesystem instance structure
- *
- * Returns: errno
- *
- * Update on-disk superblock, using (modified) data in sdp->sd_sb
- */
-
-static int
-iah_super_update(struct gfs_sbd *sdp)
-{
- struct gfs_glock *gl;
- struct buffer_head *bh;
- int error;
-
- error = gfs_glock_get(sdp,
- GFS_SB_LOCK, &gfs_meta_glops,
- NO_CREATE, &gl);
- if (gfs_assert_withdraw(sdp, !error && gl)) /* This should already be held. */
- return -EINVAL;
-
- error = gfs_dread(gl, GFS_SB_ADDR >> sdp->sd_fsb2bb_shift,
- DIO_START | DIO_WAIT, &bh);
- if (!error) {
- gfs_trans_add_bh(gl, bh);
- gfs_sb_out(&sdp->sd_sb, bh->b_data);
- brelse(bh);
- }
-
- gfs_glock_put(gl);
-
- return error;
-}
-
-/**
- * inode_alloc_hidden - allocate on-disk inode for a special (hidden) file
- * @sdp: the filesystem instance structure
- * @inum: new dinode's block # and formal inode #, to be filled
- * in by this function.
- *
- * Returns: errno
- *
- * This function is called only very rarely, when the first-to-mount
- * node can't find a pre-existing special file (e.g. license or quota file) that
- * it expects to find. This should happen only when upgrading from an older
- * version of the filesystem.
- *
- * The @inum must be a member of sdp->sd_sb in order to get updated to on-disk
- * superblock properly.
- */
-
-static int
-inode_alloc_hidden(struct gfs_sbd *sdp, struct gfs_inum *inum)
-{
- struct gfs_inode *dip = sdp->sd_rooti;
- struct gfs_holder d_gh, i_gh;
- struct gfs_unlinked *ul;
- int error;
-
- error = gfs_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &d_gh);
- if (error)
- return error;
-
- error = dinode_alloc(dip, &ul);
- if (error)
- goto fail;
-
- inum->no_addr = ul->ul_inum.no_addr;
- pick_formal_ino(sdp, inum);
-
- /* Don't worry about deadlock ordering here. We're the first
- mounter and still under the mount lock (i.e. there is no
- contention). */
-
- error = gfs_glock_nq_num(sdp,
- inum->no_formal_ino, &gfs_inode_glops,
- LM_ST_EXCLUSIVE, GL_SKIP, &i_gh);
- if (error)
- goto fail_ul;
-
- gfs_alloc_get(dip);
-
- error = gfs_quota_hold_m(dip, 0, 0);
- if (error)
- goto fail_al;
-
- /* Trans may require:
- The new inode, the superblock,
- and one block for a quota change and
- one block for an unlinked tag. */
-
- error = gfs_trans_begin(sdp, 2, 2);
- if (error)
- goto fail_unhold;
-
- error = make_dinode(dip, i_gh.gh_gl, inum, GFS_FILE_REG, 0600, 0, 0);
- if (error)
- goto fail_end_trans;
-
- /* Hidden files get all of their data (not just metadata) journaled */
- iah_make_jdata(i_gh.gh_gl, inum);
-
- error = iah_super_update(sdp);
- if (error)
- goto fail_end_trans;
-
- gfs_trans_add_unlinked(sdp, GFS_LOG_DESC_IDA,
- &(struct gfs_inum){0, inum->no_addr});
- gfs_trans_add_quota(sdp, +1, 0, 0);
- gfs_trans_add_gl(dip->i_gl);
-
- gfs_trans_end(sdp);
- gfs_quota_unhold_m(dip);
- gfs_alloc_put(dip);
-
- gfs_glock_dq_uninit(&i_gh);
- gfs_glock_dq_uninit(&d_gh);
-
- gfs_unlinked_unlock(sdp, ul);
-
- gfs_log_flush(sdp);
-
- return 0;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail_unhold:
- gfs_quota_unhold_m(dip);
-
- fail_al:
- gfs_alloc_put(dip);
- gfs_glock_dq_uninit(&i_gh);
-
- fail_ul:
- gfs_unlinked_unlock(sdp, ul);
-
- fail:
- gfs_glock_dq_uninit(&d_gh);
-
- return error;
-}
-
-/**
- * gfs_alloc_qinode - allocate a quota inode
- * @sdp: The GFS superblock
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int
-gfs_alloc_qinode(struct gfs_sbd *sdp)
-{
- return inode_alloc_hidden(sdp, &sdp->sd_sb.sb_quota_di);
-}
-
-/**
- * gfs_alloc_linode - allocate a license inode
- * @sdp: The GFS superblock
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int
-gfs_alloc_linode(struct gfs_sbd *sdp)
-{
- return inode_alloc_hidden(sdp, &sdp->sd_sb.sb_license_di);
-}
diff --git a/gfs-kernel/src/gfs/inode.h b/gfs-kernel/src/gfs/inode.h
deleted file mode 100644
index 01f80b7..0000000
--- a/gfs-kernel/src/gfs/inode.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef __INODE_DOT_H__
-#define __INODE_DOT_H__
-
-void gfs_inode_attr_in(struct gfs_inode *ip);
-void gfs_inode_attr_out(struct gfs_inode *ip);
-struct inode *gfs_iget(struct gfs_inode *ip, int create);
-
-int gfs_copyin_dinode(struct gfs_inode *ip);
-
-int gfs_inode_get(struct gfs_glock *i_gl, struct gfs_inum *inum, int create,
- struct gfs_inode **ipp);
-void gfs_inode_hold(struct gfs_inode *ip);
-void gfs_inode_put(struct gfs_inode *ip);
-void gfs_inode_destroy(struct gfs_inode *ip);
-
-int gfs_inode_dealloc(struct gfs_sbd *sdp, struct gfs_inum *inum);
-
-int gfs_change_nlink(struct gfs_inode *ip, int diff);
-int gfs_lookupi(struct gfs_holder *d_gh, struct qstr *name,
- int is_root, struct gfs_holder *i_gh);
-int gfs_createi(struct gfs_holder *d_gh, struct qstr *name,
- unsigned int type, unsigned int mode,
- struct gfs_holder *i_gh);
-int gfs_unlinki(struct gfs_inode *dip, struct qstr *name, struct gfs_inode *ip);
-int gfs_rmdiri(struct gfs_inode *dip, struct qstr *name, struct gfs_inode *ip);
-int gfs_unlink_ok(struct gfs_inode *dip, struct qstr *name,
- struct gfs_inode *ip);
-int gfs_ok_to_move(struct gfs_inode *this, struct gfs_inode *to);
-int gfs_readlinki(struct gfs_inode *ip, char **buf, unsigned int *len);
-
-int gfs_glock_nq_atime(struct gfs_holder *gh);
-int gfs_glock_nq_m_atime(unsigned int num_gh, struct gfs_holder *ghs);
-
-void gfs_try_toss_vnode(struct gfs_inode *ip);
-
-int gfs_setattr_simple(struct gfs_inode *ip, struct iattr *attr);
-
-/* Backwards compatibility functions */
-
-int gfs_alloc_qinode(struct gfs_sbd *sdp);
-int gfs_alloc_linode(struct gfs_sbd *sdp);
-
-/* Inlines */
-
-static __inline__ int
-gfs_is_stuffed(struct gfs_inode *ip)
-{
- return !ip->i_di.di_height;
-}
-
-static __inline__ int
-gfs_is_jdata(struct gfs_inode *ip)
-{
- return ip->i_di.di_flags & GFS_DIF_JDATA;
-}
-
-#endif /* __INODE_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/ioctl.c b/gfs-kernel/src/gfs/ioctl.c
deleted file mode 100644
index afc08f0..0000000
--- a/gfs-kernel/src/gfs/ioctl.c
+++ /dev/null
@@ -1,1607 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <asm/uaccess.h>
-#include <linux/compat.h>
-#include <linux/cred.h>
-#include <linux/vmalloc.h>
-
-#include "gfs_ioctl.h"
-#include "gfs.h"
-#include "bmap.h"
-#include "dio.h"
-#include "dir.h"
-#include "eattr.h"
-#include "file.h"
-#include "glock.h"
-#include "glops.h"
-#include "inode.h"
-#include "ioctl.h"
-#include "log.h"
-#include "quota.h"
-#include "rgrp.h"
-#include "super.h"
-#include "trans.h"
-
-typedef int (*gi_filler_t) (struct gfs_inode *ip,
- struct gfs_ioctl *gi,
- char *buf,
- unsigned int size,
- unsigned int *count);
-
-#define ARG_SIZE (32)
-
-/**
- * gi_skeleton - Setup a buffer that functions can print into
- * @ip:
- * @gi:
- * @filler:
- *
- * Returns: -errno or count of bytes copied to userspace
- */
-
-static int
-gi_skeleton(struct gfs_inode *ip, struct gfs_ioctl *gi,
- gi_filler_t filler)
-{
- unsigned int size = gfs_tune_get(ip->i_sbd, gt_lockdump_size);
- char *buf;
- unsigned int count = 0;
- int error;
-
- if (size > gi->gi_size)
- size = gi->gi_size;
-
- buf = vmalloc(size);
- if (!buf)
- return -ENOMEM;
-
- error = filler(ip, gi, buf, size, &count);
- if (error)
- goto out;
-
- if (copy_to_user(gi->gi_data, buf, count + 1))
- error = -EFAULT;
- else
- error = count + 1;
-
- out:
- vfree(buf);
-
- return error;
-}
-
-/**
- * gi_get_cookie - Return the "cookie" (identifying string) for a
- * filesystem mount
- * @ip:
- * @gi:
- * @buf:
- * @size:
- * @count:
- *
- * Returns: errno
- */
-
-static int
-gi_get_cookie(struct gfs_inode *ip,
- struct gfs_ioctl *gi,
- char *buf,
- unsigned int size,
- unsigned int *count)
-{
- int error = -ENOBUFS;
-
- if (gi->gi_argc != 1)
- return -EINVAL;
-
- gfs_printf("version 0\n");
- gfs_printf("%lu", (unsigned long)ip->i_sbd);
-
- error = 0;
-
- out:
- return error;
-}
-
-/**
- * gi_get_super - Return the "struct gfs_sb" for a filesystem
- * @sdp:
- * @gi:
- *
- * Returns: errno
- */
-
-static int
-gi_get_super(struct gfs_sbd *sdp, struct gfs_ioctl *gi)
-{
- struct gfs_holder sb_gh;
- struct buffer_head *bh;
- struct gfs_sb *sb;
- int error;
-
- if (gi->gi_argc != 1)
- return -EINVAL;
- if (gi->gi_size != sizeof(struct gfs_sb))
- return -EINVAL;
-
- sb = kmalloc(sizeof(struct gfs_sb), GFP_KERNEL);
- if (!sb)
- return -ENOMEM;
-
- error = gfs_glock_nq_num(sdp,
- GFS_SB_LOCK, &gfs_meta_glops,
- LM_ST_SHARED, 0, &sb_gh);
- if (error)
- goto out;
-
- error = gfs_dread(sb_gh.gh_gl, GFS_SB_ADDR >> sdp->sd_fsb2bb_shift,
- DIO_START | DIO_WAIT, &bh);
- if (error) {
- gfs_glock_dq_uninit(&sb_gh);
- goto out;
- }
- gfs_sb_in(sb, bh->b_data);
- brelse(bh);
-
- gfs_glock_dq_uninit(&sb_gh);
-
- if (copy_to_user(gi->gi_data, sb,
- sizeof(struct gfs_sb)))
- error = -EFAULT;
- else
- error = sizeof(struct gfs_sb);
-
- out:
- kfree(sb);
-
- return error;
-}
-
-/**
- * gi_get_args - Return the mount arguments
- * @ip:
- * @gi:
- * @buf:
- * @size:
- * @count:
- *
- * Returns: errno
- */
-
-static int
-gi_get_args(struct gfs_inode *ip,
- struct gfs_ioctl *gi,
- char *buf,
- unsigned int size,
- unsigned int *count)
-{
- struct gfs_args *args = &ip->i_sbd->sd_args;
- int error = -ENOBUFS;
-
- if (gi->gi_argc != 1)
- return -EINVAL;
-
- gfs_printf("version 0\n");
- gfs_printf("lockproto %s\n", args->ar_lockproto);
- gfs_printf("locktable %s\n", args->ar_locktable);
- gfs_printf("hostdata %s\n", args->ar_hostdata);
- gfs_printf("ignore_local_fs %d\n", args->ar_ignore_local_fs);
- gfs_printf("localcaching %d\n", args->ar_localcaching);
- gfs_printf("localflocks %d\n", args->ar_localflocks);
- gfs_printf("oopses_ok %d\n", args->ar_oopses_ok);
- gfs_printf("upgrade %d\n", args->ar_upgrade);
- gfs_printf("num_glockd %u\n", args->ar_num_glockd);
- gfs_printf("posix_acls %d\n", args->ar_posix_acls);
- gfs_printf("suiddir %d\n", args->ar_suiddir);
-
- error = 0;
-
- out:
- return error;
-}
-
-/**
- * gi_get_lockstruct - Return the information in the FS' lockstruct
- * @ip:
- * @gi:
- * @buf:
- * @size:
- * @count:
- *
- * Returns: errno
- */
-
-static int
-gi_get_lockstruct(struct gfs_inode *ip,
- struct gfs_ioctl *gi,
- char *buf,
- unsigned int size,
- unsigned int *count)
-{
- struct lm_lockstruct *ls = &ip->i_sbd->sd_lockstruct;
- int error = -ENOBUFS;
-
- if (gi->gi_argc != 1)
- return -EINVAL;
-
- gfs_printf("version 0\n");
- gfs_printf("jid %u\n", ls->ls_jid);
- gfs_printf("first %u\n", ls->ls_first);
- gfs_printf("lvb_size %u\n", ls->ls_lvb_size);
- gfs_printf("flags %d\n", ls->ls_flags);
-
- error = 0;
-
- out:
- return error;
-}
-
-/**
- * gi_get_stat_gfs - Return a filesystem's space usage information
- * @ip:
- * @gi:
- * @buf:
- * @size:
- * @count:
- *
- * Returns: errno
- */
-
-static int
-gi_get_stat_gfs(struct gfs_inode *ip,
- struct gfs_ioctl *gi,
- char *buf,
- unsigned int size,
- unsigned int *count)
-{
- struct gfs_stat_gfs sg;
- int error;
-
- if (gi->gi_argc != 1)
- return -EINVAL;
-
- error = gfs_stat_gfs(ip->i_sbd, &sg, TRUE);
- if (error)
- return error;
-
- error = -ENOBUFS;
-
- gfs_printf("version 0\n");
- gfs_printf("bsize %u\n", ip->i_sbd->sd_sb.sb_bsize);
- gfs_printf("total_blocks %llu\n", (unsigned long long)sg.sg_total_blocks);
- gfs_printf("free %llu\n", (unsigned long long)sg.sg_free);
- gfs_printf("used_dinode %llu\n", (unsigned long long)sg.sg_used_dinode);
- gfs_printf("free_dinode %llu\n", (unsigned long long)sg.sg_free_dinode);
- gfs_printf("used_meta %llu\n", (unsigned long long)sg.sg_used_meta);
- gfs_printf("free_meta %llu\n", (unsigned long long)sg.sg_free_meta);
-
- error = 0;
-
- out:
- return error;
-}
-
-/**
- * handle_roll - Read a atomic_t as an unsigned int
- * @a: a counter
- *
- * if @a is negative, reset it to zero
- *
- * Returns: the value of the counter
- */
-
-static unsigned int
-handle_roll(atomic_t *a)
-{
- int x = atomic_read(a);
- if (x < 0) {
- atomic_set(a, 0);
- return 0;
- }
- return (unsigned int)x;
-}
-
-/**
- * gi_get_counters - Return usage counters
- * @ip:
- * @gi:
- * @buf:
- * @size:
- * @count:
- *
- * Returns: errno
- */
-
-static int
-gi_get_counters(struct gfs_inode *ip,
- struct gfs_ioctl *gi,
- char *buf,
- unsigned int size,
- unsigned int *count)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- int error = -ENOBUFS;
-
- if (gi->gi_argc != 1)
- return -EINVAL;
-
- gfs_printf("version 0\n");
- gfs_printf("sd_glock_count:locks::%d\n",
- atomic_read(&sdp->sd_glock_count));
- gfs_printf("sd_glock_held_count:locks held::%d\n",
- atomic_read(&sdp->sd_glock_held_count));
- gfs_printf("sd_freeze_count:freeze count::%d\n",
- sdp->sd_freeze_count);
- gfs_printf("sd_inode_count:incore inodes::%d\n",
- atomic_read(&sdp->sd_inode_count));
- gfs_printf("sd_bufdata_count:metadata buffers::%d\n",
- atomic_read(&sdp->sd_bufdata_count));
- gfs_printf("sd_unlinked_ic_count:unlinked inodes::%d\n",
- atomic_read(&sdp->sd_unlinked_ic_count));
- gfs_printf("sd_quota_count:quota IDs::%d\n",
- atomic_read(&sdp->sd_quota_count));
- gfs_printf("sd_log_buffers:incore log buffers::%u\n",
- sdp->sd_log_buffers);
- gfs_printf("sd_log_seg_free:log segments free::%u\n",
- sdp->sd_log_seg_free);
- gfs_printf("ji_nsegment:log segments total::%u\n",
- sdp->sd_jdesc.ji_nsegment);
- gfs_printf("sd_mhc_count:meta header cache entries::%d\n",
- atomic_read(&sdp->sd_mhc_count));
- gfs_printf("sd_depend_count:glock dependencies::%d\n",
- atomic_read(&sdp->sd_depend_count));
- gfs_printf("sd_reclaim_count:glocks on reclaim list::%d\n",
- atomic_read(&sdp->sd_reclaim_count));
- gfs_printf("sd_log_wrap:log wraps::%llu\n",
- (unsigned long long)sdp->sd_log_wrap);
- gfs_printf("sd_lm_outstanding:outstanding LM calls::%d\n",
- atomic_read(&sdp->sd_lm_outstanding));
- gfs_printf("sd_bio_outstanding:outstanding BIO calls::%u\n",
- atomic_read(&sdp->sd_bio_outstanding));
- gfs_printf("sd_fh2dentry_misses:fh2dentry misses:diff:%u\n",
- handle_roll(&sdp->sd_fh2dentry_misses));
- gfs_printf("sd_reclaimed:glocks reclaimed:diff:%u\n",
- handle_roll(&sdp->sd_reclaimed));
- gfs_printf("sd_glock_nq_calls:glock nq calls:diff:%u\n",
- handle_roll(&sdp->sd_glock_nq_calls));
- gfs_printf("sd_glock_dq_calls:glock dq calls:diff:%u\n",
- handle_roll(&sdp->sd_glock_dq_calls));
- gfs_printf("sd_glock_prefetch_calls:glock prefetch calls:diff:%u\n",
- handle_roll(&sdp->sd_glock_prefetch_calls));
- gfs_printf("sd_lm_lock_calls:lm_lock calls:diff:%u\n",
- handle_roll(&sdp->sd_lm_lock_calls));
- gfs_printf("sd_lm_unlock_calls:lm_unlock calls:diff:%u\n",
- handle_roll(&sdp->sd_lm_unlock_calls));
- gfs_printf("sd_lm_callbacks:lm callbacks:diff:%u\n",
- handle_roll(&sdp->sd_lm_callbacks));
- gfs_printf("sd_ops_address:address operations:diff:%u\n",
- handle_roll(&sdp->sd_ops_address));
- gfs_printf("sd_ops_dentry:dentry operations:diff:%u\n",
- handle_roll(&sdp->sd_ops_dentry));
- gfs_printf("sd_ops_export:export operations:diff:%u\n",
- handle_roll(&sdp->sd_ops_export));
- gfs_printf("sd_ops_file:file operations:diff:%u\n",
- handle_roll(&sdp->sd_ops_file));
- gfs_printf("sd_ops_inode:inode operations:diff:%u\n",
- handle_roll(&sdp->sd_ops_inode));
- gfs_printf("sd_ops_super:super operations:diff:%u\n",
- handle_roll(&sdp->sd_ops_super));
- gfs_printf("sd_ops_vm:vm operations:diff:%u\n",
- handle_roll(&sdp->sd_ops_vm));
- gfs_printf("sd_bio_reads:block I/O reads:diff:%u\n",
- handle_roll(&sdp->sd_bio_reads) >>
- (sdp->sd_sb.sb_bsize_shift - 9));
- gfs_printf("sd_bio_writes:block I/O writes:diff:%u\n",
- handle_roll(&sdp->sd_bio_writes) >>
- (sdp->sd_sb.sb_bsize_shift - 9));
-
- error = 0;
-
- out:
- return error;
-}
-
-/**
- * gi_get_tune - Return current values of the tuneable parameters
- * @ip:
- * @gi:
- * @buf:
- * @size:
- * @count:
- *
- * Returns: errno
- */
-
-static int
-gi_get_tune(struct gfs_inode *ip,
- struct gfs_ioctl *gi,
- char *buf,
- unsigned int size,
- unsigned int *count)
-{
- struct gfs_tune *gt = &ip->i_sbd->sd_tune;
- int error = -ENOBUFS;
-
- if (gi->gi_argc != 1)
- return -EINVAL;
-
- spin_lock(>->gt_spin);
-
- gfs_printf("version 0\n");
- gfs_printf("ilimit1 %u\n", gt->gt_ilimit1);
- gfs_printf("ilimit1_tries %u\n", gt->gt_ilimit1_tries);
- gfs_printf("ilimit1_min %u\n", gt->gt_ilimit1_min);
- gfs_printf("ilimit2 %u\n", gt->gt_ilimit2);
- gfs_printf("ilimit2_tries %u\n", gt->gt_ilimit2_tries);
- gfs_printf("ilimit2_min %u\n", gt->gt_ilimit2_min);
- gfs_printf("demote_secs %u\n", gt->gt_demote_secs);
- gfs_printf("incore_log_blocks %u\n", gt->gt_incore_log_blocks);
- gfs_printf("jindex_refresh_secs %u\n", gt->gt_jindex_refresh_secs);
- gfs_printf("depend_secs %u\n", gt->gt_depend_secs);
- gfs_printf("scand_secs %u\n", gt->gt_scand_secs);
- gfs_printf("recoverd_secs %u\n", gt->gt_recoverd_secs);
- gfs_printf("logd_secs %u\n", gt->gt_logd_secs);
- gfs_printf("quotad_secs %u\n", gt->gt_quotad_secs);
- gfs_printf("inoded_secs %u\n", gt->gt_inoded_secs);
- gfs_printf("glock_purge %u\n", gt->gt_glock_purge);
- gfs_printf("quota_simul_sync %u\n", gt->gt_quota_simul_sync);
- gfs_printf("quota_warn_period %u\n", gt->gt_quota_warn_period);
- gfs_printf("atime_quantum %u\n", gt->gt_atime_quantum);
- gfs_printf("quota_quantum %u\n", gt->gt_quota_quantum);
- gfs_printf("quota_scale_num %u\n", gt->gt_quota_scale_num);
- gfs_printf("quota_scale_den %u\n", gt->gt_quota_scale_den);
- gfs_printf("quota_enforce %u\n", gt->gt_quota_enforce);
- gfs_printf("quota_account %u\n", gt->gt_quota_account);
- gfs_printf("new_files_jdata %u\n", gt->gt_new_files_jdata);
- gfs_printf("new_files_directio %u\n", gt->gt_new_files_directio);
- gfs_printf("max_atomic_write %u\n", gt->gt_max_atomic_write);
- gfs_printf("max_readahead %u\n", gt->gt_max_readahead);
- gfs_printf("lockdump_size %u\n", gt->gt_lockdump_size);
- gfs_printf("stall_secs %u\n", gt->gt_stall_secs);
- gfs_printf("complain_secs %u\n", gt->gt_complain_secs);
- gfs_printf("reclaim_limit %u\n", gt->gt_reclaim_limit);
- gfs_printf("entries_per_readdir %u\n", gt->gt_entries_per_readdir);
- gfs_printf("prefetch_secs %u\n", gt->gt_prefetch_secs);
- gfs_printf("statfs_slots %u\n", gt->gt_statfs_slots);
- gfs_printf("max_mhc %u\n", gt->gt_max_mhc);
- gfs_printf("greedy_default %u\n", gt->gt_greedy_default);
- gfs_printf("greedy_quantum %u\n", gt->gt_greedy_quantum);
- gfs_printf("greedy_max %u\n", gt->gt_greedy_max);
- gfs_printf("rgrp_try_threshold %u\n", gt->gt_rgrp_try_threshold);
- gfs_printf("statfs_fast %u\n", gt->gt_statfs_fast);
-
- error = 0;
-
- out:
- spin_unlock(>->gt_spin);
-
- return error;
-}
-
-#define tune_set(f, v) \
-do { \
- spin_lock(>->gt_spin); \
- gt->f = (v); \
- spin_unlock(>->gt_spin); \
-} while (0)
-
-/**
- * gi_set_tune - Set a tuneable parameter
- * @sdp:
- * @gi:
- *
- * Returns: errno
- */
-
-static int
-gi_set_tune(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user)
-{
- struct gfs_tune *gt = &sdp->sd_tune;
- char param[ARG_SIZE], value[ARG_SIZE];
- unsigned int x;
- int error;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (gi->gi_argc != 3)
- return -EINVAL;
-
- if (from_user) {
- if (strncpy_from_user(param, gi->gi_argv[1], ARG_SIZE) < 0)
- return -EFAULT;
- } else {
- strncpy(param, gi->gi_argv[1], ARG_SIZE);
- }
- param[ARG_SIZE - 1] = 0;
-
- if (from_user) {
- if (strncpy_from_user(value, gi->gi_argv[2], ARG_SIZE) < 0)
- return -EFAULT;
- } else {
- strncpy(value, gi->gi_argv[2], ARG_SIZE);
- }
-
- value[ARG_SIZE - 1] = 0;
-
- if (strcmp(param, "ilimit1") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_ilimit1, x);
-
- } else if (strcmp(param, "ilimit1_tries") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_ilimit1_tries, x);
-
- } else if (strcmp(param, "ilimit1_min") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_ilimit1_min, x);
-
- } else if (strcmp(param, "ilimit2") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_ilimit2, x);
-
- } else if (strcmp(param, "ilimit2_tries") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_ilimit2_tries, x);
-
- } else if (strcmp(param, "ilimit2_min") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_ilimit2_min, x);
-
- } else if (strcmp(param, "demote_secs") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_demote_secs, x);
-
- } else if (strcmp(param, "incore_log_blocks") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_incore_log_blocks, x);
-
- } else if (strcmp(param, "jindex_refresh_secs") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_jindex_refresh_secs, x);
-
- } else if (strcmp(param, "depend_secs") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_depend_secs, x);
-
- } else if (strcmp(param, "scand_secs") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_scand_secs, x);
- wake_up_process(sdp->sd_scand_process);
-
- } else if (strcmp(param, "recoverd_secs") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_recoverd_secs, x);
- wake_up_process(sdp->sd_recoverd_process);
-
- } else if (strcmp(param, "logd_secs") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_logd_secs, x);
- wake_up_process(sdp->sd_logd_process);
-
- } else if (strcmp(param, "quotad_secs") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_quotad_secs, x);
- wake_up_process(sdp->sd_quotad_process);
-
- } else if (strcmp(param, "inoded_secs") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_inoded_secs, x);
- wake_up_process(sdp->sd_inoded_process);
-
- } else if (strcmp(param, "glock_purge") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_glock_purge, x);
-
- } else if (strcmp(param, "quota_simul_sync") == 0) {
- if (sscanf(value, "%u", &x) != 1 || !x)
- return -EINVAL;
- tune_set(gt_quota_simul_sync, x);
-
- } else if (strcmp(param, "quota_warn_period") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_quota_warn_period, x);
-
- } else if (strcmp(param, "atime_quantum") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_atime_quantum, x);
-
- } else if (strcmp(param, "quota_quantum") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_quota_quantum, x);
-
- } else if (strcmp(param, "quota_scale") == 0) {
- unsigned int y;
- if (sscanf(value, "%u %u", &x, &y) != 2 || !y)
- return -EINVAL;
- spin_lock(>->gt_spin);
- gt->gt_quota_scale_num = x;
- gt->gt_quota_scale_den = y;
- spin_unlock(>->gt_spin);
-
- } else if (strcmp(param, "quota_enforce") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- x = !!x;
- spin_lock(>->gt_spin);
- gt->gt_quota_enforce = x;
- if (x)
- gt->gt_quota_account = 1;
- spin_unlock(>->gt_spin);
-
- } else if (strcmp(param, "quota_account") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- x = !!x;
- spin_lock(>->gt_spin);
- gt->gt_quota_account = x;
- if (x)
- spin_unlock(>->gt_spin);
- else {
- unsigned int y;
- gt->gt_quota_enforce = 0;
- spin_unlock(>->gt_spin);
- for (y = 0; y < 2; y++) {
- gfs_log_flush(sdp);
- gfs_sync_meta(sdp);
- gfs_quota_sync(sdp);
- }
- }
-
- } else if (strcmp(param, "new_files_jdata") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- x = !!x;
- tune_set(gt_new_files_jdata, x);
-
- } else if (strcmp(param, "new_files_directio") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- x = !!x;
- tune_set(gt_new_files_directio, x);
-
- } else if (strcmp(param, "max_atomic_write") == 0) {
- if (sscanf(value, "%u", &x) != 1 || !x)
- return -EINVAL;
- tune_set(gt_max_atomic_write, x);
-
- } else if (strcmp(param, "max_readahead") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_max_readahead, x);
-
- } else if (strcmp(param, "lockdump_size") == 0) {
- if (sscanf(value, "%u", &x) != 1 || !x)
- return -EINVAL;
- tune_set(gt_lockdump_size, x);
-
- } else if (strcmp(param, "stall_secs") == 0) {
- if (sscanf(value, "%u", &x) != 1 || !x)
- return -EINVAL;
- tune_set(gt_stall_secs, x);
-
- } else if (strcmp(param, "complain_secs") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_complain_secs, x);
-
- } else if (strcmp(param, "reclaim_limit") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_reclaim_limit, x);
-
- } else if (strcmp(param, "entries_per_readdir") == 0) {
- if (sscanf(value, "%u", &x) != 1 || !x)
- return -EINVAL;
- tune_set(gt_entries_per_readdir, x);
-
- } else if (strcmp(param, "prefetch_secs") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_prefetch_secs, x);
-
- } else if (strcmp(param, "statfs_slots") == 0) {
- if (sscanf(value, "%u", &x) != 1 || !x)
- return -EINVAL;
- tune_set(gt_statfs_slots, x);
-
- } else if (strcmp(param, "max_mhc") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_max_mhc, x);
-
- } else if (strcmp(param, "greedy_default") == 0) {
- if (sscanf(value, "%u", &x) != 1 || !x)
- return -EINVAL;
- tune_set(gt_greedy_default, x);
-
- } else if (strcmp(param, "greedy_quantum") == 0) {
- if (sscanf(value, "%u", &x) != 1 || !x)
- return -EINVAL;
- tune_set(gt_greedy_quantum, x);
-
- } else if (strcmp(param, "greedy_max") == 0) {
- if (sscanf(value, "%u", &x) != 1 || !x)
- return -EINVAL;
- tune_set(gt_greedy_max, x);
-
- } else if (strcmp(param, "rgrp_try_threshold") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- tune_set(gt_rgrp_try_threshold, x);
-
- } else if (strcmp(param, "statfs_fast") == 0) {
- if (sscanf(value, "%u", &x) != 1)
- return -EINVAL;
- error = gfs_statfs_init(sdp, x);
- if (error)
- return error;
- else
- tune_set(gt_statfs_fast, x);
-
-
- } else
- return -EINVAL;
-
- return 0;
-}
-
-/**
- * gi_do_reclaim - Reclaim unused metadata
- * @ip:
- * @gi:
- * @buf:
- * @size:
- * @count:
- *
- * Returns: errno
- */
-
-static int
-gi_do_reclaim(struct gfs_inode *ip,
- struct gfs_ioctl *gi,
- char *buf,
- unsigned int size,
- unsigned int *count)
-{
- uint64_t inodes, metadata;
- int error;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (gi->gi_argc != 1)
- return -EINVAL;
-
- error = gfs_reclaim_metadata(ip->i_sbd,
- &inodes,
- &metadata);
- if (error)
- return error;
-
- error = -ENOBUFS;
-
- gfs_printf("version 0\n");
- gfs_printf("inodes %llu\n", (unsigned long long)inodes);
- gfs_printf("metadata %llu\n", (unsigned long long)metadata);
-
- error = 0;
-
- out:
- return error;
-}
-
-/**
- * gi_do_shrink - throw out unused glocks
- * @sdp:
- * @gi:
- *
- * Returns: 0
- */
-
-static int
-gi_do_shrink(struct gfs_sbd *sdp, struct gfs_ioctl *gi)
-{
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (gi->gi_argc != 1)
- return -EINVAL;
- gfs_gl_hash_clear(sdp, FALSE);
- return 0;
-}
-
-/**
- * gi_get_file_stat -
- * @ip:
- * @gi:
- *
- * Returns: the number of bytes copied, or -errno
- */
-
-static int
-gi_get_file_stat(struct gfs_inode *ip, struct gfs_ioctl *gi)
-{
- struct gfs_holder i_gh;
- struct gfs_dinode *di;
- int error;
-
- if (gi->gi_argc != 1)
- return -EINVAL;
- if (gi->gi_size != sizeof(struct gfs_dinode))
- return -EINVAL;
-
- di = kmalloc(sizeof(struct gfs_dinode), GFP_KERNEL);
- if (!di)
- return -ENOMEM;
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
- if (error)
- goto out;
- memcpy(di, &ip->i_di, sizeof(struct gfs_dinode));
- gfs_glock_dq_uninit(&i_gh);
-
- if (copy_to_user(gi->gi_data, di,
- sizeof(struct gfs_dinode)))
- error = -EFAULT;
- else
- error = sizeof(struct gfs_dinode);
-
- out:
- kfree(di);
-
- return error;
-}
-
-/**
- * gi_set_file_flag - set or clear a flag on a file
- * @ip:
- * @gi:
- *
- * Returns: errno
- */
-
-static int
-gi_set_file_flag(struct gfs_inode *ip, struct gfs_ioctl *gi, int from_user)
-{
- char buf[ARG_SIZE];
- int set;
- uint32_t flag;
- struct gfs_holder i_gh;
- struct buffer_head *dibh;
- int error;
-
- if (gi->gi_argc != 3)
- return -EINVAL;
-
- if (from_user) {
- if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0)
- return -EFAULT;
- } else {
- strncpy(buf, gi->gi_argv[1], ARG_SIZE);
- }
- buf[ARG_SIZE - 1] = 0;
-
- if (strcmp(buf, "set") == 0)
- set = TRUE;
- else if (strcmp(buf, "clear") == 0)
- set = FALSE;
- else
- return -EINVAL;
-
- if (from_user) {
- if (strncpy_from_user(buf, gi->gi_argv[2], ARG_SIZE) < 0)
- return -EFAULT;
- } else {
- strncpy(buf, gi->gi_argv[2], ARG_SIZE);
- }
- buf[ARG_SIZE - 1] = 0;
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
- if (error)
- return error;
-
- error = -EACCES;
- if (ip->i_di.di_uid != current_fsuid() && !capable(CAP_FOWNER))
- goto out;
-
- error = -EINVAL;
-
- if (strcmp(buf, "jdata") == 0) {
- if (ip->i_di.di_type != GFS_FILE_REG ||
- ip->i_di.di_size)
- goto out;
- flag = GFS_DIF_JDATA;
- } else if (strcmp(buf, "directio") == 0) {
- if (ip->i_di.di_type != GFS_FILE_REG)
- goto out;
- flag = GFS_DIF_DIRECTIO;
- } else if (strcmp(buf, "immutable") == 0) {
- /* The IMMUTABLE flag can only be changed by
- the relevant capability. */
- error = -EPERM;
- if (!capable(CAP_LINUX_IMMUTABLE))
- goto out;
- flag = GFS_DIF_IMMUTABLE;
- } else if (strcmp(buf, "appendonly") == 0) {
- /* The APPENDONLY flag can only be changed by
- the relevant capability. */
- error = -EPERM;
- if (!capable(CAP_LINUX_IMMUTABLE))
- goto out;
- flag = GFS_DIF_APPENDONLY;
- } else if (strcmp(buf, "inherit_jdata") == 0) {
- if (ip->i_di.di_type != GFS_FILE_DIR)
- goto out;
- flag = GFS_DIF_INHERIT_JDATA;
- } else if (strcmp(buf, "inherit_directio") == 0) {
- if (ip->i_di.di_type != GFS_FILE_DIR)
- goto out;
- flag = GFS_DIF_INHERIT_DIRECTIO;
- } else
- goto out;
-
- error = gfs_trans_begin(ip->i_sbd, 1, 0);
- if (error)
- goto out;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto out_trans_end;
-
- if (set)
- ip->i_di.di_flags |= flag;
- else
- ip->i_di.di_flags &= ~flag;
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
-
- brelse(dibh);
-
- out_trans_end:
- gfs_trans_end(ip->i_sbd);
-
- out:
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-
-}
-
-/**
- * gi_get_file_meta - Return all the metadata for a file
- * @ip:
- * @gi:
- *
- * Returns: the number of bytes copied, or -errno
- */
-
-static int
-gi_get_file_meta(struct gfs_inode *ip, struct gfs_ioctl *gi)
-{
- struct gfs_holder i_gh;
- struct gfs_user_buffer ub;
- int error;
-
- if (gi->gi_argc != 1)
- return -EINVAL;
-
- ub.ub_data = gi->gi_data;
- ub.ub_size = gi->gi_size;
- ub.ub_count = 0;
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
- if (error)
- return error;
-
- error = -EACCES;
- if (ip->i_di.di_uid != current_fsuid() && !capable(CAP_FOWNER))
- goto out;
-
- error = gfs_get_file_meta(ip, &ub);
- if (error)
- goto out;
-
- if (ip->i_di.di_type == GFS_FILE_DIR &&
- (ip->i_di.di_flags & GFS_DIF_EXHASH)) {
- error = gfs_get_dir_meta(ip, &ub);
- if (error)
- goto out;
- }
-
- if (ip->i_di.di_eattr) {
- error = gfs_get_eattr_meta(ip, &ub);
- if (error)
- goto out;
- }
-
- error = ub.ub_count;
-
- out:
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gi_do_file_flush - sync out all dirty data and
- * drop the cache (and lock) for a file.
- * @ip:
- * @gi:
- *
- * Returns: errno
- */
-
-static int
-gi_do_file_flush(struct gfs_inode *ip, struct gfs_ioctl *gi)
-{
- if (gi->gi_argc != 1)
- return -EINVAL;
- gfs_glock_force_drop(ip->i_gl);
- return 0;
-}
-
-/**
- * gi2hip - return the "struct gfs_inode" for a hidden file
- * @sdp:
- * @gi:
- *
- * Returns: the "struct gfs_inode"
- */
-
-static struct gfs_inode *
-gi2hip(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user)
-{
- char buf[ARG_SIZE];
-
- if (gi->gi_argc != 2)
- return ERR_PTR(-EINVAL);
-
- if (from_user) {
- if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0)
- return ERR_PTR(-EFAULT);
- } else {
- strncpy(buf, gi->gi_argv[1], ARG_SIZE);
- }
- buf[ARG_SIZE - 1] = 0;
-
- if (strcmp(buf, "jindex") == 0)
- return sdp->sd_jiinode;
- else if (strcmp(buf, "rindex") == 0)
- return sdp->sd_riinode;
- else if (strcmp(buf, "quota") == 0)
- return sdp->sd_qinode;
- else if (strcmp(buf, "license") == 0)
- return sdp->sd_linode;
- else
- return ERR_PTR(-EINVAL);
-}
-
-/**
- * gi_get_hfile_stat - get stat info on a hidden file
- * @sdp:
- * @gi:
- *
- * Returns: the number of bytes copied, or -errno
- */
-
-static int
-gi_get_hfile_stat(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user)
-{
- struct gfs_inode *ip;
- struct gfs_dinode *di;
- struct gfs_holder i_gh;
- int error;
-
- ip = gi2hip(sdp, gi, from_user);
- if (IS_ERR(ip))
- return PTR_ERR(ip);
-
- if (gi->gi_size != sizeof(struct gfs_dinode))
- return -EINVAL;
-
- di = kmalloc(sizeof(struct gfs_dinode), GFP_KERNEL);
- if (!di)
- return -ENOMEM;
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
- if (error)
- goto out;
- memcpy(di, &ip->i_di, sizeof(struct gfs_dinode));
- gfs_glock_dq_uninit(&i_gh);
-
- if (copy_to_user(gi->gi_data, di,
- sizeof(struct gfs_dinode)))
- error = -EFAULT;
- else
- error = sizeof(struct gfs_dinode);
-
- out:
- kfree(di);
-
- return error;
-}
-
-/**
- * gi_do_hfile_read - Read data from a hidden file
- * @sdp:
- * @gi:
- *
- * Returns: the number of bytes read, or -errno
- */
-
-static int
-gi_do_hfile_read(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user)
-{
- struct gfs_inode *ip;
- struct gfs_holder i_gh;
- int error;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
- ip = gi2hip(sdp, gi, from_user);
- if (IS_ERR(ip))
- return PTR_ERR(ip);
-
- if (!access_ok(VERIFY_WRITE, gi->gi_data, gi->gi_size))
- return -EFAULT;
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
- if (error)
- return error;
-
- error = gfs_readi(ip, gi->gi_data, gi->gi_offset, gi->gi_size,
- gfs_copy2user);
-
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gi_do_hfile_write - Write data to a hidden file
- * @sdp:
- * @gi:
- *
- * Returns: the number of bytes written, or -errno
- */
-
-static int
-gi_do_hfile_write(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user)
-{
- struct gfs_inode *ip;
- struct gfs_alloc *al = NULL;
- struct gfs_holder i_gh;
- unsigned int data_blocks, ind_blocks;
- int alloc_required;
- int error;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
- ip = gi2hip(sdp, gi, from_user);
- if (IS_ERR(ip))
- return PTR_ERR(ip);
-
- if (!access_ok(VERIFY_READ, gi->gi_data, gi->gi_size))
- return -EFAULT;
-
- gfs_write_calc_reserv(ip, gi->gi_size, &data_blocks, &ind_blocks);
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE,
- LM_FLAG_PRIORITY | GL_SYNC | GL_NOCANCEL_OTHER,
- &i_gh);
- if (error)
- return error;
-
- if (!gfs_is_jdata(ip)) {
- gfs_consist_inode(ip);
- error = -EIO;
- goto out;
- }
-
- error = gfs_write_alloc_required(ip, gi->gi_offset, gi->gi_size,
- &alloc_required);
- if (error)
- goto out;
-
- if (alloc_required) {
- al = gfs_alloc_get(ip);
-
- error = gfs_quota_hold_m(ip, NO_QUOTA_CHANGE,
- NO_QUOTA_CHANGE);
- if (error)
- goto out_alloc;
-
- al->al_requested_meta = ind_blocks + data_blocks;
-
- error = gfs_inplace_reserve(ip);
- if (error)
- goto out_qs;
-
- /* Trans may require:
- All blocks for a RG bitmap, all the "data" blocks, whatever
- indirect blocks we need, a modified dinode, and a quota change */
-
- error = gfs_trans_begin(sdp,
- 1 + al->al_rgd->rd_ri.ri_length +
- ind_blocks + data_blocks, 1);
- if (error)
- goto out_relse;
- } else {
- /* Trans may require:
- All the "data" blocks and a modified dinode. */
-
- error = gfs_trans_begin(sdp, 1 + data_blocks, 0);
- if (error)
- goto out_relse;
- }
-
- if (from_user)
- error = gfs_writei(ip, gi->gi_data, gi->gi_offset, gi->gi_size,
- gfs_copy_from_user, NULL);
- else
- error = gfs_writei(ip, gi->gi_data, gi->gi_offset, gi->gi_size,
- gfs_copy_from_mem, NULL);
-
- gfs_trans_end(sdp);
-
- out_relse:
- if (alloc_required) {
- gfs_assert_warn(sdp, error || al->al_alloced_meta);
- gfs_inplace_release(ip);
- }
-
- out_qs:
- if (alloc_required)
- gfs_quota_unhold_m(ip);
-
- out_alloc:
- if (alloc_required)
- gfs_alloc_put(ip);
-
- out:
- ip->i_gl->gl_vn++;
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gi_do_hfile_trunc - truncate a hidden file
- * @sdp:
- * @gi:
- *
- * Returns: the number of bytes copied, or -errno
- */
-
-static int
-gi_do_hfile_trunc(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user)
-{
- struct gfs_inode *ip;
- struct gfs_holder i_gh;
- int error;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
- ip = gi2hip(sdp, gi, from_user);
- if (IS_ERR(ip))
- return PTR_ERR(ip);
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SYNC, &i_gh);
- if (error)
- return error;
-
- error = gfs_truncatei(ip, gi->gi_offset, NULL);
-
- ip->i_gl->gl_vn++;
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gi_do_quota_sync - sync the outstanding quota changes for a FS
- * @sdp:
- * @gi:
- *
- * Returns: errno
- */
-
-static int
-gi_do_quota_sync(struct gfs_sbd *sdp, struct gfs_ioctl *gi)
-{
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (gi->gi_argc != 1)
- return -EINVAL;
- return gfs_quota_sync(sdp);
-}
-
-/**
- * gi_do_quota_refresh - Refresh the a quota LVB from the quota file
- * @sdp:
- * @gi:
- *
- * Returns: errno
- */
-
-static int
-gi_do_quota_refresh(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user)
-{
- char buf[ARG_SIZE];
- int user;
- uint32_t id;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (gi->gi_argc != 2)
- return -EINVAL;
-
- if (from_user) {
- if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0)
- return -EFAULT;
- } else {
- strncpy(buf, gi->gi_argv[1], ARG_SIZE);
- }
- buf[ARG_SIZE - 1] = 0;
-
- switch (buf[0]) {
- case 'u':
- user = TRUE;
- break;
- case 'g':
- user = FALSE;
- break;
- default:
- return -EINVAL;
- }
-
- if (buf[1] != ':')
- return -EINVAL;
-
- if (sscanf(buf + 2, "%u", &id) != 1)
- return -EINVAL;
-
- return gfs_quota_refresh(sdp, user, id);
-}
-
-/**
- * gi_do_quota_read - read quota values from the quota file
- * @sdp:
- * @gi:
- *
- * Returns: errno
- */
-
-static int
-gi_do_quota_read(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user)
-{
- char buf[ARG_SIZE];
- int user;
- uint32_t id;
- struct gfs_quota q;
- int error;
-
- if (gi->gi_argc != 2)
- return -EINVAL;
- if (gi->gi_size != sizeof(struct gfs_quota))
- return -EINVAL;
-
- if (from_user) {
- if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0)
- return -EFAULT;
- } else {
- strncpy(buf, gi->gi_argv[1], ARG_SIZE);
- }
- buf[ARG_SIZE - 1] = 0;
-
- switch (buf[0]) {
- case 'u':
- user = TRUE;
- break;
- case 'g':
- user = FALSE;
- break;
- default:
- return -EINVAL;
- }
-
- if (buf[1] != ':')
- return -EINVAL;
-
- if (sscanf(buf + 2, "%u", &id) != 1)
- return -EINVAL;
-
- error = gfs_quota_read(sdp, user, id, &q);
- if (error)
- return error;
-
- if (copy_to_user(gi->gi_data, &q, sizeof(struct gfs_quota)))
- return -EFAULT;
-
- return 0;
-}
-
-int
-gfs_ioctl_i_local(struct gfs_inode *ip, struct gfs_ioctl *gi, const char *arg0,
- int from_user)
-{
- int error = -EFAULT;
-
- if (strcmp(arg0, "get_cookie") == 0)
- error = gi_skeleton(ip, gi, gi_get_cookie);
- else if (strcmp(arg0, "get_super") == 0)
- error = gi_get_super(ip->i_sbd, gi);
- else if (strcmp(arg0, "get_args") == 0)
- error = gi_skeleton(ip, gi, gi_get_args);
- else if (strcmp(arg0, "get_lockstruct") == 0)
- error = gi_skeleton(ip, gi, gi_get_lockstruct);
- else if (strcmp(arg0, "get_stat_gfs") == 0)
- error = gi_skeleton(ip, gi, gi_get_stat_gfs);
- else if (strcmp(arg0, "get_counters") == 0)
- error = gi_skeleton(ip, gi, gi_get_counters);
- else if (strcmp(arg0, "get_tune") == 0)
- error = gi_skeleton(ip, gi, gi_get_tune);
- else if (strcmp(arg0, "set_tune") == 0)
- error = gi_set_tune(ip->i_sbd, gi, from_user);
- else if (strcmp(arg0, "do_reclaim") == 0)
- error = gi_skeleton(ip, gi, gi_do_reclaim);
- else if (strcmp(arg0, "do_shrink") == 0)
- error = gi_do_shrink(ip->i_sbd, gi);
- else if (strcmp(arg0, "get_file_stat") == 0)
- error = gi_get_file_stat(ip, gi);
- else if (strcmp(arg0, "set_file_flag") == 0)
- error = gi_set_file_flag(ip, gi, from_user);
- else if (strcmp(arg0, "get_file_meta") == 0)
- error = gi_get_file_meta(ip, gi);
- else if (strcmp(arg0, "get_file_meta_quota") == 0)
- error = gi_get_file_meta(ip->i_sbd->sd_qinode, gi);
- else if (strcmp(arg0, "do_file_flush") == 0)
- error = gi_do_file_flush(ip, gi);
- else if (strcmp(arg0, "get_hfile_stat") == 0)
- error = gi_get_hfile_stat(ip->i_sbd, gi, from_user);
- else if (strcmp(arg0, "do_hfile_read") == 0)
- error = gi_do_hfile_read(ip->i_sbd, gi, from_user);
- else if (strcmp(arg0, "do_hfile_write") == 0)
- error = gi_do_hfile_write(ip->i_sbd, gi, from_user);
- else if (strcmp(arg0, "do_hfile_trunc") == 0)
- error = gi_do_hfile_trunc(ip->i_sbd, gi, from_user);
- else if (strcmp(arg0, "do_quota_sync") == 0)
- error = gi_do_quota_sync(ip->i_sbd, gi);
- else if (strcmp(arg0, "do_quota_refresh") == 0)
- error = gi_do_quota_refresh(ip->i_sbd, gi, from_user);
- else if (strcmp(arg0, "do_quota_read") == 0)
- error = gi_do_quota_read(ip->i_sbd, gi, from_user);
- else
- error = -ENOTTY;
-
- return error;
-}
-
-/**
- * gfs_ioctl_i - Normal ioctls
- * @ip:
- * @arg:
- *
- * Returns: -errno or positive byte count
- */
-
-int
-gfs_ioctl_i(struct gfs_inode *ip, void *arg)
-{
- struct gfs_ioctl *gi_user = (struct gfs_ioctl *)arg;
- struct gfs_ioctl gi;
- char **argv;
- char arg0[ARG_SIZE];
- int error = -EFAULT;
-
- if (copy_from_user(&gi, gi_user, sizeof(struct gfs_ioctl)))
- return -EFAULT;
- if (!gi.gi_argc)
- return -EINVAL;
- argv = kmalloc(gi.gi_argc * sizeof(char *), GFP_KERNEL);
- if (!argv)
- return -ENOMEM;
- if (copy_from_user(argv, gi.gi_argv,
- gi.gi_argc * sizeof(char *)))
- goto out;
- gi.gi_argv = argv;
-
- if (strncpy_from_user(arg0, argv[0], ARG_SIZE) < 0)
- goto out;
- arg0[ARG_SIZE - 1] = 0;
- error = gfs_ioctl_i_local(ip, &gi, arg0, 1);
- out:
- kfree(argv);
-
- return error;
-}
-
-#ifdef CONFIG_COMPAT
-/**
- * gfs_ioctl_i_compat - compatibility ioctls
- * These ioctls are used to provide ioctls for situations
- * where userland and kernel arch is different.
- * For example, userland may be 32-bit ppc whereas the
- * kernel may be ppc64. In this case, we need to do
- * extra translation between the addresses.
- * @ip:
- * @arg:
- *
- * Returns: -errno or positive byte count
- */
-
-int
-gfs_ioctl_i_compat(struct gfs_inode *ip, unsigned long arg)
-{
- struct gfs_ioctl_compat *src;
- struct gfs_ioctl dst;
- char **argv, *argptr;
- uint32_t *ptr;
- char arg0[ARG_SIZE];
- char *tmparg;
- int i;
- int error = -EFAULT;
-
- src = (struct gfs_ioctl_compat *)compat_ptr(arg);
-
- memset(&dst, 0, sizeof(dst));
- dst.gi_argc = src->gi_argc;
- dst.gi_size = src->gi_size;
- dst.gi_offset = src->gi_offset;
-
- argv = kmalloc(dst.gi_argc * sizeof(char *), GFP_KERNEL);
- if (!argv)
- return -ENOMEM;
-
- memset(argv, 0, dst.gi_argc * sizeof(char *));
- ptr = (uint32_t *)compat_ptr(src->gi_argv);
-
- for (i = 0; i < dst.gi_argc; i++) { /* for each parm */
- tmparg = kmalloc(ARG_SIZE * sizeof(char *), GFP_KERNEL);
- if (!tmparg)
- goto out;
- argptr = (char *)compat_ptr(*ptr);
- if (strncpy_from_user(tmparg, argptr, ARG_SIZE) < 0)
- goto out;
- argv[i] = tmparg;
- ptr++;
- }
-
- strncpy(arg0, argv[0], ARG_SIZE);
- arg0[ARG_SIZE - 1] = 0;
- dst.gi_argv = argv;
- dst.gi_data = compat_ptr(src->gi_data);
- error = gfs_ioctl_i_local(ip, &dst, arg0, 0);
- out:
- for (i = 0; i < dst.gi_argc; i++)
- kfree(argv[i]);
- kfree(argv);
- return error;
-}
-#endif
diff --git a/gfs-kernel/src/gfs/ioctl.h b/gfs-kernel/src/gfs/ioctl.h
deleted file mode 100644
index 8377496..0000000
--- a/gfs-kernel/src/gfs/ioctl.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __IOCTL_DOT_H__
-#define __IOCTL_DOT_H__
-
-int gfs_ioctl_i_local(struct gfs_inode *ip, struct gfs_ioctl *gi,
- const char *arg0, int from_user);
-int gfs_ioctl_i_compat(struct gfs_inode *ip, unsigned long arg);
-int gfs_ioctl_i(struct gfs_inode *ip, void *arg);
-
-#endif /* __IOCTL_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/lm.c b/gfs-kernel/src/gfs/lm.c
deleted file mode 100644
index bff0806..0000000
--- a/gfs-kernel/src/gfs/lm.c
+++ /dev/null
@@ -1,237 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/delay.h>
-
-#include "gfs_ondisk.h"
-#include "gfs.h"
-#include "incore.h"
-#include "glock.h"
-#include "lm.h"
-#include "super.h"
-#include "util.h"
-#include "lvb.h"
-
-/**
- * gfs_lm_mount - mount a locking protocol
- * @sdp: the filesystem
- * @args: mount arguements
- * @silent: if 1, don't complain if the FS isn't a GFS fs
- *
- * Returns: errno
- */
-
-int gfs_lm_mount(struct gfs_sbd *sdp, int silent)
-{
- char *proto = sdp->sd_proto_name;
- char *table = sdp->sd_table_name;
- int flags = 0;
- int error;
-
- if (sdp->sd_args.ar_spectator)
- flags |= LM_MFLAG_SPECTATOR;
-
- printk("Trying to join cluster \"%s\", \"%s\"\n", proto, table);
-
- error = gfs_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata,
- gfs_glock_cb, sdp,
- GFS_MIN_LVB_SIZE, flags,
- &sdp->sd_lockstruct, &sdp->sd_kobj);
- if (error) {
- printk("can't mount proto=%s, table=%s, hostdata=%s\n",
- proto, table, sdp->sd_args.ar_hostdata);
- goto out;
- }
-
- if (gfs_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) ||
- gfs_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) ||
- gfs_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >=
- GFS_MIN_LVB_SIZE)) {
- gfs_unmount_lockproto(&sdp->sd_lockstruct);
- goto out;
- }
-
- if (sdp->sd_args.ar_spectator)
- snprintf(sdp->sd_fsname, 256, "%s.s", table);
- else
- snprintf(sdp->sd_fsname, 256, "%s.%u", table,
- sdp->sd_lockstruct.ls_jid);
-
- printk("Joined cluster. Now mounting FS...\n");
- if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) &&
- !sdp->sd_args.ar_ignore_local_fs) {
- sdp->sd_args.ar_localflocks = 1;
- sdp->sd_args.ar_localcaching = 1;
- }
-
- out:
- return error;
-}
-
-void gfs_lm_others_may_mount(struct gfs_sbd *sdp)
-{
- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- sdp->sd_lockstruct.ls_ops->lm_others_may_mount(
- sdp->sd_lockstruct.ls_lockspace);
-}
-
-void gfs_lm_unmount(struct gfs_sbd *sdp)
-{
- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- gfs_unmount_lockproto(&sdp->sd_lockstruct);
-}
-
-int gfs_lm_withdraw(struct gfs_sbd *sdp, char *fmt, ...)
-{
- va_list args;
-
- if (sdp->sd_args.ar_errors == GFS_ERRORS_WITHDRAW &&
- test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
- return 0;
-
- va_start(args, fmt);
- vprintk(fmt, args);
- va_end(args);
-
- if (sdp->sd_args.ar_errors == GFS_ERRORS_WITHDRAW) {
- printk("GFS: fsid=%s: about to withdraw from the cluster\n",
- sdp->sd_fsname);
-
- BUG_ON(sdp->sd_args.ar_debug);
-
- printk("GFS: fsid=%s: telling LM to withdraw\n",
- sdp->sd_fsname);
-
- gfs_withdraw_lockproto(&sdp->sd_lockstruct);
-
- printk("GFS: fsid=%s: withdrawn\n", sdp->sd_fsname);
- }
- dump_stack();
- if (sdp->sd_args.ar_errors == GFS_ERRORS_PANIC)
- panic("GFS: fsid=%s: panic requested.\n", sdp->sd_fsname);
-
- return -1;
-}
-
-int gfs_lm_get_lock(struct gfs_sbd *sdp, struct lm_lockname *name,
- void **lockp)
-{
- int error;
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- error = -EIO;
- else
- error = sdp->sd_lockstruct.ls_ops->lm_get_lock(
- sdp->sd_lockstruct.ls_lockspace, name, lockp);
- return error;
-}
-
-void gfs_lm_put_lock(struct gfs_sbd *sdp, void *lock)
-{
- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- sdp->sd_lockstruct.ls_ops->lm_put_lock(lock);
-}
-
-unsigned int gfs_lm_lock(struct gfs_sbd *sdp, void *lock,
- unsigned int cur_state, unsigned int req_state,
- unsigned int flags)
-{
- int ret;
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- ret = 0;
- else
- ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock,
- cur_state,
- req_state, flags);
- return ret;
-}
-
-unsigned int gfs_lm_unlock(struct gfs_sbd *sdp, void *lock,
- unsigned int cur_state)
-{
- int ret;
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- ret = 0;
- else
- ret = sdp->sd_lockstruct.ls_ops->lm_unlock(lock, cur_state);
- return ret;
-}
-
-void gfs_lm_cancel(struct gfs_sbd *sdp, void *lock)
-{
- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- sdp->sd_lockstruct.ls_ops->lm_cancel(lock);
-}
-
-int gfs_lm_hold_lvb(struct gfs_sbd *sdp, void *lock, char **lvbp)
-{
- int error;
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- error = -EIO;
- else
- error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp);
- return error;
-}
-
-void gfs_lm_unhold_lvb(struct gfs_sbd *sdp, void *lock, char *lvb)
-{
- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(lock, lvb);
-}
-
-#if 0
-void gfs_lm_sync_lvb(struct gfs_sbd *sdp, void *lock, char *lvb)
-{
- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- sdp->sd_lockstruct.ls_ops->lm_sync_lvb(lock, lvb);
-}
-#endif
-
-int gfs_lm_plock_get(struct gfs_sbd *sdp, struct lm_lockname *name,
- struct file *file, struct file_lock *fl)
-{
- int error;
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- error = -EIO;
- else
- error = sdp->sd_lockstruct.ls_ops->lm_plock_get(
- sdp->sd_lockstruct.ls_lockspace,
- name, file, fl);
- return error;
-}
-
-int gfs_lm_plock(struct gfs_sbd *sdp, struct lm_lockname *name,
- struct file *file, int cmd, struct file_lock *fl)
-{
- int error;
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- error = -EIO;
- else
- error = sdp->sd_lockstruct.ls_ops->lm_plock(
- sdp->sd_lockstruct.ls_lockspace,
- name, file, cmd, fl);
- return error;
-}
-
-int gfs_lm_punlock(struct gfs_sbd *sdp, struct lm_lockname *name,
- struct file *file, struct file_lock *fl)
-{
- int error;
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- error = -EIO;
- else
- error = sdp->sd_lockstruct.ls_ops->lm_punlock(
- sdp->sd_lockstruct.ls_lockspace,
- name, file, fl);
- return error;
-}
-
-void gfs_lm_recovery_done(struct gfs_sbd *sdp, unsigned int jid,
- unsigned int message)
-{
- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- sdp->sd_lockstruct.ls_ops->lm_recovery_done(
- sdp->sd_lockstruct.ls_lockspace, jid, message);
-}
-
diff --git a/gfs-kernel/src/gfs/lm.h b/gfs-kernel/src/gfs/lm.h
deleted file mode 100644
index 40ddf2b..0000000
--- a/gfs-kernel/src/gfs/lm.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __LM_DOT_H__
-#define __LM_DOT_H__
-
-int gfs_lm_mount(struct gfs_sbd *sdp, int silent);
-void gfs_lm_others_may_mount(struct gfs_sbd *sdp);
-void gfs_lm_unmount(struct gfs_sbd *sdp);
-int gfs_lm_withdraw(struct gfs_sbd *sdp, char *fmt, ...)
-__attribute__ ((format(printf, 2, 3)));
-int gfs_lm_get_lock(struct gfs_sbd *sdp,
- struct lm_lockname *name, void **lockp);
-void gfs_lm_put_lock(struct gfs_sbd *sdp, void *lock);
-unsigned int gfs_lm_lock(struct gfs_sbd *sdp, void *lock,
- unsigned int cur_state, unsigned int req_state,
- unsigned int flags);
-unsigned int gfs_lm_unlock(struct gfs_sbd *sdp, void *lock,
- unsigned int cur_state);
-void gfs_lm_cancel(struct gfs_sbd *sdp, void *lock);
-int gfs_lm_hold_lvb(struct gfs_sbd *sdp, void *lock, char **lvbp);
-void gfs_lm_unhold_lvb(struct gfs_sbd *sdp, void *lock, char *lvb);
-int gfs_lm_plock_get(struct gfs_sbd *sdp,
- struct lm_lockname *name,
- struct file *file, struct file_lock *fl);
-int gfs_lm_plock(struct gfs_sbd *sdp,
- struct lm_lockname *name,
- struct file *file, int cmd, struct file_lock *fl);
-int gfs_lm_punlock(struct gfs_sbd *sdp,
- struct lm_lockname *name,
- struct file *file, struct file_lock *fl);
-void gfs_lm_recovery_done(struct gfs_sbd *sdp,
- unsigned int jid, unsigned int message);
-
-#endif /* __LM_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/lm_interface.h b/gfs-kernel/src/gfs/lm_interface.h
deleted file mode 100644
index fd07379..0000000
--- a/gfs-kernel/src/gfs/lm_interface.h
+++ /dev/null
@@ -1,269 +0,0 @@
-#ifndef __LM_INTERFACE_DOT_H__
-#define __LM_INTERFACE_DOT_H__
-
-
-typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
-
-/*
- * lm_mount() flags
- *
- * LM_MFLAG_SPECTATOR
- * GFS is asking to join the filesystem's lockspace, but it doesn't want to
- * modify the filesystem. The lock module shouldn't assign a journal to the FS
- * mount. It shouldn't send recovery callbacks to the FS mount. If the node
- * dies or withdraws, all locks can be wiped immediately.
- */
-
-#define LM_MFLAG_SPECTATOR 0x00000001
-
-/*
- * lm_lockstruct flags
- *
- * LM_LSFLAG_LOCAL
- * The lock_nolock module returns LM_LSFLAG_LOCAL to GFS, indicating that GFS
- * can make single-node optimizations.
- */
-
-#define LM_LSFLAG_LOCAL 0x00000001
-
-/*
- * lm_lockname types
- */
-
-#define LM_TYPE_RESERVED 0x00
-#define LM_TYPE_NONDISK 0x01
-#define LM_TYPE_INODE 0x02
-#define LM_TYPE_RGRP 0x03
-#define LM_TYPE_META 0x04
-#define LM_TYPE_IOPEN 0x05
-#define LM_TYPE_FLOCK 0x06
-#define LM_TYPE_PLOCK 0x07
-#define LM_TYPE_QUOTA 0x08
-#define LM_TYPE_JOURNAL 0x09
-
-/*
- * lm_lock() states
- *
- * SHARED is compatible with SHARED, not with DEFERRED or EX.
- * DEFERRED is compatible with DEFERRED, not with SHARED or EX.
- */
-
-#define LM_ST_UNLOCKED 0
-#define LM_ST_EXCLUSIVE 1
-#define LM_ST_DEFERRED 2
-#define LM_ST_SHARED 3
-
-/*
- * lm_lock() flags
- *
- * LM_FLAG_TRY
- * Don't wait to acquire the lock if it can't be granted immediately.
- *
- * LM_FLAG_TRY_1CB
- * Send one blocking callback if TRY is set and the lock is not granted.
- *
- * LM_FLAG_NOEXP
- * GFS sets this flag on lock requests it makes while doing journal recovery.
- * These special requests should not be blocked due to the recovery like
- * ordinary locks would be.
- *
- * LM_FLAG_ANY
- * A SHARED request may also be granted in DEFERRED, or a DEFERRED request may
- * also be granted in SHARED. The preferred state is whichever is compatible
- * with other granted locks, or the specified state if no other locks exist.
- *
- * LM_FLAG_PRIORITY
- * Override fairness considerations. Suppose a lock is held in a shared state
- * and there is a pending request for the deferred state. A shared lock
- * request with the priority flag would be allowed to bypass the deferred
- * request and directly join the other shared lock. A shared lock request
- * without the priority flag might be forced to wait until the deferred
- * requested had acquired and released the lock.
- */
-
-#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
-
-/*
- * lm_lock() and lm_async_cb return flags
- *
- * LM_OUT_ST_MASK
- * Masks the lower two bits of lock state in the returned value.
- *
- * LM_OUT_CACHEABLE
- * The lock hasn't been released so GFS can continue to cache data for it.
- *
- * LM_OUT_CANCELED
- * The lock request was canceled.
- *
- * LM_OUT_ASYNC
- * The result of the request will be returned in an LM_CB_ASYNC callback.
- */
-
-#define LM_OUT_ST_MASK 0x00000003
-#define LM_OUT_CACHEABLE 0x00000004
-#define LM_OUT_CANCELED 0x00000008
-#define LM_OUT_ASYNC 0x00000080
-#define LM_OUT_ERROR 0x00000100
-
-/*
- * lm_callback_t types
- *
- * LM_CB_NEED_E LM_CB_NEED_D LM_CB_NEED_S
- * Blocking callback, a remote node is requesting the given lock in
- * EXCLUSIVE, DEFERRED, or SHARED.
- *
- * LM_CB_NEED_RECOVERY
- * The given journal needs to be recovered.
- *
- * LM_CB_DROPLOCKS
- * Reduce the number of cached locks.
- *
- * LM_CB_ASYNC
- * The given lock has been granted.
- */
-
-#define LM_CB_NEED_E 257
-#define LM_CB_NEED_D 258
-#define LM_CB_NEED_S 259
-#define LM_CB_NEED_RECOVERY 260
-#define LM_CB_DROPLOCKS 261
-#define LM_CB_ASYNC 262
-
-/*
- * lm_recovery_done() messages
- */
-
-#define LM_RD_GAVEUP 308
-#define LM_RD_SUCCESS 309
-
-
-struct lm_lockname {
- u64 ln_number;
- unsigned int ln_type;
-};
-
-#define lm_name_equal(name1, name2) \
- (((name1)->ln_number == (name2)->ln_number) && \
- ((name1)->ln_type == (name2)->ln_type)) \
-
-struct lm_async_cb {
- struct lm_lockname lc_name;
- int lc_ret;
-};
-
-struct lm_lockstruct;
-
-struct lm_lockops {
- const char *lm_proto_name;
-
- /*
- * Mount/Unmount
- */
-
- int (*lm_mount) (char *table_name, char *host_data,
- lm_callback_t cb, void *cb_data,
- unsigned int min_lvb_size, int flags,
- struct lm_lockstruct *lockstruct,
- struct kobject *fskobj);
-
- void (*lm_others_may_mount) (void *lockspace);
-
- void (*lm_unmount) (void *lockspace);
-
- void (*lm_withdraw) (void *lockspace);
-
- /*
- * Lock oriented operations
- */
-
- int (*lm_get_lock) (void *lockspace, struct lm_lockname *name, void **lockp);
-
- void (*lm_put_lock) (void *lock);
-
- unsigned int (*lm_lock) (void *lock, unsigned int cur_state,
- unsigned int req_state, unsigned int flags);
-
- unsigned int (*lm_unlock) (void *lock, unsigned int cur_state);
-
- void (*lm_cancel) (void *lock);
-
- int (*lm_hold_lvb) (void *lock, char **lvbp);
- void (*lm_unhold_lvb) (void *lock, char *lvb);
-
- /*
- * Posix Lock oriented operations
- */
-
- int (*lm_plock_get) (void *lockspace, struct lm_lockname *name,
- struct file *file, struct file_lock *fl);
-
- int (*lm_plock) (void *lockspace, struct lm_lockname *name,
- struct file *file, int cmd, struct file_lock *fl);
-
- int (*lm_punlock) (void *lockspace, struct lm_lockname *name,
- struct file *file, struct file_lock *fl);
-
- /*
- * Client oriented operations
- */
-
- void (*lm_recovery_done) (void *lockspace, unsigned int jid,
- unsigned int message);
-
- struct module *lm_owner;
-};
-
-/*
- * lm_mount() return values
- *
- * ls_jid - the journal ID this node should use
- * ls_first - this node is the first to mount the file system
- * ls_lvb_size - size in bytes of lock value blocks
- * ls_lockspace - lock module's context for this file system
- * ls_ops - lock module's functions
- * ls_flags - lock module features
- */
-
-struct lm_lockstruct {
- unsigned int ls_jid;
- unsigned int ls_first;
- unsigned int ls_lvb_size;
- void *ls_lockspace;
- const struct lm_lockops *ls_ops;
- int ls_flags;
-};
-
-/*
- * Lock module bottom interface. A lock module makes itself available to GFS
- * with these functions.
- */
-
-int gfs_register_lockproto(const struct lm_lockops *proto);
-void gfs_unregister_lockproto(const struct lm_lockops *proto);
-
-/*
- * Lock module top interface. GFS calls these functions when mounting or
- * unmounting a file system.
- */
-
-int gfs_mount_lockproto(char *proto_name, char *table_name, char *host_data,
- lm_callback_t cb, void *cb_data,
- unsigned int min_lvb_size, int flags,
- struct lm_lockstruct *lockstruct,
- struct kobject *fskobj);
-
-void gfs_unmount_lockproto(struct lm_lockstruct *lockstruct);
-
-void gfs_withdraw_lockproto(struct lm_lockstruct *lockstruct);
-
-int init_lock_dlm(void);
-void exit_lock_dlm(void);
-int init_nolock(void);
-void exit_nolock(void);
-
-#endif /* __LM_INTERFACE_DOT_H__ */
-
diff --git a/gfs-kernel/src/gfs/lock_dlm.h b/gfs-kernel/src/gfs/lock_dlm.h
deleted file mode 100644
index 15908cd..0000000
--- a/gfs-kernel/src/gfs/lock_dlm.h
+++ /dev/null
@@ -1,173 +0,0 @@
-#ifndef LOCK_DLM_DOT_H
-#define LOCK_DLM_DOT_H
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/list.h>
-#include <linux/socket.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <linux/kobject.h>
-#include <linux/fcntl.h>
-#include <linux/wait.h>
-#include <net/sock.h>
-
-#include <linux/dlm.h>
-#include <linux/dlm_plock.h>
-#include "lm_interface.h"
-
-/*
- * Internally, we prefix things with gdlm_ and GDLM_ (for gfs-dlm) since a
- * prefix of lock_dlm_ gets awkward. Externally, GFS refers to this module
- * as "lock_dlm".
- */
-
-#define GDLM_STRNAME_BYTES 24
-#define GDLM_LVB_SIZE 32
-#define GDLM_DROP_COUNT 0
-#define GDLM_DROP_PERIOD 60
-#define GDLM_NAME_LEN 128
-
-/* GFS uses 12 bytes to identify a resource (32 bit type + 64 bit number).
- We sprintf these numbers into a 24 byte string of hex values to make them
- human-readable (to make debugging simpler.) */
-
-struct gdlm_strname {
- unsigned char name[GDLM_STRNAME_BYTES];
- unsigned short namelen;
-};
-
-enum {
- DFL_BLOCK_LOCKS = 0,
- DFL_SPECTATOR = 1,
- DFL_WITHDRAW = 2,
-};
-
-struct gdlm_ls {
- u32 id;
- int jid;
- int first;
- int first_done;
- unsigned long flags;
- struct kobject kobj;
- char clustername[GDLM_NAME_LEN];
- char fsname[GDLM_NAME_LEN];
- int fsflags;
- dlm_lockspace_t *dlm_lockspace;
- lm_callback_t fscb;
- struct gfs_sbd *sdp;
- int recover_jid;
- int recover_jid_done;
- int recover_jid_status;
- spinlock_t async_lock;
- struct list_head complete;
- struct list_head blocking;
- struct list_head delayed;
- struct list_head submit;
- struct list_head all_locks;
- u32 all_locks_count;
- wait_queue_head_t wait_control;
- struct task_struct *thread1;
- struct task_struct *thread2;
- wait_queue_head_t thread_wait;
- unsigned long drop_time;
- int drop_locks_count;
- int drop_locks_period;
-};
-
-enum {
- LFL_NOBLOCK = 0,
- LFL_NOCACHE = 1,
- LFL_DLM_UNLOCK = 2,
- LFL_DLM_CANCEL = 3,
- LFL_SYNC_LVB = 4,
- LFL_FORCE_PROMOTE = 5,
- LFL_REREQUEST = 6,
- LFL_ACTIVE = 7,
- LFL_INLOCK = 8,
- LFL_CANCEL = 9,
- LFL_NOBAST = 10,
- LFL_HEADQUE = 11,
- LFL_UNLOCK_DELETE = 12,
- LFL_AST_WAIT = 13,
-};
-
-struct gdlm_lock {
- struct gdlm_ls *ls;
- struct lm_lockname lockname;
- struct gdlm_strname strname;
- char *lvb;
- struct dlm_lksb lksb;
-
- s16 cur;
- s16 req;
- s16 prev_req;
- u32 lkf; /* dlm flags DLM_LKF_ */
- unsigned long flags; /* lock_dlm flags LFL_ */
-
- int bast_mode; /* protected by async_lock */
-
- struct list_head clist; /* complete */
- struct list_head blist; /* blocking */
- struct list_head delay_list; /* delayed */
- struct list_head all_list; /* all locks for the fs */
- struct gdlm_lock *hold_null; /* NL lock for hold_lvb */
-};
-
-#define gdlm_assert(assertion, fmt, args...) \
-do { \
- if (unlikely(!(assertion))) { \
- printk(KERN_EMERG "lock_dlm: fatal assertion failed \"%s\"\n" \
- "lock_dlm: " fmt "\n", \
- #assertion, ##args); \
- BUG(); \
- } \
-} while (0)
-
-#define log_print(lev, fmt, arg...) printk(lev "lock_dlm: " fmt "\n" , ## arg)
-#define log_info(fmt, arg...) log_print(KERN_INFO , fmt , ## arg)
-#define log_error(fmt, arg...) log_print(KERN_ERR , fmt , ## arg)
-#ifdef LOCK_DLM_LOG_DEBUG
-#define log_debug(fmt, arg...) log_print(KERN_DEBUG , fmt , ## arg)
-#else
-#define log_debug(fmt, arg...)
-#endif
-
-/* sysfs.c */
-
-int gdlm_sysfs_init(void);
-void gdlm_sysfs_exit(void);
-int gdlm_kobject_setup(struct gdlm_ls *, struct kobject *);
-void gdlm_kobject_release(struct gdlm_ls *);
-
-/* thread.c */
-
-int gdlm_init_threads(struct gdlm_ls *);
-void gdlm_release_threads(struct gdlm_ls *);
-
-/* lock.c */
-
-s16 gdlm_make_lmstate(s16);
-void gdlm_queue_delayed(struct gdlm_lock *);
-void gdlm_submit_delayed(struct gdlm_ls *);
-int gdlm_release_all_locks(struct gdlm_ls *);
-void gdlm_delete_lp(struct gdlm_lock *);
-unsigned int gdlm_do_lock(struct gdlm_lock *);
-
-int gdlm_get_lock(void *, struct lm_lockname *, void **);
-void gdlm_put_lock(void *);
-unsigned int gdlm_lock(void *, unsigned int, unsigned int, unsigned int);
-unsigned int gdlm_unlock(void *, unsigned int);
-void gdlm_cancel(void *);
-int gdlm_hold_lvb(void *, char **);
-void gdlm_unhold_lvb(void *, char *);
-
-/* mount.c */
-
-extern const struct lm_lockops gdlm_ops;
-
-#endif
-
diff --git a/gfs-kernel/src/gfs/lock_dlm_lock.c b/gfs-kernel/src/gfs/lock_dlm_lock.c
deleted file mode 100644
index 65ef0bd..0000000
--- a/gfs-kernel/src/gfs/lock_dlm_lock.c
+++ /dev/null
@@ -1,518 +0,0 @@
-#include "lock_dlm.h"
-
-static char junk_lvb[GDLM_LVB_SIZE];
-
-static void queue_complete(struct gdlm_lock *lp)
-{
- struct gdlm_ls *ls = lp->ls;
-
- clear_bit(LFL_ACTIVE, &lp->flags);
-
- spin_lock(&ls->async_lock);
- list_add_tail(&lp->clist, &ls->complete);
- spin_unlock(&ls->async_lock);
- wake_up(&ls->thread_wait);
-}
-
-static inline void gdlm_ast(void *astarg)
-{
- queue_complete(astarg);
-}
-
-static inline void gdlm_bast(void *astarg, int mode)
-{
- struct gdlm_lock *lp = astarg;
- struct gdlm_ls *ls = lp->ls;
-
- if (!mode) {
- printk(KERN_INFO "lock_dlm: bast mode zero %x,%llx\n",
- lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number);
- return;
- }
-
- spin_lock(&ls->async_lock);
- if (!lp->bast_mode) {
- list_add_tail(&lp->blist, &ls->blocking);
- lp->bast_mode = mode;
- } else if (lp->bast_mode < mode)
- lp->bast_mode = mode;
- spin_unlock(&ls->async_lock);
- wake_up(&ls->thread_wait);
-}
-
-void gdlm_queue_delayed(struct gdlm_lock *lp)
-{
- struct gdlm_ls *ls = lp->ls;
-
- spin_lock(&ls->async_lock);
- list_add_tail(&lp->delay_list, &ls->delayed);
- spin_unlock(&ls->async_lock);
-}
-
-/* convert gfs lock-state to dlm lock-mode */
-
-static s16 make_mode(s16 lmstate)
-{
- switch (lmstate) {
- case LM_ST_UNLOCKED:
- return DLM_LOCK_NL;
- case LM_ST_EXCLUSIVE:
- return DLM_LOCK_EX;
- case LM_ST_DEFERRED:
- return DLM_LOCK_CW;
- case LM_ST_SHARED:
- return DLM_LOCK_PR;
- }
- gdlm_assert(0, "unknown LM state %d", lmstate);
- return -1;
-}
-
-/* convert dlm lock-mode to gfs lock-state */
-
-s16 gdlm_make_lmstate(s16 dlmmode)
-{
- switch (dlmmode) {
- case DLM_LOCK_IV:
- case DLM_LOCK_NL:
- return LM_ST_UNLOCKED;
- case DLM_LOCK_EX:
- return LM_ST_EXCLUSIVE;
- case DLM_LOCK_CW:
- return LM_ST_DEFERRED;
- case DLM_LOCK_PR:
- return LM_ST_SHARED;
- }
- gdlm_assert(0, "unknown DLM mode %d", dlmmode);
- return -1;
-}
-
-/* verify agreement with GFS on the current lock state, NB: DLM_LOCK_NL and
- DLM_LOCK_IV are both considered LM_ST_UNLOCKED by GFS. */
-
-static void check_cur_state(struct gdlm_lock *lp, unsigned int cur_state)
-{
- s16 cur = make_mode(cur_state);
- if (lp->cur != DLM_LOCK_IV)
- gdlm_assert(lp->cur == cur, "%d, %d", lp->cur, cur);
-}
-
-static inline unsigned int make_flags(struct gdlm_lock *lp,
- unsigned int gfs_flags,
- s16 cur, s16 req)
-{
- unsigned int lkf = 0;
-
- if (gfs_flags & LM_FLAG_TRY)
- lkf |= DLM_LKF_NOQUEUE;
-
- if (gfs_flags & LM_FLAG_TRY_1CB) {
- lkf |= DLM_LKF_NOQUEUE;
- lkf |= DLM_LKF_NOQUEUEBAST;
- }
-
- if (gfs_flags & LM_FLAG_PRIORITY) {
- lkf |= DLM_LKF_NOORDER;
- lkf |= DLM_LKF_HEADQUE;
- }
-
- if (gfs_flags & LM_FLAG_ANY) {
- if (req == DLM_LOCK_PR)
- lkf |= DLM_LKF_ALTCW;
- else if (req == DLM_LOCK_CW)
- lkf |= DLM_LKF_ALTPR;
- }
-
- if (lp->lksb.sb_lkid != 0) {
- lkf |= DLM_LKF_CONVERT;
-
- /* Conversion deadlock avoidance by DLM */
-
- if (!test_bit(LFL_FORCE_PROMOTE, &lp->flags) &&
- !(lkf & DLM_LKF_NOQUEUE) &&
- cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req)
- lkf |= DLM_LKF_CONVDEADLK;
- }
-
- if (lp->lvb)
- lkf |= DLM_LKF_VALBLK;
-
- return lkf;
-}
-
-/* make_strname - convert GFS lock numbers to a string */
-
-static inline void make_strname(const struct lm_lockname *lockname,
- struct gdlm_strname *str)
-{
- sprintf(str->name, "%8x%16llx", lockname->ln_type,
- (unsigned long long)lockname->ln_number);
- str->namelen = GDLM_STRNAME_BYTES;
-}
-
-static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name,
- struct gdlm_lock **lpp)
-{
- struct gdlm_lock *lp;
-
- lp = kzalloc(sizeof(struct gdlm_lock), GFP_NOFS);
- if (!lp)
- return -ENOMEM;
-
- lp->lockname = *name;
- make_strname(name, &lp->strname);
- lp->ls = ls;
- lp->cur = DLM_LOCK_IV;
- lp->lvb = NULL;
- lp->hold_null = NULL;
- INIT_LIST_HEAD(&lp->clist);
- INIT_LIST_HEAD(&lp->blist);
- INIT_LIST_HEAD(&lp->delay_list);
-
- spin_lock(&ls->async_lock);
- list_add(&lp->all_list, &ls->all_locks);
- ls->all_locks_count++;
- spin_unlock(&ls->async_lock);
-
- *lpp = lp;
- return 0;
-}
-
-void gdlm_delete_lp(struct gdlm_lock *lp)
-{
- struct gdlm_ls *ls = lp->ls;
-
- spin_lock(&ls->async_lock);
- if (!list_empty(&lp->clist))
- list_del_init(&lp->clist);
- if (!list_empty(&lp->blist))
- list_del_init(&lp->blist);
- if (!list_empty(&lp->delay_list))
- list_del_init(&lp->delay_list);
- gdlm_assert(!list_empty(&lp->all_list), "%x,%llx", lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number);
- list_del_init(&lp->all_list);
- ls->all_locks_count--;
- spin_unlock(&ls->async_lock);
-
- kfree(lp);
-}
-
-int gdlm_get_lock(void *lockspace, struct lm_lockname *name,
- void **lockp)
-{
- struct gdlm_lock *lp;
- int error;
-
- error = gdlm_create_lp(lockspace, name, &lp);
-
- *lockp = lp;
- return error;
-}
-
-void gdlm_put_lock(void *lock)
-{
- gdlm_delete_lp(lock);
-}
-
-unsigned int gdlm_do_lock(struct gdlm_lock *lp)
-{
- struct gdlm_ls *ls = lp->ls;
- int error, bast = 1;
-
- /*
- * When recovery is in progress, delay lock requests for submission
- * once recovery is done. Requests for recovery (NOEXP) and unlocks
- * can pass.
- */
-
- if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) &&
- !test_bit(LFL_NOBLOCK, &lp->flags) && lp->req != DLM_LOCK_NL) {
- gdlm_queue_delayed(lp);
- return LM_OUT_ASYNC;
- }
-
- /*
- * Submit the actual lock request.
- */
-
- if (test_bit(LFL_NOBAST, &lp->flags))
- bast = 0;
-
- set_bit(LFL_ACTIVE, &lp->flags);
-
- log_debug("lk %x,%llx id %x %d,%d %x", lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number, lp->lksb.sb_lkid,
- lp->cur, lp->req, lp->lkf);
-
- error = dlm_lock(ls->dlm_lockspace, lp->req, &lp->lksb, lp->lkf,
- lp->strname.name, lp->strname.namelen, 0, gdlm_ast,
- lp, bast ? gdlm_bast : NULL);
-
- if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) {
- lp->lksb.sb_status = -EAGAIN;
- queue_complete(lp);
- error = 0;
- }
-
- if (error) {
- log_error("%s: gdlm_lock %x,%llx err=%d cur=%d req=%d lkf=%x "
- "flags=%lx", ls->fsname, lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number, error,
- lp->cur, lp->req, lp->lkf, lp->flags);
- return LM_OUT_ERROR;
- }
- return LM_OUT_ASYNC;
-}
-
-static unsigned int gdlm_do_unlock(struct gdlm_lock *lp)
-{
- struct gdlm_ls *ls = lp->ls;
- unsigned int lkf = 0;
- int error;
-
- set_bit(LFL_DLM_UNLOCK, &lp->flags);
- set_bit(LFL_ACTIVE, &lp->flags);
-
- if (lp->lvb)
- lkf = DLM_LKF_VALBLK;
-
- log_debug("un %x,%llx %x %d %x", lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number,
- lp->lksb.sb_lkid, lp->cur, lkf);
-
- error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, lkf, NULL, lp);
-
- if (error) {
- log_error("%s: gdlm_unlock %x,%llx err=%d cur=%d req=%d lkf=%x "
- "flags=%lx", ls->fsname, lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number, error,
- lp->cur, lp->req, lp->lkf, lp->flags);
- return LM_OUT_ERROR;
- }
- return LM_OUT_ASYNC;
-}
-
-unsigned int gdlm_lock(void *lock, unsigned int cur_state,
- unsigned int req_state, unsigned int flags)
-{
- struct gdlm_lock *lp = lock;
-
- clear_bit(LFL_DLM_CANCEL, &lp->flags);
- if (flags & LM_FLAG_NOEXP)
- set_bit(LFL_NOBLOCK, &lp->flags);
-
- check_cur_state(lp, cur_state);
- lp->req = make_mode(req_state);
- lp->lkf = make_flags(lp, flags, lp->cur, lp->req);
-
- return gdlm_do_lock(lp);
-}
-
-unsigned int gdlm_unlock(void *lock, unsigned int cur_state)
-{
- struct gdlm_lock *lp = lock;
-
- clear_bit(LFL_DLM_CANCEL, &lp->flags);
- if (lp->cur == DLM_LOCK_IV)
- return 0;
- return gdlm_do_unlock(lp);
-}
-
-void gdlm_cancel(void *lock)
-{
- struct gdlm_lock *lp = lock;
- struct gdlm_ls *ls = lp->ls;
- int error, delay_list = 0;
-
- if (test_bit(LFL_DLM_CANCEL, &lp->flags))
- return;
-
- log_info("gdlm_cancel %x,%llx flags %lx", lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number, lp->flags);
-
- spin_lock(&ls->async_lock);
- if (!list_empty(&lp->delay_list)) {
- list_del_init(&lp->delay_list);
- delay_list = 1;
- }
- spin_unlock(&ls->async_lock);
-
- if (delay_list) {
- set_bit(LFL_CANCEL, &lp->flags);
- set_bit(LFL_ACTIVE, &lp->flags);
- queue_complete(lp);
- return;
- }
-
- if (!test_bit(LFL_ACTIVE, &lp->flags) ||
- test_bit(LFL_DLM_UNLOCK, &lp->flags)) {
- log_info("gdlm_cancel skip %x,%llx flags %lx",
- lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number, lp->flags);
- return;
- }
-
- /* the lock is blocked in the dlm */
-
- set_bit(LFL_DLM_CANCEL, &lp->flags);
- set_bit(LFL_ACTIVE, &lp->flags);
-
- error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, DLM_LKF_CANCEL,
- NULL, lp);
-
- log_info("gdlm_cancel rv %d %x,%llx flags %lx", error,
- lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number, lp->flags);
-
- if (error == -EBUSY)
- clear_bit(LFL_DLM_CANCEL, &lp->flags);
-}
-
-static int gdlm_add_lvb(struct gdlm_lock *lp)
-{
- char *lvb;
-
- lvb = kzalloc(GDLM_LVB_SIZE, GFP_NOFS);
- if (!lvb)
- return -ENOMEM;
-
- lp->lksb.sb_lvbptr = lvb;
- lp->lvb = lvb;
- return 0;
-}
-
-static void gdlm_del_lvb(struct gdlm_lock *lp)
-{
- kfree(lp->lvb);
- lp->lvb = NULL;
- lp->lksb.sb_lvbptr = NULL;
-}
-
-static int gdlm_ast_wait(void *word)
-{
- schedule();
- return 0;
-}
-
-/* This can do a synchronous dlm request (requiring a lock_dlm thread to get
- the completion) because gfs won't call hold_lvb() during a callback (from
- the context of a lock_dlm thread). */
-
-static int hold_null_lock(struct gdlm_lock *lp)
-{
- struct gdlm_lock *lpn = NULL;
- int error;
-
- if (lp->hold_null) {
- printk(KERN_INFO "lock_dlm: lvb already held\n");
- return 0;
- }
-
- error = gdlm_create_lp(lp->ls, &lp->lockname, &lpn);
- if (error)
- goto out;
-
- lpn->lksb.sb_lvbptr = junk_lvb;
- lpn->lvb = junk_lvb;
-
- lpn->req = DLM_LOCK_NL;
- lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE;
- set_bit(LFL_NOBAST, &lpn->flags);
- set_bit(LFL_INLOCK, &lpn->flags);
- set_bit(LFL_AST_WAIT, &lpn->flags);
-
- gdlm_do_lock(lpn);
- wait_on_bit(&lpn->flags, LFL_AST_WAIT, gdlm_ast_wait, TASK_UNINTERRUPTIBLE);
- error = lpn->lksb.sb_status;
- if (error) {
- printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n",
- error);
- gdlm_delete_lp(lpn);
- lpn = NULL;
- }
-out:
- lp->hold_null = lpn;
- return error;
-}
-
-/* This cannot do a synchronous dlm request (requiring a lock_dlm thread to get
- the completion) because gfs may call unhold_lvb() during a callback (from
- the context of a lock_dlm thread) which could cause a deadlock since the
- other lock_dlm thread could be engaged in recovery. */
-
-static void unhold_null_lock(struct gdlm_lock *lp)
-{
- struct gdlm_lock *lpn = lp->hold_null;
-
- gdlm_assert(lpn, "%x,%llx", lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number);
- lpn->lksb.sb_lvbptr = NULL;
- lpn->lvb = NULL;
- set_bit(LFL_UNLOCK_DELETE, &lpn->flags);
- gdlm_do_unlock(lpn);
- lp->hold_null = NULL;
-}
-
-/* Acquire a NL lock because gfs requires the value block to remain
- intact on the resource while the lvb is "held" even if it's holding no locks
- on the resource. */
-
-int gdlm_hold_lvb(void *lock, char **lvbp)
-{
- struct gdlm_lock *lp = lock;
- int error;
-
- error = gdlm_add_lvb(lp);
- if (error)
- return error;
-
- *lvbp = lp->lvb;
-
- error = hold_null_lock(lp);
- if (error)
- gdlm_del_lvb(lp);
-
- return error;
-}
-
-void gdlm_unhold_lvb(void *lock, char *lvb)
-{
- struct gdlm_lock *lp = lock;
-
- unhold_null_lock(lp);
- gdlm_del_lvb(lp);
-}
-
-void gdlm_submit_delayed(struct gdlm_ls *ls)
-{
- struct gdlm_lock *lp, *safe;
-
- spin_lock(&ls->async_lock);
- list_for_each_entry_safe(lp, safe, &ls->delayed, delay_list) {
- list_del_init(&lp->delay_list);
- list_add_tail(&lp->delay_list, &ls->submit);
- }
- spin_unlock(&ls->async_lock);
- wake_up(&ls->thread_wait);
-}
-
-int gdlm_release_all_locks(struct gdlm_ls *ls)
-{
- struct gdlm_lock *lp, *safe;
- int count = 0;
-
- spin_lock(&ls->async_lock);
- list_for_each_entry_safe(lp, safe, &ls->all_locks, all_list) {
- list_del_init(&lp->all_list);
-
- if (lp->lvb && lp->lvb != junk_lvb)
- kfree(lp->lvb);
- kfree(lp);
- count++;
- }
- spin_unlock(&ls->async_lock);
-
- return count;
-}
-
diff --git a/gfs-kernel/src/gfs/lock_dlm_main.c b/gfs-kernel/src/gfs/lock_dlm_main.c
deleted file mode 100644
index be7c625..0000000
--- a/gfs-kernel/src/gfs/lock_dlm_main.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <linux/init.h>
-
-#include "lock_dlm.h"
-
-int init_lock_dlm()
-{
- int error;
-
- error = gfs_register_lockproto(&gdlm_ops);
- if (error) {
- printk(KERN_WARNING "lock_dlm: can't register protocol: %d\n",
- error);
- return error;
- }
-
- error = gdlm_sysfs_init();
- if (error) {
- gfs_unregister_lockproto(&gdlm_ops);
- return error;
- }
-
- printk(KERN_INFO
- "Lock_DLM (built %s %s) installed\n", __DATE__, __TIME__);
- return 0;
-}
-
-void exit_lock_dlm()
-{
- gdlm_sysfs_exit();
- gfs_unregister_lockproto(&gdlm_ops);
-}
diff --git a/gfs-kernel/src/gfs/lock_dlm_mount.c b/gfs-kernel/src/gfs/lock_dlm_mount.c
deleted file mode 100644
index ce5906a..0000000
--- a/gfs-kernel/src/gfs/lock_dlm_mount.c
+++ /dev/null
@@ -1,278 +0,0 @@
-#include "lock_dlm.h"
-
-const struct lm_lockops gdlm_ops;
-
-
-static struct gdlm_ls *init_gdlm(lm_callback_t cb, struct gfs_sbd *sdp,
- int flags, char *table_name)
-{
- struct gdlm_ls *ls;
- char buf[256], *p;
-
- ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL);
- if (!ls)
- return NULL;
-
- ls->drop_locks_count = GDLM_DROP_COUNT;
- ls->drop_locks_period = GDLM_DROP_PERIOD;
- ls->fscb = cb;
- ls->sdp = sdp;
- ls->fsflags = flags;
- spin_lock_init(&ls->async_lock);
- INIT_LIST_HEAD(&ls->complete);
- INIT_LIST_HEAD(&ls->blocking);
- INIT_LIST_HEAD(&ls->delayed);
- INIT_LIST_HEAD(&ls->submit);
- INIT_LIST_HEAD(&ls->all_locks);
- init_waitqueue_head(&ls->thread_wait);
- init_waitqueue_head(&ls->wait_control);
- ls->thread1 = NULL;
- ls->thread2 = NULL;
- ls->drop_time = jiffies;
- ls->jid = -1;
-
- strncpy(buf, table_name, 256);
- buf[255] = '\0';
-
- p = strchr(buf, ':');
- if (!p) {
- log_info("invalid table_name \"%s\"", table_name);
- kfree(ls);
- return NULL;
- }
- *p = '\0';
- p++;
-
- strncpy(ls->clustername, buf, GDLM_NAME_LEN);
- strncpy(ls->fsname, p, GDLM_NAME_LEN);
-
- return ls;
-}
-
-static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
-{
- char data[256];
- char *options, *x, *y;
- int error = 0;
-
- memset(data, 0, 256);
- strncpy(data, data_arg, 255);
-
- if (!strlen(data)) {
- log_error("no mount options, (u)mount helpers not installed");
- return -EINVAL;
- }
-
- for (options = data; (x = strsep(&options, ":")); ) {
- if (!*x)
- continue;
-
- y = strchr(x, '=');
- if (y)
- *y++ = 0;
-
- if (!strcmp(x, "jid")) {
- if (!y) {
- log_error("need argument to jid");
- error = -EINVAL;
- break;
- }
- sscanf(y, "%u", &ls->jid);
-
- } else if (!strcmp(x, "first")) {
- if (!y) {
- log_error("need argument to first");
- error = -EINVAL;
- break;
- }
- sscanf(y, "%u", &ls->first);
-
- } else if (!strcmp(x, "id")) {
- if (!y) {
- log_error("need argument to id");
- error = -EINVAL;
- break;
- }
- sscanf(y, "%u", &ls->id);
-
- } else if (!strcmp(x, "nodir")) {
- if (!y) {
- log_error("need argument to nodir");
- error = -EINVAL;
- break;
- }
- sscanf(y, "%u", nodir);
-
- } else {
- log_error("unkonwn option: %s", x);
- error = -EINVAL;
- break;
- }
- }
-
- return error;
-}
-
-static int gdlm_mount(char *table_name, char *host_data,
- lm_callback_t cb, void *cb_data,
- unsigned int min_lvb_size, int flags,
- struct lm_lockstruct *lockstruct,
- struct kobject *fskobj)
-{
- struct gdlm_ls *ls;
- int error = -ENOMEM, nodir = 0;
-
- if (min_lvb_size > GDLM_LVB_SIZE)
- goto out;
-
- ls = init_gdlm(cb, cb_data, flags, table_name);
- if (!ls)
- goto out;
-
- error = make_args(ls, host_data, &nodir);
- if (error)
- goto out;
-
- error = gdlm_init_threads(ls);
- if (error)
- goto out_free;
-
- error = gdlm_kobject_setup(ls, fskobj);
- if (error)
- goto out_thread;
-
- error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
- &ls->dlm_lockspace,
- DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
- GDLM_LVB_SIZE);
- if (error) {
- log_error("dlm_new_lockspace error %d", error);
- goto out_kobj;
- }
-
- lockstruct->ls_jid = ls->jid;
- lockstruct->ls_first = ls->first;
- lockstruct->ls_lockspace = ls;
- lockstruct->ls_ops = &gdlm_ops;
- lockstruct->ls_flags = 0;
- lockstruct->ls_lvb_size = GDLM_LVB_SIZE;
- return 0;
-
-out_kobj:
- gdlm_kobject_release(ls);
-out_thread:
- gdlm_release_threads(ls);
-out_free:
- kfree(ls);
-out:
- return error;
-}
-
-static void gdlm_unmount(void *lockspace)
-{
- struct gdlm_ls *ls = lockspace;
- int rv;
-
- log_debug("unmount flags %lx", ls->flags);
-
- /* FIXME: serialize unmount and withdraw in case they
- happen at once. Also, if unmount follows withdraw,
- wait for withdraw to finish. */
-
- if (test_bit(DFL_WITHDRAW, &ls->flags))
- goto out;
-
- gdlm_kobject_release(ls);
- dlm_release_lockspace(ls->dlm_lockspace, 2);
- gdlm_release_threads(ls);
- rv = gdlm_release_all_locks(ls);
- if (rv)
- log_info("gdlm_unmount: %d stray locks freed", rv);
-out:
- kfree(ls);
-}
-
-static void gdlm_recovery_done(void *lockspace, unsigned int jid,
- unsigned int message)
-{
- char env_jid[20];
- char env_status[20];
- char *envp[] = { env_jid, env_status, NULL };
- struct gdlm_ls *ls = lockspace;
- ls->recover_jid_done = jid;
- ls->recover_jid_status = message;
- sprintf(env_jid, "JID=%d", jid);
- sprintf(env_status, "RECOVERY=%s",
- message == LM_RD_SUCCESS ? "Done" : "Failed");
- kobject_uevent_env(&ls->kobj, KOBJ_CHANGE, envp);
-}
-
-static void gdlm_others_may_mount(void *lockspace)
-{
- char *message = "FIRSTMOUNT=Done";
- char *envp[] = { message, NULL };
- struct gdlm_ls *ls = lockspace;
- ls->first_done = 1;
- kobject_uevent_env(&ls->kobj, KOBJ_CHANGE, envp);
-}
-
-/* Userspace gets the offline uevent, blocks new gfs locks on
- other mounters, and lets us know (sets WITHDRAW flag). Then,
- userspace leaves the mount group while we leave the lockspace. */
-
-static void gdlm_withdraw(void *lockspace)
-{
- struct gdlm_ls *ls = lockspace;
-
- kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
-
- wait_event_interruptible(ls->wait_control,
- test_bit(DFL_WITHDRAW, &ls->flags));
-
- dlm_release_lockspace(ls->dlm_lockspace, 2);
- gdlm_release_threads(ls);
- gdlm_release_all_locks(ls);
- gdlm_kobject_release(ls);
-}
-
-static int gdlm_plock(void *lockspace, struct lm_lockname *name,
- struct file *file, int cmd, struct file_lock *fl)
-{
- struct gdlm_ls *ls = lockspace;
- return dlm_posix_lock(ls->dlm_lockspace, name->ln_number, file, cmd, fl);
-}
-
-static int gdlm_punlock(void *lockspace, struct lm_lockname *name,
- struct file *file, struct file_lock *fl)
-{
- struct gdlm_ls *ls = lockspace;
- return dlm_posix_unlock(ls->dlm_lockspace, name->ln_number, file, fl);
-}
-
-static int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
- struct file *file, struct file_lock *fl)
-{
- struct gdlm_ls *ls = lockspace;
- return dlm_posix_get(ls->dlm_lockspace, name->ln_number, file, fl);
-}
-
-const struct lm_lockops gdlm_ops = {
- .lm_proto_name = "lock_dlm",
- .lm_mount = gdlm_mount,
- .lm_others_may_mount = gdlm_others_may_mount,
- .lm_unmount = gdlm_unmount,
- .lm_withdraw = gdlm_withdraw,
- .lm_get_lock = gdlm_get_lock,
- .lm_put_lock = gdlm_put_lock,
- .lm_lock = gdlm_lock,
- .lm_unlock = gdlm_unlock,
- .lm_plock = gdlm_plock,
- .lm_punlock = gdlm_punlock,
- .lm_plock_get = gdlm_plock_get,
- .lm_cancel = gdlm_cancel,
- .lm_hold_lvb = gdlm_hold_lvb,
- .lm_unhold_lvb = gdlm_unhold_lvb,
- .lm_recovery_done = gdlm_recovery_done,
- .lm_owner = THIS_MODULE,
-};
-
diff --git a/gfs-kernel/src/gfs/lock_dlm_sysfs.c b/gfs-kernel/src/gfs/lock_dlm_sysfs.c
deleted file mode 100644
index 01445a5..0000000
--- a/gfs-kernel/src/gfs/lock_dlm_sysfs.c
+++ /dev/null
@@ -1,229 +0,0 @@
-#include <linux/ctype.h>
-#include <linux/stat.h>
-
-#include "lock_dlm.h"
-
-static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf)
-{
- return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name);
-}
-
-static ssize_t block_show(struct gdlm_ls *ls, char *buf)
-{
- ssize_t ret;
- int val = 0;
-
- if (test_bit(DFL_BLOCK_LOCKS, &ls->flags))
- val = 1;
- ret = sprintf(buf, "%d\n", val);
- return ret;
-}
-
-static ssize_t block_store(struct gdlm_ls *ls, const char *buf, size_t len)
-{
- ssize_t ret = len;
- int val;
-
- val = simple_strtol(buf, NULL, 0);
-
- if (val == 1)
- set_bit(DFL_BLOCK_LOCKS, &ls->flags);
- else if (val == 0) {
- clear_bit(DFL_BLOCK_LOCKS, &ls->flags);
- gdlm_submit_delayed(ls);
- } else {
- ret = -EINVAL;
- }
- return ret;
-}
-
-static ssize_t withdraw_show(struct gdlm_ls *ls, char *buf)
-{
- ssize_t ret;
- int val = 0;
-
- if (test_bit(DFL_WITHDRAW, &ls->flags))
- val = 1;
- ret = sprintf(buf, "%d\n", val);
- return ret;
-}
-
-static ssize_t withdraw_store(struct gdlm_ls *ls, const char *buf, size_t len)
-{
- ssize_t ret = len;
- int val;
-
- val = simple_strtol(buf, NULL, 0);
-
- if (val == 1)
- set_bit(DFL_WITHDRAW, &ls->flags);
- else
- ret = -EINVAL;
- wake_up(&ls->wait_control);
- return ret;
-}
-
-static ssize_t id_show(struct gdlm_ls *ls, char *buf)
-{
- return sprintf(buf, "%u\n", ls->id);
-}
-
-static ssize_t jid_show(struct gdlm_ls *ls, char *buf)
-{
- return sprintf(buf, "%d\n", ls->jid);
-}
-
-static ssize_t first_show(struct gdlm_ls *ls, char *buf)
-{
- return sprintf(buf, "%d\n", ls->first);
-}
-
-static ssize_t first_done_show(struct gdlm_ls *ls, char *buf)
-{
- return sprintf(buf, "%d\n", ls->first_done);
-}
-
-static ssize_t recover_show(struct gdlm_ls *ls, char *buf)
-{
- return sprintf(buf, "%d\n", ls->recover_jid);
-}
-
-static ssize_t recover_store(struct gdlm_ls *ls, const char *buf, size_t len)
-{
- ls->recover_jid = simple_strtol(buf, NULL, 0);
- ls->fscb(ls->sdp, LM_CB_NEED_RECOVERY, &ls->recover_jid);
- return len;
-}
-
-static ssize_t recover_done_show(struct gdlm_ls *ls, char *buf)
-{
- return sprintf(buf, "%d\n", ls->recover_jid_done);
-}
-
-static ssize_t recover_status_show(struct gdlm_ls *ls, char *buf)
-{
- return sprintf(buf, "%d\n", ls->recover_jid_status);
-}
-
-static ssize_t drop_count_show(struct gdlm_ls *ls, char *buf)
-{
- return sprintf(buf, "%d\n", ls->drop_locks_count);
-}
-
-static ssize_t drop_count_store(struct gdlm_ls *ls, const char *buf, size_t len)
-{
- ls->drop_locks_count = simple_strtol(buf, NULL, 0);
- return len;
-}
-
-struct gdlm_attr {
- struct attribute attr;
- ssize_t (*show)(struct gdlm_ls *, char *);
- ssize_t (*store)(struct gdlm_ls *, const char *, size_t);
-};
-
-#define GDLM_ATTR(_name,_mode,_show,_store) \
-static struct gdlm_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store)
-
-GDLM_ATTR(proto_name, 0444, proto_name_show, NULL);
-GDLM_ATTR(block, 0644, block_show, block_store);
-GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store);
-GDLM_ATTR(id, 0444, id_show, NULL);
-GDLM_ATTR(jid, 0444, jid_show, NULL);
-GDLM_ATTR(first, 0444, first_show, NULL);
-GDLM_ATTR(first_done, 0444, first_done_show, NULL);
-GDLM_ATTR(recover, 0644, recover_show, recover_store);
-GDLM_ATTR(recover_done, 0444, recover_done_show, NULL);
-GDLM_ATTR(recover_status, 0444, recover_status_show, NULL);
-GDLM_ATTR(drop_count, 0644, drop_count_show, drop_count_store);
-
-static struct attribute *gdlm_attrs[] = {
- &gdlm_attr_proto_name.attr,
- &gdlm_attr_block.attr,
- &gdlm_attr_withdraw.attr,
- &gdlm_attr_id.attr,
- &gdlm_attr_jid.attr,
- &gdlm_attr_first.attr,
- &gdlm_attr_first_done.attr,
- &gdlm_attr_recover.attr,
- &gdlm_attr_recover_done.attr,
- &gdlm_attr_recover_status.attr,
- &gdlm_attr_drop_count.attr,
- NULL,
-};
-
-static ssize_t gdlm_attr_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj);
- struct gdlm_attr *a = container_of(attr, struct gdlm_attr, attr);
- return a->show ? a->show(ls, buf) : 0;
-}
-
-static ssize_t gdlm_attr_store(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t len)
-{
- struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj);
- struct gdlm_attr *a = container_of(attr, struct gdlm_attr, attr);
- return a->store ? a->store(ls, buf, len) : len;
-}
-
-static struct sysfs_ops gdlm_attr_ops = {
- .show = gdlm_attr_show,
- .store = gdlm_attr_store,
-};
-
-static struct kobj_type gdlm_ktype = {
- .default_attrs = gdlm_attrs,
- .sysfs_ops = &gdlm_attr_ops,
-};
-
-static struct kset *gdlm_kset;
-
-int gdlm_kobject_setup(struct gdlm_ls *ls, struct kobject *fskobj)
-{
- int error;
-
- ls->kobj.kset = gdlm_kset;
- error = kobject_init_and_add(&ls->kobj, &gdlm_ktype, fskobj,
- "lock_module");
- if (error)
- log_error("can't register kobj %d", error);
- kobject_uevent(&ls->kobj, KOBJ_ADD);
-
- return error;
-}
-
-void gdlm_kobject_release(struct gdlm_ls *ls)
-{
- kobject_put(&ls->kobj);
-}
-
-static int gdlm_uevent(struct kset *kset, struct kobject *kobj,
- struct kobj_uevent_env *env)
-{
- struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj);
- add_uevent_var(env, "LOCKTABLE=%s:%s", ls->clustername, ls->fsname);
- add_uevent_var(env, "LOCKPROTO=lock_dlm");
- return 0;
-}
-
-static struct kset_uevent_ops gdlm_uevent_ops = {
- .uevent = gdlm_uevent,
-};
-
-int gdlm_sysfs_init(void)
-{
- gdlm_kset = kset_create_and_add("lock_dlm_gfs", &gdlm_uevent_ops, kernel_kobj);
- if (!gdlm_kset) {
- printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__);
- return -ENOMEM;
- }
- return 0;
-}
-
-void gdlm_sysfs_exit(void)
-{
- kset_unregister(gdlm_kset);
-}
-
diff --git a/gfs-kernel/src/gfs/lock_dlm_thread.c b/gfs-kernel/src/gfs/lock_dlm_thread.c
deleted file mode 100644
index 58641c7..0000000
--- a/gfs-kernel/src/gfs/lock_dlm_thread.c
+++ /dev/null
@@ -1,358 +0,0 @@
-#include "lock_dlm.h"
-
-/* A lock placed on this queue is re-submitted to DLM as soon as the lock_dlm
- thread gets to it. */
-
-static void queue_submit(struct gdlm_lock *lp)
-{
- struct gdlm_ls *ls = lp->ls;
-
- spin_lock(&ls->async_lock);
- list_add_tail(&lp->delay_list, &ls->submit);
- spin_unlock(&ls->async_lock);
- wake_up(&ls->thread_wait);
-}
-
-static void process_blocking(struct gdlm_lock *lp, int bast_mode)
-{
- struct gdlm_ls *ls = lp->ls;
- unsigned int cb = 0;
-
- switch (gdlm_make_lmstate(bast_mode)) {
- case LM_ST_EXCLUSIVE:
- cb = LM_CB_NEED_E;
- break;
- case LM_ST_DEFERRED:
- cb = LM_CB_NEED_D;
- break;
- case LM_ST_SHARED:
- cb = LM_CB_NEED_S;
- break;
- default:
- gdlm_assert(0, "unknown bast mode %u", lp->bast_mode);
- }
-
- ls->fscb(ls->sdp, cb, &lp->lockname);
-}
-
-static void wake_up_ast(struct gdlm_lock *lp)
-{
- clear_bit(LFL_AST_WAIT, &lp->flags);
- smp_mb__after_clear_bit();
- wake_up_bit(&lp->flags, LFL_AST_WAIT);
-}
-
-static void process_complete(struct gdlm_lock *lp)
-{
- struct gdlm_ls *ls = lp->ls;
- struct lm_async_cb acb;
- s16 prev_mode = lp->cur;
-
- memset(&acb, 0, sizeof(acb));
-
- if (lp->lksb.sb_status == -DLM_ECANCEL) {
- log_info("complete dlm cancel %x,%llx flags %lx",
- lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number,
- lp->flags);
-
- lp->req = lp->cur;
- acb.lc_ret |= LM_OUT_CANCELED;
- if (lp->cur == DLM_LOCK_IV)
- lp->lksb.sb_lkid = 0;
- goto out;
- }
-
- if (test_and_clear_bit(LFL_DLM_UNLOCK, &lp->flags)) {
- if (lp->lksb.sb_status != -DLM_EUNLOCK) {
- log_info("unlock sb_status %d %x,%llx flags %lx",
- lp->lksb.sb_status, lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number,
- lp->flags);
- return;
- }
-
- lp->cur = DLM_LOCK_IV;
- lp->req = DLM_LOCK_IV;
- lp->lksb.sb_lkid = 0;
-
- if (test_and_clear_bit(LFL_UNLOCK_DELETE, &lp->flags)) {
- gdlm_delete_lp(lp);
- return;
- }
- goto out;
- }
-
- if (lp->lksb.sb_flags & DLM_SBF_VALNOTVALID)
- memset(lp->lksb.sb_lvbptr, 0, GDLM_LVB_SIZE);
-
- if (lp->lksb.sb_flags & DLM_SBF_ALTMODE) {
- if (lp->req == DLM_LOCK_PR)
- lp->req = DLM_LOCK_CW;
- else if (lp->req == DLM_LOCK_CW)
- lp->req = DLM_LOCK_PR;
- }
-
- /*
- * A canceled lock request. The lock was just taken off the delayed
- * list and was never even submitted to dlm.
- */
-
- if (test_and_clear_bit(LFL_CANCEL, &lp->flags)) {
- log_info("complete internal cancel %x,%llx",
- lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number);
- lp->req = lp->cur;
- acb.lc_ret |= LM_OUT_CANCELED;
- goto out;
- }
-
- /*
- * An error occured.
- */
-
- if (lp->lksb.sb_status) {
- /* a "normal" error */
- if ((lp->lksb.sb_status == -EAGAIN) &&
- (lp->lkf & DLM_LKF_NOQUEUE)) {
- lp->req = lp->cur;
- if (lp->cur == DLM_LOCK_IV)
- lp->lksb.sb_lkid = 0;
- goto out;
- }
-
- /* this could only happen with cancels I think */
- log_info("ast sb_status %d %x,%llx flags %lx",
- lp->lksb.sb_status, lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number,
- lp->flags);
- return;
- }
-
- /*
- * This is an AST for an EX->EX conversion for sync_lvb from GFS.
- */
-
- if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) {
- wake_up_ast(lp);
- return;
- }
-
- /*
- * A lock has been demoted to NL because it initially completed during
- * BLOCK_LOCKS. Now it must be requested in the originally requested
- * mode.
- */
-
- if (test_and_clear_bit(LFL_REREQUEST, &lp->flags)) {
- gdlm_assert(lp->req == DLM_LOCK_NL, "%x,%llx",
- lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number);
- gdlm_assert(lp->prev_req > DLM_LOCK_NL, "%x,%llx",
- lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number);
-
- lp->cur = DLM_LOCK_NL;
- lp->req = lp->prev_req;
- lp->prev_req = DLM_LOCK_IV;
- lp->lkf &= ~DLM_LKF_CONVDEADLK;
-
- set_bit(LFL_NOCACHE, &lp->flags);
-
- if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) &&
- !test_bit(LFL_NOBLOCK, &lp->flags))
- gdlm_queue_delayed(lp);
- else
- queue_submit(lp);
- return;
- }
-
- /*
- * A request is granted during dlm recovery. It may be granted
- * because the locks of a failed node were cleared. In that case,
- * there may be inconsistent data beneath this lock and we must wait
- * for recovery to complete to use it. When gfs recovery is done this
- * granted lock will be converted to NL and then reacquired in this
- * granted state.
- */
-
- if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) &&
- !test_bit(LFL_NOBLOCK, &lp->flags) &&
- lp->req != DLM_LOCK_NL) {
-
- lp->cur = lp->req;
- lp->prev_req = lp->req;
- lp->req = DLM_LOCK_NL;
- lp->lkf |= DLM_LKF_CONVERT;
- lp->lkf &= ~DLM_LKF_CONVDEADLK;
-
- log_debug("rereq %x,%llx id %x %d,%d",
- lp->lockname.ln_type,
- (unsigned long long)lp->lockname.ln_number,
- lp->lksb.sb_lkid, lp->cur, lp->req);
-
- set_bit(LFL_REREQUEST, &lp->flags);
- queue_submit(lp);
- return;
- }
-
- /*
- * DLM demoted the lock to NL before it was granted so GFS must be
- * told it cannot cache data for this lock.
- */
-
- if (lp->lksb.sb_flags & DLM_SBF_DEMOTED)
- set_bit(LFL_NOCACHE, &lp->flags);
-
-out:
- /*
- * This is an internal lock_dlm lock
- */
-
- if (test_bit(LFL_INLOCK, &lp->flags)) {
- clear_bit(LFL_NOBLOCK, &lp->flags);
- lp->cur = lp->req;
- wake_up_ast(lp);
- return;
- }
-
- /*
- * Normal completion of a lock request. Tell GFS it now has the lock.
- */
-
- clear_bit(LFL_NOBLOCK, &lp->flags);
- lp->cur = lp->req;
-
- acb.lc_name = lp->lockname;
- acb.lc_ret |= gdlm_make_lmstate(lp->cur);
-
- if (!test_and_clear_bit(LFL_NOCACHE, &lp->flags) &&
- (lp->cur > DLM_LOCK_NL) && (prev_mode > DLM_LOCK_NL))
- acb.lc_ret |= LM_OUT_CACHEABLE;
-
- ls->fscb(ls->sdp, LM_CB_ASYNC, &acb);
-}
-
-static inline int no_work(struct gdlm_ls *ls, int blocking)
-{
- int ret;
-
- spin_lock(&ls->async_lock);
- ret = list_empty(&ls->complete) && list_empty(&ls->submit);
- if (ret && blocking)
- ret = list_empty(&ls->blocking);
- spin_unlock(&ls->async_lock);
-
- return ret;
-}
-
-static inline int check_drop(struct gdlm_ls *ls)
-{
- if (!ls->drop_locks_count)
- return 0;
-
- if (time_after(jiffies, ls->drop_time + ls->drop_locks_period * HZ)) {
- ls->drop_time = jiffies;
- if (ls->all_locks_count >= ls->drop_locks_count)
- return 1;
- }
- return 0;
-}
-
-static int gdlm_thread(void *data, int blist)
-{
- struct gdlm_ls *ls = (struct gdlm_ls *) data;
- struct gdlm_lock *lp = NULL;
- uint8_t complete, blocking, submit, drop;
-
- /* Only thread1 is allowed to do blocking callbacks since gfs
- may wait for a completion callback within a blocking cb. */
-
- while (!kthread_should_stop()) {
- wait_event_interruptible(ls->thread_wait,
- !no_work(ls, blist) || kthread_should_stop());
-
- complete = blocking = submit = drop = 0;
-
- spin_lock(&ls->async_lock);
-
- if (blist && !list_empty(&ls->blocking)) {
- lp = list_entry(ls->blocking.next, struct gdlm_lock,
- blist);
- list_del_init(&lp->blist);
- blocking = lp->bast_mode;
- lp->bast_mode = 0;
- } else if (!list_empty(&ls->complete)) {
- lp = list_entry(ls->complete.next, struct gdlm_lock,
- clist);
- list_del_init(&lp->clist);
- complete = 1;
- } else if (!list_empty(&ls->submit)) {
- lp = list_entry(ls->submit.next, struct gdlm_lock,
- delay_list);
- list_del_init(&lp->delay_list);
- submit = 1;
- }
-
- drop = check_drop(ls);
- spin_unlock(&ls->async_lock);
-
- if (complete)
- process_complete(lp);
-
- else if (blocking)
- process_blocking(lp, blocking);
-
- else if (submit)
- gdlm_do_lock(lp);
-
- if (drop)
- ls->fscb(ls->sdp, LM_CB_DROPLOCKS, NULL);
-
- schedule();
- }
-
- return 0;
-}
-
-static int gdlm_thread1(void *data)
-{
- return gdlm_thread(data, 1);
-}
-
-static int gdlm_thread2(void *data)
-{
- return gdlm_thread(data, 0);
-}
-
-int gdlm_init_threads(struct gdlm_ls *ls)
-{
- struct task_struct *p;
- int error;
-
- p = kthread_run(gdlm_thread1, ls, "lock_dlm1");
- error = IS_ERR(p);
- if (error) {
- log_error("can't start lock_dlm1 thread %d", error);
- return error;
- }
- ls->thread1 = p;
-
- p = kthread_run(gdlm_thread2, ls, "lock_dlm2");
- error = IS_ERR(p);
- if (error) {
- log_error("can't start lock_dlm2 thread %d", error);
- kthread_stop(ls->thread1);
- return error;
- }
- ls->thread2 = p;
-
- return 0;
-}
-
-void gdlm_release_threads(struct gdlm_ls *ls)
-{
- kthread_stop(ls->thread1);
- kthread_stop(ls->thread2);
-}
-
diff --git a/gfs-kernel/src/gfs/lock_nolock_main.c b/gfs-kernel/src/gfs/lock_nolock_main.c
deleted file mode 100644
index 18315ef..0000000
--- a/gfs-kernel/src/gfs/lock_nolock_main.c
+++ /dev/null
@@ -1,221 +0,0 @@
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#include "lm_interface.h"
-
-struct nolock_lockspace {
- unsigned int nl_lvb_size;
-};
-
-static const struct lm_lockops nolock_ops;
-
-static int nolock_mount(char *table_name, char *host_data,
- lm_callback_t cb, void *cb_data,
- unsigned int min_lvb_size, int flags,
- struct lm_lockstruct *lockstruct,
- struct kobject *fskobj)
-{
- char *c;
- unsigned int jid;
- struct nolock_lockspace *nl;
-
- c = strstr(host_data, "jid=");
- if (!c)
- jid = 0;
- else {
- c += 4;
- sscanf(c, "%u", &jid);
- }
-
- nl = kzalloc(sizeof(struct nolock_lockspace), GFP_KERNEL);
- if (!nl)
- return -ENOMEM;
-
- nl->nl_lvb_size = min_lvb_size;
-
- lockstruct->ls_jid = jid;
- lockstruct->ls_first = 1;
- lockstruct->ls_lvb_size = min_lvb_size;
- lockstruct->ls_lockspace = nl;
- lockstruct->ls_ops = &nolock_ops;
- lockstruct->ls_flags = LM_LSFLAG_LOCAL;
-
- return 0;
-}
-
-static void nolock_others_may_mount(void *lockspace)
-{
-}
-
-static void nolock_unmount(void *lockspace)
-{
- struct nolock_lockspace *nl = lockspace;
- kfree(nl);
-}
-
-static void nolock_withdraw(void *lockspace)
-{
-}
-
-/**
- * nolock_get_lock - get a lm_lock_t given a descripton of the lock
- * @lockspace: the lockspace the lock lives in
- * @name: the name of the lock
- * @lockp: return the lm_lock_t here
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-static int nolock_get_lock(void *lockspace, struct lm_lockname *name,
- void **lockp)
-{
- *lockp = lockspace;
- return 0;
-}
-
-/**
- * nolock_put_lock - get rid of a lock structure
- * @lock: the lock to throw away
- *
- */
-
-static void nolock_put_lock(void *lock)
-{
-}
-
-/**
- * nolock_lock - acquire a lock
- * @lock: the lock to manipulate
- * @cur_state: the current state
- * @req_state: the requested state
- * @flags: modifier flags
- *
- * Returns: A bitmap of LM_OUT_*
- */
-
-static unsigned int nolock_lock(void *lock, unsigned int cur_state,
- unsigned int req_state, unsigned int flags)
-{
- return req_state | LM_OUT_CACHEABLE;
-}
-
-/**
- * nolock_unlock - unlock a lock
- * @lock: the lock to manipulate
- * @cur_state: the current state
- *
- * Returns: 0
- */
-
-static unsigned int nolock_unlock(void *lock, unsigned int cur_state)
-{
- return 0;
-}
-
-static void nolock_cancel(void *lock)
-{
-}
-
-/**
- * nolock_hold_lvb - hold on to a lock value block
- * @lock: the lock the LVB is associated with
- * @lvbp: return the lm_lvb_t here
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-static int nolock_hold_lvb(void *lock, char **lvbp)
-{
- struct nolock_lockspace *nl = lock;
- int error = 0;
-
- *lvbp = kzalloc(nl->nl_lvb_size, GFP_NOFS);
- if (!*lvbp)
- error = -ENOMEM;
-
- return error;
-}
-
-/**
- * nolock_unhold_lvb - release a LVB
- * @lock: the lock the LVB is associated with
- * @lvb: the lock value block
- *
- */
-
-static void nolock_unhold_lvb(void *lock, char *lvb)
-{
- kfree(lvb);
-}
-
-static int nolock_plock_get(void *lockspace, struct lm_lockname *name,
- struct file *file, struct file_lock *fl)
-{
- posix_test_lock(file, fl);
-
- return 0;
-}
-
-static int nolock_plock(void *lockspace, struct lm_lockname *name,
- struct file *file, int cmd, struct file_lock *fl)
-{
- int error;
- error = posix_lock_file_wait(file, fl);
- return error;
-}
-
-static int nolock_punlock(void *lockspace, struct lm_lockname *name,
- struct file *file, struct file_lock *fl)
-{
- int error;
- error = posix_lock_file_wait(file, fl);
- return error;
-}
-
-static void nolock_recovery_done(void *lockspace, unsigned int jid,
- unsigned int message)
-{
-}
-
-static const struct lm_lockops nolock_ops = {
- .lm_proto_name = "lock_nolock",
- .lm_mount = nolock_mount,
- .lm_others_may_mount = nolock_others_may_mount,
- .lm_unmount = nolock_unmount,
- .lm_withdraw = nolock_withdraw,
- .lm_get_lock = nolock_get_lock,
- .lm_put_lock = nolock_put_lock,
- .lm_lock = nolock_lock,
- .lm_unlock = nolock_unlock,
- .lm_cancel = nolock_cancel,
- .lm_hold_lvb = nolock_hold_lvb,
- .lm_unhold_lvb = nolock_unhold_lvb,
- .lm_plock_get = nolock_plock_get,
- .lm_plock = nolock_plock,
- .lm_punlock = nolock_punlock,
- .lm_recovery_done = nolock_recovery_done,
- .lm_owner = THIS_MODULE,
-};
-
-int init_nolock()
-{
- int error;
-
- error = gfs_register_lockproto(&nolock_ops);
- if (error) {
- printk(KERN_WARNING
- "lock_nolock: can't register protocol: %d\n", error);
- return error;
- }
-
- printk(KERN_INFO
- "Lock_Nolock (built %s %s) installed\n", __DATE__, __TIME__);
- return 0;
-}
-
-void exit_nolock()
-{
- gfs_unregister_lockproto(&nolock_ops);
-}
diff --git a/gfs-kernel/src/gfs/locking.c b/gfs-kernel/src/gfs/locking.c
deleted file mode 100644
index 26c3c51..0000000
--- a/gfs-kernel/src/gfs/locking.c
+++ /dev/null
@@ -1,171 +0,0 @@
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
-#include <linux/kmod.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include "lm_interface.h"
-
-struct lmh_wrapper {
- struct list_head lw_list;
- const struct lm_lockops *lw_ops;
-};
-
-/* List of registered low-level locking protocols. A file system selects one
- of them by name at mount time, e.g. lock_nolock, lock_dlm. */
-
-static LIST_HEAD(lmh_list);
-static DEFINE_MUTEX(lmh_lock);
-
-/**
- * gfs_register_lockproto - Register a low-level locking protocol
- * @proto: the protocol definition
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-int gfs_register_lockproto(const struct lm_lockops *proto)
-{
- struct lmh_wrapper *lw;
-
- mutex_lock(&lmh_lock);
-
- list_for_each_entry(lw, &lmh_list, lw_list) {
- if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) {
- mutex_unlock(&lmh_lock);
- printk(KERN_INFO "GFS2: protocol %s already exists\n",
- proto->lm_proto_name);
- return -EEXIST;
- }
- }
-
- lw = kzalloc(sizeof(struct lmh_wrapper), GFP_KERNEL);
- if (!lw) {
- mutex_unlock(&lmh_lock);
- return -ENOMEM;
- }
-
- lw->lw_ops = proto;
- list_add(&lw->lw_list, &lmh_list);
-
- mutex_unlock(&lmh_lock);
-
- return 0;
-}
-
-/**
- * gfs_unregister_lockproto - Unregister a low-level locking protocol
- * @proto: the protocol definition
- *
- */
-
-void gfs_unregister_lockproto(const struct lm_lockops *proto)
-{
- struct lmh_wrapper *lw;
-
- mutex_lock(&lmh_lock);
-
- list_for_each_entry(lw, &lmh_list, lw_list) {
- if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) {
- list_del(&lw->lw_list);
- mutex_unlock(&lmh_lock);
- kfree(lw);
- return;
- }
- }
-
- mutex_unlock(&lmh_lock);
-
- printk(KERN_WARNING "GFS2: can't unregister lock protocol %s\n",
- proto->lm_proto_name);
-}
-
-/**
- * gfs_mount_lockproto - Mount a lock protocol
- * @proto_name - the name of the protocol
- * @table_name - the name of the lock space
- * @host_data - data specific to this host
- * @cb - the callback to the code using the lock module
- * @sdp - The GFS2 superblock
- * @min_lvb_size - the mininum LVB size that the caller can deal with
- * @flags - LM_MFLAG_*
- * @lockstruct - a structure returned describing the mount
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-int gfs_mount_lockproto(char *proto_name, char *table_name, char *host_data,
- lm_callback_t cb, void *cb_data,
- unsigned int min_lvb_size, int flags,
- struct lm_lockstruct *lockstruct,
- struct kobject *fskobj)
-{
- struct lmh_wrapper *lw = NULL;
- int try = 0;
- int error, found;
-
-retry:
- mutex_lock(&lmh_lock);
-
- found = 0;
- list_for_each_entry(lw, &lmh_list, lw_list) {
- if (!strcmp(lw->lw_ops->lm_proto_name, proto_name)) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- if (!try && capable(CAP_SYS_MODULE)) {
- try = 1;
- mutex_unlock(&lmh_lock);
- request_module(proto_name);
- goto retry;
- }
- printk(KERN_INFO "GFS2: can't find protocol %s\n", proto_name);
- error = -ENOENT;
- goto out;
- }
-
- if (!try_module_get(lw->lw_ops->lm_owner)) {
- try = 0;
- mutex_unlock(&lmh_lock);
- msleep(1000);
- goto retry;
- }
-
- error = lw->lw_ops->lm_mount(table_name, host_data, cb, cb_data,
- min_lvb_size, flags, lockstruct, fskobj);
- if (error)
- module_put(lw->lw_ops->lm_owner);
-out:
- mutex_unlock(&lmh_lock);
- return error;
-}
-
-void gfs_unmount_lockproto(struct lm_lockstruct *lockstruct)
-{
- mutex_lock(&lmh_lock);
- lockstruct->ls_ops->lm_unmount(lockstruct->ls_lockspace);
- if (lockstruct->ls_ops->lm_owner)
- module_put(lockstruct->ls_ops->lm_owner);
- mutex_unlock(&lmh_lock);
-}
-
-/**
- * gfs_withdraw_lockproto - abnormally unmount a lock module
- * @lockstruct: the lockstruct passed into mount
- *
- */
-
-void gfs_withdraw_lockproto(struct lm_lockstruct *lockstruct)
-{
- mutex_lock(&lmh_lock);
- lockstruct->ls_ops->lm_withdraw(lockstruct->ls_lockspace);
- if (lockstruct->ls_ops->lm_owner)
- module_put(lockstruct->ls_ops->lm_owner);
- mutex_unlock(&lmh_lock);
-}
diff --git a/gfs-kernel/src/gfs/log.c b/gfs-kernel/src/gfs/log.c
deleted file mode 100644
index f8f2f6c..0000000
--- a/gfs-kernel/src/gfs/log.c
+++ /dev/null
@@ -1,1424 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "dio.h"
-#include "log.h"
-#include "lops.h"
-
-/**
- * gfs_struct2blk - compute stuff
- * @sdp: the filesystem
- * @nstruct: the number of structures
- * @ssize: the size of the structures
- *
- * Compute the number of log descriptor blocks needed to hold a certain number
- * of structures of a certain size.
- *
- * Returns: the number of blocks needed (minimum is always 1)
- */
-
-unsigned int
-gfs_struct2blk(struct gfs_sbd *sdp, unsigned int nstruct, unsigned int ssize)
-{
- unsigned int blks;
- unsigned int first, second;
-
- blks = 1;
- first = (sdp->sd_sb.sb_bsize - sizeof(struct gfs_log_descriptor)) / ssize;
-
- if (nstruct > first) {
- second = sdp->sd_sb.sb_bsize / ssize;
- blks += DIV_RU(nstruct - first, second);
- }
-
- return blks;
-}
-
-/**
- * gfs_blk2seg - Convert number of blocks into number of segments
- * @sdp: The GFS superblock
- * @blocks: The number of blocks
- *
- * Returns: The number of journal segments
- */
-
-unsigned int
-gfs_blk2seg(struct gfs_sbd *sdp, unsigned int blocks)
-{
- return DIV_RU(blocks, sdp->sd_sb.sb_seg_size - 1);
-}
-
-/**
- * log_distance - Compute distance between two journal blocks
- * @sdp: The GFS superblock
- * @newer: The most recent journal block of the pair
- * @older: The older journal block of the pair
- *
- * Compute the distance (in the journal direction) between two
- * blocks in the journal
- *
- * Returns: the distance in blocks
- */
-
-static __inline__ unsigned int
-log_distance(struct gfs_sbd *sdp, uint64_t newer, uint64_t older)
-{
- int64_t dist;
-
- dist = newer - older;
- if (dist < 0)
- dist += sdp->sd_jdesc.ji_nsegment * sdp->sd_sb.sb_seg_size;
-
- return dist;
-}
-
-/**
- * log_incr_head - Increment journal head (next block to fill in journal)
- * @sdp: The GFS superblock
- * @head: the variable holding the head of the journal
- *
- * Increment journal head by one.
- * At the end of the journal, wrap head back to the start.
- * Don't confuse journal/log head with a gfs_log_header!
- */
-
-static __inline__ void
-log_incr_head(struct gfs_sbd *sdp, uint64_t * head)
-{
- struct gfs_jindex *jdesc = &sdp->sd_jdesc;
-
- if (++*head ==
- jdesc->ji_addr + jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size)
- *head = jdesc->ji_addr;
-}
-
-/**
- * gfs_ail_start - Start I/O on the AIL
- * @sdp: the filesystem
- * @flags: DIO_ALL -- flush *all* AIL transactions to disk
- * default -- flush first-on-list AIL transaction to disk
- *
- */
-
-void
-gfs_ail_start(struct gfs_sbd *sdp, int flags)
-{
- struct list_head *head = &sdp->sd_log_ail;
- struct list_head *first, *tmp;
- struct gfs_trans *first_tr, *tr;
-
- gfs_log_lock(sdp);
-
- if (list_empty(head)) {
- gfs_log_unlock(sdp);
- return;
- }
-
- first = head->prev;
- first_tr = list_entry(first, struct gfs_trans, tr_list);
- gfs_ail_start_trans(sdp, first_tr);
-
- if (flags & DIO_ALL)
- first_tr = NULL;
-
- for (tmp = first->prev; tmp != head; tmp = tmp->prev) {
- if (first_tr && gfs_ail_empty_trans(sdp, first_tr))
- break;
-
- tr = list_entry(tmp, struct gfs_trans, tr_list);
- gfs_ail_start_trans(sdp, tr);
- }
-
- gfs_log_unlock(sdp);
-}
-
-/**
- * current_tail - Find block number of current log tail
- * @sdp: The GFS superblock
- *
- * Find the block number of the current tail of the log.
- * Assumes that the log lock is held.
- *
- * Returns: The tail's block number (must be on a log segment boundary)
- */
-
-static uint64_t
-current_tail(struct gfs_sbd *sdp)
-{
- struct gfs_trans *tr;
- uint64_t tail;
-
- if (list_empty(&sdp->sd_log_ail)) {
- tail = sdp->sd_log_head;
-
- if (!gfs_log_is_header(sdp, tail)) {
- tail--;
- gfs_assert(sdp, gfs_log_is_header(sdp, tail), );
- }
- } else {
- tr = list_entry(sdp->sd_log_ail.prev,
- struct gfs_trans, tr_list);
- tail = tr->tr_first_head;
- }
-
- return tail;
-}
-
-/**
- * gfs_ail_empty - move the tail of the log forward (if possible)
- * @sdp: the filesystem
- *
- * Returns: TRUE if the AIL is empty
- *
- * Checks each transaction on sd_log_ail, to see if it has been successfully
- * flushed to in-place blocks on disk. If so, removes trans from sd_log_ail,
- * effectively advancing the tail of the log (freeing log segments so they
- * can be overwritten).
- * Adds # freed log segments to sd_log_seg_free.
- */
-
-int
-gfs_ail_empty(struct gfs_sbd *sdp)
-{
- struct list_head *head, *tmp, *prev;
- struct gfs_trans *tr;
- uint64_t oldtail, newtail;
- unsigned int dist;
- unsigned int segments;
- int ret;
-
- gfs_log_lock(sdp);
-
- oldtail = current_tail(sdp);
-
- for (head = &sdp->sd_log_ail, tmp = head->prev, prev = tmp->prev;
- tmp != head;
- tmp = prev, prev = tmp->prev) {
- tr = list_entry(tmp, struct gfs_trans, tr_list);
- if (gfs_ail_empty_trans(sdp, tr)) {
- list_del(&tr->tr_list);
- kfree(tr);
- }
- }
-
- newtail = current_tail(sdp);
-
- if (oldtail != newtail) {
- dist = log_distance(sdp, newtail, oldtail);
-
- segments = dist / sdp->sd_sb.sb_seg_size;
- gfs_assert(sdp, segments * sdp->sd_sb.sb_seg_size == dist,);
-
- sdp->sd_log_seg_ail2 += segments;
- gfs_assert(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 <=
- sdp->sd_jdesc.ji_nsegment,);
- }
-
- ret = list_empty(head);
-
- gfs_log_unlock(sdp);
-
- return ret;
-}
-
-/**
- * gfs_log_reserve - Make a log reservation
- * @sdp: The GFS superblock
- * @segments: The number of segments to reserve
- * @jump_queue: if TRUE, don't care about fairness ordering
- *
- * Returns: errno
- */
-
-int
-gfs_log_reserve(struct gfs_sbd *sdp, unsigned int segments, int jump_queue)
-{
- struct list_head list;
- unsigned int try = 0;
-
- if (gfs_assert_warn(sdp, segments))
- return -EINVAL;
- if (gfs_assert_warn(sdp, segments < sdp->sd_jdesc.ji_nsegment))
- return -EINVAL;
-
- INIT_LIST_HEAD(&list);
-
- for (;;) {
- spin_lock(&sdp->sd_log_seg_lock);
-
- if (list_empty(&list)) {
- if (jump_queue)
- list_add(&list, &sdp->sd_log_seg_list);
- else {
- list_add_tail(&list, &sdp->sd_log_seg_list);
- while (sdp->sd_log_seg_list.next != &list) {
- DECLARE_WAITQUEUE(__wait_chan, current);
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&sdp->sd_log_seg_wait,
- &__wait_chan);
- spin_unlock(&sdp->sd_log_seg_lock);
- schedule();
- spin_lock(&sdp->sd_log_seg_lock);
- remove_wait_queue(&sdp->sd_log_seg_wait,
- &__wait_chan);
- set_current_state(TASK_RUNNING);
- }
- }
- }
-
- if (sdp->sd_log_seg_free > segments) {
- sdp->sd_log_seg_free -= segments;
- list_del(&list);
- spin_unlock(&sdp->sd_log_seg_lock);
- wake_up(&sdp->sd_log_seg_wait);
- break;
- }
-
- spin_unlock(&sdp->sd_log_seg_lock);
-
- if (try) {
- gfs_log_flush(sdp);
- gfs_ail_start(sdp, 0);
- }
-
- gfs_ail_empty(sdp);
-
- try++;
- yield();
- }
-
- return 0;
-}
-
-/**
- * gfs_log_release - Release a given number of log segments
- * @sdp: The GFS superblock
- * @segments: The number of segments
- *
- */
-
-void
-gfs_log_release(struct gfs_sbd *sdp, unsigned int segments)
-{
- spin_lock(&sdp->sd_log_seg_lock);
- sdp->sd_log_seg_free += segments;
- gfs_assert(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 <=
- sdp->sd_jdesc.ji_nsegment,);
- spin_unlock(&sdp->sd_log_seg_lock);
-}
-
-/**
- * log_get_header - Get and initialize a journal header buffer
- * @sdp: The GFS superblock
- * @tr: The transaction that needs a log header
- * @next: FALSE if this log header appears in midst of current transaction
- * TRUE if this starts next transaction (and commits current trans)
- *
- * Returns: the initialized log buffer descriptor
- *
- * Initialize one of the transaction's pre-allocated buffers (and associated
- * log buffer descriptor) to be a log header for this transaction.
- * A log header gets written to *each* log segment boundary block, so journal
- * recovery will quickly be able to get its bearings. A single transaction
- * may span several log segments, which means that log headers will appear
- * in the midst of that transaction (@next == FALSE). These headers get
- * added to trans' list of buffers to write to log.
- * Log commit is accomplished by writing the log header for the next
- * transaction (@next == TRUE), with pre-incremented sequence number,
- * and updated first-in-transaction block number. These headers do *not* get
- * added to trans' buffer list, since they are written separately to disk
- * *after* the trans gets completely flushed to on-disk log.
- * NOTE: This buffer will *not* get written to an in-place location in the
- * filesystem; it is for use only within the log.
- */
-
-static struct gfs_log_buf *
-log_get_header(struct gfs_sbd *sdp, struct gfs_trans *tr, int next)
-{
- struct gfs_log_buf *lb;
- struct list_head *bmem;
- struct gfs_log_header header;
-
- /* Make sure we're on a log segment boundary block */
- gfs_assert(sdp, gfs_log_is_header(sdp, tr->tr_log_head),);
-
- /* Grab a free log buffer descriptor (attached to trans) */
- gfs_assert(sdp, tr->tr_num_free_bufs &&
- !list_empty(&tr->tr_free_bufs),);
- lb = list_entry(tr->tr_free_bufs.next, struct gfs_log_buf, lb_list);
- list_del(&lb->lb_list);
- tr->tr_num_free_bufs--;
-
- /* Grab a free log buffer (attached to trans) */
- gfs_assert(sdp, tr->tr_num_free_bmem &&
- !list_empty(&tr->tr_free_bmem),);
- bmem = tr->tr_free_bmem.next;
- list_del(bmem);
- tr->tr_num_free_bmem--;
-
- /* Create "fake" bh to write bmem to log header block */
- gfs_logbh_init(sdp, &lb->lb_bh, tr->tr_log_head, (char *)bmem);
- memset(bmem, 0, sdp->sd_sb.sb_bsize);
-
- memset(&header, 0, sizeof (header));
-
- if (next) {
- /* Fill in header for next transaction, committing previous */
- header.lh_header.mh_magic = GFS_MAGIC;
- header.lh_header.mh_type = GFS_METATYPE_LH;
- header.lh_header.mh_format = GFS_FORMAT_LH;
- header.lh_first = tr->tr_log_head;
- header.lh_sequence = sdp->sd_sequence + 1;
- header.lh_tail = current_tail(sdp);
- header.lh_last_dump = sdp->sd_log_dump_last;
- } else {
- /* Fill in another header for this transaction */
- header.lh_header.mh_magic = GFS_MAGIC;
- header.lh_header.mh_type = GFS_METATYPE_LH;
- header.lh_header.mh_format = GFS_FORMAT_LH;
- header.lh_first = tr->tr_first_head;
- header.lh_sequence = sdp->sd_sequence;
- header.lh_tail = current_tail(sdp);
- header.lh_last_dump = sdp->sd_log_dump_last;
-
- /* Attach log header buf to trans' list of bufs going to log */
- list_add(&lb->lb_list, &tr->tr_bufs);
- }
-
- /* Copy log header struct to beginning and end of buffer's 1st 512B */
- gfs_log_header_out(&header, lb->lb_bh.b_data);
- gfs_log_header_out(&header,
- lb->lb_bh.b_data + GFS_BASIC_BLOCK -
- sizeof(struct gfs_log_header));
-
- /* Find next log buffer to fill */
- log_incr_head(sdp, &tr->tr_log_head);
-
- return lb;
-}
-
-/**
- * gfs_log_get_buf - Get and initialize a buffer to use for log control data
- * @sdp: The GFS superblock
- * @tr: The GFS transaction
- *
- * Initialize one of the transaction's pre-allocated buffers (and associated
- * log buffer descriptor) to be used for log control data (e.g. log tags).
- * Make sure this buffer is attached to the transaction, to be logged to disk.
- * NOTE: This buffer will *not* get written to an in-place location in the
- * filesystem; it is for use only within the log.
- *
- * Returns: the log buffer descriptor
- */
-
-struct gfs_log_buf *
-gfs_log_get_buf(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct gfs_log_buf *lb;
- struct list_head *bmem;
-
- /* If next block in log is on a segment boundary, we need to
- write a log header */
- if (gfs_log_is_header(sdp, tr->tr_log_head))
- log_get_header(sdp, tr, FALSE);
-
- /* Grab a free buffer descriptor (attached to trans) */
- gfs_assert(sdp, tr->tr_num_free_bufs &&
- !list_empty(&tr->tr_free_bufs),);
- lb = list_entry(tr->tr_free_bufs.next, struct gfs_log_buf, lb_list);
- list_del(&lb->lb_list);
- tr->tr_num_free_bufs--;
-
- /* Grab a free buffer (attached to trans) */
- gfs_assert(sdp, tr->tr_num_free_bmem
- && !list_empty(&tr->tr_free_bmem),);
- bmem = tr->tr_free_bmem.next;
- list_del(bmem);
- tr->tr_num_free_bmem--;
-
- /* Create "fake" bh to write bmem to log block */
- gfs_logbh_init(sdp, &lb->lb_bh, tr->tr_log_head, (char *)bmem);
- memset(bmem, 0, sdp->sd_sb.sb_bsize);
-
- list_add(&lb->lb_list, &tr->tr_bufs);
-
- /* Find next log buffer to fill */
- log_incr_head(sdp, &tr->tr_log_head);
-
- return lb;
-}
-
-/**
- * gfs_log_fake_buf - Build a fake buffer head to write metadata buffer to log
- * @sdp: the filesystem
- * @tr: the transaction this is part of
- * @data: the data the buffer_head should point to
- * @unlock: a buffer_head to be unlocked when struct gfs_log_buf is torn down
- * (i.e. the "real" buffer_head that will write to in-place location)
- *
- * Initialize one of the transaction's pre-allocated log buffer descriptors
- * to be used for writing a metadata buffer into the log.
- * Make sure this buffer is attached to the transaction, to be logged to disk.
- * NOTE: This buffer *will* be written to in-place location within filesytem,
- * in addition to being written into the log.
- *
- */
-
-void
-gfs_log_fake_buf(struct gfs_sbd *sdp, struct gfs_trans *tr, char *data,
- struct buffer_head *unlock)
-{
- struct gfs_log_buf *lb;
-
- if (gfs_log_is_header(sdp, tr->tr_log_head))
- log_get_header(sdp, tr, FALSE);
-
- /* Grab a free buffer descriptor (attached to trans) */
- gfs_assert(sdp, tr->tr_num_free_bufs &&
- !list_empty(&tr->tr_free_bufs),);
- lb = list_entry(tr->tr_free_bufs.next, struct gfs_log_buf, lb_list);
- list_del(&lb->lb_list);
- tr->tr_num_free_bufs--;
-
- /* Create "fake" bh to write data to log block */
- gfs_logbh_init(sdp, &lb->lb_bh, tr->tr_log_head, data);
- lb->lb_unlock = unlock;
-
- list_add(&lb->lb_list, &tr->tr_bufs);
-
- /* Find next log buffer to fill */
- log_incr_head(sdp, &tr->tr_log_head);
-}
-
-/**
- * check_seg_usage - Check that we didn't use too many segments
- * @sdp: The GFS superblock
- * @tr: The transaction
- *
- * Also, make sure we don't write ever get to a point where there are
- * no dumps in the log (corrupting the log). Panic before we let
- * that happen.
- *
- */
-
-static void
-check_seg_usage(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct gfs_jindex *jdesc = &sdp->sd_jdesc;
- unsigned int dist;
- unsigned int segments;
- uint64_t head_off, head_wrap;
- uint64_t dump_off, dump_wrap;
-
- dist = log_distance(sdp, tr->tr_log_head, tr->tr_first_head);
-
- segments = dist / sdp->sd_sb.sb_seg_size;
- gfs_assert(sdp, segments * sdp->sd_sb.sb_seg_size == dist,);
- gfs_assert(sdp, segments == tr->tr_seg_reserved,);
-
- if (sdp->sd_log_dump_last) {
- int diff;
-
- head_off = tr->tr_first_head +
- tr->tr_seg_reserved * sdp->sd_sb.sb_seg_size;
- head_wrap = sdp->sd_log_wrap;
- if (head_off >= jdesc->ji_addr +
- jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size) {
- head_off -= jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size;
- head_wrap++;
- }
-
- dump_off = sdp->sd_log_dump_last;
- dump_wrap = sdp->sd_log_dump_last_wrap;
-
- diff = (int)(head_wrap - dump_wrap);
- switch (diff) {
- case 0:
- break;
-
- case 1:
- if (head_off < dump_off - sdp->sd_sb.sb_seg_size)
- break;
- else if (head_off <= dump_off &&
- (tr->tr_flags & TRF_LOG_DUMP))
- break;
-
- default:
- gfs_assert(sdp, FALSE,
- printk("GFS: fsid=%s: head_off = %llu, head_wrap = %llu\n"
- "GFS: fsid=%s: dump_off = %llu, dump_wrap = %llu\n",
- sdp->sd_fsname,
- (unsigned long long)head_off,
- (unsigned long long)head_wrap,
- sdp->sd_fsname,
- (unsigned long long)dump_off,
- (unsigned long long)dump_wrap););
- break;
- }
- }
-}
-
-/**
- * log_free_buf - Free a struct gfs_log_buf (and possibly the data it points to)
- * @sdp: the filesystem
- * @lb: the log buffer descriptor
- *
- * If buffer contains (meta)data to be written into filesystem in-place block,
- * descriptor will point to the "real" (lb_unlock) buffer head. Unlock it.
- * If buffer was used only for log header or control data (e.g. tags), we're
- * done with it as soon as it gets written to on-disk log. Free it.
- * Either way, we can free the log descriptor structure.
- */
-
-static void
-log_free_buf(struct gfs_sbd *sdp, struct gfs_log_buf *lb)
-{
- char *bmem;
-
- bmem = lb->lb_bh.b_data;
- gfs_logbh_uninit(sdp, &lb->lb_bh);
-
- if (lb->lb_unlock)
- gfs_unlock_buffer(lb->lb_unlock);
- else
- kfree(bmem);
-
- kfree(lb);
-}
-
-/**
- * sync_trans - Add "last" descriptor, sync transaction to on-disk log
- * @sdp: The GFS superblock
- * @tr: The transaction
- *
- * Add the "last" descriptor onto the end of the current transaction
- * and sync the whole transaction out to on-disk log.
- * Don't log-commit (i.e. write next transaction's log header) yet, though.
- *
- * Returns: errno
- */
-
-static int
-sync_trans(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct list_head *tmp, *head, *prev;
- struct gfs_log_descriptor desc;
- struct gfs_log_buf *lb;
- uint64_t blk;
- int error = 0, e;
-
- /* Build LAST descriptor */
-
- lb = gfs_log_get_buf(sdp, tr);
-
- memset(&desc, 0, sizeof(struct gfs_log_descriptor));
- desc.ld_header.mh_magic = GFS_MAGIC;
- desc.ld_header.mh_type = GFS_METATYPE_LD;
- desc.ld_header.mh_format = GFS_FORMAT_LD;
- desc.ld_type = GFS_LOG_DESC_LAST;
- desc.ld_length = 1;
- for (blk = tr->tr_log_head; !gfs_log_is_header(sdp, blk); blk++)
- desc.ld_length++;
- gfs_desc_out(&desc, lb->lb_bh.b_data);
-
- while (!gfs_log_is_header(sdp, tr->tr_log_head))
- log_incr_head(sdp, &tr->tr_log_head);
-
- check_seg_usage(sdp, tr);
-
- /* Start I/O
- Go in "prev" direction to start the I/O in order. */
-
- for (head = &tr->tr_bufs, tmp = head->prev, prev = tmp->prev;
- tmp != head;
- tmp = prev, prev = tmp->prev) {
- lb = list_entry(tmp, struct gfs_log_buf, lb_list);
- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
- gfs_logbh_start(sdp, &lb->lb_bh);
- } else {
- list_del(&lb->lb_list);
- log_free_buf(sdp, lb);
- error = -EIO;
- }
- }
-
- /* Wait on I/O
- Go in "next" direction to minimize sleeps/wakeups. */
-
- while (!list_empty(&tr->tr_bufs)) {
- lb = list_entry(tr->tr_bufs.next, struct gfs_log_buf, lb_list);
-
- e = gfs_logbh_wait(sdp, &lb->lb_bh);
- if (e)
- error = e;
-
- list_del(&lb->lb_list);
- log_free_buf(sdp, lb);
- }
-
- return error;
-}
-
-/**
- * commit_trans - Commit the current transaction
- * @sdp: The GFS superblock
- * @tr: The transaction
- *
- * Write next header to commit
- *
- * Returns: errno
- */
-
-static int
-commit_trans(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct gfs_log_buf *lb;
- int error = 0;
-
- lb = log_get_header(sdp, tr, TRUE);
-
- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
- gfs_logbh_start(sdp, &lb->lb_bh);
- error = gfs_logbh_wait(sdp, &lb->lb_bh);
- }
- if (!error) {
- spin_lock(&sdp->sd_log_seg_lock);
- if (!(tr->tr_flags & TRF_DUMMY))
- sdp->sd_log_seg_free += sdp->sd_log_seg_ail2;
- else
- sdp->sd_log_seg_free += (sdp->sd_log_seg_ail2 - 1);
- sdp->sd_log_seg_ail2 = 0;
- spin_unlock(&sdp->sd_log_seg_lock);
- }
- log_free_buf(sdp, lb);
-
- return error;
-}
-
-/**
- * disk_commit - Write a transaction to the on-disk journal
- * @sdp: The GFS superblock
- * @tr: The transaction
- *
- * Returns: errno
- */
-
-static int
-disk_commit(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- uint64_t last_dump, last_dump_wrap;
- int error = 0;
-
- gfs_assert(sdp, !test_bit(SDF_ROFS, &sdp->sd_flags),);
- tr->tr_log_head = sdp->sd_log_head;
- tr->tr_first_head = tr->tr_log_head - 1;
- gfs_assert(sdp, gfs_log_is_header(sdp, tr->tr_first_head),);
-
- LO_BUILD_BHLIST(sdp, tr);
-
- if (!(tr->tr_flags & TRF_DUMMY))
- gfs_assert(sdp, !list_empty(&tr->tr_bufs),);
-
- error = sync_trans(sdp, tr);
- if (error) {
- /* Eat unusable commit buffer */
- log_free_buf(sdp, log_get_header(sdp, tr, TRUE));
- goto out;
- }
-
- if (tr->tr_flags & TRF_LOG_DUMP) {
- /* This commit header should point to the log dump we're
- commiting as the current one. But save the copy of the
- old one in case we have problems commiting the dump. */
-
- last_dump = sdp->sd_log_dump_last;
- last_dump_wrap = sdp->sd_log_dump_last_wrap;
-
- sdp->sd_log_dump_last = tr->tr_first_head;
- sdp->sd_log_dump_last_wrap = sdp->sd_log_wrap;
-
- error = commit_trans(sdp, tr);
- if (error) {
- sdp->sd_log_dump_last = last_dump;
- sdp->sd_log_dump_last_wrap = last_dump_wrap;
- goto out;
- }
- } else {
- error = commit_trans(sdp, tr);
- if (error)
- goto out;
- }
-
- if (sdp->sd_log_head > tr->tr_log_head)
- sdp->sd_log_wrap++;
- sdp->sd_log_head = tr->tr_log_head;
- sdp->sd_sequence++;
-
- out:
- gfs_assert_warn(sdp, !tr->tr_num_free_bufs &&
- list_empty(&tr->tr_free_bufs));
- gfs_assert_warn(sdp, !tr->tr_num_free_bmem &&
- list_empty(&tr->tr_free_bmem));
-
- return error;
-}
-
-/**
- * add_trans_to_ail - Add a ondisk commited transaction to the AIL
- * @sdp: the filesystem
- * @tr: the transaction
- *
- */
-
-static void
-add_trans_to_ail(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct gfs_log_element *le;
-
- while (!list_empty(&tr->tr_elements)) {
- le = list_entry(tr->tr_elements.next,
- struct gfs_log_element, le_list);
- LO_ADD_TO_AIL(sdp, le);
- }
-
- list_add(&tr->tr_list, &sdp->sd_log_ail);
-}
-
-/**
- * log_refund - Refund log segments to the free pool
- * @sdp: The GFS superblock
- * @tr: The transaction to examine
- *
- * Look at the number of segments reserved for this transaction and the
- * number of segments actually needed for it. If they aren't the
- * same, refund the difference to the free segment pool.
- *
- * De-alloc any unneeded log buffers and log buffer descriptors.
- *
- * Called with the log lock held.
- */
-
-static void
-log_refund(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct gfs_log_buf *lb;
- struct list_head *bmem;
- unsigned int num_bufs = 0, num_bmem = 0;
- unsigned int segments;
-
- LO_TRANS_SIZE(sdp, tr, NULL, NULL, &num_bufs, &num_bmem);
-
- segments = gfs_blk2seg(sdp, num_bufs + 1);
- num_bufs += segments + 1;
- num_bmem += segments + 1;
-
- /* Unreserve unneeded log segments */
- if (tr->tr_seg_reserved > segments) {
- spin_lock(&sdp->sd_log_seg_lock);
- sdp->sd_log_seg_free += tr->tr_seg_reserved - segments;
- gfs_assert(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 <=
- sdp->sd_jdesc.ji_nsegment,);
- spin_unlock(&sdp->sd_log_seg_lock);
-
- tr->tr_seg_reserved = segments;
- } else
- gfs_assert(sdp, tr->tr_seg_reserved == segments,);
-
- /* De-alloc unneeded log buffer descriptors */
- gfs_assert(sdp, tr->tr_num_free_bufs >= num_bufs,);
- while (tr->tr_num_free_bufs > num_bufs) {
- lb = list_entry(tr->tr_free_bufs.next,
- struct gfs_log_buf, lb_list);
- list_del(&lb->lb_list);
- kfree(lb);
- tr->tr_num_free_bufs--;
- }
-
- /* De-alloc unneeded log buffers */
- gfs_assert(sdp, tr->tr_num_free_bmem >= num_bmem,);
- while (tr->tr_num_free_bmem > num_bmem) {
- bmem = tr->tr_free_bmem.next;
- list_del(bmem);
- kfree(bmem);
- tr->tr_num_free_bmem--;
- }
-}
-
-/**
- * trans_combine - combine two transactions
- * @sdp: the filesystem
- * @tr: the surviving transaction
- * @new_tr: the transaction that gets freed
- *
- * Assumes that the two transactions are independent.
- */
-
-static void
-trans_combine(struct gfs_sbd *sdp, struct gfs_trans *tr,
- struct gfs_trans *new_tr)
-{
- struct gfs_log_element *le;
- struct gfs_log_buf *lb;
- struct list_head *bmem;
-
- tr->tr_file = __FILE__;
- tr->tr_line = __LINE__;
- tr->tr_seg_reserved += new_tr->tr_seg_reserved;
- tr->tr_flags |= new_tr->tr_flags;
- tr->tr_num_free_bufs += new_tr->tr_num_free_bufs;
- tr->tr_num_free_bmem += new_tr->tr_num_free_bmem;
-
- /* Combine the log elements of the two transactions */
-
- while (!list_empty(&new_tr->tr_elements)) {
- le = list_entry(new_tr->tr_elements.next,
- struct gfs_log_element, le_list);
- gfs_assert(sdp, le->le_trans == new_tr,);
- le->le_trans = tr;
- list_move(&le->le_list, &tr->tr_elements);
- }
-
- LO_TRANS_COMBINE(sdp, tr, new_tr);
-
- /* Move free log buffer descriptors to surviving trans */
- while (!list_empty(&new_tr->tr_free_bufs)) {
- lb = list_entry(new_tr->tr_free_bufs.next,
- struct gfs_log_buf, lb_list);
- list_move(&lb->lb_list, &tr->tr_free_bufs);
- new_tr->tr_num_free_bufs--;
- }
- /* Move free log buffers to surviving trans */
- while (!list_empty(&new_tr->tr_free_bmem)) {
- bmem = new_tr->tr_free_bmem.next;
- list_move(bmem, &tr->tr_free_bmem);
- new_tr->tr_num_free_bmem--;
- }
-
- gfs_assert_warn(sdp, !new_tr->tr_num_free_bufs);
- gfs_assert_warn(sdp, !new_tr->tr_num_free_bmem);
-
- kfree(new_tr);
-}
-
-static void
-make_dummy_transaction(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct gfs_log_buf *lb;
- struct list_head *bmem;
-
- memset(tr, 0, sizeof(struct gfs_trans));
- INIT_LIST_HEAD(&tr->tr_list);
- INIT_LIST_HEAD(&tr->tr_elements);
- INIT_LIST_HEAD(&tr->tr_free_bufs);
- INIT_LIST_HEAD(&tr->tr_free_bmem);
- INIT_LIST_HEAD(&tr->tr_bufs);
- INIT_LIST_HEAD(&tr->tr_ail_bufs);
- tr->tr_flags = TRF_DUMMY;
- tr->tr_file = __FILE__;
- tr->tr_line = __LINE__;
- tr->tr_seg_reserved = 1;
- while (tr->tr_num_free_bufs < 2) {
- lb = gmalloc(sizeof(struct gfs_log_buf));
- memset(lb, 0, sizeof(struct gfs_log_buf));
- list_add(&lb->lb_list, &tr->tr_free_bufs);
- tr->tr_num_free_bufs++;
- }
- while (tr->tr_num_free_bmem < 2) {
- bmem = gmalloc(sdp->sd_sb.sb_bsize);
- list_add(bmem, &tr->tr_free_bmem);
- tr->tr_num_free_bmem++;
- }
-}
-
-
-/**
- * log_flush_internal - flush incore transaction(s)
- * @sdp: the filesystem
- * @gl: The glock structure to flush. If NULL, flush the whole incore log
- *
- * If a glock is provided, we flush, to on-disk log, all of the metadata for
- * the one incore-committed (complete, but not-yet-flushed-to-log)
- * transaction that the glock protects.
- * If NULL, we combine *all* of the filesystem's incore-committed
- * transactions into one big transaction, and flush it to the log.
- */
-
-static void
-log_flush_internal(struct gfs_sbd *sdp, struct gfs_glock *gl)
-{
-
- struct gfs_trans *trans = NULL, *tr;
- int error;
-
- gfs_log_lock(sdp);
-
- if (!gl && list_empty(&sdp->sd_log_incore)) {
- if (sdp->sd_log_seg_ail2) {
- trans = gmalloc(sizeof(struct gfs_trans));
- make_dummy_transaction(sdp, trans);
- }
- else
- goto out;
- }
-
- if (gl) {
- if (!gl->gl_incore_le.le_trans)
- goto out;
-
- trans = gl->gl_incore_le.le_trans;
-
- list_del(&trans->tr_list);
- } else {
- /* combine *all* transactions in incore list */
- while (!list_empty(&sdp->sd_log_incore)) {
- tr = list_entry(sdp->sd_log_incore.next,
- struct gfs_trans, tr_list);
-
- list_del(&tr->tr_list);
-
- if (trans)
- trans_combine(sdp, trans, tr);
- else
- trans = tr;
- }
- }
-
- log_refund(sdp, trans);
-
- /* Actually do the stuff to commit the transaction */
-
- error = disk_commit(sdp, trans);
- if (error)
- gfs_io_error(sdp);
-
- add_trans_to_ail(sdp, trans);
-
- if (log_distance(sdp, sdp->sd_log_head, sdp->sd_log_dump_last) * GFS_DUMPS_PER_LOG >=
- sdp->sd_jdesc.ji_nsegment * sdp->sd_sb.sb_seg_size)
- set_bit(SDF_NEED_LOG_DUMP, &sdp->sd_flags);
-
- out:
- if (list_empty(&sdp->sd_log_incore))
- sdp->sd_vfs->s_dirt = FALSE;
-
- gfs_log_unlock(sdp);
-
- /* Dump if we need to. */
-
- if (test_bit(SDF_NEED_LOG_DUMP, &sdp->sd_flags))
- gfs_log_dump(sdp, FALSE);
-}
-
-/**
- * gfs_log_flush - flush the whole incore log
- * @sdp: the filesystem
- *
- */
-
-void
-gfs_log_flush(struct gfs_sbd *sdp)
-{
- log_flush_internal(sdp, NULL);
-}
-
-/**
- * gfs_log_flush_glock - flush the incore log for a glock
- * @gl: the glock
- *
- */
-
-void
-gfs_log_flush_glock(struct gfs_glock *gl)
-{
- log_flush_internal(gl->gl_sbd, gl);
-}
-
-/**
- * incore_commit - commit a transaction in-core
- * @sdp: the filesystem
- * @new_tr: the transaction to commit
- *
- * Add the transaction @new_tr to the end of the incore commit list.
- * Pull up and merge any previously committed transactions that share
- * locks. Also pull up any rename transactions that need it.
- */
-
-static void
-incore_commit(struct gfs_sbd *sdp, struct gfs_trans *new_tr)
-{
- struct gfs_log_element *le;
- struct gfs_trans *trans = NULL, *exist_tr;
- struct gfs_log_buf *lb;
- struct list_head *bmem;
- struct list_head *tmp, *head, *next;
-
- for (head = &new_tr->tr_elements, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- le = list_entry(tmp, struct gfs_log_element, le_list);
-
- /* Do overlap_trans log-op, if any, to find another
- incore transaction with which we can combine new_tr */
- exist_tr = LO_OVERLAP_TRANS(sdp, le);
- if (!exist_tr)
- continue;
-
- if (exist_tr != trans) {
- /* remove trans from superblock's sd_log_incore list */
- list_del(&exist_tr->tr_list);
-
- /* Maybe there's more than one that can be combined.
- If so, combine them together before merging new_tr */
- if (trans)
- trans_combine(sdp, trans, exist_tr);
- else
- trans = exist_tr;
- }
- }
-
- /* Yes, we can combine new_tr with pre-existing transaction(s) */
- if (trans) {
- trans->tr_file = __FILE__;
- trans->tr_line = __LINE__;
- trans->tr_seg_reserved += new_tr->tr_seg_reserved;
- trans->tr_flags |= new_tr->tr_flags;
- trans->tr_num_free_bufs += new_tr->tr_num_free_bufs;
- trans->tr_num_free_bmem += new_tr->tr_num_free_bmem;
-
- /* Move free log buffer descriptors to surviving trans */
- while (!list_empty(&new_tr->tr_free_bufs)) {
- lb = list_entry(new_tr->tr_free_bufs.next,
- struct gfs_log_buf, lb_list);
- list_move(&lb->lb_list, &trans->tr_free_bufs);
- new_tr->tr_num_free_bufs--;
- }
-
- /* Move free log buffers to surviving trans */
- while (!list_empty(&new_tr->tr_free_bmem)) {
- bmem = new_tr->tr_free_bmem.next;
- list_move(bmem, &trans->tr_free_bmem);
- new_tr->tr_num_free_bmem--;
- }
- } else
- trans = new_tr;
-
- /* Do incore_commit log-op for each *new* log element (in new_tr).
- Each commit log-op removes its log element from "new_tr" LE list,
- and attaches an LE to "trans" LE list; if there was no trans
- combining, "new_tr" is the same transaction as "trans". */
- for (head = &new_tr->tr_elements, tmp = head->next, next = tmp->next;
- tmp != head;
- tmp = next, next = next->next) {
- le = list_entry(tmp, struct gfs_log_element, le_list);
- LO_INCORE_COMMIT(sdp, trans, le);
- }
-
- /* If we successfully combined transactions, new_tr should be empty */
- if (trans != new_tr) {
- gfs_assert_warn(sdp, !new_tr->tr_num_free_bufs);
- gfs_assert_warn(sdp, !new_tr->tr_num_free_bmem);
- gfs_assert_warn(sdp, list_empty(&new_tr->tr_elements));
- kfree(new_tr);
- }
-
- /* If we successfully combined transactions, we might have some log
- segments that we reserved, and log buffers and buffer descriptors
- that we allocated, but now don't need. */
- log_refund(sdp, trans);
-
- list_add(&trans->tr_list, &sdp->sd_log_incore);
-}
-
-/**
- * gfs_log_commit - Commit a transaction to the log
- * @sdp: the filesystem
- * @tr: the transaction
- *
- * Returns: errno
- */
-
-void
-gfs_log_commit(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct gfs_log_buf *lb;
- struct list_head *bmem;
- unsigned int num_mblks = 0, num_eblks = 0, num_bufs = 0, num_bmem = 0;
- unsigned int segments;
-
- /* Calculate actual log area needed for this trans */
- LO_TRANS_SIZE(sdp, tr, &num_mblks, &num_eblks, &num_bufs, &num_bmem);
-
- gfs_assert(sdp, num_mblks <= tr->tr_mblks_asked &&
- num_eblks <= tr->tr_eblks_asked,
- printk("GFS: fsid=%s: type = (%s, %u)\n"
- "GFS: fsid=%s: num_mblks = %u, tr->tr_mblks_asked = %u\n"
- "GFS: fsid=%s: num_eblks = %u, tr->tr_eblks_asked = %u\n",
- sdp->sd_fsname, tr->tr_file, tr->tr_line,
- sdp->sd_fsname, num_mblks, tr->tr_mblks_asked,
- sdp->sd_fsname, num_eblks, tr->tr_eblks_asked););
-
- segments = gfs_blk2seg(sdp, num_bufs + 1);
- num_bufs += segments + 1;
- num_bmem += segments + 1;
-
- /* Alloc log buffer descriptors */
- while (num_bufs--) {
- lb = gmalloc(sizeof(struct gfs_log_buf));
- memset(lb, 0, sizeof(struct gfs_log_buf));
- list_add(&lb->lb_list, &tr->tr_free_bufs);
- tr->tr_num_free_bufs++;
- }
- /* Alloc log buffers */
- while (num_bmem--) {
- bmem = gmalloc(sdp->sd_sb.sb_bsize);
- list_add(bmem, &tr->tr_free_bmem);
- tr->tr_num_free_bmem++;
- }
-
- gfs_log_lock(sdp);
-
- incore_commit(sdp, tr);
-
- /* Flush log buffers to disk if we're over the threshold */
- if (sdp->sd_log_buffers > gfs_tune_get(sdp, gt_incore_log_blocks)) {
- gfs_log_unlock(sdp);
- gfs_log_flush(sdp);
- } else {
- sdp->sd_vfs->s_dirt = TRUE;
- gfs_log_unlock(sdp);
- }
-
-}
-
-/**
- * gfs_log_dump - make a Log Dump entry in the log
- * @sdp: the filesystem
- * @force: if TRUE, always make the dump even if one has been made recently
- *
- */
-
-void
-gfs_log_dump(struct gfs_sbd *sdp, int force)
-{
- struct gfs_log_element *le;
- struct gfs_trans tr;
- struct gfs_log_buf *lb;
- struct list_head *bmem;
- unsigned int num_bufs, num_bmem;
- unsigned int segments;
- int error;
-
- if (test_and_set_bit(SDF_IN_LOG_DUMP, &sdp->sd_flags)) {
- gfs_assert(sdp, !force,);
- return;
- }
-
- memset(&tr, 0, sizeof(struct gfs_trans));
- INIT_LIST_HEAD(&tr.tr_elements);
- INIT_LIST_HEAD(&tr.tr_free_bufs);
- INIT_LIST_HEAD(&tr.tr_free_bmem);
- INIT_LIST_HEAD(&tr.tr_bufs);
- tr.tr_flags = TRF_LOG_DUMP;
- tr.tr_file = __FILE__;
- tr.tr_line = __LINE__;
-
- for (;;) {
- gfs_log_lock(sdp);
-
- if (!force && !test_bit(SDF_NEED_LOG_DUMP, &sdp->sd_flags))
- goto out;
-
- num_bufs = num_bmem = 0;
- LO_DUMP_SIZE(sdp, NULL, &num_bufs, &num_bmem);
- gfs_assert(sdp, num_bufs,);
- segments = gfs_blk2seg(sdp, num_bufs + 1);
- num_bufs += segments + 1;
- num_bmem += segments + 1;
-
- if (tr.tr_seg_reserved >= segments &&
- tr.tr_num_free_bufs >= num_bufs &&
- tr.tr_num_free_bmem >= num_bmem)
- break;
-
- gfs_log_unlock(sdp);
-
- if (tr.tr_seg_reserved < segments) {
- error = gfs_log_reserve(sdp,
- segments - tr.tr_seg_reserved,
- TRUE);
- gfs_assert(sdp, !error,);
- tr.tr_seg_reserved = segments;
- }
- while (tr.tr_num_free_bufs < num_bufs) {
- lb = gmalloc(sizeof(struct gfs_log_buf));
- memset(lb, 0, sizeof(struct gfs_log_buf));
- list_add(&lb->lb_list, &tr.tr_free_bufs);
- tr.tr_num_free_bufs++;
- }
- while (tr.tr_num_free_bmem < num_bmem) {
- bmem = gmalloc(sdp->sd_sb.sb_bsize);
- list_add(bmem, &tr.tr_free_bmem);
- tr.tr_num_free_bmem++;
- }
- }
-
- if (tr.tr_seg_reserved > segments) {
- spin_lock(&sdp->sd_log_seg_lock);
- sdp->sd_log_seg_free += tr.tr_seg_reserved - segments;
- gfs_assert(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 <=
- sdp->sd_jdesc.ji_nsegment,);
- spin_unlock(&sdp->sd_log_seg_lock);
- tr.tr_seg_reserved = segments;
- }
- while (tr.tr_num_free_bufs > num_bufs) {
- lb = list_entry(tr.tr_free_bufs.next,
- struct gfs_log_buf, lb_list);
- list_del(&lb->lb_list);
- kfree(lb);
- tr.tr_num_free_bufs--;
- }
- while (tr.tr_num_free_bmem > num_bmem) {
- bmem = tr.tr_free_bmem.next;
- list_del(bmem);
- kfree(bmem);
- tr.tr_num_free_bmem--;
- }
-
- LO_BUILD_DUMP(sdp, &tr);
-
- error = disk_commit(sdp, &tr);
- if (error)
- gfs_io_error(sdp);
-
- while (!list_empty(&tr.tr_elements)) {
- le = list_entry(tr.tr_elements.next,
- struct gfs_log_element, le_list);
- LO_CLEAN_DUMP(sdp, le);
- }
-
- /* If there isn't anything in the AIL, we won't get back the log
- space we reserved unless we do it ourselves. */
-
- if (list_empty(&sdp->sd_log_ail)) {
- spin_lock(&sdp->sd_log_seg_lock);
- sdp->sd_log_seg_free += tr.tr_seg_reserved;
- gfs_assert(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 <=
- sdp->sd_jdesc.ji_nsegment,);
- spin_unlock(&sdp->sd_log_seg_lock);
- }
-
- clear_bit(SDF_NEED_LOG_DUMP, &sdp->sd_flags);
-
- out:
- gfs_log_unlock(sdp);
- clear_bit(SDF_IN_LOG_DUMP, &sdp->sd_flags);
-}
-
-/**
- * gfs_log_shutdown - write a shutdown header into a journal
- * @sdp: the filesystem
- *
- */
-
-void
-gfs_log_shutdown(struct gfs_sbd *sdp)
-{
- struct gfs_log_buf *lb;
- char *bmem;
- struct gfs_log_header head;
- struct gfs_log_descriptor desc;
- unsigned int elements = 0;
- int error;
-
- lb = gmalloc(sizeof(struct gfs_log_buf));
- memset(lb, 0, sizeof(struct gfs_log_buf));
- bmem = gmalloc(sdp->sd_sb.sb_bsize);
-
- gfs_log_lock(sdp);
-
- gfs_assert_withdraw(sdp, list_empty(&sdp->sd_log_ail));
- gfs_assert_withdraw(sdp, sdp->sd_log_seg_free + sdp->sd_log_seg_ail2 ==
- sdp->sd_jdesc.ji_nsegment);
- gfs_assert_withdraw(sdp, !sdp->sd_log_buffers);
- gfs_assert_withdraw(sdp, gfs_log_is_header(sdp, sdp->sd_log_head - 1));
- if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
- goto out;
-
- /* Build a "last" log descriptor */
-
- memset(&desc, 0, sizeof(struct gfs_log_descriptor));
- desc.ld_header.mh_magic = GFS_MAGIC;
- desc.ld_header.mh_type = GFS_METATYPE_LD;
- desc.ld_header.mh_format = GFS_FORMAT_LD;
- desc.ld_type = GFS_LOG_DESC_LAST;
- desc.ld_length = sdp->sd_sb.sb_seg_size - 1;
-
- /* Write the descriptor */
-
- gfs_logbh_init(sdp, &lb->lb_bh, sdp->sd_log_head, bmem);
- memset(bmem, 0, sdp->sd_sb.sb_bsize);
- gfs_desc_out(&desc, lb->lb_bh.b_data);
- if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
- goto out;
- gfs_logbh_start(sdp, &lb->lb_bh);
- error = gfs_logbh_wait(sdp, &lb->lb_bh);
- gfs_logbh_uninit(sdp, &lb->lb_bh);
-
- if (error)
- goto out;
-
- /* Move to the next header */
-
- while (!gfs_log_is_header(sdp, sdp->sd_log_head))
- log_incr_head(sdp, &sdp->sd_log_head);
-
- LO_DUMP_SIZE(sdp, &elements, NULL, NULL);
-
- /* Build the shutdown header */
-
- memset(&head, 0, sizeof (struct gfs_log_header));
- head.lh_header.mh_magic = GFS_MAGIC;
- head.lh_header.mh_type = GFS_METATYPE_LH;
- head.lh_header.mh_format = GFS_FORMAT_LH;
- head.lh_flags = GFS_LOG_HEAD_UNMOUNT;
- head.lh_first = sdp->sd_log_head;
- head.lh_sequence = sdp->sd_sequence + 1;
- /* Don't care about tail */
- head.lh_last_dump = (elements) ? sdp->sd_log_dump_last : 0;
-
- /* Write out the shutdown header */
-
- gfs_logbh_init(sdp, &lb->lb_bh, sdp->sd_log_head, bmem);
- memset(bmem, 0, sdp->sd_sb.sb_bsize);
- gfs_log_header_out(&head, lb->lb_bh.b_data);
- gfs_log_header_out(&head,
- lb->lb_bh.b_data + GFS_BASIC_BLOCK -
- sizeof(struct gfs_log_header));
- if (!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) {
- gfs_logbh_start(sdp, &lb->lb_bh);
- gfs_logbh_wait(sdp, &lb->lb_bh);
- gfs_logbh_uninit(sdp, &lb->lb_bh);
- }
- /* If a withdraw is called before we've a chance to relock the trans
- * lock, the sd_log_head points to the wrong place, and a umount will
- * fail on asserts because of this.
- * Adding one puts sd_log_head at a value that passes the assert. The
- * value may not be correct for on disk, but we've withdrawn so there is
- * no more disk io.
- * If we're not withdrawn, the next io will grab the trans lock, which
- * will fill sd_log_head with the correct value.
- */
- sdp->sd_log_head += 1;
-
- out:
- gfs_log_unlock(sdp);
-
- kfree(lb);
- kfree(bmem);
-}
diff --git a/gfs-kernel/src/gfs/log.h b/gfs-kernel/src/gfs/log.h
deleted file mode 100644
index 649d43d..0000000
--- a/gfs-kernel/src/gfs/log.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef __LOG_DOT_H__
-#define __LOG_DOT_H__
-
-/**
- * gfs_log_lock - acquire the right to mess with the log manager
- * @sdp: the filesystem
- *
- */
-
-static __inline__ void
-gfs_log_lock(struct gfs_sbd *sdp)
-{
- down_write(&sdp->sd_log_lock);
-}
-
-/**
- * gfs_log_unlock - release the right to mess with the log manager
- * @sdp: the filesystem
- *
- */
-
-static __inline__ void
-gfs_log_unlock(struct gfs_sbd *sdp)
-{
- up_write(&sdp->sd_log_lock);
-}
-
-unsigned int gfs_struct2blk(struct gfs_sbd *sdp, unsigned int nstruct,
- unsigned int ssize);
-unsigned int gfs_blk2seg(struct gfs_sbd *sdp, unsigned int blocks);
-
-int gfs_log_reserve(struct gfs_sbd *sdp, unsigned int segments, int jump_queue);
-void gfs_log_release(struct gfs_sbd *sdp, unsigned int segments);
-
-void gfs_ail_start(struct gfs_sbd *sdp, int flags);
-int gfs_ail_empty(struct gfs_sbd *sdp);
-
-void gfs_log_commit(struct gfs_sbd *sdp, struct gfs_trans *trans);
-void gfs_log_flush(struct gfs_sbd *sdp);
-void gfs_log_flush_glock(struct gfs_glock *gl);
-
-void gfs_log_shutdown(struct gfs_sbd *sdp);
-
-void gfs_log_dump(struct gfs_sbd *sdp, int force);
-
-/* Internal crap used the log operations */
-
-/**
- * gfs_log_is_header - Discover if block is on journal header
- * @sdp: The GFS superblock
- * @block: The block number
- *
- * Returns: TRUE if the block is on a journal segment boundary, FALSE otherwise
- */
-
-static __inline__ int
-gfs_log_is_header(struct gfs_sbd *sdp, uint64_t block)
-{
- return !do_mod(block, sdp->sd_sb.sb_seg_size);
-}
-
-struct gfs_log_buf *gfs_log_get_buf(struct gfs_sbd *sdp, struct gfs_trans *tr);
-void gfs_log_fake_buf(struct gfs_sbd *sdp, struct gfs_trans *tr, char *data,
- struct buffer_head *unlock);
-
-#endif /* __LOG_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/lops.c b/gfs-kernel/src/gfs/lops.c
deleted file mode 100644
index 70f2a32..0000000
--- a/gfs-kernel/src/gfs/lops.c
+++ /dev/null
@@ -1,1649 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "dio.h"
-#include "glock.h"
-#include "log.h"
-#include "lops.h"
-#include "quota.h"
-#include "recovery.h"
-#include "trans.h"
-#include "unlinked.h"
-
-/**
- * generic_le_add - generic routine to add a log element to a transaction
- * @sdp: the filesystem
- * @le: the log entry
- *
- */
-
-static void
-generic_le_add(struct gfs_sbd *sdp, struct gfs_log_element *le)
-{
- struct gfs_trans *tr;
-
- /* Make sure it's not attached to a transaction already */
- gfs_assert(sdp, le->le_ops &&
- !le->le_trans &&
- list_empty(&le->le_list),);
-
- /* Attach it to the (one) transaction being built by this process */
- tr = get_transaction;
- gfs_assert(sdp, tr,);
-
- le->le_trans = tr;
- list_add(&le->le_list, &tr->tr_elements);
-}
-
-/**
- * glock_trans_end - drop a glock reference
- * @sdp: the filesystem
- * @le: the log element
- *
- * Called before incore-committing a transaction
- * Release reference that was taken in gfs_trans_add_gl()
- */
-
-static void
-glock_trans_end(struct gfs_sbd *sdp, struct gfs_log_element *le)
-{
- struct gfs_glock *gl = container_of(le, struct gfs_glock, gl_new_le);
-
- gfs_assert(sdp, gfs_glock_is_locked_by_me(gl) &&
- gfs_glock_is_held_excl(gl),);
- gfs_glock_put(gl);
-}
-
-/**
- * glock_print - print debug info about a log element
- * @sdp: the filesystem
- * @le: the log element
- * @where: is this a new transaction or a incore transaction
- *
- */
-
-static void
-glock_print(struct gfs_sbd *sdp, struct gfs_log_element *le, unsigned int where)
-{
- struct gfs_glock *gl;
-
- switch (where) {
- case TRANS_IS_NEW:
- gl = container_of(le, struct gfs_glock, gl_new_le);
- break;
- case TRANS_IS_INCORE:
- gl = container_of(le, struct gfs_glock, gl_incore_le);
- break;
- default:
- gfs_assert_warn(sdp, FALSE);
- return;
- }
-
- printk(" Glock: (%u, %llu)\n",
- gl->gl_name.ln_type,
- (unsigned long long)gl->gl_name.ln_number);
-}
-
-/**
- * glock_overlap_trans - Find any incore transactions that might overlap with
- * (i.e. be combinable with the transaction containing) this LE
- * @sdp: the filesystem
- * @le: the log element
- *
- * Transactions that share a given glock are combinable.
- *
- * For a glock, the scope of the "search" is just the (max) one unique incore
- * committed transaction to which the glock may be attached via its
- * gl->gl_incore_le embedded log element. This trans may have previously
- * been combined with other transactions, though (i.e. previous
- * incore committed transactions that shared the same glock).
- *
- * Called as a beginning part of the incore commit of a transaction.
- */
-
-static struct gfs_trans *
-glock_overlap_trans(struct gfs_sbd *sdp, struct gfs_log_element *le)
-{
- struct gfs_glock *gl = container_of(le, struct gfs_glock, gl_new_le);
-
- return gl->gl_incore_le.le_trans;
-}
-
-/**
- * glock_incore_commit - commit this LE to the incore log
- * @sdp: the filesystem
- * @tr: the being-incore-committed transaction this LE is to be a part of
- * @le: the log element (should be a gl->gl_new_le), which is attached
- * to a "new" (just-ended) transaction.
- *
- * Attach glock's gl_incore_le to the being-incore-committed trans' LE list.
- * Remove glock's gl_new_le from the just-ended new trans' LE list.
- * If the just-ended new trans (le->le_trans) was combined (in incore_commit())
- * with a pre-existing incore trans (tr), this function effectively moves
- * the LE from the new to the combined incore trans.
- * If there was no combining, then the new trans itself is being committed
- * (le->le_trans == tr); this function simply replaces the gl_new_le with a
- * gl_incore_le on the trans' LE list.
- *
- * Make sure that this glock's gl_incore_le is attached to one and only one
- * incore-committed transaction's (this one's) tr_elements list.
- * One transaction (instead of a list of transactions) is sufficient,
- * because incore_commit() combines multiple transactions that share a glock
- * into one trans.
- * Since transactions can contain multiple glocks, there are multiple
- * possibilities for shared glocks, therefore multiple potential "bridges"
- * for combining transactions.
- */
-
-static void
-glock_incore_commit(struct gfs_sbd *sdp, struct gfs_trans *tr,
- struct gfs_log_element *le)
-{
- struct gfs_glock *gl = container_of(le, struct gfs_glock, gl_new_le);
-
- /* Transactions were combined, based on this glock */
- if (gl->gl_incore_le.le_trans)
- gfs_assert(sdp, gl->gl_incore_le.le_trans == tr,);
- else {
- /* Attach gl->gl_incore_le to being-committed trans */
- gl->gl_incore_le.le_trans = tr;
- list_add(&gl->gl_incore_le.le_list, &tr->tr_elements);
-
- /* If transactions were combined (via another shared glock),
- the combined trans is getting a new glock log element */
- if (tr != le->le_trans)
- tr->tr_num_gl++;
- }
-
- /* Remove gl->gl_new_le from "new" trans */
- le->le_trans = NULL;
- list_del_init(&le->le_list);
-}
-
-/**
- * glock_add_to_ail - Add this LE to the AIL
- * @sdp: the filesystem
- * @le: the log element
- *
- * Glocks don't really get added to AIL (there's nothing to write to disk),
- * they just get removed from the transaction at this time.
- */
-
-static void
-glock_add_to_ail(struct gfs_sbd *sdp, struct gfs_log_element *le)
-{
- le->le_trans = NULL;
- list_del_init(&le->le_list);
-}
-
-/**
- * glock_trans_combine - combine two incore transactions
- * @sdp: the filesystem
- * @tr: the surviving transaction
- * @new_tr: the transaction that's going to disappear
- *
- */
-
-static void
-glock_trans_combine(struct gfs_sbd *sdp, struct gfs_trans *tr,
- struct gfs_trans *new_tr)
-{
- tr->tr_num_gl += new_tr->tr_num_gl;
-}
-
-/**
- * buf_print - print debug info about a log element
- * @sdp: the filesystem
- * @le: the log element
- * @where: is this a new transaction or a incore transaction
- *
- */
-
-static void
-buf_print(struct gfs_sbd *sdp, struct gfs_log_element *le, unsigned int where)
-{
- struct gfs_bufdata *bd;
-
- switch (where) {
- case TRANS_IS_NEW:
- bd = container_of(le, struct gfs_bufdata, bd_new_le);
- break;
- case TRANS_IS_INCORE:
- bd = container_of(le, struct gfs_bufdata, bd_incore_le);
- break;
- default:
- gfs_assert_warn(sdp, FALSE);
- return;
- }
-
- printk(" Buffer: %llu\n", (unsigned long long)bd->bd_bh->b_blocknr);
-}
-
-/**
- * buf_incore_commit - commit this buffer LE to the incore log
- * @sdp: the filesystem
- * @tr: the incore transaction this LE is a part of
- * @le: the log element for the "new" (just now complete) trans
- *
- * Invoked from incore_commit().
- * Move this buffer from "new" stage to "incore committed" stage of the
- * transaction pipeline.
- * If this buffer was already attached to a pre-existing incore trans, GFS is
- * combining the new and incore transactions; decrement buffer's recursive
- * pin count that was incremented when it was added to the new transaction,
- * and remove the reference to the "new" (being swallowed) trans.
- * Else, move this buffer's attach point from "new" to "incore" embedded LE
- * (same transaction, just new status) and add this buf to (incore) trans'
- * LE list.
- */
-
-static void
-buf_incore_commit(struct gfs_sbd *sdp, struct gfs_trans *tr,
- struct gfs_log_element *le)
-{
- struct gfs_bufdata *bd = container_of(le, struct gfs_bufdata, bd_new_le);
-
- /* We've completed our (atomic) changes to this buffer for this trans.
- We no longer need the frozen copy. If frozen copy was not written
- to on-disk log already, there's no longer a need to; we can now
- write the "real" buffer (with more up-to-date content) instead. */
- if (bd->bd_frozen) {
- kfree(bd->bd_frozen);
- bd->bd_frozen = NULL;
- }
-
- /* New trans being combined with pre-existing incore trans? */
- if (bd->bd_incore_le.le_trans) {
- gfs_assert(sdp, bd->bd_incore_le.le_trans == tr,);
- gfs_dunpin(sdp, bd->bd_bh, NULL);
- } else {
- bd->bd_incore_le.le_trans = tr;
- list_add(&bd->bd_incore_le.le_list, &tr->tr_elements);
- if (tr != le->le_trans)
- tr->tr_num_buf++;
-
- sdp->sd_log_buffers++;
- }
-
- /* Reset buffer's bd_new_le */
- le->le_trans = NULL;
- list_del_init(&le->le_list);
-}
-
-/**
- * buf_add_to_ail - Add this LE to the AIL
- * @sdp: the filesystem
- * @le: the log element
- *
- */
-
-static void
-buf_add_to_ail(struct gfs_sbd *sdp, struct gfs_log_element *le)
-{
- struct gfs_bufdata *bd = container_of(le,
- struct gfs_bufdata,
- bd_incore_le);
-
- gfs_dunpin(sdp, bd->bd_bh, le->le_trans);
-
- le->le_trans = NULL;
- list_del_init(&le->le_list);
-
- gfs_assert(sdp, sdp->sd_log_buffers,);
- sdp->sd_log_buffers--;
-}
-
-/**
- * buf_trans_size - compute how much space the LE class takes up in a transaction
- * @sdp: the filesystem
- * @tr: the transaction
- * @mblks: the number of regular metadata blocks
- * @eblks: the number of extra blocks
- * @blocks: the number of log blocks
- * @bmem: the number of buffer-sized chunks of memory we need
- *
- */
-
-static void
-buf_trans_size(struct gfs_sbd *sdp, struct gfs_trans *tr,
- unsigned int *mblks, unsigned int *eblks,
- unsigned int *blocks, unsigned int *bmem)
-{
- unsigned int cblks;
-
- if (tr->tr_num_buf) {
- cblks = gfs_struct2blk(sdp, tr->tr_num_buf,
- sizeof(struct gfs_block_tag));
-
- if (mblks)
- *mblks += tr->tr_num_buf;
- if (blocks)
- *blocks += tr->tr_num_buf + cblks;
- if (bmem)
- *bmem += cblks;
- }
-}
-
-/**
- * buf_trans_combine - combine two incore transactions
- * @sdp: the filesystem
- * @tr: the surviving transaction
- * @new_tr: the transaction that's going to disappear
- *
- */
-
-static void
-buf_trans_combine(struct gfs_sbd *sdp, struct gfs_trans *tr,
- struct gfs_trans *new_tr)
-{
- tr->tr_num_buf += new_tr->tr_num_buf;
-}
-
-/**
- * increment_generation - increment the generation number in metadata buffer
- * @sdp: the filesystem
- * @bd: the struct gfs_bufdata structure associated with the buffer
- *
- * Increment the generation # of the most recent buffer contents, as well as
- * that of frozen buffer, if any. If there is a frozen buffer, only *it*
- * will be going to the log now ... in this case, the current buffer will
- * have its gen # incremented again later, when it gets written to log.
- * Gen # is used by journal recovery (replay_block()) to determine whether
- * to overwrite an inplace block with the logged block contents.
- */
-
-static void
-increment_generation(struct gfs_sbd *sdp, struct gfs_bufdata *bd)
-{
- struct gfs_meta_header *mh, *mh2;
- uint64_t tmp64;
-
- mh = (struct gfs_meta_header *)bd->bd_bh->b_data;
-
- tmp64 = gfs64_to_cpu(mh->mh_generation) + 1;
- tmp64 = cpu_to_gfs64(tmp64);
-
- if (bd->bd_frozen) {
- mh2 = (struct gfs_meta_header *)bd->bd_frozen;
- gfs_assert(sdp, mh->mh_generation == mh2->mh_generation,);
- mh2->mh_generation = tmp64;
- }
- mh->mh_generation = tmp64;
-}
-
-/**
- * buf_build_bhlist - create the buffers that will make up the ondisk part of a transaction
- * @sdp: the filesystem
- * @tr: the transaction
- *
- * Create the log (transaction) descriptor block
- */
-
-static void
-buf_build_bhlist(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct list_head *tmp, *head;
- struct gfs_log_element *le;
- struct gfs_bufdata *bd;
- struct gfs_log_descriptor desc;
- struct gfs_block_tag tag;
- struct gfs_log_buf *clb = NULL;
- unsigned int num_ctl;
- unsigned int offset = sizeof(struct gfs_log_descriptor);
- unsigned int x, bufs;
-
- if (!tr->tr_num_buf)
- return;
-
- /* set up control buffers for descriptor and tags */
-
- num_ctl = gfs_struct2blk(sdp, tr->tr_num_buf,
- sizeof(struct gfs_block_tag));
-
- for (x = 0; x < num_ctl; x++) {
- if (clb)
- gfs_log_get_buf(sdp, tr);
- else
- clb = gfs_log_get_buf(sdp, tr);
- }
-
- /* Init and copy log descriptor into 1st control block */
- memset(&desc, 0, sizeof(struct gfs_log_descriptor));
- desc.ld_header.mh_magic = GFS_MAGIC;
- desc.ld_header.mh_type = GFS_METATYPE_LD;
- desc.ld_header.mh_format = GFS_FORMAT_LD;
- desc.ld_type = GFS_LOG_DESC_METADATA;
- desc.ld_length = num_ctl + tr->tr_num_buf;
- desc.ld_data1 = tr->tr_num_buf;
- gfs_desc_out(&desc, clb->lb_bh.b_data);
-
- x = 1;
- bufs = 0;
-
- for (head = &tr->tr_elements, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- le = list_entry(tmp, struct gfs_log_element, le_list);
-
- /* Skip over non-buffer (e.g. glock, unlinked, etc.) LEs */
- if (le->le_ops != &gfs_buf_lops)
- continue;
-
- bd = container_of(le, struct gfs_bufdata, bd_incore_le);
-
- gfs_meta_check(sdp, bd->bd_bh);
-
- gfs_lock_buffer(bd->bd_bh);
-
- increment_generation(sdp, bd);
-
- /* Create "fake" buffer head to write block to on-disk log. Use
- frozen copy if another transaction is modifying the "real"
- buffer contents. Unlock real bh after log write completes,
- so Linux can write real contents to inplace block. */
- gfs_log_fake_buf(sdp, tr,
- (bd->bd_frozen) ? bd->bd_frozen : bd->bd_bh->b_data,
- bd->bd_bh);
-
- /* find another buffer for tags if we're overflowing this one */
- if (offset + sizeof(struct gfs_block_tag) > sdp->sd_sb.sb_bsize) {
- clb = list_entry(clb->lb_list.prev,
- struct gfs_log_buf, lb_list);
- if (gfs_log_is_header(sdp, clb->lb_bh.b_blocknr))
- clb = list_entry(clb->lb_list.prev,
- struct gfs_log_buf, lb_list);
- x++;
- offset = 0;
- }
-
- /* Write this LE's tag into a control buffer */
- memset(&tag, 0, sizeof(struct gfs_block_tag));
- tag.bt_blkno = bd->bd_bh->b_blocknr;
-
- gfs_block_tag_out(&tag, clb->lb_bh.b_data + offset);
-
- offset += sizeof(struct gfs_block_tag);
- bufs++;
- }
-
- gfs_assert(sdp, x == num_ctl,);
- gfs_assert(sdp, bufs == tr->tr_num_buf,);
-}
-
-/**
- * buf_before_scan - called before journal replay
- * @sdp: the filesystem
- * @jid: the journal ID about to be replayed
- * @head: the current head of the log
- * @pass: the pass through the journal
- *
- */
-
-static void
-buf_before_scan(struct gfs_sbd *sdp, unsigned int jid,
- struct gfs_log_header *head, unsigned int pass)
-{
- if (pass == GFS_RECPASS_A1)
- sdp->sd_recovery_replays =
- sdp->sd_recovery_skips =
- sdp->sd_recovery_sames = 0;
-}
-
-/**
- * replay_block - Replay a single metadata block
- * @sdp: the filesystem
- * @jdesc: the struct gfs_jindex structure for the journal being replayed
- * @gl: the journal's glock
- * @tag: the block tag describing the inplace location of the block
- * @blkno: the location of the log's copy of the block
- *
- * Returns: errno
- *
- * Read in-place block from disk
- * Read log (journal) block from disk
- * Compare generation numbers
- * Copy log block to in-place block on-disk if:
- * log generation # > in-place generation #
- * OR generation #s are ==, but data contained in block is different (corrupt)
- */
-
-static int
-replay_block(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, struct gfs_block_tag *tag, uint64_t blkno)
-{
- struct buffer_head *inplace_bh, *log_bh;
- struct gfs_meta_header inplace_mh, log_mh;
- int replay_block = TRUE;
- int error = 0;
-
- gfs_replay_check(sdp);
-
- /* Warning: Using a real buffer here instead of a tempbh can be bad
- on a OS that won't support multiple simultaneous buffers for the
- same block on different glocks. */
-
- error = gfs_dread(gl, tag->bt_blkno,
- DIO_START | DIO_WAIT, &inplace_bh);
- if (error)
- return error;
- if (gfs_meta_check(sdp, inplace_bh)) {
- brelse(inplace_bh);
- return -EIO;
- }
- gfs_meta_header_in(&inplace_mh, inplace_bh->b_data);
-
- error = gfs_dread(gl, blkno, DIO_START | DIO_WAIT, &log_bh);
- if (error) {
- brelse(inplace_bh);
- return error;
- }
- if (gfs_meta_check(sdp, log_bh)) {
- brelse(inplace_bh);
- brelse(log_bh);
- return -EIO;
- }
- gfs_meta_header_in(&log_mh, log_bh->b_data);
-
- if (log_mh.mh_generation < inplace_mh.mh_generation) {
- replay_block = FALSE;
- sdp->sd_recovery_skips++;
- } else if (log_mh.mh_generation == inplace_mh.mh_generation) {
- if (memcmp(log_bh->b_data,
- inplace_bh->b_data,
- sdp->sd_sb.sb_bsize) == 0) {
- replay_block = FALSE;
- sdp->sd_recovery_sames++;
- }
- }
-
- if (replay_block) {
- memcpy(inplace_bh->b_data,
- log_bh->b_data,
- sdp->sd_sb.sb_bsize);
-
- error = gfs_replay_buf(gl, inplace_bh);
- if (!error)
- sdp->sd_recovery_replays++;
- }
-
- brelse(log_bh);
- brelse(inplace_bh);
-
- return error;
-}
-
-/**
- * buf_scan_elements - Replay a metadata log descriptor
- * @sdp: the filesystem
- * @jdesc: the struct gfs_jindex structure for the journal being replayed
- * @gl: the journal's glock
- * @start: the starting block of the descriptor
- * @desc: the descriptor structure
- * @pass: the pass through the journal
- *
- * Returns: errno
- */
-
-static int
-buf_scan_elements(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, uint64_t start,
- struct gfs_log_descriptor *desc, unsigned int pass)
-{
- struct gfs_block_tag tag;
- struct buffer_head *bh;
- uint64_t cblk = start;
- unsigned int num_tags = desc->ld_data1;
- unsigned int offset = sizeof(struct gfs_log_descriptor);
- unsigned int x;
- int error;
-
- if (pass != GFS_RECPASS_A1)
- return 0;
- if (desc->ld_type != GFS_LOG_DESC_METADATA)
- return 0;
-
- x = gfs_struct2blk(sdp, num_tags, sizeof(struct gfs_block_tag));
- while (x--) {
- error = gfs_increment_blkno(sdp, jdesc, gl, &start, TRUE);
- if (error)
- return error;
- }
-
- for (;;) {
- gfs_assert(sdp, num_tags,);
-
- error = gfs_dread(gl, cblk, DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
-
- /* Do readahead for the inplace blocks in this control block */
- {
- unsigned int o2 = offset;
- unsigned int nt2 = num_tags;
-
- while (o2 + sizeof(struct gfs_block_tag) <=
- sdp->sd_sb.sb_bsize) {
- gfs_block_tag_in(&tag, bh->b_data + o2);
- gfs_start_ra(gl, tag.bt_blkno, 1);
- if (!--nt2)
- break;
- o2 += sizeof(struct gfs_block_tag);
- }
- }
-
- while (offset + sizeof(struct gfs_block_tag) <=
- sdp->sd_sb.sb_bsize) {
- gfs_block_tag_in(&tag, bh->b_data + offset);
-
- error = replay_block(sdp, jdesc, gl, &tag, start);
- if (error)
- goto out_drelse;
-
- if (!--num_tags)
- goto out_drelse;
-
- error = gfs_increment_blkno(sdp, jdesc, gl, &start, TRUE);
- if (error)
- goto out_drelse;
-
- offset += sizeof(struct gfs_block_tag);
- }
-
- brelse(bh);
-
- error = gfs_increment_blkno(sdp, jdesc, gl, &cblk, TRUE);
- if (error)
- return error;
-
- offset = 0;
- }
-
- return 0;
-
- out_drelse:
- brelse(bh);
-
- return error;
-}
-
-/**
- * buf_after_scan - called after journal replay
- * @sdp: the filesystem
- * @jid: the journal ID about to be replayed
- * @pass: the pass through the journal
- *
- */
-
-static void
-buf_after_scan(struct gfs_sbd *sdp, unsigned int jid, unsigned int pass)
-{
- if (pass == GFS_RECPASS_A1) {
- printk("GFS: fsid=%s: jid=%u: Replayed %u of %u blocks\n",
- sdp->sd_fsname, jid,
- sdp->sd_recovery_replays,
- sdp->sd_recovery_replays + sdp->sd_recovery_skips +
- sdp->sd_recovery_sames);
- printk("GFS: fsid=%s: jid=%u: replays = %u, skips = %u, sames = %u\n",
- sdp->sd_fsname, jid, sdp->sd_recovery_replays,
- sdp->sd_recovery_skips, sdp->sd_recovery_sames);
- }
-}
-
-/**
- * unlinked_print - print debug info about a log element
- * @sdp: the filesystem
- * @le: the log element
- * @where: is this a new transaction or a incore transaction
- *
- */
-
-static void
-unlinked_print(struct gfs_sbd *sdp, struct gfs_log_element *le,
- unsigned int where)
-{
- struct gfs_unlinked *ul;
- char *type;
-
- switch (where) {
- case TRANS_IS_NEW:
- ul = container_of(le, struct gfs_unlinked, ul_new_le);
- type = (test_bit(ULF_NEW_UL, &ul->ul_flags)) ?
- "unlink" : "dealloc";
- break;
- case TRANS_IS_INCORE:
- ul = container_of(le, struct gfs_unlinked, ul_incore_le);
- type = (test_bit(ULF_INCORE_UL, &ul->ul_flags)) ?
- "unlink" : "dealloc";
- break;
- default:
- gfs_assert_warn(sdp, FALSE);
- return;
- }
-
- printk(" unlinked: %llu/%llu, %s\n",
- (unsigned long long)ul->ul_inum.no_formal_ino,
- (unsigned long long)ul->ul_inum.no_addr,
- type);
-}
-
-/**
- * unlinked_incore_commit - commit this LE to the incore log
- * @sdp: the filesystem
- * @tr: the incore transaction this LE is a part of
- * @le: the log element
- *
- */
-
-static void
-unlinked_incore_commit(struct gfs_sbd *sdp, struct gfs_trans *tr,
- struct gfs_log_element *le)
-{
- struct gfs_unlinked *ul = container_of(le,
- struct gfs_unlinked,
- ul_new_le);
- int n = !!test_bit(ULF_NEW_UL, &ul->ul_flags);
- int i = !!test_bit(ULF_INCORE_UL, &ul->ul_flags);
-
- if (ul->ul_incore_le.le_trans) {
- gfs_assert(sdp, ul->ul_incore_le.le_trans == tr,);
- gfs_assert(sdp, n != i,);
-
- ul->ul_incore_le.le_trans = NULL;
- list_del_init(&ul->ul_incore_le.le_list);
- gfs_unlinked_put(sdp, ul);
-
- if (i) {
- gfs_assert(sdp, tr->tr_num_iul,);
- tr->tr_num_iul--;
- } else {
- gfs_assert(sdp, tr->tr_num_ida,);
- tr->tr_num_ida--;
- }
- } else {
- gfs_unlinked_hold(sdp, ul);
- ul->ul_incore_le.le_trans = tr;
- list_add(&ul->ul_incore_le.le_list, &tr->tr_elements);
-
- if (n) {
- set_bit(ULF_INCORE_UL, &ul->ul_flags);
- if (tr != le->le_trans)
- tr->tr_num_iul++;
- } else {
- clear_bit(ULF_INCORE_UL, &ul->ul_flags);
- if (tr != le->le_trans)
- tr->tr_num_ida++;
- }
- }
-
- if (n) {
- gfs_unlinked_hold(sdp, ul);
- gfs_assert(sdp, !test_bit(ULF_IC_LIST, &ul->ul_flags),);
- set_bit(ULF_IC_LIST, &ul->ul_flags);
- atomic_inc(&sdp->sd_unlinked_ic_count);
- } else {
- gfs_assert(sdp, test_bit(ULF_IC_LIST, &ul->ul_flags),);
- clear_bit(ULF_IC_LIST, &ul->ul_flags);
- gfs_unlinked_put(sdp, ul);
- gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_ic_count),);
- atomic_dec(&sdp->sd_unlinked_ic_count);
- }
-
- le->le_trans = NULL;
- list_del_init(&le->le_list);
- gfs_unlinked_put(sdp, ul);
-}
-
-/**
- * unlinked_add_to_ail - Add this LE to the AIL
- * @sdp: the filesystem
- * @le: the log element
- *
- */
-
-static void
-unlinked_add_to_ail(struct gfs_sbd *sdp, struct gfs_log_element *le)
-{
- struct gfs_unlinked *ul = container_of(le,
- struct gfs_unlinked,
- ul_incore_le);
- int i = !!test_bit(ULF_INCORE_UL, &ul->ul_flags);
-
- if (i) {
- gfs_unlinked_hold(sdp, ul);
- gfs_assert(sdp, !test_bit(ULF_OD_LIST, &ul->ul_flags),);
- set_bit(ULF_OD_LIST, &ul->ul_flags);
- atomic_inc(&sdp->sd_unlinked_od_count);
- } else {
- gfs_assert(sdp, test_bit(ULF_OD_LIST, &ul->ul_flags),);
- clear_bit(ULF_OD_LIST, &ul->ul_flags);
- gfs_unlinked_put(sdp, ul);
- gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_od_count),);
- atomic_dec(&sdp->sd_unlinked_od_count);
- }
-
- le->le_trans = NULL;
- list_del_init(&le->le_list);
- gfs_unlinked_put(sdp, ul);
-}
-
-/**
- * unlinked_clean_dump - clean up a LE after a log dump
- * @sdp: the filesystem
- * @le: the log element
- *
- */
-
-static void
-unlinked_clean_dump(struct gfs_sbd *sdp, struct gfs_log_element *le)
-{
- le->le_trans = NULL;
- list_del_init(&le->le_list);
-}
-
-/**
- * unlinked_trans_size - compute how much space the LE class takes up in a transaction
- * @sdp: the filesystem
- * @tr: the transaction
- * @mblks: the number of regular metadata blocks
- * @eblks: the number of extra blocks
- * @blocks: the number of log blocks
- * @bmem: the number of buffer-sized chunks of memory we need
- *
- */
-
-static void
-unlinked_trans_size(struct gfs_sbd *sdp, struct gfs_trans *tr,
- unsigned int *mblks, unsigned int *eblks,
- unsigned int *blocks, unsigned int *bmem)
-{
- unsigned int ublks = 0;
-
- if (tr->tr_num_iul)
- ublks = gfs_struct2blk(sdp, tr->tr_num_iul,
- sizeof(struct gfs_inum));
- if (tr->tr_num_ida)
- ublks += gfs_struct2blk(sdp, tr->tr_num_ida,
- sizeof(struct gfs_inum));
-
- if (eblks)
- *eblks += ublks;
- if (blocks)
- *blocks += ublks;
- if (bmem)
- *bmem += ublks;
-}
-
-/**
- * unlinked_trans_combine - combine two incore transactions
- * @sdp: the filesystem
- * @tr: the surviving transaction
- * @new_tr: the transaction that's going to disappear
- *
- */
-
-static void
-unlinked_trans_combine(struct gfs_sbd *sdp, struct gfs_trans *tr,
- struct gfs_trans *new_tr)
-{
- tr->tr_num_iul += new_tr->tr_num_iul;
- tr->tr_num_ida += new_tr->tr_num_ida;
-}
-
-/**
- * unlinked_build_bhlist - create the buffers that will make up the ondisk part of a transaction
- * @sdp: the filesystem
- * @tr: the transaction
- *
- * For unlinked and/or deallocated inode log elements (separately):
- * Get a log block
- * Create a log descriptor in beginning of that block
- * Fill rest of block with gfs_inum structs to identify each inode
- * that became unlinked/deallocated during this transaction.
- * Get another log block if needed, continue filling with gfs_inums.
- */
-
-static void
-unlinked_build_bhlist(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct list_head *tmp, *head;
- struct gfs_log_element *le;
- struct gfs_unlinked *ul;
- struct gfs_log_descriptor desc;
- struct gfs_log_buf *lb;
- unsigned int pass = 2;
- unsigned int type, number;
- unsigned int offset, entries;
-
- /* 2 passes: 1st for Unlinked, 2nd for De-Alloced inodes,
- unless this is a log dump: just 1 pass, for Unlinked */
- while (pass--) {
- if (tr->tr_flags & TRF_LOG_DUMP) {
- if (pass) {
- type = GFS_LOG_DESC_IUL;
- number = tr->tr_num_iul;
- } else
- break;
- } else {
- if (pass) {
- type = GFS_LOG_DESC_IUL;
- number = tr->tr_num_iul;
- } else {
- type = GFS_LOG_DESC_IDA;
- number = tr->tr_num_ida;
- }
-
- if (!number)
- continue;
- }
-
- lb = gfs_log_get_buf(sdp, tr);
-
- /* Header: log descriptor */
- memset(&desc, 0, sizeof(struct gfs_log_descriptor));
- desc.ld_header.mh_magic = GFS_MAGIC;
- desc.ld_header.mh_type = GFS_METATYPE_LD;
- desc.ld_header.mh_format = GFS_FORMAT_LD;
- desc.ld_type = type;
- desc.ld_length = gfs_struct2blk(sdp, number, sizeof(struct gfs_inum));
- desc.ld_data1 = (tr->tr_flags & TRF_LOG_DUMP) ? TRUE : FALSE;
- gfs_desc_out(&desc, lb->lb_bh.b_data);
-
- offset = sizeof(struct gfs_log_descriptor);
- entries = 0;
-
- /* Look through transaction's log elements for Unlinked LEs */
- for (head = &tr->tr_elements, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- le = list_entry(tmp, struct gfs_log_element, le_list);
- if (le->le_ops != &gfs_unlinked_lops)
- continue;
- if (tr->tr_flags & TRF_LOG_DUMP)
- ul = container_of(le,
- struct gfs_unlinked,
- ul_ondisk_le);
- else {
- ul = container_of(le,
- struct gfs_unlinked,
- ul_incore_le);
- if (!!test_bit(ULF_INCORE_UL, &ul->ul_flags) != pass)
- continue;
- }
-
- if (offset + sizeof(struct gfs_inum) > sdp->sd_sb.sb_bsize) {
- offset = 0;
- lb = gfs_log_get_buf(sdp, tr);
- }
-
- /* Payload: write the inode identifier */
- gfs_inum_out(&ul->ul_inum,
- lb->lb_bh.b_data + offset);
-
- offset += sizeof(struct gfs_inum);
- entries++;
- }
-
- gfs_assert(sdp, entries == number,);
- }
-}
-
-/**
- * unlinked_dump_size - compute how much space the LE class takes up in a log dump
- * @sdp: the filesystem
- * @elements: the number of log elements in the dump
- * @blocks: the number of blocks in the dump
- * @bmem: the number of buffer-sized chunks of memory we need
- *
- */
-
-static void
-unlinked_dump_size(struct gfs_sbd *sdp, unsigned int *elements,
- unsigned int *blocks, unsigned int *bmem)
-{
- unsigned int c = atomic_read(&sdp->sd_unlinked_od_count);
- unsigned int b = gfs_struct2blk(sdp, c, sizeof(struct gfs_inum));
-
- if (elements)
- *elements += c;
- if (blocks)
- *blocks += b;
- if (bmem)
- *bmem += b;
-}
-
-/**
- * unlinked_build_dump - create a transaction that represents a log dump for this LE class
- * @sdp: the filesystem
- * @tr: the transaction to fill
- *
- */
-
-static void
-unlinked_build_dump(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct list_head *tmp, *head;
- struct gfs_unlinked *ul;
- unsigned int x = 0;
-
- tr->tr_num_iul = atomic_read(&sdp->sd_unlinked_od_count);
-
- spin_lock(&sdp->sd_unlinked_lock);
-
- for (head = &sdp->sd_unlinked_list, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- ul = list_entry(tmp, struct gfs_unlinked, ul_list);
- if (!test_bit(ULF_OD_LIST, &ul->ul_flags))
- continue;
-
- gfs_assert(sdp, !ul->ul_ondisk_le.le_trans,);
- ul->ul_ondisk_le.le_trans = tr;
- list_add(&ul->ul_ondisk_le.le_list, &tr->tr_elements);
-
- x++;
- }
-
- spin_unlock(&sdp->sd_unlinked_lock);
-
- gfs_assert(sdp, x == atomic_read(&sdp->sd_unlinked_od_count),);
-}
-
-/**
- * unlinked_before_scan - called before a log dump is recovered
- * @sdp: the filesystem
- * @jid: the journal ID about to be scanned
- * @head: the current head of the log
- * @pass: the pass through the journal
- *
- */
-
-static void
-unlinked_before_scan(struct gfs_sbd *sdp, unsigned int jid,
- struct gfs_log_header *head, unsigned int pass)
-{
- if (pass == GFS_RECPASS_B1)
- clear_bit(SDF_FOUND_UL_DUMP, &sdp->sd_flags);
-}
-
-/**
- * unlinked_scan_elements - scan unlinked inodes from the journal
- * @sdp: the filesystem
- * @jdesc: the struct gfs_jindex structure for the journal being scaned
- * @gl: the journal's glock
- * @start: the starting block of the descriptor
- * @desc: the descriptor structure
- * @pass: the pass through the journal
- *
- * Returns: errno
- */
-
-static int
-unlinked_scan_elements(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, uint64_t start,
- struct gfs_log_descriptor *desc, unsigned int pass)
-{
- struct gfs_inum inum;
- struct buffer_head *bh;
- unsigned int offset = sizeof(struct gfs_log_descriptor);
- unsigned int x;
- int error;
-
- if (pass != GFS_RECPASS_B1)
- return 0;
-
- switch (desc->ld_type) {
- case GFS_LOG_DESC_IUL:
- if (test_bit(SDF_FOUND_UL_DUMP, &sdp->sd_flags))
- gfs_assert(sdp, !desc->ld_data1,);
- else {
- gfs_assert(sdp, desc->ld_data1,);
- set_bit(SDF_FOUND_UL_DUMP, &sdp->sd_flags);
- }
- break;
-
- case GFS_LOG_DESC_IDA:
- gfs_assert(sdp, test_bit(SDF_FOUND_UL_DUMP, &sdp->sd_flags),);
- break;
-
- default:
- return 0;
- }
-
- for (x = 0; x < desc->ld_length; x++) {
- error = gfs_dread(gl, start, DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
-
- for (;
- offset + sizeof(struct gfs_inum) <= sdp->sd_sb.sb_bsize;
- offset += sizeof(struct gfs_inum)) {
- gfs_inum_in(&inum, bh->b_data + offset);
-
- if (inum.no_addr)
- gfs_unlinked_merge(sdp, desc->ld_type, &inum);
- }
-
- brelse(bh);
-
- error = gfs_increment_blkno(sdp, jdesc, gl, &start, TRUE);
- if (error)
- return error;
-
- offset = 0;
- }
-
- return 0;
-}
-
-/**
- * unlinked_after_scan - called after a log dump is recovered
- * @sdp: the filesystem
- * @jid: the journal ID about to be scanned
- * @pass: the pass through the journal
- *
- */
-
-static void
-unlinked_after_scan(struct gfs_sbd *sdp, unsigned int jid, unsigned int pass)
-{
- if (pass == GFS_RECPASS_B1) {
- gfs_assert(sdp, test_bit(SDF_FOUND_UL_DUMP, &sdp->sd_flags),);
- printk("GFS: fsid=%s: Found %d unlinked inodes\n",
- sdp->sd_fsname, atomic_read(&sdp->sd_unlinked_ic_count));
- }
-}
-
-/**
- * quota_print - print debug info about a log element
- * @sdp: the filesystem
- * @le: the log element
- * @where: is this a new transaction or a incore transaction
- *
- */
-
-static void
-quota_print(struct gfs_sbd *sdp, struct gfs_log_element *le, unsigned int where)
-{
- struct gfs_quota_le *ql;
-
- ql = container_of(le, struct gfs_quota_le, ql_le);
- printk(" quota: %s %u: %lld blocks\n",
- (test_bit(QDF_USER, &ql->ql_data->qd_flags)) ? "user" : "group",
- ql->ql_data->qd_id, (long long)ql->ql_change);
-}
-
-/**
- * quota_incore_commit - commit this LE to the incore log
- * @sdp: the filesystem
- * @tr: the incore transaction this LE is a part of
- * @le: the log element
- *
- */
-
-static void
-quota_incore_commit(struct gfs_sbd *sdp, struct gfs_trans *tr,
- struct gfs_log_element *le)
-{
- struct gfs_quota_le *ql = container_of(le, struct gfs_quota_le, ql_le);
- struct gfs_quota_data *qd = ql->ql_data;
-
- gfs_assert(sdp, ql->ql_change,);
-
- /* Make this change under the sd_quota_lock, so other processes
- checking qd_change_ic don't have to acquire the log lock. */
-
- spin_lock(&sdp->sd_quota_lock);
- qd->qd_change_new -= ql->ql_change;
- qd->qd_change_ic += ql->ql_change;
- spin_unlock(&sdp->sd_quota_lock);
-
- if (le->le_trans == tr)
- list_add(&ql->ql_data_list, &qd->qd_le_list);
- else {
- struct list_head *tmp, *head;
- struct gfs_quota_le *tmp_ql;
- int found = FALSE;
-
- for (head = &qd->qd_le_list, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- tmp_ql = list_entry(tmp, struct gfs_quota_le, ql_data_list);
- if (tmp_ql->ql_le.le_trans != tr)
- continue;
-
- tmp_ql->ql_change += ql->ql_change;
-
- list_del(&le->le_list);
- gfs_quota_put(sdp, qd);
- kfree(ql);
-
- if (!tmp_ql->ql_change) {
- list_del(&tmp_ql->ql_data_list);
- list_del(&tmp_ql->ql_le.le_list);
- gfs_quota_put(sdp, tmp_ql->ql_data);
- kfree(tmp_ql);
- tr->tr_num_q--;
- }
-
- found = TRUE;
- break;
- }
-
- if (!found) {
- le->le_trans = tr;
- list_move(&le->le_list, &tr->tr_elements);
- tr->tr_num_q++;
- list_add(&ql->ql_data_list, &qd->qd_le_list);
- }
- }
-}
-
-/**
- * quota_add_to_ail - Add this LE to the AIL
- * @sdp: the filesystem
- * @le: the log element
- *
- */
-
-static void
-quota_add_to_ail(struct gfs_sbd *sdp, struct gfs_log_element *le)
-{
- struct gfs_quota_le *ql = container_of(le, struct gfs_quota_le, ql_le);
- struct gfs_quota_data *qd = ql->ql_data;
-
- qd->qd_change_od += ql->ql_change;
- if (qd->qd_change_od) {
- if (!test_bit(QDF_OD_LIST, &qd->qd_flags)) {
- gfs_quota_hold(sdp, qd);
- set_bit(QDF_OD_LIST, &qd->qd_flags);
- atomic_inc(&sdp->sd_quota_od_count);
- }
- } else {
- gfs_assert(sdp, test_bit(QDF_OD_LIST, &qd->qd_flags),);
- clear_bit(QDF_OD_LIST, &qd->qd_flags);
- gfs_quota_put(sdp, qd);
- gfs_assert(sdp, atomic_read(&sdp->sd_quota_od_count),);
- atomic_dec(&sdp->sd_quota_od_count);
- }
-
- list_del(&ql->ql_data_list);
- list_del(&le->le_list);
- gfs_quota_put(sdp, qd);
- kfree(ql);
-}
-
-/**
- * quota_clean_dump - clean up a LE after a log dump
- * @sdp: the filesystem
- * @le: the log element
- *
- */
-
-static void
-quota_clean_dump(struct gfs_sbd *sdp, struct gfs_log_element *le)
-{
- le->le_trans = NULL;
- list_del_init(&le->le_list);
-}
-
-/**
- * quota_trans_size - compute how much space the LE class takes up in a transaction
- * @sdp: the filesystem
- * @tr: the transaction
- * @mblks: the number of regular metadata blocks
- * @eblks: the number of extra blocks
- * @blocks: the number of log blocks
- * @bmem: the number of buffer-sized chunks of memory we need
- *
- */
-
-static void
-quota_trans_size(struct gfs_sbd *sdp, struct gfs_trans *tr,
- unsigned int *mblks, unsigned int *eblks,
- unsigned int *blocks, unsigned int *bmem)
-{
- unsigned int qblks;
-
- if (tr->tr_num_q) {
- qblks = gfs_struct2blk(sdp, tr->tr_num_q,
- sizeof(struct gfs_quota_tag));
-
- if (eblks)
- *eblks += qblks;
- if (blocks)
- *blocks += qblks;
- if (bmem)
- *bmem += qblks;
- }
-}
-
-/**
- * quota_trans_combine - combine two incore transactions
- * @sdp: the filesystem
- * @tr: the surviving transaction
- * @new_tr: the transaction that's going to disappear
- *
- */
-
-static void
-quota_trans_combine(struct gfs_sbd *sdp, struct gfs_trans *tr,
- struct gfs_trans *new_tr)
-{
- tr->tr_num_q += new_tr->tr_num_q;
-}
-
-/**
- * quota_build_bhlist - create the buffers that will make up the ondisk part of a transaction
- * @sdp: the filesystem
- * @tr: the transaction
- *
- */
-
-static void
-quota_build_bhlist(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct list_head *tmp, *head;
- struct gfs_log_element *le;
- struct gfs_quota_le *ql;
- struct gfs_log_descriptor desc;
- struct gfs_quota_tag tag;
- struct gfs_log_buf *lb;
- unsigned int offset = sizeof(struct gfs_log_descriptor), entries = 0;
-
- if (!tr->tr_num_q && !(tr->tr_flags & TRF_LOG_DUMP))
- return;
-
- lb = gfs_log_get_buf(sdp, tr);
-
- memset(&desc, 0, sizeof(struct gfs_log_descriptor));
- desc.ld_header.mh_magic = GFS_MAGIC;
- desc.ld_header.mh_type = GFS_METATYPE_LD;
- desc.ld_header.mh_format = GFS_FORMAT_LD;
- desc.ld_type = GFS_LOG_DESC_Q;
- desc.ld_length = gfs_struct2blk(sdp, tr->tr_num_q,
- sizeof(struct gfs_quota_tag));
- desc.ld_data1 = tr->tr_num_q;
- desc.ld_data2 = (tr->tr_flags & TRF_LOG_DUMP) ? TRUE : FALSE;
- gfs_desc_out(&desc, lb->lb_bh.b_data);
-
- for (head = &tr->tr_elements, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- le = list_entry(tmp, struct gfs_log_element, le_list);
- if (le->le_ops != &gfs_quota_lops)
- continue;
-
- ql = container_of(le, struct gfs_quota_le, ql_le);
-
- if (offset + sizeof(struct gfs_quota_tag) >
- sdp->sd_sb.sb_bsize) {
- offset = 0;
- lb = gfs_log_get_buf(sdp, tr);
- }
-
- memset(&tag, 0, sizeof(struct gfs_quota_tag));
- tag.qt_change = ql->ql_change;
- tag.qt_flags = (test_bit(QDF_USER, &ql->ql_data->qd_flags)) ?
- GFS_QTF_USER : 0;
- tag.qt_id = ql->ql_data->qd_id;
-
- gfs_quota_tag_out(&tag, lb->lb_bh.b_data + offset);
-
- offset += sizeof(struct gfs_quota_tag);
- entries++;
- }
-
- gfs_assert(sdp, entries == tr->tr_num_q,);
-}
-
-/**
- * quota_dump_size - compute how much space the LE class takes up in a log dump
- * @sdp: the filesystem
- * @elements: the number of log elements in the dump
- * @blocks: the number of blocks in the dump
- * @bmem: the number of buffer-sized chunks of memory we need
- *
- */
-
-static void
-quota_dump_size(struct gfs_sbd *sdp, unsigned int *elements,
- unsigned int *blocks, unsigned int *bmem)
-{
- unsigned int c = atomic_read(&sdp->sd_quota_od_count);
- unsigned int b = gfs_struct2blk(sdp, c, sizeof(struct gfs_quota_tag));
-
- if (elements)
- *elements += c;
- if (blocks)
- *blocks += b;
- if (bmem)
- *bmem += b;
-}
-
-/**
- * quota_build_dump - create a transaction that represents a log dump for this LE class
- * @sdp: the filesystem
- * @tr: the transaction to fill
- *
- */
-
-static void
-quota_build_dump(struct gfs_sbd *sdp, struct gfs_trans *tr)
-{
- struct list_head *tmp, *head;
- struct gfs_quota_data *qd;
- struct gfs_quota_le *ql;
- unsigned int x = 0;
-
- tr->tr_num_q = atomic_read(&sdp->sd_quota_od_count);
-
- spin_lock(&sdp->sd_quota_lock);
-
- for (head = &sdp->sd_quota_list, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- qd = list_entry(tmp, struct gfs_quota_data, qd_list);
- if (!test_bit(QDF_OD_LIST, &qd->qd_flags))
- continue;
-
- ql = &qd->qd_ondisk_ql;
-
- ql->ql_le.le_ops = &gfs_quota_lops;
- gfs_assert(sdp, !ql->ql_le.le_trans,);
- ql->ql_le.le_trans = tr;
- list_add(&ql->ql_le.le_list, &tr->tr_elements);
-
- ql->ql_data = qd;
- ql->ql_change = qd->qd_change_od;
-
- x++;
- }
-
- spin_unlock(&sdp->sd_quota_lock);
-
- gfs_assert(sdp, x == atomic_read(&sdp->sd_quota_od_count),);
-}
-
-/**
- * quota_before_scan - called before a log dump is recovered
- * @sdp: the filesystem
- * @jid: the journal ID about to be scanned
- * @head: the current head of the log
- * @pass: the pass through the journal
- *
- */
-
-static void
-quota_before_scan(struct gfs_sbd *sdp, unsigned int jid,
- struct gfs_log_header *head, unsigned int pass)
-{
- if (pass == GFS_RECPASS_B1)
- clear_bit(SDF_FOUND_Q_DUMP, &sdp->sd_flags);
-}
-
-/**
- * quota_scan_elements - scan quota inodes from the journal
- * @sdp: the filesystem
- * @jdesc: the struct gfs_jindex structure for the journal being scaned
- * @gl: the journal's glock
- * @start: the starting block of the descriptor
- * @desc: the descriptor structure
- * @pass: the pass through the journal
- *
- * Returns: errno
- */
-
-static int
-quota_scan_elements(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, uint64_t start,
- struct gfs_log_descriptor *desc, unsigned int pass)
-{
- struct gfs_quota_tag tag;
- struct buffer_head *bh;
- unsigned int num_tags = desc->ld_data1;
- unsigned int offset = sizeof(struct gfs_log_descriptor);
- unsigned int x;
- int error;
-
- if (pass != GFS_RECPASS_B1)
- return 0;
- if (desc->ld_type != GFS_LOG_DESC_Q)
- return 0;
-
- if (test_bit(SDF_FOUND_Q_DUMP, &sdp->sd_flags))
- gfs_assert(sdp, !desc->ld_data2,);
- else {
- gfs_assert(sdp, desc->ld_data2,);
- set_bit(SDF_FOUND_Q_DUMP, &sdp->sd_flags);
- }
-
- if (!num_tags)
- return 0;
-
- for (x = 0; x < desc->ld_length; x++) {
- error = gfs_dread(gl, start, DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
-
- while (offset + sizeof(struct gfs_quota_tag) <=
- sdp->sd_sb.sb_bsize) {
- gfs_quota_tag_in(&tag, bh->b_data + offset);
-
- error = gfs_quota_merge(sdp, &tag);
- if (error)
- goto out_drelse;
-
- if (!--num_tags)
- goto out_drelse;
-
- offset += sizeof(struct gfs_quota_tag);
- }
-
- brelse(bh);
-
- error = gfs_increment_blkno(sdp, jdesc, gl, &start, TRUE);
- if (error)
- return error;
-
- offset = 0;
- }
-
- return 0;
-
- out_drelse:
- brelse(bh);
-
- return error;
-}
-
-/**
- * quota_after_scan - called after a log dump is recovered
- * @sdp: the filesystem
- * @jid: the journal ID about to be scanned
- * @pass: the pass through the journal
- *
- */
-
-static void
-quota_after_scan(struct gfs_sbd *sdp, unsigned int jid, unsigned int pass)
-{
- if (pass == GFS_RECPASS_B1) {
- gfs_assert(sdp, !sdp->sd_sb.sb_quota_di.no_formal_ino ||
- test_bit(SDF_FOUND_Q_DUMP, &sdp->sd_flags),);
- printk("GFS: fsid=%s: Found quota changes for %d IDs\n",
- sdp->sd_fsname, atomic_read(&sdp->sd_quota_od_count));
- }
-}
-
-struct gfs_log_operations gfs_glock_lops = {
- .lo_add = generic_le_add,
- .lo_trans_end = glock_trans_end,
- .lo_print = glock_print,
- .lo_overlap_trans = glock_overlap_trans,
- .lo_incore_commit = glock_incore_commit,
- .lo_add_to_ail = glock_add_to_ail,
- .lo_trans_combine = glock_trans_combine,
- .lo_name = "glock"
-};
-
-struct gfs_log_operations gfs_buf_lops = {
- .lo_add = generic_le_add,
- .lo_print = buf_print,
- .lo_incore_commit = buf_incore_commit,
- .lo_add_to_ail = buf_add_to_ail,
- .lo_trans_size = buf_trans_size,
- .lo_trans_combine = buf_trans_combine,
- .lo_build_bhlist = buf_build_bhlist,
- .lo_before_scan = buf_before_scan,
- .lo_scan_elements = buf_scan_elements,
- .lo_after_scan = buf_after_scan,
- .lo_name = "buf"
-};
-
-struct gfs_log_operations gfs_unlinked_lops = {
- .lo_add = generic_le_add,
- .lo_print = unlinked_print,
- .lo_incore_commit = unlinked_incore_commit,
- .lo_add_to_ail = unlinked_add_to_ail,
- .lo_clean_dump = unlinked_clean_dump,
- .lo_trans_size = unlinked_trans_size,
- .lo_trans_combine = unlinked_trans_combine,
- .lo_build_bhlist = unlinked_build_bhlist,
- .lo_dump_size = unlinked_dump_size,
- .lo_build_dump = unlinked_build_dump,
- .lo_before_scan = unlinked_before_scan,
- .lo_scan_elements = unlinked_scan_elements,
- .lo_after_scan = unlinked_after_scan,
- .lo_name = "unlinked"
-};
-
-struct gfs_log_operations gfs_quota_lops = {
- .lo_add = generic_le_add,
- .lo_print = quota_print,
- .lo_incore_commit = quota_incore_commit,
- .lo_add_to_ail = quota_add_to_ail,
- .lo_clean_dump = quota_clean_dump,
- .lo_trans_size = quota_trans_size,
- .lo_trans_combine = quota_trans_combine,
- .lo_build_bhlist = quota_build_bhlist,
- .lo_dump_size = quota_dump_size,
- .lo_build_dump = quota_build_dump,
- .lo_before_scan = quota_before_scan,
- .lo_scan_elements = quota_scan_elements,
- .lo_after_scan = quota_after_scan,
- .lo_name = "quota"
-};
-
-struct gfs_log_operations *gfs_log_ops[] = {
- &gfs_glock_lops,
- &gfs_buf_lops,
- &gfs_unlinked_lops,
- &gfs_quota_lops,
- NULL
-};
diff --git a/gfs-kernel/src/gfs/lops.h b/gfs-kernel/src/gfs/lops.h
deleted file mode 100644
index 2b752f1..0000000
--- a/gfs-kernel/src/gfs/lops.h
+++ /dev/null
@@ -1,166 +0,0 @@
-#ifndef __LOPS_DOT_H__
-#define __LOPS_DOT_H__
-
-extern struct gfs_log_operations gfs_glock_lops;
-extern struct gfs_log_operations gfs_buf_lops;
-extern struct gfs_log_operations gfs_unlinked_lops;
-extern struct gfs_log_operations gfs_quota_lops;
-
-extern struct gfs_log_operations *gfs_log_ops[];
-
-#define INIT_LE(le, lops) \
-do \
-{ \
- (le)->le_ops = (lops); \
- (le)->le_trans = NULL; \
- INIT_LIST_HEAD(&(le)->le_list); \
-} \
-while (0)
-
-#define LO_ADD(sdp, le) \
-do \
-{ \
- if ((le)->le_ops->lo_add) \
- (le)->le_ops->lo_add((sdp), (le)); \
-} \
-while (0)
-
-#define LO_TRANS_END(sdp, le) \
-do \
-{ \
- if ((le)->le_ops->lo_trans_end) \
- (le)->le_ops->lo_trans_end((sdp), (le)); \
-} \
-while (0)
-
-#define LO_PRINT(sdp, le, where) \
-do \
-{ \
- if ((le)->le_ops->lo_print) \
- (le)->le_ops->lo_print((sdp), (le), (where)); \
-} \
-while (0)
-
-static __inline__ struct gfs_trans *
-LO_OVERLAP_TRANS(struct gfs_sbd *sdp, struct gfs_log_element *le)
-{
- if (le->le_ops->lo_overlap_trans)
- return le->le_ops->lo_overlap_trans(sdp, le);
- else
- return NULL;
-}
-
-#define LO_INCORE_COMMIT(sdp, tr, le) \
-do \
-{ \
- if ((le)->le_ops->lo_incore_commit) \
- (le)->le_ops->lo_incore_commit((sdp), (tr), (le)); \
-} \
-while (0)
-
-#define LO_ADD_TO_AIL(sdp, le) \
-do \
-{ \
- if ((le)->le_ops->lo_add_to_ail) \
- (le)->le_ops->lo_add_to_ail((sdp), (le)); \
-} \
-while (0)
-
-#define LO_CLEAN_DUMP(sdp, le) \
-do \
-{ \
- if ((le)->le_ops->lo_clean_dump) \
- (le)->le_ops->lo_clean_dump((sdp), (le)); \
-} \
-while (0)
-
-#define LO_TRANS_SIZE(sdp, tr, mblks, eblks, blocks, bmem) \
-do \
-{ \
- int __lops_x; \
- for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \
- if (gfs_log_ops[__lops_x]->lo_trans_size) \
- gfs_log_ops[__lops_x]->lo_trans_size((sdp), (tr), (mblks), (eblks), (blocks), (bmem)); \
-} \
-while (0)
-
-#define LO_TRANS_COMBINE(sdp, tr, new_tr) \
-do \
-{ \
- int __lops_x; \
- for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \
- if (gfs_log_ops[__lops_x]->lo_trans_combine) \
- gfs_log_ops[__lops_x]->lo_trans_combine((sdp), (tr), (new_tr)); \
-} \
-while (0)
-
-#define LO_BUILD_BHLIST(sdp, tr) \
-do \
-{ \
- int __lops_x; \
- for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \
- if (gfs_log_ops[__lops_x]->lo_build_bhlist) \
- gfs_log_ops[__lops_x]->lo_build_bhlist((sdp), (tr)); \
-} \
-while (0)
-
-#define LO_DUMP_SIZE(sdp, elements, blocks, bmem) \
-do \
-{ \
- int __lops_x; \
- for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \
- if (gfs_log_ops[__lops_x]->lo_dump_size) \
- gfs_log_ops[__lops_x]->lo_dump_size((sdp), (elements), (blocks), (bmem)); \
-} \
-while (0)
-
-#define LO_BUILD_DUMP(sdp, tr) \
-do \
-{ \
- int __lops_x; \
- for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \
- if (gfs_log_ops[__lops_x]->lo_build_dump) \
- gfs_log_ops[__lops_x]->lo_build_dump((sdp), (tr)); \
-} \
-while (0)
-
-#define LO_BEFORE_SCAN(sdp, jid, head, pass) \
-do \
-{ \
- int __lops_x; \
- for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \
- if (gfs_log_ops[__lops_x]->lo_before_scan) \
- gfs_log_ops[__lops_x]->lo_before_scan((sdp), (jid), (head), (pass)); \
-} \
-while (0)
-
-static __inline__ int
-LO_SCAN_ELEMENTS(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, uint64_t start,
- struct gfs_log_descriptor *desc, unsigned int pass)
-{
- int x;
- int error;
-
- for (x = 0; gfs_log_ops[x]; x++)
- if (gfs_log_ops[x]->lo_scan_elements) {
- error = gfs_log_ops[x]->lo_scan_elements(sdp, jdesc, gl,
- start, desc, pass);
- if (error)
- return error;
- }
-
- return 0;
-}
-
-#define LO_AFTER_SCAN(sdp, jid, pass) \
-do \
-{ \
- int __lops_x; \
- for (__lops_x = 0; gfs_log_ops[__lops_x]; __lops_x++) \
- if (gfs_log_ops[__lops_x]->lo_after_scan) \
- gfs_log_ops[__lops_x]->lo_after_scan((sdp), (jid), (pass)); \
-} \
-while (0)
-
-#endif /* __LOPS_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/lvb.c b/gfs-kernel/src/gfs/lvb.c
deleted file mode 100644
index 8e7d75d..0000000
--- a/gfs-kernel/src/gfs/lvb.c
+++ /dev/null
@@ -1,135 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-
-#define pv(struct, member, fmt) printk(" "#member" = "fmt"\n", struct->member);
-
-#define CPIN_08(s1, s2, member, count) {memcpy((s1->member), (s2->member), (count));}
-#define CPOUT_08(s1, s2, member, count) {memcpy((s2->member), (s1->member), (count));}
-#define CPIN_16(s1, s2, member) {(s1->member) = gfs16_to_cpu((s2->member));}
-#define CPOUT_16(s1, s2, member) {(s2->member) = cpu_to_gfs16((s1->member));}
-#define CPIN_32(s1, s2, member) {(s1->member) = gfs32_to_cpu((s2->member));}
-#define CPOUT_32(s1, s2, member) {(s2->member) = cpu_to_gfs32((s1->member));}
-#define CPIN_64(s1, s2, member) {(s1->member) = gfs64_to_cpu((s2->member));}
-#define CPOUT_64(s1, s2, member) {(s2->member) = cpu_to_gfs64((s1->member));}
-
-/**
- * gfs_rgrp_lvb_in - Read in rgrp data
- * @rb: the cpu-order structure
- * @lvb: the lvb
- *
- */
-
-void
-gfs_rgrp_lvb_in(struct gfs_rgrp_lvb *rb, char *lvb)
-{
- struct gfs_rgrp_lvb *str = (struct gfs_rgrp_lvb *)lvb;
-
- CPIN_32(rb, str, rb_magic);
- CPIN_32(rb, str, rb_free);
- CPIN_32(rb, str, rb_useddi);
- CPIN_32(rb, str, rb_freedi);
- CPIN_32(rb, str, rb_usedmeta);
- CPIN_32(rb, str, rb_freemeta);
-}
-
-/**
- * gfs_rgrp_lvb_out - Write out rgrp data
- * @rb: the cpu-order structure
- * @lvb: the lvb
- *
- */
-
-void
-gfs_rgrp_lvb_out(struct gfs_rgrp_lvb *rb, char *lvb)
-{
- struct gfs_rgrp_lvb *str = (struct gfs_rgrp_lvb *)lvb;
-
- CPOUT_32(rb, str, rb_magic);
- CPOUT_32(rb, str, rb_free);
- CPOUT_32(rb, str, rb_useddi);
- CPOUT_32(rb, str, rb_freedi);
- CPOUT_32(rb, str, rb_usedmeta);
- CPOUT_32(rb, str, rb_freemeta);
-}
-
-/**
- * gfs_rgrp_lvb_print - Print out rgrp data
- * @rb: the cpu-order structure
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- */
-
-void
-gfs_rgrp_lvb_print(struct gfs_rgrp_lvb *rb)
-{
- pv(rb, rb_magic, "%u");
- pv(rb, rb_free, "%u");
- pv(rb, rb_useddi, "%u");
- pv(rb, rb_freedi, "%u");
- pv(rb, rb_usedmeta, "%u");
- pv(rb, rb_freemeta, "%u");
-}
-
-/**
- * gfs_quota_lvb_in - Read in quota data
- * @rb: the cpu-order structure
- * @lvb: the lvb
- *
- */
-
-void
-gfs_quota_lvb_in(struct gfs_quota_lvb *qb, char *lvb)
-{
- struct gfs_quota_lvb *str = (struct gfs_quota_lvb *)lvb;
-
- CPIN_32(qb, str, qb_magic);
- CPIN_32(qb, str, qb_pad);
- CPIN_64(qb, str, qb_limit);
- CPIN_64(qb, str, qb_warn);
- CPIN_64(qb, str, qb_value);
-}
-
-/**
- * gfs_quota_lvb_out - Write out quota data
- * @rb: the cpu-order structure
- * @lvb: the lvb
- *
- */
-
-void
-gfs_quota_lvb_out(struct gfs_quota_lvb *qb, char *lvb)
-{
- struct gfs_quota_lvb *str = (struct gfs_quota_lvb *)lvb;
-
- CPOUT_32(qb, str, qb_magic);
- CPOUT_32(qb, str, qb_pad);
- CPOUT_64(qb, str, qb_limit);
- CPOUT_64(qb, str, qb_warn);
- CPOUT_64(qb, str, qb_value);
-}
-
-/**
- * gfs_quota_lvb_print - Print out quota data
- * @rb: the cpu-order structure
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- */
-
-void
-gfs_quota_lvb_print(struct gfs_quota_lvb *qb)
-{
- pv(qb, qb_magic, "%u");
- pv(qb, qb_pad, "%u");
- pv(qb, qb_limit, "%llu");
- pv(qb, qb_warn, "%llu");
- pv(qb, qb_value, "%lld");
-}
diff --git a/gfs-kernel/src/gfs/lvb.h b/gfs-kernel/src/gfs/lvb.h
deleted file mode 100644
index e729491..0000000
--- a/gfs-kernel/src/gfs/lvb.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Formats of Lock Value Blocks (LVBs) for various types of locks.
- * These 32-bit data chunks can be shared quickly between nodes
- * via the inter-node lock manager (via LAN instead of on-disk).
- */
-
-#ifndef __LVB_DOT_H__
-#define __LVB_DOT_H__
-
-#define GFS_MIN_LVB_SIZE (32)
-
-/*
- * Resource Group block allocation statistics
- * Each resource group lock contains one of these in its LVB.
- * Used for sharing approximate current statistics for statfs.
- * Not used for actual block allocation.
- */
-struct gfs_rgrp_lvb {
- uint32_t rb_magic; /* GFS_MAGIC sanity check value */
- uint32_t rb_free; /* # free data blocks */
- uint32_t rb_useddi; /* # used dinode blocks */
- uint32_t rb_freedi; /* # free dinode blocks */
- uint32_t rb_usedmeta; /* # used metadata blocks */
- uint32_t rb_freemeta; /* # free metadata blocks */
-};
-
-/*
- * Quota
- * Each quota lock contains one of these in its LVB.
- * Keeps track of block allocation limits and current block allocation
- * for either a cluster-wide user or a cluster-wide group.
- */
-struct gfs_quota_lvb {
- uint32_t qb_magic; /* GFS_MAGIC sanity check value */
- uint32_t qb_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 */
-};
-
-/* Translation functions */
-
-void gfs_rgrp_lvb_in(struct gfs_rgrp_lvb *rb, char *lvb);
-void gfs_rgrp_lvb_out(struct gfs_rgrp_lvb *rb, char *lvb);
-void gfs_quota_lvb_in(struct gfs_quota_lvb *qb, char *lvb);
-void gfs_quota_lvb_out(struct gfs_quota_lvb *qb, char *lvb);
-
-/* Printing functions */
-
-void gfs_rgrp_lvb_print(struct gfs_rgrp_lvb *rb);
-void gfs_quota_lvb_print(struct gfs_quota_lvb *qb);
-
-#endif /* __LVB_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/main.c b/gfs-kernel/src/gfs/main.c
deleted file mode 100644
index 16b520b..0000000
--- a/gfs-kernel/src/gfs/main.c
+++ /dev/null
@@ -1,134 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/proc_fs.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/time.h>
-
-#include "gfs.h"
-#include "ops_fstype.h"
-#include "sys.h"
-#include "proc.h"
-
-/**
- * init_gfs_fs - Register GFS as a filesystem
- *
- * Returns: 0 on success, error code on failure
- */
-
-int __init init_gfs_fs(void)
-{
- int error;
- struct timespec tv;
-
-/* gfs2_init_lmh(); gfs2 should do this for us*/
-
- error = gfs_sys_init();
- if (error)
- return error;
- error = gfs_proc_init();
- if (error)
- goto fail;
-
- getnstimeofday(&tv);
- gfs_random_number = tv.tv_nsec;
-
- gfs_glock_cachep = kmem_cache_create("gfs_glock", sizeof(struct gfs_glock),
- 0, 0,
- NULL);
- gfs_inode_cachep = NULL;
- gfs_bufdata_cachep = NULL;
- gfs_mhc_cachep = NULL;
- error = -ENOMEM;
- if (!gfs_glock_cachep)
- goto fail1;
-
- gfs_inode_cachep = kmem_cache_create("gfs_inode", sizeof(struct gfs_inode),
- 0, 0,
- NULL);
- if (!gfs_inode_cachep)
- goto fail1;
-
- gfs_bufdata_cachep = kmem_cache_create("gfs_bufdata", sizeof(struct gfs_bufdata),
- 0, 0,
- NULL);
- if (!gfs_bufdata_cachep)
- goto fail1;
-
- gfs_mhc_cachep = kmem_cache_create("gfs_meta_header_cache", sizeof(struct gfs_meta_header_cache),
- 0, 0,
- NULL);
- if (!gfs_mhc_cachep)
- goto fail;
-
- error = register_filesystem(&gfs_fs_type);
- if (error)
- goto fail;
-
- printk("GFS %s (built %s %s) installed\n",
- RELEASE_VERSION, __DATE__, __TIME__);
-
- error = init_lock_dlm();
- if (error)
- goto fail1;
-
- error = init_nolock();
- if (error)
- goto fail1;
-
- return 0;
-
- fail1:
- if (gfs_mhc_cachep)
- kmem_cache_destroy(gfs_mhc_cachep);
-
- if (gfs_bufdata_cachep)
- kmem_cache_destroy(gfs_bufdata_cachep);
-
- if (gfs_inode_cachep)
- kmem_cache_destroy(gfs_inode_cachep);
-
- if (gfs_glock_cachep)
- kmem_cache_destroy(gfs_glock_cachep);
-
- gfs_proc_uninit();
-
- fail:
- gfs_sys_uninit();
-
- return error;
-}
-
-/**
- * exit_gfs_fs - Unregister the file system
- *
- */
-
-void __exit
-exit_gfs_fs(void)
-{
- exit_nolock();
- exit_lock_dlm();
- unregister_filesystem(&gfs_fs_type);
-
- kmem_cache_destroy(gfs_mhc_cachep);
- kmem_cache_destroy(gfs_bufdata_cachep);
- kmem_cache_destroy(gfs_inode_cachep);
- kmem_cache_destroy(gfs_glock_cachep);
-
- gfs_proc_uninit();
- gfs_sys_uninit();
-}
-
-MODULE_DESCRIPTION("Global File System " RELEASE_VERSION);
-MODULE_AUTHOR("Red Hat, Inc.");
-MODULE_LICENSE("GPL");
-
-module_init(init_gfs_fs);
-module_exit(exit_gfs_fs);
-
diff --git a/gfs-kernel/src/gfs/mount.c b/gfs-kernel/src/gfs/mount.c
deleted file mode 100644
index 51e40c8..0000000
--- a/gfs-kernel/src/gfs/mount.c
+++ /dev/null
@@ -1,209 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "mount.h"
-#include "proc.h"
-#include "sys.h"
-
-/**
- * gfs_make_args - Parse mount arguments
- * @data:
- * @args:
- *
- * Return: errno
- */
-
-int
-gfs_make_args(char *data_arg, struct gfs_args *args, int remount)
-{
- char *data = data_arg;
- char *options, *x, *y;
- int error = 0;
-
- /* If someone preloaded options, use those instead */
-
- spin_lock(&gfs_proc_margs_lock);
- if (!remount && gfs_proc_margs) {
- data = gfs_proc_margs;
- gfs_proc_margs = NULL;
- }
- spin_unlock(&gfs_proc_margs_lock);
-
- /* Set some defaults */
-
- memset(args, 0, sizeof(struct gfs_args));
- args->ar_num_glockd = GFS_GLOCKD_DEFAULT;
- args->ar_errors = GFS_ERRORS_WITHDRAW;
-
- if (!remount) {
- /* If someone preloaded options, use those instead */
- spin_lock(&gfs_sys_margs_lock);
- if (gfs_sys_margs) {
- data = gfs_sys_margs;
- gfs_sys_margs = NULL;
- }
- spin_unlock(&gfs_sys_margs_lock);
-
- /* Set some defaults */
- args->ar_num_glockd = GFS_GLOCKD_DEFAULT;
- }
-
- /* Split the options into tokens with the "," character and
- process them */
-
- for (options = data; (x = strsep(&options, ",")); ) {
- if (!*x)
- continue;
-
- y = strchr(x, '=');
- if (y)
- *y++ = 0;
-
- if (!strcmp(x, "lockproto")) {
- if (!y) {
- printk("GFS: need argument to lockproto\n");
- error = -EINVAL;
- break;
- }
- strncpy(args->ar_lockproto, y, GFS_LOCKNAME_LEN);
- args->ar_lockproto[GFS_LOCKNAME_LEN - 1] = 0;
- }
-
- else if (!strcmp(x, "locktable")) {
- if (!y) {
- printk("GFS: need argument to locktable\n");
- error = -EINVAL;
- break;
- }
- strncpy(args->ar_locktable, y, GFS_LOCKNAME_LEN);
- args->ar_locktable[GFS_LOCKNAME_LEN - 1] = 0;
- }
-
- else if (!strcmp(x, "hostdata")) {
- if (!y) {
- printk("GFS: need argument to hostdata\n");
- error = -EINVAL;
- break;
- }
- strncpy(args->ar_hostdata, y, GFS_LOCKNAME_LEN);
- args->ar_hostdata[GFS_LOCKNAME_LEN - 1] = 0;
- }
-
- else if (!strcmp(x, "spectator"))
- args->ar_spectator = TRUE;
-
- else if (!strcmp(x, "ignore_local_fs"))
- args->ar_ignore_local_fs = TRUE;
-
- else if (!strcmp(x, "localflocks"))
- args->ar_localflocks = TRUE;
-
- else if (!strcmp(x, "localcaching"))
- args->ar_localcaching = TRUE;
-
- else if (!strcmp(x, "oopses_ok")) {
- if (args->ar_errors == GFS_ERRORS_PANIC) {
- printk("GFS: -o oopses_ok and -o errors=panic "
- "are mutually exclusive.\n");
- error = -EINVAL;
- break;
- }
- args->ar_oopses_ok = TRUE;
- } else if (!strcmp(x, "debug")) {
- if (args->ar_errors == GFS_ERRORS_PANIC) {
- printk("GFS: -o debug and -o errors=panic "
- "are mutually exclusive.\n");
- error = -EINVAL;
- break;
- }
- args->ar_oopses_ok = TRUE;
- args->ar_debug = TRUE;
-
- } else if (!strcmp(x, "upgrade"))
- args->ar_upgrade = TRUE;
-
- else if (!strcmp(x, "num_glockd")) {
- if (!y) {
- printk("GFS: need argument to num_glockd\n");
- error = -EINVAL;
- break;
- }
- sscanf(y, "%u", &args->ar_num_glockd);
- if (!args->ar_num_glockd || args->ar_num_glockd > GFS_GLOCKD_MAX) {
- printk("GFS: 0 < num_glockd <= %u (not %u)\n",
- GFS_GLOCKD_MAX, args->ar_num_glockd);
- error = -EINVAL;
- break;
- }
- }
-
- else if (!strcmp(x, "acl"))
- args->ar_posix_acls = TRUE;
-
- else if (!strcmp(x, "noacl"))
- args->ar_posix_acls = FALSE;
-
- else if (!strcmp(x, "suiddir"))
- args->ar_suiddir = TRUE;
-
- else if (!strcmp(x, "noquota"))
- args->ar_noquota = TRUE;
-
- else if (!strcmp(x, "gfs_noatime"))
- args->ar_noatime = TRUE;
-
- else if (!strcmp(x, "errors")) {
- if (!y) {
- printk("GFS: need argument to errors\n");
- error = -EINVAL;
- break;
- }
- if (!strcmp(y, "withdraw"))
- args->ar_errors = GFS_ERRORS_WITHDRAW;
- else if (!strcmp(y, "panic")) {
- if (args->ar_debug) {
- printk("GFS: -o debug and -o errors="
- "panic are mutually "
- "exclusive.\n");
- error = -EINVAL;
- break;
- } else if (args->ar_oopses_ok) {
- printk("GFS: -o oopses_ok and -o "
- "errors=panic are mutually "
- "exclusive.\n");
- error = -EINVAL;
- break;
- }
- args->ar_errors = GFS_ERRORS_PANIC;
- } else {
- printk("GFS: errors= must be either withdraw "
- "or panic.\n");
- error = -EINVAL;
- break;
- }
- }
-
- /* Unknown */
-
- else {
- printk("GFS: unknown option: %s\n", x);
- error = -EINVAL;
- break;
- }
- }
-
- if (error)
- printk("GFS: invalid mount option(s)\n");
-
- if (data != data_arg)
- kfree(data);
-
- return error;
-}
-
diff --git a/gfs-kernel/src/gfs/mount.h b/gfs-kernel/src/gfs/mount.h
deleted file mode 100644
index d3d09c9..0000000
--- a/gfs-kernel/src/gfs/mount.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __MOUNT_DOT_H__
-#define __MOUNT_DOT_H__
-
-int gfs_make_args(char *data, struct gfs_args *args, int remount);
-
-#endif /* __MOUNT_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/ondisk.c b/gfs-kernel/src/gfs/ondisk.c
deleted file mode 100644
index 1d169eb..0000000
--- a/gfs-kernel/src/gfs/ondisk.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-
-#define pv(struct, member, fmt) printk(" "#member" = "fmt"\n", struct->member);
-
-#define WANT_GFS_CONVERSION_FUNCTIONS
-#include "gfs_ondisk.h"
-
diff --git a/gfs-kernel/src/gfs/ops_address.c b/gfs-kernel/src/gfs/ops_address.c
deleted file mode 100644
index 5e55477..0000000
--- a/gfs-kernel/src/gfs/ops_address.c
+++ /dev/null
@@ -1,504 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/pagemap.h>
-
-#include "gfs.h"
-#include "bmap.h"
-#include "dio.h"
-#include "file.h"
-#include "glock.h"
-#include "inode.h"
-#include "ops_address.h"
-#include "page.h"
-#include "quota.h"
-#include "trans.h"
-
-static int
-gfs_write_end(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *page, void *fsdata);
-
-/**
- * get_block - Fills in a buffer head with details about a block
- * @inode: The inode
- * @lblock: The block number to look up
- * @bh_result: The buffer head to return the result in
- * @create: Non-zero if we may add block to the file
- *
- * Returns: errno
- */
-
-static int
-get_block(struct inode *inode, sector_t lblock,
- struct buffer_head *bh_result, int create)
-{
- struct gfs_inode *ip = get_v2ip(inode);
- int new = create;
- uint64_t dblock;
- int error;
-
- error = gfs_block_map(ip, lblock, &new, &dblock, NULL);
- if (error)
- return error;
-
- if (!dblock)
- return 0;
-
- map_bh(bh_result, inode->i_sb, dblock);
- if (new)
- set_buffer_new(bh_result);
-
- return 0;
-}
-
-/**
- * get_block_noalloc - Fills in a buffer head with details about a block
- * @inode: The inode
- * @lblock: The block number to look up
- * @bh_result: The buffer head to return the result in
- * @create: Non-zero if we may add block to the file
- *
- * Returns: errno
- */
-
-static int
-get_block_noalloc(struct inode *inode, sector_t lblock,
- struct buffer_head *bh_result, int create)
-{
- int error;
-
- error = get_block(inode, lblock, bh_result, FALSE);
- if (error)
- return error;
-
- if (gfs_assert_withdraw(get_v2sdp(inode->i_sb),
- !create || buffer_mapped(bh_result)))
- return -EIO;
-
- return 0;
-}
-
-/**
- * get_blocks -
- * @inode:
- * @lblock:
- * @max_blocks:
- * @bh_result:
- * @create:
- *
- * Returns: errno
- */
-
-static int
-get_blocks(struct inode *inode, sector_t lblock,
- struct buffer_head *bh_result, int create)
-{
- struct gfs_inode *ip = get_v2ip(inode);
- int new = create;
- uint64_t dblock;
- int error;
-
- error = gfs_block_map(ip, lblock, &new, &dblock, NULL);
- if (error)
- return error;
-
- if (!dblock)
- return 0;
-
- map_bh(bh_result, inode->i_sb, dblock);
- if (new)
- set_buffer_new(bh_result);
-
- return 0;
-}
-
-/**
- * get_blocks_noalloc -
- * @inode:
- * @lblock:
- * @max_blocks:
- * @bh_result:
- * @create:
- *
- * Returns: errno
- */
-
-static int
-get_blocks_noalloc(struct inode *inode, sector_t lblock,
- struct buffer_head *bh_result, int create)
-{
- int error;
-
- error = get_blocks(inode, lblock, bh_result, FALSE);
- if (error)
- return error;
-
- if (gfs_assert_withdraw(get_v2sdp(inode->i_sb),
- !create || buffer_mapped(bh_result)))
- return -EIO;
-
- return 0;
-}
-
-/**
- * gfs_writepage - Write complete page
- * @page: Page to write
- *
- * Returns: errno
- *
- * Use Linux VFS block_write_full_page() to write one page,
- * using GFS's get_block_noalloc to find which blocks to write.
- */
-
-static int
-gfs_writepage(struct page *page, struct writeback_control *wbc)
-{
- struct gfs_inode *ip = get_v2ip(page->mapping->host);
- struct gfs_sbd *sdp = ip->i_sbd;
- int error;
-
- atomic_inc(&sdp->sd_ops_address);
-
- if (gfs_assert_withdraw(sdp, gfs_glock_is_held_excl(ip->i_gl))) {
- unlock_page(page);
- return -EIO;
- }
- if (get_transaction) {
- redirty_page_for_writepage(wbc, page);
- unlock_page(page);
- return 0;
- }
-
- error = block_write_full_page(page, get_block_noalloc, wbc);
-
- gfs_flush_meta_cache(ip);
-
- return error;
-}
-
-/**
- * stuffed_readpage - Fill in a Linux page with stuffed file data
- * @ip: the inode
- * @page: the page
- *
- * Returns: errno
- */
-
-static int
-stuffed_readpage(struct gfs_inode *ip, struct page *page)
-{
- struct buffer_head *dibh;
- void *kaddr;
- int error;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (!error) {
- kaddr = kmap(page);
- memcpy((char *)kaddr,
- dibh->b_data + sizeof(struct gfs_dinode),
- ip->i_di.di_size);
- memset((char *)kaddr + ip->i_di.di_size,
- 0,
- PAGE_CACHE_SIZE - ip->i_di.di_size);
- kunmap(page);
-
- brelse(dibh);
-
- SetPageUptodate(page);
- }
-
- return error;
-}
-
-/**
- * readi_readpage - readpage that goes through gfs_internal_read()
- * @page: The page to read
- *
- * Returns: errno
- */
-
-static int
-readi_readpage(struct page *page)
-{
- struct gfs_inode *ip = get_v2ip(page->mapping->host);
- void *kaddr;
- int ret;
-
- kaddr = kmap(page);
-
- ret = gfs_internal_read(ip, kaddr,
- (uint64_t)page->index << PAGE_CACHE_SHIFT,
- PAGE_CACHE_SIZE);
- if (ret >= 0) {
- if (ret < PAGE_CACHE_SIZE)
- memset(kaddr + ret, 0, PAGE_CACHE_SIZE - ret);
- SetPageUptodate(page);
- ret = 0;
- }
-
- kunmap(page);
-
- unlock_page(page);
-
- return ret;
-}
-
-/**
- * gfs_readpage - readpage with locking
- * @file: The file to read a page for
- * @page: The page to read
- *
- * Returns: errno
- */
-
-static int
-gfs_readpage(struct file *file, struct page *page)
-{
- struct gfs_inode *ip = get_v2ip(page->mapping->host);
- struct gfs_sbd *sdp = ip->i_sbd;
- int error;
-
- atomic_inc(&sdp->sd_ops_address);
-
- if (!gfs_glock_is_locked_by_me(ip->i_gl)) {
- unlock_page(page);
- return -ENOSYS;
- }
-
- if (!gfs_is_jdata(ip)) {
- if (gfs_is_stuffed(ip) && !page->index) {
- error = stuffed_readpage(ip, page);
- unlock_page(page);
- } else
- error = block_read_full_page(page, get_block);
- } else
- error = readi_readpage(page);
-
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- error = -EIO;
-
- return error;
-}
-
-/**
- * gfs_write_begin - Begin to write to a file
- * @file: The file to write to
- * @mapping: The mapping in which to write
- * @pos: The file offset at which to start writing
- * @len: Length of the write
- * @flags: Various flags
- * @pagep: Pointer to return the page
- * @fsdata: Pointer to return fs data (unused by GFS)
- *
- * Returns: errno
- *
- * Make sure file's inode is glocked; we shouldn't write without that!
- * If GFS dinode is currently stuffed (small enough that all data fits within
- * the dinode block), and new file size is too large, unstuff it.
- * Use Linux VFS block_prepare_write() to write blocks, using GFS' get_block()
- * to find which blocks to write.
- */
-
-static int
-gfs_write_begin(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned flags,
- struct page **pagep, void **fsdata)
-{
- struct gfs_inode *ip = get_v2ip(mapping->host);
- struct gfs_sbd *sdp = ip->i_sbd;
- int error = 0;
- pgoff_t index = pos >> PAGE_CACHE_SHIFT;
- unsigned from = pos & (PAGE_CACHE_SIZE - 1);
- unsigned to = from + len;
- struct page *page;
-
- atomic_inc(&sdp->sd_ops_address);
-
- /* We can't set write_end in the structure in the declare */
- /* because if we do, loopback (loop.c) will interpret that to mean */
- /* it's okay to do buffered writes without locking through sendfile. */
- /* This is a kludge to get around the problem with loop.c because */
- /* the upstream community rejected my changes to loop.c. */
- ip->gfs_file_aops.write_end = gfs_write_end;
-
- if (gfs_assert_warn(sdp, gfs_glock_is_locked_by_me(ip->i_gl)))
- return -ENOSYS;
-
- error = -ENOMEM;
- page = grab_cache_page_write_begin(mapping, index, flags);
- *pagep = page;
- if (!page)
- goto out;
-
- if (gfs_is_stuffed(ip)) {
- if (pos + len > sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode)) {
- error = gfs_unstuff_dinode(ip, gfs_unstuffer_page, page);
- if (!error)
- error = block_prepare_write(page, from, to, get_block);
- } else if (!PageUptodate(page))
- error = stuffed_readpage(ip, page);
- } else
- error = block_prepare_write(page, from, to, get_block);
-
- if (error)
- page_cache_release(page);
-
-out:
- return error;
-}
-
-/**
- * gfs_write_end
- * @file: The file to write to
- * @mapping: The address space to write to
- * @pos: The file position
- * @len: The length of the data
- * @copied:
- * @page: The page that has been written
- * @fsdata: The fsdata (unused in GFS)
- *
- * The main write_end function for GFS. We have a separate one for
- * stuffed files as they are slightly different, otherwise we just
- * put our locking around the VFS provided functions
- *
- * Returns: errno
- */
-
-static int
-gfs_write_end(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *page, void *fsdata)
-{
- struct inode *inode = page->mapping->host;
- struct gfs_inode *ip = get_v2ip(inode);
- struct gfs_sbd *sdp = ip->i_sbd;
- int ret;
-
- atomic_inc(&sdp->sd_ops_address);
- BUG_ON(gfs_glock_is_locked_by_me(ip->i_gl) == 0);
-
- if (gfs_is_stuffed(ip)) {
- struct buffer_head *dibh;
- u64 to = pos + copied;
- void *kaddr;
- unsigned char *buf;
-
- ret = gfs_get_inode_buffer(ip, &dibh);
- if (ret)
- goto fail;
- buf = dibh->b_data + sizeof(struct gfs_dinode);
- BUG_ON((pos + len) > (dibh->b_size - sizeof(struct gfs_dinode)));
-
- kaddr = kmap(page);
- memcpy(buf + pos, kaddr + pos, copied);
- memset(kaddr + pos + copied, 0, len - copied);
- flush_dcache_page(page);
- kunmap(page);
-
- brelse(dibh);
- if (!PageUptodate(page))
- SetPageUptodate(page);
- unlock_page(page);
- page_cache_release(page);
-
- if (inode->i_size < to)
- i_size_write(inode, to);
- } else {
- ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
- }
-
- ip->gfs_file_aops.write_end = NULL;
- return ret;
-
-fail:
- ClearPageUptodate(page);
- unlock_page(page);
- page_cache_release(page);
- return ret;
-}
-
-/**
- * gfs_bmap - Block map function
- * @mapping: Address space info
- * @lblock: The block to map
- *
- * Returns: The disk address for the block or 0 on hole or error
- */
-
-static sector_t
-gfs_bmap(struct address_space *mapping, sector_t lblock)
-{
- struct gfs_inode *ip = get_v2ip(mapping->host);
- struct gfs_holder i_gh;
- int dblock = 0;
- int error;
-
- atomic_inc(&ip->i_sbd->sd_ops_address);
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
- if (error)
- return 0;
-
- if (!gfs_is_stuffed(ip))
- dblock = generic_block_bmap(mapping, lblock, get_block);
-
- gfs_glock_dq_uninit(&i_gh);
-
- return dblock;
-}
-
-/**
- * gfs_direct_IO -
- * @rw:
- * @iocb:
- * @iov:
- * @offset:
- * @nr_segs:
- *
- * Returns: errno
- */
-
-static ssize_t
-gfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs)
-{
- struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_mapping->host;
- struct gfs_inode *ip = get_v2ip(inode);
- struct gfs_sbd *sdp = ip->i_sbd;
- get_block_t *gb = get_blocks;
-
- atomic_inc(&sdp->sd_ops_address);
-
- if (gfs_assert_warn(sdp, gfs_glock_is_locked_by_me(ip->i_gl)) ||
- gfs_assert_warn(sdp, !gfs_is_stuffed(ip)))
- return -EINVAL;
-
- if (rw == WRITE && !get_transaction)
- gb = get_blocks_noalloc;
-
- if (rw == WRITE)
- return blockdev_direct_IO(rw, iocb, inode,
- inode->i_sb->s_bdev, iov,
- offset, nr_segs, gb, NULL);
- else
- return blockdev_direct_IO_no_locking(rw, iocb, inode,
- inode->i_sb->s_bdev, iov,
- offset, nr_segs, gb, NULL);
-
-}
-
-struct address_space_operations gfs_file_aops = {
- .writepage = gfs_writepage,
- .readpage = gfs_readpage,
- .sync_page = block_sync_page,
- .write_begin = gfs_write_begin,
- .bmap = gfs_bmap,
- .direct_IO = gfs_direct_IO,
-};
diff --git a/gfs-kernel/src/gfs/ops_address.h b/gfs-kernel/src/gfs/ops_address.h
deleted file mode 100644
index f847a7a..0000000
--- a/gfs-kernel/src/gfs/ops_address.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __OPS_ADDRESS_DOT_H__
-#define __OPS_ADDRESS_DOT_H__
-
-extern struct address_space_operations gfs_file_aops;
-
-#endif /* __OPS_ADDRESS_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/ops_dentry.c b/gfs-kernel/src/gfs/ops_dentry.c
deleted file mode 100644
index 48efd34..0000000
--- a/gfs-kernel/src/gfs/ops_dentry.c
+++ /dev/null
@@ -1,111 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "dir.h"
-#include "glock.h"
-#include "ops_dentry.h"
-
-/**
- * gfs_drevalidate - Check directory lookup consistency
- * @dentry: the mapping to check
- * @nd:
- *
- * Check to make sure the lookup necessary to arrive at this inode from its
- * parent is still good.
- *
- * Returns: 1 if the dentry is ok, 0 if it isn't
- */
-
-static int
-gfs_drevalidate(struct dentry *dentry, struct nameidata *nd)
-{
- struct dentry *parent = dget_parent(dentry);
- struct gfs_inode *dip = get_v2ip(parent->d_inode);
- struct gfs_sbd *sdp = dip->i_sbd;
- struct inode *inode;
- struct gfs_holder d_gh;
- struct gfs_inode *ip;
- struct gfs_inum inum;
- unsigned int type;
- int error;
-
- lock_kernel();
-
- atomic_inc(&sdp->sd_ops_dentry);
-
- if (sdp->sd_args.ar_localcaching)
- goto valid;
-
- inode = dentry->d_inode;
- if (inode && is_bad_inode(inode))
- goto invalid;
-
- error = gfs_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
- if (error)
- goto fail;
-
- error = gfs_dir_search(dip, &dentry->d_name, &inum, &type);
- switch (error) {
- case 0:
- if (!inode)
- goto invalid_gunlock;
- break;
- case -ENOENT:
- if (!inode)
- goto valid_gunlock;
- goto invalid_gunlock;
- default:
- goto fail_gunlock;
- }
-
- ip = get_v2ip(inode);
-
- if (ip->i_num.no_formal_ino != inum.no_formal_ino)
- goto invalid_gunlock;
-
- if (ip->i_di.di_type != type) {
- gfs_consist_inode(dip);
- goto fail_gunlock;
- }
-
- valid_gunlock:
- gfs_glock_dq_uninit(&d_gh);
-
- valid:
- unlock_kernel();
- dput(parent);
- return 1;
-
- invalid_gunlock:
- gfs_glock_dq_uninit(&d_gh);
-
- invalid:
- if (inode && S_ISDIR(inode->i_mode)) {
- if (have_submounts(dentry))
- goto valid;
- shrink_dcache_parent(dentry);
- }
- d_drop(dentry);
-
- unlock_kernel();
- dput(parent);
- return 0;
-
- fail_gunlock:
- gfs_glock_dq_uninit(&d_gh);
-
- fail:
- unlock_kernel();
- dput(parent);
- return 0;
-}
-
-struct dentry_operations gfs_dops = {
- .d_revalidate = gfs_drevalidate,
-};
diff --git a/gfs-kernel/src/gfs/ops_dentry.h b/gfs-kernel/src/gfs/ops_dentry.h
deleted file mode 100644
index a6e7a75..0000000
--- a/gfs-kernel/src/gfs/ops_dentry.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __OPS_DENTRY_DOT_H__
-#define __OPS_DENTRY_DOT_H__
-
-extern struct dentry_operations gfs_dops;
-
-#endif /* __OPS_DENTRY_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/ops_export.c b/gfs-kernel/src/gfs/ops_export.c
deleted file mode 100644
index ca5e648..0000000
--- a/gfs-kernel/src/gfs/ops_export.c
+++ /dev/null
@@ -1,395 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/exportfs.h>
-
-#include "gfs.h"
-#include "dio.h"
-#include "dir.h"
-#include "glock.h"
-#include "glops.h"
-#include "inode.h"
-#include "ops_dentry.h"
-#include "ops_export.h"
-#include "rgrp.h"
-
-struct inode_cookie
-{
- uint64_t formal_ino;
- uint32_t gen;
- int gen_valid;
-};
-
-struct get_name_filldir
-{
- uint64_t formal_ino;
- char *name;
-};
-
-/**
- * gfs_encode_fh -
- * @param1: description
- * @param2: description
- * @param3: description
- *
- * Function description
- *
- * Returns: what is returned
- */
-
-int
-gfs_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
- int connectable)
-{
- struct inode *inode = dentry->d_inode;
- struct gfs_inode *ip = get_v2ip(inode);
- int maxlen = *len;
-
- atomic_inc(&ip->i_sbd->sd_ops_export);
-
- if (maxlen < 3)
- return 255;
-
- fh[0] = cpu_to_gfs32((uint32_t)(ip->i_num.no_formal_ino >> 32));
- fh[1] = cpu_to_gfs32((uint32_t)(ip->i_num.no_formal_ino & 0xFFFFFFFF));
- fh[2] = cpu_to_gfs32(inode->i_generation); /* dinode's mh_incarn */
- *len = 3;
-
- if (maxlen < 5 || !connectable)
- return 3;
-
- spin_lock(&dentry->d_lock);
-
- inode = dentry->d_parent->d_inode;
- ip = get_v2ip(inode);
-
- fh[3] = cpu_to_gfs32((uint32_t)(ip->i_num.no_formal_ino >> 32));
- fh[4] = cpu_to_gfs32((uint32_t)(ip->i_num.no_formal_ino & 0xFFFFFFFF));
- *len = 5;
-
- if (maxlen < 6) {
- spin_unlock(&dentry->d_lock);
- return 5;
- }
-
- fh[5] = cpu_to_gfs32(inode->i_generation); /* dinode's mh_incarn */
-
- spin_unlock(&dentry->d_lock);
-
- *len = 6;
-
- return 6;
-}
-
-/**
- * get_name_filldir -
- * @param1: description
- * @param2: description
- * @param3: description
- *
- * Function description
- *
- * Returns: what is returned
- */
-
-static int
-get_name_filldir(void *opaque,
- const char *name, unsigned int length,
- uint64_t offset,
- struct gfs_inum *inum, unsigned int type)
-{
- struct get_name_filldir *gnfd = (struct get_name_filldir *)opaque;
-
- if (inum->no_formal_ino != gnfd->formal_ino)
- return 0;
-
- memcpy(gnfd->name, name, length);
- gnfd->name[length] = 0;
-
- return 1;
-}
-
-/**
- * gfs_get_name -
- * @param1: description
- * @param2: description
- * @param3: description
- *
- * Function description
- *
- * Returns: what is returned
- */
-
-int gfs_get_name(struct dentry *parent, char *name,
- struct dentry *child)
-{
- struct inode *dir = parent->d_inode;
- struct inode *inode = child->d_inode;
- struct gfs_inode *dip, *ip;
- struct get_name_filldir gnfd;
- struct gfs_holder gh;
- uint64_t offset = 0;
- int error;
-
- if (!dir)
- return -EINVAL;
-
- atomic_inc(&get_v2sdp(dir->i_sb)->sd_ops_export);
-
- if (!S_ISDIR(dir->i_mode) || !inode)
- return -EINVAL;
-
- dip = get_v2ip(dir);
- ip = get_v2ip(inode);
-
- *name = 0;
- gnfd.formal_ino = ip->i_num.no_formal_ino;
- gnfd.name = name;
-
- error = gfs_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
- if (error)
- return error;
-
- error = gfs_dir_read(dip, &offset, &gnfd, get_name_filldir);
-
- gfs_glock_dq_uninit(&gh);
-
- if (!error & !*name)
- error = -ENOENT;
-
- return error;
-}
-
-/**
- * gfs_get_parent -
- * @param1: description
- * @param2: description
- * @param3: description
- *
- * Function description
- *
- * Returns: what is returned
- */
-
-struct dentry *
-gfs_get_parent(struct dentry *child)
-{
- struct gfs_inode *dip = get_v2ip(child->d_inode);
- struct gfs_holder d_gh, i_gh;
- struct qstr dotdot = { .name = "..", .len = 2 };
- struct gfs_inode *ip;
- struct inode *inode;
- struct dentry *dentry;
- int error;
-
- atomic_inc(&dip->i_sbd->sd_ops_export);
-
- gfs_holder_init(dip->i_gl, 0, 0, &d_gh);
- error = gfs_lookupi(&d_gh, &dotdot, TRUE, &i_gh);
- if (error)
- goto fail;
-
- error = -ENOENT;
- if (!i_gh.gh_gl)
- goto fail;
-
- ip = get_gl2ip(i_gh.gh_gl);
-
- inode = gfs_iget(ip, CREATE);
- gfs_inode_put(ip);
-
- gfs_glock_dq_uninit(&d_gh);
- gfs_glock_dq_uninit(&i_gh);
-
- if (!inode)
- return ERR_PTR(-ENOMEM);
-
- dentry = d_obtain_alias(inode);
- if (!IS_ERR(dentry))
- dentry->d_op = &gfs_dops;
- return dentry;
-
- fail:
- gfs_holder_uninit(&d_gh);
- return ERR_PTR(error);
-}
-
-/**
- * gfs_get_dentry -
- * @param1: description
- * @param2: description
- * @param3: description
- *
- * Function description
- *
- * Returns: what is returned
- */
-
-struct dentry *
-gfs_get_dentry(struct super_block *sb, struct inode_cookie *cookie)
-{
- struct gfs_sbd *sdp = get_v2sdp(sb);
- struct gfs_inum inum;
- struct gfs_holder i_gh, ri_gh, rgd_gh;
- struct gfs_rgrpd *rgd;
- struct buffer_head *bh;
- struct gfs_dinode *di;
- struct gfs_inode *ip;
- struct inode *inode;
- struct dentry *dentry;
- int error;
-
- atomic_inc(&sdp->sd_ops_export);
-
- if (!cookie->formal_ino ||
- cookie->formal_ino == sdp->sd_jiinode->i_num.no_formal_ino ||
- cookie->formal_ino == sdp->sd_riinode->i_num.no_formal_ino ||
- cookie->formal_ino == sdp->sd_qinode->i_num.no_formal_ino)
- return ERR_PTR(-EINVAL);
-
- inum.no_formal_ino = cookie->formal_ino;
- inum.no_addr = cookie->formal_ino;
-
- error = gfs_glock_nq_num(sdp,
- inum.no_formal_ino, &gfs_inode_glops,
- LM_ST_SHARED, LM_FLAG_ANY | GL_LOCAL_EXCL,
- &i_gh);
- if (error)
- return ERR_PTR(error);
-
- error = gfs_inode_get(i_gh.gh_gl, &inum, NO_CREATE, &ip);
- if (error)
- goto fail;
- if (ip)
- goto out;
-
- error = gfs_rindex_hold(sdp, &ri_gh);
- if (error)
- goto fail;
-
- error = -EINVAL;
- rgd = gfs_blk2rgrpd(sdp, inum.no_addr);
- if (!rgd)
- goto fail_rindex;
-
- error = gfs_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh);
- if (error)
- goto fail_rindex;
-
- error = -ESTALE;
- if (gfs_get_block_type(rgd, inum.no_addr) != GFS_BLKST_USEDMETA)
- goto fail_rgd;
-
- error = gfs_dread(i_gh.gh_gl, inum.no_addr,
- DIO_START | DIO_WAIT, &bh);
- if (error)
- goto fail_rgd;
-
- di = (struct gfs_dinode *)bh->b_data;
-
- error = -ESTALE;
- if (gfs32_to_cpu(di->di_header.mh_magic) != GFS_MAGIC ||
- gfs32_to_cpu(di->di_header.mh_type) != GFS_METATYPE_DI ||
- (gfs32_to_cpu(di->di_flags) & GFS_DIF_UNUSED))
- goto fail_relse;
-
- brelse(bh);
- gfs_glock_dq_uninit(&rgd_gh);
- gfs_glock_dq_uninit(&ri_gh);
-
- error = gfs_inode_get(i_gh.gh_gl, &inum, CREATE, &ip);
- if (error)
- goto fail;
-
- atomic_inc(&sdp->sd_fh2dentry_misses);
-
- out:
- inode = gfs_iget(ip, CREATE);
- gfs_inode_put(ip);
-
- gfs_glock_dq_uninit(&i_gh);
-
- if (!inode)
- return ERR_PTR(-ENOMEM);
-
- /* inode->i_generation is GFS dinode's mh_incarn value */
- if (cookie->gen_valid && cookie->gen != inode->i_generation) {
- iput(inode);
- return ERR_PTR(-ESTALE);
- }
-
- dentry = d_obtain_alias(inode);
- if (!IS_ERR(dentry))
- dentry->d_op = &gfs_dops;
- return dentry;
-
- fail_relse:
- brelse(bh);
-
- fail_rgd:
- gfs_glock_dq_uninit(&rgd_gh);
-
- fail_rindex:
- gfs_glock_dq_uninit(&ri_gh);
-
- fail:
- gfs_glock_dq_uninit(&i_gh);
- return ERR_PTR(error);
-}
-
-static struct dentry *gfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
- int fh_len, int fh_type)
-{
- struct inode_cookie this;
- __u32 *fh = fid->raw;
-
- atomic_inc(&get_v2sdp(sb)->sd_ops_export);
-
- switch (fh_type) {
- case 6:
- case 5:
- case 3:
- this.gen_valid = TRUE;
- this.gen = gfs32_to_cpu(fh[2]);
- this.formal_ino = ((uint64_t)gfs32_to_cpu(fh[0])) << 32;
- this.formal_ino |= (uint64_t)gfs32_to_cpu(fh[1]);
- return gfs_get_dentry(sb, &this);
- default:
- return NULL;
- }
-}
-
-static struct dentry *gfs_fh_to_parent(struct super_block *sb, struct fid *fid,
- int fh_len, int fh_type)
-{
- struct inode_cookie parent;
- __u32 *fh = fid->raw;
-
- atomic_inc(&get_v2sdp(sb)->sd_ops_export);
-
- switch (fh_type) {
- case 6:
- parent.gen_valid = TRUE;
- parent.gen = gfs32_to_cpu(fh[5]);
- case 5:
- parent.formal_ino = ((uint64_t)gfs32_to_cpu(fh[3])) << 32;
- parent.formal_ino |= (uint64_t)gfs32_to_cpu(fh[4]);
- default:
- return NULL;
- }
-
- return gfs_get_dentry(sb, &parent);
-}
-
-const struct export_operations gfs_export_ops = {
- .encode_fh = gfs_encode_fh,
- .fh_to_dentry = gfs_fh_to_dentry,
- .fh_to_parent = gfs_fh_to_parent,
- .get_name = gfs_get_name,
- .get_parent = gfs_get_parent,
-};
-
diff --git a/gfs-kernel/src/gfs/ops_export.h b/gfs-kernel/src/gfs/ops_export.h
deleted file mode 100644
index 778ca9e..0000000
--- a/gfs-kernel/src/gfs/ops_export.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __OPS_EXPORT_DOT_H__
-#define __OPS_EXPORT_DOT_H__
-
-extern const struct export_operations gfs_export_ops;
-
-#endif /* __OPS_EXPORT_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/ops_file.c b/gfs-kernel/src/gfs/ops_file.c
deleted file mode 100644
index e675772..0000000
--- a/gfs-kernel/src/gfs/ops_file.c
+++ /dev/null
@@ -1,1913 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <asm/uaccess.h>
-#include <linux/pagemap.h>
-#include <linux/uio.h>
-#include <linux/blkdev.h>
-#include <linux/mm.h>
-#include <linux/aio.h>
-#include <linux/writeback.h>
-#include <asm/uaccess.h>
-#include <linux/compat.h>
-
-#include "gfs_ioctl.h"
-#include "gfs.h"
-#include "bmap.h"
-#include "dio.h"
-#include "dir.h"
-#include "file.h"
-#include "glock.h"
-#include "glops.h"
-#include "inode.h"
-#include "ioctl.h"
-#include "lm.h"
-#include "log.h"
-#include "ops_file.h"
-#include "ops_vm.h"
-#include "quota.h"
-#include "rgrp.h"
-#include "trans.h"
-
-/* "bad" is for NFS support */
-struct filldir_bad_entry {
- char *fbe_name;
- unsigned int fbe_length;
- uint64_t fbe_offset;
- struct gfs_inum fbe_inum;
- unsigned int fbe_type;
-};
-
-struct filldir_bad {
- struct gfs_sbd *fdb_sbd;
-
- struct filldir_bad_entry *fdb_entry;
- unsigned int fdb_entry_num;
- unsigned int fdb_entry_off;
-
- char *fdb_name;
- unsigned int fdb_name_size;
- unsigned int fdb_name_off;
-};
-
-/* For regular, non-NFS */
-struct filldir_reg {
- struct gfs_sbd *fdr_sbd;
- int fdr_prefetch;
-
- filldir_t fdr_filldir;
- void *fdr_opaque;
-};
-
-typedef ssize_t(*do_rw_t) (struct file * file,
- char *buf,
- size_t size, loff_t * offset,
- struct kiocb *iocb,
- unsigned int num_gh, struct gfs_holder * ghs);
-
-/**
- * gfs_llseek - seek to a location in a file
- * @file: the file
- * @offset: the offset
- * @origin: Where to seek from (SEEK_SET, SEEK_CUR, or SEEK_END)
- *
- * SEEK_END requires the glock for the file because it references the
- * file's size.
- *
- * Returns: The new offset, or errno
- */
-
-static loff_t
-gfs_llseek(struct file *file, loff_t offset, int origin)
-{
- struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
- struct gfs_holder i_gh;
- loff_t error;
-
- atomic_inc(&ip->i_sbd->sd_ops_file);
-
- if (origin == 2) {
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
- if (!error) {
- error = generic_file_llseek_unlocked(file, offset, origin);
- gfs_glock_dq_uninit(&i_gh);
- }
- } else
- error = generic_file_llseek_unlocked(file, offset, origin);
-
- return error;
-}
-
-#define vma2state(vma) \
-((((vma)->vm_flags & (VM_MAYWRITE | VM_MAYSHARE)) == \
- (VM_MAYWRITE | VM_MAYSHARE)) ? \
- LM_ST_EXCLUSIVE : LM_ST_SHARED) \
-
-/**
- * functionname - summary
- * @param1: description
- * @param2: description
- * @param3: description
- *
- * Function description
- *
- * Returns: what is returned
- */
-
-static ssize_t
-walk_vm_hard(struct file *file, char *buf, size_t size, loff_t *offset,
- struct kiocb *iocb, do_rw_t operation)
-{
- struct gfs_holder *ghs;
- unsigned int num_gh = 0;
- ssize_t count;
-
- {
- struct super_block *sb = file->f_dentry->d_inode->i_sb;
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma;
- unsigned long start = (unsigned long)buf;
- unsigned long end = start + size;
- int dumping = (current->flags & PF_DUMPCORE);
- unsigned int x = 0;
-
- for (vma = find_vma(mm, start); vma; vma = vma->vm_next) {
- if (end <= vma->vm_start)
- break;
- if (vma->vm_file &&
- vma->vm_file->f_dentry->d_inode->i_sb == sb) {
- num_gh++;
- }
- }
-
- ghs = kmalloc((num_gh + 1) * sizeof(struct gfs_holder), GFP_KERNEL);
- if (!ghs) {
- if (!dumping)
- up_read(&mm->mmap_sem);
- return -ENOMEM;
- }
-
- for (vma = find_vma(mm, start); vma; vma = vma->vm_next) {
- if (end <= vma->vm_start)
- break;
- if (vma->vm_file) {
- struct inode *inode = vma->vm_file->f_dentry->d_inode;
- if (inode->i_sb == sb)
- gfs_holder_init(get_v2ip(inode)->i_gl,
- vma2state(vma),
- 0, &ghs[x++]);
- }
- }
-
- if (!dumping)
- up_read(&mm->mmap_sem);
-
- gfs_assert(get_v2sdp(sb), x == num_gh,);
- }
-
- count = operation(file, buf, size, offset, iocb, num_gh, ghs);
-
- while (num_gh--)
- gfs_holder_uninit(&ghs[num_gh]);
- kfree(ghs);
-
- return count;
-}
-
-/**
- * walk_vm - Walk the vmas associated with a buffer for read or write.
- * If any of them are gfs, pass the gfs inode down to the read/write
- * worker function so that locks can be acquired in the correct order.
- * @file: The file to read/write from/to
- * @buf: The buffer to copy to/from
- * @size: The amount of data requested
- * @offset: The current file offset
- * @operation: The read or write worker function
- *
- * Outputs: Offset - updated according to number of bytes written
- *
- * Returns: The number of bytes written, errno on failure
- */
-
-static ssize_t
-walk_vm(struct file *file, char *buf, size_t size, loff_t *offset,
- struct kiocb *iocb,
- do_rw_t operation)
-{
- if (current->mm) {
- struct super_block *sb = file->f_dentry->d_inode->i_sb;
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma;
- unsigned long start = (unsigned long)buf;
- unsigned long end = start + size;
- int dumping = (current->flags & PF_DUMPCORE);
-
- if (!dumping)
- down_read(&mm->mmap_sem);
-
- for (vma = find_vma(mm, start); vma; vma = vma->vm_next) {
- if (end <= vma->vm_start)
- break;
- if (vma->vm_file &&
- vma->vm_file->f_dentry->d_inode->i_sb == sb)
- goto do_locks;
- }
-
- if (!dumping)
- up_read(&mm->mmap_sem);
- }
-
- {
- struct gfs_holder gh;
- return operation(file, buf, size, offset, iocb, 0, &gh);
- }
-
- do_locks:
- return walk_vm_hard(file, buf, size, offset, iocb, operation);
-}
-
-/**
- * functionname - summary
- * @param1: description
- * @param2: description
- * @param3: description
- *
- * Function description
- *
- * Returns: what is returned
- */
-
-static ssize_t
-do_read_readi(struct file *file, char *buf, size_t size, loff_t *offset,
- struct kiocb *iocb)
-{
- struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
- ssize_t count = 0;
-
- if (*offset < 0)
- return -EINVAL;
- if (!access_ok(VERIFY_WRITE, buf, size))
- return -EFAULT;
-
- if (!(file->f_flags & O_LARGEFILE)) {
- if (*offset >= 0x7FFFFFFFull)
- return -EFBIG;
- if (*offset + size > 0x7FFFFFFFull)
- size = 0x7FFFFFFFull - *offset;
- }
-
- /* ToDo: not sure about iocb .. wcheng
- */
- count = gfs_readi(ip, buf, *offset, size, gfs_copy2user);
-
- if (count > 0)
- *offset += count;
-
- return count;
-}
-
-/**
- * grope_mapping - feel up a mapping that needs to be written
- * @buf: the start of the memory to be written
- * @size: the size of the memory to be written
- *
- * We do this after acquiring the locks on the mapping,
- * but before starting the write transaction. We need to make
- * sure that we don't cause recursive transactions if blocks
- * need to be allocated to the file backing the mapping.
- *
- * Returns: errno
- */
-
-static int
-grope_mapping(char *buf, size_t size)
-{
- unsigned long start = (unsigned long)buf;
- unsigned long stop = start + size;
- char c;
-
- while (start < stop) {
- if (copy_from_user(&c, (char *)start, 1))
- return -EFAULT;
-
- start += PAGE_CACHE_SIZE;
- start &= PAGE_CACHE_MASK;
- }
-
- return 0;
-}
-
-/**
- * do_read_direct - Read bytes from a file
- * @file: The file to read from
- * @buf: The buffer to copy into
- * @size: The amount of data requested
- * @offset: The current file offset
- * @num_gh: The number of other locks we need to do the read
- * @ghs: the locks we need plus one for our lock
- *
- * Outputs: Offset - updated according to number of bytes read
- *
- * Returns: The number of bytes read, errno on failure
- */
-
-static ssize_t
-do_read_direct(struct file *file, char *buf, size_t size, loff_t *offset,
- struct kiocb *iocb,
- unsigned int num_gh, struct gfs_holder *ghs)
-{
- struct inode *inode = file->f_mapping->host;
- struct gfs_inode *ip = get_v2ip(inode);
- unsigned int state = LM_ST_DEFERRED;
- int flags = 0;
- unsigned int x;
- ssize_t count = 0;
- int error;
-
- for (x = 0; x < num_gh; x++)
- if (ghs[x].gh_gl == ip->i_gl) {
- state = LM_ST_SHARED;
- flags |= GL_LOCAL_EXCL;
- break;
- }
-
- gfs_holder_init(ip->i_gl, state, flags, &ghs[num_gh]);
-
- if (num_gh && atomic_read(¤t->mm->mm_users) > 1) {
- error = grope_mapping(buf, size);
- if (error)
- goto out;
- }
-
- error = gfs_glock_nq_m(num_gh + 1, ghs);
- if (error)
- goto out;
-
- error = -EINVAL;
- if (gfs_is_jdata(ip))
- goto out_gunlock;
-
- if (gfs_is_stuffed(ip)) {
- size_t mask = bdev_logical_block_size(inode->i_sb->s_bdev) - 1;
-
- if (((*offset) & mask) || (((unsigned long)buf) & mask))
- goto out_gunlock;
-
- count = do_read_readi(file, buf, size & ~mask, offset, iocb);
- }
- else {
- if (!iocb)
- count = do_sync_read(file, buf, size, offset);
- else {
- struct iovec local_iov = { .iov_base = buf, .iov_len = size};
-
- count = generic_file_aio_read(iocb, &local_iov, 1, *offset);
- iocb->ki_pos = *offset;
- }
- }
-
- error = 0;
-
- out_gunlock:
- gfs_glock_dq_m(num_gh + 1, ghs);
-
- out:
- gfs_holder_uninit(&ghs[num_gh]);
-
- return (count) ? count : error;
-}
-
-/**
- * do_read_buf - Read bytes from a file
- * @file: The file to read from
- * @buf: The buffer to copy into
- * @size: The amount of data requested
- * @offset: The current file offset
- * @num_gh: The number of other locks we need to do the read
- * @ghs: the locks we need plus one for our lock
- *
- * Outputs: Offset - updated according to number of bytes read
- *
- * Returns: The number of bytes read, errno on failure
- */
-
-static ssize_t
-do_read_buf(struct file *file, char *buf, size_t size, loff_t *offset,
- struct kiocb *iocb,
- unsigned int num_gh, struct gfs_holder *ghs)
-{
- struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
- ssize_t count = 0;
- int error;
-
- gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &ghs[num_gh]);
-
- if (num_gh && atomic_read(¤t->mm->mm_users) > 1) {
- error = grope_mapping(buf, size);
- if (error)
- goto out;
- }
-
- error = gfs_glock_nq_m_atime(num_gh + 1, ghs);
- if (error)
- goto out;
-
- if (gfs_is_jdata(ip) ||
- (gfs_is_stuffed(ip) && !test_bit(GIF_PAGED, &ip->i_flags)))
- count = do_read_readi(file, buf, size, offset, iocb);
- else {
- if (!iocb) {
- count = do_sync_read(file, buf, size, offset);
- } else {
- struct iovec local_iov = { .iov_base = buf, .iov_len = size};
-
- count = generic_file_aio_read(iocb, &local_iov, 1, *offset);
- iocb->ki_pos = *offset;
- }
- }
-
- gfs_glock_dq_m(num_gh + 1, ghs);
-
- out:
- gfs_holder_uninit(&ghs[num_gh]);
-
- return (count) ? count : error;
-}
-
-static ssize_t
-__gfs_read(struct file *file, char *buf, size_t size, loff_t *offset, struct kiocb *iocb)
-{
- atomic_inc(&get_v2sdp(file->f_mapping->host->i_sb)->sd_ops_file);
-
- if (file->f_flags & O_DIRECT)
- return walk_vm(file, buf, size, offset, iocb, do_read_direct);
- else
- return walk_vm(file, buf, size, offset, iocb, do_read_buf);
-}
-
-/**
- * gfs_read - Read bytes from a file
- * @file: The file to read from
- * @buf: The buffer to copy into
- * @size: The amount of data requested
- * @offset: The current file offset
- *
- * Outputs: Offset - updated according to number of bytes read
- *
- * Returns: The number of bytes read, errno on failure
- */
-
-static ssize_t
-gfs_read(struct file *file, char *buf, size_t size, loff_t *offset)
-{
- return(__gfs_read(file, buf, size, offset, NULL));
-}
-
-/*
- * gfs_aio_read: match with vfs generic_file_aio_read as:
- * (struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
- */
-static ssize_t
-gfs_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long count,
- loff_t pos)
-{
- struct file *filp = iocb->ki_filp;
-
- BUG_ON(iocb->ki_pos != pos);
- return(__gfs_read(filp, iov->iov_base, iov->iov_len, &iocb->ki_pos, iocb));
-}
-
-/**
- * gfs_file_aio_write_nolock - Call vfs aio layer to write bytes to a file
- * @file: The file to write to
- * @buf: The buffer to copy from
- * @size: The amount of data requested
- * @offset: The offset in the file to write
- * @iocb: The io control block. If NULL, a temporary one will be used.
- *
- * Returns: The number of bytes written, errno on failure
- */
-static ssize_t
-gfs_file_aio_write_nolock(struct file *file, char *buf, size_t size,
- loff_t *offset, struct kiocb *iocb)
-{
- struct iovec local_iov = { .iov_base = buf, .iov_len = size };
- struct kiocb local_iocb, *kiocb = NULL;
- ssize_t count;
-
- if (!iocb) {
- init_sync_kiocb(&local_iocb, file);
- local_iocb.ki_nr_segs = 1;
- kiocb = &local_iocb;
- }
- else
- kiocb = iocb;
-
- kiocb->ki_pos = *offset;
- count = generic_file_aio_write_nolock(kiocb, &local_iov, kiocb->ki_nr_segs,
- kiocb->ki_pos);
- *offset = kiocb->ki_pos;
- if (kiocb == &local_iocb && count == -EIOCBQUEUED)
- count = wait_on_sync_kiocb(kiocb);
- return count;
-}
-
-/**
- * do_write_direct_alloc - Write bytes to a file
- * @file: The file to write to
- * @buf: The buffer to copy from
- * @size: The amount of data requested
- * @offset: The current file offset
- *
- * Outputs: Offset - updated according to number of bytes written
- *
- * Returns: The number of bytes written, errno on failure
- */
-
-static ssize_t
-do_write_direct_alloc(struct file *file, char *buf, size_t size, loff_t *offset,
- struct kiocb *iocb)
-{
- struct inode *inode = file->f_mapping->host;
- struct gfs_inode *ip = get_v2ip(inode);
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = NULL;
- struct buffer_head *dibh;
- unsigned int data_blocks, ind_blocks;
- ssize_t count;
- int error;
-
- gfs_write_calc_reserv(ip, size, &data_blocks, &ind_blocks);
-
- al = gfs_alloc_get(ip);
-
- error = gfs_quota_lock_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error)
- goto fail;
-
- error = gfs_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid);
- if (error)
- goto fail_gunlock_q;
-
- al->al_requested_meta = ind_blocks;
- al->al_requested_data = data_blocks;
-
- error = gfs_inplace_reserve(ip);
- if (error)
- goto fail_gunlock_q;
-
- /* Trans may require:
- All blocks for a RG bitmap, whatever indirect blocks we
- need, a modified dinode, and a quota change. */
-
- error = gfs_trans_begin(sdp,
- 1 + al->al_rgd->rd_ri.ri_length + ind_blocks,
- 1);
- if (error)
- goto fail_ipres;
-
- if ((ip->i_di.di_mode & (S_ISUID | S_ISGID)) && !capable(CAP_FSETID)) {
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto fail_end_trans;
-
- ip->i_di.di_mode &= (ip->i_di.di_mode & S_IXGRP) ? (~(S_ISUID | S_ISGID)) : (~S_ISUID);
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- if (gfs_is_stuffed(ip)) { error = gfs_unstuff_dinode(ip, gfs_unstuffer_sync, NULL); if (error)
- goto fail_end_trans;
- }
-
- count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb);
- if (count < 0) {
- error = count;
- goto fail_end_trans;
- }
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto fail_end_trans;
-
- if (ip->i_di.di_size < inode->i_size)
- ip->i_di.di_size = inode->i_size;
- ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
-
- gfs_trans_end(sdp);
-
- /* Question (wcheng)
- * 1. should IS_SYNC flush glock ?
- * 2. does gfs_log_flush_glock flush data ?
- */
- if (file->f_flags & O_SYNC)
- gfs_log_flush_glock(ip->i_gl);
-
- gfs_inplace_release(ip);
- gfs_quota_unlock_m(ip);
- gfs_alloc_put(ip);
-
- if (file->f_mapping->nrpages) {
- error = filemap_fdatawrite(file->f_mapping);
- if (!error)
- error = filemap_fdatawait(file->f_mapping);
- }
- if (error)
- return error;
-
- return count;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail_ipres:
- gfs_inplace_release(ip);
-
- fail_gunlock_q:
- gfs_quota_unlock_m(ip);
-
- fail:
- gfs_alloc_put(ip);
-
- return error;
-}
-
-/**
- * do_write_direct - Write bytes to a file
- * @file: The file to write to
- * @buf: The buffer to copy from
- * @size: The amount of data requested
- * @offset: The current file offset
- * @num_gh: The number of other locks we need to do the read
- * @gh: the locks we need plus one for our lock
- *
- * Outputs: Offset - updated according to number of bytes written
- *
- * Returns: The number of bytes written, errno on failure
- */
-
-static ssize_t
-do_write_direct(struct file *file, char *buf, size_t size, loff_t *offset,
- struct kiocb *iocb,
- unsigned int num_gh, struct gfs_holder *ghs)
-{
- struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_file *fp = get_v2fp(file);
- unsigned int state = LM_ST_DEFERRED;
- int alloc_required;
- unsigned int x;
- size_t s;
- ssize_t count = 0;
- int error;
-
- if (test_bit(GFF_DID_DIRECT_ALLOC, &fp->f_flags))
- state = LM_ST_EXCLUSIVE;
- else
- for (x = 0; x < num_gh; x++)
- if (ghs[x].gh_gl == ip->i_gl) {
- state = LM_ST_EXCLUSIVE;
- break;
- }
-
- restart:
- gfs_holder_init(ip->i_gl, state, 0, &ghs[num_gh]);
-
- if (num_gh && atomic_read(¤t->mm->mm_users) > 1) {
- error = grope_mapping(buf, size);
- if (error)
- goto out;
- }
-
- error = gfs_glock_nq_m(num_gh + 1, ghs);
- if (error)
- goto out;
-
- error = -EINVAL;
- if (gfs_is_jdata(ip))
- goto out_gunlock;
-
- if (num_gh) {
- error = grope_mapping(buf, size);
- if (error)
- goto out_gunlock;
- }
-
- if (file->f_flags & O_APPEND)
- *offset = ip->i_di.di_size;
-
- if (!(file->f_flags & O_LARGEFILE)) {
- error = -EFBIG;
- if (*offset >= 0x7FFFFFFFull)
- goto out_gunlock;
- if (*offset + size > 0x7FFFFFFFull)
- size = 0x7FFFFFFFull - *offset;
- }
-
- if (gfs_is_stuffed(ip) ||
- *offset + size > ip->i_di.di_size ||
- ((ip->i_di.di_mode & (S_ISUID | S_ISGID)) && !capable(CAP_FSETID)))
- alloc_required = TRUE;
- else {
- error = gfs_write_alloc_required(ip, *offset, size,
- &alloc_required);
- if (error)
- goto out_gunlock;
- }
-
- if (alloc_required && state != LM_ST_EXCLUSIVE) {
- gfs_glock_dq_m(num_gh + 1, ghs);
- gfs_holder_uninit(&ghs[num_gh]);
- state = LM_ST_EXCLUSIVE;
- goto restart;
- }
-
- if (alloc_required) {
- set_bit(GFF_DID_DIRECT_ALLOC, &fp->f_flags);
-
- /* for asynchronous IO, the buffer can not be splitted */
- if (iocb) {
- count = do_write_direct_alloc(file, buf, size, offset, iocb);
- goto out_iocb_write;
- }
-
- /* split large writes into smaller atomic transactions */
- while (size) {
- s = gfs_tune_get(sdp, gt_max_atomic_write);
- if (s > size)
- s = size;
-
- error = do_write_direct_alloc(file, buf, s, offset, iocb);
- if (error < 0)
- goto out_gunlock;
-
- buf += error;
- size -= error;
- count += error;
- }
- } else {
- struct gfs_holder t_gh;
-
- clear_bit(GFF_DID_DIRECT_ALLOC, &fp->f_flags);
-
- error = gfs_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &t_gh);
- if (error)
- goto out_gunlock;
-
- /* Todo: It would be nice if init_sync_kiocb is exported.
- * .. wcheng
- */
- count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb);
- gfs_glock_dq_uninit(&t_gh);
- }
-
-out_iocb_write:
- error = 0;
-
-out_gunlock:
- gfs_glock_dq_m(num_gh + 1, ghs);
-
-out:
- gfs_holder_uninit(&ghs[num_gh]);
-
- return (count) ? count : error;
-}
-
-/**
- * do_do_write_buf - Write bytes to a file
- * @file: The file to write to
- * @buf: The buffer to copy from
- * @size: The amount of data requested
- * @offset: The current file offset
- *
- * Outputs: Offset - updated according to number of bytes written
- *
- * Returns: The number of bytes written, errno on failure
- */
-
-static ssize_t
-do_do_write_buf(struct file *file, char *buf, size_t size, loff_t *offset,
- struct kiocb *iocb)
-{
- struct inode *inode = file->f_mapping->host;
- struct gfs_inode *ip = get_v2ip(inode);
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = NULL;
- struct buffer_head *dibh;
- unsigned int data_blocks, ind_blocks;
- int alloc_required, journaled;
- ssize_t count;
- int error;
- unsigned int posix = sdp->sd_args.ar_posix_acls ? 4 : 0;
-
- journaled = gfs_is_jdata(ip);
-
- gfs_write_calc_reserv(ip, size, &data_blocks, &ind_blocks);
-
- error = gfs_write_alloc_required(ip, *offset, size, &alloc_required);
- if (error)
- return error;
-
- if (alloc_required) {
- al = gfs_alloc_get(ip);
-
- error = gfs_quota_lock_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error)
- goto fail;
-
- error = gfs_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid);
- if (error)
- goto fail_gunlock_q;
-
- if (journaled)
- al->al_requested_meta = ind_blocks + data_blocks;
- else {
- al->al_requested_meta = ind_blocks;
- al->al_requested_data = data_blocks;
- }
-
- error = gfs_inplace_reserve(ip);
- if (error)
- goto fail_gunlock_q;
-
- /* Trans may require:
- All blocks for a RG bitmap, whatever indirect blocks we
- need, a modified dinode, and a quota change. */
-
- error = gfs_trans_begin(sdp,
- 1 + al->al_rgd->rd_ri.ri_length +
- ind_blocks + posix +
- ((journaled) ? data_blocks : 0), 1);
- if (error)
- goto fail_ipres;
- } else {
- /* Trans may require:
- A modified dinode. */
-
- error = gfs_trans_begin(sdp, posix +
- 1 + ((journaled) ? data_blocks : 0), 0);
- if (error)
- goto fail_ipres;
- }
-
- if ((ip->i_di.di_mode & (S_ISUID | S_ISGID)) && !capable(CAP_FSETID)) {
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto fail_end_trans;
-
- ip->i_di.di_mode &= (ip->i_di.di_mode & S_IXGRP) ? (~(S_ISUID | S_ISGID)) : (~S_ISUID);
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- if (journaled ||
- (gfs_is_stuffed(ip) && !test_bit(GIF_PAGED, &ip->i_flags) &&
- *offset + size <= sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode))) {
-
- count = gfs_writei(ip, buf, *offset, size, gfs_copy_from_user, iocb);
- if (count < 0) {
- error = count;
- goto fail_end_trans;
- }
- if (gfs_is_stuffed(ip)){
- struct page *page;
- page = find_get_page(file->f_mapping, 0);
- if (page) {
- ClearPageUptodate(page);
- page_cache_release(page);
- }
- }
- *offset += count;
- } else {
- count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb);
- if (count < 0) {
- error = count;
- goto fail_end_trans;
- }
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto fail_end_trans;
-
- if (ip->i_di.di_size < inode->i_size)
- ip->i_di.di_size = inode->i_size;
- ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- gfs_trans_end(sdp);
-
- if (file->f_flags & O_SYNC || IS_SYNC(inode)) {
- gfs_log_flush_glock(ip->i_gl);
- error = filemap_fdatawrite(file->f_mapping);
- if (error == 0)
- error = filemap_fdatawait(file->f_mapping);
- if (error)
- goto fail_ipres;
- }
-
- if (alloc_required) {
- gfs_assert_warn(sdp, count != size ||
- al->al_alloced_meta ||
- al->al_alloced_data);
- gfs_inplace_release(ip);
- gfs_quota_unlock_m(ip);
- gfs_alloc_put(ip);
- }
-
- return count;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail_ipres:
- if (alloc_required)
- gfs_inplace_release(ip);
-
- fail_gunlock_q:
- if (alloc_required)
- gfs_quota_unlock_m(ip);
-
- fail:
- if (alloc_required)
- gfs_alloc_put(ip);
-
- return error;
-}
-
-/**
- * do_write_buf - Write bytes to a file
- * @file: The file to write to
- * @buf: The buffer to copy from
- * @size: The amount of data requested
- * @offset: The current file offset
- * @num_gh: The number of other locks we need to do the read
- * @gh: the locks we need plus one for our lock
- *
- * Outputs: Offset - updated according to number of bytes written
- *
- * Returns: The number of bytes written, errno on failure
- */
-
-static ssize_t
-do_write_buf(struct file *file,
- char *buf, size_t size, loff_t *offset,
- struct kiocb *iocb,
- unsigned int num_gh, struct gfs_holder *ghs)
-{
- struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
- struct gfs_sbd *sdp = ip->i_sbd;
- size_t s;
- ssize_t count = 0;
- int error;
-
- gfs_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[num_gh]);
-
- if (num_gh && atomic_read(¤t->mm->mm_users) > 1) {
- error = grope_mapping(buf, size);
- if (error)
- goto out;
- }
-
- error = gfs_glock_nq_m(num_gh + 1, ghs);
- if (error)
- goto out;
-
- if (num_gh) {
- error = grope_mapping(buf, size);
- if (error)
- goto out_gunlock;
- }
-
- if (file->f_flags & O_APPEND)
- *offset = ip->i_di.di_size;
-
- if (!(file->f_flags & O_LARGEFILE)) {
- error = -EFBIG;
- if (*offset >= 0x7FFFFFFFull)
- goto out_gunlock;
- if (*offset + size > 0x7FFFFFFFull)
- size = 0x7FFFFFFFull - *offset;
- }
-
- /* split large writes into smaller atomic transactions */
- while (size) {
- s = gfs_tune_get(sdp, gt_max_atomic_write);
- if (s > size)
- s = size;
-
- error = do_do_write_buf(file, buf, s, offset, iocb);
- if (error < 0)
- goto out_gunlock;
-
- buf += error;
- size -= error;
- count += error;
- }
-
- error = 0;
-
- out_gunlock:
- gfs_glock_dq_m(num_gh + 1, ghs);
-
- out:
- gfs_holder_uninit(&ghs[num_gh]);
-
- return (count) ? count : error;
-}
-
-/**
- * gfs_write - Write bytes to a file
- * @file: The file to write to
- * @buf: The buffer to copy from
- * @size: The amount of data requested
- * @offset: The current file offset
- *
- * Outputs: Offset - updated according to number of bytes written
- *
- * Returns: The number of bytes written, errno on failure
- */
-
-static ssize_t
-__gfs_write(struct file *file, const char *buf, size_t size, loff_t *offset, struct kiocb *iocb)
-{
- struct inode *inode = file->f_mapping->host;
- ssize_t count;
-
- atomic_inc(&get_v2sdp(inode->i_sb)->sd_ops_file);
-
- if (*offset < 0)
- return -EINVAL;
- if (!access_ok(VERIFY_READ, buf, size))
- return -EFAULT;
-
- mutex_lock(&inode->i_mutex);
- if (file->f_flags & O_DIRECT)
- count = walk_vm(file, (char *)buf, size, offset, iocb, do_write_direct);
- else
- count = walk_vm(file, (char *)buf, size, offset, iocb, do_write_buf);
- mutex_unlock(&inode->i_mutex);
-
- return count;
-}
-
-static ssize_t
-gfs_write(struct file *file, const char *buf, size_t size, loff_t *offset)
-{
- return(__gfs_write(file, buf, size, offset, NULL));
-}
-
-static ssize_t
-gfs_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long segs,
- loff_t pos)
-{
- struct file *file = iocb->ki_filp;
-
- BUG_ON(iocb->ki_pos != pos);
-
- return(__gfs_write(file, iov->iov_base, iov->iov_len, &iocb->ki_pos,
- iocb));
-}
-
-/**
- * filldir_reg_func - Report a directory entry to the caller of gfs_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
- */
-
-static int
-filldir_reg_func(void *opaque,
- const char *name, unsigned int length,
- uint64_t offset,
- struct gfs_inum *inum, unsigned int type)
-{
- struct filldir_reg *fdr = (struct filldir_reg *)opaque;
- struct gfs_sbd *sdp = fdr->fdr_sbd;
- unsigned int vfs_type;
- int error;
-
- switch (type) {
- case GFS_FILE_NON:
- vfs_type = DT_UNKNOWN;
- break;
- case GFS_FILE_REG:
- vfs_type = DT_REG;
- break;
- case GFS_FILE_DIR:
- vfs_type = DT_DIR;
- break;
- case GFS_FILE_LNK:
- vfs_type = DT_LNK;
- break;
- case GFS_FILE_BLK:
- vfs_type = DT_BLK;
- break;
- case GFS_FILE_CHR:
- vfs_type = DT_CHR;
- break;
- case GFS_FILE_FIFO:
- vfs_type = DT_FIFO;
- break;
- case GFS_FILE_SOCK:
- vfs_type = DT_SOCK;
- break;
- default:
- if (gfs_consist(sdp))
- printk("GFS: fsid=%s: type = %u\n",
- sdp->sd_fsname, type);
- return -EIO;
- }
-
- error = fdr->fdr_filldir(fdr->fdr_opaque, name, length, offset,
- inum->no_formal_ino, vfs_type);
- if (error)
- return 1;
-
- /* Prefetch locks */
- if (fdr->fdr_prefetch && !(length == 1 && *name == '.')) {
- gfs_glock_prefetch_num(sdp,
- inum->no_formal_ino, &gfs_inode_glops,
- LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY);
- gfs_glock_prefetch_num(sdp,
- inum->no_addr, &gfs_iopen_glops,
- LM_ST_SHARED, LM_FLAG_TRY);
- }
-
- return 0;
-}
-
-static inline int
-high_stat_rate(struct gfs_inode *ip)
-{
- struct timeval now, diff;
- unsigned long milli = 0;
- unsigned int rate = 0; /* stats per second in this dir */
-
- do_gettimeofday(&now);
- diff.tv_sec = now.tv_sec - ip->i_dir_stat_st.tv_sec;
- diff.tv_usec = now.tv_usec - ip->i_dir_stat_st.tv_usec;
- if (diff.tv_usec < 0) {
- diff.tv_usec += 1000000;
- diff.tv_sec--;
- }
- milli = (diff.tv_sec * 1000) + (diff.tv_usec / 1000);
- if (milli)
- rate = (ip->i_dir_stats * 1000) / milli;
-
- if (rate > 10) /* More than 10 stats/sec */
- return 1;
- return 0;
-}
-
-/**
- * readdir_reg - Read directory entries from a directory
- * @file: The directory to read from
- * @dirent: Buffer for dirents
- * @filldir: Function used to do the copying
- *
- * Returns: errno
- */
-
-static int
-readdir_reg(struct file *file, void *dirent, filldir_t filldir)
-{
- struct gfs_inode *dip = get_v2ip(file->f_mapping->host);
- struct filldir_reg fdr;
- struct gfs_holder d_gh;
- uint64_t offset = file->f_pos;
- int error;
-
- fdr.fdr_sbd = dip->i_sbd;
- fdr.fdr_prefetch = high_stat_rate(dip) ? TRUE : FALSE;
- fdr.fdr_filldir = filldir;
- fdr.fdr_opaque = dirent;
-
- /* reset stat counter and timestamp */
- dip->i_dir_stats = 0;
- do_gettimeofday(&dip->i_dir_stat_st);
-
- gfs_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh);
- error = gfs_glock_nq_atime(&d_gh);
- if (error) {
- gfs_holder_uninit(&d_gh);
- return error;
- }
-
- error = gfs_dir_read(dip, &offset, &fdr, filldir_reg_func);
-
- gfs_glock_dq_uninit(&d_gh);
-
- file->f_pos = offset;
-
- return error;
-}
-
-/**
- * filldir_bad_func - Report a directory entry to the caller of gfs_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
- *
- * For supporting NFS.
- *
- * Returns: 0 on success, 1 if buffer full
- */
-
-static int
-filldir_bad_func(void *opaque,
- const char *name, unsigned int length,
- uint64_t offset,
- struct gfs_inum *inum, unsigned int type)
-{
- struct filldir_bad *fdb = (struct filldir_bad *)opaque;
- struct gfs_sbd *sdp = fdb->fdb_sbd;
- struct filldir_bad_entry *fbe;
-
- if (fdb->fdb_entry_off == fdb->fdb_entry_num ||
- fdb->fdb_name_off + length > fdb->fdb_name_size)
- return 1;
-
- fbe = &fdb->fdb_entry[fdb->fdb_entry_off];
- fbe->fbe_name = fdb->fdb_name + fdb->fdb_name_off;
- memcpy(fbe->fbe_name, name, length);
- fbe->fbe_length = length;
- fbe->fbe_offset = offset;
- fbe->fbe_inum = *inum;
- fbe->fbe_type = type;
-
- fdb->fdb_entry_off++;
- fdb->fdb_name_off += length;
-
- /* Prefetch locks */
- if (!(length == 1 && *name == '.')) {
- gfs_glock_prefetch_num(sdp,
- inum->no_formal_ino, &gfs_inode_glops,
- LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY);
- gfs_glock_prefetch_num(sdp,
- inum->no_addr, &gfs_iopen_glops,
- LM_ST_SHARED, LM_FLAG_TRY);
- }
-
- return 0;
-}
-
-/**
- * readdir_bad - Read directory entries from a directory
- * @file: The directory to read from
- * @dirent: Buffer for dirents
- * @filldir: Function used to do the copying
- *
- * For supporting NFS.
- *
- * Returns: errno
- */
-
-static int
-readdir_bad(struct file *file, void *dirent, filldir_t filldir)
-{
- struct gfs_inode *dip = get_v2ip(file->f_mapping->host);
- struct gfs_sbd *sdp = dip->i_sbd;
- struct filldir_reg fdr;
- unsigned int entries, size;
- struct filldir_bad *fdb;
- struct gfs_holder d_gh;
- uint64_t offset = file->f_pos;
- unsigned int x;
- struct filldir_bad_entry *fbe;
- int error;
-
- entries = gfs_tune_get(sdp, gt_entries_per_readdir);
- size = sizeof(struct filldir_bad) +
- entries * (sizeof(struct filldir_bad_entry) + GFS_FAST_NAME_SIZE);
-
- fdb = kmalloc(size, GFP_KERNEL);
- if (!fdb)
- return -ENOMEM;
- memset(fdb, 0, size);
-
- fdb->fdb_sbd = sdp;
- fdb->fdb_entry = (struct filldir_bad_entry *)(fdb + 1);
- fdb->fdb_entry_num = entries;
- fdb->fdb_name = ((char *)fdb) + sizeof(struct filldir_bad) +
- entries * sizeof(struct filldir_bad_entry);
- fdb->fdb_name_size = entries * GFS_FAST_NAME_SIZE;
-
- gfs_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh);
- error = gfs_glock_nq_atime(&d_gh);
- if (error) {
- gfs_holder_uninit(&d_gh);
- goto out;
- }
-
- error = gfs_dir_read(dip, &offset, fdb, filldir_bad_func);
-
- gfs_glock_dq_uninit(&d_gh);
-
- fdr.fdr_sbd = sdp;
- fdr.fdr_prefetch = FALSE;
- fdr.fdr_filldir = filldir;
- fdr.fdr_opaque = dirent;
-
- for (x = 0; x < fdb->fdb_entry_off; x++) {
- fbe = &fdb->fdb_entry[x];
-
- error = filldir_reg_func(&fdr,
- fbe->fbe_name, fbe->fbe_length,
- fbe->fbe_offset,
- &fbe->fbe_inum, fbe->fbe_type);
- if (error) {
- file->f_pos = fbe->fbe_offset;
- error = 0;
- goto out;
- }
- }
-
- file->f_pos = offset;
-
- out:
- kfree(fdb);
-
- return error;
-}
-
-/**
- * gfs_readdir - Read directory entries from a directory
- * @file: The directory to read from
- * @dirent: Buffer for dirents
- * @filldir: Function used to do the copying
- *
- * Returns: errno
- */
-
-static int
-gfs_readdir(struct file *file, void *dirent, filldir_t filldir)
-{
- int error;
-
- atomic_inc(&get_v2sdp(file->f_mapping->host->i_sb)->sd_ops_file);
-
- /* Use "bad" one if we're called from NFS daemon */
- if (strcmp(current->comm, "nfsd") != 0)
- error = readdir_reg(file, dirent, filldir);
- else
- error = readdir_bad(file, dirent, filldir);
-
- return error;
-}
-
-/**
- * gfs_ioctl - do an ioctl on a file
- * @inode: the inode
- * @file: the file pointer
- * @cmd: the ioctl command
- * @arg: the argument
- *
- * Returns: errno
- */
-
-static int
-gfs_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct gfs_inode *ip = get_v2ip(inode);
-
- atomic_inc(&ip->i_sbd->sd_ops_file);
-
- switch (cmd) {
- case GFS_IOCTL_IDENTIFY: {
- unsigned int x = GFS_MAGIC;
- if (copy_to_user((unsigned int *)arg, &x, sizeof(unsigned int)))
- return -EFAULT;
- return 0;
- }
-
- case GFS_IOCTL_SUPER:
- return gfs_ioctl_i(ip, (void *)arg);
-
- default:
- return -ENOTTY;
- }
-}
-
-#ifdef CONFIG_COMPAT
-/**
- * gfs_compat_ioctl - do an ioctl on a file - compatible between 32-64 bit
- * @inode: the inode
- * @file: the file pointer
- * @cmd: the ioctl command
- * @arg: the argument
- *
- * Returns: errno
- */
-
-static long
-gfs_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
-{
- struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
-
- atomic_inc(&ip->i_sbd->sd_ops_file);
-
- switch (cmd) {
- case GFS_IOCTL_IDENTIFY: {
- unsigned int x = GFS_MAGIC;
- if (copy_to_user((unsigned int *)arg, &x, sizeof(unsigned int)))
- return -EFAULT;
- return 0;
- }
-
- case GFS_IOCTL_SUPER:
- return gfs_ioctl_i_compat(ip, arg);
-
- default:
- return -ENOTTY;
- }
-}
-#endif
-
-/**
- * gfs_mmap - We don't support shared writable mappings right now
- * @file: The file to map
- * @vma: The VMA which described the mapping
- *
- * Returns: 0 or error code
- */
-
-static int
-gfs_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
- struct gfs_holder i_gh;
- int error;
-
- atomic_inc(&ip->i_sbd->sd_ops_file);
-
- gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh);
- error = gfs_glock_nq_atime(&i_gh);
- if (error) {
- gfs_holder_uninit(&i_gh);
- return error;
- }
-
- if (gfs_is_jdata(ip)) {
- if (vma->vm_flags & VM_MAYSHARE)
- error = -ENOSYS;
- else
- vma->vm_ops = &gfs_vm_ops_private;
- } else {
- /* This is VM_MAYWRITE instead of VM_WRITE because a call
- to mprotect() can turn on VM_WRITE later. */
-
- if ((vma->vm_flags & (VM_MAYSHARE | VM_MAYWRITE)) == (VM_MAYSHARE | VM_MAYWRITE))
- vma->vm_ops = &gfs_vm_ops_sharewrite;
- else
- vma->vm_ops = &gfs_vm_ops_private;
- }
-
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gfs_open - open a file
- * @inode: the inode to open
- * @file: the struct file for this opening
- *
- * Returns: errno
- */
-
-static int
-gfs_open(struct inode *inode, struct file *file)
-{
- struct gfs_inode *ip = get_v2ip(inode);
- struct gfs_holder i_gh;
- struct gfs_file *fp;
- int error;
-
- atomic_inc(&ip->i_sbd->sd_ops_file);
-
- fp = kmalloc(sizeof(struct gfs_file), GFP_KERNEL);
- if (!fp)
- return -ENOMEM;
- memset(fp, 0, sizeof(struct gfs_file));
-
- init_MUTEX(&fp->f_fl_lock);
-
- fp->f_inode = ip;
- fp->f_vfile = file;
-
- gfs_assert_warn(ip->i_sbd, !get_v2fp(file));
- set_v2fp(file, fp);
-
- if (ip->i_di.di_type == GFS_FILE_REG) {
- error = gfs_glock_nq_init(ip->i_gl,
- LM_ST_SHARED, LM_FLAG_ANY,
- &i_gh);
- if (error)
- goto fail;
-
- if (!(file->f_flags & O_LARGEFILE) &&
- ip->i_di.di_size > 0x7FFFFFFFull) {
- error = -EFBIG;
- goto fail_gunlock;
- }
-
- /* Listen to the Direct I/O flag */
-
- if (ip->i_di.di_flags & GFS_DIF_DIRECTIO)
- file->f_flags |= O_DIRECT;
-
- /* Don't let the user open O_DIRECT on a jdata file */
-
- if ((file->f_flags & O_DIRECT) && gfs_is_jdata(ip)) {
- error = -EINVAL;
- goto fail_gunlock;
- }
-
- gfs_glock_dq_uninit(&i_gh);
- }
-
- return 0;
-
- fail_gunlock:
- gfs_glock_dq_uninit(&i_gh);
-
- fail:
- set_v2fp(file, NULL);
- kfree(fp);
-
- return error;
-}
-
-/**
- * gfs_close - called to close a struct file
- * @inode: the inode the struct file belongs to
- * @file: the struct file being closed
- *
- * Returns: errno
- */
-
-static int
-gfs_close(struct inode *inode, struct file *file)
-{
- struct gfs_sbd *sdp = get_v2sdp(inode->i_sb);
- struct gfs_file *fp;
-
- atomic_inc(&sdp->sd_ops_file);
-
- fp = get_v2fp(file);
- set_v2fp(file, NULL);
-
- if (!gfs_assert_warn(sdp, fp))
- kfree(fp);
-
- return 0;
-}
-
-/**
- * gfs_fsync - sync the dirty data for a file (across the cluster)
- * @file: the file that points to the dentry (we ignore this)
- * @dentry: the dentry that points to the inode to sync
- *
- * Returns: errno
- *
- * Obtain a SHARED lock on the file, to force any node with an EXCLUSIVE lock
- * to sync file's dirty data to disk, as it releases the EXCLUSIVE lock.
- */
-
-static int
-gfs_fsync(struct file *file, struct dentry *dentry, int datasync)
-{
- struct gfs_inode *ip = get_v2ip(dentry->d_inode);
- struct gfs_holder i_gh;
- struct inode *inode = dentry->d_inode;
- int error;
-
- atomic_inc(&ip->i_sbd->sd_ops_file);
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
- if (error)
- return error;
-
- if (gfs_is_jdata(ip))
- gfs_log_flush_glock(ip->i_gl);
- else {
- if ((!datasync) || (inode->i_state & I_DIRTY_DATASYNC)) {
- struct writeback_control wbc = {
- .sync_mode = WB_SYNC_ALL,
- .nr_to_write = 0,
- };
- error = sync_inode(inode, &wbc);
- }
- if (gfs_is_stuffed(ip))
- gfs_log_flush_glock(ip->i_gl);
- }
-
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gfs_lock - acquire/release a posix lock on a file
- * @file: the file pointer
- * @cmd: either modify or retrieve lock state, possibly wait
- * @fl: type and range of lock
- *
- * Returns: errno
- */
-
-static int
-gfs_lock(struct file *file, int cmd, struct file_lock *fl)
-{
- struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
- struct gfs_sbd *sdp = ip->i_sbd;
- struct lm_lockname name =
- { .ln_number = ip->i_num.no_formal_ino,
- .ln_type = LM_TYPE_PLOCK };
-
- atomic_inc(&sdp->sd_ops_file);
-
- if (!(fl->fl_flags & FL_POSIX))
- return -ENOLCK;
- if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
- return -ENOLCK;
-
- if (cmd == F_CANCELLK) {
- /* Hack: */
- cmd = F_SETLK;
- fl->fl_type = F_UNLCK;
- }
-
- if (IS_GETLK(cmd))
- return gfs_lm_plock_get(sdp, &name, file, fl);
- else if (fl->fl_type == F_UNLCK)
- return gfs_lm_punlock(sdp, &name, file, fl);
- else
- return gfs_lm_plock(sdp, &name, file, cmd, fl);
-}
-
-/**
- * gfs_splice_read - Send bytes to a file or socket
- * @in_file: The file to read from
- * @out_file: The file to write to
- * @count: The amount of data
- * @ppos: The beginning file offset
- *
- * Outputs: offset - updated according to number of bytes read
- *
- * Returns: The number of bytes sent, errno on failure
- */
-
-static ssize_t
-gfs_splice_read(struct file *in_file, loff_t *ppos, struct pipe_inode_info *pipe, size_t count, unsigned int flags)
-{
- struct gfs_inode *ip = get_v2ip(in_file->f_mapping->host);
- struct gfs_holder gh;
- ssize_t retval;
-
- atomic_inc(&ip->i_sbd->sd_ops_file);
-
- gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
-
- retval = gfs_glock_nq_atime(&gh);
- if (retval)
- goto out;
-
- if (gfs_is_jdata(ip))
- retval = -ENOSYS;
- else
- retval = generic_file_splice_read(in_file, ppos, pipe, count, flags);
-
- gfs_glock_dq(&gh);
-
- out:
- gfs_holder_uninit(&gh);
-
- return retval;
-}
-
-/**
- * do_flock - Acquire a flock on a file
- * @file:
- * @cmd:
- * @fl:
- *
- * Returns: errno
- */
-
-static int
-do_flock(struct file *file, int cmd, struct file_lock *fl)
-{
- struct gfs_file *fp = get_v2fp(file);
- struct gfs_holder *fl_gh = &fp->f_fl_gh;
- struct gfs_inode *ip = fp->f_inode;
- struct gfs_glock *gl;
- unsigned int state;
- int flags;
- int error = 0;
-
- state = (fl->fl_type == F_WRLCK) ? LM_ST_EXCLUSIVE : LM_ST_SHARED;
- flags = ((IS_SETLKW(cmd)) ? 0 : LM_FLAG_TRY) | GL_EXACT | GL_NOCACHE
- | GL_FLOCK;
-
- down(&fp->f_fl_lock);
-
- gl = fl_gh->gh_gl;
- if (gl) {
- if (fl_gh->gh_state == state)
- goto out;
- flock_lock_file_wait(file,
- &(struct file_lock){.fl_type = F_UNLCK});
- gfs_glock_dq_wait(fl_gh);
- gfs_holder_reinit(state, flags, fl_gh);
- } else {
- error = gfs_glock_get(ip->i_sbd,
- ip->i_num.no_formal_ino, &gfs_flock_glops,
- CREATE, &gl);
- if (error)
- goto out;
- gfs_holder_init(gl, state, flags, fl_gh);
- gfs_glock_put(gl);
- }
- error = gfs_glock_nq(fl_gh);
- if (error) {
- gfs_holder_uninit(fl_gh);
- if (error == GLR_TRYFAILED)
- error = -EAGAIN;
- } else {
- error = flock_lock_file_wait(file, fl);
- gfs_assert_warn(ip->i_sbd, !error);
- }
-
- out:
- up(&fp->f_fl_lock);
-
- return error;
-}
-
-/**
- * do_unflock - Release a flock on a file
- * @file: the file
- * @fl:
- *
- */
-
-static void
-do_unflock(struct file *file, struct file_lock *fl)
-{
- struct gfs_file *fp = get_v2fp(file);
- struct gfs_holder *fl_gh = &fp->f_fl_gh;
-
- down(&fp->f_fl_lock);
- flock_lock_file_wait(file, fl);
- if (fl_gh->gh_gl)
- gfs_glock_dq_uninit(fl_gh);
- up(&fp->f_fl_lock);
-}
-
-/**
- * gfs_flock - acquire/release a flock lock on a file
- * @file: the file pointer
- * @cmd: either modify or retrieve lock state, possibly wait
- * @fl: type and range of lock
- *
- * Returns: errno
- */
-
-static int
-gfs_flock(struct file *file, int cmd, struct file_lock *fl)
-{
- struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
-
- atomic_inc(&ip->i_sbd->sd_ops_file);
-
- if (!(fl->fl_flags & FL_FLOCK))
- return -ENOLCK;
- if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
- return -ENOLCK;
-
- if (fl->fl_type == F_UNLCK) {
- do_unflock(file, fl);
- return 0;
- } else
- return do_flock(file, cmd, fl);
-}
-
-struct file_operations gfs_file_fops = {
- .llseek = gfs_llseek,
- .read = gfs_read,
- .write = gfs_write,
- .aio_read = gfs_aio_read,
- .aio_write = gfs_aio_write,
- .ioctl = gfs_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = gfs_compat_ioctl,
-#endif
- .mmap = gfs_mmap,
- .open = gfs_open,
- .release = gfs_close,
- .fsync = gfs_fsync,
- .lock = gfs_lock,
- .splice_read = gfs_splice_read,
- .flock = gfs_flock,
-};
-
-struct file_operations gfs_file_fops_jdata = {
- .llseek = gfs_llseek,
- .read = gfs_read,
- .write = gfs_write,
- .aio_read = gfs_aio_read,
- .aio_write = gfs_aio_write,
- .ioctl = gfs_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = gfs_compat_ioctl,
-#endif
- .mmap = gfs_mmap,
- .open = gfs_open,
- .release = gfs_close,
- .fsync = gfs_fsync,
- .lock = gfs_lock,
- .flock = gfs_flock,
-};
-
-struct file_operations gfs_dir_fops = {
- .readdir = gfs_readdir,
- .ioctl = gfs_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = gfs_compat_ioctl,
-#endif
- .open = gfs_open,
- .release = gfs_close,
- .fsync = gfs_fsync,
- .lock = gfs_lock,
- .flock = gfs_flock,
-};
-
-struct file_operations gfs_file_fops_nolock = {
- .llseek = gfs_llseek,
- .read = gfs_read,
- .write = gfs_write,
- .aio_read = gfs_aio_read,
- .aio_write = gfs_aio_write,
- .ioctl = gfs_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = gfs_compat_ioctl,
-#endif
- .mmap = gfs_mmap,
- .open = gfs_open,
- .release = gfs_close,
- .fsync = gfs_fsync,
- .splice_read = gfs_splice_read,
-};
-
-struct file_operations gfs_file_fops_nolock_jdata = {
- .llseek = gfs_llseek,
- .read = gfs_read,
- .write = gfs_write,
- .aio_read = gfs_aio_read,
- .aio_write = gfs_aio_write,
- .ioctl = gfs_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = gfs_compat_ioctl,
-#endif
- .mmap = gfs_mmap,
- .open = gfs_open,
- .release = gfs_close,
- .fsync = gfs_fsync,
-};
-
-struct file_operations gfs_dir_fops_nolock = {
- .readdir = gfs_readdir,
- .ioctl = gfs_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = gfs_compat_ioctl,
-#endif
- .open = gfs_open,
- .release = gfs_close,
- .fsync = gfs_fsync,
-};
diff --git a/gfs-kernel/src/gfs/ops_file.h b/gfs-kernel/src/gfs/ops_file.h
deleted file mode 100644
index 4e7e15f..0000000
--- a/gfs-kernel/src/gfs/ops_file.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __OPS_FILE_DOT_H__
-#define __OPS_FILE_DOT_H__
-
-extern struct file_operations gfs_file_fops;
-extern struct file_operations gfs_file_fops_jdata;
-extern struct file_operations gfs_dir_fops;
-extern struct file_operations gfs_file_fops_nolock;
-extern struct file_operations gfs_file_fops_nolock_jdata;
-extern struct file_operations gfs_dir_fops_nolock;
-
-#endif /* __OPS_FILE_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/ops_fstype.c b/gfs-kernel/src/gfs/ops_fstype.c
deleted file mode 100644
index 8bc76bf..0000000
--- a/gfs-kernel/src/gfs/ops_fstype.c
+++ /dev/null
@@ -1,828 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/vmalloc.h>
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-
-#include "gfs.h"
-#include "daemon.h"
-#include "glock.h"
-#include "glops.h"
-#include "inode.h"
-#include "lm.h"
-#include "mount.h"
-#include "ops_export.h"
-#include "ops_fstype.h"
-#include "ops_super.h"
-#include "proc.h"
-#include "quota.h"
-#include "recovery.h"
-#include "rgrp.h"
-#include "super.h"
-#include "sys.h"
-#include "unlinked.h"
-
-#define DO 0
-#define UNDO 1
-
-extern struct dentry_operations gfs_dops;
-
-static struct gfs_sbd *init_sbd(struct super_block *sb)
-{
- struct gfs_sbd *sdp;
- unsigned int x;
-
- sdp = vmalloc(sizeof(struct gfs_sbd));
- if (!sdp)
- return NULL;
-
- memset(sdp, 0, sizeof(struct gfs_sbd));
-
- set_v2sdp(sb, sdp);
- sdp->sd_vfs = sb;
- gfs_tune_init(&sdp->sd_tune);
-
- /* Init rgrp variables */
-
- INIT_LIST_HEAD(&sdp->sd_rglist);
- init_MUTEX(&sdp->sd_rindex_lock);
- INIT_LIST_HEAD(&sdp->sd_rg_mru_list);
- spin_lock_init(&sdp->sd_rg_mru_lock);
- INIT_LIST_HEAD(&sdp->sd_rg_recent);
- spin_lock_init(&sdp->sd_rg_recent_lock);
- spin_lock_init(&sdp->sd_rg_forward_lock);
-
- spin_lock_init(&sdp->sd_statfs_spin);
-
- for (x = 0; x < GFS_GL_HASH_SIZE; x++) {
- sdp->sd_gl_hash[x].hb_lock = RW_LOCK_UNLOCKED;
- INIT_LIST_HEAD(&sdp->sd_gl_hash[x].hb_list);
- }
-
- INIT_LIST_HEAD(&sdp->sd_reclaim_list);
- spin_lock_init(&sdp->sd_reclaim_lock);
- init_waitqueue_head(&sdp->sd_reclaim_wchan);
-
- for (x = 0; x < GFS_MHC_HASH_SIZE; x++)
- INIT_LIST_HEAD(&sdp->sd_mhc[x]);
- INIT_LIST_HEAD(&sdp->sd_mhc_single);
- spin_lock_init(&sdp->sd_mhc_lock);
-
- for (x = 0; x < GFS_DEPEND_HASH_SIZE; x++)
- INIT_LIST_HEAD(&sdp->sd_depend[x]);
- spin_lock_init(&sdp->sd_depend_lock);
-
- init_MUTEX(&sdp->sd_freeze_lock);
-
- spin_lock_init(&sdp->sd_log_seg_lock);
- INIT_LIST_HEAD(&sdp->sd_log_seg_list);
- init_waitqueue_head(&sdp->sd_log_seg_wait);
- INIT_LIST_HEAD(&sdp->sd_log_ail);
- INIT_LIST_HEAD(&sdp->sd_log_incore);
- init_rwsem(&sdp->sd_log_lock);
- INIT_LIST_HEAD(&sdp->sd_unlinked_list);
- spin_lock_init(&sdp->sd_unlinked_lock);
- INIT_LIST_HEAD(&sdp->sd_quota_list);
- spin_lock_init(&sdp->sd_quota_lock);
-
- INIT_LIST_HEAD(&sdp->sd_dirty_j);
- spin_lock_init(&sdp->sd_dirty_j_lock);
-
- spin_lock_init(&sdp->sd_ail_lock);
- INIT_LIST_HEAD(&sdp->sd_recovery_bufs);
-
- return sdp;
-}
-
-static void init_vfs(struct super_block *sb, unsigned noatime)
-{
- struct gfs_sbd *sdp = sb->s_fs_info;
-
- /* Set up Linux Virtual (VFS) Super Block */
-
- sb->s_magic = GFS_MAGIC;
- sb->s_op = &gfs_super_ops;
- sb->s_export_op = &gfs_export_ops;
-
- /* Don't let the VFS update atimes. GFS handles this itself. */
- sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
- sb->s_maxbytes = MAX_LFS_FILESIZE;
-
- /* If we were mounted with -o acl (to support POSIX access control
- lists), tell VFS */
- if (sdp->sd_args.ar_posix_acls)
- sb->s_flags |= MS_POSIXACL;
-}
-
-int init_names(struct gfs_sbd *sdp, int silent)
-{
- struct gfs_sb *sb = NULL;
- char *proto, *table;
- int error = 0;
-
- proto = sdp->sd_args.ar_lockproto;
- table = sdp->sd_args.ar_locktable;
-
- /* Try to autodetect */
-
- if (!proto[0] || !table[0]) {
- struct buffer_head *bh;
-
- bh = sb_getblk(sdp->sd_vfs,
- GFS_SB_ADDR >> sdp->sd_fsb2bb_shift);
- lock_buffer(bh);
- clear_buffer_uptodate(bh);
- clear_buffer_dirty(bh);
- unlock_buffer(bh);
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
-
- if (!buffer_uptodate(bh)) {
- brelse(bh);
- return -EIO;
- }
-
- sb = kmalloc(sizeof(struct gfs_sb), GFP_KERNEL);
- if (!sb) {
- brelse(bh);
- return -ENOMEM;
- }
- gfs_sb_in(sb, bh->b_data);
- brelse(bh);
-
- error = gfs_check_sb(sdp, sb, silent);
- if (error)
- goto out;
-
- if (!proto[0])
- proto = sb->sb_lockproto;
- if (!table[0])
- table = sb->sb_locktable;
- }
-
- if (!table[0])
- table = sdp->sd_vfs->s_id;
-
- snprintf(sdp->sd_proto_name, 256, "%s", proto);
- snprintf(sdp->sd_table_name, 256, "%s", table);
-
- while ((table = strchr(sdp->sd_table_name, '/')))
- *table = '_';
-
- out:
- kfree(sb);
-
- return error;
-}
-
-static int init_locking(struct gfs_sbd *sdp, struct gfs_holder *mount_gh,
- int undo)
-{
- struct task_struct *p;
- int error = 0;
-
- if (undo)
- goto fail_live;
-
- if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) &&
- !sdp->sd_args.ar_ignore_local_fs) {
- /* Force local [p|f]locks */
- sdp->sd_args.ar_localflocks = TRUE;
-
- /* Force local read ahead and caching */
- sdp->sd_args.ar_localcaching = TRUE;
-
- /* Allow the machine to oops */
- sdp->sd_args.ar_oopses_ok = TRUE;
- }
-
- /* Start up the scand thread */
-
- p = kthread_run(gfs_scand, sdp, "gfs_scand");
- error = IS_ERR(p);
- if (error) {
- printk("GFS: fsid=%s: can't start scand thread: %d\n",
- sdp->sd_fsname, error);
- return error;
- }
- sdp->sd_scand_process = p;
-
- /* Start up the glockd thread */
-
- for (sdp->sd_glockd_num = 0;
- sdp->sd_glockd_num < sdp->sd_args.ar_num_glockd;
- sdp->sd_glockd_num++) {
- p = kthread_run(gfs_glockd, sdp, "gfs_glockd");
- error = IS_ERR(p);
- if (error) {
- printk("GFS: fsid=%s: can't start glockd thread: %d\n",
- sdp->sd_fsname, error);
- goto fail;
- }
- sdp->sd_glockd_process[sdp->sd_glockd_num] = p;
- }
-
- /* Only one node may mount at a time */
- error = gfs_glock_nq_num(sdp,
- GFS_MOUNT_LOCK, &gfs_nondisk_glops,
- LM_ST_EXCLUSIVE, LM_FLAG_NOEXP | GL_NOCACHE,
- mount_gh);
- if (error) {
- printk("GFS: fsid=%s: can't acquire mount glock: %d\n",
- sdp->sd_fsname, error);
- goto fail;
- }
-
- /* Show that cluster is alive */
- error = gfs_glock_nq_num(sdp,
- GFS_LIVE_LOCK, &gfs_nondisk_glops,
- LM_ST_SHARED, LM_FLAG_NOEXP | GL_EXACT,
- &sdp->sd_live_gh);
- if (error) {
- printk("GFS: fsid=%s: can't acquire live glock: %d\n",
- sdp->sd_fsname, error);
- goto fail_mount;
- }
-
- sdp->sd_live_gh.gh_owner = NULL;
- return 0;
-
-fail_live:
- gfs_glock_dq_uninit(&sdp->sd_live_gh);
-
-fail_mount:
- gfs_glock_dq_uninit(mount_gh);
-
-fail:
- while (sdp->sd_glockd_num--)
- kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]);
-
- kthread_stop(sdp->sd_scand_process);
-
- return error;
-}
-
-static int init_sb(struct gfs_sbd *sdp, int silent, int undo)
-{
- struct super_block *sb = sdp->sd_vfs;
- struct gfs_holder sb_gh;
- int error = 0;
- struct inode *inode;
-
- if (undo)
- goto fail_dput;
-
- /* Read the SuperBlock from disk, get enough info to enable us
- to read-in the journal index and replay all journals. */
-
- error = gfs_glock_nq_num(sdp,
- GFS_SB_LOCK, &gfs_meta_glops,
- (sdp->sd_args.ar_upgrade) ? LM_ST_EXCLUSIVE : LM_ST_SHARED,
- 0, &sb_gh);
- if (error) {
- printk("GFS: fsid=%s: can't acquire superblock glock: %d\n",
- sdp->sd_fsname, error);
- return error;
- }
-
- error = gfs_read_sb(sdp, sb_gh.gh_gl, silent);
- if (error) {
- printk("GFS: fsid=%s: can't read superblock: %d\n",
- sdp->sd_fsname, error);
- goto out;
- }
-
- /* Set up the buffer cache and SB for real, now that we know block
- sizes, version #s, locations of important on-disk inodes, etc. */
-
- error = -EINVAL;
- if (sdp->sd_sb.sb_bsize < bdev_logical_block_size(sb->s_bdev)) {
- printk("GFS: fsid=%s: FS block size (%u) is too small for device block size (%u)\n",
- sdp->sd_fsname, sdp->sd_sb.sb_bsize, bdev_logical_block_size(sb->s_bdev));
- goto fail;
- }
- if (sdp->sd_sb.sb_bsize > PAGE_SIZE) {
- printk("GFS: fsid=%s: FS block size (%u) is too big for machine page size (%u)\n",
- sdp->sd_fsname, sdp->sd_sb.sb_bsize,
- (unsigned int)PAGE_SIZE);
- goto fail;
- }
-
- /* Get rid of buffers from the original block size */
- sb_gh.gh_gl->gl_ops->go_inval(sb_gh.gh_gl, DIO_METADATA | DIO_DATA);
- sb_gh.gh_gl->gl_aspace->i_blkbits = sdp->sd_sb.sb_bsize_shift;
-
- sb_set_blocksize(sb, sdp->sd_sb.sb_bsize);
-
- /* Read in the resource index inode */
-
- error = gfs_get_riinode(sdp);
- if (error) {
- printk("GFS: fsid=%s: can't get resource index inode: %d\n",
- sdp->sd_fsname, error);
- goto fail;
- }
-
- /* Get the root inode */
- error = gfs_get_rootinode(sdp);
- if (error) {
- printk("GFS: fsid=%s: can't read in root inode: %d\n",
- sdp->sd_fsname, error);
- goto fail_ri_free;
- }
- /* Get the root inode/dentry */
-
- inode = gfs_iget(sdp->sd_rooti, CREATE);
- if (!inode) {
- printk("GFS: fsid=%s: can't get root inode\n", sdp->sd_fsname);
- error = -ENOMEM;
- goto fail_ri_free;
- }
- sb->s_root = d_alloc_root(inode);
- if (!sb->s_root) {
- iput(inode);
- printk("GFS: fsid=%s: can't get root dentry\n", sdp->sd_fsname);
- error = -ENOMEM;
- goto fail_root_free;
- }
- sb->s_root->d_op = &gfs_dops;
-
- /* Read in the quota inode */
- error = gfs_get_qinode(sdp);
- if (error) {
- printk("GFS: fsid=%s: can't get quota file inode: %d\n",
- sdp->sd_fsname, error);
- goto fail_root_free;
- }
-
- /* Implement fast statfs on the unused license inode location.
- * sb->sb_quota_di.no_formal_ino = jindex_dinode + 2;
- * sb->sb_quota_di.no_addr = jindex_dinode + 2;
- * sb->sb_license_di.no_formal_ino = jindex_dinode + 3;
- * sb->sb_license_di.no_addr = jindex_dinode + 3;
- */
- error = gfs_get_linode(sdp);
- if (error) {
- printk("GFS: fsid=%s: can't get statfs file inode: %d\n",
- sdp->sd_fsname, error);
- goto fail_qi_free;
- }
-
- /* We're through with the superblock lock */
-out:
- gfs_glock_dq_uninit(&sb_gh);
- return error;
-
-fail_dput:
- gfs_inode_put(sdp->sd_linode);
- if (sb->s_root) {
- dput(sb->s_root);
- sb->s_root = NULL;
- }
-fail_qi_free:
- gfs_inode_put(sdp->sd_qinode);
-fail_root_free:
- gfs_inode_put(sdp->sd_rooti);
-fail_ri_free:
- gfs_inode_put(sdp->sd_riinode);
- gfs_clear_rgrpd(sdp);
-fail:
- if (!undo)
- gfs_glock_dq_uninit(&sb_gh);
- return error;
-}
-
-static int init_journal(struct gfs_sbd *sdp, int undo)
-{
- struct gfs_holder ji_gh;
- int error = 0;
- unsigned int x;
- int jindex = TRUE;
- struct task_struct *p;
-
- if (undo) {
- jindex = 0;
- goto fail_recoverd;
- }
-
- init_MUTEX(&sdp->sd_jindex_lock);
-
- /* Get a handle on the transaction glock; we need this for disk format
- upgrade and journal replays, as well as normal operation. */
-
- error = gfs_glock_get(sdp, GFS_TRANS_LOCK, &gfs_trans_glops,
- CREATE, &sdp->sd_trans_gl);
- if (error)
- return error;
- set_bit(GLF_STICKY, &sdp->sd_trans_gl->gl_flags);
-
- /* Load in the journal index special file */
-
- error = gfs_jindex_hold(sdp, &ji_gh);
- if (error) {
- printk("GFS: fsid=%s: can't read journal index: %d\n",
- sdp->sd_fsname, error);
- goto fail_jhold;
- }
-
- if (sdp->sd_args.ar_spectator) {
- sdp->sd_jdesc = sdp->sd_jindex[0];
- sdp->sd_log_seg_free = sdp->sd_jdesc.ji_nsegment;
- sdp->sd_log_seg_ail2 = 0;
- }
- else {
- /* Discover this node's journal number (lock module tells us
- which one to use), and lock it */
- error = -EUSERS;
- if (sdp->sd_lockstruct.ls_jid >= sdp->sd_journals) {
- printk("GFS: fsid=%s: can't mount journal #%u\n",
- sdp->sd_fsname, sdp->sd_lockstruct.ls_jid);
- printk("GFS: fsid=%s: there are only %u journals (0 - %u)\n",
- sdp->sd_fsname, sdp->sd_journals, sdp->sd_journals - 1);
- goto fail_jindex;
- }
- sdp->sd_jdesc = sdp->sd_jindex[sdp->sd_lockstruct.ls_jid];
- sdp->sd_log_seg_free = sdp->sd_jdesc.ji_nsegment;
- sdp->sd_log_seg_ail2 = 0;
-
- error = gfs_glock_nq_num(sdp,
- sdp->sd_jdesc.ji_addr, &gfs_meta_glops,
- LM_ST_EXCLUSIVE, LM_FLAG_NOEXP,
- &sdp->sd_journal_gh);
- if (error) {
- printk("GFS: fsid=%s: can't acquire the journal glock: %d\n",
- sdp->sd_fsname, error);
- goto fail_jindex;
- }
- }
-
- if (sdp->sd_lockstruct.ls_first) {
- /* We're first node within cluster to mount this filesystem,
- replay ALL of the journals, then let lock module know
- that we're done. */
- for (x = 0; x < sdp->sd_journals; x++) {
- error = gfs_recover_journal(sdp,
- x, sdp->sd_jindex + x,
- FALSE);
- if (error) {
- printk("GFS: fsid=%s: error recovering journal %u: %d\n",
- sdp->sd_fsname, x, error);
- goto fail_journal_gh;
- }
- }
-
- gfs_lm_others_may_mount(sdp);
- } else if (!sdp->sd_args.ar_spectator) {
- /* We're not the first; replay only our own journal. */
- error = gfs_recover_journal(sdp, sdp->sd_lockstruct.ls_jid,
- &sdp->sd_jdesc, TRUE);
- if (error) {
- printk("GFS: fsid=%s: error recovering my journal: %d\n",
- sdp->sd_fsname, error);
- goto fail_journal_gh;
- }
- }
-
- gfs_glock_dq_uninit(&ji_gh);
- jindex = FALSE;
-
- /* Disown my Journal glock */
- sdp->sd_journal_gh.gh_owner = NULL;
-
- /* Make the FS read/write */
-
- if (!test_bit(SDF_ROFS, &sdp->sd_flags)) {
- error = gfs_make_fs_rw(sdp);
- if (error) {
- printk("GFS: fsid=%s: can't make file system RW: %d\n",
- sdp->sd_fsname, error);
- goto fail_journal_gh;
- }
- }
-
- /* Start up the journal recovery thread */
-
- p = kthread_run(gfs_recoverd, sdp, "gfs_recoverd");
- error = IS_ERR(p);
- if (error) {
- printk("GFS: fsid=%s: can't start recoverd thread: %d\n",
- sdp->sd_fsname, error);
- goto fail_journal_gh;
- }
- sdp->sd_recoverd_process = p;
-
- return 0;
-
-fail_recoverd:
- kthread_stop(sdp->sd_recoverd_process);
- sdp->sd_recoverd_process = NULL;
-
-fail_journal_gh:
- if (!sdp->sd_args.ar_spectator)
- gfs_glock_dq_uninit(&sdp->sd_journal_gh);
-
-fail_jindex:
- if (jindex)
- gfs_glock_dq_uninit(&ji_gh);
-
-fail_jhold:
- gfs_glock_put(sdp->sd_trans_gl);
- return error;
-}
-
-static int init_threads(struct gfs_sbd *sdp, int undo)
-{
- struct task_struct *p;
- int error = 0;
-
- if (undo)
- goto fail_logd;
-
- sdp->sd_jindex_refresh_time = jiffies;
-
- /* Start up the logd thread */
- p = kthread_run(gfs_logd, sdp, "gfs_logd");
- error = IS_ERR(p);
- if (error) {
- printk("GFS: fsid=%s: can't start logd thread: %d\n",
- sdp->sd_fsname, error);
- goto fail;
- }
- sdp->sd_logd_process = p;
-
- /* Start up the quotad thread */
-
- p = kthread_run(gfs_quotad, sdp, "gfs_quotad");
- if (error < 0) {
- printk("GFS: fsid=%s: can't start quotad thread: %d\n",
- sdp->sd_fsname, error);
- goto fail_quotad;
- }
- sdp->sd_quotad_process = p;
-
- /* Start up the inoded thread */
-
- p = kthread_run(gfs_inoded, sdp, "gfs_inoded");
- if (error < 0) {
- printk("GFS: fsid=%s: can't start inoded thread: %d\n",
- sdp->sd_fsname, error);
- goto fail_inoded;
- }
- sdp->sd_inoded_process = p;
- return 0;
-
-fail_logd:
- kthread_stop(sdp->sd_inoded_process);
-fail_inoded:
- kthread_stop(sdp->sd_quotad_process);
-fail_quotad:
- kthread_stop(sdp->sd_logd_process);
-fail:
- return error;
-}
-
-void gfs_online_uevent(struct gfs_sbd *sdp)
-{
- struct super_block *sb = sdp->sd_vfs;
- char ro[20];
- char spectator[20];
- char *envp[] = { ro, spectator, NULL };
- sprintf(ro, "RDONLY=%d", (sb->s_flags & MS_RDONLY) ? 1 : 0);
- sprintf(spectator, "SPECTATOR=%d", sdp->sd_args.ar_spectator ? 1 : 0);
- kobject_uevent_env(&sdp->sd_kobj, KOBJ_ONLINE, envp);
-}
-
-/**
- * fill_super - Read in superblock
- * @sb: The VFS superblock
- * @data: Mount options
- * @silent: Don't complain if it's not a GFS filesystem
- *
- * Returns: errno
- *
- * After cross-linking Linux VFS incore superblock and our GFS incore
- * superblock (filesystem instance structures) to one another, we:
- * -- Init some of our GFS incore superblock, including some temporary
- * block-size values (enough to read on-disk superblock).
- * -- Set up some things in Linux VFS superblock.
- * -- Mount a lock module, init glock system (incl. glock reclaim daemons),
- * and init some important inter-node locks (MOUNT, LIVE, SuperBlock).
- * -- Read-in the GFS on-disk superblock (1st time, to get enough info
- * to do filesystem upgrade and journal replay, incl. journal index).
- * -- Upgrade on-disk filesystem format (rarely needed).
- * -- Replay journals (always; replay *all* journals if we're first-to-mount).
- * -- Read-in on-disk superblock and journal index special file again
- * (2nd time, assumed 100% valid now after journal replay).
- * -- Read-in info on other special (hidden) files (root inode, resource index,
- * quota inode, license inode).
- * -- Start other daemons (journal/log recovery, log tail, quota updates, inode
- * reclaim) for periodic maintenance.
- *
- */
-
-static int fill_super(struct super_block *sb, void *data, int silent)
-{
- struct gfs_sbd *sdp;
- struct gfs_holder mount_gh;
- int error;
-
- sdp = init_sbd(sb);
- if (!sdp) {
- printk(KERN_WARNING "GFS: can't alloc struct gfs_sbd\n");
- return -ENOMEM;
- }
-
- error = gfs_make_args((char *)data, &sdp->sd_args, FALSE);
- if (error) {
- printk("GFS: can't parse mount arguments\n");
- goto fail;
- }
-
- if (sdp->sd_args.ar_spectator) {
- sb->s_flags |= MS_RDONLY;
- set_bit(SDF_ROFS, &sdp->sd_flags);
- }
-
- /* Copy VFS mount flags */
-
- if (sdp->sd_args.ar_noatime)
- set_bit(SDF_NOATIME, &sdp->sd_flags);
- if (sb->s_flags & MS_RDONLY)
- set_bit(SDF_ROFS, &sdp->sd_flags);
-
- init_vfs(sb, SDF_NOATIME);
-
- /* Turn off quota stuff if we get the noquota mount option, don't
- need to grab the sd_tune lock here since its before anything
- touches the sd_tune values */
- if (sdp->sd_args.ar_noquota) {
- sdp->sd_tune.gt_quota_enforce = 0;
- sdp->sd_tune.gt_quota_account = 0;
- }
-
- /* Set up the buffer cache and fill in some fake block size values
- to allow us to read-in the on-disk superblock. */
-
- sdp->sd_sb.sb_bsize = sb_min_blocksize(sb, GFS_BASIC_BLOCK);
- sdp->sd_sb.sb_bsize_shift = sb->s_blocksize_bits;
- sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - GFS_BASIC_BLOCK_SHIFT;
- sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;
-
- if (sizeof(struct gfs_sb) > sdp->sd_sb.sb_bsize) {
- printk("GFS: sizeof(struct gfs_sb) > sdp->sd_sb.sb_bsize\n"
- "GFS: %u > %u\n",
- (unsigned int)sizeof(struct gfs_sb), sdp->sd_sb.sb_bsize);
- error = -EINVAL;
- goto fail;
- }
- error = init_names(sdp, silent);
- if (error)
- goto fail;
-
- error = gfs_sys_fs_add(sdp);
- if (error)
- goto fail;
-
- /* Mount an inter-node lock module, check for local optimizations */
-
- error = gfs_lm_mount(sdp, silent);
- if (error)
- goto fail_sys;
-
- error = init_locking(sdp, &mount_gh, DO);
- if (error)
- goto fail_lm;
-
- error = init_sb(sdp, silent, DO);
- if (error)
- goto fail_locking;
-
- /* Read-in journal index inode (but not the file contents, yet) */
-
- error = gfs_get_jiinode(sdp);
- if (error) {
- printk("GFS: fsid=%s: can't get journal index inode: %d\n",
- sdp->sd_fsname, error);
- goto fail_jiinode;
- }
-
- error = init_journal(sdp, DO);
- if (error)
- goto fail_sb;
- /* Get a handle on the rename lock */
-
- error = gfs_glock_get(sdp, GFS_RENAME_LOCK, &gfs_nondisk_glops,
- CREATE, &sdp->sd_rename_gl);
- if (error)
- goto fail_journal;
-
- error = init_threads(sdp, DO);
- if (error)
- goto fail_journal;
-
- gfs_proc_fs_add(sdp);
- gfs_glock_dq_uninit(&mount_gh);
- gfs_online_uevent(sdp);
-
- return 0;
-
-fail_journal:
- init_journal(sdp, UNDO);
-
-fail_sb:
- gfs_inode_put(sdp->sd_jiinode);
-
-fail_jiinode:
- init_sb(sdp, 0, UNDO);
-
-fail_locking:
- init_locking(sdp, &mount_gh, UNDO);
-
-fail_lm:
- gfs_gl_hash_clear(sdp, TRUE);
- gfs_lm_unmount(sdp);
- gfs_clear_dirty_j(sdp);
- while (invalidate_inodes(sb))
- yield();
-
-fail_sys:
- gfs_sys_fs_del(sdp);
-
-fail:
- vfree(sdp);
- sb->s_fs_info = NULL;
-
- return error;
-}
-
-/**
- * gfs_test_bdev_super -
- * @sb:
- * @data:
- *
- */
-
-int
-gfs_test_bdev_super(struct super_block *sb, void *data)
-{
- return (void *)sb->s_bdev == data;
-}
-
-/**
- * gfs_test_bdev_super -
- * @sb:
- * @data:
- *
- */
-
-int
-gfs_set_bdev_super(struct super_block *sb, void *data)
-{
- sb->s_bdev = data;
- sb->s_dev = sb->s_bdev->bd_dev;
- return 0;
-}
-
-/**
- * gfs_get_sb -
- * @fs_type:
- * @flags:
- * @dev_name:
- * @data:
- *
- * Rip off of get_sb_bdev().
- *
- * Returns: the new superblock
- */
-
-static int gfs_get_sb(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *data, struct vfsmount *mnt)
-{
- return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt);
-}
-
-/**
- * gfs_kill_sb -
- * @sb:
- *
- * Rip off of kill_block_super().
- *
- */
-
-void
-gfs_kill_sb(struct super_block *sb)
-{
- kill_block_super(sb);
-}
-
-struct file_system_type gfs_fs_type = {
- .name = "gfs",
- .fs_flags = FS_REQUIRES_DEV,
- .get_sb = gfs_get_sb,
- .kill_sb = gfs_kill_sb,
- .owner = THIS_MODULE,
-};
diff --git a/gfs-kernel/src/gfs/ops_fstype.h b/gfs-kernel/src/gfs/ops_fstype.h
deleted file mode 100644
index 6d97022..0000000
--- a/gfs-kernel/src/gfs/ops_fstype.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __OPS_FSTYPE_DOT_H__
-#define __OPS_FSTYPE_DOT_H__
-
-int gfs_sys_init(void);
-void gfs_sys_uninit(void);
-void gfs_sys_fs_del(struct gfs_sbd *sdp);
-int gfs_test_bdev_super(struct super_block *sb, void *data);
-int gfs_set_bdev_super(struct super_block *sb, void *data);
-int init_names(struct gfs_sbd *sdp, int silent);
-
-extern struct file_system_type gfs_fs_type;
-
-#endif /* __OPS_FSTYPE_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/ops_inode.c b/gfs-kernel/src/gfs/ops_inode.c
deleted file mode 100644
index bac215c..0000000
--- a/gfs-kernel/src/gfs/ops_inode.c
+++ /dev/null
@@ -1,1680 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/namei.h>
-#include <linux/utsname.h>
-#include <asm/uaccess.h>
-#include <linux/mm.h>
-#include <linux/xattr.h>
-#include <linux/posix_acl.h>
-#include <linux/security.h>
-#include <linux/cred.h>
-
-#include "gfs.h"
-#include "acl.h"
-#include "bmap.h"
-#include "dio.h"
-#include "dir.h"
-#include "eaops.h"
-#include "eattr.h"
-#include "glock.h"
-#include "inode.h"
-#include "ops_dentry.h"
-#include "ops_inode.h"
-#include "page.h"
-#include "quota.h"
-#include "rgrp.h"
-#include "trans.h"
-#include "unlinked.h"
-
-/**
- * gfs_security_init -
- * @dip:
- * @ip:
- *
- * Returns: errno
- */
-
-static int
-gfs_security_init(struct gfs_inode *dip, struct gfs_inode *ip)
-{
- int err;
- size_t len;
- void *value;
- char *name;
- struct gfs_ea_request er;
-
- err = security_inode_init_security(ip->i_vnode, dip->i_vnode,
- &name, &value, &len);
-
- if (err) {
- if (err == -EOPNOTSUPP)
- return 0;
- return err;
- }
-
- memset(&er, 0, sizeof(struct gfs_ea_request));
-
- er.er_type = GFS_EATYPE_SECURITY;
- er.er_name = name;
- er.er_data = value;
- er.er_name_len = strlen(name);
- er.er_data_len = len;
-
- err = gfs_ea_set_i(ip, &er);
-
- kfree(value);
- kfree(name);
-
- return err;
-}
-
-/**
- * gfs_create - Create a file
- * @dir: The directory in which to create the file
- * @dentry: The dentry of the new file
- * @mode: The mode of the new file
- *
- * Returns: errno
- */
-
-static int
-gfs_create(struct inode *dir, struct dentry *dentry,
- int mode, struct nameidata *nd)
-{
- struct gfs_inode *dip = get_v2ip(dir), *ip;
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_holder d_gh, i_gh;
- struct inode *inode;
- int new = TRUE;
- int error;
-
- atomic_inc(&sdp->sd_ops_inode);
-
- gfs_unlinked_limit(sdp);
-
- gfs_holder_init(dip->i_gl, 0, 0, &d_gh);
-
- for (;;) {
- error = gfs_createi(&d_gh, &dentry->d_name,
- GFS_FILE_REG, mode,
- &i_gh);
- if (!error)
- break;
- else if (error != -EEXIST ||
- (nd && (nd->intent.open.flags & O_EXCL))) {
- gfs_holder_uninit(&d_gh);
- return error;
- }
-
- error = gfs_lookupi(&d_gh, &dentry->d_name,
- FALSE, &i_gh);
- if (!error) {
- if (i_gh.gh_gl) {
- new = FALSE;
- break;
- }
- } else {
- gfs_holder_uninit(&d_gh);
- return error;
- }
- }
-
- ip = get_gl2ip(i_gh.gh_gl);
-
- if (new) {
- gfs_trans_end(sdp);
- if (dip->i_alloc->al_rgd)
- gfs_inplace_release(dip);
- gfs_quota_unlock_m(dip);
- gfs_unlinked_unlock(sdp, dip->i_alloc->al_ul);
- gfs_alloc_put(dip);
- }
-
- inode = gfs_iget(ip, CREATE);
- gfs_inode_put(ip);
-
- if (!inode)
- error = -ENOMEM;
- else if (new)
- error = gfs_security_init(dip, ip);
-
- gfs_glock_dq_uninit(&d_gh);
- gfs_glock_dq_uninit(&i_gh);
-
- if (error)
- return error;
-
- d_instantiate(dentry, inode);
- if (new)
- mark_inode_dirty(inode);
-
- return 0;
-}
-
-/**
- * lookup_cdpn_sub_at - Maybe lookup a Context Dependent Pathname
- * @sdp: the filesystem
- * @dentry: the original dentry to lookup
- * @new_dentry: the new dentry, if this was a substitutable path.
- *
- * Returns: the new dentry, a ERR_PTR, or NULL
- */
-
-static struct dentry *
-lookup_cdpn_sub_at(struct gfs_sbd *sdp, struct dentry *dentry)
-{
- struct dentry *parent, *new = NULL;
- char *buf;
-
- buf = kmalloc(2 * __NEW_UTS_LEN + 2, GFP_KERNEL);
- if (!buf)
- return ERR_PTR(-ENOMEM);
-
- parent = dget_parent(dentry);
-
- if (gfs_filecmp(&dentry->d_name, "@hostname", 9))
- new = lookup_one_len(init_utsname()->nodename,
- parent,
- strlen(init_utsname()->nodename));
- else if (gfs_filecmp(&dentry->d_name, "@mach", 5))
- new = lookup_one_len(init_utsname()->machine,
- parent,
- strlen(init_utsname()->machine));
- else if (gfs_filecmp(&dentry->d_name, "@os", 3))
- new = lookup_one_len(init_utsname()->sysname,
- parent,
- strlen(init_utsname()->sysname));
- else if (gfs_filecmp(&dentry->d_name, "@uid", 4))
- new = lookup_one_len(buf,
- parent,
- sprintf(buf, "%u", current_fsuid()));
- else if (gfs_filecmp(&dentry->d_name, "@gid", 4))
- new = lookup_one_len(buf,
- parent,
- sprintf(buf, "%u", current_fsgid()));
- else if (gfs_filecmp(&dentry->d_name, "@sys", 4))
- new = lookup_one_len(buf,
- parent,
- sprintf(buf, "%s_%s",
- init_utsname()->machine,
- init_utsname()->sysname));
- else if (gfs_filecmp(&dentry->d_name, "@jid", 4))
- new = lookup_one_len(buf,
- parent,
- sprintf(buf, "%u",
- sdp->sd_lockstruct.ls_jid));
-
- dput(parent);
- kfree(buf);
-
- return new;
-}
-
-/**
- * lookup_cdpn_sub_brace - Maybe lookup a Context Dependent Pathname
- * @sdp: the filesystem
- * @dentry: the original dentry to lookup
- * @new_dentry: the new dentry, if this was a substitutable path.
- *
- * Returns: the new dentry, a ERR_PTR, or NULL
- */
-
-static struct dentry *
-lookup_cdpn_sub_brace(struct gfs_sbd *sdp, struct dentry *dentry)
-{
- struct dentry *parent, *new = NULL;
- char *buf;
-
- buf = kmalloc(2 * __NEW_UTS_LEN + 2, GFP_KERNEL);
- if (!buf)
- return ERR_PTR(-ENOMEM);
-
- parent = dget_parent(dentry);
-
- if (gfs_filecmp(&dentry->d_name, "{hostname}", 10))
- new = lookup_one_len(init_utsname()->nodename,
- parent,
- strlen(init_utsname()->nodename));
- else if (gfs_filecmp(&dentry->d_name, "{mach}", 6))
- new = lookup_one_len(init_utsname()->machine,
- parent,
- strlen(init_utsname()->machine));
- else if (gfs_filecmp(&dentry->d_name, "{os}", 4))
- new = lookup_one_len(init_utsname()->sysname,
- parent,
- strlen(init_utsname()->sysname));
- else if (gfs_filecmp(&dentry->d_name, "{uid}", 5))
- new = lookup_one_len(buf,
- parent,
- sprintf(buf, "%u", current_fsuid()));
- else if (gfs_filecmp(&dentry->d_name, "{gid}", 5))
- new = lookup_one_len(buf,
- parent,
- sprintf(buf, "%u", current_fsgid()));
- else if (gfs_filecmp(&dentry->d_name, "{sys}", 5))
- new = lookup_one_len(buf,
- parent,
- sprintf(buf, "%s_%s",
- init_utsname()->machine,
- init_utsname()->sysname));
- else if (gfs_filecmp(&dentry->d_name, "{jid}", 5))
- new = lookup_one_len(buf,
- parent,
- sprintf(buf, "%u",
- sdp->sd_lockstruct.ls_jid));
-
- dput(parent);
- kfree(buf);
-
- return new;
-}
-
-/**
- * gfs_lookup - Look up a filename in a directory and return its inode
- * @dir: The directory inode
- * @dentry: The dentry of the new inode
- * @nd: passed from Linux VFS, ignored by us
- *
- * Called by the VFS layer. Lock dir and call gfs_lookupi()
- *
- * Returns: errno
- */
-
-static struct dentry *
-gfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
- struct gfs_inode *dip = get_v2ip(dir), *ip;
- struct gfs_holder d_gh, i_gh;
- struct inode *inode = NULL;
- int error;
-
- atomic_inc(&dip->i_sbd->sd_ops_inode);
-
- /* Do Context Dependent Path Name expansion */
-
- if (*dentry->d_name.name == '@' && dentry->d_name.len > 1) {
- struct dentry *new_dentry;
- new_dentry = lookup_cdpn_sub_at(dip->i_sbd, dentry);
- if (new_dentry)
- return new_dentry;
- } else if (*dentry->d_name.name == '{' && dentry->d_name.len > 2) {
- struct dentry *new_dentry;
- new_dentry = lookup_cdpn_sub_brace(dip->i_sbd, dentry);
- if (new_dentry)
- return new_dentry;
- }
-
- dentry->d_op = &gfs_dops;
-
- gfs_holder_init(dip->i_gl, 0, 0, &d_gh);
-
- error = gfs_lookupi(&d_gh, &dentry->d_name, FALSE, &i_gh);
- if (error) {
- gfs_holder_uninit(&d_gh);
- return ERR_PTR(error);
- }
-
- if (i_gh.gh_gl) {
- ip = get_gl2ip(i_gh.gh_gl);
-
- inode = gfs_iget(ip, CREATE);
- gfs_inode_put(ip);
-
- gfs_glock_dq_uninit(&d_gh);
- gfs_glock_dq_uninit(&i_gh);
-
- if (!inode)
- return ERR_PTR(-ENOMEM);
- } else
- gfs_holder_uninit(&d_gh);
-
- if (inode)
- return d_splice_alias(inode, dentry);
- d_add(dentry, inode);
-
- return NULL;
-}
-
-/**
- * gfs_link - Link to a file
- * @old_dentry: The inode to link
- * @dir: Add link to this directory
- * @dentry: The name of the link
- *
- * Link the inode in "old_dentry" into the directory "dir" with the
- * name in "dentry".
- *
- * Returns: errno
- */
-
-static int
-gfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
-{
- struct gfs_inode *dip = get_v2ip(dir);
- struct gfs_sbd *sdp = dip->i_sbd;
- struct inode *inode = old_dentry->d_inode;
- struct gfs_inode *ip = get_v2ip(inode);
- struct gfs_alloc *al = NULL;
- struct gfs_holder ghs[2];
- int alloc_required;
- int error;
-
- atomic_inc(&sdp->sd_ops_inode);
-
- if (ip->i_di.di_type == GFS_FILE_DIR)
- return -EPERM;
-
- gfs_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[0]);
- gfs_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[1]);
-
- error = gfs_glock_nq_m(2, ghs);
- if (error)
- goto fail;
-
- error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
- if (error)
- goto fail_gunlock;
-
- error = gfs_dir_search(dip, &dentry->d_name, NULL, NULL);
- switch (error) {
- case -ENOENT:
- break;
- case 0:
- error = -EEXIST;
- default:
- goto fail_gunlock;
- }
-
- if (!dip->i_di.di_nlink) {
- error = -EINVAL;
- goto fail_gunlock;
- }
- if (dip->i_di.di_entries == (uint32_t)-1) {
- error = -EFBIG;
- goto fail_gunlock;
- }
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
- error = -EPERM;
- goto fail_gunlock;
- }
- if (!ip->i_di.di_nlink) {
- error = -EINVAL;
- goto fail_gunlock;
- }
- if (ip->i_di.di_nlink == (uint32_t)-1) {
- error = -EMLINK;
- goto fail_gunlock;
- }
-
- error = gfs_diradd_alloc_required(dip, &dentry->d_name, &alloc_required);
- if (error)
- goto fail_gunlock;
-
- if (alloc_required) {
- al = gfs_alloc_get(dip);
-
- error = gfs_quota_lock_m(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error)
- goto fail_alloc;
-
- error = gfs_quota_check(dip, dip->i_di.di_uid, dip->i_di.di_gid);
- if (error)
- goto fail_gunlock_q;
-
- al->al_requested_meta = sdp->sd_max_dirres;
-
- error = gfs_inplace_reserve(dip);
- if (error)
- goto fail_gunlock_q;
-
- /* Trans may require:
- two dinode blocks, directory modifications to add an entry,
- RG bitmap blocks to allocate from, and quota change */
-
- error = gfs_trans_begin(sdp,
- 2 + sdp->sd_max_dirres +
- al->al_rgd->rd_ri.ri_length,
- 1);
- if (error)
- goto fail_ipres;
- } else {
- /* Trans may require:
- Two dinode blocks and a leaf block. */
-
- error = gfs_trans_begin(sdp, 3, 0);
- if (error)
- goto fail_ipres;
- }
-
- error = gfs_dir_add(dip, &dentry->d_name, &ip->i_num, ip->i_di.di_type);
- if (error)
- goto fail_end_trans;
-
- error = gfs_change_nlink(ip, +1);
- if (error)
- goto fail_end_trans;
-
- gfs_trans_end(sdp);
-
- if (alloc_required) {
- gfs_assert_warn(sdp, al->al_alloced_meta);
- gfs_inplace_release(dip);
- gfs_quota_unlock_m(dip);
- gfs_alloc_put(dip);
- }
-
- gfs_glock_dq_m(2, ghs);
-
- gfs_holder_uninit(&ghs[0]);
- gfs_holder_uninit(&ghs[1]);
-
- atomic_inc(&inode->i_count);
-
- d_instantiate(dentry, inode);
- mark_inode_dirty(inode);
-
- return 0;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail_ipres:
- if (alloc_required)
- gfs_inplace_release(dip);
-
- fail_gunlock_q:
- if (alloc_required)
- gfs_quota_unlock_m(dip);
-
- fail_alloc:
- if (alloc_required)
- gfs_alloc_put(dip);
-
- fail_gunlock:
- gfs_glock_dq_m(2, ghs);
-
- fail:
- gfs_holder_uninit(&ghs[0]);
- gfs_holder_uninit(&ghs[1]);
-
- return error;
-}
-
-/**
- * gfs_unlink - Unlink a file
- * @dir: The inode of the directory containing the file to unlink
- * @dentry: The file itself
- *
- * Unlink a file. Call gfs_unlinki()
- *
- * Returns: errno
- */
-
-static int
-gfs_unlink(struct inode *dir, struct dentry *dentry)
-{
- struct gfs_inode *dip = get_v2ip(dir);
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_inode *ip = get_v2ip(dentry->d_inode);
- struct gfs_holder ghs[2];
- int error;
-
- atomic_inc(&sdp->sd_ops_inode);
-
- gfs_unlinked_limit(sdp);
-
- gfs_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[0]);
- gfs_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[1]);
-
- error = gfs_glock_nq_m(2, ghs);
- if (error)
- goto fail;
-
- error = gfs_unlink_ok(dip, &dentry->d_name, ip);
- if (error)
- goto fail_gunlock;
-
- /* Trans may require:
- Two dinode blocks and one modified directory leaf block
- and one unlinked tag. */
-
- error = gfs_trans_begin(sdp, 3, 1);
- if (error)
- goto fail_gunlock;
-
- error = gfs_unlinki(dip, &dentry->d_name, ip);
- if (error)
- goto fail_end_trans;
-
- gfs_trans_end(sdp);
-
- gfs_glock_dq_m(2, ghs);
-
- gfs_holder_uninit(&ghs[0]);
- gfs_holder_uninit(&ghs[1]);
-
- return 0;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail_gunlock:
- gfs_glock_dq_m(2, ghs);
-
- fail:
- gfs_holder_uninit(&ghs[0]);
- gfs_holder_uninit(&ghs[1]);
-
- return error;
-}
-
-/**
- * gfs_symlink - Create a symlink
- * @dir: The directory to create the symlink in
- * @dentry: The dentry to put the symlink in
- * @symname: The thing which the link points to
- *
- * Returns: errno
- */
-
-static int
-gfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
-{
- struct gfs_inode *dip = get_v2ip(dir), *ip;
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_holder d_gh, i_gh;
- struct inode *inode;
- struct buffer_head *dibh;
- int size;
- int error;
-
- atomic_inc(&sdp->sd_ops_inode);
-
- gfs_unlinked_limit(sdp);
-
- /* Must be stuffed with a null terminator for gfs_follow_link() */
- size = strlen(symname);
- if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode) - 1)
- return -ENAMETOOLONG;
-
- gfs_holder_init(dip->i_gl, 0, 0, &d_gh);
-
- error = gfs_createi(&d_gh, &dentry->d_name,
- GFS_FILE_LNK, S_IFLNK | S_IRWXUGO,
- &i_gh);
- if (error) {
- gfs_holder_uninit(&d_gh);
- return error;
- }
-
- ip = get_gl2ip(i_gh.gh_gl);
-
- ip->i_di.di_size = size;
-
- error = gfs_get_inode_buffer(ip, &dibh);
-
- if (!gfs_assert_withdraw(sdp, !error)) {
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- memcpy(dibh->b_data + sizeof(struct gfs_dinode), symname, size);
- brelse(dibh);
- }
-
- gfs_trans_end(sdp);
- if (dip->i_alloc->al_rgd)
- gfs_inplace_release(dip);
- gfs_quota_unlock_m(dip);
- gfs_unlinked_unlock(sdp, dip->i_alloc->al_ul);
- gfs_alloc_put(dip);
-
- inode = gfs_iget(ip, CREATE);
- gfs_inode_put(ip);
-
- error = gfs_security_init(dip, ip);
-
- gfs_glock_dq_uninit(&d_gh);
- gfs_glock_dq_uninit(&i_gh);
-
- if (error)
- return error;
-
- if (!inode)
- return -ENOMEM;
-
- d_instantiate(dentry, inode);
- mark_inode_dirty(inode);
-
- return 0;
-}
-
-/**
- * gfs_mkdir - Make a directory
- * @dir: The parent directory of the new one
- * @dentry: The dentry of the new directory
- * @mode: The mode of the new directory
- *
- * Returns: errno
- */
-
-static int
-gfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
- struct gfs_inode *dip = get_v2ip(dir), *ip;
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_holder d_gh, i_gh;
- struct inode *inode;
- struct buffer_head *dibh;
- int error;
-
- atomic_inc(&sdp->sd_ops_inode);
-
- gfs_unlinked_limit(sdp);
-
- gfs_holder_init(dip->i_gl, 0, 0, &d_gh);
-
- error = gfs_createi(&d_gh, &dentry->d_name,
- GFS_FILE_DIR, S_IFDIR | mode,
- &i_gh);
- if (error) {
- gfs_holder_uninit(&d_gh);
- return error;
- }
-
- ip = get_gl2ip(i_gh.gh_gl);
-
- ip->i_di.di_nlink = 2;
- ip->i_di.di_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode);
- ip->i_di.di_flags |= GFS_DIF_JDATA;
- ip->i_di.di_payload_format = GFS_FORMAT_DE;
- ip->i_di.di_entries = 2;
-
- error = gfs_get_inode_buffer(ip, &dibh);
-
- if (!gfs_assert_withdraw(sdp, !error)) {
- struct gfs_dinode *di = (struct gfs_dinode *)dibh->b_data;
- struct gfs_dirent *dent;
-
- gfs_dirent_alloc(ip, dibh, 1, &dent);
-
- dent->de_inum = di->di_num; /* already GFS endian */
- dent->de_hash = gfs_dir_hash(".", 1);
- dent->de_hash = cpu_to_gfs32(dent->de_hash);
- dent->de_type = cpu_to_gfs16(GFS_FILE_DIR);
- memcpy((char *) (dent + 1), ".", 1);
- di->di_entries = cpu_to_gfs32(1);
-
- gfs_dirent_alloc(ip, dibh, 2, &dent);
-
- gfs_inum_out(&dip->i_num, (char *) &dent->de_inum);
- dent->de_hash = gfs_dir_hash("..", 2);
- dent->de_hash = cpu_to_gfs32(dent->de_hash);
- dent->de_type = cpu_to_gfs16(GFS_FILE_DIR);
- memcpy((char *) (dent + 1), "..", 2);
-
- gfs_dinode_out(&ip->i_di, (char *)di);
-
- brelse(dibh);
- }
-
- error = gfs_change_nlink(dip, +1);
- gfs_assert_withdraw(sdp, !error); /* dip already pinned */
-
- gfs_trans_end(sdp);
- if (dip->i_alloc->al_rgd)
- gfs_inplace_release(dip);
- gfs_quota_unlock_m(dip);
- gfs_unlinked_unlock(sdp, dip->i_alloc->al_ul);
- gfs_alloc_put(dip);
-
- inode = gfs_iget(ip, CREATE);
- gfs_inode_put(ip);
-
- if (!inode)
- return -ENOMEM;
-
- error = gfs_security_init(dip, ip);
-
- gfs_glock_dq_uninit(&d_gh);
- gfs_glock_dq_uninit(&i_gh);
-
- if (error)
- return error;
-
- d_instantiate(dentry, inode);
- mark_inode_dirty(inode);
-
- return 0;
-}
-
-/**
- * gfs_rmdir - Remove a directory
- * @dir: The parent directory of the directory to be removed
- * @dentry: The dentry of the directory to remove
- *
- * Remove a directory. Call gfs_rmdiri()
- *
- * Returns: errno
- */
-
-static int
-gfs_rmdir(struct inode *dir, struct dentry *dentry)
-{
- struct gfs_inode *dip = get_v2ip(dir);
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_inode *ip = get_v2ip(dentry->d_inode);
- struct gfs_holder ghs[2];
- int error;
-
- atomic_inc(&sdp->sd_ops_inode);
-
- gfs_unlinked_limit(sdp);
-
- gfs_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[0]);
- gfs_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[1]);
-
- error = gfs_glock_nq_m(2, ghs);
- if (error)
- goto fail;
-
- error = gfs_unlink_ok(dip, &dentry->d_name, ip);
- if (error)
- goto fail_gunlock;
-
- if (ip->i_di.di_entries < 2) {
- if (gfs_consist_inode(ip))
- gfs_dinode_print(&ip->i_di);
- error = -EIO;
- goto fail_gunlock;
- }
- if (ip->i_di.di_entries > 2) {
- error = -ENOTEMPTY;
- goto fail_gunlock;
- }
-
- /* Trans may require:
- Two dinode blocks, one directory leaf block containing the
- entry to be rmdired, two leaf blocks containing . and .. of
- the directory being rmdired, and one unlinked tag */
-
- error = gfs_trans_begin(sdp, 5, 1);
- if (error)
- goto fail_gunlock;
-
- error = gfs_rmdiri(dip, &dentry->d_name, ip);
- if (error)
- goto fail_end_trans;
-
- gfs_trans_end(sdp);
-
- gfs_glock_dq_m(2, ghs);
-
- gfs_holder_uninit(&ghs[0]);
- gfs_holder_uninit(&ghs[1]);
-
- return 0;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail_gunlock:
- gfs_glock_dq_m(2, ghs);
-
- fail:
- gfs_holder_uninit(&ghs[0]);
- gfs_holder_uninit(&ghs[1]);
-
- return error;
-}
-
-/**
- * gfs_mknod - Make a special file
- * @dir: The directory in which the special file will reside
- * @dentry: The dentry of the special file
- * @mode: The mode of the special file
- * @rdev: The device specification of the special file
- *
- */
-
-static int
-gfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
-{
- struct gfs_inode *dip = get_v2ip(dir), *ip;
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_holder d_gh, i_gh;
- struct inode *inode;
- struct buffer_head *dibh;
- uint16_t type = 0;
- uint32_t major = 0, minor = 0;
- int error;
-
- atomic_inc(&sdp->sd_ops_inode);
-
- gfs_unlinked_limit(sdp);
-
- switch (mode & S_IFMT) {
- case S_IFBLK:
- type = GFS_FILE_BLK;
- major = MAJOR(dev);
- minor = MINOR(dev);
- break;
- case S_IFCHR:
- type = GFS_FILE_CHR;
- major = MAJOR(dev);
- minor = MINOR(dev);
- break;
- case S_IFIFO:
- type = GFS_FILE_FIFO;
- break;
- case S_IFSOCK:
- type = GFS_FILE_SOCK;
- break;
- default:
- printk("GFS: fsid=%s: mknod() with invalid type (%d)\n",
- sdp->sd_fsname, mode);
- return -EINVAL;
- };
-
- gfs_holder_init(dip->i_gl, 0, 0, &d_gh);
-
- error = gfs_createi(&d_gh, &dentry->d_name,
- type, mode,
- &i_gh);
- if (error) {
- gfs_holder_uninit(&d_gh);
- return error;
- }
-
- ip = get_gl2ip(i_gh.gh_gl);
-
- ip->i_di.di_major = major;
- ip->i_di.di_minor = minor;
-
- error = gfs_get_inode_buffer(ip, &dibh);
-
- if (!gfs_assert_withdraw(sdp, !error)) {
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
- }
-
- gfs_trans_end(sdp);
- if (dip->i_alloc->al_rgd)
- gfs_inplace_release(dip);
- gfs_quota_unlock_m(dip);
- gfs_unlinked_unlock(sdp, dip->i_alloc->al_ul);
- gfs_alloc_put(dip);
-
- inode = gfs_iget(ip, CREATE);
- gfs_inode_put(ip);
-
- error = gfs_security_init(dip, ip);
-
- gfs_glock_dq_uninit(&d_gh);
- gfs_glock_dq_uninit(&i_gh);
-
- if (error)
- return error;
-
- if (!inode)
- return -ENOMEM;
-
- d_instantiate(dentry, inode);
- mark_inode_dirty(inode);
-
- return 0;
-}
-
-/**
- * gfs_rename - Rename a file
- * @odir: Parent directory of old file name
- * @odentry: The old dentry of the file
- * @ndir: Parent directory of new file name
- * @ndentry: The new dentry of the file
- *
- * Returns: errno
- */
-
-static int
-gfs_rename(struct inode *odir, struct dentry *odentry,
- struct inode *ndir, struct dentry *ndentry)
-{
- struct gfs_inode *odip = get_v2ip(odir);
- struct gfs_inode *ndip = get_v2ip(ndir);
- struct gfs_inode *ip = get_v2ip(odentry->d_inode);
- struct gfs_inode *nip = NULL;
- struct gfs_sbd *sdp = odip->i_sbd;
- struct qstr name;
- struct gfs_alloc *al;
- struct gfs_holder ghs[4], r_gh;
- unsigned int num_gh;
- int dir_rename = FALSE;
- int alloc_required;
- unsigned int x;
- int error;
-
- atomic_inc(&sdp->sd_ops_inode);
-
- gfs_unlinked_limit(sdp);
-
- if (ndentry->d_inode) {
- nip = get_v2ip(ndentry->d_inode);
- if (ip == nip)
- return 0;
- }
-
- /* Make sure we aren't trying to move a dirctory into it's subdir */
-
- if (ip->i_di.di_type == GFS_FILE_DIR && odip != ndip) {
- dir_rename = TRUE;
-
- error = gfs_glock_nq_init(sdp->sd_rename_gl,
- LM_ST_EXCLUSIVE, 0,
- &r_gh);
- if (error)
- return error;
-
- error = gfs_ok_to_move(ip, ndip);
- if (error)
- goto fail;
- }
-
- gfs_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[0]);
- gfs_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[1]);
- num_gh = 2;
-
- if (nip)
- gfs_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[num_gh++]);
-
- if (dir_rename)
- gfs_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[num_gh++]);
-
- error = gfs_glock_nq_m(num_gh, ghs);
- if (error)
- goto fail_uninit;
-
- /* Check out the old directory */
-
- error = gfs_unlink_ok(odip, &odentry->d_name, ip);
- if (error)
- goto fail_gunlock;
-
- /* Check out the new directory */
-
- if (nip) {
- error = gfs_unlink_ok(ndip, &ndentry->d_name, nip);
- if (error)
- goto fail_gunlock;
-
- if (nip->i_di.di_type == GFS_FILE_DIR) {
- if (nip->i_di.di_entries < 2) {
- if (gfs_consist_inode(nip))
- gfs_dinode_print(&nip->i_di);
- error = -EIO;
- goto fail_gunlock;
- }
- if (nip->i_di.di_entries > 2) {
- error = -ENOTEMPTY;
- goto fail_gunlock;
- }
- }
- } else {
- error = inode_permission(ndir, MAY_WRITE | MAY_EXEC);
- if (error)
- goto fail_gunlock;
-
- error = gfs_dir_search(ndip, &ndentry->d_name, NULL, NULL);
- switch (error) {
- case -ENOENT:
- error = 0;
- break;
- case 0:
- error = -EEXIST;
- default:
- goto fail_gunlock;
- };
-
- if (odip != ndip) {
- if (!ndip->i_di.di_nlink) {
- error = -EINVAL;
- goto fail_gunlock;
- }
- if (ndip->i_di.di_entries == (uint32_t)-1) {
- error = -EFBIG;
- goto fail_gunlock;
- }
- if (ip->i_di.di_type == GFS_FILE_DIR &&
- ndip->i_di.di_nlink == (uint32_t)-1) {
- error = -EMLINK;
- goto fail_gunlock;
- }
- }
- }
-
- error = gfs_diradd_alloc_required(ndip, &ndentry->d_name, &alloc_required);
- if (error)
- goto fail_gunlock;
-
- if (alloc_required) {
- al = gfs_alloc_get(ndip);
-
- error = gfs_quota_lock_m(ndip,
- NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error)
- goto fail_alloc;
-
- error = gfs_quota_check(ndip, ndip->i_di.di_uid, ndip->i_di.di_gid);
- if (error)
- goto fail_gunlock_q;
-
- al->al_requested_meta = sdp->sd_max_dirres;
-
- error = gfs_inplace_reserve(ndip);
- if (error)
- goto fail_gunlock_q;
-
- /* Trans may require:
- Dinodes for the srcdir, srcino, dstdir, dstino. Blocks for
- adding the entry to dstdir. RG bitmaps for that allocation.
- One leaf block in the srcdir for removal of the entry.
- One leaf block for changing .. in srcino (if it's a directory).
- Two leaf blocks for removing . and .. from dstino (if it exists
- and it's a directory), one unlinked tag, and one quota block. */
-
- error = gfs_trans_begin(sdp,
- 8 + sdp->sd_max_dirres +
- al->al_rgd->rd_ri.ri_length,
- 2);
- if (error)
- goto fail_ipres;
- } else {
- /* Trans may require:
- Dinodes for the srcdir, srcino, dstdir, dstino. One block for
- adding the entry to dstdir.
- One leaf block in the srcdir for removal of the entry.
- One leaf block for changing .. in srcino (if it's a directory).
- Two leaf blocks for removing . and .. from dstino (if it exists
- and it's a directory), and one unlinked tag. */
-
- error = gfs_trans_begin(sdp, 9, 1);
- if (error)
- goto fail_ipres;
- }
-
- /* Remove the target file, if it exists */
-
- if (nip) {
- if (nip->i_di.di_type == GFS_FILE_DIR)
- error = gfs_rmdiri(ndip, &ndentry->d_name, nip);
- else
- error = gfs_unlinki(ndip, &ndentry->d_name, nip);
-
- if (error)
- goto fail_end_trans;
- }
-
- if (dir_rename) {
- error = gfs_change_nlink(ndip, +1);
- if (error)
- goto fail_end_trans;
- error = gfs_change_nlink(odip, -1);
- if (error)
- goto fail_end_trans;
-
- name.len = 2;
- name.name = "..";
-
- error = gfs_dir_mvino(ip, &name, &ndip->i_num, GFS_FILE_DIR);
- if (error)
- goto fail_end_trans;
- }
-
- error = gfs_dir_del(odip, &odentry->d_name);
- if (error)
- goto fail_end_trans;
-
- error = gfs_dir_add(ndip, &ndentry->d_name, &ip->i_num, ip->i_di.di_type);
- if (error)
- goto fail_end_trans;
-
- if (dir_rename)
- gfs_trans_add_gl(sdp->sd_rename_gl);
-
- gfs_trans_end(sdp);
-
- if (alloc_required) {
- /* Don't check al->al_alloced_meta and friends. */
- gfs_inplace_release(ndip);
- gfs_quota_unlock_m(ndip);
- gfs_alloc_put(ndip);
- }
-
- gfs_glock_dq_m(num_gh, ghs);
-
- for (x = 0; x < num_gh; x++)
- gfs_holder_uninit(&ghs[x]);
-
- if (dir_rename)
- gfs_glock_dq_uninit(&r_gh);
-
- return 0;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail_ipres:
- if (alloc_required)
- gfs_inplace_release(ndip);
-
- fail_gunlock_q:
- if (alloc_required)
- gfs_quota_unlock_m(ndip);
-
- fail_alloc:
- if (alloc_required)
- gfs_alloc_put(ndip);
-
- fail_gunlock:
- gfs_glock_dq_m(num_gh, ghs);
-
- fail_uninit:
- for (x = 0; x < num_gh; x++)
- gfs_holder_uninit(&ghs[x]);
-
- fail:
- if (dir_rename)
- gfs_glock_dq_uninit(&r_gh);
-
- return error;
-}
-
-/**
- * gfs_readlink - Read the value of a symlink
- * @dentry: the symlink
- * @buf: the buffer to read the symlink data into
- * @size: the size of the buffer
- *
- * Returns: errno
- */
-
-static int
-gfs_readlink(struct dentry *dentry, char *user_buf, int user_size)
-{
- struct gfs_inode *ip = get_v2ip(dentry->d_inode);
- char array[GFS_FAST_NAME_SIZE], *buf = array;
- unsigned int len = GFS_FAST_NAME_SIZE;
- int error;
-
- atomic_inc(&ip->i_sbd->sd_ops_inode);
-
- error = gfs_readlinki(ip, &buf, &len);
- if (error)
- return error;
-
- if (user_size > len - 1)
- user_size = len - 1;
-
- if (copy_to_user(user_buf, buf, user_size))
- error = -EFAULT;
- else
- error = user_size;
-
- if (buf != array)
- kfree(buf);
-
- return error;
-}
-
-/**
- * gfs_follow_link - Follow a symbolic link
- * @dentry: The dentry of the link
- * @nd: Data that we pass to vfs_follow_link()
- *
- * This can handle symlinks of any size. It is optimised for symlinks
- * under GFS_FAST_NAME_SIZE.
- *
- * Returns: 0 on success or error code
- */
-
-static void *
-gfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
- struct gfs_inode *ip = get_v2ip(dentry->d_inode);
- char array[GFS_FAST_NAME_SIZE], *buf = array;
- unsigned int len = GFS_FAST_NAME_SIZE;
- int error;
-
- atomic_inc(&ip->i_sbd->sd_ops_inode);
-
- error = gfs_readlinki(ip, &buf, &len);
- if (!error) {
- error = vfs_follow_link(nd, buf);
- if (buf != array)
- kfree(buf);
- }
-
- return ERR_PTR(error);
-}
-
-/**
- * gfs_permission_i -
- * @inode:
- * @mask:
- *
- * Shamelessly ripped from ext3
- *
- * Returns: errno
- */
-
-static int
-gfs_permission_i(struct inode *inode, int mask)
-{
- return generic_permission(inode, mask, gfs_check_acl);
-}
-
-/**
- * gfs_permission -
- * @inode:
- * @mask:
- *
- * Returns: errno
- */
-
-static int
-gfs_permission(struct inode *inode, int mask)
-{
- struct gfs_inode *ip = get_v2ip(inode);
- struct gfs_holder i_gh;
- int error;
-
- atomic_inc(&ip->i_sbd->sd_ops_inode);
-
- error = gfs_glock_nq_init(ip->i_gl,
- LM_ST_SHARED, LM_FLAG_ANY,
- &i_gh);
- if (error)
- return error;
-
- error = gfs_permission_i(inode, mask);
-
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gfs_setattr - Change attributes on an inode
- * @dentry: The dentry which is changing
- * @attr: The structure describing the change
- *
- * The VFS layer wants to change one or more of an inodes attributes. Write
- * that change out to disk.
- *
- * Returns: errno
- */
-
-static int
-gfs_setattr(struct dentry *dentry, struct iattr *attr)
-{
- struct inode *inode = dentry->d_inode;
- struct gfs_inode *ip = get_v2ip(inode);
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_holder i_gh;
- int error;
-
- atomic_inc(&sdp->sd_ops_inode);
-
- /* Bugzilla 203170: we'll have the same deadlock as described
- * in bugzilla 173912 if
- * 1. without RHEL4's DIO_CLUSTER_LOCKING, and
- * 2. we come down to this line of code from do_truncate()
- * where i_sem(i_mutex) and i_alloc_sem have been taken, and
- * 3. grab the exclusive glock here.
- * To avoid this to happen, i_alloc_sem must be dropped and trust
- * be put into glock that it can carry the same protection.
- *
- * One issue with dropping i_alloc_sem is that the gfs_setattr()
- * can be invoked from other code path without this sempaphore.
- * We'll need a new rwsem function that can "up" the semaphore
- * only when it is needed. Before that happens (will research the
- * possibility), i_alloc_sem (now) is a meaningless lock within
- * GFS. If it is ever been used by other non-directIO code, this
- * hack will fall apart.
- *
- * wcheng at redhat.com 10/14/06
- */
- if (attr->ia_valid & ATTR_SIZE) {
- up_write(&dentry->d_inode->i_alloc_sem);
- }
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
-
- if (attr->ia_valid & ATTR_SIZE) {
- down_write(&dentry->d_inode->i_alloc_sem);
- }
-
- if (error)
- return error;
-
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
- error = -EPERM;
- goto fail;
- }
-
- error = inode_change_ok(inode, attr);
- if (error)
- goto fail;
-
- if (attr->ia_valid & ATTR_SIZE) {
- error = inode_permission(inode, MAY_WRITE);
- if (error)
- goto fail;
-
- if (attr->ia_size != ip->i_di.di_size) {
- error = vmtruncate(inode, attr->ia_size);
- if (error)
- goto fail;
- }
-
- error = gfs_truncatei(ip, attr->ia_size, gfs_truncator_page);
- if (error) {
- if (inode->i_size != ip->i_di.di_size)
- i_size_write(inode, ip->i_di.di_size);
- goto fail;
- }
-
- if ((sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) &&
- !gfs_is_jdata(ip))
- i_gh.gh_flags |= GL_SYNC;
- }
-
- else if (attr->ia_valid & (ATTR_UID | ATTR_GID)) {
- struct gfs_alloc *al;
- struct buffer_head *dibh;
- uint32_t ouid, ogid, nuid, ngid;
-
- ouid = ip->i_di.di_uid;
- ogid = ip->i_di.di_gid;
- nuid = attr->ia_uid;
- ngid = attr->ia_gid;
-
- if (!(attr->ia_valid & ATTR_UID) || ouid == nuid)
- ouid = nuid = NO_QUOTA_CHANGE;
- if (!(attr->ia_valid & ATTR_GID) || ogid == ngid)
- ogid = ngid = NO_QUOTA_CHANGE;
-
- al = gfs_alloc_get(ip);
-
- error = gfs_quota_lock_m(ip, nuid, ngid);
- if (error)
- goto fail_alloc;
-
- if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
- error = gfs_quota_check(ip, nuid, ngid);
- if (error)
- goto fail_gunlock_q;
- }
-
- /* Trans may require:
- one dinode block and one quota change block */
-
- error = gfs_trans_begin(sdp, 1, 1);
- if (error)
- goto fail_gunlock_q;
-
- error = gfs_get_inode_buffer(ip, &dibh);
- if (error)
- goto fail_end_trans;
-
- if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
- gfs_trans_add_quota(sdp, -ip->i_di.di_blocks,
- ouid, ogid);
- gfs_trans_add_quota(sdp, ip->i_di.di_blocks,
- nuid, ngid);
- }
-
- error = inode_setattr(inode, attr);
- gfs_assert_warn(sdp, !error);
- gfs_inode_attr_out(ip);
-
- gfs_trans_add_bh(ip->i_gl, dibh);
- gfs_dinode_out(&ip->i_di, dibh->b_data);
- brelse(dibh);
-
- gfs_trans_end(sdp);
-
- gfs_quota_unlock_m(ip);
- gfs_alloc_put(ip);
- }
-
- else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) {
- error = gfs_acl_chmod(ip, attr);
- if (error)
- goto fail;
- }
-
- else {
- error = gfs_setattr_simple(ip, attr);
- if (error)
- goto fail;
- }
-
- gfs_glock_dq_uninit(&i_gh);
-
- mark_inode_dirty(inode);
-
- return error;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail_gunlock_q:
- gfs_quota_unlock_m(ip);
-
- fail_alloc:
- gfs_alloc_put(ip);
-
- fail:
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gfs_getattr - Read out an inode's attributes
- * @mnt: ?
- * @dentry: The dentry to stat
- * @stat: The inode's stats
- *
- * Returns: errno
- */
-
-static int
-gfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
-{
- struct inode *inode = dentry->d_inode, *p_inode = NULL;
- struct gfs_inode *ip = get_v2ip(inode), *pi = NULL;
- struct gfs_holder gh;
- int error;
-
- atomic_inc(&ip->i_sbd->sd_ops_inode);
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
- if (!error) {
- generic_fillattr(inode, stat);
- if (S_ISREG(inode->i_mode) && dentry->d_parent
- && dentry->d_parent->d_inode) {
- p_inode = igrab(dentry->d_parent->d_inode);
- if (p_inode) {
- pi = get_v2ip(p_inode);
- pi->i_dir_stats++;
- iput(p_inode);
- }
- }
- gfs_glock_dq_uninit(&gh);
- }
-
- return error;
-}
-
-/**
- * gfs_setxattr - Set (or create or replace) an inode's extended attribute
- * @dentry:
- * @name:
- * @data:
- * @size:
- * @flags:
- *
- * Returns: errno
- */
-
-int
-gfs_setxattr(struct dentry *dentry, const char *name,
- const void *data, size_t size,
- int flags)
-{
- struct gfs_ea_request er;
-
- atomic_inc(&get_v2sdp(dentry->d_inode->i_sb)->sd_ops_inode);
-
- memset(&er, 0, sizeof(struct gfs_ea_request));
- er.er_type = gfs_ea_name2type(name, &er.er_name);
- if (er.er_type == GFS_EATYPE_UNUSED)
- return -EOPNOTSUPP;
- er.er_data = (char *)data;
- er.er_name_len = strlen(er.er_name);
- er.er_data_len = size;
- er.er_flags = flags;
-
- return gfs_ea_set(get_v2ip(dentry->d_inode), &er);
-}
-
-/**
- * gfs_getxattr -
- * @dentry:
- * @name:
- * @data:
- * @size:
- *
- * Returns: The number of bytes put into data, or -errno
- */
-
-ssize_t
-gfs_getxattr(struct dentry *dentry, const char *name,
- void *data, size_t size)
-{
- struct gfs_ea_request er;
-
- atomic_inc(&get_v2sdp(dentry->d_inode->i_sb)->sd_ops_inode);
-
- memset(&er, 0, sizeof(struct gfs_ea_request));
- er.er_type = gfs_ea_name2type(name, &er.er_name);
- if (er.er_type == GFS_EATYPE_UNUSED)
- return -EOPNOTSUPP;
- er.er_data = data;
- er.er_name_len = strlen(er.er_name);
- er.er_data_len = size;
-
- return gfs_ea_get(get_v2ip(dentry->d_inode), &er);
-}
-
-/**
- * gfs_listxattr -
- * @dentry:
- * @buffer:
- * @size:
- *
- * Returns: The number of bytes put into data, or -errno
- */
-
-ssize_t
-gfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
-{
- struct gfs_ea_request er;
-
- atomic_inc(&get_v2sdp(dentry->d_inode->i_sb)->sd_ops_inode);
-
- memset(&er, 0, sizeof(struct gfs_ea_request));
- er.er_data = (size) ? buffer : NULL;
- er.er_data_len = size;
-
- return gfs_ea_list(get_v2ip(dentry->d_inode), &er);
-}
-
-/**
- * gfs_removexattr -
- * @dentry:
- * @name:
- *
- * Returns: errno
- */
-
-int
-gfs_removexattr(struct dentry *dentry, const char *name)
-{
- struct gfs_ea_request er;
-
- atomic_inc(&get_v2sdp(dentry->d_inode->i_sb)->sd_ops_inode);
-
- memset(&er, 0, sizeof(struct gfs_ea_request));
- er.er_type = gfs_ea_name2type(name, &er.er_name);
- if (er.er_type == GFS_EATYPE_UNUSED)
- return -EOPNOTSUPP;
- er.er_name_len = strlen(er.er_name);
-
- return gfs_ea_remove(get_v2ip(dentry->d_inode), &er);
-}
-
-struct inode_operations gfs_file_iops = {
- .permission = gfs_permission,
- .setattr = gfs_setattr,
- .getattr = gfs_getattr,
- .setxattr = gfs_setxattr,
- .getxattr = gfs_getxattr,
- .listxattr = gfs_listxattr,
- .removexattr = gfs_removexattr,
-};
-
-struct inode_operations gfs_dev_iops = {
- .permission = gfs_permission,
- .setattr = gfs_setattr,
- .getattr = gfs_getattr,
- .setxattr = gfs_setxattr,
- .getxattr = gfs_getxattr,
- .listxattr = gfs_listxattr,
- .removexattr = gfs_removexattr,
-};
-
-struct inode_operations gfs_dir_iops = {
- .create = gfs_create,
- .lookup = gfs_lookup,
- .link = gfs_link,
- .unlink = gfs_unlink,
- .symlink = gfs_symlink,
- .mkdir = gfs_mkdir,
- .rmdir = gfs_rmdir,
- .mknod = gfs_mknod,
- .rename = gfs_rename,
- .permission = gfs_permission,
- .setattr = gfs_setattr,
- .getattr = gfs_getattr,
- .setxattr = gfs_setxattr,
- .getxattr = gfs_getxattr,
- .listxattr = gfs_listxattr,
- .removexattr = gfs_removexattr,
-};
-
-struct inode_operations gfs_symlink_iops = {
- .readlink = gfs_readlink,
- .follow_link = gfs_follow_link,
- .permission = gfs_permission,
- .setattr = gfs_setattr,
- .getattr = gfs_getattr,
- .setxattr = gfs_setxattr,
- .getxattr = gfs_getxattr,
- .listxattr = gfs_listxattr,
- .removexattr = gfs_removexattr,
-};
-
diff --git a/gfs-kernel/src/gfs/ops_inode.h b/gfs-kernel/src/gfs/ops_inode.h
deleted file mode 100644
index a753396..0000000
--- a/gfs-kernel/src/gfs/ops_inode.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __OPS_INODE_DOT_H__
-#define __OPS_INODE_DOT_H__
-
-extern struct inode_operations gfs_file_iops;
-extern struct inode_operations gfs_dir_iops;
-extern struct inode_operations gfs_symlink_iops;
-extern struct inode_operations gfs_dev_iops;
-
-#endif /* __OPS_INODE_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/ops_super.c b/gfs-kernel/src/gfs/ops_super.c
deleted file mode 100644
index 621973e..0000000
--- a/gfs-kernel/src/gfs/ops_super.c
+++ /dev/null
@@ -1,463 +0,0 @@
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/buffer_head.h>
-#include <linux/vmalloc.h>
-#include <linux/statfs.h>
-#include <linux/seq_file.h>
-#include <linux/mount.h>
-
-#include "gfs.h"
-#include "dio.h"
-#include "glock.h"
-#include "inode.h"
-#include "lm.h"
-#include "log.h"
-#include "ops_fstype.h"
-#include "ops_super.h"
-#include "page.h"
-#include "proc.h"
-#include "quota.h"
-#include "recovery.h"
-#include "rgrp.h"
-#include "super.h"
-#include "sys.h"
-#include "mount.h"
-
-/**
- * gfs_write_inode - Make sure the inode is stable on the disk
- * @inode: The inode
- * @sync: synchronous write flag
- *
- * Returns: errno
- */
-
-static int
-gfs_write_inode(struct inode *inode, int sync)
-{
- struct gfs_inode *ip = get_v2ip(inode);
-
- atomic_inc(&ip->i_sbd->sd_ops_super);
-
- if (ip && sync)
- gfs_log_flush_glock(ip->i_gl);
-
- return 0;
-}
-
-/**
- * gfs_drop_inode - drop an inode
- * @inode: The inode
- *
- * If i_nlink is zero, any dirty data for the inode is thrown away.
- * If a process on another machine has the file open, it may need that
- * data. So, sync it out.
- */
-
-static void
-gfs_drop_inode(struct inode *inode)
-{
- struct gfs_sbd *sdp = get_v2sdp(inode->i_sb);
- struct gfs_inode *ip = get_v2ip(inode);
-
- atomic_inc(&sdp->sd_ops_super);
-
- if (ip &&
- !inode->i_nlink &&
- S_ISREG(inode->i_mode) &&
- !sdp->sd_args.ar_localcaching)
- gfs_sync_page_i(inode, DIO_START | DIO_WAIT);
- generic_drop_inode(inode);
-}
-
-/**
- * gfs_put_super - Unmount the filesystem
- * @sb: The VFS superblock
- *
- */
-
-static void
-gfs_put_super(struct super_block *sb)
-{
- struct gfs_sbd *sdp = get_v2sdp(sb);
- int error;
-
- if (!sdp)
- return;
-
- atomic_inc(&sdp->sd_ops_super);
-
- gfs_proc_fs_del(sdp);
-
- /* Unfreeze the filesystem, if we need to */
-
- down(&sdp->sd_freeze_lock);
- if (sdp->sd_freeze_count)
- gfs_glock_dq_uninit(&sdp->sd_freeze_gh);
- up(&sdp->sd_freeze_lock);
-
- /* Kill off the inode thread */
- kthread_stop(sdp->sd_inoded_process);
-
- /* Kill off the quota thread */
- kthread_stop(sdp->sd_quotad_process);
-
- /* Kill off the log thread */
- kthread_stop(sdp->sd_logd_process);
-
- /* Kill off the recoverd thread */
- kthread_stop(sdp->sd_recoverd_process);
-
- /* Kill off the glockd threads */
- while (sdp->sd_glockd_num--)
- kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]);
-
- /* Kill off the scand thread */
- kthread_stop(sdp->sd_scand_process);
-
- if (!test_bit(SDF_ROFS, &sdp->sd_flags)) {
- error = gfs_make_fs_ro(sdp);
- if (error)
- gfs_io_error(sdp);
- }
-
- /* At this point, we're through modifying the disk */
-
- /* Release stuff */
-
- gfs_inode_put(sdp->sd_riinode);
- gfs_inode_put(sdp->sd_jiinode);
- gfs_inode_put(sdp->sd_rooti);
- gfs_inode_put(sdp->sd_qinode);
- gfs_inode_put(sdp->sd_linode);
- gfs_glock_put(sdp->sd_trans_gl);
- gfs_glock_put(sdp->sd_rename_gl);
-
- if (!sdp->sd_args.ar_spectator)
- gfs_glock_dq_uninit(&sdp->sd_journal_gh);
-
- gfs_glock_dq_uninit(&sdp->sd_live_gh);
-
- /* Get rid of rgrp bitmap structures */
- gfs_clear_rgrpd(sdp);
- gfs_clear_journals(sdp);
-
- /* Take apart glock structures and buffer lists */
- gfs_gl_hash_clear(sdp, TRUE);
-
- /* Unmount the locking protocol */
- gfs_lm_unmount(sdp);
-
- /* At this point, we're through participating in the lockspace */
-
- gfs_sys_fs_del(sdp);
-
- gfs_clear_dirty_j(sdp);
-
- /* Get rid of any extra inodes */
- while (invalidate_inodes(sb))
- yield();
-
- vfree(sdp);
-
- set_v2sdp(sb, NULL);
-}
-
-/**
- * gfs_write_super - disk commit all incore transactions
- * @sb: the filesystem
- *
- * This function is called every time sync(2) is called.
- * After this exits, all dirty buffers and synced.
- */
-
-static void
-gfs_write_super(struct super_block *sb)
-{
- struct gfs_sbd *sdp = get_v2sdp(sb);
- atomic_inc(&sdp->sd_ops_super);
- gfs_log_flush(sdp);
-}
-
-/**
- * gfs_freeze - prevent further writes to the filesystem
- * @sb: the VFS structure for the filesystem
- *
- */
-
-static int
-gfs_freeze(struct super_block *sb)
-{
- struct gfs_sbd *sdp = get_v2sdp(sb);
- int error;
-
- if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
- return -EINVAL;
-
- atomic_inc(&sdp->sd_ops_super);
-
- for (;;) {
- error = gfs_freeze_fs(sdp);
- if (!error)
- break;
-
- switch (error) {
- case -EBUSY:
- printk("GFS: fsid=%s: waiting for recovery before freeze\n",
- sdp->sd_fsname);
- break;
-
- default:
- printk("GFS: fsid=%s: error freezing FS: %d\n",
- sdp->sd_fsname, error);
- break;
- }
-
- printk("GFS: fsid=%s: retrying...\n", sdp->sd_fsname);
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
- }
- return 0;
-}
-
-/**
- * gfs_unfreeze - reallow writes to the filesystem
- * @sb: the VFS structure for the filesystem
- *
- */
-
-static int
-gfs_unfreeze(struct super_block *sb)
-{
- struct gfs_sbd *sdp = get_v2sdp(sb);
-
- atomic_inc(&sdp->sd_ops_super);
-
- gfs_unfreeze_fs(sdp);
- return 0;
-}
-
-/**
- * gfs_statfs - Gather and return stats about the filesystem
- * @sb: The superblock
- * @statfsbuf: The buffer
- *
- * Returns: 0 on success or error code
- */
-
-static int gfs_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
- struct super_block *sb = dentry->d_inode->i_sb;
- struct gfs_sbd *sdp = get_v2sdp(sb);
- struct gfs_stat_gfs sg;
- int error;
-
- atomic_inc(&sdp->sd_ops_super);
-
- if (gfs_tune_get(sdp, gt_statfs_fast))
- return(gfs_statfs_fast(sdp, (void *)buf));
-
- error = gfs_stat_gfs(sdp, &sg, TRUE);
- if (error)
- return error;
-
- memset(buf, 0, sizeof(struct kstatfs));
-
- buf->f_type = GFS_MAGIC;
- buf->f_bsize = sdp->sd_sb.sb_bsize;
- buf->f_blocks = sg.sg_total_blocks;
- buf->f_bfree = sg.sg_free + sg.sg_free_dinode + sg.sg_free_meta;
- buf->f_bavail = sg.sg_free + sg.sg_free_dinode + sg.sg_free_meta;
- buf->f_files = sg.sg_used_dinode + sg.sg_free_dinode +
- sg.sg_free_meta + sg.sg_free;
- buf->f_ffree = sg.sg_free_dinode + sg.sg_free_meta + sg.sg_free;
- buf->f_namelen = GFS_FNAMESIZE;
-
- return 0;
-}
-
-/**
- * gfs_remount_fs - called when the FS is remounted
- * @sb: the filesystem
- * @flags: the remount flags
- * @data: extra data passed in (not used right now)
- *
- * Returns: errno
- */
-
-static int
-gfs_remount_fs(struct super_block *sb, int *flags, char *data)
-{
- struct gfs_sbd *sdp = get_v2sdp(sb);
- struct gfs_tune *gt = &sdp->sd_tune;
- int error = 0;
- struct gfs_args *args;
-
- atomic_inc(&sdp->sd_ops_super);
-
- args = kmalloc(sizeof(struct gfs_args), GFP_KERNEL);
- if (!args)
- return -ENOMEM;
-
- error = gfs_make_args(data, args, TRUE);
- if (error) {
- printk("GFS: can't parse remount arguments\n");
- goto out;
- }
- if (args->ar_posix_acls) {
- sdp->sd_args.ar_posix_acls = TRUE;
- sb->s_flags |= MS_POSIXACL;
- }
- else {
- sdp->sd_args.ar_posix_acls = FALSE;
- sb->s_flags &= ~MS_POSIXACL;
- }
-
- if (*flags & (MS_NOATIME | MS_NODIRATIME))
- set_bit(SDF_NOATIME, &sdp->sd_flags);
- else
- clear_bit(SDF_NOATIME, &sdp->sd_flags);
-
- if (sdp->sd_args.ar_spectator)
- *flags |= MS_RDONLY;
- else {
- if (*flags & MS_RDONLY) {
- if (!test_bit(SDF_ROFS, &sdp->sd_flags))
- error = gfs_make_fs_ro(sdp);
- } else if (!(*flags & MS_RDONLY) &&
- test_bit(SDF_ROFS, &sdp->sd_flags)) {
- error = gfs_make_fs_rw(sdp);
- }
- }
-
- if (args->ar_noquota) {
- if (sdp->sd_args.ar_noquota == FALSE)
- printk("GFS: remounting without quota\n");
- sdp->sd_args.ar_noquota = TRUE;
- spin_lock(>->gt_spin);
- gt->gt_quota_enforce = 0;
- gt->gt_quota_account = 0;
- spin_unlock(>->gt_spin);
- }
- else {
- if (sdp->sd_args.ar_noquota == TRUE)
- printk("GFS: remounting with quota\n");
- sdp->sd_args.ar_noquota = FALSE;
- spin_lock(>->gt_spin);
- gt->gt_quota_enforce = 1;
- gt->gt_quota_account = 1;
- spin_unlock(>->gt_spin);
- }
-
- /* Don't let the VFS update atimes. GFS handles this itself. */
- *flags |= MS_NOATIME | MS_NODIRATIME;
-
- if (error == 0)
- gfs_online_uevent(sdp);
-out:
- kfree(args);
- return error;
-}
-
-/**
- * gfs_clear_inode - Deallocate an inode when VFS is done with it
- * @inode: The VFS inode
- *
- * If there's a GFS incore inode structure attached to the VFS inode:
- * -- Detach them from one another.
- * -- Schedule reclaim of GFS inode struct, the glock protecting it, and
- * the associated iopen glock.
- */
-
-static void
-gfs_clear_inode(struct inode *inode)
-{
- struct gfs_inode *ip = get_v2ip(inode);
-
- atomic_inc(&get_v2sdp(inode->i_sb)->sd_ops_super);
-
- if (ip) {
- spin_lock(&ip->i_spin);
- ip->i_vnode = NULL;
- set_v2ip(inode, NULL);
- spin_unlock(&ip->i_spin);
-
- gfs_glock_schedule_for_reclaim(ip->i_gl);
- gfs_inode_put(ip);
- }
-}
-
-/**
- * gfs_show_options - Show mount options for /proc/mounts
- * @s: seq_file structure
- * @mnt: vfsmount
- *
- * Returns: 0 on success or error code
- */
-
-static int
-gfs_show_options(struct seq_file *s, struct vfsmount *mnt)
-{
- struct gfs_sbd *sdp = get_v2sdp(mnt->mnt_sb);
- struct gfs_args *args = &sdp->sd_args;
-
- atomic_inc(&sdp->sd_ops_super);
-
- if (args->ar_lockproto[0]) {
- seq_printf(s, ",lockproto=");
- seq_puts(s, args->ar_lockproto);
- }
- if (args->ar_locktable[0]) {
- seq_printf(s, ",locktable=");
- seq_puts(s, args->ar_locktable);
- }
- if (args->ar_hostdata[0]) {
- seq_printf(s, ",hostdata=");
- seq_puts(s, args->ar_hostdata);
- }
- if (args->ar_spectator)
- seq_printf(s, ",spectator");
- if (args->ar_ignore_local_fs)
- seq_printf(s, ",ignore_local_fs");
- if (args->ar_localflocks)
- seq_printf(s, ",localflocks");
- if (args->ar_localcaching)
- seq_printf(s, ",localcaching");
- if (args->ar_oopses_ok)
- seq_printf(s, ",oopses_ok");
- if (args->ar_debug)
- seq_printf(s, ",debug");
- if (args->ar_upgrade)
- seq_printf(s, ",upgrade");
- if (args->ar_num_glockd != GFS_GLOCKD_DEFAULT)
- seq_printf(s, ",num_glockd=%u", args->ar_num_glockd);
- if (args->ar_posix_acls)
- seq_printf(s, ",acl");
- if (args->ar_noquota)
- seq_printf(s, ",noquota");
- if (args->ar_suiddir)
- seq_printf(s, ",suiddir");
- if (args->ar_errors) {
- seq_printf(s, ",errors=");
- if (args->ar_errors == GFS_ERRORS_PANIC)
- seq_printf(s, "panic");
- }
- return 0;
-}
-
-struct super_operations gfs_super_ops = {
- .write_inode = gfs_write_inode,
- .drop_inode = gfs_drop_inode,
- .put_super = gfs_put_super,
- .write_super = gfs_write_super,
- .freeze_fs = gfs_freeze,
- .unfreeze_fs = gfs_unfreeze,
- .statfs = gfs_statfs,
- .remount_fs = gfs_remount_fs,
- .clear_inode = gfs_clear_inode,
- .show_options = gfs_show_options,
-};
diff --git a/gfs-kernel/src/gfs/ops_super.h b/gfs-kernel/src/gfs/ops_super.h
deleted file mode 100644
index d3dad88..0000000
--- a/gfs-kernel/src/gfs/ops_super.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __OPS_SUPER_DOT_H__
-#define __OPS_SUPER_DOT_H__
-
-extern struct super_operations gfs_super_ops;
-
-#endif /* __OPS_SUPER_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/ops_vm.c b/gfs-kernel/src/gfs/ops_vm.c
deleted file mode 100644
index 423435e..0000000
--- a/gfs-kernel/src/gfs/ops_vm.c
+++ /dev/null
@@ -1,233 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-
-#include "gfs.h"
-#include "bmap.h"
-#include "glock.h"
-#include "inode.h"
-#include "ops_vm.h"
-#include "page.h"
-#include "quota.h"
-#include "rgrp.h"
-#include "trans.h"
-
-/**
- * pfault_be_greedy -
- * @ip:
- *
- */
-
-static void
-pfault_be_greedy(struct gfs_inode *ip)
-{
- unsigned int time;
-
- spin_lock(&ip->i_spin);
- time = ip->i_greedy;
- ip->i_last_pfault = jiffies;
- spin_unlock(&ip->i_spin);
-
- gfs_inode_hold(ip);
- if (gfs_glock_be_greedy(ip->i_gl, time))
- gfs_inode_put(ip);
-}
-
-/**
- * gfs_private_fault -
- * @area:
- * @address:
- * @type:
- *
- * Returns: the page
- */
-
-static int gfs_private_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct gfs_inode *ip = get_v2ip(vma->vm_file->f_mapping->host);
- struct gfs_holder i_gh;
- int error;
- int ret = 0;
-
- atomic_inc(&ip->i_sbd->sd_ops_vm);
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
- if (error)
- goto out;
-
- set_bit(GIF_PAGED, &ip->i_flags);
-
- ret = filemap_fault(vma, vmf);
-
- if (ret && ret != VM_FAULT_OOM)
- pfault_be_greedy(ip);
-
- gfs_glock_dq_uninit(&i_gh);
- out:
- return ret;
-}
-
-/**
- * alloc_page_backing -
- * @ip:
- * @index:
- *
- * Returns: errno
- */
-
-static int
-alloc_page_backing(struct gfs_inode *ip, struct page *page)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- unsigned long index = page->index;
- uint64_t lblock = index << (PAGE_CACHE_SHIFT - sdp->sd_sb.sb_bsize_shift);
- unsigned int blocks = PAGE_CACHE_SIZE >> sdp->sd_sb.sb_bsize_shift;
- struct gfs_alloc *al;
- unsigned int x;
- int error;
-
- al = gfs_alloc_get(ip);
-
- error = gfs_quota_lock_m(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
- if (error)
- goto out;
-
- error = gfs_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid);
- if (error)
- goto out_gunlock_q;
-
- gfs_write_calc_reserv(ip, PAGE_CACHE_SIZE,
- &al->al_requested_data, &al->al_requested_meta);
-
- error = gfs_inplace_reserve(ip);
- if (error)
- goto out_gunlock_q;
-
- /* Trans may require:
- a dinode block, RG bitmaps to allocate from,
- indirect blocks, and a quota block */
-
- error = gfs_trans_begin(sdp,
- 1 + al->al_rgd->rd_ri.ri_length +
- al->al_requested_meta, 1);
- if (error)
- goto out_ipres;
-
- if (gfs_is_stuffed(ip)) {
- error = gfs_unstuff_dinode(ip, gfs_unstuffer_page, NULL);
- if (error)
- goto out_trans;
- }
-
- for (x = 0; x < blocks; ) {
- uint64_t dblock;
- unsigned int extlen;
- int new = TRUE;
-
- error = gfs_block_map(ip, lblock, &new, &dblock, &extlen);
- if (error)
- goto out_trans;
-
- lblock += extlen;
- x += extlen;
- }
-
- gfs_assert_warn(sdp, al->al_alloced_meta || al->al_alloced_data);
-
- out_trans:
- gfs_trans_end(sdp);
-
- out_ipres:
- gfs_inplace_release(ip);
-
- out_gunlock_q:
- gfs_quota_unlock_m(ip);
-
- out:
- gfs_alloc_put(ip);
-
- return error;
-}
-
-/**
- * gfs_sharewrite_fault -
- * @area:
- * @address:
- * @type:
- *
- * Returns: the page
- */
-
-static int gfs_sharewrite_fault(struct vm_area_struct *vma,
- struct vm_fault *vmf)
-{
- struct file *file = vma->vm_file;
- struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
- struct gfs_holder i_gh;
- int alloc_required;
- int error;
- int ret = 0;
-
- atomic_inc(&ip->i_sbd->sd_ops_vm);
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
- if (error)
- goto out;
-
- if (gfs_is_jdata(ip))
- goto out_unlock;
-
- set_bit(GIF_PAGED, &ip->i_flags);
- set_bit(GIF_SW_PAGED, &ip->i_flags);
-
- error = gfs_write_alloc_required(ip,
- (u64)vmf->pgoff << PAGE_CACHE_SHIFT,
- PAGE_CACHE_SIZE, &alloc_required);
- if (error) {
- ret = VM_FAULT_OOM; /* XXX: are these right? */
- goto out_unlock;
- }
-
- ret = filemap_fault(vma, vmf);
- if (ret & VM_FAULT_ERROR)
- goto out_unlock;
-
- if (alloc_required) {
- /* XXX: do we need to drop page lock around alloc_page_backing?*/
- error = alloc_page_backing(ip, vmf->page);
- if (error) {
- /*
- * VM_FAULT_LOCKED should always be the case for
- * filemap_fault, but it may not be in a future
- * implementation.
- */
- if (ret & VM_FAULT_LOCKED)
- unlock_page(vmf->page);
- page_cache_release(vmf->page);
- ret = VM_FAULT_OOM;
- goto out_unlock;
- }
- set_page_dirty(vmf->page);
- }
-
- pfault_be_greedy(ip);
-
- out_unlock:
- gfs_glock_dq_uninit(&i_gh);
- out:
- return ret;
-}
-
-struct vm_operations_struct gfs_vm_ops_private = {
- .fault = gfs_private_fault,
-};
-
-struct vm_operations_struct gfs_vm_ops_sharewrite = {
- .fault = gfs_sharewrite_fault,
-};
-
diff --git a/gfs-kernel/src/gfs/ops_vm.h b/gfs-kernel/src/gfs/ops_vm.h
deleted file mode 100644
index 0361c97..0000000
--- a/gfs-kernel/src/gfs/ops_vm.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __OPS_VM_DOT_H__
-#define __OPS_VM_DOT_H__
-
-extern struct vm_operations_struct gfs_vm_ops_private;
-extern struct vm_operations_struct gfs_vm_ops_sharewrite;
-
-#endif /* __OPS_VM_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/page.c b/gfs-kernel/src/gfs/page.c
deleted file mode 100644
index 4c5cdb3..0000000
--- a/gfs-kernel/src/gfs/page.c
+++ /dev/null
@@ -1,266 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/pagemap.h>
-#include <linux/mm.h>
-
-#include "gfs.h"
-#include "bmap.h"
-#include "inode.h"
-#include "page.h"
-
-/**
- * gfs_inval_pte - Sync and invalidate all PTEs associated with a glock
- * @gl: the glock
- *
- */
-
-void
-gfs_inval_pte(struct gfs_glock *gl)
-{
- struct gfs_inode *ip;
- struct inode *inode;
-
- ip = get_gl2ip(gl);
- if (!ip ||
- ip->i_di.di_type != GFS_FILE_REG)
- return;
-
- if (!test_bit(GIF_PAGED, &ip->i_flags))
- return;
-
- inode = gfs_iget(ip, NO_CREATE);
- if (inode) {
- unmap_shared_mapping_range(inode->i_mapping, 0, 0);
- iput(inode);
-
- if (test_bit(GIF_SW_PAGED, &ip->i_flags))
- set_bit(GLF_DIRTY, &gl->gl_flags);
- }
-
- clear_bit(GIF_SW_PAGED, &ip->i_flags);
-}
-
-/**
- * gfs_inval_page - Invalidate all pages associated with a glock
- * @gl: the glock
- *
- */
-
-void
-gfs_inval_page(struct gfs_glock *gl)
-{
- struct gfs_inode *ip;
- struct inode *inode;
-
- ip = get_gl2ip(gl);
- if (!ip ||
- ip->i_di.di_type != GFS_FILE_REG)
- return;
-
- inode = gfs_iget(ip, NO_CREATE);
- if (inode) {
- struct address_space *mapping = inode->i_mapping;
-
- truncate_inode_pages(mapping, 0);
- gfs_assert_withdraw(ip->i_sbd, !mapping->nrpages);
-
- iput(inode);
- }
-
- clear_bit(GIF_PAGED, &ip->i_flags);
-}
-
-/**
- * gfs_sync_page_i - Sync the data pages (not metadata) for a struct inode
- * @inode: the inode
- * @flags: DIO_START | DIO_WAIT
- *
- */
-
-void
-gfs_sync_page_i(struct inode *inode, int flags)
-{
- struct address_space *mapping = inode->i_mapping;
- int error = 0;
-
- if (flags & DIO_START)
- error = filemap_fdatawrite(mapping);
- if (!error && (flags & DIO_WAIT))
- error = filemap_fdatawait(mapping);
-
- /* Find a better way to report this to the user. */
- if (error)
- gfs_io_error_inode(get_v2ip(inode));
-}
-
-/**
- * gfs_sync_page - Sync the data pages (not metadata) associated with a glock
- * @gl: the glock
- * @flags: DIO_START | DIO_WAIT
- *
- * Syncs data (not metadata) for a regular file.
- * No-op for all other types.
- */
-
-void
-gfs_sync_page(struct gfs_glock *gl, int flags)
-{
- struct gfs_inode *ip;
- struct inode *inode;
-
- ip = get_gl2ip(gl);
- if (!ip ||
- ip->i_di.di_type != GFS_FILE_REG)
- return;
-
- inode = gfs_iget(ip, NO_CREATE);
- if (inode) {
- gfs_sync_page_i(inode, flags);
- iput(inode);
- }
-}
-
-/**
- * gfs_unstuffer_page - unstuff a stuffed inode into a block cached by a page
- * @ip: the inode
- * @dibh: the dinode buffer
- * @block: the block number that was allocated
- * @private: any locked page held by the caller process
- *
- * Returns: errno
- */
-
-int
-gfs_unstuffer_page(struct gfs_inode *ip, struct buffer_head *dibh,
- uint64_t block, void *private)
-{
- struct inode *inode = ip->i_vnode;
- struct page *page = (struct page *)private;
- struct buffer_head *bh;
- int release = FALSE;
-
- if (!page || page->index) {
- page = grab_cache_page(inode->i_mapping, 0);
- if (!page)
- return -ENOMEM;
- release = TRUE;
- }
-
- if (!PageUptodate(page)) {
- void *kaddr = kmap(page);
-
- memcpy(kaddr,
- dibh->b_data + sizeof(struct gfs_dinode),
- ip->i_di.di_size);
- memset(kaddr + ip->i_di.di_size,
- 0,
- PAGE_CACHE_SIZE - ip->i_di.di_size);
- kunmap(page);
-
- SetPageUptodate(page);
- }
-
- if (!page_has_buffers(page))
- create_empty_buffers(page, 1 << inode->i_blkbits,
- (1 << BH_Uptodate));
-
- bh = page_buffers(page);
-
- if (!buffer_mapped(bh))
- map_bh(bh, inode->i_sb, block);
- else if (gfs_assert_warn(ip->i_sbd,
- bh->b_bdev == inode->i_sb->s_bdev &&
- bh->b_blocknr == block))
- map_bh(bh, inode->i_sb, block);
-
- set_buffer_uptodate(bh);
- mark_buffer_dirty(bh);
-
- if (release) {
- unlock_page(page);
- page_cache_release(page);
- }
-
- return 0;
-}
-
-/**
- * gfs_truncator_page - truncate a partial data block in the page cache
- * @ip: the inode
- * @size: the size the file should be
- *
- * Returns: errno
- */
-
-int
-gfs_truncator_page(struct gfs_inode *ip, uint64_t size)
-{
- struct inode *inode = ip->i_vnode;
- struct page *page;
- struct buffer_head *bh;
- void *kaddr;
- uint64_t lbn, dbn;
- unsigned long index;
- unsigned int offset;
- unsigned int bufnum;
- int not_new = 0;
- int error;
-
- lbn = size >> inode->i_blkbits;
- error = gfs_block_map(ip,
- lbn, ¬_new,
- &dbn, NULL);
- if (error || !dbn)
- return error;
-
- index = size >> PAGE_CACHE_SHIFT;
- offset = size & (PAGE_CACHE_SIZE - 1);
- bufnum = lbn - (index << (PAGE_CACHE_SHIFT - inode->i_blkbits));
-
- /* Not in a transaction here -- a non-disk-I/O error is ok. */
-
- page = read_cache_page(inode->i_mapping, index,
- (filler_t *)inode->i_mapping->a_ops->readpage,
- NULL);
- if (IS_ERR(page))
- return PTR_ERR(page);
-
- lock_page(page);
-
- if (!PageUptodate(page) || PageError(page)) {
- error = -EIO;
- goto out;
- }
-
- kaddr = kmap(page);
- memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
- kunmap(page);
-
- if (!page_has_buffers(page))
- create_empty_buffers(page, 1 << inode->i_blkbits,
- (1 << BH_Uptodate));
-
- for (bh = page_buffers(page); bufnum--; bh = bh->b_this_page)
- /* Do nothing */;
-
- if (!buffer_mapped(bh))
- map_bh(bh, inode->i_sb, dbn);
- else if (gfs_assert_warn(ip->i_sbd,
- bh->b_bdev == inode->i_sb->s_bdev &&
- bh->b_blocknr == dbn))
- map_bh(bh, inode->i_sb, dbn);
-
- set_buffer_uptodate(bh);
- mark_buffer_dirty(bh);
-
- out:
- unlock_page(page);
- page_cache_release(page);
-
- return error;
-}
diff --git a/gfs-kernel/src/gfs/page.h b/gfs-kernel/src/gfs/page.h
deleted file mode 100644
index c9e0d55..0000000
--- a/gfs-kernel/src/gfs/page.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __PAGE_DOT_H__
-#define __PAGE_DOT_H__
-
-void gfs_inval_pte(struct gfs_glock *gl);
-void gfs_inval_page(struct gfs_glock *gl);
-void gfs_sync_page_i(struct inode *inode, int flags);
-void gfs_sync_page(struct gfs_glock *gl, int flags);
-
-int gfs_unstuffer_page(struct gfs_inode *ip, struct buffer_head *dibh,
- uint64_t block, void *private);
-int gfs_truncator_page(struct gfs_inode *ip, uint64_t size);
-
-#endif /* __PAGE_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/proc.c b/gfs-kernel/src/gfs/proc.c
deleted file mode 100644
index 069b39d..0000000
--- a/gfs-kernel/src/gfs/proc.c
+++ /dev/null
@@ -1,490 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/proc_fs.h>
-#include <linux/module.h>
-#include <asm/uaccess.h>
-
-#include "gfs.h"
-#include "glock.h"
-#include "lm.h"
-#include "proc.h"
-#include "super.h"
-
-struct list_head gfs_fs_list;
-struct semaphore gfs_fs_lock;
-char *gfs_proc_margs;
-spinlock_t gfs_proc_margs_lock;
-spinlock_t gfs_req_lock;
-
-/**
- * gfs_proc_fs_add - Add a FS to the list of mounted FSs
- * @sdp:
- *
- */
-
-void
-gfs_proc_fs_add(struct gfs_sbd *sdp)
-{
- down(&gfs_fs_lock);
- list_add(&sdp->sd_list, &gfs_fs_list);
- up(&gfs_fs_lock);
-}
-
-/**
- * gfs_proc_fs_del - Remove a FS from the list of mounted FSs
- * @sdp:
- *
- */
-
-void
-gfs_proc_fs_del(struct gfs_sbd *sdp)
-{
- down(&gfs_fs_lock);
- list_del(&sdp->sd_list);
- up(&gfs_fs_lock);
-}
-
-/**
- * do_list - Copy the list of mountes FSs to userspace
- * @user_buf:
- * @size:
- *
- * @Returns: -errno, or the number of bytes copied to userspace
- */
-
-static ssize_t
-do_list(char *user_buf, size_t size)
-{
- struct list_head *tmp;
- struct gfs_sbd *sdp = NULL;
- unsigned int x;
- char num[21];
- char device_id[32];
- char *buf;
- int error = 0;
-
- down(&gfs_fs_lock);
-
- x = 0;
- for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) {
- sdp = list_entry(tmp, struct gfs_sbd, sd_list);
- sprintf(device_id, "%u:%u", MAJOR(sdp->sd_vfs->s_dev),
- MINOR(sdp->sd_vfs->s_dev));
- x += sprintf(num, "%lu", (unsigned long)sdp) +
- strlen(device_id) +
- strlen(sdp->sd_fsname) + 3;
- }
-
- if (!x)
- goto out;
-
- error = -EFBIG;
- if (x > size)
- goto out;
-
- error = -ENOMEM;
- buf = kmalloc(x + 1, GFP_KERNEL);
- if (!buf)
- goto out;
-
- x = 0;
- for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) {
- sdp = list_entry(tmp, struct gfs_sbd, sd_list);
- sprintf(device_id, "%u:%u", MAJOR(sdp->sd_vfs->s_dev),
- MINOR(sdp->sd_vfs->s_dev));
- x += sprintf(buf + x, "%lu %s %s\n",
- (unsigned long)sdp, device_id, sdp->sd_fsname);
- }
-
- if (copy_to_user(user_buf, buf, x))
- error = -EFAULT;
- else
- error = x;
-
- kfree(buf);
-
- out:
- up(&gfs_fs_lock);
-
- return error;
-}
-
-/**
- * find_argument -
- * @p:
- *
- * Returns:
- */
-
-static char *
-find_argument(char *p)
-{
- char *p2;
-
- while (*p == ' ' || *p == '\n')
- p++;
- if (!*p)
- return NULL;
- for (p2 = p; *p2; p2++) /* do nothing */;
- p2--;
- while (*p2 == ' ' || *p2 == '\n')
- *p2-- = 0;
-
- return p;
-}
-
-/**
- * do_freeze - freeze a filesystem
- * @p: the freeze command
- *
- * Returns: errno
- */
-
-static int
-do_freeze(char *p)
-{
- struct list_head *tmp;
- struct gfs_sbd *sdp;
- char num[21];
- int error = 0;
-
- p = find_argument(p + 6);
- if (!p)
- return -ENOENT;
-
- down(&gfs_fs_lock);
-
- for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) {
- sdp = list_entry(tmp, struct gfs_sbd, sd_list);
- sprintf(num, "%lu", (unsigned long)sdp);
- if (strcmp(num, p) == 0)
- break;
- }
-
- if (tmp == &gfs_fs_list)
- error = -ENOENT;
- else
- error = gfs_freeze_fs(sdp);
-
- up(&gfs_fs_lock);
-
- return error;
-}
-
-/**
- * do_unfreeze - unfreeze a filesystem
- * @p: the unfreeze command
- *
- * Returns: errno
- */
-
-static int
-do_unfreeze(char *p)
-{
- struct list_head *tmp;
- struct gfs_sbd *sdp;
- char num[21];
- int error = 0;
-
- p = find_argument(p + 8);
- if (!p)
- return -ENOENT;
-
- down(&gfs_fs_lock);
-
- for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) {
- sdp = list_entry(tmp, struct gfs_sbd, sd_list);
- sprintf(num, "%lu", (unsigned long)sdp);
- if (strcmp(num, p) == 0)
- break;
- }
-
- if (tmp == &gfs_fs_list)
- error = -ENOENT;
- else
- gfs_unfreeze_fs(sdp);
-
- up(&gfs_fs_lock);
-
- return error;
-}
-
-/**
- * do_margs - Pass in mount arguments
- * @p: the margs command
- *
- * Returns: errno
- */
-
-static int
-do_margs(char *p)
-{
- char *new_buf, *old_buf;
-
- p = find_argument(p + 5);
- if (!p)
- return -ENOENT;
-
- new_buf = kmalloc(strlen(p) + 1, GFP_KERNEL);
- if (!new_buf)
- return -ENOMEM;
- strcpy(new_buf, p);
-
- spin_lock(&gfs_proc_margs_lock);
- old_buf = gfs_proc_margs;
- gfs_proc_margs = new_buf;
- spin_unlock(&gfs_proc_margs_lock);
-
- if (old_buf)
- kfree(old_buf);
-
- return 0;
-}
-
-/**
- * do_withdraw - withdraw a from the cluster for one filesystem
- * @p: the cookie of the filesystem
- *
- * Returns: errno
- */
-
-static int
-do_withdraw(char *p)
-{
- struct list_head *tmp;
- struct gfs_sbd *sdp;
- char num[21];
- int error = 0;
-
- p = find_argument(p + 8);
- if (!p)
- return -ENOENT;
-
- down(&gfs_fs_lock);
-
- for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) {
- sdp = list_entry(tmp, struct gfs_sbd, sd_list);
- sprintf(num, "%lu", (unsigned long)sdp);
- if (strcmp(num, p) == 0)
- break;
- }
-
- if (tmp == &gfs_fs_list)
- error = -ENOENT;
- else
- gfs_lm_withdraw(sdp,
- "GFS: fsid=%s: withdrawing from cluster at user's request\n",
- sdp->sd_fsname);
-
- up(&gfs_fs_lock);
-
- return error;
-}
-
-/**
- * do_lockdump - Copy out the lock hash table to userspace
- * @p: the cookie of the filesystem
- * @buf:
- * @size:
- *
- * Returns: errno
- */
-
-static int
-do_lockdump(char *p, char *buf, size_t size)
-{
- struct list_head *tmp;
- struct gfs_sbd *sdp;
- char num[21];
- struct gfs_user_buffer ub;
- int error = 0;
-
- p = find_argument(p + 8);
- if (!p)
- return -ENOENT;
-
- down(&gfs_fs_lock);
-
- for (tmp = gfs_fs_list.next; tmp != &gfs_fs_list; tmp = tmp->next) {
- sdp = list_entry(tmp, struct gfs_sbd, sd_list);
- sprintf(num, "%lu", (unsigned long)sdp);
- if (strcmp(num, p) == 0)
- break;
- }
-
- if (tmp == &gfs_fs_list)
- error = -ENOENT;
- else {
- ub.ub_data = buf;
- ub.ub_size = size;
- ub.ub_count = 0;
-
- error = gfs_dump_lockstate(sdp, &ub);
- if (!error)
- error = ub.ub_count;
- }
-
- up(&gfs_fs_lock);
-
- return error;
-}
-
-/**
- * gfs_proc_write - take a command from userspace
- * @file:
- * @buf:
- * @size:
- * @offset:
- *
- * Returns: -errno or the number of bytes taken
- */
-
-static ssize_t
-gfs_proc_write(struct file *file, const char *buf, size_t size, loff_t *offset)
-{
- char *p;
-
- spin_lock(&gfs_req_lock);
- p = file->private_data;
- file->private_data = NULL;
- spin_unlock(&gfs_req_lock);
-
- if (p)
- kfree(p);
-
- if (!size)
- return -EINVAL;
-
- p = kmalloc(size + 1, GFP_KERNEL);
- if (!p)
- return -ENOMEM;
- p[size] = 0;
-
- if (copy_from_user(p, buf, size)) {
- kfree(p);
- return -EFAULT;
- }
-
- spin_lock(&gfs_req_lock);
- file->private_data = p;
- spin_unlock(&gfs_req_lock);
-
- return size;
-}
-
-/**
- * gfs_proc_read - return the results of a command
- * @file:
- * @buf:
- * @size:
- * @offset:
- *
- * Returns: -errno or the number of bytes returned
- */
-
-static ssize_t
-gfs_proc_read(struct file *file, char *buf, size_t size, loff_t *offset)
-{
- char *p;
- int error;
-
- spin_lock(&gfs_req_lock);
- p = file->private_data;
- file->private_data = NULL;
- spin_unlock(&gfs_req_lock);
-
- if (!p)
- return -ENOENT;
-
- if (!size) {
- kfree(p);
- return -EINVAL;
- }
-
- if (strncmp(p, "list", 4) == 0)
- error = do_list(buf, size);
- else if (strncmp(p, "freeze", 6) == 0)
- error = do_freeze(p);
- else if (strncmp(p, "unfreeze", 8) == 0)
- error = do_unfreeze(p);
- else if (strncmp(p, "margs", 5) == 0)
- error = do_margs(p);
- else if (strncmp(p, "withdraw", 8) == 0)
- error = do_withdraw(p);
- else if (strncmp(p, "lockdump", 8) == 0)
- error = do_lockdump(p, buf, size);
- else
- error = -ENOSYS;
-
- kfree(p);
-
- return error;
-}
-
-/**
- * gfs_proc_close - free any mismatches writes
- * @inode:
- * @file:
- *
- * Returns: 0
- */
-
-static int
-gfs_proc_close(struct inode *inode, struct file *file)
-{
- if (file->private_data)
- kfree(file->private_data);
- return 0;
-}
-
-static struct file_operations gfs_proc_fops =
-{
- .owner = THIS_MODULE,
- .write = gfs_proc_write,
- .read = gfs_proc_read,
- .release = gfs_proc_close,
-};
-
-/**
- * gfs_proc_init - initialize GFS' proc interface
- *
- */
-
-int
-gfs_proc_init(void)
-{
- struct proc_dir_entry *pde;
-
- INIT_LIST_HEAD(&gfs_fs_list);
- init_MUTEX(&gfs_fs_lock);
- gfs_proc_margs = NULL;
- spin_lock_init(&gfs_proc_margs_lock);
- spin_lock_init(&gfs_req_lock);
-
- pde = create_proc_entry("fs/gfs", S_IFREG | 0600, NULL);
- if (!pde)
- return -ENOMEM;
-
- pde->proc_fops = &gfs_proc_fops;
-
- return 0;
-}
-
-/**
- * gfs_proc_uninit - uninitialize GFS' proc interface
- *
- */
-
-void
-gfs_proc_uninit(void)
-{
- if (gfs_proc_margs)
- kfree(gfs_proc_margs);
- remove_proc_entry("fs/gfs", NULL);
-}
-
diff --git a/gfs-kernel/src/gfs/proc.h b/gfs-kernel/src/gfs/proc.h
deleted file mode 100644
index ea8c261..0000000
--- a/gfs-kernel/src/gfs/proc.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __PROC_DOT_H__
-#define __PROC_DOT_H__
-
-/* Allow args to be passed to GFS when using an initial ram disk */
-extern char *gfs_proc_margs;
-extern spinlock_t gfs_proc_margs_lock;
-
-void gfs_proc_fs_add(struct gfs_sbd *sdp);
-void gfs_proc_fs_del(struct gfs_sbd *sdp);
-
-int gfs_proc_init(void);
-void gfs_proc_uninit(void);
-
-#endif /* __PROC_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/quota.c b/gfs-kernel/src/gfs/quota.c
deleted file mode 100644
index df45487..0000000
--- a/gfs-kernel/src/gfs/quota.c
+++ /dev/null
@@ -1,1140 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/tty.h>
-#include <linux/cred.h>
-
-#include "gfs.h"
-#include "bmap.h"
-#include "file.h"
-#include "glock.h"
-#include "glops.h"
-#include "log.h"
-#include "quota.h"
-#include "rgrp.h"
-#include "super.h"
-#include "trans.h"
-
-/**
- * gfs_quota_get - Get a structure to represent a quota change
- * @sdp: the filesystem
- * @user: TRUE if this is a user quota
- * @id: the uid or gid
- * @create: if TRUE, create the structure, otherwise return NULL
- * @qdp: the returned quota structure
- *
- * Returns: errno
- */
-
-int
-gfs_quota_get(struct gfs_sbd *sdp, int user, uint32_t id, int create,
- struct gfs_quota_data **qdp)
-{
- struct gfs_quota_data *qd = NULL, *new_qd = NULL;
- struct list_head *tmp, *head;
- int error;
-
- *qdp = NULL;
-
- for (;;) {
- spin_lock(&sdp->sd_quota_lock);
-
- for (head = &sdp->sd_quota_list, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- qd = list_entry(tmp, struct gfs_quota_data, qd_list);
- if (qd->qd_id == id &&
- !test_bit(QDF_USER, &qd->qd_flags) == !user) {
- qd->qd_count++;
- break;
- }
- }
-
- if (tmp == head)
- qd = NULL;
-
- if (!qd && new_qd) {
- qd = new_qd;
- list_add(&qd->qd_list, &sdp->sd_quota_list);
- new_qd = NULL;
- }
-
- spin_unlock(&sdp->sd_quota_lock);
-
- if (qd || !create) {
- if (new_qd) {
- gfs_lvb_unhold(new_qd->qd_gl);
- kfree(new_qd);
- atomic_dec(&sdp->sd_quota_count);
- }
- *qdp = qd;
- return 0;
- }
-
- new_qd = kmalloc(sizeof(struct gfs_quota_data), GFP_KERNEL);
- if (!new_qd)
- return -ENOMEM;
- memset(new_qd, 0, sizeof(struct gfs_quota_data));
-
- new_qd->qd_count = 1;
-
- new_qd->qd_id = id;
- if (user)
- set_bit(QDF_USER, &new_qd->qd_flags);
-
- INIT_LIST_HEAD(&new_qd->qd_le_list);
-
- error = gfs_glock_get(sdp, 2 * (uint64_t)id + ((user) ? 0 : 1),
- &gfs_quota_glops, CREATE,
- &new_qd->qd_gl);
- if (error) {
- kfree(new_qd);
- return error;
- }
-
- error = gfs_lvb_hold(new_qd->qd_gl);
-
- gfs_glock_put(new_qd->qd_gl);
-
- if (error) {
- kfree(new_qd);
- return error;
- }
-
- atomic_inc(&sdp->sd_quota_count);
- }
-}
-
-/**
- * gfs_quota_hold - increment the usage count on a struct gfs_quota_data
- * @sdp: the filesystem
- * @qd: the structure
- *
- */
-
-void
-gfs_quota_hold(struct gfs_sbd *sdp, struct gfs_quota_data *qd)
-{
- spin_lock(&sdp->sd_quota_lock);
- gfs_assert(sdp, qd->qd_count,);
- qd->qd_count++;
- spin_unlock(&sdp->sd_quota_lock);
-}
-
-/**
- * gfs_quota_put - decrement the usage count on a struct gfs_quota_data
- * @sdp: the filesystem
- * @qd: the structure
- *
- * Free the structure if its reference count hits zero.
- *
- */
-
-void
-gfs_quota_put(struct gfs_sbd *sdp, struct gfs_quota_data *qd)
-{
- spin_lock(&sdp->sd_quota_lock);
- gfs_assert(sdp, qd->qd_count,);
- qd->qd_count--;
- spin_unlock(&sdp->sd_quota_lock);
-}
-
-/**
- * quota_find - Find a quota change to sync to the quota file
- * @sdp: the filesystem
- *
- * The returned structure is locked and needs to be unlocked
- * with quota_unlock().
- *
- * Returns: A quota structure, or NULL
- */
-
-static struct gfs_quota_data *
-quota_find(struct gfs_sbd *sdp)
-{
- struct list_head *tmp, *head;
- struct gfs_quota_data *qd = NULL;
-
- if (test_bit(SDF_ROFS, &sdp->sd_flags))
- return NULL;
-
- gfs_log_lock(sdp);
- spin_lock(&sdp->sd_quota_lock);
-
- if (!atomic_read(&sdp->sd_quota_od_count))
- goto out;
-
- for (head = &sdp->sd_quota_list, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- qd = list_entry(tmp, struct gfs_quota_data, qd_list);
-
- if (test_bit(QDF_LOCK, &qd->qd_flags))
- continue;
- if (!test_bit(QDF_OD_LIST, &qd->qd_flags))
- continue;
- if (qd->qd_sync_gen >= sdp->sd_quota_sync_gen)
- continue;
-
- list_move_tail(&qd->qd_list, &sdp->sd_quota_list);
-
- set_bit(QDF_LOCK, &qd->qd_flags);
- qd->qd_count++;
- qd->qd_change_sync = qd->qd_change_od;
-
- goto out;
- }
-
- qd = NULL;
-
- out:
- spin_unlock(&sdp->sd_quota_lock);
- gfs_log_unlock(sdp);
-
- return qd;
-}
-
-/**
- * quota_trylock - Try to lock a given quota entry
- * @sdp: the filesystem
- * @qd: the quota data structure
- *
- * Returns: TRUE if the lock was successful, FALSE, otherwise
- */
-
-static int
-quota_trylock(struct gfs_sbd *sdp, struct gfs_quota_data *qd)
-{
- int ret = FALSE;
-
- if (test_bit(SDF_ROFS, &sdp->sd_flags))
- return FALSE;
-
- gfs_log_lock(sdp);
- spin_lock(&sdp->sd_quota_lock);
-
- if (test_bit(QDF_LOCK, &qd->qd_flags))
- goto out;
- if (!test_bit(QDF_OD_LIST, &qd->qd_flags))
- goto out;
-
- list_move_tail(&qd->qd_list, &sdp->sd_quota_list);
-
- set_bit(QDF_LOCK, &qd->qd_flags);
- qd->qd_count++;
- qd->qd_change_sync = qd->qd_change_od;
-
- ret = TRUE;
-
- out:
- spin_unlock(&sdp->sd_quota_lock);
- gfs_log_unlock(sdp);
-
- return ret;
-}
-
-/**
- * quota_unlock - drop and a reference on a quota structure
- * @sdp: the filesystem
- * @qd: the quota inode structure
- *
- */
-
-static void
-quota_unlock(struct gfs_sbd *sdp, struct gfs_quota_data *qd)
-{
- spin_lock(&sdp->sd_quota_lock);
-
- gfs_assert_warn(sdp, test_bit(QDF_LOCK, &qd->qd_flags));
- clear_bit(QDF_LOCK, &qd->qd_flags);
-
- gfs_assert(sdp, qd->qd_count,);
- qd->qd_count--;
-
- spin_unlock(&sdp->sd_quota_lock);
-}
-
-/**
- * gfs_quota_merge - add/remove a quota change from the in-memory list
- * @sdp: the filesystem
- * @tag: the quota change tag
- *
- * Returns: errno
- */
-
-int
-gfs_quota_merge(struct gfs_sbd *sdp, struct gfs_quota_tag *tag)
-{
- struct gfs_quota_data *qd;
- int error;
-
- error = gfs_quota_get(sdp,
- tag->qt_flags & GFS_QTF_USER, tag->qt_id,
- CREATE, &qd);
- if (error)
- return error;
-
- gfs_assert(sdp, qd->qd_change_ic == qd->qd_change_od,);
-
- gfs_log_lock(sdp);
-
- qd->qd_change_ic += tag->qt_change;
- qd->qd_change_od += tag->qt_change;
-
- if (qd->qd_change_od) {
- if (!test_bit(QDF_OD_LIST, &qd->qd_flags)) {
- gfs_quota_hold(sdp, qd);
- set_bit(QDF_OD_LIST, &qd->qd_flags);
- atomic_inc(&sdp->sd_quota_od_count);
- }
- } else {
- gfs_assert_warn(sdp, test_bit(QDF_OD_LIST, &qd->qd_flags));
- clear_bit(QDF_OD_LIST, &qd->qd_flags);
- gfs_quota_put(sdp, qd);
- gfs_assert(sdp, atomic_read(&sdp->sd_quota_od_count) > 0,);
- atomic_dec(&sdp->sd_quota_od_count);
- }
-
- gfs_log_unlock(sdp);
-
- gfs_quota_put(sdp, qd);
-
- return 0;
-}
-
-/**
- * gfs_quota_scan - Look for unused struct gfs_quota_data structures to throw away
- * @sdp: the filesystem
- *
- */
-
-void
-gfs_quota_scan(struct gfs_sbd *sdp)
-{
- struct list_head *head, *tmp, *next;
- struct gfs_quota_data *qd;
- LIST_HEAD(dead);
-
- spin_lock(&sdp->sd_quota_lock);
-
- for (head = &sdp->sd_quota_list, tmp = head->next, next = tmp->next;
- tmp != head;
- tmp = next, next = next->next) {
- qd = list_entry(tmp, struct gfs_quota_data, qd_list);
- if (!qd->qd_count)
- list_move(&qd->qd_list, &dead);
- }
-
- spin_unlock(&sdp->sd_quota_lock);
-
- while (!list_empty(&dead)) {
- qd = list_entry(dead.next, struct gfs_quota_data, qd_list);
-
- gfs_assert_warn(sdp, !qd->qd_count);
- gfs_assert_warn(sdp, !test_bit(QDF_OD_LIST, &qd->qd_flags) &&
- !test_bit(QDF_LOCK, &qd->qd_flags));
- gfs_assert_warn(sdp, !qd->qd_change_new && !qd->qd_change_ic &&
- !qd->qd_change_od);
-
- list_del(&qd->qd_list);
- gfs_lvb_unhold(qd->qd_gl);
- kfree(qd);
- atomic_dec(&sdp->sd_quota_count);
- }
-}
-
-/**
- * gfs_quota_cleanup - get rid of any extra struct gfs_quota_data structures
- * @sdp: the filesystem
- *
- */
-
-void
-gfs_quota_cleanup(struct gfs_sbd *sdp)
-{
- struct gfs_quota_data *qd;
-
- restart:
- gfs_log_lock(sdp);
-
- spin_lock(&sdp->sd_quota_lock);
-
- while (!list_empty(&sdp->sd_quota_list)) {
- qd = list_entry(sdp->sd_quota_list.next,
- struct gfs_quota_data,
- qd_list);
-
- if (qd->qd_count > 1) {
- spin_unlock(&sdp->sd_quota_lock);
- gfs_log_unlock(sdp);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
- goto restart;
-
- } else if (qd->qd_count) {
- gfs_assert_warn(sdp,
- test_bit(QDF_OD_LIST, &qd->qd_flags) &&
- !test_bit(QDF_LOCK, &qd->qd_flags));
- gfs_assert_warn(sdp, qd->qd_change_od &&
- qd->qd_change_od == qd->qd_change_ic);
- gfs_assert_warn(sdp, !qd->qd_change_new);
-
- list_del(&qd->qd_list);
- atomic_dec(&sdp->sd_quota_od_count);
-
- spin_unlock(&sdp->sd_quota_lock);
- gfs_lvb_unhold(qd->qd_gl);
- kfree(qd);
- atomic_dec(&sdp->sd_quota_count);
- spin_lock(&sdp->sd_quota_lock);
-
- } else {
- gfs_assert_warn(sdp,
- !test_bit(QDF_OD_LIST, &qd->qd_flags) &&
- !test_bit(QDF_LOCK, &qd->qd_flags));
- gfs_assert_warn(sdp, !qd->qd_change_new &&
- !qd->qd_change_ic &&
- !qd->qd_change_od);
-
- list_del(&qd->qd_list);
-
- spin_unlock(&sdp->sd_quota_lock);
- gfs_lvb_unhold(qd->qd_gl);
- kfree(qd);
- atomic_dec(&sdp->sd_quota_count);
- spin_lock(&sdp->sd_quota_lock);
- }
- }
-
- spin_unlock(&sdp->sd_quota_lock);
-
- gfs_assert(sdp, !atomic_read(&sdp->sd_quota_od_count),);
-
- gfs_log_unlock(sdp);
-}
-
-/**
- * sort_qd - figure out the order between two quota data structures
- * @a: first quota data structure
- * @b: second quota data structure
- *
- * Returns: -1 if @a comes before @b, 0 if @a equals @b, 1 if @b comes before @a
- */
-
-static int
-sort_qd(const void *a, const void *b)
-{
- struct gfs_quota_data *qd_a = *(struct gfs_quota_data **)a;
- struct gfs_quota_data *qd_b = *(struct gfs_quota_data **)b;
- int ret = 0;
-
- if (!test_bit(QDF_USER, &qd_a->qd_flags) !=
- !test_bit(QDF_USER, &qd_b->qd_flags)) {
- if (test_bit(QDF_USER, &qd_a->qd_flags))
- ret = -1;
- else
- ret = 1;
- } else {
- if (qd_a->qd_id < qd_b->qd_id)
- ret = -1;
- else if (qd_a->qd_id > qd_b->qd_id)
- ret = 1;
- }
-
- return ret;
-}
-
-/**
- * do_quota_sync - Sync a bunch quota changes to the quota file
- * @sdp: the filesystem
- * @qda: an array of struct gfs_quota_data structures to be synced
- * @num_qd: the number of elements in @qda
- *
- * Returns: errno
- */
-
-static int
-do_quota_sync(struct gfs_sbd *sdp, struct gfs_quota_data **qda,
- unsigned int num_qd)
-{
- struct gfs_inode *ip = sdp->sd_qinode;
- struct gfs_alloc *al = NULL;
- struct gfs_holder i_gh, *ghs;
- struct gfs_quota q;
- char buf[sizeof(struct gfs_quota)];
- uint64_t offset;
- unsigned int qx, x;
- int ar;
- unsigned int nalloc = 0;
- unsigned int data_blocks, ind_blocks;
- int error;
-
- gfs_write_calc_reserv(ip, sizeof(struct gfs_quota), &data_blocks,
- &ind_blocks);
-
- ghs = kmalloc(num_qd * sizeof(struct gfs_holder), GFP_KERNEL);
- if (!ghs)
- return -ENOMEM;
-
- gfs_sort(qda, num_qd, sizeof (struct gfs_quota_data *), sort_qd);
- for (qx = 0; qx < num_qd; qx++) {
- error = gfs_glock_nq_init(qda[qx]->qd_gl,
- LM_ST_EXCLUSIVE,
- GL_NOCACHE, &ghs[qx]);
- if (error)
- goto fail;
- }
-
- error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
- if (error)
- goto fail;
-
- for (x = 0; x < num_qd; x++) {
- offset = (2 * (uint64_t)qda[x]->qd_id +
- ((test_bit(QDF_USER, &qda[x]->qd_flags)) ? 0 : 1)) *
- sizeof(struct gfs_quota);
-
- error = gfs_write_alloc_required(ip, offset,
- sizeof(struct gfs_quota),
- &ar);
- if (error)
- goto fail_gunlock;
-
- if (ar)
- nalloc++;
- }
-
- if (nalloc) {
- al = gfs_alloc_get(ip);
-
- error =
- gfs_quota_hold_m(ip, NO_QUOTA_CHANGE,
- NO_QUOTA_CHANGE);
- if (error)
- goto fail_alloc;
-
- al->al_requested_meta = nalloc * (data_blocks + ind_blocks);
-
- error = gfs_inplace_reserve(ip);
- if (error)
- goto fail_qs;
-
- /* Trans may require:
- two (journaled) data blocks, a dinode block, RG bitmaps to allocate from,
- indirect blocks, and a quota block */
-
- error = gfs_trans_begin(sdp,
- 1 + al->al_rgd->rd_ri.ri_length +
- num_qd * data_blocks +
- nalloc * ind_blocks,
- gfs_struct2blk(sdp, num_qd + 2,
- sizeof(struct gfs_quota_tag)));
- if (error)
- goto fail_ipres;
- } else {
- /* Trans may require:
- Data blocks, a dinode block, and quota blocks */
-
- error = gfs_trans_begin(sdp,
- 1 + data_blocks * num_qd,
- gfs_struct2blk(sdp, num_qd,
- sizeof(struct gfs_quota_tag)));
- if (error)
- goto fail_gunlock;
- }
-
- for (x = 0; x < num_qd; x++) {
- offset = (2 * (uint64_t)qda[x]->qd_id +
- ((test_bit(QDF_USER, &qda[x]->qd_flags)) ? 0 : 1)) *
- sizeof(struct gfs_quota);
-
- /* The quota file may not be a multiple of sizeof(struct gfs_quota) bytes. */
- memset(buf, 0, sizeof(struct gfs_quota));
-
- error = gfs_internal_read(ip, buf, offset,
- sizeof(struct gfs_quota));
- if (error < 0)
- goto fail_end_trans;
-
- gfs_quota_in(&q, buf);
- q.qu_value += qda[x]->qd_change_sync;
- gfs_quota_out(&q, buf);
-
- error = gfs_internal_write(ip, buf, offset,
- sizeof(struct gfs_quota));
- if (error < 0)
- goto fail_end_trans;
- else if (error != sizeof(struct gfs_quota)) {
- error = -EIO;
- goto fail_end_trans;
- }
-
- if (test_bit(QDF_USER, &qda[x]->qd_flags))
- gfs_trans_add_quota(sdp, -qda[x]->qd_change_sync,
- qda[x]->qd_id, NO_QUOTA_CHANGE);
- else
- gfs_trans_add_quota(sdp, -qda[x]->qd_change_sync,
- NO_QUOTA_CHANGE, qda[x]->qd_id);
-
- memset(&qda[x]->qd_qb, 0, sizeof(struct gfs_quota_lvb));
- qda[x]->qd_qb.qb_magic = GFS_MAGIC;
- qda[x]->qd_qb.qb_limit = q.qu_limit;
- qda[x]->qd_qb.qb_warn = q.qu_warn;
- qda[x]->qd_qb.qb_value = q.qu_value;
-
- gfs_quota_lvb_out(&qda[x]->qd_qb, qda[x]->qd_gl->gl_lvb);
- }
-
- gfs_trans_end(sdp);
-
- if (nalloc) {
- gfs_assert_warn(sdp, al->al_alloced_meta);
- gfs_inplace_release(ip);
- gfs_quota_unhold_m(ip);
- gfs_alloc_put(ip);
- }
-
- gfs_glock_dq_uninit(&i_gh);
-
- for (x = 0; x < num_qd; x++)
- gfs_glock_dq_uninit(&ghs[x]);
-
- kfree(ghs);
-
- gfs_log_flush_glock(ip->i_gl);
-
- return 0;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail_ipres:
- if (nalloc)
- gfs_inplace_release(ip);
-
- fail_qs:
- if (nalloc)
- gfs_quota_unhold_m(ip);
-
- fail_alloc:
- if (nalloc)
- gfs_alloc_put(ip);
-
- fail_gunlock:
- gfs_glock_dq_uninit(&i_gh);
-
- fail:
- while (qx--)
- gfs_glock_dq_uninit(&ghs[qx]);
-
- kfree(ghs);
-
- return error;
-}
-
-/**
- * glock_q - Acquire a lock for a quota entry
- * @sdp: the filesystem
- * @qd: the quota data structure to glock
- * @force_refresh: If TRUE, always read from the quota file
- * @q_gh: the glock holder for the quota lock
- *
- * Returns: errno
- */
-
-static int
-glock_q(struct gfs_sbd *sdp, struct gfs_quota_data *qd, int force_refresh,
- struct gfs_holder *q_gh)
-{
- struct gfs_holder i_gh;
- struct gfs_quota q;
- char buf[sizeof(struct gfs_quota)];
- int error;
-
- restart:
- error = gfs_glock_nq_init(qd->qd_gl, LM_ST_SHARED, 0, q_gh);
- if (error)
- return error;
-
- gfs_quota_lvb_in(&qd->qd_qb, qd->qd_gl->gl_lvb);
-
- if (force_refresh ||
- qd->qd_qb.qb_magic != GFS_MAGIC) {
- gfs_glock_dq_uninit(q_gh);
- error = gfs_glock_nq_init(qd->qd_gl,
- LM_ST_EXCLUSIVE, GL_NOCACHE,
- q_gh);
- if (error)
- return error;
-
- error = gfs_glock_nq_init(sdp->sd_qinode->i_gl,
- LM_ST_SHARED, 0,
- &i_gh);
- if (error)
- goto fail;
-
- memset(buf, 0, sizeof(struct gfs_quota));
-
- error = gfs_internal_read(sdp->sd_qinode, buf,
- (2 * (uint64_t)qd->qd_id +
- ((test_bit(QDF_USER, &qd->qd_flags)) ? 0 : 1)) *
- sizeof(struct gfs_quota),
- sizeof(struct gfs_quota));
- if (error < 0)
- goto fail_gunlock;
-
- gfs_glock_dq_uninit(&i_gh);
-
- gfs_quota_in(&q, buf);
-
- memset(&qd->qd_qb, 0, sizeof(struct gfs_quota_lvb));
- qd->qd_qb.qb_magic = GFS_MAGIC;
- qd->qd_qb.qb_limit = q.qu_limit;
- qd->qd_qb.qb_warn = q.qu_warn;
- qd->qd_qb.qb_value = q.qu_value;
-
- gfs_quota_lvb_out(&qd->qd_qb, qd->qd_gl->gl_lvb);
-
- gfs_glock_dq_uninit(q_gh);
- force_refresh = FALSE;
- goto restart;
- }
-
- return 0;
-
- fail_gunlock:
- gfs_glock_dq_uninit(&i_gh);
-
- fail:
- gfs_glock_dq_uninit(q_gh);
-
- return error;
-}
-
-/**
- * gfs_quota_hold_m - Hold the quota structures for up to 4 IDs
- * @ip: Two of the IDs are the UID and GID from this file
- * @uid: a UID or the constant NO_QUOTA_CHANGE
- * @gid: a GID or the constant NO_QUOTA_CHANGE
- *
- * The struct gfs_quota_data structures representing the locks are
- * stored in the ip->i_alloc->al_qd array.
- *
- * Returns: errno
- */
-
-int
-gfs_quota_hold_m(struct gfs_inode *ip, uint32_t uid, uint32_t gid)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = ip->i_alloc;
- unsigned int x = 0;
- int error;
-
- if (gfs_assert_warn(sdp, !al->al_qd_num &&
- !test_bit(GIF_QD_LOCKED, &ip->i_flags)))
- return -EIO;
-
- if (!gfs_tune_get(sdp, gt_quota_account))
- return 0;
-
- error = gfs_quota_get(sdp, TRUE, ip->i_di.di_uid,
- CREATE, &al->al_qd[x]);
- if (error)
- goto fail;
- x++;
-
- error = gfs_quota_get(sdp, FALSE, ip->i_di.di_gid,
- CREATE, &al->al_qd[x]);
- if (error)
- goto fail;
- x++;
-
- if (uid != NO_QUOTA_CHANGE) {
- error = gfs_quota_get(sdp, TRUE, uid,
- CREATE, &al->al_qd[x]);
- if (error)
- goto fail;
- x++;
- }
-
- if (gid != NO_QUOTA_CHANGE) {
- error = gfs_quota_get(sdp, FALSE, gid,
- CREATE, &al->al_qd[x]);
- if (error)
- goto fail;
- x++;
- }
-
- al->al_qd_num = x;
-
- return 0;
-
- fail:
- if (x) {
- al->al_qd_num = x;
- gfs_quota_unhold_m(ip);
- }
-
- return error;
-}
-
-/**
- * gfs_quota_unhold_m - throw away some quota locks
- * @ip: the inode who's ip->i_alloc->al_qd array holds the structures
- *
- */
-
-void
-gfs_quota_unhold_m(struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = ip->i_alloc;
- unsigned int x;
-
- gfs_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags));
-
- for (x = 0; x < al->al_qd_num; x++) {
- gfs_quota_put(sdp, al->al_qd[x]);
- al->al_qd[x] = NULL;
- }
- al->al_qd_num = 0;
-}
-
-/**
- * gfs_quota_lock_m - Acquire the quota locks for up to 4 IDs
- * @ip: Two of the IDs are the UID and GID from this file
- * @uid: a UID or the constant NO_QUOTA_CHANGE
- * @gid: a GID or the constant NO_QUOTA_CHANGE
- *
- * The struct gfs_quota_data structures representing the locks are
- * stored in the ip->i_alloc->al_qd array.
- *
- * Returns: errno
- */
-
-int
-gfs_quota_lock_m(struct gfs_inode *ip, uint32_t uid, uint32_t gid)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = ip->i_alloc;
- unsigned int x;
- int error;
-
- gfs_quota_hold_m(ip, uid, gid);
-
- if (!gfs_tune_get(sdp, gt_quota_enforce))
- return 0;
- if (capable(CAP_SYS_RESOURCE))
- return 0;
-
- gfs_sort(al->al_qd, al->al_qd_num,
- sizeof(struct gfs_quota_data *), sort_qd);
-
- for (x = 0; x < al->al_qd_num; x++) {
- error = glock_q(sdp, al->al_qd[x], FALSE, &al->al_qd_ghs[x]);
- if (error)
- goto fail;
- }
-
- set_bit(GIF_QD_LOCKED, &ip->i_flags);
-
- return 0;
-
- fail:
- while (x--)
- gfs_glock_dq_uninit(&al->al_qd_ghs[x]);
-
- return error;
-}
-
-/**
- * gfs_quota_unlock_m - drop some quota locks
- * @ip: the inode who's ip->i_alloc->al_qd array holds the locks
- *
- */
-
-void
-gfs_quota_unlock_m(struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = ip->i_alloc;
- struct gfs_quota_data *qd, *qda[4];
- int64_t value;
- unsigned int count = 0;
- unsigned int x;
- int do_sync;
-
- if (!test_and_clear_bit(GIF_QD_LOCKED, &ip->i_flags))
- goto out;
-
- for (x = 0; x < al->al_qd_num; x++) {
- qd = al->al_qd[x];
-
- spin_lock(&sdp->sd_quota_lock);
- value = qd->qd_change_new + qd->qd_change_ic;
- spin_unlock(&sdp->sd_quota_lock);
-
- do_sync = TRUE;
- if (!qd->qd_qb.qb_limit)
- do_sync = FALSE;
- else if (qd->qd_qb.qb_value >= (int64_t)qd->qd_qb.qb_limit)
- do_sync = FALSE;
- else {
- struct gfs_tune *gt = &sdp->sd_tune;
- unsigned int num, den;
- int64_t v;
-
- spin_lock(>->gt_spin);
- num = gt->gt_quota_scale_num;
- den = gt->gt_quota_scale_den;
- spin_unlock(>->gt_spin);
-
- v = value * gfs_num_journals(sdp) * num;
- do_div(v, den);
- v += qd->qd_qb.qb_value;
- if (v < (int64_t)qd->qd_qb.qb_limit)
- do_sync = FALSE;
- }
-
- gfs_glock_dq_uninit(&al->al_qd_ghs[x]);
-
- if (do_sync) {
- gfs_log_flush(sdp);
- if (quota_trylock(sdp, qd))
- qda[count++] = qd;
- }
- }
-
- if (count) {
- do_quota_sync(sdp, qda, count);
-
- for (x = 0; x < count; x++)
- quota_unlock(sdp, qda[x]);
- }
-
- out:
- gfs_quota_unhold_m(ip);
-}
-
-/**
- * print_quota_message - print a message to the user's tty about quotas
- * @sdp: the filesystem
- * @qd: the quota ID that the message is about
- * @type: the type of message ("exceeded" or "warning")
- *
- * Returns: errno
- */
-
-static int
-print_quota_message(struct gfs_sbd *sdp, struct gfs_quota_data *qd, char *type)
-{
- struct tty_struct *tty;
- char *line;
- int len;
-
- line = kmalloc(256, GFP_KERNEL);
- if (!line)
- return -ENOMEM;
-
- len = snprintf(line, 256, "GFS: fsid=%s: quota %s for %s %u\r\n",
- sdp->sd_fsname, type,
- (test_bit(QDF_USER, &qd->qd_flags)) ? "user" : "group",
- qd->qd_id);
-
- if (current->signal) {
- tty = current->signal->tty;
- if (tty && tty->ops->write)
- tty->ops->write(tty, line, len);
- }
-
- kfree(line);
-
- return 0;
-}
-
-/**
- * gfs_quota_check - Check to see if a block allocation is possible
- * @ip: the inode who's ip->i_res.ir_qd array holds the quota locks
- * @uid: the UID the block is allocated for
- * @gid: the GID the block is allocated for
- *
- */
-
-int
-gfs_quota_check(struct gfs_inode *ip, uint32_t uid, uint32_t gid)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = ip->i_alloc;
- struct gfs_quota_data *qd;
- int64_t value;
- unsigned int x;
- int error = 0;
-
- if (!al)
- return 0;
-
- if (!gfs_tune_get(sdp, gt_quota_enforce))
- return 0;
-
- for (x = 0; x < al->al_qd_num; x++) {
- qd = al->al_qd[x];
-
- if (!((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) ||
- (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))))
- continue;
-
- spin_lock(&sdp->sd_quota_lock);
- value = qd->qd_change_new + qd->qd_change_ic;
- spin_unlock(&sdp->sd_quota_lock);
- value += qd->qd_qb.qb_value;
-
- if (qd->qd_qb.qb_limit && (int64_t)qd->qd_qb.qb_limit < value) {
- print_quota_message(sdp, qd, "exceeded");
- error = -EDQUOT;
- break;
- } else if (qd->qd_qb.qb_warn &&
- (int64_t)qd->qd_qb.qb_warn < value &&
- time_after_eq(jiffies,
- qd->qd_last_warn +
- gfs_tune_get(sdp, gt_quota_warn_period) * HZ)) {
- error = print_quota_message(sdp, qd, "warning");
- qd->qd_last_warn = jiffies;
- }
- }
-
- return error;
-}
-
-/**
- * gfs_quota_sync - Sync quota changes to the quota file
- * @sdp: the filesystem
- *
- * Returns: errno
- */
-
-int
-gfs_quota_sync(struct gfs_sbd *sdp)
-{
- struct gfs_quota_data **qda;
- unsigned int max_qd = gfs_tune_get(sdp, gt_quota_simul_sync);
- unsigned int num_qd;
- unsigned int x;
- int error = 0;
-
- sdp->sd_quota_sync_gen++;
-
- qda = kmalloc(max_qd * sizeof(struct gfs_quota_data *), GFP_KERNEL);
- if (!qda)
- return -ENOMEM;
- memset(qda, 0, max_qd * sizeof(struct gfs_quota_data *));
-
- do {
- num_qd = 0;
-
- for (;;) {
- qda[num_qd] = quota_find(sdp);
- if (!qda[num_qd])
- break;
-
- if (++num_qd == max_qd)
- break;
- }
-
- if (num_qd) {
- error = do_quota_sync(sdp, qda, num_qd);
- if (!error)
- for (x = 0; x < num_qd; x++)
- qda[x]->qd_sync_gen =
- sdp->sd_quota_sync_gen;
-
- for (x = 0; x < num_qd; x++)
- quota_unlock(sdp, qda[x]);
- }
- }
- while (!error && num_qd == max_qd);
-
- kfree(qda);
-
- return error;
-}
-
-/**
- * gfs_quota_refresh - Refresh the LVB for a given quota ID
- * @sdp: the filesystem
- * @user:
- * @id:
- *
- * Returns: errno
- */
-
-int
-gfs_quota_refresh(struct gfs_sbd *sdp, int user, uint32_t id)
-{
- struct gfs_quota_data *qd;
- struct gfs_holder q_gh;
- int error;
-
- error = gfs_quota_get(sdp, user, id, CREATE, &qd);
- if (error)
- return error;
-
- error = glock_q(sdp, qd, TRUE, &q_gh);
- if (!error)
- gfs_glock_dq_uninit(&q_gh);
-
- gfs_quota_put(sdp, qd);
-
- return error;
-}
-
-/**
- * gfs_quota_read - Read the info a given quota ID
- * @sdp: the filesystem
- * @user:
- * @id:
- * @q:
- *
- * Returns: errno
- */
-
-int
-gfs_quota_read(struct gfs_sbd *sdp, int user, uint32_t id,
- struct gfs_quota *q)
-{
- struct gfs_quota_data *qd;
- struct gfs_holder q_gh;
- int error;
-
- if (((user) ? (id != current_fsuid()) : (!in_group_p(id))) &&
- !capable(CAP_SYS_ADMIN))
- return -EACCES;
-
- error = gfs_quota_get(sdp, user, id, CREATE, &qd);
- if (error)
- return error;
-
- error = glock_q(sdp, qd, FALSE, &q_gh);
- if (error)
- goto out;
-
- memset(q, 0, sizeof(struct gfs_quota));
- q->qu_limit = qd->qd_qb.qb_limit;
- q->qu_warn = qd->qd_qb.qb_warn;
- q->qu_value = qd->qd_qb.qb_value;
-
- spin_lock(&sdp->sd_quota_lock);
- q->qu_value += qd->qd_change_new + qd->qd_change_ic;
- spin_unlock(&sdp->sd_quota_lock);
-
- gfs_glock_dq_uninit(&q_gh);
-
- out:
- gfs_quota_put(sdp, qd);
-
- return error;
-}
diff --git a/gfs-kernel/src/gfs/quota.h b/gfs-kernel/src/gfs/quota.h
deleted file mode 100644
index 62620ec..0000000
--- a/gfs-kernel/src/gfs/quota.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __QUOTA_DOT_H__
-#define __QUOTA_DOT_H__
-
-#define NO_QUOTA_CHANGE ((uint32_t)-1)
-
-int gfs_quota_get(struct gfs_sbd *sdp, int user, uint32_t id, int create,
- struct gfs_quota_data **qdp);
-void gfs_quota_hold(struct gfs_sbd *sdp, struct gfs_quota_data *qd);
-void gfs_quota_put(struct gfs_sbd *sdp, struct gfs_quota_data *qd);
-
-int gfs_quota_merge(struct gfs_sbd *sdp, struct gfs_quota_tag *tag);
-void gfs_quota_scan(struct gfs_sbd *sdp);
-void gfs_quota_cleanup(struct gfs_sbd *sdp);
-
-int gfs_quota_hold_m(struct gfs_inode *ip, uint32_t uid, uint32_t gid);
-void gfs_quota_unhold_m(struct gfs_inode *ip);
-
-int gfs_quota_lock_m(struct gfs_inode *ip, uint32_t uid, uint32_t gid);
-void gfs_quota_unlock_m(struct gfs_inode *ip);
-
-int gfs_quota_check(struct gfs_inode *ip, uint32_t uid, uint32_t gid);
-
-int gfs_quota_sync(struct gfs_sbd *sdp);
-int gfs_quota_refresh(struct gfs_sbd *sdp, int user, uint32_t id);
-int gfs_quota_read(struct gfs_sbd *sdp, int user, uint32_t id,
- struct gfs_quota *q);
-
-#endif /* __QUOTA_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/recovery.c b/gfs-kernel/src/gfs/recovery.c
deleted file mode 100644
index d014272..0000000
--- a/gfs-kernel/src/gfs/recovery.c
+++ /dev/null
@@ -1,780 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "dio.h"
-#include "glock.h"
-#include "glops.h"
-#include "lm.h"
-#include "lops.h"
-#include "recovery.h"
-
-#define bn2seg(bn) (((uint32_t)((bn) - jdesc->ji_addr)) / sdp->sd_sb.sb_seg_size)
-#define seg2bn(seg) ((seg) * sdp->sd_sb.sb_seg_size + jdesc->ji_addr)
-
-struct dirty_j {
- struct list_head dj_list;
- unsigned int dj_jid;
- struct gfs_jindex dj_desc;
-};
-
-/**
- * gfs_add_dirty_j - add a jid to the list of dirty journals
- * @sdp: the filesystem
- * @jid: the journal ID number
- *
- */
-
-void
-gfs_add_dirty_j(struct gfs_sbd *sdp, unsigned int jid)
-{
- struct dirty_j *dj;
-
- dj = gmalloc(sizeof(struct dirty_j));
- memset(dj, 0, sizeof(struct dirty_j));
-
- dj->dj_jid = jid;
-
- spin_lock(&sdp->sd_dirty_j_lock);
- list_add(&dj->dj_list, &sdp->sd_dirty_j);
- spin_unlock(&sdp->sd_dirty_j_lock);
-}
-
-/**
- * get_dirty_j - return a dirty journal from the list
- * @sdp: the filesystem
- *
- * Returns: a struct dirty_j or NULL
- */
-
-static struct dirty_j *
-get_dirty_j(struct gfs_sbd *sdp)
-{
- struct dirty_j *dj = NULL;
-
- spin_lock(&sdp->sd_dirty_j_lock);
- if (!list_empty(&sdp->sd_dirty_j)) {
- dj = list_entry(sdp->sd_dirty_j.prev, struct dirty_j, dj_list);
- list_del(&dj->dj_list);
- }
- spin_unlock(&sdp->sd_dirty_j_lock);
-
- return dj;
-}
-
-/**
- * gfs_clear_dirty_j - destroy the list of dirty journals
- * @sdp: the filesystem
- *
- */
-
-void
-gfs_clear_dirty_j(struct gfs_sbd *sdp)
-{
- struct dirty_j *dj;
- for (;;) {
- dj = get_dirty_j(sdp);
- if (!dj)
- break;
- kfree(dj);
- }
-}
-
-/**
- * gfs_log_header - read the log header for a given segment
- * @sdp: the filesystem
- * @jdesc: the journal
- * @gl: the journal's glock
- * @seg: the segment to look at
- * @lh: the log header to return
- *
- * Read the log header for a given segement in a given journal. Do a few
- * sanity checks on it.
- *
- * Returns: 0 on success, 1 if the header was invalid or incomplete and, errno on error
- */
-
-static int
-get_log_header(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, uint32_t seg, struct gfs_log_header *lh)
-{
- struct buffer_head *bh;
- struct gfs_log_header lh2;
- int error;
-
- error = gfs_dread(gl, seg2bn(seg), DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
-
- gfs_log_header_in(lh, bh->b_data);
- gfs_log_header_in(&lh2,
- bh->b_data + GFS_BASIC_BLOCK -
- sizeof(struct gfs_log_header));
-
- brelse(bh);
-
- if (memcmp(lh, &lh2, sizeof(struct gfs_log_header)) != 0 ||
- lh->lh_header.mh_magic != GFS_MAGIC ||
- lh->lh_header.mh_type != GFS_METATYPE_LH)
- error = 1;
-
- return error;
-}
-
-/**
- * find_good_lh - find a good log header
- * @sdp: the filesystem
- * @jdesc: the journal
- * @gl: the journal's glock
- * @seg: the segment to start searching from (it's also filled in with a new value.)
- * @lh: the log header to fill in
- * @forward: if true search forward in the log, else search backward
- *
- * Call get_log_header() to get a log header for a segment, but if the
- * segment is bad, either scan forward or backward until we find a good one.
- *
- * Returns: errno
- */
-
-static int
-find_good_lh(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, uint32_t *seg, struct gfs_log_header *lh,
- int forward)
-{
- int error;
- uint32_t orig_seg = *seg;
-
- for (;;) {
- error = get_log_header(sdp, jdesc, gl, *seg, lh);
- if (error <= 0)
- return error;
-
- if (forward) {
- if (++*seg == jdesc->ji_nsegment)
- *seg = 0;
- } else {
- if ((*seg)-- == 0)
- *seg = jdesc->ji_nsegment - 1;
- }
-
- if (*seg == orig_seg) {
- gfs_consist(sdp);
- return -EIO;
- }
- }
-}
-
-/**
- * verify_jhead - make sure we've found the head of the log
- * @sdp: the filesystem
- * @jdesc: the journal
- * @gl: the journal's glock
- * @head: this is filled in with the log descriptor of the head
- *
- * At this point, seg and lh should be either the head of the log or just
- * before. Scan forward until we find the head.
- *
- * Returns: errno
- */
-
-static int
-verify_jhead(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, struct gfs_log_header *head)
-{
- struct gfs_log_header lh;
- uint32_t seg;
- int error;
-
- seg = bn2seg(head->lh_first);
-
- for (;;) {
- if (++seg == jdesc->ji_nsegment)
- seg = 0;
-
- error = get_log_header(sdp, jdesc, gl, seg, &lh);
- if (error < 0)
- return error;
-
- if (error == 1)
- continue;
- if (lh.lh_sequence == head->lh_sequence)
- continue;
-
- if (lh.lh_sequence < head->lh_sequence)
- break;
-
- memcpy(head, &lh, sizeof(struct gfs_log_header));
- }
-
- return 0;
-}
-
-/**
- * gfs_find_jhead - find the head of a log
- * @sdp: the filesystem
- * @jdesc: the journal
- * @gl: the journal's glock
- * @head: the log descriptor for the head of the log is returned here
- *
- * Do a binary search of a journal and find the valid log entry with the
- * highest sequence number. (i.e. the log head)
- *
- * Returns: errno
- */
-
-int
-gfs_find_jhead(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, struct gfs_log_header *head)
-{
- struct gfs_log_header lh;
- uint32_t seg1, seg2, seg_m;
- int error;
- uint64_t lh1_sequence;
-
- seg1 = 0;
- seg2 = jdesc->ji_nsegment - 1;
-
- for (;;) {
- seg_m = (seg1 + seg2) / 2;
-
- error = find_good_lh(sdp, jdesc, gl, &seg1, &lh, TRUE);
- if (error)
- break;
-
- if (seg1 == seg_m) {
- error = verify_jhead(sdp, jdesc, gl, &lh);
- if (unlikely(error))
- printk("GFS: verify_jhead error=%d\n", error);
- else
- memcpy(head, &lh, sizeof(struct gfs_log_header));
- break;
- }
-
- lh1_sequence = lh.lh_sequence;
-
- error = find_good_lh(sdp, jdesc, gl, &seg_m, &lh, FALSE);
- if (error)
- break;
-
- if (lh1_sequence <= lh.lh_sequence)
- seg1 = seg_m;
- else
- seg2 = seg_m;
- }
-
- return error;
-}
-
-/**
- * gfs_increment_blkno - move to the next block in a journal
- * @sdp: the filesystem
- * @jdesc: the journal
- * @gl: the journal's glock
- * @addr: the block number to increment
- * @skip_header: if this is TRUE, skip log headers
- *
- * Replace @addr with the location of the next block in the log.
- * Take care of journal wrap and skip of log header if necessary.
- *
- * Returns: errno
- */
-
-int
-gfs_increment_blkno(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, uint64_t *addr, int skip_headers)
-{
- struct gfs_log_header header;
- int error;
-
- (*addr)++;
-
- /* Handle journal wrap */
-
- if (*addr == seg2bn(jdesc->ji_nsegment))
- *addr -= jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size;
-
- gfs_start_ra(gl, *addr,
- jdesc->ji_addr +
- jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size - *addr);
-
- /* Handle landing on a header block */
-
- if (skip_headers && !do_mod(*addr, sdp->sd_sb.sb_seg_size)) {
- error = get_log_header(sdp, jdesc, gl, bn2seg(*addr), &header);
- if (error < 0)
- return error;
-
- if (error) { /* Corrupt headers here are bad */
- if (gfs_consist(sdp))
- printk("GFS: fsid=%s: *addr = %llu\n",
- sdp->sd_fsname, (unsigned long long)*addr);
- return -EIO;
- }
- if (header.lh_first == *addr) {
- if (gfs_consist(sdp))
- printk("GFS: fsid=%s: *addr = %llu\n",
- sdp->sd_fsname, (unsigned long long)*addr);
- gfs_log_header_print(&header);
- return -EIO;
- }
-
- (*addr)++;
- /* Can't wrap here */
- }
-
- return 0;
-}
-
-/**
- * foreach_descriptor - go through the active part of the log
- * @sdp: the filesystem
- * @jdesc: the journal
- * @gl: the journal's glock
- * @start: the first log header in the active region
- * @end: the last log header (don't process the contents of this entry))
- * @pass: the recovery pass
- *
- * Call a given function once for every log descriptor in the active
- * portion of the log.
- *
- * Returns: errno
- */
-
-static int
-foreach_descriptor(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, uint64_t start, uint64_t end,
- unsigned int pass)
-{
- struct gfs_log_header header;
- struct gfs_log_descriptor desc;
- struct buffer_head *bh;
- int error = 0;
-
- while (start != end) {
- if (do_mod(start, sdp->sd_sb.sb_seg_size)) {
- gfs_consist(sdp);
- return -EIO;
- }
-
- error = get_log_header(sdp, jdesc, gl, bn2seg(start), &header);
- if (error < 0)
- return error;
-
- if (error) { /* Corrupt headers here are bad */
- if (gfs_consist(sdp))
- printk("GFS: fsid=%s: start = %llu\n",
- sdp->sd_fsname, (unsigned long long)start);
- return -EIO;
- }
- if (header.lh_first != start) {
- if (gfs_consist(sdp))
- printk("GFS: fsid=%s: start = %llu\n",
- sdp->sd_fsname, (unsigned long long)start);
- gfs_log_header_print(&header);
- return -EIO;
- }
-
- start++;
-
- for (;;) {
- error = gfs_dread(gl, start, DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
-
- if (gfs_metatype_check(sdp, bh, GFS_METATYPE_LD)) {
- brelse(bh);
- return -EIO;
- }
-
- gfs_desc_in(&desc, bh->b_data);
- brelse(bh);
-
- if (desc.ld_type != GFS_LOG_DESC_LAST) {
- error = LO_SCAN_ELEMENTS(sdp, jdesc, gl, start,
- &desc, pass);
- if (error)
- return error;
-
- while (desc.ld_length--) {
- error = gfs_increment_blkno(sdp, jdesc, gl,
- &start, TRUE);
- if (error)
- return error;
- }
- } else {
- while (desc.ld_length--) {
- error = gfs_increment_blkno(sdp, jdesc, gl,
- &start,
- !!desc.ld_length);
- if (error)
- return error;
- }
-
- break;
- }
- }
- }
-
- return error;
-}
-
-/**
- * clean_journal - mark a dirty journal as being clean
- * @sdp: the filesystem
- * @jdesc: the journal
- * @gl: the journal's glock
- * @head: the head journal to start from
- *
- * Returns: errno
- */
-
-static int noinline
-clean_journal(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, struct gfs_log_header *head)
-{
- struct gfs_log_header lh;
- struct gfs_log_descriptor desc;
- struct buffer_head *bh;
- uint32_t seg;
- uint64_t blkno;
- int error;
-
- seg = bn2seg(head->lh_first);
-
- for (;;) {
- if (++seg == jdesc->ji_nsegment)
- seg = 0;
-
- error = get_log_header(sdp, jdesc, gl, seg, &lh);
- if (error < 0)
- return error;
-
- /* Rewrite corrupt header blocks */
-
- if (error == 1) {
- bh = gfs_dgetblk(gl, seg2bn(seg));
-
- gfs_prep_new_buffer(bh);
- gfs_buffer_clear(bh);
- gfs_log_header_out(head, bh->b_data);
- gfs_log_header_out(head,
- bh->b_data + GFS_BASIC_BLOCK -
- sizeof(struct gfs_log_header));
-
- error = gfs_dwrite(sdp, bh, DIO_DIRTY | DIO_START | DIO_WAIT);
- brelse(bh);
- if (error)
- return error;
- }
-
- /* Stop when we get to the end of the log. */
-
- if (lh.lh_sequence < head->lh_sequence)
- break;
- }
-
- /* Build a "last" descriptor for the transaction we are
- about to commit by writing the shutdown header. */
-
- memset(&desc, 0, sizeof(struct gfs_log_descriptor));
- desc.ld_header.mh_magic = GFS_MAGIC;
- desc.ld_header.mh_type = GFS_METATYPE_LD;
- desc.ld_header.mh_format = GFS_FORMAT_LD;
- desc.ld_type = GFS_LOG_DESC_LAST;
- desc.ld_length = 0;
-
- for (blkno = head->lh_first + 1; blkno != seg2bn(seg);) {
- if (do_mod(blkno, sdp->sd_sb.sb_seg_size))
- desc.ld_length++;
- if (++blkno == seg2bn(jdesc->ji_nsegment))
- blkno -= jdesc->ji_nsegment * sdp->sd_sb.sb_seg_size;
- }
-
- /* Write the descriptor */
-
- bh = gfs_dgetblk(gl, head->lh_first + 1);
-
- gfs_prep_new_buffer(bh);
- gfs_buffer_clear(bh);
- gfs_desc_out(&desc, bh->b_data);
-
- error = gfs_dwrite(sdp, bh, DIO_DIRTY | DIO_START | DIO_WAIT);
- brelse(bh);
- if (error)
- return error;
-
- /* Build a log header that says the journal is clean */
-
- memset(&lh, 0, sizeof(struct gfs_log_header));
- lh.lh_header.mh_magic = GFS_MAGIC;
- lh.lh_header.mh_type = GFS_METATYPE_LH;
- lh.lh_header.mh_format = GFS_FORMAT_LH;
- lh.lh_flags = GFS_LOG_HEAD_UNMOUNT;
- lh.lh_first = seg2bn(seg);
- lh.lh_sequence = head->lh_sequence + 1;
- /* Don't care about tail */
- lh.lh_last_dump = head->lh_last_dump;
-
- /* Write the header */
-
- bh = gfs_dgetblk(gl, lh.lh_first);
-
- gfs_prep_new_buffer(bh);
- gfs_buffer_clear(bh);
- gfs_log_header_out(&lh, bh->b_data);
- gfs_log_header_out(&lh,
- bh->b_data + GFS_BASIC_BLOCK -
- sizeof(struct gfs_log_header));
-
- error = gfs_dwrite(sdp, bh, DIO_DIRTY | DIO_START | DIO_WAIT);
- brelse(bh);
-
- return error;
-}
-
-/**
- * gfs_recover_journal - recover a given journal
- * @sdp: the filesystem
- * @jid: the number of the journal to recover
- * @jdesc: the struct gfs_jindex describing the journal
- * @wait: Don't return until the journal is clean (or an error is encountered)
- *
- * Acquire the journal's lock, check to see if the journal is clean, and
- * do recovery if necessary.
- *
- * Returns: errno
- */
-
-int
-gfs_recover_journal(struct gfs_sbd *sdp,
- unsigned int jid, struct gfs_jindex *jdesc,
- int wait)
-{
- struct gfs_log_header *head;
- struct gfs_holder j_gh, t_gh;
- unsigned long t;
- int error;
-
- printk("GFS: fsid=%s: jid=%u: Trying to acquire journal lock...\n",
- sdp->sd_fsname, jid);
-
- /* Acquire the journal lock so we can do recovery */
-
- error = gfs_glock_nq_num(sdp,
- jdesc->ji_addr, &gfs_meta_glops,
- LM_ST_EXCLUSIVE,
- LM_FLAG_NOEXP |
- ((wait) ? 0 : LM_FLAG_TRY) |
- GL_NOCACHE, &j_gh);
- switch (error) {
- case 0:
- break;
-
- case GLR_TRYFAILED:
- printk("GFS: fsid=%s: jid=%u: Busy\n", sdp->sd_fsname, jid);
- error = 0;
-
- default:
- goto fail;
- };
-
- printk("GFS: fsid=%s: jid=%u: Looking at journal...\n",
- sdp->sd_fsname, jid);
-
- head = kmalloc(sizeof(struct gfs_log_header), GFP_KERNEL);
- if (!head) {
- printk("GFS: fsid=%s jid=%u: Can't replay: Not enough memory",
- sdp->sd_fsname, jid);
- goto fail_gunlock;
- }
-
- error = gfs_find_jhead(sdp, jdesc, j_gh.gh_gl, head);
- if (error)
- goto fail_header;
-
- if (!(head->lh_flags & GFS_LOG_HEAD_UNMOUNT)) {
- if (test_bit(SDF_ROFS, &sdp->sd_flags)) {
- printk("GFS: fsid=%s: jid=%u: Can't replay: read-only FS\n",
- sdp->sd_fsname, jid);
- error = -EROFS;
- goto fail_header;
- }
-
- printk("GFS: fsid=%s: jid=%u: Acquiring the transaction lock...\n",
- sdp->sd_fsname, jid);
-
- t = jiffies;
-
- /* Acquire an exclusive hold on the transaction lock */
-
- error = gfs_glock_nq_init(sdp->sd_trans_gl,
- LM_ST_EXCLUSIVE,
- LM_FLAG_NOEXP |
- LM_FLAG_PRIORITY |
- GL_NOCANCEL |
- GL_NOCACHE,
- &t_gh);
- if (error)
- goto fail_header;
-
- if (test_bit(SDF_ROFS, &sdp->sd_flags)) {
- printk("GFS: fsid=%s: jid=%u: Can't replay: read-only FS\n",
- sdp->sd_fsname, jid);
- error = -EROFS;
- goto fail_gunlock_tr;
- }
-
- printk("GFS: fsid=%s: jid=%u: Replaying journal...\n",
- sdp->sd_fsname, jid);
-
- set_bit(GLF_DIRTY, &j_gh.gh_gl->gl_flags);
-
- LO_BEFORE_SCAN(sdp, jid, head, GFS_RECPASS_A1);
-
- error = foreach_descriptor(sdp, jdesc, j_gh.gh_gl,
- head->lh_tail, head->lh_first,
- GFS_RECPASS_A1);
- if (error)
- goto fail_gunlock_tr;
-
- LO_AFTER_SCAN(sdp, jid, GFS_RECPASS_A1);
-
- gfs_replay_wait(sdp);
-
- error = clean_journal(sdp, jdesc, j_gh.gh_gl, head);
- if (error)
- goto fail_gunlock_tr;
-
- gfs_glock_dq_uninit(&t_gh);
-
- t = DIV_RU(jiffies - t, HZ);
-
- printk("GFS: fsid=%s: jid=%u: Journal replayed in %lus\n",
- sdp->sd_fsname, jid, t);
- }
-
- gfs_lm_recovery_done(sdp, jid, LM_RD_SUCCESS);
-
- kfree(head);
-
- gfs_glock_dq_uninit(&j_gh);
-
- printk("GFS: fsid=%s: jid=%u: Done\n", sdp->sd_fsname, jid);
-
- return 0;
-
- fail_gunlock_tr:
- gfs_replay_wait(sdp);
- gfs_glock_dq_uninit(&t_gh);
-
- fail_header:
- kfree(head);
-
- fail_gunlock:
- gfs_glock_dq_uninit(&j_gh);
-
- printk("GFS: fsid=%s: jid=%u: %s\n",
- sdp->sd_fsname, jid, (error) ? "Failed" : "Done");
-
- fail:
- gfs_lm_recovery_done(sdp, jid, LM_RD_GAVEUP);
-
- return error;
-}
-
-/**
- * gfs_check_journals - Recover any dirty journals
- * @sdp: the filesystem
- *
- */
-
-void
-gfs_check_journals(struct gfs_sbd *sdp)
-{
- struct dirty_j *dj;
-
- for (;;) {
- dj = get_dirty_j(sdp);
- if (!dj)
- break;
-
- down(&sdp->sd_jindex_lock);
-
- if (dj->dj_jid != sdp->sd_lockstruct.ls_jid &&
- dj->dj_jid < sdp->sd_journals) {
- memcpy(&dj->dj_desc,
- sdp->sd_jindex + dj->dj_jid,
- sizeof(struct gfs_jindex));
- up(&sdp->sd_jindex_lock);
-
- gfs_recover_journal(sdp,
- dj->dj_jid, &dj->dj_desc,
- FALSE);
-
- } else {
- up(&sdp->sd_jindex_lock);
- gfs_lm_recovery_done(sdp, dj->dj_jid, LM_RD_GAVEUP);
- }
-
- kfree(dj);
- }
-}
-
-/**
- * gfs_recover_dump - recover the log elements in this machine's journal
- * @sdp: the filesystem
- *
- * Returns: errno
- */
-
-int
-gfs_recover_dump(struct gfs_sbd *sdp)
-{
- struct gfs_log_header head;
- int error;
-
- error = gfs_find_jhead(sdp, &sdp->sd_jdesc, sdp->sd_journal_gh.gh_gl,
- &head);
- if (error)
- goto fail;
-
- if (!(head.lh_flags & GFS_LOG_HEAD_UNMOUNT)) {
- gfs_consist(sdp);
- return -EIO;
- }
- if (!head.lh_last_dump)
- return error;
-
- printk("GFS: fsid=%s: Scanning for log elements...\n",
- sdp->sd_fsname);
-
- LO_BEFORE_SCAN(sdp, sdp->sd_lockstruct.ls_jid, &head, GFS_RECPASS_B1);
-
- error = foreach_descriptor(sdp, &sdp->sd_jdesc, sdp->sd_journal_gh.gh_gl,
- head.lh_last_dump, head.lh_first,
- GFS_RECPASS_B1);
- if (error)
- goto fail;
-
- LO_AFTER_SCAN(sdp, sdp->sd_lockstruct.ls_jid, GFS_RECPASS_B1);
-
- /* We need to make sure if we crash during the next log dump that
- all intermediate headers in the transaction point to the last
- log dump before the one we're making so we don't lose it. */
-
- sdp->sd_log_dump_last = head.lh_last_dump;
-
- printk("GFS: fsid=%s: Done\n", sdp->sd_fsname);
-
- return 0;
-
- fail:
- printk("GFS: fsid=%s: Failed\n", sdp->sd_fsname);
-
- return error;
-}
diff --git a/gfs-kernel/src/gfs/recovery.h b/gfs-kernel/src/gfs/recovery.h
deleted file mode 100644
index 369cb38..0000000
--- a/gfs-kernel/src/gfs/recovery.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __RECOVERY_DOT_H__
-#define __RECOVERY_DOT_H__
-
-#define GFS_RECPASS_A1 (12)
-#define GFS_RECPASS_B1 (14)
-
-void gfs_add_dirty_j(struct gfs_sbd *sdp, unsigned int jid);
-void gfs_clear_dirty_j(struct gfs_sbd *sdp);
-
-int gfs_find_jhead(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, struct gfs_log_header *head);
-int gfs_increment_blkno(struct gfs_sbd *sdp, struct gfs_jindex *jdesc,
- struct gfs_glock *gl, uint64_t *addr,
- int skip_headers);
-
-int gfs_recover_journal(struct gfs_sbd *sdp,
- unsigned int jid, struct gfs_jindex *jdesc,
- int wait);
-void gfs_check_journals(struct gfs_sbd *sdp);
-
-int gfs_recover_dump(struct gfs_sbd *sdp);
-
-#endif /* __RECOVERY_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/rgrp.c b/gfs-kernel/src/gfs/rgrp.c
deleted file mode 100644
index e0c670f..0000000
--- a/gfs-kernel/src/gfs/rgrp.c
+++ /dev/null
@@ -1,2152 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "bits.h"
-#include "dio.h"
-#include "file.h"
-#include "glock.h"
-#include "glops.h"
-#include "rgrp.h"
-#include "super.h"
-#include "trans.h"
-
-/**
- * mhc_hash: find the mhc hash bucket for a buffer
- * @bh: the buffer
- *
- * Returns: The bucket number
- */
-
-static unsigned int
-mhc_hash(struct buffer_head *bh)
-{
- uint64_t blkno;
- unsigned int h;
-
- blkno = bh->b_blocknr;
- h = gfs_hash(&blkno, sizeof(uint64_t)) & GFS_MHC_HASH_MASK;
-
- return h;
-}
-
-/**
- * mhc_trim - Throw away cached meta-headers, if there are too many of them
- * @sdp: The filesystem instance
- * @max: Max # of cached meta-headers allowed to survive
- *
- * Walk filesystem's list of cached meta-headers, in least-recently-used order,
- * and keep throwing them away until we're under the max threshold.
- */
-
-static void
-mhc_trim(struct gfs_sbd *sdp, unsigned int max)
-{
- struct gfs_meta_header_cache *mc;
-
- for (;;) {
- spin_lock(&sdp->sd_mhc_lock);
- if (list_empty(&sdp->sd_mhc_single)) {
- spin_unlock(&sdp->sd_mhc_lock);
- return;
- } else {
- mc = list_entry(sdp->sd_mhc_single.prev,
- struct gfs_meta_header_cache,
- mc_list_single);
- list_del(&mc->mc_list_hash);
- list_del(&mc->mc_list_single);
- list_del(&mc->mc_list_rgd);
- spin_unlock(&sdp->sd_mhc_lock);
-
- kmem_cache_free(gfs_mhc_cachep, mc);
- atomic_dec(&sdp->sd_mhc_count);
-
- if (atomic_read(&sdp->sd_mhc_count) <= max)
- return;
- }
- }
-}
-
-/**
- * gfs_mhc_add - add buffer(s) to the cache of metadata headers
- * @rgd: Resource Group in which the buffered block(s) reside
- * @bh: an array of buffer_head pointers
- * @num: the number of bh pointers in the array
- *
- * Increment each meta-header's generation # by 2.
- * Alloc and add each gfs_meta-header_cache to 3 lists/caches:
- * Filesystem's meta-header cache (hash)
- * Filesystem's list of cached meta-headers
- * Resource Group's list of cached meta-headers
- * If we now have too many cached, throw some older ones away
- */
-
-void
-gfs_mhc_add(struct gfs_rgrpd *rgd,
- struct buffer_head **bh, unsigned int num)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- unsigned int x;
-
- for (x = 0; x < num; x++) {
- struct gfs_meta_header_cache *mc;
- struct list_head *head;
- uint64_t gen;
-
- if (gfs_meta_check(sdp, bh[x]))
- return;
-
- mc = kmem_cache_alloc(gfs_mhc_cachep, GFP_KERNEL);
- if (!mc)
- return;
- memset(mc, 0, sizeof(struct gfs_meta_header_cache));
-
- mc->mc_block = bh[x]->b_blocknr;
- memcpy(&mc->mc_mh, bh[x]->b_data,
- sizeof(struct gfs_meta_header));
-
- gen = gfs64_to_cpu(mc->mc_mh.mh_generation) + 2;
- mc->mc_mh.mh_generation = cpu_to_gfs64(gen);
-
- head = &sdp->sd_mhc[mhc_hash(bh[x])];
-
- spin_lock(&sdp->sd_mhc_lock);
- list_add(&mc->mc_list_hash, head);
- list_add(&mc->mc_list_single, &sdp->sd_mhc_single);
- list_add(&mc->mc_list_rgd, &rgd->rd_mhc);
- spin_unlock(&sdp->sd_mhc_lock);
-
- atomic_inc(&sdp->sd_mhc_count);
- }
-
- x = gfs_tune_get(sdp, gt_max_mhc);
-
- /* If we've got too many cached, throw some older ones away */
- if (atomic_read(&sdp->sd_mhc_count) > x)
- mhc_trim(sdp, x);
-}
-
-/**
- * gfs_mhc_fish - Try to fill in a meta buffer with meta-header from the cache
- * @sdp: the filesystem
- * @bh: the buffer to fill in
- *
- * Returns: TRUE if the buffer was cached, FALSE otherwise
- *
- * If buffer is referenced in meta-header cache (search using hash):
- * Copy the cached meta-header into the buffer (instead of reading from disk).
- * Note that only the meta-header portion of the buffer will have valid data
- * (as would be on disk), rest of buffer does *not* reflect disk contents.
- * Remove cached gfs_meta_header_cache from all cache lists, free its memory.
- */
-
-int
-gfs_mhc_fish(struct gfs_sbd *sdp, struct buffer_head *bh)
-{
- struct list_head *tmp, *head;
- struct gfs_meta_header_cache *mc;
-
- head = &sdp->sd_mhc[mhc_hash(bh)];
-
- spin_lock(&sdp->sd_mhc_lock);
-
- for (tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- mc = list_entry(tmp, struct gfs_meta_header_cache, mc_list_hash);
- if (mc->mc_block != bh->b_blocknr)
- continue;
-
- list_del(&mc->mc_list_hash);
- list_del(&mc->mc_list_single);
- list_del(&mc->mc_list_rgd);
- spin_unlock(&sdp->sd_mhc_lock);
-
- gfs_prep_new_buffer(bh);
- memcpy(bh->b_data, &mc->mc_mh,
- sizeof(struct gfs_meta_header));
-
- kmem_cache_free(gfs_mhc_cachep, mc);
- atomic_dec(&sdp->sd_mhc_count);
-
- return TRUE;
- }
-
- spin_unlock(&sdp->sd_mhc_lock);
-
- return FALSE;
-}
-
-/**
- * gfs_mhc_zap - Throw away an RG's list of cached metadata headers
- * @rgd: The resource group whose list we want to clear
- *
- * Simply throw away all cached metadata headers on RG's list,
- * and free their memory.
- */
-
-void
-gfs_mhc_zap(struct gfs_rgrpd *rgd)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- struct gfs_meta_header_cache *mc;
-
- spin_lock(&sdp->sd_mhc_lock);
-
- while (!list_empty(&rgd->rd_mhc)) {
- mc = list_entry(rgd->rd_mhc.next,
- struct gfs_meta_header_cache,
- mc_list_rgd);
-
- list_del(&mc->mc_list_hash);
- list_del(&mc->mc_list_single);
- list_del(&mc->mc_list_rgd);
- spin_unlock(&sdp->sd_mhc_lock);
-
- kmem_cache_free(gfs_mhc_cachep, mc);
- atomic_dec(&sdp->sd_mhc_count);
-
- spin_lock(&sdp->sd_mhc_lock);
- }
-
- spin_unlock(&sdp->sd_mhc_lock);
-}
-
-/**
- * depend_hash() - Turn glock number into hash bucket number
- * @formal_ino:
- *
- * Returns: The number of the corresponding hash bucket
- */
-
-static unsigned int
-depend_hash(uint64_t formal_ino)
-{
- unsigned int h;
-
- h = gfs_hash(&formal_ino, sizeof(uint64_t));
- h &= GFS_DEPEND_HASH_MASK;
-
- return h;
-}
-
-/**
- * depend_sync_one - Sync metadata (not data) for a dependency inode
- * @sdp: filesystem instance
- * @gd: dependency descriptor
- *
- * Remove dependency from superblock's hash table and rgrp's list.
- * Sync dependency inode's metadata to log and in-place location.
- */
-
-static void
-depend_sync_one(struct gfs_sbd *sdp, struct gfs_depend *gd)
-{
- struct gfs_glock *gl;
-
- spin_lock(&sdp->sd_depend_lock);
- list_del(&gd->gd_list_hash);
- spin_unlock(&sdp->sd_depend_lock);
- list_del(&gd->gd_list_rgd);
-
- gl = gfs_glock_find(sdp,
- &(struct lm_lockname){gd->gd_formal_ino,
- LM_TYPE_INODE});
- if (gl) {
- if (gl->gl_ops->go_sync)
- gl->gl_ops->go_sync(gl,
- DIO_METADATA |
- DIO_INVISIBLE);
- gfs_glock_put(gl);
- }
-
- kfree(gd);
- atomic_dec(&sdp->sd_depend_count);
-}
-
-/**
- * depend_sync_old - Sync older rgrp-dependent inodes to disk.
- * @rgd: Resource group containing dependent inodes
- *
- * Look at oldest entries in resource group's dependency list,
- * sync 'em if they're older than timeout threshold.
- */
-
-static void
-depend_sync_old(struct gfs_rgrpd *rgd)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- struct gfs_depend *gd;
-
- while (!list_empty(&rgd->rd_depend)) {
- /* Oldest entries are in prev direction */
- gd = list_entry(rgd->rd_depend.prev,
- struct gfs_depend,
- gd_list_rgd);
-
- if (time_before(jiffies,
- gd->gd_time +
- gfs_tune_get(sdp, gt_depend_secs) * HZ))
- return;
-
- depend_sync_one(sdp, gd);
- }
-}
-
-/**
- * gfs_depend_add - Add a dependent inode to rgrp's and filesystem's list
- * @rgd: Resource group containing blocks associated with inode
- * @formal_ino: inode
- *
- * Dependent inodes must be flushed to log and in-place blocks before
- * releasing an EXCLUSIVE rgrp lock.
- * Find pre-existing dependency for this inode/rgrp combination in
- * incore superblock struct's sd_depend hash table, or create a new one.
- * Either way, move or attach dependency to head of superblock's hash bucket
- * and top of rgrp's list.
- * If we create a new one, take a moment to sync older dependencies to disk.
- */
-
-void
-gfs_depend_add(struct gfs_rgrpd *rgd, uint64_t formal_ino)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- struct list_head *head, *tmp;
- struct gfs_depend *gd;
-
- head = &sdp->sd_depend[depend_hash(formal_ino)];
-
- spin_lock(&sdp->sd_depend_lock);
-
- for (tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- gd = list_entry(tmp, struct gfs_depend, gd_list_hash);
- if (gd->gd_rgd == rgd &&
- gd->gd_formal_ino == formal_ino) {
- list_move(&gd->gd_list_hash, head);
- spin_unlock(&sdp->sd_depend_lock);
- list_move(&gd->gd_list_rgd, &rgd->rd_depend);
- gd->gd_time = jiffies;
- return;
- }
- }
-
- spin_unlock(&sdp->sd_depend_lock);
-
- gd = gmalloc(sizeof(struct gfs_depend));
- memset(gd, 0, sizeof(struct gfs_depend));
-
- gd->gd_rgd = rgd;
- gd->gd_formal_ino = formal_ino;
- gd->gd_time = jiffies;
-
- spin_lock(&sdp->sd_depend_lock);
- list_add(&gd->gd_list_hash, head);
- spin_unlock(&sdp->sd_depend_lock);
- list_add(&gd->gd_list_rgd, &rgd->rd_depend);
-
- atomic_inc(&sdp->sd_depend_count);
-
- depend_sync_old(rgd);
-}
-
-/**
- * gfs_depend_sync - Sync metadata (not data) for an rgrp's dependent inodes
- * @rgd: Resource group containing the dependent inodes
- *
- * As long as this node owns an EXCLUSIVE lock on the rgrp, we can keep
- * rgrp's modified metadata blocks in buffer cache.
- *
- * When this node releases the EX lock, we must flush metadata, so other
- * nodes can read the modified content from disk.
- */
-
-void
-gfs_depend_sync(struct gfs_rgrpd *rgd)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- struct gfs_depend *gd;
-
- while (!list_empty(&rgd->rd_depend)) {
- gd = list_entry(rgd->rd_depend.next,
- struct gfs_depend,
- gd_list_rgd);
- depend_sync_one(sdp, gd);
- }
-}
-
-/**
- * rgrp_verify - Verify that a resource group is consistent
- * @sdp: the filesystem
- * @rgd: the rgrp
- *
- * Somebody should have already called gfs_glock_rg() on this RG.
- */
-
-static void
-rgrp_verify(struct gfs_rgrpd *rgd)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- struct gfs_bitmap *bits = NULL;
- uint32_t length = rgd->rd_ri.ri_length;
- uint32_t count[4], tmp;
- int buf, x;
-
- memset(count, 0, 4 * sizeof(uint32_t));
-
- /* Count # blocks in each of 4 possible allocation states */
- for (buf = 0; buf < length; buf++) {
- bits = &rgd->rd_bits[buf];
- for (x = 0; x < 4; x++)
- count[x] += gfs_bitcount(rgd,
- rgd->rd_bh[buf]->b_data +
- bits->bi_offset,
- bits->bi_len, x);
- }
-
- if (count[0] != rgd->rd_rg.rg_free) {
- if (gfs_consist_rgrpd(rgd))
- printk("GFS: fsid=%s: free data mismatch: %u != %u\n",
- sdp->sd_fsname, count[0], rgd->rd_rg.rg_free);
- return;
- }
-
- tmp = rgd->rd_ri.ri_data -
- (rgd->rd_rg.rg_usedmeta + rgd->rd_rg.rg_freemeta) -
- (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi) -
- rgd->rd_rg.rg_free;
- if (count[1] != tmp) {
- if (gfs_consist_rgrpd(rgd))
- printk("GFS: fsid=%s: used data mismatch: %u != %u\n",
- sdp->sd_fsname, count[1], tmp);
- return;
- }
-
- if (count[2] != rgd->rd_rg.rg_freemeta) {
- if (gfs_consist_rgrpd(rgd))
- printk("GFS: fsid=%s: free metadata mismatch: %u != %u\n",
- sdp->sd_fsname, count[2], rgd->rd_rg.rg_freemeta);
- return;
- }
-
- tmp = rgd->rd_rg.rg_usedmeta +
- (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi);
- if (count[3] != tmp) {
- if (gfs_consist_rgrpd(rgd))
- printk("GFS: fsid=%s: used metadata mismatch: %u != %u\n",
- sdp->sd_fsname, count[3], tmp);
- return;
- }
-}
-
-/**
- * gfs_blk2rgrpd - Find resource group for a given data/meta block number
- * @sdp: The GFS superblock
- * @n: The data block number
- *
- * Returns: The resource group, or NULL if not found
- *
- * Don't try to use this for non-allocatable block numbers (i.e. rgrp header
- * or bitmap blocks); it's for allocatable (data/meta) blocks only.
- */
-
-struct gfs_rgrpd *
-gfs_blk2rgrpd(struct gfs_sbd *sdp, uint64_t blk)
-{
- struct list_head *tmp, *head;
- struct gfs_rgrpd *rgd = NULL;
- struct gfs_rindex *ri;
-
- spin_lock(&sdp->sd_rg_mru_lock);
-
- for (head = &sdp->sd_rg_mru_list, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- rgd = list_entry(tmp, struct gfs_rgrpd, rd_list_mru);
- ri = &rgd->rd_ri;
-
- if (ri->ri_data1 <= blk && blk < ri->ri_data1 + ri->ri_data) {
- list_move(&rgd->rd_list_mru, &sdp->sd_rg_mru_list);
- spin_unlock(&sdp->sd_rg_mru_lock);
- return rgd;
- }
- }
-
- spin_unlock(&sdp->sd_rg_mru_lock);
-
- return NULL;
-}
-
-/**
- * gfs_rgrpd_get_first - get the first Resource Group in the filesystem
- * @sdp: The GFS superblock
- *
- * Returns: The first rgrp in the filesystem
- */
-
-struct gfs_rgrpd *
-gfs_rgrpd_get_first(struct gfs_sbd *sdp)
-{
- gfs_assert(sdp, !list_empty(&sdp->sd_rglist),);
- return list_entry(sdp->sd_rglist.next, struct gfs_rgrpd, rd_list);
-}
-
-/**
- * gfs_rgrpd_get_next - get the next RG
- * @rgd: A RG
- *
- * Returns: The next rgrp
- */
-
-struct gfs_rgrpd *
-gfs_rgrpd_get_next(struct gfs_rgrpd *rgd)
-{
- if (rgd->rd_list.next == &rgd->rd_sbd->sd_rglist)
- return NULL;
- return list_entry(rgd->rd_list.next, struct gfs_rgrpd, rd_list);
-}
-
-/**
- * clear_rgrpdi - Clear up rgrps
- * @sdp: The GFS superblock
- *
- */
-
-void
-clear_rgrpdi(struct gfs_sbd *sdp)
-{
- struct gfs_rgrpd *rgd;
- struct gfs_glock *gl;
-
- spin_lock(&sdp->sd_rg_forward_lock);
- sdp->sd_rg_forward = NULL;
- spin_unlock(&sdp->sd_rg_forward_lock);
-
- spin_lock(&sdp->sd_rg_recent_lock);
- while (!list_empty(&sdp->sd_rg_recent)) {
- rgd = list_entry(sdp->sd_rg_recent.next,
- struct gfs_rgrpd, rd_recent);
- list_del(&rgd->rd_recent);
- }
- spin_unlock(&sdp->sd_rg_recent_lock);
-
- while (!list_empty(&sdp->sd_rglist)) {
- rgd = list_entry(sdp->sd_rglist.next,
- struct gfs_rgrpd, rd_list);
- gl = rgd->rd_gl;
-
- list_del(&rgd->rd_list);
- list_del(&rgd->rd_list_mru);
-
- if (gl) {
- gfs_glock_force_drop(gl);
- if (atomic_read(&gl->gl_lvb_count))
- gfs_lvb_unhold(gl);
- set_gl2rgd(gl, NULL);
- gfs_glock_put(gl);
- }
-
- if (rgd->rd_bits)
- kfree(rgd->rd_bits);
- if (rgd->rd_bh)
- kfree(rgd->rd_bh);
-
- kfree(rgd);
- }
-}
-
-/**
- * gfs_clear_rgrpd - Clear up rgrps
- * @sdp: The GFS superblock
- *
- */
-
-void
-gfs_clear_rgrpd(struct gfs_sbd *sdp)
-{
- down(&sdp->sd_rindex_lock);
- clear_rgrpdi(sdp);
- up(&sdp->sd_rindex_lock);
-}
-
-/**
- * gfs_compute_bitstructs - Compute the bitmap sizes
- * @rgd: The resource group descriptor
- *
- * Calculates bitmap descriptors, one for each block that contains bitmap data
- *
- * Returns: errno
- */
-
-static int
-compute_bitstructs(struct gfs_rgrpd *rgd)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- struct gfs_bitmap *bits;
- uint32_t length = rgd->rd_ri.ri_length; /* # blocks in hdr & bitmap */
- uint32_t bytes_left, bytes;
- int x;
-
- rgd->rd_bits = kmalloc(length * sizeof(struct gfs_bitmap), GFP_KERNEL);
- if (!rgd->rd_bits)
- return -ENOMEM;
- memset(rgd->rd_bits, 0, length * sizeof(struct gfs_bitmap));
-
- bytes_left = rgd->rd_ri.ri_bitbytes;
-
- for (x = 0; x < length; x++) {
- bits = &rgd->rd_bits[x];
-
- /* small rgrp; bitmap stored completely in header block */
- if (length == 1) {
- bytes = bytes_left;
- bits->bi_offset = sizeof(struct gfs_rgrp);
- bits->bi_start = 0;
- bits->bi_len = bytes;
- /* header block */
- } else if (x == 0) {
- bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs_rgrp);
- bits->bi_offset = sizeof(struct gfs_rgrp);
- bits->bi_start = 0;
- bits->bi_len = bytes;
- /* last block */
- } else if (x + 1 == length) {
- bytes = bytes_left;
- bits->bi_offset = sizeof(struct gfs_meta_header);
- bits->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
- bits->bi_len = bytes;
- /* other blocks */
- } else {
- bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs_meta_header);
- bits->bi_offset = sizeof(struct gfs_meta_header);
- bits->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
- bits->bi_len = bytes;
- }
-
- bytes_left -= bytes;
- }
-
- if (bytes_left) {
- gfs_consist_rgrpd(rgd);
- return -EIO;
- }
- if ((rgd->rd_bits[length - 1].bi_start +
- rgd->rd_bits[length - 1].bi_len) * GFS_NBBY !=
- rgd->rd_ri.ri_data) {
- if (gfs_consist_rgrpd(rgd)) {
- gfs_rindex_print(&rgd->rd_ri);
- printk("GFS: fsid=%s: start=%u len=%u offset=%u\n",
- sdp->sd_fsname,
- rgd->rd_bits[length - 1].bi_start,
- rgd->rd_bits[length - 1].bi_len,
- rgd->rd_bits[length - 1].bi_offset);
- }
- return -EIO;
- }
-
- rgd->rd_bh = kmalloc(length * sizeof(struct buffer_head *), GFP_KERNEL);
- if (!rgd->rd_bh) {
- kfree(rgd->rd_bits);
- rgd->rd_bits = NULL;
- return -ENOMEM;
- }
- memset(rgd->rd_bh, 0, length * sizeof(struct buffer_head *));
-
- return 0;
-}
-
-/**
- * gfs_ri_update - Pull in a new resource index from the disk
- * @gl: The glock covering the rindex inode
- *
- * Returns: 0 on successful update, error code otherwise
- */
-
-static int
-gfs_ri_update(struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_rgrpd *rgd;
- char buf[sizeof(struct gfs_rindex)];
- int error;
-
- if (do_mod(ip->i_di.di_size, sizeof(struct gfs_rindex))) {
- gfs_consist_inode(ip);
- return -EIO;
- }
-
- clear_rgrpdi(sdp);
-
- for (sdp->sd_rgcount = 0;; sdp->sd_rgcount++) {
- error = gfs_internal_read(ip, buf,
- sdp->sd_rgcount *
- sizeof(struct gfs_rindex),
- sizeof(struct gfs_rindex));
- if (!error)
- break;
- if (error != sizeof(struct gfs_rindex)) {
- if (error > 0)
- error = -EIO;
- goto fail;
- }
-
- rgd = kmalloc(sizeof(struct gfs_rgrpd), GFP_KERNEL);
- error = -ENOMEM;
- if (!rgd)
- goto fail;
- memset(rgd, 0, sizeof(struct gfs_rgrpd));
-
- INIT_LIST_HEAD(&rgd->rd_mhc);
- INIT_LIST_HEAD(&rgd->rd_depend);
- rgd->rd_sbd = sdp;
-
- list_add_tail(&rgd->rd_list, &sdp->sd_rglist);
- list_add_tail(&rgd->rd_list_mru, &sdp->sd_rg_mru_list);
-
- gfs_rindex_in(&rgd->rd_ri, buf);
-
- error = compute_bitstructs(rgd);
- if (error)
- goto fail;
-
- error = gfs_glock_get(sdp, rgd->rd_ri.ri_addr, &gfs_rgrp_glops,
- CREATE, &rgd->rd_gl);
- if (error)
- goto fail;
-
- error = gfs_lvb_hold(rgd->rd_gl);
- if (error)
- goto fail;
-
- set_gl2rgd(rgd->rd_gl, rgd);
- rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
- }
-
- sdp->sd_riinode_vn = ip->i_gl->gl_vn;
-
- return 0;
-
- fail:
- clear_rgrpdi(sdp);
-
- return error;
-}
-
-/**
- * gfs_rindex_hold - Grab a lock on the rindex
- * @sdp: The GFS superblock
- * @ri_gh: the glock holder
- *
- * We grab a lock on the rindex inode to make sure that it doesn't
- * change whilst we are performing an operation. We keep this lock
- * for quite long periods of time compared to other locks. This
- * doesn't matter, since it is shared and it is very, very rarely
- * accessed in the exclusive mode (i.e. only when expanding the filesystem).
- *
- * This makes sure that we're using the latest copy of the resource index
- * special file, which might have been updated if someone expanded the
- * filesystem (via gfs_grow utility), which adds new resource groups.
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int
-gfs_rindex_hold(struct gfs_sbd *sdp, struct gfs_holder *ri_gh)
-{
- struct gfs_inode *ip = sdp->sd_riinode;
- struct gfs_glock *gl = ip->i_gl;
- int error;
-
- error = gfs_glock_nq_init(gl, LM_ST_SHARED, 0, ri_gh);
- if (error)
- return error;
-
- /* Read new copy from disk if we don't have the latest */
- if (sdp->sd_riinode_vn != gl->gl_vn) {
- down(&sdp->sd_rindex_lock);
- if (sdp->sd_riinode_vn != gl->gl_vn) {
- error = gfs_ri_update(ip);
- if (error)
- gfs_glock_dq_uninit(ri_gh);
- }
- up(&sdp->sd_rindex_lock);
- }
-
- return error;
-}
-
-/**
- * gfs_rgrp_read - Read in a RG's header and bitmaps
- * @rgd: the struct gfs_rgrpd describing the RG to read in
- *
- * Read in all of a Resource Group's header and bitmap blocks.
- * Caller must eventually call gfs_rgrp_relse() to free the bitmaps.
- *
- * Returns: errno
- */
-
-int
-gfs_rgrp_read(struct gfs_rgrpd *rgd)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- struct gfs_glock *gl = rgd->rd_gl;
- unsigned int x, length = rgd->rd_ri.ri_length;
- int error;
-
- for (x = 0; x < length; x++) {
- gfs_assert_warn(sdp, !rgd->rd_bh[x]);
- rgd->rd_bh[x] = gfs_dgetblk(gl, rgd->rd_ri.ri_addr + x);
- }
-
- for (x = 0; x < length; x++) {
- error = gfs_dreread(sdp, rgd->rd_bh[x], DIO_START);
- if (error)
- goto fail;
- }
-
- for (x = length; x--;) {
- error = gfs_dreread(sdp, rgd->rd_bh[x], DIO_WAIT);
- if (error)
- goto fail;
- if (gfs_metatype_check(sdp, rgd->rd_bh[x],
- (x) ? GFS_METATYPE_RB : GFS_METATYPE_RG)) {
- error = -EIO;
- goto fail;
- }
- }
-
- if (rgd->rd_rg_vn != gl->gl_vn) {
- gfs_rgrp_in(&rgd->rd_rg, (rgd->rd_bh[0])->b_data);
- rgd->rd_rg_vn = gl->gl_vn;
- }
-
- return 0;
-
- fail:
- for (x = 0; x < length; x++) {
- brelse(rgd->rd_bh[x]);
- rgd->rd_bh[x] = NULL;
- }
-
- return error;
-}
-
-/**
- * gfs_rgrp_relse - Release RG bitmaps read in with gfs_rgrp_read()
- * @rgd: the struct gfs_rgrpd describing the RG to read in
- *
- */
-
-void
-gfs_rgrp_relse(struct gfs_rgrpd *rgd)
-{
- int x, length = rgd->rd_ri.ri_length;
-
- for (x = 0; x < length; x++) {
- brelse(rgd->rd_bh[x]);
- rgd->rd_bh[x] = NULL;
- }
-}
-
-/**
- * gfs_rgrp_lvb_fill - copy RG usage data out of the struct gfs_rgrp into the struct gfs_rgrp_lvb
- * @rgd: the resource group data structure
- *
- */
-
-void
-gfs_rgrp_lvb_fill(struct gfs_rgrpd *rgd)
-{
- struct gfs_rgrp *rg = &rgd->rd_rg;
- struct gfs_rgrp_lvb *rb = (struct gfs_rgrp_lvb *)rgd->rd_gl->gl_lvb;
-
- rb->rb_magic = cpu_to_gfs32(GFS_MAGIC);
- rb->rb_free = cpu_to_gfs32(rg->rg_free);
- rb->rb_useddi = cpu_to_gfs32(rg->rg_useddi);
- rb->rb_freedi = cpu_to_gfs32(rg->rg_freedi);
- rb->rb_usedmeta = cpu_to_gfs32(rg->rg_usedmeta);
- rb->rb_freemeta = cpu_to_gfs32(rg->rg_freemeta);
-}
-
-/**
- * gfs_rgrp_lvb_init - Init the data of a RG LVB
- * @rgd: the resource group data structure
- *
- * Returns: errno
- */
-
-int
-gfs_rgrp_lvb_init(struct gfs_rgrpd *rgd)
-{
- struct gfs_glock *gl = rgd->rd_gl;
- struct gfs_holder rgd_gh;
- int error;
-
- error = gfs_glock_nq_init(gl, LM_ST_EXCLUSIVE, 0, &rgd_gh);
- if (!error) {
- gfs_rgrp_lvb_fill(rgd);
- gfs_glock_dq_uninit(&rgd_gh);
- }
-
- return error;
-}
-
-/**
- * gfs_alloc_get - allocate a struct gfs_alloc structure for an inode
- * @ip: the incore GFS inode structure
- *
- * Alloc and zero an in-place reservation structure,
- * and attach it to the GFS incore inode.
- *
- * FIXME: Don't use gmalloc()
- *
- * Returns: the struct gfs_alloc
- */
-
-struct gfs_alloc *
-gfs_alloc_get(struct gfs_inode *ip)
-{
- struct gfs_alloc *al = ip->i_alloc;
-
- gfs_assert_warn(ip->i_sbd, !al);
-
- al = gmalloc(sizeof(struct gfs_alloc));
- memset(al, 0, sizeof(struct gfs_alloc));
-
- ip->i_alloc = al;
-
- return al;
-}
-
-/**
- * gfs_alloc_put - throw away the struct gfs_alloc for an inode
- * @ip: the inode
- *
- */
-
-void
-gfs_alloc_put(struct gfs_inode *ip)
-{
- struct gfs_alloc *al = ip->i_alloc;
-
- if (gfs_assert_warn(ip->i_sbd, al))
- return;
-
- ip->i_alloc = NULL;
- kfree(al);
-}
-
-/**
- * try_rgrp_fit - See if a given reservation will fit in a given RG
- * @rgd: the RG data
- * @al: the struct gfs_alloc structure describing the reservation
- *
- * If there's room for the requested blocks to be allocated from the RG:
- * Sets the $al_reserved_data field in @al.
- * Sets the $al_reserved_meta field in @al.
- * Sets the $al_rgd field in @al.
- *
- * Returns: 1 on success (it fits), 0 on failure (it doesn't fit)
- */
-
-static int
-try_rgrp_fit(struct gfs_rgrpd *rgd, struct gfs_alloc *al)
-{
- uint32_t freeblks = rgd->rd_rg.rg_free;
- uint32_t freemeta = rgd->rd_rg.rg_freemeta;
- uint32_t metares = al->al_requested_meta;
- uint32_t datares = al->al_requested_data;
-
- /* First take care of the data blocks required */
-
- if (freeblks < al->al_requested_data)
- return 0;
-
- freeblks -= al->al_requested_data;
-
- /* Then take care of the dinodes */
-
- metares += al->al_requested_di;
-
- /* Then take care of the metadata blocks */
-
- while (freemeta < metares) {
- if (freeblks < GFS_META_CLUMP)
- return 0;
-
- freeblks -= GFS_META_CLUMP;
- freemeta += GFS_META_CLUMP;
-
- datares += GFS_META_CLUMP;
- }
-
- al->al_rgd = rgd;
- al->al_reserved_meta = metares;
- al->al_reserved_data = datares;
-
- return 1;
-}
-
-/**
- * recent_rgrp_first - get first RG from "recent" list
- * @sdp: The GFS superblock
- * @rglast: address of the rgrp used last
- *
- * Returns: The first rgrp in the recent list
- */
-
-static struct gfs_rgrpd *
-recent_rgrp_first(struct gfs_sbd *sdp, uint64_t rglast)
-{
- struct list_head *tmp, *head;
- struct gfs_rgrpd *rgd = NULL;
-
- spin_lock(&sdp->sd_rg_recent_lock);
-
- if (list_empty(&sdp->sd_rg_recent))
- goto out;
-
- if (!rglast)
- goto first;
-
- for (head = &sdp->sd_rg_recent, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- rgd = list_entry(tmp, struct gfs_rgrpd, rd_recent);
- if (rgd->rd_ri.ri_addr == rglast)
- goto out;
- }
-
- first:
- rgd = list_entry(sdp->sd_rg_recent.next, struct gfs_rgrpd, rd_recent);
-
- out:
- spin_unlock(&sdp->sd_rg_recent_lock);
-
- return rgd;
-}
-
-/**
- * recent_rgrp_next - get next RG from "recent" list
- * @cur_rgd: current rgrp
- * @remove:
- *
- * Returns: The next rgrp in the recent list
- */
-
-static struct gfs_rgrpd *
-recent_rgrp_next(struct gfs_rgrpd *cur_rgd, int remove)
-{
- struct gfs_sbd *sdp = cur_rgd->rd_sbd;
- struct list_head *tmp, *head;
- struct gfs_rgrpd *rgd;
-
- spin_lock(&sdp->sd_rg_recent_lock);
-
- for (head = &sdp->sd_rg_recent, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- rgd = list_entry(tmp, struct gfs_rgrpd, rd_recent);
- if (rgd == cur_rgd) {
- if (cur_rgd->rd_recent.next != head)
- rgd = list_entry(cur_rgd->rd_recent.next,
- struct gfs_rgrpd, rd_recent);
- else
- rgd = NULL;
-
- if (remove)
- list_del(&cur_rgd->rd_recent);
-
- goto out;
- }
- }
-
- rgd = NULL;
- if (!list_empty(head))
- rgd = list_entry(head->next, struct gfs_rgrpd, rd_recent);
-
- out:
- spin_unlock(&sdp->sd_rg_recent_lock);
-
- return rgd;
-}
-
-/**
- * recent_rgrp_add - add an RG to tail of "recent" list
- * @new_rgd: The rgrp to add
- *
- * Before adding, make sure that:
- * 1) it's not already on the list
- * 2) there's still room for more entries
- * The capacity limit imposed on the "recent" list is basically a node's "share"
- * of rgrps within a cluster, i.e. (total # rgrps) / (# nodes (journals))
- */
-
-static void
-recent_rgrp_add(struct gfs_rgrpd *new_rgd)
-{
- struct gfs_sbd *sdp = new_rgd->rd_sbd;
- struct list_head *tmp, *head;
- struct gfs_rgrpd *rgd = NULL;
- unsigned int count = 0;
- unsigned int max = sdp->sd_rgcount / gfs_num_journals(sdp);
-
- spin_lock(&sdp->sd_rg_recent_lock);
-
- for (head = &sdp->sd_rg_recent, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- rgd = list_entry(tmp, struct gfs_rgrpd, rd_recent);
- if (rgd == new_rgd)
- goto out;
-
- if (++count >= max)
- goto out;
- }
- new_rgd->rd_try_counter = 0;
- list_add_tail(&new_rgd->rd_recent, &sdp->sd_rg_recent);
-
- out:
- spin_unlock(&sdp->sd_rg_recent_lock);
-}
-
-/**
- * forward_rgrp_get - get an rgrp to try next from full list
- * @sdp: The GFS superblock
- *
- * Returns: The rgrp to try next
- */
-
-static struct gfs_rgrpd *
-forward_rgrp_get(struct gfs_sbd *sdp)
-{
- struct gfs_rgrpd *rgd;
- unsigned int journals = gfs_num_journals(sdp);
- unsigned int rg = 0, x;
-
- spin_lock(&sdp->sd_rg_forward_lock);
-
- rgd = sdp->sd_rg_forward;
- if (!rgd) {
- if (sdp->sd_rgcount >= journals)
- rg = sdp->sd_rgcount *
- sdp->sd_lockstruct.ls_jid /
- journals;
-
- for (x = 0, rgd = gfs_rgrpd_get_first(sdp);
- x < rg;
- x++, rgd = gfs_rgrpd_get_next(rgd))
- /* Do Nothing */;
-
- sdp->sd_rg_forward = rgd;
- }
-
- spin_unlock(&sdp->sd_rg_forward_lock);
-
- return rgd;
-}
-
-/**
- * forward_rgrp_set - set the forward rgrp pointer
- * @sdp: the filesystem
- * @rgd: The new forward rgrp
- *
- */
-
-static void
-forward_rgrp_set(struct gfs_sbd *sdp, struct gfs_rgrpd *rgd)
-{
- spin_lock(&sdp->sd_rg_forward_lock);
- sdp->sd_rg_forward = rgd;
- spin_unlock(&sdp->sd_rg_forward_lock);
-}
-
-/**
- * get_local_rgrp - Choose and lock a rgrp for allocation
- * @ip: the inode to reserve space for
- * @rgp: the chosen and locked rgrp
- *
- * Try to acquire rgrp in way which avoids contending with others.
- *
- * Returns: errno
- */
-
-static int
-get_local_rgrp(struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_rgrpd *rgd, *begin = NULL;
- struct gfs_alloc *al = ip->i_alloc;
- int flags = LM_FLAG_TRY;
- int skipped = 0;
- int loops = 0;
- int error;
- int try_flag;
- unsigned int try_threshold = gfs_tune_get(sdp, gt_rgrp_try_threshold);
-
- /* Try recently successful rgrps */
-
- rgd = recent_rgrp_first(sdp, ip->i_last_rg_alloc);
-
- while (rgd) {
- try_flag = (rgd->rd_try_counter >= try_threshold) ?
- 0: LM_FLAG_TRY;
- error = gfs_glock_nq_init(rgd->rd_gl,
- LM_ST_EXCLUSIVE, try_flag,
- &al->al_rgd_gh);
- switch (error) {
- case 0:
- if (try_rgrp_fit(rgd, al)) {
- rgd->rd_try_counter = 0;
- goto out;
- }
- gfs_glock_dq_uninit(&al->al_rgd_gh);
- rgd = recent_rgrp_next(rgd, TRUE);
- break;
-
- case GLR_TRYFAILED:
- rgd->rd_try_counter++;
- rgd = recent_rgrp_next(rgd, FALSE);
- break;
-
- default:
- return error;
- }
- }
-
- /* Go through full list of rgrps */
-
- begin = rgd = forward_rgrp_get(sdp);
-
- for (;;) {
- error = gfs_glock_nq_init(rgd->rd_gl,
- LM_ST_EXCLUSIVE, flags,
- &al->al_rgd_gh);
- switch (error) {
- case 0:
- if (try_rgrp_fit(rgd, al))
- goto out;
- gfs_glock_dq_uninit(&al->al_rgd_gh);
- break;
-
- case GLR_TRYFAILED:
- skipped++;
- break;
-
- default:
- return error;
- }
-
- rgd = gfs_rgrpd_get_next(rgd);
- if (!rgd)
- rgd = gfs_rgrpd_get_first(sdp);
-
- if (rgd == begin) {
- if (++loops >= 2 || !skipped)
- return -ENOSPC;
- flags = 0;
- }
- }
-
- out:
- ip->i_last_rg_alloc = rgd->rd_ri.ri_addr;
-
- if (begin) {
- recent_rgrp_add(rgd);
- rgd = gfs_rgrpd_get_next(rgd);
- if (!rgd)
- rgd = gfs_rgrpd_get_first(sdp);
- forward_rgrp_set(sdp, rgd);
- }
-
- return 0;
-}
-
-/**
- * gfs_inplace_reserve_i - Reserve space in the filesystem
- * @ip: the inode to reserve space for
- *
- * Acquire resource group locks to allow for the maximum allocation
- * described by "res".
- *
- * This should probably become more complex again, but for now, let's go
- * for simple (one resource group) reservations.
- *
- * Returns: errno
- */
-
-int
-gfs_inplace_reserve_i(struct gfs_inode *ip,
- char *file, unsigned int line)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = ip->i_alloc;
- int error;
-
- if (gfs_assert_warn(sdp,
- al->al_requested_di ||
- al->al_requested_data ||
- al->al_requested_meta))
- return -EINVAL;
-
- error = gfs_rindex_hold(sdp, &al->al_ri_gh);
- if (error)
- return error;
-
- error = get_local_rgrp(ip);
- if (error) {
- gfs_glock_dq_uninit(&al->al_ri_gh);
- return error;
- }
-
- gfs_depend_sync(al->al_rgd);
-
- al->al_file = file;
- al->al_line = line;
-
- return 0;
-}
-
-/**
- * gfs_inplace_release - release an inplace reservation
- * @ip: the inode the reservation was taken out on
- *
- * Release a reservation made by gfs_inplace_reserve().
- */
-
-void
-gfs_inplace_release(struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = ip->i_alloc;
-
- if (gfs_assert_warn(sdp, al->al_alloced_di <= al->al_requested_di) == -1)
- printk("GFS: fsid=%s: al_alloced_di = %u, al_requested_di = %u\n"
- "GFS: fsid=%s: al_file = %s, al_line = %u\n",
- sdp->sd_fsname, al->al_alloced_di, al->al_requested_di,
- sdp->sd_fsname, al->al_file, al->al_line);
- if (gfs_assert_warn(sdp, al->al_alloced_meta <= al->al_reserved_meta) == -1)
- printk("GFS: fsid=%s: al_alloced_meta = %u, al_reserved_meta = %u\n"
- "GFS: fsid=%s: al_file = %s, al_line = %u\n",
- sdp->sd_fsname, al->al_alloced_meta, al->al_reserved_meta,
- sdp->sd_fsname, al->al_file, al->al_line);
- if (gfs_assert_warn(sdp, al->al_alloced_data <= al->al_reserved_data) == -1)
- printk("GFS: fsid=%s: al_alloced_data = %u, al_reserved_data = %u\n"
- "GFS: fsid=%s: al_file = %s, al_line = %u\n",
- sdp->sd_fsname, al->al_alloced_data, al->al_reserved_data,
- sdp->sd_fsname, al->al_file, al->al_line);
-
- al->al_rgd = NULL;
- gfs_glock_dq_uninit(&al->al_rgd_gh);
- gfs_glock_dq_uninit(&al->al_ri_gh);
-}
-
-/**
- * gfs_get_block_type - Check a block in a RG is of given type
- * @rgd: the resource group holding the block
- * @block: the block number
- *
- * Returns: The block type (GFS_BLKST_*)
- */
-
-unsigned char
-gfs_get_block_type(struct gfs_rgrpd *rgd, uint64_t block)
-{
- struct gfs_bitmap *bits = NULL;
- uint32_t length, rgrp_block, buf_block;
- unsigned int buf;
- unsigned char type;
-
- length = rgd->rd_ri.ri_length;
- rgrp_block = block - rgd->rd_ri.ri_data1;
-
- for (buf = 0; buf < length; buf++) {
- bits = &rgd->rd_bits[buf];
- if (rgrp_block < (bits->bi_start + bits->bi_len) * GFS_NBBY)
- break;
- }
-
- gfs_assert(rgd->rd_sbd, buf < length,);
- buf_block = rgrp_block - bits->bi_start * GFS_NBBY;
-
- type = gfs_testbit(rgd,
- rgd->rd_bh[buf]->b_data + bits->bi_offset,
- bits->bi_len, buf_block);
-
- return type;
-}
-
-/**
- * blkalloc_internal - find a block in @old_state, change allocation
- * state to @new_state
- * @rgd: the resource group descriptor
- * @goal: the goal block within the RG (start here to search for avail block)
- * @old_state: GFS_BLKST_XXX the before-allocation state to find
- * @new_state: GFS_BLKST_XXX the after-allocation block state
- *
- * Walk rgrp's bitmap to find bits that represent a block in @old_state.
- * Add the found bitmap buffer to the transaction.
- * Set the found bits to @new_state to change block's allocation state.
- *
- * This function never fails, because we wouldn't call it unless we
- * know (from reservation results, etc.) that a block is available.
- *
- * Scope of @goal and returned block is just within rgrp (32-bit),
- * not the whole filesystem (64-bit).
- *
- * Returns: the block # allocated (32-bit rgrp scope)
- */
-
-static uint32_t
-blkalloc_internal(struct gfs_rgrpd *rgd,
- uint32_t goal,
- unsigned char old_state, unsigned char new_state)
-{
- struct gfs_bitmap *bits = NULL;
- uint32_t length = rgd->rd_ri.ri_length;
- uint32_t blk = 0;
- unsigned int buf, x;
-
- /* Find bitmap block that contains bits for goal block */
- for (buf = 0; buf < length; buf++) {
- bits = &rgd->rd_bits[buf];
- if (goal < (bits->bi_start + bits->bi_len) * GFS_NBBY)
- break;
- }
-
- gfs_assert(rgd->rd_sbd, buf < length,);
-
- /* Convert scope of "goal" from rgrp-wide to within found bit block */
- goal -= bits->bi_start * GFS_NBBY;
-
- /* Search (up to entire) bitmap in this rgrp for allocatable block.
- "x <= length", instead of "x < length", because we typically start
- the search in the middle of a bit block, but if we can't find an
- allocatable block anywhere else, we want to be able wrap around and
- search in the first part of our first-searched bit block. */
- for (x = 0; x <= length; x++) {
- blk = gfs_bitfit(rgd->rd_bh[buf]->b_data + bits->bi_offset,
- bits->bi_len, goal, old_state);
- if (blk != BFITNOENT)
- break;
-
- /* Try next bitmap block (wrap back to rgrp header if at end) */
- buf = (buf + 1) % length;
- bits = &rgd->rd_bits[buf];
- goal = 0;
- }
-
- if (unlikely(x > length)) {
- printk("GFS error: possible RG corruption\n");
- printk(" please run gfs_fsck after withdraw\n");
- dump_stack();
- if (gfs_assert_withdraw(rgd->rd_sbd, x <= length))
- blk = 0;
- }
-
- /* Attach bitmap buffer to trans, modify bits to do block alloc */
- gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[buf]);
- gfs_setbit(rgd,
- rgd->rd_bh[buf]->b_data + bits->bi_offset,
- bits->bi_len, blk, new_state);
-
- /* Return allocated block #, rgrp scope (32-bit) */
- return bits->bi_start * GFS_NBBY + blk;
-}
-
-/**
- * blkfree_internal - Change alloc state of given block(s)
- * @sdp: the filesystem
- * @bstart: first block (64-bit filesystem scope) of a run of contiguous blocks
- * @blen: the length of the block run (all must lie within ONE RG!)
- * @new_state: GFS_BLKST_XXX the after-allocation block state
- *
- * Returns: Resource group containing the block(s)
- *
- * Find rgrp containing @bstart.
- * For each block in run:
- * Find allocation bitmap buffer.
- * Add bitmap buffer to transaction.
- * Set bits to new state.
- * Typically used to free blocks to GFS_BLKST_FREE or GFS_BLKST_FREEMETA,
- * but @new_state can be any GFS_BLKST_XXX
- *
- */
-
-static struct gfs_rgrpd *
-blkfree_internal(struct gfs_sbd *sdp, uint64_t bstart, uint32_t blen,
- unsigned char new_state)
-{
- struct gfs_rgrpd *rgd;
- struct gfs_bitmap *bits = NULL;
- uint32_t length, rgrp_blk, buf_blk;
- unsigned int buf;
-
- /* Find rgrp */
- rgd = gfs_blk2rgrpd(sdp, bstart);
- if (!rgd) {
- if (gfs_consist(sdp))
- printk("GFS: fsid=%s: block = %llu\n",
- sdp->sd_fsname, bstart);
- return NULL;
- }
-
- length = rgd->rd_ri.ri_length;
-
- /* Convert blk # from filesystem scope (64-bit) to RG scope (32-bit) */
- rgrp_blk = bstart - rgd->rd_ri.ri_data1;
-
- while (blen--) {
- /* Find bitmap buffer for this block */
- for (buf = 0; buf < length; buf++) {
- bits = &rgd->rd_bits[buf];
- if (rgrp_blk < (bits->bi_start + bits->bi_len) * GFS_NBBY)
- break;
- }
-
- gfs_assert(rgd->rd_sbd, buf < length,);
-
- /* Find bits and set 'em */
- buf_blk = rgrp_blk - bits->bi_start * GFS_NBBY;
- rgrp_blk++;
-
- gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[buf]);
- gfs_setbit(rgd,
- rgd->rd_bh[buf]->b_data + bits->bi_offset,
- bits->bi_len, buf_blk, new_state);
- }
-
- return rgd;
-}
-
-/**
- * clump_alloc - Allocate a clump of metadata blocks
- * @rgd: the resource group in which to allocate
- * @first: returns the first block allocated
- *
- * Returns: errno
- *
- * Bitmap-allocate a clump of metadata blocks
- * Write metadata blocks to disk with dummy meta-headers
- * Add meta-headers to incore meta-header cache
- */
-
-static int
-clump_alloc(struct gfs_rgrpd *rgd, uint32_t *first)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- struct gfs_meta_header mh;
- struct buffer_head **bh;
- uint32_t goal, blk;
- unsigned int x;
- int error = 0;
-
- /* Dummy meta-header template */
- memset(&mh, 0, sizeof(struct gfs_meta_header));
- mh.mh_magic = GFS_MAGIC;
- mh.mh_type = GFS_METATYPE_NONE;
-
- /* Array of bh pointers used in several steps */
- bh = gmalloc(GFS_META_CLUMP * sizeof(struct buffer_head *));
- memset(bh, 0, GFS_META_CLUMP * sizeof(struct buffer_head *));
-
- /* Since we're looking for data blocks to change into meta blocks,
- use last alloc'd *data* (not meta) block as start point */
- goal = rgd->rd_last_alloc_data;
-
- for (x = 0; x < GFS_META_CLUMP; x++) {
- blk = blkalloc_internal(rgd, goal, GFS_BLKST_FREE,
- GFS_BLKST_FREEMETA);
- if (!x)
- *first = blk;
-
- bh[x] = gfs_dgetblk(rgd->rd_gl, rgd->rd_ri.ri_data1 + blk);
-
- gfs_prep_new_buffer(bh[x]);
-
- gfs_meta_header_out(&mh, bh[x]->b_data);
- ((struct gfs_meta_header *)bh[x]->b_data)->mh_generation = 0;
-
- /* start write of new meta-buffer to disk */
- error = gfs_dwrite(sdp, bh[x], DIO_DIRTY | DIO_START);
- if (error)
- goto out;
-
- goal = blk;
- }
-
- /* Block alloc start point for next time */
- rgd->rd_last_alloc_data = goal;
-
- /* Wait for all new meta-buffers to get on-disk */
- for (x = 0; x < GFS_META_CLUMP; x++) {
- error = gfs_dwrite(sdp, bh[x], DIO_WAIT);
- if (error)
- goto out;
- }
-
- /* Add all new meta-headers to meta-header cache */
- gfs_mhc_add(rgd, bh, GFS_META_CLUMP);
-
- gfs_assert_withdraw(sdp, rgd->rd_rg.rg_free >= GFS_META_CLUMP);
- rgd->rd_rg.rg_free -= GFS_META_CLUMP;
- rgd->rd_rg.rg_freemeta += GFS_META_CLUMP;
-
- out:
- for (x = 0; x < GFS_META_CLUMP; x++)
- if (bh[x]) {
- gfs_dwrite(sdp, bh[x], DIO_WAIT);
- brelse(bh[x]);
- }
- kfree(bh);
-
- return error;
-}
-
-/**
- * gfs_blkalloc - Allocate a data block
- * @ip: the inode to allocate the data block for
- * @block: the block allocated
- *
- */
-
-void
-gfs_blkalloc(struct gfs_inode *ip, uint64_t *block)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = ip->i_alloc;
- struct gfs_rgrpd *rgd = al->al_rgd;
- uint32_t goal, blk;
- int same;
-
- same = (rgd->rd_ri.ri_addr == ip->i_di.di_goal_rgrp);
- goal = (same) ? ip->i_di.di_goal_dblk : rgd->rd_last_alloc_data;
-
- blk = blkalloc_internal(rgd, goal,
- GFS_BLKST_FREE, GFS_BLKST_USED);
- rgd->rd_last_alloc_data = blk;
-
- if (!same) {
- ip->i_di.di_goal_rgrp = rgd->rd_ri.ri_addr;
- ip->i_di.di_goal_mblk = 0;
- }
- ip->i_di.di_goal_dblk = blk;
-
- *block = rgd->rd_ri.ri_data1 + blk;
-
- gfs_assert_withdraw(sdp, rgd->rd_rg.rg_free);
- rgd->rd_rg.rg_free--;
-
- gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]);
- gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data);
-
- al->al_alloced_data++;
-
- gfs_trans_add_quota(sdp, +1, ip->i_di.di_uid, ip->i_di.di_gid);
-
- /* total=0, free=-1, dinodes=0 */
- gfs_statfs_modify(sdp, 0, -1, 0);
-}
-
-/**
- * gfs_metaalloc - Allocate a metadata block to a file
- * @ip: the file
- * @block: the block allocated
- *
- * Returns: errno
- */
-
-int
-gfs_metaalloc(struct gfs_inode *ip, uint64_t *block)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = ip->i_alloc;
- struct gfs_rgrpd *rgd = al->al_rgd;
- uint32_t goal, blk;
- int same;
- int error;
-
- same = (rgd->rd_ri.ri_addr == ip->i_di.di_goal_rgrp);
-
- if (!rgd->rd_rg.rg_freemeta) {
- error = clump_alloc(rgd, &goal);
- if (error)
- return error;
-
- al->al_alloced_data += GFS_META_CLUMP;
- } else
- goal = (same) ? ip->i_di.di_goal_mblk : rgd->rd_last_alloc_meta;
-
- blk = blkalloc_internal(rgd, goal,
- GFS_BLKST_FREEMETA, GFS_BLKST_USEDMETA);
- rgd->rd_last_alloc_meta = blk;
-
- if (!same) {
- ip->i_di.di_goal_rgrp = rgd->rd_ri.ri_addr;
- ip->i_di.di_goal_dblk = 0;
- }
- ip->i_di.di_goal_mblk = blk;
-
- *block = rgd->rd_ri.ri_data1 + blk;
-
- gfs_assert_withdraw(sdp, rgd->rd_rg.rg_freemeta);
- rgd->rd_rg.rg_freemeta--;
- rgd->rd_rg.rg_usedmeta++;
-
- gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]);
- gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data);
-
- al->al_alloced_meta++;
-
- gfs_trans_add_quota(sdp, +1, ip->i_di.di_uid, ip->i_di.di_gid);
-
- /* total=0, free=-1, dinode=0 */
- gfs_statfs_modify(sdp, 0, -1, 0);
-
- return 0;
-}
-
-/**
- * gfs_dialloc - Allocate a dinode
- * @dip: the directory that the inode is going in
- * @block: the block (result) which this function allocates as the dinode
- * (64-bit filesystem scope)
- *
- * Returns: errno
- */
-
-int
-gfs_dialloc(struct gfs_inode *dip, uint64_t *block)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_alloc *al = dip->i_alloc;
- struct gfs_rgrpd *rgd = al->al_rgd;
- uint32_t goal, blk;
- int error = 0;
-
- if (rgd->rd_rg.rg_freemeta)
- /* pick up where we left off last time */
- goal = rgd->rd_last_alloc_meta;
- else {
- /* no free meta blocks, allocate a bunch more */
- error = clump_alloc(rgd, &goal);
- if (error)
- return error;
-
- al->al_alloced_data += GFS_META_CLUMP;
- }
-
- /* Alloc the dinode; 32-bit "blk" is block offset within rgrp */
- blk = blkalloc_internal(rgd, goal,
- GFS_BLKST_FREEMETA, GFS_BLKST_USEDMETA);
-
- /* remember where we left off, for next time */
- rgd->rd_last_alloc_meta = blk;
-
- /* convert from rgrp scope (32-bit) to filesystem scope (64-bit) */
- *block = rgd->rd_ri.ri_data1 + blk;
-
- gfs_assert_withdraw(rgd->rd_sbd, rgd->rd_rg.rg_freemeta);
- rgd->rd_rg.rg_freemeta--;
- rgd->rd_rg.rg_useddi++;
-
- /* Attach rgrp header to trans, update freemeta and useddi stats */
- gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]);
- gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data);
-
- /* Update stats in in-place reservation struct */
- al->al_alloced_di++;
- al->al_alloced_meta++;
-
- /* total=0, free=-1, dinodes=1 */
- gfs_statfs_modify(sdp, 0, -1, +1);
-
- return error;
-}
-
-/**
- * gfs_blkfree - free a contiguous run of data block(s)
- * @ip: the inode these blocks are being freed from
- * @bstart: first block (64-bit filesystem scope) of a run of contiguous blocks
- * @blen: the length of the block run (all must lie within ONE RG!)
- *
- * Bitmap-deallocate the blocks (to FREE data state), add bitmap blks to trans
- * Update rgrp alloc statistics in rgrp header, add rgrp header buf to trans
- * Update quotas, add to trans.
- */
-
-void
-gfs_blkfree(struct gfs_inode *ip, uint64_t bstart, uint32_t blen)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_rgrpd *rgd;
-
- rgd = blkfree_internal(sdp, bstart, blen, GFS_BLKST_FREE);
- if (!rgd)
- return;
-
- rgd->rd_rg.rg_free += blen;
-
- gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]);
- gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data);
-
- gfs_trans_add_quota(sdp, -(int64_t)blen,
- ip->i_di.di_uid,
- ip->i_di.di_gid);
-
- /* total=0, free=+blen, dinodes=0 */
- gfs_statfs_modify(sdp, 0, blen, 0);
-}
-
-/**
- * gfs_metafree - free a contiguous run of metadata block(s)
- * @ip: the inode these blocks are being freed from
- * @bstart: first block (64-bit filesystem scope) of a run of contiguous blocks
- * @blen: the length of the block run (all must lie within ONE RG!)
- *
- * Bitmap-deallocate the blocks (to FREEMETA state), add bitmap blks to trans.
- * Update rgrp alloc statistics in rgrp header, add rgrp header to trans.
- * Update quotas (quotas include metadata, not just data block usage),
- * add to trans.
- * Release deallocated buffers, add to meta-header cache (we save these in-core
- * so we don't need to re-read meta blocks if/when they are re-alloc'd).
- */
-
-void
-gfs_metafree(struct gfs_inode *ip, uint64_t bstart, uint32_t blen)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_rgrpd *rgd;
-
- rgd = blkfree_internal(sdp, bstart, blen, GFS_BLKST_FREEMETA);
- if (!rgd)
- return;
-
- if (rgd->rd_rg.rg_usedmeta < blen)
- gfs_consist_rgrpd(rgd);
- rgd->rd_rg.rg_usedmeta -= blen;
- rgd->rd_rg.rg_freemeta += blen;
-
- gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]);
- gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data);
-
- /* total=0, free=blen, dinode=0 */
- gfs_statfs_modify(sdp, 0, blen, 0);
-
- gfs_trans_add_quota(sdp, -(int64_t)blen,
- ip->i_di.di_uid,
- ip->i_di.di_gid);
- gfs_wipe_buffers(ip, rgd, bstart, blen);
-}
-
-/**
- * gfs_difree_uninit - free a dinode block
- * @rgd: the resource group that contains the dinode
- * @addr: the dinode address
- *
- * De-allocate the dinode to FREEMETA using block alloc bitmap.
- * Update rgrp's block usage statistics (used dinode--, free meta++).
- * Add rgrp header to transaction.
- */
-
-void
-gfs_difree_uninit(struct gfs_rgrpd *rgd, uint64_t addr)
-{
- struct gfs_rgrpd *tmp_rgd;
-
- tmp_rgd = blkfree_internal(rgd->rd_sbd, addr, 1,
- GFS_BLKST_FREEMETA);
- if (!tmp_rgd)
- return;
- gfs_assert_withdraw(rgd->rd_sbd, rgd == tmp_rgd);
-
- if (!rgd->rd_rg.rg_useddi)
- gfs_consist_rgrpd(rgd);
- rgd->rd_rg.rg_useddi--;
- rgd->rd_rg.rg_freemeta++;
-
- gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]);
- gfs_rgrp_out(&rgd->rd_rg, rgd->rd_bh[0]->b_data);
-
- /* total=0, free=1, dinodes=-1 */
- gfs_statfs_modify(rgd->rd_sbd, 0, +1, -1);
-}
-
-/**
- * gfs_difree - free a dinode block
- * @rgd: the resource group that contains the dinode
- * @ip: the inode representing the dinode to free
- *
- * Free the dinode block to FREEMETA, update rgrp's block usage stats.
- * Update quotas (quotas include metadata, not just data block usage),
- * add to trans.
- * Release deallocated buffers, add to meta-header cache (we save these in-core
- * so we don't need to re-read meta blocks if/when they are re-alloc'd).
- */
-
-void
-gfs_difree(struct gfs_rgrpd *rgd, struct gfs_inode *ip)
-{
- gfs_difree_uninit(rgd, ip->i_num.no_addr);
- gfs_trans_add_quota(ip->i_sbd, -1, ip->i_di.di_uid, ip->i_di.di_gid);
- gfs_wipe_buffers(ip, rgd, ip->i_num.no_addr, 1);
-}
-
-/**
- * gfs_rlist_add - add a RG to a list of RGs
- * @sdp: the filesystem
- * @rlist: the list of resource groups
- * @block: the block
- *
- * Figure out what RG a block belongs to and add that RG to the list
- *
- * FIXME: Don't use gmalloc()
- *
- */
-
-void
-gfs_rlist_add(struct gfs_sbd *sdp, struct gfs_rgrp_list *rlist, uint64_t block)
-{
- struct gfs_rgrpd *rgd;
- struct gfs_rgrpd **tmp;
- unsigned int new_space;
- unsigned int x;
-
- if (gfs_assert_warn(sdp, !rlist->rl_ghs))
- return;
-
- rgd = gfs_blk2rgrpd(sdp, block);
- if (!rgd) {
- if (gfs_consist(sdp))
- printk("GFS: fsid=%s: block = %llu\n",
- sdp->sd_fsname, block);
- return;
- }
-
- for (x = 0; x < rlist->rl_rgrps; x++)
- if (rlist->rl_rgd[x] == rgd)
- return;
-
- if (rlist->rl_rgrps == rlist->rl_space) {
- new_space = rlist->rl_space + 10;
-
- tmp = gmalloc(new_space * sizeof(struct gfs_rgrpd *));
-
- if (rlist->rl_rgd) {
- memcpy(tmp, rlist->rl_rgd,
- rlist->rl_space * sizeof(struct gfs_rgrpd *));
- kfree(rlist->rl_rgd);
- }
-
- rlist->rl_space = new_space;
- rlist->rl_rgd = tmp;
- }
-
- rlist->rl_rgd[rlist->rl_rgrps++] = rgd;
-}
-
-/**
- * gfs_rlist_alloc - all RGs have been added to the rlist, now allocate
- * and initialize an array of glock holders for them
- * @rlist: the list of resource groups
- * @state: the lock state to acquire the RG lock in
- * @flags: the modifier flags for the holder structures
- *
- * FIXME: Don't use gmalloc()
- *
- */
-
-void
-gfs_rlist_alloc(struct gfs_rgrp_list *rlist, unsigned int state, int flags)
-{
- unsigned int x;
-
- rlist->rl_ghs = gmalloc(rlist->rl_rgrps * sizeof(struct gfs_holder));
- for (x = 0; x < rlist->rl_rgrps; x++)
- gfs_holder_init(rlist->rl_rgd[x]->rd_gl,
- state, flags,
- &rlist->rl_ghs[x]);
-}
-
-/**
- * gfs_rlist_free - free a resource group list
- * @list: the list of resource groups
- *
- */
-
-void
-gfs_rlist_free(struct gfs_rgrp_list *rlist)
-{
- unsigned int x;
-
- if (rlist->rl_rgd)
- kfree(rlist->rl_rgd);
-
- if (rlist->rl_ghs) {
- for (x = 0; x < rlist->rl_rgrps; x++)
- gfs_holder_uninit(&rlist->rl_ghs[x]);
- kfree(rlist->rl_ghs);
- }
-}
-
-/**
- * gfs_reclaim_metadata - reclaims unused metadata
- * @sdp: the file system
- * @inodes:
- * @metadata:
- *
- * This function will look through the resource groups and
- * free the unused metadata.
- *
- * Returns: errno
- */
-
-int
-gfs_reclaim_metadata(struct gfs_sbd *sdp,
- uint64_t *inodes,
- uint64_t *metadata)
-{
- struct gfs_holder ji_gh, ri_gh, rgd_gh, t_gh;
- struct gfs_rgrpd *rgd;
- struct gfs_rgrp *rg;
- struct gfs_dinode *di;
- struct gfs_inum next;
- struct buffer_head *bh;
- uint32_t flags;
- uint32_t goal;
- unsigned int x;
- int error = 0;
-
- *inodes = *metadata = 0;
-
- /* Acquire the jindex lock here so we don't deadlock with a
- process writing the the jindex inode. :-( */
-
- error = gfs_jindex_hold(sdp, &ji_gh);
- if (error)
- goto fail;
-
- error = gfs_rindex_hold(sdp, &ri_gh);
- if (error)
- goto fail_jindex_relse;
-
- for (rgd = gfs_rgrpd_get_first(sdp);
- rgd;
- rgd = gfs_rgrpd_get_next(rgd)) {
- error = gfs_glock_nq_init(rgd->rd_gl,
- LM_ST_EXCLUSIVE, GL_NOCACHE,
- &rgd_gh);
- if (error)
- goto fail_rindex_relse;
-
- rgrp_verify(rgd);
-
- rg = &rgd->rd_rg;
-
- if (!rg->rg_freedi && !rg->rg_freemeta) {
- gfs_glock_dq_uninit(&rgd_gh);
- continue;
- }
-
- gfs_mhc_zap(rgd);
- gfs_depend_sync(rgd);
-
- error = gfs_lock_fs_check_clean(sdp, LM_ST_EXCLUSIVE, &t_gh);
- if (error)
- goto fail_gunlock_rg;
-
- error = gfs_trans_begin(sdp, rgd->rd_ri.ri_length, 0);
- if (error)
- goto fail_unlock_fs;
-
- next = rg->rg_freedi_list;
-
- for (x = rg->rg_freedi; x--;) {
- if (!next.no_formal_ino || !next.no_addr) {
- gfs_consist_rgrpd(rgd);
- error = -EIO;
- goto fail_end_trans;
- }
-
- blkfree_internal(sdp, next.no_addr, 1, GFS_BLKST_FREE);
-
- error = gfs_dread(rgd->rd_gl, next.no_addr,
- DIO_FORCE | DIO_START | DIO_WAIT, &bh);
- if (error)
- goto fail_end_trans;
-
- di = (struct gfs_dinode *)bh->b_data;
- flags = di->di_flags;
- flags = gfs32_to_cpu(flags);
- if (!(flags & GFS_DIF_UNUSED)) {
- gfs_consist_rgrpd(rgd);
- brelse(bh);
- error = -EIO;
- goto fail_end_trans;
- }
-
- gfs_inum_in(&next, (char *)&di->di_next_unused);
-
- brelse(bh);
-
- rg->rg_freedi--;
- rg->rg_free++;
- (*inodes)++;
- }
-
- if (next.no_formal_ino || next.no_addr) {
- gfs_consist_rgrpd(rgd);
- error = -EIO;
- goto fail_end_trans;
- }
- rg->rg_freedi_list = next;
-
- goal = 0;
- for (x = rg->rg_freemeta; x--;) {
- goal = blkalloc_internal(rgd, goal,
- GFS_BLKST_FREEMETA, GFS_BLKST_FREE);
- rg->rg_freemeta--;
- rg->rg_free++;
- (*metadata)++;
- }
-
- gfs_trans_add_bh(rgd->rd_gl, rgd->rd_bh[0]);
- gfs_rgrp_out(rg, rgd->rd_bh[0]->b_data);
-
- gfs_trans_end(sdp);
-
- gfs_glock_dq_uninit(&t_gh);
-
- gfs_glock_dq_uninit(&rgd_gh);
- }
-
- gfs_glock_dq_uninit(&ri_gh);
-
- gfs_glock_dq_uninit(&ji_gh);
-
- return 0;
-
- fail_end_trans:
- gfs_trans_end(sdp);
-
- fail_unlock_fs:
- gfs_glock_dq_uninit(&t_gh);
-
- fail_gunlock_rg:
- gfs_glock_dq_uninit(&rgd_gh);
-
- fail_rindex_relse:
- gfs_glock_dq_uninit(&ri_gh);
-
- fail_jindex_relse:
- gfs_glock_dq_uninit(&ji_gh);
-
- fail:
- return error;
-}
diff --git a/gfs-kernel/src/gfs/rgrp.h b/gfs-kernel/src/gfs/rgrp.h
deleted file mode 100644
index 0f5c620..0000000
--- a/gfs-kernel/src/gfs/rgrp.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef __RGRP_DOT_H__
-#define __RGRP_DOT_H__
-
-void gfs_mhc_add(struct gfs_rgrpd *rgd, struct buffer_head **bh,
- unsigned int num);
-int gfs_mhc_fish(struct gfs_sbd *sdp, struct buffer_head *bh);
-void gfs_mhc_zap(struct gfs_rgrpd *rgd);
-
-void gfs_depend_add(struct gfs_rgrpd *rgd, uint64_t formal_ino);
-void gfs_depend_sync(struct gfs_rgrpd *rgd);
-
-struct gfs_rgrpd *gfs_blk2rgrpd(struct gfs_sbd *sdp, uint64_t blk);
-struct gfs_rgrpd *gfs_rgrpd_get_first(struct gfs_sbd *sdp);
-struct gfs_rgrpd *gfs_rgrpd_get_next(struct gfs_rgrpd *rgd);
-
-void gfs_clear_rgrpd(struct gfs_sbd *sdp);
-
-int gfs_rindex_hold(struct gfs_sbd *sdp, struct gfs_holder *ri_gh);
-
-int gfs_rgrp_read(struct gfs_rgrpd *rgd);
-void gfs_rgrp_relse(struct gfs_rgrpd *rgd);
-
-void gfs_rgrp_lvb_fill(struct gfs_rgrpd *rgd);
-int gfs_rgrp_lvb_init(struct gfs_rgrpd *rgd);
-
-struct gfs_alloc *gfs_alloc_get(struct gfs_inode *ip);
-void gfs_alloc_put(struct gfs_inode *ip);
-
-int gfs_inplace_reserve_i(struct gfs_inode *ip,
- char *file, unsigned int line);
-#define gfs_inplace_reserve(ip) \
-gfs_inplace_reserve_i((ip), __FILE__, __LINE__)
-
-void gfs_inplace_release(struct gfs_inode *ip);
-
-unsigned char gfs_get_block_type(struct gfs_rgrpd *rgd, uint64_t block);
-
-void gfs_blkalloc(struct gfs_inode *ip, uint64_t *block);
-int gfs_metaalloc(struct gfs_inode *ip, uint64_t *block);
-int gfs_dialloc(struct gfs_inode *dip, uint64_t *block);
-
-void gfs_blkfree(struct gfs_inode *ip, uint64_t bstart, uint32_t blen);
-void gfs_metafree(struct gfs_inode *ip, uint64_t bstart, uint32_t blen);
-void gfs_difree_uninit(struct gfs_rgrpd *rgd, uint64_t addr);
-void gfs_difree(struct gfs_rgrpd *rgd, struct gfs_inode *ip);
-
-extern void gfs_statfs_modify(struct gfs_sbd *sdp,
- int64_t total,
- int64_t free,
- int64_t dinodes);
-
-/*
- * gfs_rgrp_list
- *
- * Used to collect a list of all resource groups spanned by a given
- * inode/file/directory
- */
-struct gfs_rgrp_list {
- unsigned int rl_rgrps; /* # (qty) of rgrps in list (array) */
- unsigned int rl_space; /* Current capacity in list for rgrps */
- struct gfs_rgrpd **rl_rgd; /* Array of ptrs to rgrp descriptors */
- struct gfs_holder *rl_ghs; /* Array of glock holders for rgrps */
-};
-
-void gfs_rlist_add(struct gfs_sbd *sdp, struct gfs_rgrp_list *rlist,
- uint64_t block);
-void gfs_rlist_alloc(struct gfs_rgrp_list *rlist, unsigned int state,
- int flags);
-void gfs_rlist_free(struct gfs_rgrp_list *rlist);
-
-int gfs_reclaim_metadata(struct gfs_sbd *sdp,
- uint64_t *inodes,
- uint64_t *metadata);
-
-#endif /* __RGRP_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/super.c b/gfs-kernel/src/gfs/super.c
deleted file mode 100644
index 781350e..0000000
--- a/gfs-kernel/src/gfs/super.c
+++ /dev/null
@@ -1,1274 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/vmalloc.h>
-#include <linux/statfs.h>
-
-#include "gfs.h"
-#include "dio.h"
-#include "file.h"
-#include "format.h"
-#include "glock.h"
-#include "glops.h"
-#include "inode.h"
-#include "log.h"
-#include "quota.h"
-#include "recovery.h"
-#include "rgrp.h"
-#include "super.h"
-#include "unlinked.h"
-#include "trans.h"
-
-/**
- * gfs_tune_init - Fill a gfs_tune structure with default values
- * @gt: tune
- *
- */
-
-void
-gfs_tune_init(struct gfs_tune *gt)
-{
- spin_lock_init(>->gt_spin);
-
- gt->gt_ilimit1 = 100;
- gt->gt_ilimit1_tries = 3;
- gt->gt_ilimit1_min = 1;
- gt->gt_ilimit2 = 500;
- gt->gt_ilimit2_tries = 10;
- gt->gt_ilimit2_min = 3;
- gt->gt_demote_secs = 300;
- gt->gt_incore_log_blocks = 1024;
- gt->gt_jindex_refresh_secs = 60;
- gt->gt_depend_secs = 60;
- gt->gt_scand_secs = 5;
- gt->gt_recoverd_secs = 60;
- gt->gt_logd_secs = 1;
- gt->gt_quotad_secs = 5;
- gt->gt_inoded_secs = 15;
- gt->gt_glock_purge = 0;
- gt->gt_quota_simul_sync = 64;
- gt->gt_quota_warn_period = 10;
- gt->gt_atime_quantum = 3600;
- gt->gt_quota_quantum = 60;
- gt->gt_quota_scale_num = 1;
- gt->gt_quota_scale_den = 1;
- gt->gt_quota_enforce = 1;
- gt->gt_quota_account = 1;
- gt->gt_new_files_jdata = 0;
- gt->gt_new_files_directio = 0;
- gt->gt_max_atomic_write = 4 << 20;
- gt->gt_max_readahead = 1 << 18;
- gt->gt_lockdump_size = 131072;
- gt->gt_stall_secs = 600;
- gt->gt_complain_secs = 10;
- gt->gt_reclaim_limit = 5000;
- gt->gt_entries_per_readdir = 32;
- gt->gt_prefetch_secs = 10;
- gt->gt_statfs_slots = 64;
- gt->gt_max_mhc = 10000;
- gt->gt_greedy_default = HZ / 10;
- gt->gt_greedy_quantum = HZ / 40;
- gt->gt_greedy_max = HZ / 4;
- gt->gt_rgrp_try_threshold = 100;
- gt->gt_statfs_fast = 0;
-}
-
-/**
- * gfs_check_sb - Check superblock
- * @sdp: the filesystem
- * @sb: The superblock
- * @silent: Don't print a message if the check fails
- *
- * Checks the version code of the FS is one that we understand how to
- * read and that the sizes of the various on-disk structures have not
- * changed.
- */
-
-int
-gfs_check_sb(struct gfs_sbd *sdp, struct gfs_sb *sb, int silent)
-{
- unsigned int x;
-
- if (sb->sb_header.mh_magic != GFS_MAGIC ||
- sb->sb_header.mh_type != GFS_METATYPE_SB) {
- if (!silent)
- printk("GFS: not a GFS filesystem\n");
- return -EINVAL;
- }
-
- /* If format numbers match exactly, we're done. */
-
- if (sb->sb_fs_format == GFS_FORMAT_FS &&
- sb->sb_multihost_format == GFS_FORMAT_MULTI)
- return 0;
-
- if (sb->sb_fs_format != GFS_FORMAT_FS) {
- for (x = 0; gfs_old_fs_formats[x]; x++)
- if (gfs_old_fs_formats[x] == sb->sb_fs_format)
- break;
-
- if (!gfs_old_fs_formats[x]) {
- printk("GFS: code version (%u, %u) is incompatible with ondisk format (%u, %u)\n",
- GFS_FORMAT_FS, GFS_FORMAT_MULTI,
- sb->sb_fs_format, sb->sb_multihost_format);
- printk("GFS: I don't know how to upgrade this FS\n");
- return -EINVAL;
- }
- }
-
- if (sb->sb_multihost_format != GFS_FORMAT_MULTI) {
- for (x = 0; gfs_old_multihost_formats[x]; x++)
- if (gfs_old_multihost_formats[x] == sb->sb_multihost_format)
- break;
-
- if (!gfs_old_multihost_formats[x]) {
- printk("GFS: code version (%u, %u) is incompatible with ondisk format (%u, %u)\n",
- GFS_FORMAT_FS, GFS_FORMAT_MULTI,
- sb->sb_fs_format, sb->sb_multihost_format);
- printk("GFS: I don't know how to upgrade this FS\n");
- return -EINVAL;
- }
- }
-
- if (!sdp->sd_args.ar_upgrade) {
- printk("GFS: code version (%u, %u) is incompatible with ondisk format (%u, %u)\n",
- GFS_FORMAT_FS, GFS_FORMAT_MULTI,
- sb->sb_fs_format, sb->sb_multihost_format);
- printk("GFS: Use the \"upgrade\" mount option to upgrade the FS\n");
- printk("GFS: See the manual for more details\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-/**
- * gfs_read_sb - Read super block
- * @sdp: The GFS superblock
- * @gl: the glock for the superblock (assumed to be held)
- * @silent: Don't print message if mount fails
- *
- */
-
-int
-gfs_read_sb(struct gfs_sbd *sdp, struct gfs_glock *gl, int silent)
-{
- struct buffer_head *bh;
- uint32_t hash_blocks, ind_blocks, leaf_blocks;
- uint32_t tmp_blocks;
- unsigned int x;
- int error;
-
- error = gfs_dread(gl, GFS_SB_ADDR >> sdp->sd_fsb2bb_shift,
- DIO_FORCE | DIO_START | DIO_WAIT, &bh);
- if (error) {
- if (!silent)
- printk("GFS: fsid=%s: can't read superblock\n",
- sdp->sd_fsname);
- return error;
- }
-
- gfs_assert(sdp, sizeof(struct gfs_sb) <= bh->b_size,);
- gfs_sb_in(&sdp->sd_sb, bh->b_data);
- brelse(bh);
-
- error = gfs_check_sb(sdp, &sdp->sd_sb, silent);
- if (error)
- return error;
-
- sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift -
- GFS_BASIC_BLOCK_SHIFT;
- sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;
- sdp->sd_diptrs = (sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode)) /
- sizeof(uint64_t);
- sdp->sd_inptrs = (sdp->sd_sb.sb_bsize - sizeof(struct gfs_indirect)) /
- sizeof(uint64_t);
- sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs_meta_header);
- sdp->sd_hash_bsize = sdp->sd_sb.sb_bsize / 2;
- sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1;
- sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
-
- /* Compute maximum reservation required to add a entry to a directory */
-
- hash_blocks = DIV_RU(sizeof(uint64_t) * (1 << GFS_DIR_MAX_DEPTH),
- sdp->sd_jbsize);
-
- ind_blocks = 0;
- for (tmp_blocks = hash_blocks; tmp_blocks > sdp->sd_diptrs;) {
- tmp_blocks = DIV_RU(tmp_blocks, sdp->sd_inptrs);
- ind_blocks += tmp_blocks;
- }
-
- leaf_blocks = 2 + GFS_DIR_MAX_DEPTH;
-
- sdp->sd_max_dirres = hash_blocks + ind_blocks + leaf_blocks;
-
- sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode);
- sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs;
- for (x = 2;; x++) {
- uint64_t space, d;
- uint32_t m;
-
- space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs;
- d = space;
- m = do_div(d, sdp->sd_inptrs);
-
- if (d != sdp->sd_heightsize[x - 1] || m)
- break;
- sdp->sd_heightsize[x] = space;
- }
- sdp->sd_max_height = x;
- gfs_assert(sdp, sdp->sd_max_height <= GFS_MAX_META_HEIGHT,);
-
- sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode);
- sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs;
- for (x = 2;; x++) {
- uint64_t space, d;
- uint32_t m;
-
- space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs;
- d = space;
- m = do_div(d, sdp->sd_inptrs);
-
- if (d != sdp->sd_jheightsize[x - 1] || m)
- break;
- sdp->sd_jheightsize[x] = space;
- }
- sdp->sd_max_jheight = x;
- gfs_assert(sdp, sdp->sd_max_jheight <= GFS_MAX_META_HEIGHT,);
-
- return 0;
-}
-
-/**
- * gfs_do_upgrade - upgrade a filesystem
- * @sdp: The GFS superblock
- *
- */
-
-int
-gfs_do_upgrade(struct gfs_sbd *sdp, struct gfs_glock *sb_gl)
-{
- struct gfs_holder ji_gh, t_gh, j_gh;
- struct gfs_log_header lh;
- struct buffer_head *bh;
- unsigned int x;
- int error;
-
- /* If format numbers match exactly, we're done. */
-
- if (sdp->sd_sb.sb_fs_format == GFS_FORMAT_FS &&
- sdp->sd_sb.sb_multihost_format == GFS_FORMAT_MULTI) {
- printk("GFS: fsid=%s: no upgrade necessary\n",
- sdp->sd_fsname);
- sdp->sd_args.ar_upgrade = FALSE;
- return 0;
- }
-
- error = gfs_jindex_hold(sdp, &ji_gh);
- if (error)
- goto fail;
-
- error = gfs_glock_nq_init(sdp->sd_trans_gl,
- LM_ST_EXCLUSIVE, GL_NOCACHE,
- &t_gh);
- if (error)
- goto fail_ji_relse;
-
- if (test_bit(SDF_ROFS, &sdp->sd_flags)) {
- printk("GFS: fsid=%s: can't upgrade: read-only FS\n",
- sdp->sd_fsname);
- error = -EROFS;
- goto fail_gunlock_tr;
- }
-
- for (x = 0; x < sdp->sd_journals; x++) {
- error = gfs_glock_nq_num(sdp,
- sdp->sd_jindex[x].ji_addr,
- &gfs_meta_glops, LM_ST_SHARED,
- LM_FLAG_TRY | GL_NOCACHE, &j_gh);
- switch (error) {
- case 0:
- break;
-
- case GLR_TRYFAILED:
- printk("GFS: fsid=%s: journal %u is busy\n",
- sdp->sd_fsname, x);
- error = -EBUSY;
-
- default:
- goto fail_gunlock_tr;
- }
-
- error = gfs_find_jhead(sdp, &sdp->sd_jindex[x],
- j_gh.gh_gl, &lh);
-
- gfs_glock_dq_uninit(&j_gh);
-
- if (error)
- goto fail_gunlock_tr;
-
- if (!(lh.lh_flags & GFS_LOG_HEAD_UNMOUNT) || lh.lh_last_dump) {
- printk("GFS: fsid=%s: journal %u is busy\n",
- sdp->sd_fsname, x);
- error = -EBUSY;
- goto fail_gunlock_tr;
- }
- }
-
- /* We don't need to journal this change because we're changing
- only one sector of one block. We definitely don't want to have
- the journaling code running at this point. */
-
- error = gfs_dread(sb_gl, GFS_SB_ADDR >> sdp->sd_fsb2bb_shift,
- DIO_START | DIO_WAIT, &bh);
- if (error)
- goto fail_gunlock_tr;
-
- gfs_sb_in(&sdp->sd_sb, bh->b_data);
-
- error = gfs_check_sb(sdp, &sdp->sd_sb, FALSE);
- if (error) {
- gfs_consist(sdp);
- brelse(bh);
- goto fail_gunlock_tr;
- }
-
- sdp->sd_sb.sb_fs_format = GFS_FORMAT_FS;
- sdp->sd_sb.sb_multihost_format = GFS_FORMAT_MULTI;
-
- gfs_sb_out(&sdp->sd_sb, bh->b_data);
-
- set_bit(GLF_DIRTY, &sb_gl->gl_flags);
- error = gfs_dwrite(sdp, bh, DIO_DIRTY | DIO_START | DIO_WAIT);
-
- brelse(bh);
-
- gfs_glock_dq_uninit(&t_gh);
-
- gfs_glock_dq_uninit(&ji_gh);
-
- if (!error) {
- printk("GFS: fsid=%s: upgrade successful\n",
- sdp->sd_fsname);
- sdp->sd_args.ar_upgrade = FALSE;
- }
-
- return error;
-
- fail_gunlock_tr:
- gfs_glock_dq_uninit(&t_gh);
-
- fail_ji_relse:
- gfs_glock_dq_uninit(&ji_gh);
-
- fail:
- if (error == -EBUSY)
- printk("GFS: fsid=%s: can't upgrade: the FS is still busy or contains dirty journals\n",
- sdp->sd_fsname);
- else
- printk("GFS: fsid=%s: can't upgrade: %d\n",
- sdp->sd_fsname, error);
-
- return error;
-}
-
-/**
- * clear_journalsi - Clear all the journal index information (without locking)
- * @sdp: The GFS superblock
- *
- */
-
-static void
-clear_journalsi(struct gfs_sbd *sdp)
-{
- if (sdp->sd_jindex) {
- kfree(sdp->sd_jindex);
- sdp->sd_jindex = NULL;
- }
- sdp->sd_journals = 0;
-}
-
-/**
- * gfs_clear_journals - Clear all the journal index information
- * @sdp: The GFS superblock
- *
- */
-
-void
-gfs_clear_journals(struct gfs_sbd *sdp)
-{
- down(&sdp->sd_jindex_lock);
- clear_journalsi(sdp);
- up(&sdp->sd_jindex_lock);
-}
-
-/**
- * gfs_ji_update - Update the journal index information
- * @ip: The journal index inode
- *
- * Returns: errno
- */
-
-static int
-gfs_ji_update(struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- char buf[sizeof(struct gfs_jindex)];
- unsigned int j;
- int error;
-
- if (do_mod(ip->i_di.di_size, sizeof(struct gfs_jindex))) {
- gfs_consist_inode(ip);
- return -EIO;
- }
-
- clear_journalsi(sdp);
-
- sdp->sd_jindex = kmalloc(ip->i_di.di_size, GFP_KERNEL);
- if (!sdp->sd_jindex)
- return -ENOMEM;
- memset(sdp->sd_jindex, 0, ip->i_di.di_size);
-
- for (j = 0;; j++) {
- error = gfs_internal_read(ip, buf,
- j * sizeof(struct gfs_jindex),
- sizeof(struct gfs_jindex));
- if (!error)
- break;
- if (error != sizeof(struct gfs_jindex)) {
- if (error > 0)
- error = -EIO;
- goto fail;
- }
-
- gfs_jindex_in(sdp->sd_jindex + j, buf);
- }
-
- sdp->sd_journals = j;
- sdp->sd_jiinode_vn = ip->i_gl->gl_vn;
-
- return 0;
-
- fail:
- clear_journalsi(sdp);
- return error;
-}
-
-/**
- * gfs_jindex_hold - Grab a lock on the jindex
- * @sdp: The GFS superblock
- * @ji_gh: the holder for the jindex glock
- *
- * This makes sure that we're using the latest copy of the journal index
- * special file (this describes all of the journals for this filesystem),
- * which might have been updated if someone added journals
- * (via gfs_jadd utility).
- *
- * This is very similar to the gfs_rindex_hold() function, except that
- * in general we hold the jindex lock for longer periods of time and
- * we grab it far less frequently (in general) then the rgrp lock.
- *
- * Returns: errno
- */
-
-int
-gfs_jindex_hold(struct gfs_sbd *sdp, struct gfs_holder *ji_gh)
-{
- struct gfs_inode *ip = sdp->sd_jiinode;
- struct gfs_glock *gl = ip->i_gl;
- int error;
-
- error = gfs_glock_nq_init(gl, LM_ST_SHARED, 0, ji_gh);
- if (error)
- return error;
-
- /* Read new copy from disk if we don't have the latest */
- if (sdp->sd_jiinode_vn != gl->gl_vn) {
- down(&sdp->sd_jindex_lock);
- if (sdp->sd_jiinode_vn != gl->gl_vn)
- error = gfs_ji_update(ip);
- up(&sdp->sd_jindex_lock);
- }
-
- if (error)
- gfs_glock_dq_uninit(ji_gh);
-
- return error;
-}
-
-/**
- * gfs_get_jiinode - Read-in the special (hidden) journal index inode
- * @sdp: The GFS superblock
- *
- * Returns: errno
- *
- * This reads-in just the dinode, not the special file contents that describe
- * the journals themselves (see gfs_jindex_hold()).
- */
-
-int
-gfs_get_jiinode(struct gfs_sbd *sdp)
-{
- struct gfs_holder ji_gh;
- int error;
-
- error = gfs_glock_nq_num(sdp,
- sdp->sd_sb.sb_jindex_di.no_formal_ino,
- &gfs_inode_glops,
- LM_ST_SHARED, GL_LOCAL_EXCL,
- &ji_gh);
- if (error)
- return error;
-
- error = gfs_inode_get(ji_gh.gh_gl, &sdp->sd_sb.sb_jindex_di,
- CREATE, &sdp->sd_jiinode);
- if (!error) {
- sdp->sd_jiinode_vn = ji_gh.gh_gl->gl_vn - 1;
- set_bit(GLF_STICKY, &ji_gh.gh_gl->gl_flags);
- }
-
- gfs_glock_dq_uninit(&ji_gh);
-
- return error;
-}
-
-/**
- * gfs_get_riinode - Read in the special (hidden) resource group index inode
- * @sdp: The GFS superblock
- *
- * Returns: errno
- *
- * This reads-in just the dinode, not the special file contents that describe
- * the resource groups themselves (see gfs_rindex_hold()).
- */
-
-int
-gfs_get_riinode(struct gfs_sbd *sdp)
-{
- struct gfs_holder ri_gh;
- int error;
-
- error = gfs_glock_nq_num(sdp,
- sdp->sd_sb.sb_rindex_di.no_formal_ino,
- &gfs_inode_glops,
- LM_ST_SHARED, GL_LOCAL_EXCL,
- &ri_gh);
- if (error)
- return error;
-
- error = gfs_inode_get(ri_gh.gh_gl, &sdp->sd_sb.sb_rindex_di,
- CREATE, &sdp->sd_riinode);
- if (!error) {
- sdp->sd_riinode_vn = ri_gh.gh_gl->gl_vn - 1;
- set_bit(GLF_STICKY, &ri_gh.gh_gl->gl_flags);
- }
-
- gfs_glock_dq_uninit(&ri_gh);
-
- return error;
-}
-
-/**
- * gfs_get_rootinode - Read in the filesystem's root inode
- * @sdp: The GFS superblock
- *
- * Returns: errno
- */
-
-int
-gfs_get_rootinode(struct gfs_sbd *sdp)
-{
- struct gfs_holder i_gh;
- int error;
-
- error = gfs_glock_nq_num(sdp,
- sdp->sd_sb.sb_root_di.no_formal_ino,
- &gfs_inode_glops,
- LM_ST_SHARED, GL_LOCAL_EXCL,
- &i_gh);
- if (error)
- return error;
-
- error = gfs_inode_get(i_gh.gh_gl, &sdp->sd_sb.sb_root_di,
- CREATE, &sdp->sd_rooti);
-
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gfs_get_qinode - Read in the special (hidden) quota inode
- * @sdp: The GFS superblock
- *
- * If one is not on-disk already, create a new one.
- * Does not read in file contents, just the dinode.
- *
- * Returns: errno
- */
-
-int
-gfs_get_qinode(struct gfs_sbd *sdp)
-{
- struct gfs_holder i_gh;
- int error;
-
- /* Create, if not on-disk already */
- if (!sdp->sd_sb.sb_quota_di.no_formal_ino) {
- error = gfs_alloc_qinode(sdp);
- if (error)
- return error;
- }
-
- error = gfs_glock_nq_num(sdp,
- sdp->sd_sb.sb_quota_di.no_formal_ino,
- &gfs_inode_glops,
- LM_ST_SHARED, GL_LOCAL_EXCL,
- &i_gh);
- if (error)
- return error;
-
- error = gfs_inode_get(i_gh.gh_gl, &sdp->sd_sb.sb_quota_di,
- CREATE, &sdp->sd_qinode);
-
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gfs_get_linode - Read in the special (hidden) license inode
- * @sdp: The GFS superblock
- *
- * If one is not on-disk already, create a new one.
- * Does not read in file contents, just the dinode.
- *
- * Returns: errno
- */
-
-int
-gfs_get_linode(struct gfs_sbd *sdp)
-{
- struct gfs_holder i_gh;
- int error;
-
- /* Create, if not on-disk already */
- if (!sdp->sd_sb.sb_license_di.no_formal_ino) {
- error = gfs_alloc_linode(sdp);
- if (error)
- return error;
- }
-
- error = gfs_glock_nq_num(sdp,
- sdp->sd_sb.sb_license_di.no_formal_ino,
- &gfs_inode_glops,
- LM_ST_SHARED, GL_LOCAL_EXCL,
- &i_gh);
- if (error)
- return error;
-
- /* iopen obtained in via gfs_glock_get(..gfs_iopen_glops) */
- error = gfs_inode_get(i_gh.gh_gl, &sdp->sd_sb.sb_license_di,
- CREATE, &sdp->sd_linode);
-
- gfs_glock_dq_uninit(&i_gh);
-
- return error;
-}
-
-/**
- * gfs_make_fs_rw - Turn a Read-Only FS into a Read-Write one
- * @sdp: the filesystem
- *
- * Returns: errno
- */
-
-int
-gfs_make_fs_rw(struct gfs_sbd *sdp)
-{
- struct gfs_glock *j_gl = sdp->sd_journal_gh.gh_gl;
- struct gfs_holder t_gh;
- struct gfs_log_header head;
- int error;
-
- error = gfs_glock_nq_init(sdp->sd_trans_gl,
- LM_ST_SHARED,
- GL_LOCAL_EXCL | GL_EXACT,
- &t_gh);
- if (error)
- return error;
-
- j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA);
-
- error = gfs_find_jhead(sdp, &sdp->sd_jdesc, j_gl, &head);
- if (error)
- goto fail;
-
- if (!(head.lh_flags & GFS_LOG_HEAD_UNMOUNT)) {
- gfs_consist(sdp);
- error = -EIO;
- goto fail;
- }
-
- /* Initialize some head of the log stuff */
- sdp->sd_sequence = head.lh_sequence;
- sdp->sd_log_head = head.lh_first + 1;
-
- error = gfs_recover_dump(sdp);
- if (error)
- goto fail;
-
- set_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
- clear_bit(SDF_ROFS, &sdp->sd_flags);
-
- set_bit(GLF_DIRTY, &j_gl->gl_flags);
- gfs_log_dump(sdp, TRUE);
-
- gfs_glock_dq_uninit(&t_gh);
-
- return 0;
-
- fail:
- t_gh.gh_flags |= GL_NOCACHE;
- gfs_glock_dq_uninit(&t_gh);
-
- return error;
-}
-
-/**
- * gfs_make_fs_ro - Turn a Read-Write FS into a Read-Only one
- * @sdp: the filesystem
- *
- * Returns: errno
- */
-
-int
-gfs_make_fs_ro(struct gfs_sbd *sdp)
-{
- struct gfs_holder t_gh;
- int error;
-
- error = gfs_glock_nq_init(sdp->sd_trans_gl,
- LM_ST_SHARED,
- GL_LOCAL_EXCL | GL_EXACT | GL_NOCACHE,
- &t_gh);
- if (error &&
- !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
- return error;
-
- gfs_statfs_sync(sdp);
-
- gfs_log_flush(sdp);
- gfs_quota_sync(sdp);
- gfs_quota_scan(sdp);
-
- gfs_sync_meta(sdp);
- gfs_log_dump(sdp, TRUE);
- gfs_log_shutdown(sdp);
-
- set_bit(SDF_ROFS, &sdp->sd_flags);
- clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
-
- if (t_gh.gh_gl)
- gfs_glock_dq_uninit(&t_gh);
-
- gfs_unlinked_cleanup(sdp);
- gfs_quota_cleanup(sdp);
-
- return error;
-}
-
-/**
- * stat_gfs_fill - fill in the sg for a given RG
- * @rgd: the RG
- * @sg: the sg structure
- *
- * Returns: 0 on success, -ESTALE if the LVB is invalid
- */
-
-static int
-stat_gfs_fill(struct gfs_rgrpd *rgd, struct gfs_stat_gfs *sg)
-{
- struct gfs_rgrp_lvb *rb = (struct gfs_rgrp_lvb *)rgd->rd_gl->gl_lvb;
-
- if (gfs32_to_cpu(rb->rb_magic) != GFS_MAGIC)
- return -ESTALE;
-
- sg->sg_total_blocks += rgd->rd_ri.ri_data;
- sg->sg_free += gfs32_to_cpu(rb->rb_free);
- sg->sg_used_dinode += gfs32_to_cpu(rb->rb_useddi);
- sg->sg_free_dinode += gfs32_to_cpu(rb->rb_freedi);
- sg->sg_used_meta += gfs32_to_cpu(rb->rb_usedmeta);
- sg->sg_free_meta += gfs32_to_cpu(rb->rb_freemeta);
-
- return 0;
-}
-
-/**
- * stat_gfs_async - Stat a filesystem using asynchronous locking
- * @sdp: the filesystem
- * @sg: the sg info that will be returned
- * @interruptible: TRUE if we should look for signals.
- *
- * Any error (other than a signal) will cause this routine to fall back
- * to the synchronous version.
- *
- * FIXME: This really shouldn't busy wait like this.
- *
- * Returns: errno
- */
-
-static int
-stat_gfs_async(struct gfs_sbd *sdp, struct gfs_stat_gfs *sg, int interruptible)
-{
- struct gfs_rgrpd *rgd_next = gfs_rgrpd_get_first(sdp);
- struct gfs_holder *gha, *gh;
- unsigned int slots = gfs_tune_get(sdp, gt_statfs_slots);
- unsigned int x;
- int done;
- int error = 0, err;
-
- memset(sg, 0, sizeof(struct gfs_stat_gfs));
-
- gha = vmalloc(slots * sizeof(struct gfs_holder));
- if (!gha)
- return -ENOMEM;
- memset(gha, 0, slots * sizeof(struct gfs_holder));
-
- for (;;) {
- done = TRUE;
-
- for (x = 0; x < slots; x++) {
- gh = gha + x;
-
- if (gh->gh_gl && gfs_glock_poll(gh)) {
- err = gfs_glock_wait(gh);
- if (err) {
- gfs_holder_uninit(gh);
- error = err;
- } else {
- if (!error)
- error = stat_gfs_fill(get_gl2rgd(gh->gh_gl), sg);
- gfs_glock_dq_uninit(gh);
- }
- }
-
- if (gh->gh_gl)
- done = FALSE;
- else if (rgd_next && !error) {
- error = gfs_glock_nq_init(rgd_next->rd_gl,
- LM_ST_SHARED,
- GL_LOCAL_EXCL | GL_SKIP | GL_ASYNC,
- gh);
- rgd_next = gfs_rgrpd_get_next(rgd_next);
- done = FALSE;
- }
-
- if (interruptible && signal_pending(current))
- error = -ERESTARTSYS;
- }
-
- if (done)
- break;
-
- yield();
- }
-
- vfree(gha);
-
- return error;
-}
-
-/**
- * stat_gfs_sync - Stat a filesystem using synchronous locking
- * @sdp: the filesystem
- * @sg: the sg info that will be returned
- * @interruptible: TRUE if we should look for signals.
- *
- * Returns: errno
- */
-
-static int
-stat_gfs_sync(struct gfs_sbd *sdp, struct gfs_stat_gfs *sg, int interruptible)
-{
- struct gfs_holder rgd_gh;
- struct gfs_rgrpd *rgd;
- int error;
-
- memset(sg, 0, sizeof(struct gfs_stat_gfs));
-
- for (rgd = gfs_rgrpd_get_first(sdp);
- rgd;
- rgd = gfs_rgrpd_get_next(rgd)) {
- for (;;) {
- error = gfs_glock_nq_init(rgd->rd_gl,
- LM_ST_SHARED,
- GL_LOCAL_EXCL | GL_SKIP,
- &rgd_gh);
- if (error)
- return error;
-
- error = stat_gfs_fill(rgd, sg);
-
- gfs_glock_dq_uninit(&rgd_gh);
-
- if (!error)
- break;
-
- error = gfs_rgrp_lvb_init(rgd);
- if (error)
- return error;
- }
-
- if (interruptible && signal_pending(current))
- return -ERESTARTSYS;
- }
-
- return 0;
-}
-
-/**
- * gfs_stat_gfs - Do a statfs
- * @sdp: the filesystem
- * @sg: the sg structure
- * @interruptible: Stop if there is a signal pending
- *
- * Returns: errno
- */
-
-int
-gfs_stat_gfs(struct gfs_sbd *sdp, struct gfs_stat_gfs *sg, int interruptible)
-{
- struct gfs_holder ri_gh;
- int error;
-
- error = gfs_rindex_hold(sdp, &ri_gh);
- if (error)
- return error;
-
- error = stat_gfs_async(sdp, sg, interruptible);
- if (error == -ESTALE)
- error = stat_gfs_sync(sdp, sg, interruptible);
-
- gfs_glock_dq_uninit(&ri_gh);
-
- return error;
-}
-
-/**
- * gfs_lock_fs_check_clean - Stop all writes to the FS and check that all journals are clean
- * @sdp: the file system
- * @state: the state to put the transaction lock into
- * @t_gh: the hold on the transaction lock
- *
- * Returns: errno
- */
-
-int
-gfs_lock_fs_check_clean(struct gfs_sbd *sdp, unsigned int state,
- struct gfs_holder *t_gh)
-{
- struct gfs_holder ji_gh, cl_gh;
- struct gfs_log_header lh;
- unsigned int x;
- int error;
-
- error = gfs_jindex_hold(sdp, &ji_gh);
- if (error)
- return error;
-
- error = gfs_glock_nq_num(sdp,
- GFS_CRAP_LOCK, &gfs_meta_glops,
- LM_ST_SHARED, GL_NOCACHE,
- &cl_gh);
- if (error)
- goto fail;
-
- error = gfs_glock_nq_init(sdp->sd_trans_gl, state,
- LM_FLAG_PRIORITY | GL_EXACT | GL_NOCACHE,
- t_gh);
- if (error)
- goto fail_gunlock_craplock;
-
- for (x = 0; x < sdp->sd_journals; x++) {
- error = gfs_find_jhead(sdp, &sdp->sd_jindex[x],
- cl_gh.gh_gl, &lh);
- if (error)
- goto fail_gunlock_trans;
-
- if (!(lh.lh_flags & GFS_LOG_HEAD_UNMOUNT)) {
- error = -EBUSY;
- goto fail_gunlock_trans;
- }
- }
-
- gfs_glock_dq_uninit(&cl_gh);
- gfs_glock_dq_uninit(&ji_gh);
-
- return 0;
-
- fail_gunlock_trans:
- gfs_glock_dq_uninit(t_gh);
-
- fail_gunlock_craplock:
- gfs_glock_dq_uninit(&cl_gh);
-
- fail:
- gfs_glock_dq_uninit(&ji_gh);
-
- return error;
-}
-
-/**
- * gfs_freeze_fs - freezes the file system
- * @sdp: the file system
- *
- * This function flushes data and meta data for all machines by
- * aquiring the transaction log exclusively. All journals are
- * ensured to be in a clean state as well.
- *
- * Returns: errno
- */
-
-int
-gfs_freeze_fs(struct gfs_sbd *sdp)
-{
- int error = 0;
-
- down(&sdp->sd_freeze_lock);
-
- if (!sdp->sd_freeze_count++) {
- error = gfs_lock_fs_check_clean(sdp, LM_ST_DEFERRED,
- &sdp->sd_freeze_gh);
- if (error)
- sdp->sd_freeze_count--;
- else
- sdp->sd_freeze_gh.gh_owner = NULL;
- }
-
- up(&sdp->sd_freeze_lock);
-
- return error;
-}
-
-/**
- * gfs_unfreeze_fs - unfreezes the file system
- * @sdp: the file system
- *
- * This function allows the file system to proceed by unlocking
- * the exclusively held transaction lock. Other GFS nodes are
- * now free to acquire the lock shared and go on with their lives.
- *
- */
-
-void
-gfs_unfreeze_fs(struct gfs_sbd *sdp)
-{
- down(&sdp->sd_freeze_lock);
-
- if (sdp->sd_freeze_count && !--sdp->sd_freeze_count)
- gfs_glock_dq_uninit(&sdp->sd_freeze_gh);
-
- up(&sdp->sd_freeze_lock);
-}
-
-/*
- * Fast statfs implementation - mostly based on GFS2 implementation.
- */
-
-void gfs_statfs_change_in(struct gfs_statfs_change_host *sc, const void *buf)
-{
- const struct gfs_statfs_change *str = buf;
-
- sc->sc_total = be64_to_cpu(str->sc_total);
- sc->sc_free = be64_to_cpu(str->sc_free);
- sc->sc_dinodes = be64_to_cpu(str->sc_dinodes);
-}
-
-void gfs_statfs_change_out(const struct gfs_statfs_change_host *sc, void *buf)
-{
- struct gfs_statfs_change *str = buf;
-
- str->sc_total = cpu_to_be64(sc->sc_total);
- str->sc_free = cpu_to_be64(sc->sc_free);
- str->sc_dinodes = cpu_to_be64(sc->sc_dinodes);
-}
-
-int gfs_statfs_start(struct gfs_sbd *sdp)
-{
- struct gfs_stat_gfs sg;
- struct gfs_inode *m_ip;
- struct gfs_statfs_change_host *m_sc = &sdp->sd_statfs_master;
- struct gfs_statfs_change_host *l_sc = &sdp->sd_statfs_local;
- struct buffer_head *m_bh;
- struct gfs_holder gh;
- int error;
-
- printk("GFS: fsid=%s: fast statfs start time = %lu\n",
- sdp->sd_fsname, get_seconds());
-
- /* created via gfs_get_linode() in fill_super(). */
- /* gfs_inode_glops */
- m_ip = sdp->sd_linode;
-
- /* get real statistics */
- error = gfs_stat_gfs(sdp, &sg, TRUE);
- if (error)
- return error;
-
- /* make sure the page is refreshed via glock flushing */
- error = gfs_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, GL_NOCACHE,
- &gh);
- if (error)
- goto gfs_statfs_start_out;
-
- error = gfs_get_inode_buffer(m_ip, &m_bh);
- if (error)
- goto gfs_statfs_start_unlock;
-
- error = gfs_trans_begin(sdp, 1, 0);
- if (error)
- goto gfs_statfs_start_bh;
-
- spin_lock(&sdp->sd_statfs_spin);
- m_sc->sc_total = sg.sg_total_blocks;
- m_sc->sc_free = sg.sg_free + sg.sg_free_dinode + sg.sg_free_meta;
- m_sc->sc_dinodes = sg.sg_used_dinode;
- memset(l_sc, 0, sizeof(struct gfs_statfs_change_host));
- spin_unlock(&sdp->sd_statfs_spin);
-
- gfs_trans_add_bh(m_ip->i_gl, m_bh);
- gfs_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs_dinode));
-
- gfs_trans_end(sdp);
-
-gfs_statfs_start_bh:
- brelse(m_bh);
-
-gfs_statfs_start_unlock:
- gfs_glock_dq_uninit(&gh);
-
-gfs_statfs_start_out:
- return 0;
-}
-
-int gfs_statfs_init(struct gfs_sbd *sdp, int flag)
-{
- int error;
-
- /* if flag == 0, do we want to turn this off ? */
- if (!flag)
- return 0;
-
- error = gfs_statfs_start(sdp);
- if (error)
- printk("GFS: fsid=%s: can't initialize statfs subsystem: %d\n",
- sdp->sd_fsname, error);
-
- return error;
-}
-
-void gfs_statfs_modify(struct gfs_sbd *sdp,
- int64_t total,
- int64_t free,
- int64_t dinodes)
-{
- struct gfs_statfs_change_host *l_sc = &sdp->sd_statfs_local;
-
- spin_lock(&sdp->sd_statfs_spin);
- l_sc->sc_total += total;
- l_sc->sc_free += free;
- l_sc->sc_dinodes += dinodes;
- spin_unlock(&sdp->sd_statfs_spin);
-}
-
-int gfs_statfs_sync(struct gfs_sbd *sdp)
-{
- struct gfs_inode *m_ip = sdp->sd_linode;
- struct gfs_statfs_change_host *m_sc = &sdp->sd_statfs_master;
- struct gfs_statfs_change_host *l_sc = &sdp->sd_statfs_local;
- struct gfs_holder gh;
- struct buffer_head *m_bh;
- int error;
-
- error = gfs_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, GL_NOCACHE,
- &gh);
- if (error)
- return error;
-
- error = gfs_get_inode_buffer(m_ip, &m_bh);
- if (error)
- goto gfs_statfs_sync_out;
-
- /* if no change, simply return */
- spin_lock(&sdp->sd_statfs_spin);
- gfs_statfs_change_in(m_sc, m_bh->b_data +
- sizeof(struct gfs_dinode));
- if (!l_sc->sc_total && !l_sc->sc_free && !l_sc->sc_dinodes) {
- spin_unlock(&sdp->sd_statfs_spin);
- goto out_bh;
- }
- spin_unlock(&sdp->sd_statfs_spin);
-
- error = gfs_trans_begin(sdp, 1, 0);
- if (error)
- goto out_bh;
-
- spin_lock(&sdp->sd_statfs_spin);
- m_sc->sc_total += l_sc->sc_total;
- m_sc->sc_free += l_sc->sc_free;
- m_sc->sc_dinodes += l_sc->sc_dinodes;
- memset(l_sc, 0, sizeof(struct gfs_statfs_change_host));
- spin_unlock(&sdp->sd_statfs_spin);
-
- gfs_trans_add_bh(m_ip->i_gl, m_bh);
- gfs_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs_dinode));
-
- gfs_trans_end(sdp);
-
-out_bh:
- brelse(m_bh);
-
-gfs_statfs_sync_out:
- gfs_glock_dq_uninit(&gh);
- return error;
-}
-
-int gfs_statfs_fast(struct gfs_sbd *sdp, void *b)
-{
- struct kstatfs *buf = (struct kstatfs *)b;
- struct gfs_statfs_change_host sc, *m_sc = &sdp->sd_statfs_master;
- struct gfs_statfs_change_host *l_sc = &sdp->sd_statfs_local;
-
- spin_lock(&sdp->sd_statfs_spin);
-
- sc.sc_total = m_sc->sc_total + l_sc->sc_total;
- sc.sc_free = m_sc->sc_free + l_sc->sc_free;
- sc.sc_dinodes = m_sc->sc_dinodes + l_sc->sc_dinodes;
- spin_unlock(&sdp->sd_statfs_spin);
-
- if (sc.sc_free < 0)
- sc.sc_free = 0;
- if (sc.sc_free > sc.sc_total)
- sc.sc_free = sc.sc_total;
- if (sc.sc_dinodes < 0)
- sc.sc_dinodes = 0;
-
- /* fill in the statistics */
- memset(buf, 0, sizeof(struct kstatfs));
-
- buf->f_type = GFS_MAGIC; buf->f_bsize = sdp->sd_sb.sb_bsize;
- buf->f_blocks = sc.sc_total;
- buf->f_bfree = sc.sc_free;
- buf->f_bavail = sc.sc_free;
- buf->f_files = sc.sc_dinodes + sc.sc_free;
- buf->f_ffree = sc.sc_free;
- buf->f_namelen = GFS_FNAMESIZE;
-
- return 0;
-}
diff --git a/gfs-kernel/src/gfs/super.h b/gfs-kernel/src/gfs/super.h
deleted file mode 100644
index 2ffbb9f..0000000
--- a/gfs-kernel/src/gfs/super.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef __SUPER_DOT_H__
-#define __SUPER_DOT_H__
-
-void gfs_tune_init(struct gfs_tune *gt);
-
-int gfs_check_sb(struct gfs_sbd *sdp, struct gfs_sb *sb, int silent);
-int gfs_read_sb(struct gfs_sbd *sdp, struct gfs_glock *gl, int silent);
-int gfs_do_upgrade(struct gfs_sbd *sdp, struct gfs_glock *gl_sb);
-
-static __inline__ unsigned int
-gfs_num_journals(struct gfs_sbd *sdp)
-{
- unsigned int num;
- down(&sdp->sd_jindex_lock);
- num = sdp->sd_journals;
- up(&sdp->sd_jindex_lock);
- return num;
-}
-
-int gfs_jindex_hold(struct gfs_sbd *sdp, struct gfs_holder *ji_gh);
-void gfs_clear_journals(struct gfs_sbd *sdp);
-
-int gfs_get_jiinode(struct gfs_sbd *sdp);
-int gfs_get_riinode(struct gfs_sbd *sdp);
-int gfs_get_rootinode(struct gfs_sbd *sdp);
-int gfs_get_qinode(struct gfs_sbd *sdp);
-int gfs_get_linode(struct gfs_sbd *sdp);
-
-int gfs_make_fs_rw(struct gfs_sbd *sdp);
-int gfs_make_fs_ro(struct gfs_sbd *sdp);
-
-int gfs_statfs_init(struct gfs_sbd *sdp, int flag);
-int gfs_statfs_sync(struct gfs_sbd *sdp);
-int gfs_statfs_fast(struct gfs_sbd *sdp, void *buf);
-
-struct gfs_stat_gfs {
- uint64_t sg_total_blocks;
- uint64_t sg_free;
- uint64_t sg_used_dinode;
- uint64_t sg_free_dinode;
- uint64_t sg_used_meta;
- uint64_t sg_free_meta;
-};
-
-int gfs_stat_gfs(struct gfs_sbd *sdp, struct gfs_stat_gfs *sg,
- int interruptible);
-
-int gfs_lock_fs_check_clean(struct gfs_sbd *sdp, unsigned int state,
- struct gfs_holder *t_gh);
-int gfs_freeze_fs(struct gfs_sbd *sdp);
-void gfs_unfreeze_fs(struct gfs_sbd *sdp);
-void gfs_online_uevent(struct gfs_sbd *sdp);
-
-#endif /* __SUPER_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/sys.c b/gfs-kernel/src/gfs/sys.c
deleted file mode 100644
index f20d302..0000000
--- a/gfs-kernel/src/gfs/sys.c
+++ /dev/null
@@ -1,145 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/proc_fs.h>
-#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/genhd.h>
-
-#include "gfs.h"
-#include "glock.h"
-#include "lm.h"
-#include "sys.h"
-#include "super.h"
-
-char *gfs_sys_margs;
-spinlock_t gfs_sys_margs_lock;
-
-static ssize_t id_show(struct gfs_sbd *sdp, char *buf)
-{
- return sprintf(buf, "%s\n", sdp->sd_vfs->s_id);
-}
-
-static ssize_t fsname_show(struct gfs_sbd *sdp, char *buf)
-{
- return sprintf(buf, "%s\n", sdp->sd_fsname);
-}
-
-struct gfs_attr {
- struct attribute attr;
- ssize_t (*show)(struct gfs_sbd *, char *);
- ssize_t (*store)(struct gfs_sbd *, const char *, size_t);
-};
-
-#define GFS_ATTR(name, mode, show, store) \
-static struct gfs_attr gfs_attr_##name = __ATTR(name, mode, show, store)
-
-GFS_ATTR(id, 0444, id_show, NULL);
-GFS_ATTR(fsname, 0444, fsname_show, NULL);
-
-static struct attribute *gfs_attrs[] = {
- &gfs_attr_id.attr,
- &gfs_attr_fsname.attr,
- NULL,
-};
-
-static ssize_t gfs_attr_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct gfs_sbd *sdp = container_of(kobj, struct gfs_sbd, sd_kobj);
- struct gfs_attr *a = container_of(attr, struct gfs_attr, attr);
- return a->show ? a->show(sdp, buf) : 0;
-}
-
-static ssize_t gfs_attr_store(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t len)
-{
- struct gfs_sbd *sdp = container_of(kobj, struct gfs_sbd, sd_kobj);
- struct gfs_attr *a = container_of(attr, struct gfs_attr, attr);
- return a->store ? a->store(sdp, buf, len) : len;
-}
-
-static struct sysfs_ops gfs_attr_ops = {
- .show = gfs_attr_show,
- .store = gfs_attr_store,
-};
-
-static struct kobj_type gfs_ktype = {
- .default_attrs = gfs_attrs,
- .sysfs_ops = &gfs_attr_ops,
-};
-
-static struct kset *gfs_kset;
-
-int gfs_sys_fs_add(struct gfs_sbd *sdp)
-{
- struct super_block *sb = sdp->sd_vfs;
- int error;
- char ro[20];
- char spectator[20];
- char *envp[] = { ro, spectator, NULL };
-
- sprintf(ro, "RDONLY=%d", (sb->s_flags & MS_RDONLY) ? 1 : 0);
- sprintf(spectator, "SPECTATOR=%d", sdp->sd_args.ar_spectator ? 1 : 0);
-
- sdp->sd_kobj.kset = gfs_kset;
- error = kobject_init_and_add(&sdp->sd_kobj, &gfs_ktype, NULL,
- "%s", sdp->sd_table_name);
- if (error)
- goto fail;
-
- error = sysfs_create_link(&sdp->sd_kobj,
- &disk_to_dev(sb->s_bdev->bd_disk)->kobj,
- "device");
- if (error)
- goto fail_put;
-
- kobject_uevent_env(&sdp->sd_kobj, KOBJ_ADD, envp);
-
- return 0;
-
-fail_put:
- kobject_put(&sdp->sd_kobj);
-fail:
- return error;
-}
-
-void gfs_sys_fs_del(struct gfs_sbd *sdp)
-{
- kobject_put(&sdp->sd_kobj);
-}
-
-static int gfs_uevent(struct kset *kset, struct kobject *kobj,
- struct kobj_uevent_env *env)
-{
- struct gfs_sbd *sdp = container_of(kobj, struct gfs_sbd, sd_kobj);
- add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name);
- add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name);
- if (!sdp->sd_args.ar_spectator)
- add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid);
- return 0;
-}
-
-static struct kset_uevent_ops gfs_uevent_ops = {
- .uevent = gfs_uevent,
-};
-
-int gfs_sys_init(void)
-{
- gfs_sys_margs = NULL;
- spin_lock_init(&gfs_sys_margs_lock);
- gfs_kset = kset_create_and_add("gfs", &gfs_uevent_ops, fs_kobj);
- if (!gfs_kset)
- return -ENOMEM;
- return 0;
-}
-
-void gfs_sys_uninit(void)
-{
- kfree(gfs_sys_margs);
- kset_unregister(gfs_kset);
-}
diff --git a/gfs-kernel/src/gfs/sys.h b/gfs-kernel/src/gfs/sys.h
deleted file mode 100644
index 0afa549..0000000
--- a/gfs-kernel/src/gfs/sys.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __SYS_DOT_H__
-#define __SYS_DOT_H__
-
-/* Allow args to be passed to GFS when using an initial ram disk */
-extern char *gfs_sys_margs;
-extern spinlock_t gfs_sys_margs_lock;
-
-int gfs_sys_fs_add(struct gfs_sbd *sdp);
-void gfs_sys_fs_del(struct gfs_sbd *sdp);
-
-int gfs_sys_init(void);
-void gfs_sys_uninit(void);
-
-#endif /* __SYS_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/trans.c b/gfs-kernel/src/gfs/trans.c
deleted file mode 100644
index 985533e..0000000
--- a/gfs-kernel/src/gfs/trans.c
+++ /dev/null
@@ -1,453 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "dio.h"
-#include "glock.h"
-#include "log.h"
-#include "lops.h"
-#include "quota.h"
-#include "trans.h"
-#include "unlinked.h"
-
-/**
- * gfs_trans_print - Print a transaction to the console
- * @sdp: the filesystem
- * @tr: The GFS transaction
- * @where: Situation of transaction
- *
- */
-
-void
-gfs_trans_print(struct gfs_sbd *sdp, struct gfs_trans *tr, unsigned int where)
-{
- struct gfs_log_element *le;
- struct list_head *tmp, *head;
- unsigned int mblks = 0, eblks = 0;
-
- LO_TRANS_SIZE(sdp, tr, &mblks, &eblks, NULL, NULL);
-
- printk("Transaction: (%s, %u)\n", tr->tr_file, tr->tr_line);
- printk(" tr_mblks_asked = %u, tr_eblks_asked = %u, tr_seg_reserved = %u\n",
- tr->tr_mblks_asked, tr->tr_eblks_asked, tr->tr_seg_reserved);
- printk(" mblks = %u, eblks = %u\n", mblks, eblks);
- printk(" tr_flags = 0x%.8X\n", tr->tr_flags);
-
- for (head = &tr->tr_elements, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- le = list_entry(tmp, struct gfs_log_element, le_list);
- LO_PRINT(sdp, le, where);
- }
-
- printk("End Trans\n");
-}
-
-/**
- * gfs_trans_begin_i - Prepare to start a transaction
- * @sdp: The GFS superblock
- * @meta_blocks: Reserve this many metadata blocks in the log
- * @extra_blocks: Number of non-metadata blocks to reserve
- *
- * Allocate the struct gfs_trans struct.
- * Grab a shared TRANSaction lock (protects this transaction from
- * overlapping with unusual fs writes, e.g. journal replay, fs upgrade,
- * while allowing simultaneous transaction writes throughout cluster).
- * Reserve space in the log. @meta_blocks and @extra_blocks must indicate
- * the worst case (maximum) size of the transaction.
- * Record this transaction as the *one* transaction being built by this
- * Linux process, in current->journal_info.
- *
- * Returns: errno
- */
-
-int
-gfs_trans_begin_i(struct gfs_sbd *sdp,
- unsigned int meta_blocks, unsigned int extra_blocks,
- char *file, unsigned int line)
-{
- struct gfs_trans *tr;
- unsigned int blocks;
- int error;
-
- tr = kmalloc(sizeof(struct gfs_trans), GFP_KERNEL);
- if (!tr)
- return -ENOMEM;
- memset(tr, 0, sizeof(struct gfs_trans));
-
- INIT_LIST_HEAD(&tr->tr_elements);
- INIT_LIST_HEAD(&tr->tr_free_bufs);
- INIT_LIST_HEAD(&tr->tr_free_bmem);
- INIT_LIST_HEAD(&tr->tr_bufs);
- INIT_LIST_HEAD(&tr->tr_ail_bufs);
- tr->tr_file = file;
- tr->tr_line = line;
-
- error = -ENOMEM;
- tr->tr_t_gh = gfs_holder_get(sdp->sd_trans_gl, LM_ST_SHARED, 0);
- if (!tr->tr_t_gh)
- goto fail;
-
- error = gfs_glock_nq(tr->tr_t_gh);
- if (error)
- goto fail_holder_put;
-
- if (test_bit(SDF_ROFS, &sdp->sd_flags)) {
- tr->tr_t_gh->gh_flags |= GL_NOCACHE;
- error = -EROFS;
- goto fail_gunlock;
- }
-
- /* Do log reservation */
-
- tr->tr_mblks_asked = meta_blocks;
- tr->tr_eblks_asked = extra_blocks;
-
- blocks = 1;
- if (meta_blocks)
- blocks += gfs_struct2blk(sdp, meta_blocks,
- sizeof(struct gfs_block_tag)) +
- meta_blocks;
- blocks += extra_blocks;
- tr->tr_seg_reserved = gfs_blk2seg(sdp, blocks);
-
- error = gfs_log_reserve(sdp, tr->tr_seg_reserved, FALSE);
- if (error)
- goto fail_gunlock;
-
- gfs_assert(sdp, !get_transaction,);
- set_transaction(tr);
-
- return 0;
-
- fail_gunlock:
- gfs_glock_dq(tr->tr_t_gh);
-
- fail_holder_put:
- gfs_holder_put(tr->tr_t_gh);
-
- fail:
- kfree(tr);
-
- return error;
-}
-
-/**
- * gfs_trans_end - End a transaction
- * @sdp: The GFS superblock
- *
- * If buffers were actually added to the transaction,
- * commit it.
- *
- */
-
-void
-gfs_trans_end(struct gfs_sbd *sdp)
-{
- struct gfs_trans *tr;
- struct gfs_holder *t_gh;
- struct list_head *tmp, *head;
- struct gfs_log_element *le;
-
- /* Linux task struct indicates current new trans for this process.
- * We're done building it, so set it to NULL */
- tr = get_transaction;
- gfs_assert(sdp, tr,);
- set_transaction(NULL);
-
- t_gh = tr->tr_t_gh;
- tr->tr_t_gh = NULL;
-
- /* If no buffers were ever added to trans, forget it */
- if (list_empty(&tr->tr_elements)) {
- gfs_log_release(sdp, tr->tr_seg_reserved);
- kfree(tr);
-
- gfs_glock_dq(t_gh);
- gfs_holder_put(t_gh);
-
- return;
- }
-
- /* Do trans_end log-operation for each log element */
- for (head = &tr->tr_elements, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- le = list_entry(tmp, struct gfs_log_element, le_list);
- LO_TRANS_END(sdp, le);
- }
-
- gfs_log_commit(sdp, tr);
-
- gfs_glock_dq(t_gh);
- gfs_holder_put(t_gh);
-
- if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS)
- gfs_log_flush(sdp);
-}
-
-/**
- * gfs_trans_add_gl - Add a glock to a transaction
- * @gl: the glock
- *
- * If not already attached, add the given glock to this process's transaction.
- *
- * Even though no glock info will be written to the on-disk log, the glocks
- * associated with a transaction provide bridges by which to combine
- * a just-built transaction with an earlier incore committed transaction
- * that was protected by the same glock. See incore_commit().
- * Combining transactions makes for more efficient logging.
- *
- * Note that more than one glock may be associated with a single transaction.
- * However, a given glock protects no more than *one* transaction at a
- * given stage in the transaction pipeline (i.e. new or incore-committed).
- * After all, the process holds the glock EX (so no other process can be
- * building a separate trans protected by this glock), and the process can
- * build only one transaction at a time.
- *
- * Rules:
- * This process must hold the glock in EXclusive mode, since we're going
- * to be writing to something protected by this glock.
- */
-
-void
-gfs_trans_add_gl(struct gfs_glock *gl)
-{
- if (!gl->gl_new_le.le_trans) {
- gfs_assert_withdraw(gl->gl_sbd,
- gfs_glock_is_locked_by_me(gl) &&
- gfs_glock_is_held_excl(gl));
- gfs_glock_hold(gl); /* Released in glock_trans_end() */
-
- /* Ask for eventual flush of (meta)data protected by this glock,
- once trans is complete and logged. */
- set_bit(GLF_DIRTY, &gl->gl_flags);
-
- /* Invoke generic_le_add() */
- LO_ADD(gl->gl_sbd, &gl->gl_new_le);
- gl->gl_new_le.le_trans->tr_num_gl++;
- }
-}
-
-/**
- * gfs_trans_add_bh - Add a to-be-modified buffer to the current transaction
- * @gl: the glock the buffer belongs to
- * @bh: The buffer to add
- *
- * Add a to-be-modified buffer to the current being-built (i.e. new) trans,
- * and pin the buffer in memory.
- *
- * Caller must hold the glock protecting this buffer.
- *
- * Call this as many times as you want during transaction formation. It does
- * its attachment work only once. After buffer is attached to trans, the
- * process building the trans can modify the buffer again and again (calling
- * this function before each change). Only the final result (within this trans)
- * will be written to log. A good example is when allocating blocks in an RG,
- * a given bitmap buffer may be updated many times within a transaction.
- *
- * Note: This final result will also be written to its in-place location,
- * unless this transaction gets combined with a later transaction,
- * in which case only the later result will go to in-place.
- *
- */
-
-void
-gfs_trans_add_bh(struct gfs_glock *gl, struct buffer_head *bh)
-{
- struct gfs_sbd *sdp = gl->gl_sbd;
- struct gfs_bufdata *bd;
-
- /* Make sure GFS private info struct is attached to buffer head */
- bd = get_v2bd(bh);
- if (!bd) {
- gfs_attach_bufdata(bh, gl);
- bd = get_v2bd(bh);
- }
-
- /* If buffer has already been attached to trans, we're done */
- if (bd->bd_new_le.le_trans)
- return;
-
- gfs_meta_check(sdp, bh);
-
- gfs_assert(sdp, bd->bd_gl == gl,);
-
- /* Make sure glock is attached to trans */
- if (!gl->gl_new_le.le_trans)
- gfs_trans_add_gl(gl);
-
- gfs_dpin(sdp, bh);
-
- /* Attach buffer to trans */
- LO_ADD(sdp, &bd->bd_new_le);
- bd->bd_new_le.le_trans->tr_num_buf++;
-}
-
-/**
- * gfs_trans_add_unlinked - Add an unlinked or dealloced tag to
- * the current transaction
- * @sdp: the filesystem
- * @type: the type of entry
- * @inum: the inode number
- *
- * Returns: the unlinked structure
- */
-
-struct gfs_unlinked *
-gfs_trans_add_unlinked(struct gfs_sbd *sdp, unsigned int type,
- struct gfs_inum *inum)
-{
- struct gfs_unlinked *ul;
-
- /* Find in fileystem's unlinked list, or create */
- ul = gfs_unlinked_get(sdp, inum, CREATE);
-
- LO_ADD(sdp, &ul->ul_new_le);
-
- switch (type) {
- case GFS_LOG_DESC_IUL:
- set_bit(ULF_NEW_UL, &ul->ul_flags);
- ul->ul_new_le.le_trans->tr_num_iul++;
- break;
- case GFS_LOG_DESC_IDA:
- clear_bit(ULF_NEW_UL, &ul->ul_flags);
- ul->ul_new_le.le_trans->tr_num_ida++;
- break;
- default:
- gfs_assert(sdp, FALSE,);
- break;
- }
-
- return ul;
-}
-
-/**
- * gfs_trans_add_quota - Add quota changes to a transaction
- * @sdp: the filesystem
- * @change: The number of blocks allocated (positive) or freed (negative)
- * @uid: the user ID doing the change
- * @gid: the group ID doing the change
- *
- */
-
-void
-gfs_trans_add_quota(struct gfs_sbd *sdp, int64_t change,
- uint32_t uid, uint32_t gid)
-{
- struct gfs_trans *tr;
- struct list_head *tmp, *head, *next;
- struct gfs_log_element *le;
- struct gfs_quota_le *ql;
- int found_uid, found_gid;
- int error;
-
- if (!gfs_tune_get(sdp, gt_quota_account))
- return;
- if (gfs_assert_warn(sdp, change))
- return;
-
- found_uid = (uid == NO_QUOTA_CHANGE);
- found_gid = (gid == NO_QUOTA_CHANGE);
-
- if (gfs_assert_warn(sdp, !found_uid || !found_gid))
- return;
-
- tr = get_transaction;
- gfs_assert(sdp, tr,);
-
- for (head = &tr->tr_elements, tmp = head->next, next = tmp->next;
- tmp != head;
- tmp = next, next = next->next) {
- le = list_entry(tmp, struct gfs_log_element, le_list);
- if (le->le_ops != &gfs_quota_lops)
- continue;
-
- ql = container_of(le, struct gfs_quota_le, ql_le);
-
- if (test_bit(QDF_USER, &ql->ql_data->qd_flags)) {
- if (ql->ql_data->qd_id == uid) {
- ql->ql_change += change;
-
- spin_lock(&sdp->sd_quota_lock);
- ql->ql_data->qd_change_new += change;
- spin_unlock(&sdp->sd_quota_lock);
-
- list_del(&le->le_list);
-
- if (ql->ql_change)
- list_add(&le->le_list,
- &tr->tr_elements);
- else {
- gfs_quota_put(sdp, ql->ql_data);
- kfree(ql);
- tr->tr_num_q--;
- }
-
- gfs_assert(sdp, !found_uid,);
- found_uid = TRUE;
- if (found_gid)
- break;
- }
- } else {
- if (ql->ql_data->qd_id == gid) {
- ql->ql_change += change;
-
- spin_lock(&sdp->sd_quota_lock);
- ql->ql_data->qd_change_new += change;
- spin_unlock(&sdp->sd_quota_lock);
-
- list_del(&le->le_list);
-
- if (ql->ql_change)
- list_add(&le->le_list,
- &tr->tr_elements);
- else {
- gfs_quota_put(sdp, ql->ql_data);
- kfree(ql);
- tr->tr_num_q--;
- }
-
- gfs_assert(sdp, !found_gid,);
- found_gid = TRUE;
- if (found_uid)
- break;
- }
- }
- }
-
- while (!found_uid || !found_gid) {
- ql = gmalloc(sizeof(struct gfs_quota_le));
- memset(ql, 0, sizeof(struct gfs_quota_le));
-
- INIT_LE(&ql->ql_le, &gfs_quota_lops);
-
- if (found_uid) {
- error = gfs_quota_get(sdp, FALSE, gid,
- NO_CREATE,
- &ql->ql_data);
- found_gid = TRUE;
- } else {
- error = gfs_quota_get(sdp, TRUE, uid,
- NO_CREATE,
- &ql->ql_data);
- found_uid = TRUE;
- }
-
- gfs_assert(sdp, !error && ql->ql_data,);
-
- ql->ql_change = change;
-
- spin_lock(&sdp->sd_quota_lock);
- ql->ql_data->qd_change_new += change;
- spin_unlock(&sdp->sd_quota_lock);
-
- LO_ADD(sdp, &ql->ql_le);
- tr->tr_num_q++;
- }
-}
diff --git a/gfs-kernel/src/gfs/trans.h b/gfs-kernel/src/gfs/trans.h
deleted file mode 100644
index 5d62b39..0000000
--- a/gfs-kernel/src/gfs/trans.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef __TRANS_DOT_H__
-#define __TRANS_DOT_H__
-
-#define TRANS_IS_NEW (53)
-#define TRANS_IS_INCORE (54)
-void gfs_trans_print(struct gfs_sbd *sdp, struct gfs_trans *tr,
- unsigned int where);
-
-int gfs_trans_begin_i(struct gfs_sbd *sdp,
- unsigned int meta_blocks, unsigned int extra_blocks,
- char *file, unsigned int line);
-#define gfs_trans_begin(sdp, mb, eb) \
-gfs_trans_begin_i((sdp), (mb), (eb), __FILE__, __LINE__)
-
-void gfs_trans_end(struct gfs_sbd *sdp);
-
-void gfs_trans_add_gl(struct gfs_glock *gl);
-void gfs_trans_add_bh(struct gfs_glock *gl, struct buffer_head *bh);
-struct gfs_unlinked *gfs_trans_add_unlinked(struct gfs_sbd *sdp, unsigned int type,
- struct gfs_inum *inum);
-void gfs_trans_add_quota(struct gfs_sbd *sdp, int64_t change, uint32_t uid,
- uint32_t gid);
-
-#endif /* __TRANS_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/unlinked.c b/gfs-kernel/src/gfs/unlinked.c
deleted file mode 100644
index d41c48a..0000000
--- a/gfs-kernel/src/gfs/unlinked.c
+++ /dev/null
@@ -1,432 +0,0 @@
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs.h"
-#include "inode.h"
-#include "log.h"
-#include "lops.h"
-#include "unlinked.h"
-
-/**
- * gfs_unlinked_get - Get a structure to represent an unlinked inode
- * @sdp: the filesystem
- * @inum: identifies the inode that's unlinked
- * @create: if TRUE, we're allowed to create the structure if we can't find it,
- * otherwise return NULL
- *
- * Returns: the structure, or NULL
- *
- * Search the filesystem's list of gfs_unlinked to find a match.
- * If none found, create a new one and place on list.
- */
-
-struct gfs_unlinked *
-gfs_unlinked_get(struct gfs_sbd *sdp, struct gfs_inum *inum, int create)
-{
- struct gfs_unlinked *ul = NULL, *new_ul = NULL;
- struct list_head *tmp, *head;
-
- for (;;) {
- spin_lock(&sdp->sd_unlinked_lock);
-
- for (head = &sdp->sd_unlinked_list, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- ul = list_entry(tmp, struct gfs_unlinked, ul_list);
- if (gfs_inum_equal(&ul->ul_inum, inum)) {
- ul->ul_count++;
- break;
- }
- }
-
- if (tmp == head)
- ul = NULL;
-
- /* 2nd pass, still not there; add the new_ul we prepared */
- if (!ul && new_ul) {
- ul = new_ul;
- list_add(&ul->ul_list, &sdp->sd_unlinked_list);
- new_ul = NULL;
- }
-
- spin_unlock(&sdp->sd_unlinked_lock);
-
- /* 1st pass; we found pre-existing, OR not allowed to create.
- 2nd pass; another process added it, or we did */
- if (ul || !create) {
- if (new_ul)
- /* someone beat us to it; forget our new_ul */
- kfree(new_ul);
- return ul;
- }
-
- /* No match on list, 1st time through loop.
- Prepare new_ul, then repeat loop to find out if another
- process has created or unlinked an inode and put its
- gfs_unlinked on list while we've been preparing this one. */
- new_ul = gmalloc(sizeof(struct gfs_unlinked));
- memset(new_ul, 0, sizeof(struct gfs_unlinked));
-
- new_ul->ul_count = 1;
- new_ul->ul_inum = *inum;
-
- INIT_LE(&new_ul->ul_new_le, &gfs_unlinked_lops);
- INIT_LE(&new_ul->ul_incore_le, &gfs_unlinked_lops);
- INIT_LE(&new_ul->ul_ondisk_le, &gfs_unlinked_lops);
- }
-}
-
-/**
- * gfs_unlinked_hold - increment the usage count on a struct gfs_unlinked
- * @sdp: the filesystem
- * @ul: the structure
- *
- */
-
-void
-gfs_unlinked_hold(struct gfs_sbd *sdp, struct gfs_unlinked *ul)
-{
- spin_lock(&sdp->sd_unlinked_lock);
- gfs_assert(sdp, ul->ul_count,);
- ul->ul_count++;
- spin_unlock(&sdp->sd_unlinked_lock);
-}
-
-/**
- * gfs_unlinked_put - decrement the usage count on a struct gfs_unlinked
- * @sdp: the filesystem
- * @ul: the structure
- *
- * Free the structure if its reference count hits zero.
- *
- */
-
-void
-gfs_unlinked_put(struct gfs_sbd *sdp, struct gfs_unlinked *ul)
-{
- spin_lock(&sdp->sd_unlinked_lock);
-
- gfs_assert(sdp, ul->ul_count,);
- ul->ul_count--;
-
- if (!ul->ul_count) {
- gfs_assert_warn(sdp,
- !test_bit(ULF_IC_LIST, &ul->ul_flags) &&
- !test_bit(ULF_OD_LIST, &ul->ul_flags) &&
- !test_bit(ULF_LOCK, &ul->ul_flags));
- list_del(&ul->ul_list);
- spin_unlock(&sdp->sd_unlinked_lock);
- kfree(ul);
- } else
- spin_unlock(&sdp->sd_unlinked_lock);
-}
-
-/**
- * unlinked_find - Find a inode to try to deallocate
- * @sdp: the filesystem
- *
- * The returned structure is locked and needs to be unlocked
- * with gfs_unlinked_unlock().
- *
- * Returns: A unlinked structure, or NULL
- */
-
-struct gfs_unlinked *
-unlinked_find(struct gfs_sbd *sdp)
-{
- struct list_head *tmp, *head;
- struct gfs_unlinked *ul = NULL;
-
- if (test_bit(SDF_ROFS, &sdp->sd_flags))
- return NULL;
-
- gfs_log_lock(sdp);
- spin_lock(&sdp->sd_unlinked_lock);
-
- if (!atomic_read(&sdp->sd_unlinked_ic_count))
- goto out;
-
- for (head = &sdp->sd_unlinked_list, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- ul = list_entry(tmp, struct gfs_unlinked, ul_list);
-
- if (test_bit(ULF_LOCK, &ul->ul_flags))
- continue;
- if (!test_bit(ULF_IC_LIST, &ul->ul_flags))
- continue;
-
- list_move_tail(&ul->ul_list, &sdp->sd_unlinked_list);
-
- set_bit(ULF_LOCK, &ul->ul_flags);
- ul->ul_count++;
-
- goto out;
- }
-
- ul = NULL;
-
- out:
- spin_unlock(&sdp->sd_unlinked_lock);
- gfs_log_unlock(sdp);
-
- return ul;
-}
-
-/**
- * gfs_unlinked_lock - lock a unlinked structure
- * @sdp: the filesystem
- * @ul: the unlinked inode structure
- *
- */
-
-void
-gfs_unlinked_lock(struct gfs_sbd *sdp, struct gfs_unlinked *ul)
-{
- spin_lock(&sdp->sd_unlinked_lock);
-
- gfs_assert_warn(sdp, !test_bit(ULF_LOCK, &ul->ul_flags));
- set_bit(ULF_LOCK, &ul->ul_flags);
-
- ul->ul_count++;
-
- spin_unlock(&sdp->sd_unlinked_lock);
-}
-
-/**
- * gfs_unlinked_unlock - drop a reference on a unlinked structure
- * @sdp: the filesystem
- * @ul: the unlinked inode structure
- *
- */
-
-void
-gfs_unlinked_unlock(struct gfs_sbd *sdp, struct gfs_unlinked *ul)
-{
- spin_lock(&sdp->sd_unlinked_lock);
-
- gfs_assert_warn(sdp, test_bit(ULF_LOCK, &ul->ul_flags));
- clear_bit(ULF_LOCK, &ul->ul_flags);
-
- gfs_assert(sdp, ul->ul_count,);
- ul->ul_count--;
-
- if (!ul->ul_count) {
- gfs_assert_warn(sdp, !test_bit(ULF_IC_LIST, &ul->ul_flags) &&
- !test_bit(ULF_OD_LIST, &ul->ul_flags));
- list_del(&ul->ul_list);
- spin_unlock(&sdp->sd_unlinked_lock);
- kfree(ul);
- } else
- spin_unlock(&sdp->sd_unlinked_lock);
-}
-
-/**
- * gfs_unlinked_merge - add/remove a unlinked inode from the in-memory list
- * @sdp: the filesystem
- * @type: is this a unlink tag or a dealloc tag
- * @inum: the inode number
- *
- * Called during journal recovery.
- */
-
-void
-gfs_unlinked_merge(struct gfs_sbd *sdp, unsigned int type,
- struct gfs_inum *inum)
-{
- struct gfs_unlinked *ul;
-
- gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_ic_count) ==
- atomic_read(&sdp->sd_unlinked_od_count),);
-
- ul = gfs_unlinked_get(sdp, inum, CREATE);
-
- gfs_log_lock(sdp);
-
- switch (type) {
- case GFS_LOG_DESC_IUL:
- gfs_unlinked_hold(sdp, ul);
- gfs_unlinked_hold(sdp, ul);
- gfs_assert(sdp, !test_bit(ULF_IC_LIST, &ul->ul_flags) &&
- !test_bit(ULF_OD_LIST, &ul->ul_flags),);
- set_bit(ULF_IC_LIST, &ul->ul_flags);
- set_bit(ULF_OD_LIST, &ul->ul_flags);
- atomic_inc(&sdp->sd_unlinked_ic_count);
- atomic_inc(&sdp->sd_unlinked_od_count);
-
- break;
-
- case GFS_LOG_DESC_IDA:
- gfs_assert(sdp, test_bit(ULF_IC_LIST, &ul->ul_flags) &&
- test_bit(ULF_OD_LIST, &ul->ul_flags),);
- clear_bit(ULF_IC_LIST, &ul->ul_flags);
- clear_bit(ULF_OD_LIST, &ul->ul_flags);
- gfs_unlinked_put(sdp, ul);
- gfs_unlinked_put(sdp, ul);
- gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_ic_count) > 0,);
- atomic_dec(&sdp->sd_unlinked_ic_count);
- gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_od_count) > 0,);
- atomic_dec(&sdp->sd_unlinked_od_count);
-
- break;
- }
-
- gfs_log_unlock(sdp);
-
- gfs_unlinked_put(sdp, ul);
-}
-
-/**
- * gfs_unlinked_cleanup - get rid of any extra struct gfs_unlinked structures
- * @sdp: the filesystem
- *
- */
-
-void
-gfs_unlinked_cleanup(struct gfs_sbd *sdp)
-{
- struct gfs_unlinked *ul;
-
- restart:
- gfs_log_lock(sdp);
-
- gfs_assert(sdp, atomic_read(&sdp->sd_unlinked_ic_count) ==
- atomic_read(&sdp->sd_unlinked_od_count),);
-
- spin_lock(&sdp->sd_unlinked_lock);
-
- while (!list_empty(&sdp->sd_unlinked_list)) {
- ul = list_entry(sdp->sd_unlinked_list.next,
- struct gfs_unlinked, ul_list);
-
- if (ul->ul_count > 2) {
- spin_unlock(&sdp->sd_unlinked_lock);
- gfs_log_unlock(sdp);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
- goto restart;
- }
- gfs_assert(sdp, ul->ul_count == 2,);
-
- gfs_assert_warn(sdp,
- test_bit(ULF_IC_LIST, &ul->ul_flags) &&
- test_bit(ULF_OD_LIST, &ul->ul_flags) &&
- !test_bit(ULF_LOCK, &ul->ul_flags));
-
- list_del(&ul->ul_list);
-
- atomic_dec(&sdp->sd_unlinked_ic_count);
- atomic_dec(&sdp->sd_unlinked_od_count);
-
- spin_unlock(&sdp->sd_unlinked_lock);
- kfree(ul);
- spin_lock(&sdp->sd_unlinked_lock);
- }
-
- spin_unlock(&sdp->sd_unlinked_lock);
-
- gfs_assert(sdp, !atomic_read(&sdp->sd_unlinked_ic_count) &&
- !atomic_read(&sdp->sd_unlinked_od_count),);
-
- gfs_log_unlock(sdp);
-}
-
-/**
- * gfs_unlinked_limit - limit the number of inodes waiting to be deallocated
- * @sdp: the filesystem
- *
- * Returns: errno
- */
-
-void
-gfs_unlinked_limit(struct gfs_sbd *sdp)
-{
- unsigned int tries = 0, min = 0;
- int error;
-
- if (atomic_read(&sdp->sd_unlinked_ic_count) >=
- gfs_tune_get(sdp, gt_ilimit2)) {
- tries = gfs_tune_get(sdp, gt_ilimit2_tries);
- min = gfs_tune_get(sdp, gt_ilimit2_min);
- } else if (atomic_read(&sdp->sd_unlinked_ic_count) >=
- gfs_tune_get(sdp, gt_ilimit1)) {
- tries = gfs_tune_get(sdp, gt_ilimit1_tries);
- min = gfs_tune_get(sdp, gt_ilimit1_min);
- }
-
- while (tries--) {
- struct gfs_unlinked *ul = unlinked_find(sdp);
- if (!ul)
- break;
-
- error = gfs_inode_dealloc(sdp, &ul->ul_inum);
-
- gfs_unlinked_unlock(sdp, ul);
-
- if (!error) {
- if (!--min)
- break;
- } else if (error != 1)
- break;
- }
-}
-
-/**
- * gfs_unlinked_dealloc - Go through the list of inodes to be deallocated
- * @sdp: the filesystem
- *
- * Returns: errno
- */
-
-void
-gfs_unlinked_dealloc(struct gfs_sbd *sdp)
-{
- unsigned int hits, strikes;
- int error;
-
- for (;;) {
- hits = 0;
- strikes = 0;
-
- for (;;) {
- struct gfs_unlinked *ul = unlinked_find(sdp);
- if (!ul)
- return;
-
- error = gfs_inode_dealloc(sdp, &ul->ul_inum);
-
- gfs_unlinked_unlock(sdp, ul);
-
- if (!error) {
- hits++;
- if (strikes)
- strikes--;
- } else if (error == 1) {
- strikes++;
- if (strikes >= atomic_read(&sdp->sd_unlinked_ic_count)) {
- error = 0;
- break;
- }
- } else
- goto out;
- }
-
- if (!hits || kthread_should_stop())
- break;
-
- cond_resched();
- }
-
- out:
- if (error &&
- error != -EROFS &&
- !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
- printk("GFS: fsid=%s: error deallocating inodes: %d\n",
- sdp->sd_fsname, error);
-}
diff --git a/gfs-kernel/src/gfs/unlinked.h b/gfs-kernel/src/gfs/unlinked.h
deleted file mode 100644
index 1881bad..0000000
--- a/gfs-kernel/src/gfs/unlinked.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __UNLINKED_DOT_H__
-#define __UNLINKED_DOT_H__
-
-struct gfs_unlinked *gfs_unlinked_get(struct gfs_sbd *sdp,
- struct gfs_inum *inum, int create);
-void gfs_unlinked_hold(struct gfs_sbd *sdp, struct gfs_unlinked *ul);
-void gfs_unlinked_put(struct gfs_sbd *sdp, struct gfs_unlinked *ul);
-
-void gfs_unlinked_lock(struct gfs_sbd *sdp, struct gfs_unlinked *ul);
-void gfs_unlinked_unlock(struct gfs_sbd *sdp, struct gfs_unlinked *ul);
-
-void gfs_unlinked_merge(struct gfs_sbd *sdp, unsigned int type,
- struct gfs_inum *inum);
-void gfs_unlinked_cleanup(struct gfs_sbd *sdp);
-
-void gfs_unlinked_limit(struct gfs_sbd *sdp);
-void gfs_unlinked_dealloc(struct gfs_sbd *sdp);
-
-#endif /* __UNLINKED_DOT_H__ */
diff --git a/gfs-kernel/src/gfs/util.c b/gfs-kernel/src/gfs/util.c
deleted file mode 100644
index 869e479..0000000
--- a/gfs-kernel/src/gfs/util.c
+++ /dev/null
@@ -1,590 +0,0 @@
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/semaphore.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <asm/uaccess.h>
-
-#include "gfs.h"
-#include "glock.h"
-#include "lm.h"
-#include "super.h"
-
-uint32_t gfs_random_number;
-
-struct kmem_cache *gfs_glock_cachep = NULL;
-struct kmem_cache *gfs_inode_cachep = NULL;
-struct kmem_cache *gfs_bufdata_cachep = NULL;
-struct kmem_cache *gfs_mhc_cachep = NULL;
-
-/**
- * gfs_random - Generate a random 32-bit number
- *
- * Generate a semi-crappy 32-bit pseudo-random number without using
- * floating point.
- *
- * The PRNG is from "Numerical Recipes in C" (second edition), page 284.
- *
- * Returns: a 32-bit random number
- */
-
-uint32_t
-gfs_random(void)
-{
- gfs_random_number = 0x0019660D * gfs_random_number + 0x3C6EF35F;
- return gfs_random_number;
-}
-
-/**
- * hash_more_internal - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- * @hash: the hash from a previous call
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * This is the 32-bit FNV-1a hash from:
- * http://www.isthe.com/chongo/tech/comp/fnv/
- *
- * Hash guts
- *
- * Returns: the hash
- */
-
-static __inline__ uint32_t
-hash_more_internal(const void *data, unsigned int len, uint32_t hash)
-{
- unsigned char *p = (unsigned char *)data;
- unsigned char *e = p + len;
- uint32_t h = hash;
-
- while (p < e) {
- h ^= (uint32_t)(*p++);
- h *= 0x01000193;
- }
-
- return h;
-}
-
-/**
- * gfs_hash - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * This is the 32-bit FNV-1a hash from:
- * http://www.isthe.com/chongo/tech/comp/fnv/
- *
- * Returns: the hash
- */
-
-uint32_t
-gfs_hash(const void *data, unsigned int len)
-{
- uint32_t h = 0x811C9DC5;
- h = hash_more_internal(data, len, h);
- return h;
-}
-
-/**
- * gfs_hash_more - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- * @hash: the hash from a previous call
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * This is the 32-bit FNV-1a hash from:
- * http://www.isthe.com/chongo/tech/comp/fnv/
- *
- * This version let's you hash together discontinuous regions.
- * For example, to compute the combined hash of the memory in
- * (data1, len1), (data2, len2), and (data3, len3) you:
- *
- * h = gfs_hash(data1, len1);
- * h = gfs_hash_more(data2, len2, h);
- * h = gfs_hash_more(data3, len3, h);
- *
- * Returns: the hash
- */
-
-uint32_t
-gfs_hash_more(const void *data, unsigned int len, uint32_t hash)
-{
- uint32_t h;
- h = hash_more_internal(data, len, hash);
- return h;
-}
-
-/* Byte-wise swap two items of size SIZE. */
-
-#define SWAP(a, b, size) \
-do { \
- register size_t __size = (size); \
- register char *__a = (a), *__b = (b); \
- do { \
- char __tmp = *__a; \
- *__a++ = *__b; \
- *__b++ = __tmp; \
- } while (__size-- > 1); \
-} while (0)
-
-/**
- * gfs_sort - Sort base array using shell sort algorithm
- * @base: the input array
- * @num_elem: number of elements in array
- * @size: size of each element in array
- * @compar: fxn to compare array elements (returns negative
- * for lt, 0 for eq, and positive for gt
- *
- * Sorts the array passed in using the compar fxn to compare elements using
- * the shell sort algorithm
- */
-
-void
-gfs_sort(void *base, unsigned int num_elem, unsigned int size,
- int (*compar) (const void *, const void *))
-{
- register char *pbase = (char *)base;
- int i, j, k, h;
- static int cols[16] = {1391376, 463792, 198768, 86961,
- 33936, 13776, 4592, 1968,
- 861, 336, 112, 48,
- 21, 7, 3, 1};
-
- for (k = 0; k < 16; k++) {
- h = cols[k];
- for (i = h; i < num_elem; i++) {
- j = i;
- while (j >= h &&
- (*compar)((void *)(pbase + size * (j - h)),
- (void *)(pbase + size * j)) > 0) {
- SWAP(pbase + size * j,
- pbase + size * (j - h),
- size);
- j = j - h;
- }
- }
- }
-}
-
-/**
- * gfs_assert_i - Cause the machine to panic if @assertion is false
- * @sdp:
- * @assertion:
- * @function:
- * @file:
- * @line:
- *
- */
-
-void
-gfs_assert_i(struct gfs_sbd *sdp,
- char *assertion,
- const char *function,
- char *file, unsigned int line)
-{
- if (sdp->sd_args.ar_oopses_ok) {
- printk("GFS: fsid=%s: assertion \"%s\" failed\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname, assertion,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
- if (sdp->sd_args.ar_errors == GFS_ERRORS_WITHDRAW)
- BUG();
- }
- dump_stack();
- panic("GFS: fsid=%s: assertion \"%s\" failed\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname, assertion,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
-}
-
-/**
- * gfs_assert_withdraw_i - Cause the machine to withdraw if @assertion is false
- * @sdp:
- * @assertion:
- * @function:
- * @file:
- * @line:
- *
- * Returns: -1 if this call withdrew the machine,
- * -2 if it was already withdrawn
- */
-
-int
-gfs_assert_withdraw_i(struct gfs_sbd *sdp,
- char *assertion,
- const char *function,
- char *file, unsigned int line)
-{
- int me;
- me = gfs_lm_withdraw(sdp,
- "GFS: fsid=%s: fatal: assertion \"%s\" failed\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname, assertion,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
- return (me) ? -1 : -2;
-}
-
-/**
- * gfs_assert_warn_i - Print a message to the console if @assertion is false
- * @sdp:
- * @assertion:
- * @function:
- * @file:
- * @line:
- *
- * Returns: -1 if we printed something
- * -2 if we didn't
- */
-
-int
-gfs_assert_warn_i(struct gfs_sbd *sdp,
- char *assertion,
- const char *function,
- char *file, unsigned int line)
-{
- if (time_before(jiffies,
- sdp->sd_last_warning +
- gfs_tune_get(sdp, gt_complain_secs) * HZ))
- return -2;
-
- if (sdp->sd_args.ar_errors == GFS_ERRORS_WITHDRAW)
- printk("GFS: fsid=%s: warning: assertion \"%s\" failed\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname, assertion,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
-
- if (sdp->sd_args.ar_errors != GFS_ERRORS_WITHDRAW)
- dump_stack();
- sdp->sd_last_warning = jiffies;
- if (sdp->sd_args.ar_debug)
- BUG();
- if (sdp->sd_args.ar_errors == GFS_ERRORS_PANIC)
- panic("GFS: fsid=%s: assertion \"%s\" failed\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname, assertion,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
-
- return -1;
-}
-
-/**
- * gfs_consist_i - Flag a filesystem consistency error and withdraw
- * @sdp:
- * @cluster_wide:
- * @function:
- * @file:
- * @line:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int
-gfs_consist_i(struct gfs_sbd *sdp, int cluster_wide,
- const char *function,
- char *file, unsigned int line)
-{
- return gfs_lm_withdraw(sdp,
- "GFS: fsid=%s: fatal: filesystem consistency error\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
-}
-
-/**
- * gfs_consist_inode_i - Flag an inode consistency error and withdraw
- * @ip:
- * @cluster_wide:
- * @function:
- * @file:
- * @line:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int
-gfs_consist_inode_i(struct gfs_inode *ip, int cluster_wide,
- const char *function,
- char *file, unsigned int line)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- return gfs_lm_withdraw(sdp,
- "GFS: fsid=%s: fatal: filesystem consistency error\n"
- "GFS: fsid=%s: inode = %llu/%llu\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname,
- sdp->sd_fsname,
- (unsigned long long)ip->i_num.no_formal_ino,
- (unsigned long long)ip->i_num.no_addr,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
-}
-
-/**
- * gfs_consist_rgrpd_i - Flag a RG consistency error and withdraw
- * @rgd:
- * @cluster_wide:
- * @function:
- * @file:
- * @line:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int
-gfs_consist_rgrpd_i(struct gfs_rgrpd *rgd, int cluster_wide,
- const char *function,
- char *file, unsigned int line)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- return gfs_lm_withdraw(sdp,
- "GFS: fsid=%s: fatal: filesystem consistency error\n"
- "GFS: fsid=%s: RG = %llu\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname,
- sdp->sd_fsname,
- (unsigned long long)rgd->rd_ri.ri_addr,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
-}
-
-/**
- * gfs_meta_check_ii - Flag a magic number consistency error and withdraw
- * @sdp:
- * @bh:
- * @function:
- * @file:
- * @line:
- *
- * Returns: -1 if this call withdrew the machine,
- * -2 if it was already withdrawn
- */
-
-int
-gfs_meta_check_ii(struct gfs_sbd *sdp, struct buffer_head *bh,
- const char *function,
- char *file, unsigned int line)
-{
- int me;
- me = gfs_lm_withdraw(sdp,
- "GFS: fsid=%s: fatal: invalid metadata block\n"
- "GFS: fsid=%s: bh = %llu (magic)\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname,
- sdp->sd_fsname, (unsigned long long)bh->b_blocknr,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
- return (me) ? -1 : -2;
-}
-
-/**
- * gfs_metatype_check_ii - Flag a metadata type consistency error and withdraw
- * @sdp:
- * @bh:
- * @type:
- * @t:
- * @function:
- * @file:
- * @line:
- *
- * Returns: -1 if this call withdrew the machine,
- * -2 if it was already withdrawn
- */
-
-int
-gfs_metatype_check_ii(struct gfs_sbd *sdp, struct buffer_head *bh,
- uint32_t type, uint32_t t,
- const char *function,
- char *file, unsigned int line)
-{
- int me;
- me = gfs_lm_withdraw(sdp,
- "GFS: fsid=%s: fatal: invalid metadata block\n"
- "GFS: fsid=%s: bh = %llu (type: exp=%u, found=%u)\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname,
- sdp->sd_fsname, (unsigned long long)bh->b_blocknr,
- type, t, sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
- return (me) ? -1 : -2;
-}
-
-/**
- * gfs_io_error_i - Flag an I/O error and withdraw
- * @sdp:
- * @function:
- * @file:
- * @line:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int
-gfs_io_error_i(struct gfs_sbd *sdp,
- const char *function,
- char *file, unsigned int line)
-{
- return gfs_lm_withdraw(sdp,
- "GFS: fsid=%s: fatal: I/O error\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
-}
-
-/**
- * gfs_io_error_inode_i - Flag an inode I/O error and withdraw
- * @ip:
- * @function:
- * @file:
- * @line:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int
-gfs_io_error_inode_i(struct gfs_inode *ip,
- const char *function,
- char *file, unsigned int line)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- return gfs_lm_withdraw(sdp,
- "GFS: fsid=%s: fatal: I/O error\n"
- "GFS: fsid=%s: inode = %llu/%llu\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname,
- sdp->sd_fsname,
- (unsigned long long)ip->i_num.no_formal_ino,
- (unsigned long long)ip->i_num.no_addr,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
-}
-
-/**
- * gfs_io_error_bh_i - Flag a buffer I/O error and withdraw
- * @sdp:
- * @bh:
- * @function:
- * @file:
- * @line:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int
-gfs_io_error_bh_i(struct gfs_sbd *sdp, struct buffer_head *bh,
- const char *function,
- char *file, unsigned int line)
-{
- return gfs_lm_withdraw(sdp,
- "GFS: fsid=%s: fatal: I/O error\n"
- "GFS: fsid=%s: block = %llu\n"
- "GFS: fsid=%s: function = %s\n"
- "GFS: fsid=%s: file = %s, line = %u\n"
- "GFS: fsid=%s: time = %lu\n",
- sdp->sd_fsname,
- sdp->sd_fsname,
- (unsigned long long)bh->b_blocknr,
- sdp->sd_fsname, function,
- sdp->sd_fsname, file, line,
- sdp->sd_fsname, get_seconds());
-}
-
-/**
- * gmalloc - malloc a small amount of memory
- * @size: the number of bytes to malloc
- *
- * Returns: the memory
- */
-
-void *
-gmalloc(unsigned int size)
-{
- void *p;
- RETRY_MALLOC(p = kmalloc(size, GFP_KERNEL), p);
- return p;
-}
-
-/**
- * gfs_add_bh_to_ub - copy a buffer up to user space
- * @ub: the structure representing where to copy
- * @bh: the buffer
- *
- * Returns: errno
- */
-
-int
-gfs_add_bh_to_ub(struct gfs_user_buffer *ub, struct buffer_head *bh)
-{
- uint64_t blkno = bh->b_blocknr;
-
- if (ub->ub_count + sizeof(uint64_t) + bh->b_size > ub->ub_size)
- return -ENOMEM;
-
- if (copy_to_user(ub->ub_data + ub->ub_count,
- &blkno,
- sizeof(uint64_t)))
- return -EFAULT;
- ub->ub_count += sizeof(uint64_t);
-
- if (copy_to_user(ub->ub_data + ub->ub_count,
- bh->b_data,
- bh->b_size))
- return -EFAULT;
- ub->ub_count += bh->b_size;
-
- return 0;
-}
-
diff --git a/gfs-kernel/src/gfs/util.h b/gfs-kernel/src/gfs/util.h
deleted file mode 100644
index 4849f55..0000000
--- a/gfs-kernel/src/gfs/util.h
+++ /dev/null
@@ -1,330 +0,0 @@
-#ifndef __UTIL_DOT_H__
-#define __UTIL_DOT_H__
-
-
-/* Utility functions */
-
-extern uint32_t gfs_random_number;
-uint32_t gfs_random(void);
-
-uint32_t gfs_hash(const void *data, unsigned int len);
-uint32_t gfs_hash_more(const void *data, unsigned int len, uint32_t hash);
-
-void gfs_sort(void *base, unsigned int num_elem, unsigned int size,
- int (*compar) (const void *, const void *));
-
-
-/* Error handling */
-
-/**
- * gfs_assert - Cause the machine to panic if @assertion is false
- * @sdp:
- * @assertion:
- * @todo:
- *
- */
-
-void gfs_assert_i(struct gfs_sbd *sdp,
- char *assertion,
- const char *function,
- char *file, unsigned int line)
-__attribute__ ((noreturn));
-#define gfs_assert(sdp, assertion, todo) \
-do { \
- if (unlikely(!(assertion))) { \
- {todo} \
- gfs_assert_i((sdp), #assertion, \
- __FUNCTION__, __FILE__, __LINE__); \
- } \
-} while (0)
-
-/**
- * gfs_assert_withdraw - Cause the machine to withdraw if @assertion is false
- * @sdp:
- * @assertion:
- *
- * Returns: 0 if things are ok,
- * -1 if this call withdrew the machine,
- * -2 if it was already withdrawn
- */
-
-int gfs_assert_withdraw_i(struct gfs_sbd *sdp,
- char *assertion,
- const char *function,
- char *file, unsigned int line);
-#define gfs_assert_withdraw(sdp, assertion) \
-((likely(assertion)) ? 0 : \
- gfs_assert_withdraw_i((sdp), #assertion, \
- __FUNCTION__, __FILE__, __LINE__))
-
-/**
- * gfs_assert_warn - Print a message to the console if @assertion is false
- * @sdp:
- * @assertion:
- *
- * Returns: 0 if things are ok,
- * -1 if we printed something
- * -2 if we didn't
- */
-
-int gfs_assert_warn_i(struct gfs_sbd *sdp,
- char *assertion,
- const char *function,
- char *file, unsigned int line);
-#define gfs_assert_warn(sdp, assertion) \
-((likely(assertion)) ? 0 : \
- gfs_assert_warn_i((sdp), #assertion, \
- __FUNCTION__, __FILE__, __LINE__))
-
-/**
- * gfs_consist - Flag a filesystem consistency error and withdraw
- * gfs_cconsist - Flag a filesystem consistency error and withdraw cluster
- * @sdp:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int gfs_consist_i(struct gfs_sbd *sdp, int cluster_wide,
- const char *function,
- char *file, unsigned int line);
-#define gfs_consist(sdp)\
-gfs_consist_i((sdp), FALSE, __FUNCTION__, __FILE__, __LINE__)
-#define gfs_cconsist(sdp)\
-gfs_consist_i((sdp), TRUE, __FUNCTION__, __FILE__, __LINE__)
-
-/**
- * gfs_consist_inode - Flag an inode consistency error and withdraw
- * gfs_cconsist_inode - Flag an inode consistency error and withdraw cluster
- * @ip:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int gfs_consist_inode_i(struct gfs_inode *ip, int cluster_wide,
- const char *function,
- char *file, unsigned int line);
-#define gfs_consist_inode(ip) \
-gfs_consist_inode_i((ip), FALSE, __FUNCTION__, __FILE__, __LINE__)
-#define gfs_cconsist_inode(ip) \
-gfs_consist_inode_i((ip), TRUE, __FUNCTION__, __FILE__, __LINE__)
-
-/**
- * gfs_consist_rgrpd - Flag a RG consistency error and withdraw
- * gfs_cconsist_rgrpd - Flag a RG consistency error and withdraw cluster
- * @rgd:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int gfs_consist_rgrpd_i(struct gfs_rgrpd *rgd, int cluster_wide,
- const char *function,
- char *file, unsigned int line);
-#define gfs_consist_rgrpd(rgd) \
-gfs_consist_rgrpd_i((rgd), FALSE, __FUNCTION__, __FILE__, __LINE__)
-#define gfs_cconsist_rgrpd(rgd) \
-gfs_consist_rgrpd_i((rgd), TRUE, __FUNCTION__, __FILE__, __LINE__)
-
-/**
- * gfs_meta_check - Flag a magic number consistency error and withdraw
- * @sdp:
- * @bh:
- *
- * Returns: 0 if things are ok,
- * -1 if this call withdrew the machine,
- * -2 if it was already withdrawn
- */
-
-int gfs_meta_check_ii(struct gfs_sbd *sdp, struct buffer_head *bh,
- const char *function,
- char *file, unsigned int line);
-static __inline__ int
-gfs_meta_check_i(struct gfs_sbd *sdp, struct buffer_head *bh,
- const char *function,
- char *file, unsigned int line)
-{
- uint32_t magic;
- magic = ((struct gfs_meta_header *)(bh)->b_data)->mh_magic;
- magic = gfs32_to_cpu(magic);
- if (likely(magic == GFS_MAGIC))
- return 0;
- return gfs_meta_check_ii(sdp, bh, function, file, line);
-}
-#define gfs_meta_check(sdp, bh) \
-gfs_meta_check_i((sdp), (bh), \
- __FUNCTION__, __FILE__, __LINE__)
-
-/**
- * gfs_metatype_check - Flag a metadata type consistency error and withdraw
- * @sdp:
- * @bh:
- * @type:
- *
- * Returns: 0 if things are ok,
- * -1 if this call withdrew the machine,
- * -2 if it was already withdrawn
- */
-
-int gfs_metatype_check_ii(struct gfs_sbd *sdp, struct buffer_head *bh,
- uint32_t type, uint32_t t,
- const char *function,
- char *file, unsigned int line);
-static __inline__ int
-gfs_metatype_check_i(struct gfs_sbd *sdp, struct buffer_head *bh,
- uint32_t type,
- const char *function,
- char *file, unsigned int line)
-{
- uint32_t magic, t;
- magic = ((struct gfs_meta_header *)(bh)->b_data)->mh_magic;
- magic = gfs32_to_cpu(magic);
- if (unlikely(magic != GFS_MAGIC))
- return gfs_meta_check_ii(sdp, bh, function, file, line);
- t = ((struct gfs_meta_header *)(bh)->b_data)->mh_type;
- t = gfs32_to_cpu(t);
- if (unlikely(t != type))
- return gfs_metatype_check_ii(sdp, bh, type, t, function, file, line);
- return 0;
-}
-#define gfs_metatype_check(sdp, bh, type) \
-gfs_metatype_check_i((sdp), (bh), (type), \
- __FUNCTION__, __FILE__, __LINE__)
-
-/**
- * gfs_metatype_check2 - Flag a metadata type consistency error and withdraw
- * @sdp:
- * @bh:
- * @type1:
- * @type2:
- *
- * Returns: 0 if things are ok,
- * -1 if this call withdrew the machine,
- * -2 if it was already withdrawn
- */
-
-static __inline__ int
-gfs_metatype_check2_i(struct gfs_sbd *sdp, struct buffer_head *bh,
- uint32_t type1, uint32_t type2,
- const char *function,
- char *file, unsigned int line)
-{
- uint32_t magic, t;
- magic = ((struct gfs_meta_header *)(bh)->b_data)->mh_magic;
- magic = gfs32_to_cpu(magic);
- if (unlikely(magic != GFS_MAGIC))
- return gfs_meta_check_ii(sdp, bh, function, file, line);
- t = ((struct gfs_meta_header *)(bh)->b_data)->mh_type;
- t = gfs32_to_cpu(t);
- if (unlikely(t != type1 && t != type2))
- return gfs_metatype_check_ii(sdp, bh, type1, t, function, file, line);
- return 0;
-}
-#define gfs_metatype_check2(sdp, bh, type1, type2) \
-gfs_metatype_check2_i((sdp), (bh), (type1), (type2), \
- __FUNCTION__, __FILE__, __LINE__)
-
-/**
- * gfs_metatype_set - set the metadata type on a buffer
- * @bh:
- * @type:
- * @format:
- *
- */
-
-static __inline__ void
-gfs_metatype_set(struct buffer_head *bh, uint32_t type, uint32_t format)
-{
- struct gfs_meta_header *mh;
- mh = (struct gfs_meta_header *)bh->b_data;
- mh->mh_type = cpu_to_gfs32(type);
- mh->mh_format = cpu_to_gfs32(format);
-}
-
-/**
- * gfs_io_error - Flag an I/O error and withdraw
- * @sdp:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int gfs_io_error_i(struct gfs_sbd *sdp,
- const char *function,
- char *file, unsigned int line);
-#define gfs_io_error(sdp) \
-gfs_io_error_i((sdp), __FUNCTION__, __FILE__, __LINE__);
-
-/**
- * gfs_io_error_inode - Flag an inode I/O error and withdraw
- * @ip:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int gfs_io_error_inode_i(struct gfs_inode *ip,
- const char *function,
- char *file, unsigned int line);
-#define gfs_io_error_inode(ip) \
-gfs_io_error_inode_i((ip), __FUNCTION__, __FILE__, __LINE__);
-
-/**
- * gfs_io_error_bh - Flag a buffer I/O error and withdraw
- * @sdp:
- * @bh:
- *
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
- */
-
-int gfs_io_error_bh_i(struct gfs_sbd *sdp, struct buffer_head *bh,
- const char *function,
- char *file, unsigned int line);
-#define gfs_io_error_bh(sdp, bh) \
-gfs_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__);
-
-
-/* Memory stuff */
-
-#define RETRY_MALLOC(do_this, until_this) \
-for (;;) { \
- { do_this; } \
- if (until_this) \
- break; \
- printk("GFS: out of memory: %s, %u\n", __FILE__, __LINE__); \
- dump_stack(); \
- yield(); \
-}
-
-extern struct kmem_cache *gfs_glock_cachep;
-extern struct kmem_cache *gfs_inode_cachep;
-extern struct kmem_cache *gfs_bufdata_cachep;
-extern struct kmem_cache *gfs_mhc_cachep;
-
-void *gmalloc(unsigned int size);
-
-
-struct gfs_user_buffer {
- char *ub_data;
- unsigned int ub_size;
- unsigned int ub_count;
-};
-int gfs_add_bh_to_ub(struct gfs_user_buffer *ub, struct buffer_head *bh);
-
-
-static __inline__ unsigned int
-gfs_tune_get_i(struct gfs_tune *gt, unsigned int *p)
-{
- unsigned int x;
- spin_lock(>->gt_spin);
- x = *p;
- spin_unlock(>->gt_spin);
- return x;
-}
-#define gfs_tune_get(sdp, field) \
-gfs_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field)
-
-
-#endif /* __UTIL_DOT_H__ */
diff --git a/gfs/Makefile b/gfs/Makefile
deleted file mode 100644
index 510e181..0000000
--- a/gfs/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-include ../make/defines.mk
-
-SUBDIRS=libgfs gfs_debug gfs_fsck gfs_grow gfs_jadd gfs_mkfs gfs_quota gfs_tool man init.d
-
-all: ${SUBDIRS}
-
-%:
- set -e && \
- for i in ${SUBDIRS}; do \
- ${MAKE} -C $$i $@; \
- done; \
- if [ "$@" = "install" ]; then \
- mkdir -p ${DESTDIR}/sbin; \
- cd ${DESTDIR}/sbin; \
- ln -sf mount.gfs2 mount.gfs; \
- mkdir -p ${sbindir}; \
- cd ${sbindir}; \
- ln -sf gfs2_edit gfs_edit; \
- fi; \
- if [ "$@" = "uninstall" ]; then \
- cd ${DESTDIR}/sbin; rm -f mount.gfs; \
- cd ${sbindir}; rm -f gfs_edit; \
- fi
diff --git a/gfs/gfs_debug/Makefile b/gfs/gfs_debug/Makefile
deleted file mode 100644
index 29ce963..0000000
--- a/gfs/gfs_debug/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-TARGET= gfs_debug
-
-SBINDIRT=$(TARGET)
-
-all: ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= block_device.o \
- basic.o \
- main.o \
- ondisk.o \
- readfile.o \
- util.o
-
-CFLAGS += -DHELPER_PROGRAM -D_FILE_OFFSET_BITS=64
-CFLAGS += -I${gfskincdir}
-CFLAGS += -I$(S)/../include
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L${libdir}
-
-${TARGET}: ${OBJS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs/gfs_debug/basic.c b/gfs/gfs_debug/basic.c
deleted file mode 100644
index 8422767..0000000
--- a/gfs/gfs_debug/basic.c
+++ /dev/null
@@ -1,436 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "gfs_ondisk.h"
-#include "linux_endian.h"
-
-#include "gfs_debug.h"
-#include "basic.h"
-#include "block_device.h"
-
-/**
- * verify_block_size -
- * @bsize:
- *
- */
-
-static int
-verify_block_size(unsigned int bsize)
-{
- unsigned int x = 512;
-
- for (;;) {
- if (!x)
- return -1;
- if (x == bsize)
- return 0;
- x <<= 1;
- }
-}
-
-/**
- * verify_gfs -
- *
- */
-
-void
-verify_gfs(void)
-{
- char buf[GFS_BASIC_BLOCK];
- struct gfs_sb sb;
-
- if (device_size < (GFS_SB_ADDR + 1) * GFS_BASIC_BLOCK)
- return;
-
- do_lseek(device_fd, GFS_SB_ADDR * GFS_BASIC_BLOCK);
- do_read(device_fd, buf, GFS_BASIC_BLOCK);
-
- gfs_sb_in(&sb, buf);
-
- if (sb.sb_header.mh_magic != GFS_MAGIC ||
- sb.sb_header.mh_type != GFS_METATYPE_SB ||
- sb.sb_bsize != 1 << sb.sb_bsize_shift ||
- verify_block_size(sb.sb_bsize))
- return;
-
- if (!block_size || block_size == sb.sb_bsize) {
- unsigned int x;
-
- is_gfs = TRUE;
- block_size = sb.sb_bsize;
- block_size_shift = sb.sb_bsize_shift;
-
- sd_diptrs = (block_size - sizeof(struct gfs_dinode)) / sizeof(uint64_t);
- sd_inptrs = (block_size - sizeof(struct gfs_indirect)) / sizeof(uint64_t);
- sd_jbsize = block_size - sizeof(struct gfs_meta_header);
- sd_hash_bsize = block_size / 2;
- sd_hash_ptrs = sd_hash_bsize / sizeof(uint64_t);
-
- sd_heightsize[0] = block_size - sizeof(struct gfs_dinode);
- sd_heightsize[1] = block_size * sd_diptrs;
- for (x = 2;; x++) {
- uint64_t space = sd_heightsize[x - 1] * sd_inptrs;
- uint64_t d = space / sd_inptrs;
- uint32_t m = space % sd_inptrs;
-
- if (d != sd_heightsize[x - 1] || m)
- break;
- sd_heightsize[x] = space;
- }
- sd_max_height = x;
-
- sd_jheightsize[0] = block_size - sizeof(struct gfs_dinode);
- sd_jheightsize[1] = sd_jbsize * sd_diptrs;
- for (x = 2;; x++) {
- uint64_t space = sd_jheightsize[x - 1] * sd_inptrs;
- uint64_t d = space / sd_inptrs;
- uint32_t m = space % sd_inptrs;
-
- if (d != sd_jheightsize[x - 1] || m)
- break;
- sd_jheightsize[x] = space;
- }
- sd_max_jheight = x;
- }
-}
-
-/**
- * must_be_gfs -
- *
- */
-
-void
-must_be_gfs(void)
-{
- if (!is_gfs)
- die("not a gfs filesystem\n");
-}
-
-/**
- * scan_device -
- *
- */
-
-void
-scan_device(void)
-{
- char data[GFS_BASIC_BLOCK];
- uint64_t bb;
- struct gfs_meta_header mh;
-
- for (bb = 0; (bb + 1) * GFS_BASIC_BLOCK <= device_size; bb++) {
- do_lseek(device_fd, bb * GFS_BASIC_BLOCK);
- do_read(device_fd, data, GFS_BASIC_BLOCK);
- gfs_meta_header_in(&mh, data);
-
- if (mh.mh_magic == GFS_MAGIC &&
- mh.mh_type && mh.mh_type <= GFS_METATYPE_EA)
- printf("sector %"PRIu64": type %u\n",
- bb, mh.mh_type);
- }
-}
-
-/**
- * print_superblock -
- *
- */
-
-void
-print_superblock(void)
-{
- char *data;
- struct gfs_sb sb;
-
- must_be_gfs();
-
- data = get_block(GFS_SB_ADDR * GFS_BASIC_BLOCK / block_size, TRUE);
- gfs_sb_in(&sb, data);
- free(data);
-
- gfs_sb_print(&sb);
-}
-
-/**
- * print_bitmaps -
- * @data:
- * @offset:
- *
- */
-
-static void
-print_bitmaps(char *data, unsigned int offset)
-{
- unsigned int bn = 0;
- unsigned int bit;
- unsigned char value;
- const char *type;
-
- printf("\n");
-
- for (; offset < block_size; offset++) {
- for (bit = 0; bit < GFS_NBBY; bit++) {
- value = data[offset];
- value = (value >> (bit * GFS_BIT_SIZE)) & GFS_BIT_MASK;
- switch (value) {
- case GFS_BLKST_FREE:
- type = "free";
- break;
- case GFS_BLKST_USED:
- type = "used data";
- break;
- case GFS_BLKST_FREEMETA:
- type = "free meta";
- break;
- case GFS_BLKST_USEDMETA:
- type = "used meta";
- break;
- default:
- ASSERT(FALSE,);
- }
- printf(" block %u: %s\n", bn, type);
- bn++;
- }
- }
-}
-
-/**
- * print_stuffed_hash -
- * @data:
- *
- */
-
-static void
-print_stuffed_hash(char *data)
-{
- uint64_t *p = (uint64_t *)(data + sizeof(struct gfs_dinode));
- uint64_t *end = (uint64_t *)(((char *)p) + block_size / 2);
- uint64_t this, last = 0;
- unsigned int run = 0;
- int first = TRUE;
-
- printf("\n");
-
- for (; p < end; p++) {
- this = gfs64_to_cpu(*p);
-
- if (first) {
- first = FALSE;
- run = 1;
- } else {
- if (this == last)
- run++;
- else {
- printf(" pointer: %"PRIu64" (%u)\n",
- last, run);
- run = 1;
- }
- }
-
- last = this;
- }
-
- printf(" pointer: %"PRIu64" (%u)\n",
- last, run);
-}
-
-/**
- * print_dirents -
- * @data:
- * @offset:
- *
- * Make this more robust
- *
- */
-
-void
-print_dirents(char *data, unsigned int offset)
-{
- struct gfs_dirent de;
-
- for (; offset < block_size; offset += de.de_rec_len) {
- printf("\n");
- gfs_dirent_in(&de, data + offset);
-
- if (sizeof(struct gfs_dirent) + de.de_name_len > de.de_rec_len)
- continue;
- if (offset + sizeof(struct gfs_dirent) + de.de_name_len > block_size)
- break;
- if (de.de_inum.no_formal_ino)
- gfs_dirent_print(&de, data + offset + sizeof(struct gfs_dirent));
- }
-}
-
-/**
- * print_pointers -
- * @data:
- * @offset:
- *
- */
-
-static void
-print_pointers(char *data, unsigned int offset)
-{
- uint64_t *p = (uint64_t *)(data + offset);
- uint64_t *end = (uint64_t *)(data + block_size);
- unsigned int x = 0;
-
- printf("\n");
-
- for (; p < end; p++, x++)
- if (*p)
- printf(" pointer #%u: %"PRIu64"\n",
- x, gfs64_to_cpu(*p));
-}
-
-/**
- * identify_block -
- *
- */
-
-void
-identify_block(void)
-{
- char *data;
- struct gfs_meta_header mh;
-
- must_be_gfs();
-
- data = get_block(block_number, TRUE);
- gfs_meta_header_in(&mh, data);
-
- if (mh.mh_magic != GFS_MAGIC) {
- printf("Not GFS metadata\n");
- free(data);
- return;
- }
-
- switch (mh.mh_type) {
- case GFS_METATYPE_NONE:
- printf("GFS_METATYPE_NONE\n");
- break;
-
- case GFS_METATYPE_SB:
- printf("Super\n");
- if (verbose) {
- struct gfs_sb sb;
- gfs_sb_in(&sb, data);
- gfs_sb_print(&sb);
- }
- break;
-
- case GFS_METATYPE_RG:
- printf("Resource Group Header\n");
- if (verbose) {
- struct gfs_rgrp rg;
- gfs_rgrp_in(&rg, data);
- gfs_rgrp_print(&rg);
- if (verbose > 1)
- print_bitmaps(data, sizeof(struct gfs_rgrp));
- }
- break;
-
- case GFS_METATYPE_RB:
- printf("Resource Group Bitmap\n");
- if (verbose) {
- gfs_meta_header_print(&mh);
- if (verbose > 1)
- print_bitmaps(data, sizeof(struct gfs_meta_header));
- }
- break;
-
- case GFS_METATYPE_DI:
- printf("Dinode\n");
- if (verbose) {
- struct gfs_dinode di;
- gfs_dinode_in(&di, data);
- gfs_dinode_print(&di);
- if (verbose > 1) {
- if (di.di_height)
- print_pointers(data, sizeof(struct gfs_dinode));
- else {
- if (di.di_type == GFS_FILE_REG)
- printf("\n stuffed data\n");
- else if (di.di_type == GFS_FILE_DIR &&
- (di.di_flags & GFS_DIF_EXHASH))
- print_stuffed_hash(data);
- else if (di.di_type == GFS_FILE_DIR)
- print_dirents(data, sizeof(struct gfs_dinode));
- else if (di.di_type == GFS_FILE_LNK)
- printf("\nsymlink to %s\n",
- data + sizeof(struct gfs_dinode));
- }
- }
- }
- break;
-
- case GFS_METATYPE_IN:
- printf("Indirect\n");
- if (verbose) {
- struct gfs_indirect in;
- gfs_indirect_in(&in, data);
- gfs_indirect_print(&in);
- if (verbose > 1) {
- print_pointers(data, sizeof(struct gfs_indirect));
- }
- }
- break;
-
- case GFS_METATYPE_LF:
- printf("Directory Leaf\n");
- if (verbose) {
- struct gfs_leaf lf;
- gfs_leaf_in(&lf, data);
- gfs_leaf_print(&lf);
- if (verbose > 1)
- print_dirents(data, sizeof(struct gfs_leaf));
- }
- break;
-
- case GFS_METATYPE_JD:
- printf("Journaled Data\n");
- if (verbose)
- gfs_meta_header_print(&mh);
- break;
-
- case GFS_METATYPE_LH:
- printf("Log Header\n");
- if (verbose) {
- struct gfs_log_header lh;
- gfs_log_header_in(&lh, data);
- gfs_log_header_print(&lh);
- }
- break;
-
- case GFS_METATYPE_LD:
- printf("Lock Descriptor\n");
- if (verbose) {
- struct gfs_log_descriptor ld;
- gfs_desc_in(&ld, data);
- gfs_desc_print(&ld);
- }
- break;
-
- case GFS_METATYPE_EA:
- printf("Extended Attribute\n");
- if (verbose)
- gfs_meta_header_print(&mh);
- break;
-
- default:
- printf("Unknown metadata type\n");
- if (verbose)
- gfs_meta_header_print(&mh);
- break;
- }
-
- free(data);
-}
-
diff --git a/gfs/gfs_debug/basic.h b/gfs/gfs_debug/basic.h
deleted file mode 100644
index 56d4a77..0000000
--- a/gfs/gfs_debug/basic.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef __BASIC_DOT_H__
-#define __BASIC_DOT_H__
-
-
-EXTERN unsigned int sd_diptrs INIT(0);
-EXTERN unsigned int sd_inptrs INIT(0);
-EXTERN unsigned int sd_jbsize INIT(0);
-EXTERN unsigned int sd_hash_bsize INIT(0);
-EXTERN unsigned int sd_hash_ptrs INIT(0);
-EXTERN uint32_t sd_max_height INIT(0);
-EXTERN uint64_t sd_heightsize[GFS_MAX_META_HEIGHT];
-EXTERN uint32_t sd_max_jheight INIT(0);
-EXTERN uint64_t sd_jheightsize[GFS_MAX_META_HEIGHT];
-
-
-void verify_gfs(void);
-void must_be_gfs(void);
-void scan_device(void);
-void print_superblock(void);
-void identify_block(void);
-
-void print_dirents(char *data, unsigned int offset);
-
-
-#endif /* __BASIC_DOT_H__ */
-
diff --git a/gfs/gfs_debug/block_device.c b/gfs/gfs_debug/block_device.c
deleted file mode 100644
index 8640f6f..0000000
--- a/gfs/gfs_debug/block_device.c
+++ /dev/null
@@ -1,117 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "gfs_debug.h"
-#include "block_device.h"
-
-/**
- * find_device_size -
- *
- */
-
-void
-find_device_size(void)
-{
- device_size = lseek(device_fd, 0, SEEK_END);
- if (device_size < 0)
- die("can't determine device size: %s\n",
- strerror(errno));
-}
-
-/**
- * get_block -
- * @bn:
- * @fatal:
- *
- * Returns: the data in the block (needs to be freed)
- */
-
-char *
-get_block(uint64_t bn, int fatal)
-{
- char *data;
-
- if (device_size < (bn + 1) * block_size) {
- fprintf(stderr, "%s: block %"PRIu64" is off the end of the device\n",
- prog_name, bn);
- if (fatal)
- exit(EXIT_FAILURE);
- }
-
- data = malloc(block_size);
- if (!data)
- die("out of memory (%s, %u)\n",
- __FILE__, __LINE__);
-
- do_lseek(device_fd, bn * block_size);
- do_read(device_fd, data, block_size);
-
- return data;
-}
-
-/**
- * print_size -
- *
- */
-
-void
-print_size(void)
-{
- printf("%"PRIu64"\n", device_size);
-}
-
-/**
- * print_hexblock -
- *
- */
-
-void
-print_hexblock(void)
-{
- char *data;
- unsigned int x;
-
- if (!block_size)
- die("no block size set\n");
-
- data = get_block(block_number, TRUE);
-
- for (x = 0; x < block_size; x++) {
- printf("%.2X", ((unsigned char *)data)[x]);
- if (x % 16 == 15)
- printf("\n");
- else
- printf(" ");
- }
-
- if (x % 16)
- printf("\n");
-
- free(data);
-}
-
-/**
- * print_rawblock -
- *
- */
-
-void
-print_rawblock(void)
-{
- char *data;
-
- if (!block_size)
- die("no block size set\n");
-
- data = get_block(block_number, TRUE);
- do_write(STDOUT_FILENO, data, block_size);
- free(data);
-}
diff --git a/gfs/gfs_debug/block_device.h b/gfs/gfs_debug/block_device.h
deleted file mode 100644
index 6af5437..0000000
--- a/gfs/gfs_debug/block_device.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __BLOCK_DEVICE_DOT_H__
-#define __BLOCK_DEVICE_DOT_H__
-
-
-void find_device_size(void);
-char *get_block(uint64_t bn, int fatal);
-
-void print_size(void);
-void print_hexblock(void);
-void print_rawblock(void);
-
-
-#endif /* __BLOCK_DEVICE_DOT_H__ */
-
diff --git a/gfs/gfs_debug/gfs_debug.h b/gfs/gfs_debug/gfs_debug.h
deleted file mode 100644
index 2f675b2..0000000
--- a/gfs/gfs_debug/gfs_debug.h
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef __GFS_DEBUG_DOT_H__
-#define __GFS_DEBUG_DOT_H__
-
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#ifndef EXTERN
-#define EXTERN extern
-#define INIT(X)
-#else
-#undef EXTERN
-#define EXTERN
-#define INIT(X) =X
-#endif
-
-
-#define die(fmt, args...) \
-do { \
- fprintf(stderr, "%s: ", prog_name); \
- fprintf(stderr, fmt, ##args); \
- exit(EXIT_FAILURE); \
-} while (0)
-
-#define ASSERT(x, todo) \
-do { \
- if (!(x)) { \
- {todo} \
- die("assertion failed on line %d of file %s\n", \
- __LINE__, __FILE__); \
- } \
-} while (0)
-
-EXTERN char *prog_name;
-
-#define do_lseek(fd, off) \
-do { \
- if (lseek((fd), (off), SEEK_SET) != (off)) \
- die("bad seek on line %d of file %s: %s\n", \
- __LINE__, __FILE__, strerror(errno)); \
-} while (0)
-
-#define do_read(fd, buff, len) \
-do { \
- if (read((fd), (buff), (len)) != (len)) \
- die("bad read on line %d of file %s: %s\n", \
- __LINE__, __FILE__, strerror(errno)); \
-} while (0)
-
-#define do_write(fd, buff, len) \
-do { \
- if (write((fd), (buff), (len)) != (len)) \
- die("bad write on line %d of file %s: %s\n", \
- __LINE__, __FILE__, strerror(errno)); \
-} while (0)
-
-#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
-
-
-/* Command line arguments */
-
-EXTERN unsigned int verbose INIT(0);
-
-EXTERN char *action INIT(NULL);
-
-EXTERN char *device INIT(NULL);
-EXTERN int device_fd INIT(-1);
-EXTERN off_t device_size INIT(-1);
-
-EXTERN int is_gfs INIT(FALSE);
-EXTERN unsigned int block_size INIT(0);
-EXTERN unsigned int block_size_shift INIT(0);
-
-EXTERN uint64_t block_number INIT(0);
-
-
-#endif /* __GFS_DEBUG_DOT_H__ */
-
diff --git a/gfs/gfs_debug/main.c b/gfs/gfs_debug/main.c
deleted file mode 100644
index b42d34a..0000000
--- a/gfs/gfs_debug/main.c
+++ /dev/null
@@ -1,179 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "gfs_ondisk.h"
-#include "copyright.cf"
-
-#define EXTERN
-#include "gfs_debug.h"
-#include "basic.h"
-#include "block_device.h"
-#include "readfile.h"
-
-/**
- * print_usage - print out usage information
- *
- */
-
-static void
-print_usage(void)
-{
- printf("Usage:\n");
- printf("\n");
- printf("%s [options] <action>\n", prog_name);
- printf("\n");
- printf("Actions:\n");
- printf(" size print the device size\n");
- printf(" hexread print a block in hex\n");
- printf(" rawread print a block raw\n");
- printf("\n");
- printf("GFS-specific Actions:\n");
- printf(" scan scan the device looking for GFS blocks\n");
- printf(" identify identify the contents of a block\n");
- printf(" sb print superblock\n");
- printf(" jindex print journal index\n");
- printf(" rindex print resource index\n");
- printf(" quota print quota file\n");
- printf(" root print root directory\n");
- printf(" readfile print the contents of a file\n");
- printf(" readdir print the contents of a directory\n");
- printf("\n");
- printf("Options:\n");
- printf("\n");
- printf(" -B <bytes> Set the block size\n");
- printf(" -b <number> Block number\n");
- printf(" -d <device> Device to look at\n");
- printf(" -h Print this help, then exit\n");
- printf(" -v Verbose\n");
- printf(" -V Print program version information, then exit\n");
-}
-
-/**
- * decode_arguments -
- * @argc:
- * @argv:
- *
- */
-
-static void
-decode_arguments(int argc, char *argv[])
-{
- int cont = TRUE;
- int optchar;
-
- while (cont) {
- optchar = getopt(argc, argv, "B:b:d:hVv");
-
- switch (optchar) {
- case 'B':
- sscanf(optarg, "%u", &block_size);
- if (!block_size)
- die("can't have a zero block size\n");
- break;
-
- case 'b':
- sscanf(optarg, "%"SCNu64, &block_number);
- break;
-
- case 'd':
- device = optarg;
- break;
-
- case 'h':
- print_usage();
- exit(EXIT_SUCCESS);
-
- case 'V':
- printf("gfs_mkfs %s (built %s %s)\n", RELEASE_VERSION, __DATE__, __TIME__);
- printf("%s\n", REDHAT_COPYRIGHT);
- exit(EXIT_SUCCESS);
-
- case 'v':
- verbose++;
- break;
-
- case EOF:
- cont = FALSE;
- break;
-
- default:
- die("unknown option: %c\n", optchar);
- };
- }
-
- if (optind < argc) {
- action = argv[optind];
- optind++;
- } else
- die("no action specified\n");
-
- if (optind < argc)
- die("Unrecognized option: %s\n", argv[optind]);
-
- if (!device)
- die("no device specified\n");
-}
-
-/**
- * main -
- * @argc:
- * @argv:
- *
- * Returns: exit status
- */
-
-int
-main(int argc, char *argv[])
-{
- prog_name = argv[0];
-
- decode_arguments(argc, argv);
-
- device_fd = open(device, O_RDWR);
- if (device_fd < 0)
- die("can't open device %s: %s\n",
- device, strerror(errno));
-
- find_device_size();
- verify_gfs();
-
- if (!strcmp(action, "size"))
- print_size();
- else if (!strcmp(action, "hexread"))
- print_hexblock();
- else if (!strcmp(action, "rawread"))
- print_rawblock();
- else if (!strcmp(action, "scan"))
- scan_device();
- else if (!strcmp(action, "identify"))
- identify_block();
- else if (!strcmp(action, "sb"))
- print_superblock();
- else if (!strcmp(action, "jindex"))
- print_jindex();
- else if (!strcmp(action, "rindex"))
- print_rindex();
- else if (!strcmp(action, "quota"))
- print_quota();
- else if (!strcmp(action, "root"))
- print_root();
- else if (!strcmp(action, "readfile"))
- readfile();
- else if (!strcmp(action, "readdir"))
- readdir();
- else
- die("unknown action %s\n", action);
-
- close(device_fd);
-
- exit(EXIT_SUCCESS);
-}
-
diff --git a/gfs/gfs_debug/ondisk.c b/gfs/gfs_debug/ondisk.c
deleted file mode 100644
index 248cb77..0000000
--- a/gfs/gfs_debug/ondisk.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "linux_endian.h"
-
-#define printk printf
-#define pv(struct, member, fmt) printf(" "#member" = "fmt"\n", struct->member);
-
-#define ENTER(x)
-#define EXIT(x)
-#define RET(x) return
-#define RETURN(x, y) return y
-
-#define WANT_GFS_CONVERSION_FUNCTIONS
-#include "gfs_ondisk.h"
-
diff --git a/gfs/gfs_debug/readfile.c b/gfs/gfs_debug/readfile.c
deleted file mode 100644
index 75e9c66..0000000
--- a/gfs/gfs_debug/readfile.c
+++ /dev/null
@@ -1,236 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "gfs_ondisk.h"
-#include "linux_endian.h"
-
-#include "gfs_debug.h"
-#include "basic.h"
-#include "block_device.h"
-#include "readfile.h"
-#include "util.h"
-
-void
-print_jindex(void)
-{
- struct gfs_sb sb;
- struct gfs_dinode di;
- struct gfs_jindex ji;
- char *data;
- char buf[sizeof(struct gfs_jindex)];
- uint64_t o;
- unsigned int x;
- int error;
-
- must_be_gfs();
-
- data = get_block(GFS_SB_ADDR * GFS_BASIC_BLOCK / block_size, TRUE);
- gfs_sb_in(&sb, data);
- free(data);
-
- data = get_block(sb.sb_jindex_di.no_addr, TRUE);
- gfs_dinode_in(&di, data);
- free(data);
-
- if (di.di_size % sizeof(struct gfs_jindex))
- fprintf(stderr, "%s: strange size for journal index %"PRIu64"\n",
- prog_name, di.di_size);
-
- for (o = 0, x = 0;; o += sizeof(struct gfs_jindex), x++) {
- error = gfs_readi(&di, buf, o, sizeof(struct gfs_jindex));
- if (!error)
- break;
- if (error < sizeof(struct gfs_jindex))
- continue;
- gfs_jindex_in(&ji, buf);
- printf("Journal %u:\n", x);
- gfs_jindex_print(&ji);
- printf("\n");
- }
-}
-
-void
-print_rindex(void)
-{
- struct gfs_sb sb;
- struct gfs_dinode di;
- struct gfs_rindex ri;
- char *data;
- char buf[sizeof(struct gfs_rindex)];
- uint64_t o;
- unsigned int x;
- int error;
-
- must_be_gfs();
-
- data = get_block(GFS_SB_ADDR * GFS_BASIC_BLOCK / block_size, TRUE);
- gfs_sb_in(&sb, data);
- free(data);
-
- data = get_block(sb.sb_rindex_di.no_addr, TRUE);
- gfs_dinode_in(&di, data);
- free(data);
-
- if (di.di_size % sizeof(struct gfs_rindex))
- fprintf(stderr, "%s: strange size for resource index %"PRIu64"\n",
- prog_name, di.di_size);
-
- for (o = 0, x = 0;; o += sizeof(struct gfs_rindex), x++) {
- error = gfs_readi(&di, buf, o, sizeof(struct gfs_rindex));
- if (!error)
- break;
- if (error < sizeof(struct gfs_rindex))
- continue;
- gfs_rindex_in(&ri, buf);
- printf("Resource Group %u:\n", x);
- gfs_rindex_print(&ri);
- printf("\n");
- }
-}
-
-void
-print_quota(void)
-{
- struct gfs_sb sb;
- struct gfs_dinode di;
- struct gfs_quota qu;
- char *data;
- char buf[sizeof(struct gfs_quota)];
- uint64_t o;
- unsigned int x;
- int error;
-
- must_be_gfs();
-
- data = get_block(GFS_SB_ADDR * GFS_BASIC_BLOCK / block_size, TRUE);
- gfs_sb_in(&sb, data);
- free(data);
-
- data = get_block(sb.sb_quota_di.no_addr, TRUE);
- gfs_dinode_in(&di, data);
- free(data);
-
- for (o = 0, x = 0;; o += sizeof(struct gfs_quota), x++) {
- error = gfs_readi(&di, buf, o, sizeof(struct gfs_quota));
- if (!error)
- break;
- if (error < 0)
- continue;
- gfs_quota_in(&qu, buf);
-
- if (!qu.qu_limit && !qu.qu_warn && !qu.qu_value)
- continue;
-
- printf("Quota (%s, %u):\n", (x % 2) ? "group" : "user", x / 2);
- gfs_quota_print(&qu);
- printf("\n");
- }
-}
-
-void
-print_root(void)
-{
- struct gfs_sb sb;
- char *data;
-
- must_be_gfs();
-
- data = get_block(GFS_SB_ADDR * GFS_BASIC_BLOCK / block_size, TRUE);
- gfs_sb_in(&sb, data);
- free(data);
-
- block_number = sb.sb_root_di.no_addr;
-
- readdir();
-}
-
-#define CHUNKSIZE (65536)
-
-void
-readfile(void)
-{
- struct gfs_dinode di;
- char *data;
- char buf[CHUNKSIZE];
- uint64_t o = 0;
- int error, rc;
-
- must_be_gfs();
-
- data = get_block(block_number, TRUE);
- gfs_dinode_in(&di, data);
- free(data);
-
- if (di.di_header.mh_magic != GFS_MAGIC ||
- di.di_header.mh_type != GFS_METATYPE_DI)
- die("block %"PRIu64" isn't an inode\n",
- block_number);
-
- if (di.di_type != GFS_FILE_REG)
- die("block %"PRIu64" isn't a regular file\n",
- block_number);
-
- for (;;) {
- error = gfs_readi(&di, buf, o, CHUNKSIZE);
- if (error <= 0)
- break;
- rc = write(STDOUT_FILENO, buf, error);
- o += error;
- }
-}
-
-static void
-do_readdir(struct gfs_dinode *di, char *data,
- uint32_t lindex, uint32_t len, uint64_t leaf_no,
- void *opaque)
-{
- struct gfs_leaf leaf;
-
- print_dirents(data, sizeof(struct gfs_leaf));
- gfs_leaf_in(&leaf, data);
-
- while (leaf.lf_next) {
- data = get_block(leaf.lf_next, FALSE);
- if (!data)
- return;
- print_dirents(data, sizeof(struct gfs_leaf));
- gfs_leaf_in(&leaf, data);
- free(data);
- }
-}
-
-void
-readdir(void)
-{
- struct gfs_dinode di;
- char *data;
-
- must_be_gfs();
-
- data = get_block(block_number, TRUE);
- gfs_dinode_in(&di, data);
-
- if (di.di_header.mh_magic != GFS_MAGIC ||
- di.di_header.mh_type != GFS_METATYPE_DI)
- die("block %"PRIu64" isn't an inode\n",
- block_number);
-
- if (di.di_type != GFS_FILE_DIR)
- die("block %"PRIu64" isn't a directory\n",
- block_number);
-
- if (di.di_flags & GFS_DIF_EXHASH)
- foreach_leaf(&di, do_readdir, NULL);
- else
- print_dirents(data, sizeof(struct gfs_dinode));
-
- free(data);
-}
diff --git a/gfs/gfs_debug/readfile.h b/gfs/gfs_debug/readfile.h
deleted file mode 100644
index e4e84e9..0000000
--- a/gfs/gfs_debug/readfile.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __READFILE_DOT_H__
-#define __READFILE_DOT_H__
-
-
-void print_jindex(void);
-void print_rindex(void);
-void print_quota(void);
-void print_root(void);
-void readfile(void);
-void readdir(void);
-
-
-#endif /* __READFILE_DOT_H__ */
-
diff --git a/gfs/gfs_debug/util.c b/gfs/gfs_debug/util.c
deleted file mode 100644
index ab4f0ee..0000000
--- a/gfs/gfs_debug/util.c
+++ /dev/null
@@ -1,334 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "gfs_ondisk.h"
-#include "linux_endian.h"
-
-#include "gfs_debug.h"
-#include "basic.h"
-#include "block_device.h"
-#include "util.h"
-
-int
-check_type(char *data, unsigned int type)
-{
- struct gfs_meta_header mh;
-
- gfs_meta_header_in(&mh, data);
- if (mh.mh_magic != GFS_MAGIC ||
- mh.mh_type != type) {
- fprintf(stderr, "%s: expected metadata type %u\n",
- prog_name, type);
- return -1;
- }
- return 0;
-}
-
-/**
- * recursive_scan - call a function for each block pointer in a file
- * @di:
- * @height:
- * @bn:
- * @pc:
- * @opaque:
- *
- */
-
-void
-recursive_scan(struct gfs_dinode *di,
- unsigned int height, uint64_t bn,
- pointer_call_t pc, void *opaque)
-{
- char *data = NULL;
- uint64_t *top, *bottom;
- uint64_t x;
-
- if (!height) {
- data = get_block(di->di_num.no_addr, TRUE);
-
- top = (uint64_t *)(data + sizeof(struct gfs_dinode));
- bottom = (uint64_t *)(data + sizeof(struct gfs_dinode)) + sd_diptrs;
- } else {
- data = get_block(bn, FALSE);
- if (!data)
- return;
- if (check_type(data, GFS_METATYPE_IN))
- return;
-
- top = (uint64_t *)(data + sizeof(struct gfs_indirect));
- bottom = (uint64_t *)(data + sizeof(struct gfs_indirect)) + sd_inptrs;
- }
-
- for ( ; top < bottom; top++) {
- x = gfs64_to_cpu(*top);
-
- pc(di, height, x, opaque);
-
- if (x && height < di->di_height - 1)
- recursive_scan(di,
- height + 1, x,
- pc, opaque);
- }
-
- free(data);
-}
-
-void
-foreach_leaf(struct gfs_dinode *di,
- leaf_call_t lc, void *opaque)
-{
- char *data;
- struct gfs_leaf leaf;
- uint32_t hsize, len;
- uint32_t ht_offset, lp_offset, ht_offset_cur = -1;
- uint32_t lindex = 0;
- uint64_t lp[sd_hash_ptrs];
- uint64_t leaf_no;
- int error;
-
- hsize = 1 << di->di_depth;
- if (hsize * sizeof(uint64_t) != di->di_size)
- die("bad hash table size\n");
-
- while (lindex < hsize) {
- lp_offset = lindex % sd_hash_ptrs;
- ht_offset = lindex - lp_offset;
-
- if (ht_offset_cur != ht_offset) {
- error = gfs_readi(di, (char *)lp, ht_offset * sizeof(uint64_t), sd_hash_bsize);
- if (error != sd_hash_bsize)
- die("FixMe!!!\n");
- ht_offset_cur = ht_offset;
- }
-
- leaf_no = gfs64_to_cpu(lp[lp_offset]);
- if (!leaf_no)
- die("NULL leaf pointer\n");
-
- data = get_block(leaf_no, TRUE);
- gfs_leaf_in(&leaf, data);
- len = 1 << (di->di_depth - leaf.lf_depth);
-
- lc(di, data, lindex, len, leaf_no, opaque);
-
- free(data);
- lindex += len;
- }
-
- if (lindex != hsize)
- die("screwed up directory\n");
-}
-
-static unsigned int
-calc_tree_height(struct gfs_dinode *di, uint64_t size)
-{
- uint64_t *arr;
- unsigned int max, height;
-
- if (di->di_size > size)
- size = di->di_size;
-
- if (di->di_flags & GFS_DIF_JDATA) {
- arr = sd_jheightsize;
- max = sd_max_jheight;
- } else {
- arr = sd_heightsize;
- max = sd_max_height;
- }
-
- for (height = 0; height < max; height++)
- if (arr[height] >= size)
- break;
-
- return height;
-}
-
-struct metapath {
- unsigned int mp_list[GFS_MAX_META_HEIGHT];
-};
-
-static struct metapath *
-find_metapath(struct gfs_dinode *di, uint64_t block)
-{
- struct metapath *mp;
- uint64_t b = block;
- unsigned int i;
-
- mp = malloc(sizeof(struct metapath));
- if (!mp)
- die("out of memory (%s, %u)\n",
- __FILE__, __LINE__);
- memset(mp, 0, sizeof(struct metapath));
-
- for (i = di->di_height; i--;) {
- mp->mp_list[i] = b % sd_inptrs;
- b /= sd_inptrs;
- }
-
- return mp;
-}
-
-static uint64_t
-lookup_block(char *data, unsigned int height,
- struct metapath *mp)
-{
- unsigned int head_size;
- uint64_t block;
-
- head_size = (height > 0) ?
- sizeof(struct gfs_indirect) : sizeof(struct gfs_dinode);
- block = *(((uint64_t *)(data + head_size)) + mp->mp_list[height]);
-
- if (block)
- return gfs64_to_cpu(block);
- else
- return 0;
-}
-
-int
-gfs_block_map(struct gfs_dinode *di,
- uint64_t lblock, uint64_t *dblock)
-{
- unsigned int bsize;
- unsigned int height;
- struct metapath *mp;
- unsigned int end_of_metadata;
- char *data;
- unsigned int x;
- int error = 0;
-
- *dblock = 0;
-
- if (!di->di_height) {
- if (!lblock)
- *dblock = di->di_num.no_addr;
- return 0;
- }
-
- bsize = (di->di_flags & GFS_DIF_JDATA) ? sd_jbsize : block_size;
-
- height = calc_tree_height(di, (lblock + 1) * bsize);
- if (di->di_height < height)
- return 0;
-
- mp = find_metapath(di, lblock);
- end_of_metadata = di->di_height - 1;
-
- data = get_block(di->di_num.no_addr, TRUE);
-
- for (x = 0; x < end_of_metadata; x++) {
- *dblock = lookup_block(data, x, mp);
- free(data);
- if (!*dblock)
- goto out;
-
- data = get_block(*dblock, FALSE);
- if (!data) {
- error = -1;
- goto out;
- }
- }
-
- *dblock = lookup_block(data, x, mp);
-
- free(data);
-
- out:
- free(mp);
-
- return error;
-}
-
-static int
-copy2mem(char *data, void **buf,
- unsigned int offset, unsigned int size)
-{
- char **p = (char **)buf;
-
- if (data)
- memcpy(*p, data + offset, size);
- else
- memset(*p, 0, size);
-
- *p += size;
-
- return 0;
-}
-
-int
-gfs_readi(struct gfs_dinode *di, void *buf,
- uint64_t offset, unsigned int size)
-{
- int journaled = (di->di_flags & GFS_DIF_JDATA);
- uint64_t lblock, dblock;
- unsigned int o;
- unsigned int amount;
- char *data;
- int copied = 0;
- int error = 0;
-
- if (offset >= di->di_size)
- return 0;
-
- if ((offset + size) > di->di_size)
- size = di->di_size - offset;
-
- if (!size)
- return 0;
-
- if (journaled) {
- lblock = offset / sd_jbsize;
- o = offset % sd_jbsize;
- } else {
- lblock = offset >> block_size_shift;
- o = offset & (block_size - 1);
- }
-
- if (!di->di_height)
- o += sizeof(struct gfs_dinode);
- else if (journaled)
- o += sizeof(struct gfs_meta_header);
-
- while (copied < size) {
- amount = size - copied;
- if (amount > block_size - o)
- amount = block_size - o;
-
- error = gfs_block_map(di, lblock, &dblock);
- if (error)
- goto fail;
-
- if (dblock) {
- data = get_block(dblock, FALSE);
- if (!data) {
- error = -1;
- goto fail;
- }
- } else
- data = NULL;
-
- copy2mem(data, &buf, o, amount);
-
- if (data)
- free(data);
-
- copied += amount;
- lblock++;
-
- o = (journaled) ? sizeof(struct gfs_meta_header) : 0;
- }
-
- return copied;
-
- fail:
- return (copied) ? copied : error;
-}
-
diff --git a/gfs/gfs_debug/util.h b/gfs/gfs_debug/util.h
deleted file mode 100644
index 6f0489a..0000000
--- a/gfs/gfs_debug/util.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __UTIL_DOT_H__
-#define __UTIL_DOT_H__
-
-
-int check_type(char *data, unsigned int type);
-
-
-typedef void (*pointer_call_t)(struct gfs_dinode *di,
- unsigned int height, uint64_t bn,
- void *opaque);
-void recursive_scan(struct gfs_dinode *di,
- unsigned int height, uint64_t bn,
- pointer_call_t pc, void *opaque);
-
-typedef void (*leaf_call_t)(struct gfs_dinode *di, char *data,
- uint32_t index, uint32_t len, uint64_t leaf_no,
- void *opaque);
-void foreach_leaf(struct gfs_dinode *di,
- leaf_call_t lc, void *opaque);
-
-
-int gfs_block_map(struct gfs_dinode *di,
- uint64_t lblock, uint64_t *dblock);
-int gfs_readi(struct gfs_dinode *di, void *buf,
- uint64_t offset, unsigned int size);
-
-
-#endif /* __UTIL_DOT_H__ */
-
diff --git a/gfs/gfs_fsck/FEATURES b/gfs/gfs_fsck/FEATURES
deleted file mode 100644
index 8a63591..0000000
--- a/gfs/gfs_fsck/FEATURES
+++ /dev/null
@@ -1,25 +0,0 @@
-This is a completely rewritten filesystem checker for GFS. Performance
-characteristics are significantly improved. The design follows the 5-pass
-fsck design found in "Fsck - The UNIX File System Check Program"
-by McKusick & Kowalkski (1994)
- - http://citeseer.ist.psu.edu/mckusick94fsck.html
-
-
-Line item list of supported features:
-
-1. Detects and replaces missing/bad root inode
-2. Detects and relinks unlinked inodes to l+f
- o If a file is zero length, it is not relinked to l+f - unless it
- has an extended attribute attached to it.
-3. Detects duplicate blocks and removes inodes containing them
-4. Detects bad blocks (block number out of range) and removes inodes
- containing them - Currently EAs that have blocks are removed but
- the inode containing them is left.
-5. Detects bad metadata headers and clears the structure
-6. Fixes bad resource group bitmaps
-7. Fixes incorrect resource group counts
-8. Creates l+f directory if missing
-9. Detects and removes duplicate '.' and '..' entries
-10. Creates '.' if missing
-11. Beginning of support for internationalization
-12. Checks extended attributes
diff --git a/gfs/gfs_fsck/Makefile b/gfs/gfs_fsck/Makefile
deleted file mode 100644
index 4832872..0000000
--- a/gfs/gfs_fsck/Makefile
+++ /dev/null
@@ -1,60 +0,0 @@
-TARGET= fsck.gfs
-
-FORCESBINT= $(TARGET)
-
-all: ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= bio.o \
- bitmap.o \
- block_list.o \
- eattr.o \
- file.o \
- fs_bits.o \
- fs_bmap.o \
- fs_dir.o \
- fs_inode.o \
- fs_recovery.o \
- hash.o \
- initialize.o \
- inode.o \
- inode_hash.o \
- link.o \
- log.o \
- lost_n_found.o \
- main.o \
- metawalk.o \
- ondisk.o \
- pass1.o \
- pass1b.o \
- pass1c.o \
- pass2.o \
- pass3.o \
- pass4.o \
- pass5.o \
- rgrp.o \
- super.o \
- util.o
-
-CFLAGS += -D_FILE_OFFSET_BITS=64 -DHELPER_PROGRAM
-CFLAGS += -I$(S)/../include
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L${libdir}
-
-${TARGET}: $(OBJS)
- $(CC) -o $@ $^ $(LDFLAGS)
-
-clean: generalclean
-
-${TARGET}.pot: $(OBJS:.o=.c)
- xgettext -C -F --keyword=print_log --keyword=log_debug --keyword=log_info --keyword=_ \
- --keyword=log_notice --keyword=log_warn --keyword=log_err --keyword=log_crit \
- --keyword=log_debug --keyword=log_err --keyword=log_print -d - $(OBJS:.o=.c) > ${TARGET}.pot
-
--include $(OBJS:.o=.d)
diff --git a/gfs/gfs_fsck/TODO b/gfs/gfs_fsck/TODO
deleted file mode 100644
index 2b2e762..0000000
--- a/gfs/gfs_fsck/TODO
+++ /dev/null
@@ -1,49 +0,0 @@
-
-TODO:
-
-Current
- x fs_mkdir appears to be grabbing blocks that are in use - need to
- figure out why - had to fix fs_blkalloc_internal in fs_bits.c to
- use the incore bitmaps instead of ondisk.
- o Make sure that all blocks in an inode get marked cleared when an
- inode is cleared.
- x If a directory is unlinked from pass2 on, make sure that any
- directories that have it as a parent have their
- dir_info->treewalk_parent entries cleared - handled by pass3
- checking if parents inodes are valid in the bitmap
- o If an directory is unlinked from pass2 on, make sure that inodes
- have their link count decremented (this may be difficult - i'll
- have to reread the dirents and decrement the counts for all dirents
- up to the error...).
- x 'Add in UI for interactive mode
- o Check hash of directory name against name given (Would be nice -
- not in old fsck, but can cause problems if it is not verified.)
- x Unstuffed EA blocks have type GFS_METATYPE_ED in 6.1, but
- GFS_METATYPE_EA in 6.0 - handle this.
-
----
-
-Future
- o internationalization
- o Check GFS special files (quota, resource group index inode, journal
- index inode, license inode?)
- o convert dir_info list to a hash table like the inode_info hash
- o Fix up the bitmap enums and #defines in block_list.[ch]
- o Go through all fxns that have NEEDS_CHECKING in them and verify
- them (and remove NEEDS_CHECKING)
- o Add 'preen' option?
- o Add disk-based bitmaps option in case system doesn't have enough
- memory to handle all the bitmaps
- o currently rgrp bitmaps are loaded into memory on initialization -
- need to see if this is necessary or not - we're using them in pass1
- and again in pass5 - if memory is tight we might be able to free
- them in between
- o Offer exhaustive search capability if superblock or rgs are missing
- or broken that checks block by block for fs info.
- o If we encounter a directory entry in pass2 that points to a block
- marked free, shove it into a queue, and then at the end of pass2,
- clear all results, then rerun from pass1 including the blocks in
- the queue as well as those marked in the RG bitmaps. With this, we
- can rebuild the entire fs with a valid root inode, it'll just take
- several iterations.
-
diff --git a/gfs/gfs_fsck/bio.c b/gfs/gfs_fsck/bio.c
deleted file mode 100644
index 2331325..0000000
--- a/gfs/gfs_fsck/bio.c
+++ /dev/null
@@ -1,168 +0,0 @@
-#include "util.h"
-#include "fsck.h"
-#include "bio.h"
-
-/*
- * get_buf - get a buffer
- * @sdp: the super block
- * @blkno: blk # that this buffer will be associated with
- * @bhp: the location where the buffer is returned
- *
- * This function allocates space for a buffer head structure
- * and the corresponding data. It does not fill in the
- * actual data - that is done by read_buf.
- *
- * Returns: 0 on success, -1 on error
- */
-int get_buf(struct fsck_sb *sdp, uint64 blkno, osi_buf_t **bhp){
- osi_buf_t *bh = NULL;
-
- *bhp = NULL;
- bh = (osi_buf_t *)malloc(sizeof(osi_buf_t));
- if(!bh){
- log_err("Unable to allocate memory for new buffer head.\n");
- return -1;
- }
- if(!memset(bh, 0, sizeof(osi_buf_t))) {
- log_err("Unable to zero buffer head\n");
- return -1;
- }
-
- /* FIXME: Not sure how this will work on all
- * architectures without the casts */
- bh->b_blocknr = blkno;
- bh->b_size = sdp->sb.sb_bsize;
- bh->b_state = 0;
- if(!(bh->b_data = malloc(BH_SIZE(bh)))) {
- free(bh);
- log_err("Unable to allocate memory for new buffer "
- "blkno = %"PRIu64", size = %u\n", blkno, BH_SIZE(bh));
- return -1;
- }
- if(!memset(BH_DATA(bh), 0, BH_SIZE(bh))) {
- free(bh);
- log_err("Unable to zero memory for new buffer "
- "blkno = %"PRIu64", size = %u\n", blkno, BH_SIZE(bh));
- }
-
- *bhp = bh;
-
- return 0;
-}
-
-
-/*
- * relse_buf - release a buffer
- * @sdp: the super block
- * @bh: the buffer to release
- *
- * This function will release the memory of the buffer
- * and associated buffer head.
- *
- * Returns: nothing
- */
-void relse_buf(struct fsck_sb *sdp, osi_buf_t *bh){
- if(bh){
- if(BH_DATA(bh)) {
- free(BH_DATA(bh));
- bh->b_data = NULL;
- }
- free(bh);
- bh = NULL;
- }
-}
-
-
-/*
- * read_buf - read a buffer
- * @sdp: the super block
- * @blkno: block number
- * @bhp: place where buffer is returned
- * @flags:
- *
- * Returns 0 on success, -1 on error
- */
-int read_buf(struct fsck_sb *sdp, osi_buf_t *bh, int flags){
- int disk_fd = sdp->diskfd;
-
- if(do_lseek(disk_fd, (uint64)(BH_BLKNO(bh)*BH_SIZE(bh)))){
- log_err("Unable to seek to position %"PRIu64" "
- "(%"PRIu64" * %u) on storage device.\n",
- (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)),
- BH_BLKNO(bh), BH_SIZE(bh));
- return -1;
- }
-
- if(do_read(disk_fd, BH_DATA(bh), BH_SIZE(bh))){
- log_err("Unable to read %u bytes from position %"PRIu64"\n",
- BH_SIZE(bh), (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)));
- return -1;
- }
-
- return 0;
-}
-
-
-/*
- * write_buf - write a buffer
- * @sdp: the super block
- * @bh: buffer head that describes buffer to write
- * @flags: flags that determine usage
- *
- * Returns: 0 on success, -1 on failure
- */
-int write_buf(struct fsck_sb *sdp, osi_buf_t *bh, int flags){
- int disk_fd = sdp->diskfd;
-
- if(do_lseek(disk_fd, (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)))) {
- log_err("Unable to seek to position %"PRIu64
- "(%"PRIu64" * %u) on storage device.\n",
- (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)),
- BH_BLKNO(bh), BH_SIZE(bh));
- return -1;
- }
-
- log_debug("Writing to %"PRIu64" - %"PRIu64" %u\n",
- (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)),
- BH_BLKNO(bh), BH_SIZE(bh));
- if(do_write(disk_fd, BH_DATA(bh), BH_SIZE(bh))) {
- log_err("Unable to write %u bytes to position %"PRIu64"\n",
- BH_SIZE(bh), (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)));
- return -1;
- }
-
- if(flags & BW_WAIT){
- fsync(disk_fd);
- }
-
- return 0;
-}
-
-
-/*
- * get_and_read_buf - combines get_buf and read_buf functions
- * @sdp
- * @blkno
- * @bhp
- * @flags
- *
- * Returns: 0 on success, -1 on error
- */
-int get_and_read_buf(struct fsck_sb *sdp, uint64 blkno, osi_buf_t **bhp,
- int flags)
-{
- if(get_buf(sdp, blkno, bhp)) {
- stack;
- return -1;
- }
-
- if(read_buf(sdp, *bhp, flags)){
- stack;
- relse_buf(sdp, *bhp);
- *bhp = NULL; /* guarantee that ptr is NULL in failure cases */
- return -1;
- }
-
- return 0;
-}
-
diff --git a/gfs/gfs_fsck/bio.h b/gfs/gfs_fsck/bio.h
deleted file mode 100644
index 08ceefa..0000000
--- a/gfs/gfs_fsck/bio.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __BIO_H
-#define __BIO_H
-
-#include "osi_user.h"
-#include "fsck_incore.h"
-/* buf_write flags */
-#define BW_WAIT 1
-
-
-#define BH_DATA(bh) ((char *)(bh)->b_data)
-#define BH_BLKNO(bh) ((uint64)(bh)->b_blocknr)
-#define BH_SIZE(bh) ((uint32)(bh)->b_size)
-#define BH_STATE(bh) ((uint32)(bh)->b_state)
-
-int get_buf(struct fsck_sb *sdp, uint64 blkno, osi_buf_t **bhp);
-void relse_buf(struct fsck_sb *sdp, osi_buf_t *bh);
-int read_buf(struct fsck_sb *sdp, osi_buf_t *bh, int flags);
-int write_buf(struct fsck_sb *sdp, osi_buf_t *bh, int flags);
-int get_and_read_buf(struct fsck_sb *sdp, uint64 blkno, osi_buf_t **bhp, int flags);
-
-#endif /* __BIO_H */
-
-
diff --git a/gfs/gfs_fsck/bitmap.c b/gfs/gfs_fsck/bitmap.c
deleted file mode 100644
index 12da279..0000000
--- a/gfs/gfs_fsck/bitmap.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* Basic bitmap manipulation */
-#include <stdint.h>
-#include <stdio.h>
-#include <errno.h>
-#include "osi_user.h"
-#include "bitmap.h"
-#include "block_list.h"
-#include "fsck_incore.h"
-#include "log.h"
-
-
-#define BITMAP_SIZE(size, cpb) (size / cpb)
-
-#define BITMAP_BYTE_OFFSET(x, map) ((x % map->chunks_per_byte) \
- * map->chunksize )
-
-#define BITMAP_MASK(chunksize) ((2 << (chunksize - 1)) - 1)
-
-uint64_t bitmap_size(struct bmap *bmap) {
- return bmap->size;
-}
-
-int bitmap_create(struct bmap *bmap, uint64_t size, uint8_t chunksize)
-{
- if((((chunksize >> 1) << 1) != chunksize) && chunksize != 1) {
- log_err("chunksize must be a power of 2\n");
- return -1;
- }
- if(chunksize > 8) {
- log_err("chunksize must be <= 8\n");
- return -1;
- }
- bmap->chunksize = chunksize;
- bmap->chunks_per_byte = 8 / chunksize;
-
- bmap->size = size;
-
- /* Have to add 1 to BITMAP_SIZE since it's 0-based and mallocs
- * must be 1-based */
- bmap->mapsize = BITMAP_SIZE(size, bmap->chunks_per_byte)+1;
-
- if(!(bmap->map = malloc(sizeof(char) * bmap->mapsize))) {
- log_err("Unable to allocate bitmap of size %"PRIu64"\n",
- bmap->mapsize);
- return -ENOMEM;
- }
- if(!memset(bmap->map, 0, sizeof(char) * bmap->mapsize)) {
- log_err("Unable to zero bitmap of size %"PRIu64"\n",
- bmap->mapsize);
- free(bmap->map);
- bmap->map = NULL;
- return -ENOMEM;
- }
- log_debug("Allocated bitmap of size %"PRIu64
- " with %d chunks per byte\n",
- bmap->mapsize, bmap->chunks_per_byte);
- return 0;
-}
-
-int bitmap_set(struct bmap *bmap, uint64_t offset, uint8_t val)
-{
- char *byte = NULL;
- uint64_t b = offset;
-
- if(offset < bmap->size) {
- byte = bmap->map + BITMAP_SIZE(offset, bmap->chunks_per_byte);
- b = BITMAP_BYTE_OFFSET(offset, bmap);
-
- *byte |= (val & BITMAP_MASK(bmap->chunksize)) << b;
- return 0;
- }
- log_debug("offset %d out of bounds\n", offset);
- return -1;
-}
-
-int bitmap_get(struct bmap *bmap, uint64_t bit, uint8_t *val)
-{
- char *byte = NULL;
- uint64_t b = bit;
-
- if(bit < bmap->size) {
- byte = bmap->map + BITMAP_SIZE(bit, bmap->chunks_per_byte);
- b = BITMAP_BYTE_OFFSET(bit, bmap);
-
- *val = (*byte & (BITMAP_MASK(bmap->chunksize) << b )) >> b;
- return 0;
- }
- log_debug("offset %d out of bounds\n", bit);
- return -1;
-}
-
-
-int bitmap_clear(struct bmap *bmap, uint64_t offset)
-{
- char *byte = NULL;
- uint64_t b = offset;
-
- if(offset < bmap->size) {
- byte = bmap->map + BITMAP_SIZE(offset, bmap->chunks_per_byte);
- b = BITMAP_BYTE_OFFSET(offset, bmap);
-
- *byte &= ~(BITMAP_MASK(bmap->chunksize) << b);
- return 0;
- }
- log_debug("offset %d out of bounds\n", offset);
- return -1;
-
-}
-
-void bitmap_destroy(struct bmap *bmap)
-{
- if(bmap->map)
- free(bmap->map);
- bmap->size = 0;
- bmap->mapsize = 0;
- bmap->chunksize = 0;
- bmap->chunks_per_byte = 0;
-}
diff --git a/gfs/gfs_fsck/bitmap.h b/gfs/gfs_fsck/bitmap.h
deleted file mode 100644
index c634a06..0000000
--- a/gfs/gfs_fsck/bitmap.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _BITMAP_H
-#define _BITMAP_H
-
-struct bmap {
- uint64_t size;
- uint64_t mapsize;
- int chunksize;
- int chunks_per_byte;
- char *map;
-};
-
-int bitmap_create(struct bmap *bmap, uint64_t size, uint8_t bitsize);
-int bitmap_set(struct bmap *bmap, uint64_t offset, uint8_t val);
-int bitmap_get(struct bmap *bmap, uint64_t bit, uint8_t *val);
-int bitmap_clear(struct bmap *bmap, uint64_t offset);
-void bitmap_destroy(struct bmap *bmap);
-uint64_t bitmap_size(struct bmap *bmap);
-
-
-#endif /* _BITMAP_H */
diff --git a/gfs/gfs_fsck/block_list.c b/gfs/gfs_fsck/block_list.c
deleted file mode 100644
index 2e9017f..0000000
--- a/gfs/gfs_fsck/block_list.c
+++ /dev/null
@@ -1,283 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include "bitmap.h"
-#include "block_list.h"
-#include "fsck.h"
-
-/* Must be kept in sync with mark_block enum in block_list.h */
-static int mark_to_gbmap[16] = {
- block_free, block_used, indir_blk, inode_dir, inode_file,
- inode_lnk, inode_blk, inode_chr, inode_fifo, inode_sock,
- leaf_blk, journal_blk, meta_other, meta_free,
- meta_eattr, meta_inval
-};
-
-struct block_list *block_list_create(uint64_t size, enum block_list_type type)
-{
- struct block_list *il;
- uint64_t addl_mem_needed = 0L;
- log_info("Creating a block list of size %"PRIu64"...\n", size);
-
- if ((il = malloc(sizeof(*il)))) {
- memset(il, 0, sizeof(*il));
- il->type = type;
-
- switch(type) {
- case gbmap:
- if(bitmap_create(&il->list.gbmap.group_map, size, 4)) {
- /* Note on addl_mem_needed: We've tried to allocate ram */
- /* for our bitmaps, but we failed. The fs is too big. */
- /* We should tell them how much to allocate. This first */
- /* bitmap is the biggest, but we need three more smaller */
- /* for the code that immediately follows. I'm rounding */
- /* up to twice the memory for this bitmap, even though */
- /* it's actually 1 + 3/4. That will allow for future */
- /* mallocs that happen after this point in the code. */
- /* For the bad_map, we have two more to go (total of 3) */
- /* but again I'm rounding it up to 4 smaller ones. */
- /* For the dup_map, I'm rounding from 2 to 3, and for */
- /* eattr_map, I'm rounding up from 1 to 2. */
- addl_mem_needed = il->list.gbmap.group_map.mapsize * 2;
- stack;
- free(il);
- il = NULL;
- }
- else if(bitmap_create(&il->list.gbmap.bad_map, size, 1)) {
- addl_mem_needed = il->list.gbmap.group_map.mapsize * 4;
- stack;
- free(il);
- il = NULL;
- }
- else if(bitmap_create(&il->list.gbmap.dup_map, size, 1)) {
- addl_mem_needed = il->list.gbmap.group_map.mapsize * 3;
- stack;
- free(il);
- il = NULL;
- }
- else if(bitmap_create(&il->list.gbmap.eattr_map, size, 1)) {
- addl_mem_needed = il->list.gbmap.group_map.mapsize * 2;
- stack;
- free(il);
- il = NULL;
- }
- if (addl_mem_needed) {
- log_err("This system doesn't have enough memory + swap space to fsck this file system.\n");
- log_err("Additional memory needed is approximately: %ldMB\n", addl_mem_needed / 1048576);
- log_err("Please increase your swap space by that amount and run gfs_fsck again.\n");
- }
- break;
- default:
- log_crit("Block list type %d not implemented\n",
- type);
- break;
- }
- }
-
- return il;
-}
-
-int block_mark(struct block_list *il, uint64_t block, enum mark_block mark)
-{
- int err = 0;
-
- switch(il->type) {
- case gbmap:
- if(mark == bad_block) {
- err = bitmap_set(&il->list.gbmap.bad_map, block, 1);
- }
- else if(mark == dup_block) {
- err = bitmap_set(&il->list.gbmap.dup_map, block, 1);
- }
- else if(mark == eattr_block) {
- err = bitmap_set(&il->list.gbmap.eattr_map, block, 1);
- }
- else {
- err = bitmap_set(&il->list.gbmap.group_map, block,
- mark_to_gbmap[mark]);
- }
-
- break;
- default:
- log_err("block list type %d not implemented\n",
- il->type);
- err = -1;
- break;
- }
- return err;
-}
-
-int block_set(struct block_list *il, uint64_t block, enum mark_block mark)
-{
- int err = 0;
- err = block_clear(il, block);
- if(!err)
- err = block_mark(il, block, mark);
- return err;
-}
-
-int block_unmark(struct block_list *il, uint64_t block, enum mark_block m)
-{
- int err = 0;
-
- switch(il->type) {
- case gbmap:
- switch (m) {
- case dup_block:
- err = bitmap_clear(&il->list.gbmap.dup_map, block);
- break;
- case bad_block:
- err = bitmap_clear(&il->list.gbmap.bad_map, block);
- break;
- case eattr_block:
- err = bitmap_clear(&il->list.gbmap.eattr_map, block);
- break;
- default:
- /* FIXME: check types */
- err = bitmap_clear(&il->list.gbmap.group_map, block);
- break;
- }
-
- break;
- default:
- log_err("block list type %d not implemented\n",
- il->type);
- err = -1;
- break;
- }
- return err;
-}
-
-int block_clear(struct block_list *il, uint64_t block)
-{
- int err = 0;
-
- switch(il->type) {
- case gbmap:
- err = bitmap_clear(&il->list.gbmap.dup_map, block);
- err = bitmap_clear(&il->list.gbmap.bad_map, block);
- err = bitmap_clear(&il->list.gbmap.eattr_map, block);
- err = bitmap_clear(&il->list.gbmap.group_map, block);
- break;
- default:
- log_err("block list type %d not implemented\n",
- il->type);
- err = -1;
- break;
- }
- return err;
-}
-
-int block_check(struct block_list *il, uint64_t block, struct block_query *val)
-{
- int err = 0;
- val->block_type = 0;
- val->bad_block = 0;
- val->dup_block = 0;
- switch(il->type) {
- case gbmap:
- if((err = bitmap_get(&il->list.gbmap.group_map, block,
- &val->block_type))) {
- log_err("Unable to get block type for block %"
- PRIu64"\n", block);
- break;
- }
- if((err = bitmap_get(&il->list.gbmap.bad_map, block,
- &val->bad_block))) {
- log_err("Unable to get bad block status for block %"
- PRIu64"\n", block);
- break;
- }
- if((err = bitmap_get(&il->list.gbmap.dup_map, block,
- &val->dup_block))) {
- log_err("Unable to get duplicate status for block %"
- PRIu64"\n", block);
- break;
- }
- if((err = bitmap_get(&il->list.gbmap.eattr_map, block,
- &val->eattr_block))) {
- log_err("Unable to get eattr status for block %"
- PRIu64"\n", block);
- break;
- }
- break;
- default:
- log_err("block list type %d not implemented\n",
- il->type);
- err = -1;
- break;
- }
-
- return err;
-}
-
-void *block_list_destroy(struct block_list *il)
-{
- if(il) {
- switch(il->type) {
- case gbmap:
- bitmap_destroy(&il->list.gbmap.group_map);
- bitmap_destroy(&il->list.gbmap.bad_map);
- bitmap_destroy(&il->list.gbmap.dup_map);
- bitmap_destroy(&il->list.gbmap.eattr_map);
- break;
- default:
- break;
- }
- free(il);
- il = NULL;
- }
- return il;
-}
-
-
-int find_next_block_type(struct block_list *il, enum mark_block m, uint64_t *b)
-{
- uint64_t i;
- uint8_t val;
- int found = 0;
- for(i = *b; ; i++) {
- switch(il->type) {
- case gbmap:
- if(i >= bitmap_size(&il->list.gbmap.dup_map))
- return -1;
-
- switch(m) {
- case dup_block:
- if(bitmap_get(&il->list.gbmap.dup_map, i, &val)) {
- stack;
- return -1;
- }
-
- if(val)
- found = 1;
- break;
- case eattr_block:
- if(bitmap_get(&il->list.gbmap.eattr_map, i, &val)) {
- stack;
- return -1;
- }
-
- if(val)
- found = 1;
- break;
- default:
- /* FIXME: add support for getting
- * other types */
- log_err("Unhandled block type\n");
- }
- break;
- default:
- log_err("Unhandled block list type\n");
- break;
- }
- if(found) {
- *b = i;
- return 0;
- }
- }
- return -1;
-}
diff --git a/gfs/gfs_fsck/block_list.h b/gfs/gfs_fsck/block_list.h
deleted file mode 100644
index 71c5642..0000000
--- a/gfs/gfs_fsck/block_list.h
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef _BLOCK_LIST_H
-#define _BLOCK_LIST_H
-
-#include "bitmap.h"
-
-#define BMAP_COUNT 13
-
-enum block_list_type {
- gbmap = 0, /* Grouped bitmap */
- dbmap, /* Ondisk bitmap - like grouped bitmap, but mmaps
- * the bitmaps onto file(s) ondisk - not implemented */
-};
-
-/* Must be kept in sync with mark_to_bitmap array in block_list.c */
-enum mark_block {
- block_free = 0,
- block_used = 1,
- indir_blk = 2,
- inode_dir = 3,
- inode_file = 4,
- inode_lnk = 5,
- inode_blk = 6,
- inode_chr = 7,
- inode_fifo = 8,
- inode_sock = 9,
- leaf_blk = 10,
- journal_blk = 11,
- meta_other = 12,
- meta_free = 13,
- meta_eattr = 14,
- meta_inval = 15,
- /* above this are nibble-values 0x0-0xf */
- bad_block = 16, /* Contains at least one bad block */
- dup_block = 17, /* Contains at least one duplicate block */
- eattr_block = 18, /* Contains an eattr */
-};
-
-struct block_query {
- uint8_t block_type;
- uint8_t bad_block;
- uint8_t dup_block;
- uint8_t eattr_block;
-};
-
-struct gbmap {
- struct bmap group_map;
- struct bmap bad_map;
- struct bmap dup_map;
- struct bmap eattr_map;
-};
-
-struct dbmap {
- struct bmap group_map;
- char *group_file;
- struct bmap bad_map;
- char *bad_file;
- struct bmap dup_map;
- char *dup_file;
- struct bmap eattr_map;
- char *eattr_file;
-};
-
-union block_lists {
- struct gbmap gbmap;
- struct dbmap dbmap;
-};
-
-
-/* bitmap implementation */
-struct block_list {
- enum block_list_type type;
- /* Union of bitmap, rle */
- union block_lists list;
-};
-
-
-struct block_list *block_list_create(uint64_t size, enum block_list_type type);
-int block_mark(struct block_list *il, uint64_t block, enum mark_block mark);
-int block_set(struct block_list *il, uint64_t block, enum mark_block mark);
-int block_unmark(struct block_list *il, uint64_t block, enum mark_block m);
-int block_clear(struct block_list *il, uint64_t block);
-int block_check(struct block_list *il, uint64_t block,
- struct block_query *val);
-int block_check_for_mark(struct block_list *il, uint64_t block,
- enum mark_block mark);
-void *block_list_destroy(struct block_list *il);
-int find_next_block_type(struct block_list *il, enum mark_block m, uint64_t *b);
-
-#endif /* _BLOCK_LIST_H */
diff --git a/gfs/gfs_fsck/eattr.c b/gfs/gfs_fsck/eattr.c
deleted file mode 100644
index 2891c33..0000000
--- a/gfs/gfs_fsck/eattr.c
+++ /dev/null
@@ -1,100 +0,0 @@
-#include <stdint.h>
-
-#include "fsck_incore.h"
-#include "eattr.h"
-
-static int clear_blk_nodup(struct fsck_sb *sbp, uint64_t block)
-{
- struct block_query q;
-
- if(block_check(sbp->bl, block, &q)) {
- stack;
- return -1;
- }
-
- if(q.dup_block) {
- log_debug("Not clearing block with marked as a duplicate\n");
- return 1;
- }
-
- block_set(sbp->bl, block, block_free);
-
- return 0;
-
-}
-
-int clear_eattr_indir(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh,
- void *private)
-{
- return clear_blk_nodup(ip->i_sbd, block);
-}
-
-
-int clear_eattr_leaf(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh,
- void *private)
-{
-
- return clear_blk_nodup(ip->i_sbd, block);
-
-}
-
-
-int clear_eattr_entry (struct fsck_inode *ip,
- osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- char ea_name[256];
-
- if(!ea_hdr->ea_name_len){
- /* Skip this entry for now */
- return 1;
- }
-
- memset(ea_name, 0, sizeof(ea_name));
- strncpy(ea_name, (char *)ea_hdr + sizeof(struct gfs_ea_header),
- ea_hdr->ea_name_len);
-
- if(!GFS_EATYPE_VALID(ea_hdr->ea_type) &&
- ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
- /* Skip invalid entry */
- return 1;
- }
-
- if(ea_hdr->ea_num_ptrs){
- uint32 avail_size;
- int max_ptrs;
-
- avail_size = sdp->sb.sb_bsize - sizeof(struct gfs_meta_header);
- max_ptrs = (gfs32_to_cpu(ea_hdr->ea_data_len)+avail_size-1)/avail_size;
-
- if(max_ptrs > ea_hdr->ea_num_ptrs) {
- return 1;
- } else {
- log_debug(" Pointers Required: %d\n"
- " Pointers Reported: %d\n",
- max_ptrs,
- ea_hdr->ea_num_ptrs);
- }
-
-
- }
- return 0;
-}
-
-int clear_eattr_extentry(struct fsck_inode *ip, uint64_t *ea_data_ptr,
- osi_buf_t *leaf_bh, struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev, void *private)
-{
- uint64_t block = gfs64_to_cpu(*ea_data_ptr);
-
- return clear_blk_nodup(ip->i_sbd, block);
-
-}
-
-
-
diff --git a/gfs/gfs_fsck/eattr.h b/gfs/gfs_fsck/eattr.h
deleted file mode 100644
index c1cbfea..0000000
--- a/gfs/gfs_fsck/eattr.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef _EATTR_H
-#define _EATTR_H
-
-int clear_eattr_indir(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh,
- void *private);
-int clear_eattr_leaf(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh,
- void *private);
-int clear_eattr_entry (struct fsck_inode *ip,
- osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private);
-int clear_eattr_extentry(struct fsck_inode *ip, uint64_t *ea_data_ptr,
- osi_buf_t *leaf_bh, struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev, void *private);
-
-
-
-#endif /* _EATTR_H */
diff --git a/gfs/gfs_fsck/file.c b/gfs/gfs_fsck/file.c
deleted file mode 100644
index a76d359..0000000
--- a/gfs/gfs_fsck/file.c
+++ /dev/null
@@ -1,231 +0,0 @@
-#include "util.h"
-#include "bio.h"
-#include "fs_bmap.h"
-#include "fs_inode.h"
-#include "fsck.h"
-#include "file.h"
-
-/**
- * readi - Read a file
- * @ip: The GFS Inode
- * @buf: The buffer to place result into
- * @offset: File offset to begin reading from
- * @size: Amount of data to transfer
- *
- * Returns: The amount of data actually copied or the error
- */
-int readi(struct fsck_inode *ip, void *bufin, uint64 offset, unsigned int size)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- osi_buf_t *bh;
- uint64_t lblock, dblock=0;
- uint32_t extlen = 0;
- unsigned int amount;
- int not_new = 0;
- int journaled = fs_is_jdata(ip);
- int copied = 0;
- int error = 0;
- char *buf = bufin;
-
- if (offset >= ip->i_di.di_size){
- log_debug("readi: Offset (%"PRIu64") is >= "
- "the file size (%"PRIu64").\n",
- offset, ip->i_di.di_size);
- goto out;
- }
-
- if ((offset + size) > ip->i_di.di_size)
- size = ip->i_di.di_size - offset;
-
- if (!size){
- log_err("readi: Nothing to be read.\n");
- goto out;
- }
-
- if (journaled){
- lblock = offset / sdp->jbsize;
- offset %= sdp->jbsize;
- }
- else{
- lblock = offset >> sdp->sb.sb_bsize_shift;
- offset &= sdp->sb.sb_bsize - 1;
- }
-
- if (fs_is_stuffed(ip))
- offset += sizeof(struct gfs_dinode);
- else if (journaled)
- offset += sizeof(struct gfs_meta_header);
-
-
- while (copied < size){
- amount = size - copied;
- if (amount > sdp->sb.sb_bsize - offset)
- amount = sdp->sb.sb_bsize - offset;
-
- if (!extlen){
- error = fs_block_map(ip, lblock, ¬_new, &dblock, &extlen);
- if (error){
- log_err("readi: The call to fs_block_map() failed.\n");
- goto out;
- }
- }
-
- if (dblock){
- error = get_and_read_buf(ip->i_sbd, dblock, &bh, 0);
- if (error){
- log_err("readi: Unable to perform get_and_read_buf()\n");
- goto out;
- }
-
- dblock++;
- extlen--;
- }
- else
- bh = NULL;
-
- if (bh){
- memcpy(buf+copied, BH_DATA(bh)+offset, amount);
- relse_buf(ip->i_sbd, bh);
- } else {
- memset(buf+copied, 0, amount);
- }
- copied += amount;
- lblock++;
-
- offset = (journaled) ? sizeof(struct gfs_meta_header) : 0;
- }
-
- out:
-
- return (error < 0) ? error : copied;
-}
-
-
-
-/**
- * writei - Write bytes to a file
- * @ip: The GFS inode
- * @buf: The buffer containing information to be written
- * @offset: The file offset to start writing at
- * @size: The amount of data to write
- *
- * Returns: The number of bytes correctly written or error code
- */
-int writei(struct fsck_inode *ip, void *bufin, uint64_t offset, unsigned int size)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- osi_buf_t *dibh, *bh;
- uint64_t lblock, dblock;
- uint32_t extlen = 0;
- unsigned int amount;
- int new;
- int journaled = fs_is_jdata(ip);
- const uint64_t start = offset;
- int copied = 0;
- int error = 0;
- char *buf = bufin;
-
- /* Bomb out on writing nothing.
- Posix says we can't change the time here. */
-
- if (!size)
- goto fail; /* Not really an error */
-
-
- if (fs_is_stuffed(ip) &&
- ((start + size) > (sdp->sb.sb_bsize - sizeof(struct gfs_dinode)))){
- error = fs_unstuff_dinode(ip);
- if (error)
- goto fail;
- }
-
-
- if (journaled){
- lblock = offset / sdp->jbsize;
- offset %= sdp->jbsize;
- }
- else{
- lblock = offset >> sdp->sb.sb_bsize_shift;
- offset &= sdp->sb.sb_bsize - 1;
- }
-
- if (fs_is_stuffed(ip))
- offset += sizeof(struct gfs_dinode);
- else if (journaled)
- offset += sizeof(struct gfs_meta_header);
-
-
- while (copied < size){
- amount = size - copied;
- if (amount > sdp->sb.sb_bsize - offset)
- amount = sdp->sb.sb_bsize - offset;
-
- if (!extlen){
- new = TRUE;
- error = fs_block_map(ip, lblock, &new, &dblock, &extlen);
- if (error)
- goto fail;
- if(!dblock){
- log_crit("fs_writei: "
- "Unable to map logical block to real block.\n");
- log_crit("Uncircumventable error.\n");
- exit(FSCK_ERROR);
- }
- }
-
- error = get_and_read_buf(ip->i_sbd, dblock, &bh, 0);
- if (error)
- goto fail;
-
- if(journaled && dblock != ip->i_di.di_num.no_addr ) {
- set_meta(bh, GFS_METATYPE_JD, GFS_FORMAT_JD);
- }
-
- memcpy(BH_DATA(bh)+offset, buf+copied, amount);
- write_buf(ip->i_sbd, bh, 0);
- relse_buf(ip->i_sbd, bh);
-
- copied += amount;
- lblock++;
- dblock++;
- extlen--;
-
- offset = (journaled) ? sizeof(struct gfs_meta_header) : 0;
- }
-
-
- out:
- error = get_and_read_buf(ip->i_sbd, ip->i_num.no_addr, &dibh, 0);
- if (error){
- log_err("fs_writei: "
- "Unable to get inode buffer.\n");
- return -1;
- }
-
- error = check_meta(dibh, GFS_METATYPE_DI);
- if(error){
- log_err("fs_writei: "
- "Buffer is not a valid inode.\n");
- relse_buf(ip->i_sbd, dibh);
- return -1;
- }
-
- if (ip->i_di.di_size < start + copied)
- ip->i_di.di_size = start + copied;
- ip->i_di.di_mtime = ip->i_di.di_ctime = osi_current_time();
-
- gfs_dinode_out(&ip->i_di, BH_DATA(dibh));
- write_buf(ip->i_sbd, dibh, 0);
- relse_buf(ip->i_sbd, dibh);
-
- return copied;
-
-
-
- fail:
- if (copied)
- goto out;
-
- return error;
-}
-
diff --git a/gfs/gfs_fsck/file.h b/gfs/gfs_fsck/file.h
deleted file mode 100644
index dfccb00..0000000
--- a/gfs/gfs_fsck/file.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _FILE_H
-#define _FILE_H
-
-#include <stdint.h>
-#include "fsck_incore.h"
-
-int readi(struct fsck_inode *ip, void *buf, uint64_t offset, unsigned int size);
-int writei(struct fsck_inode *ip, void *buf, uint64_t offset, unsigned int size);
-
-#endif /* _FILE_H */
diff --git a/gfs/gfs_fsck/fs_bits.c b/gfs/gfs_fsck/fs_bits.c
deleted file mode 100644
index b0edfe1..0000000
--- a/gfs/gfs_fsck/fs_bits.c
+++ /dev/null
@@ -1,350 +0,0 @@
-#include "util.h"
-#include "bio.h"
-#include "rgrp.h"
-
-#include "fsck_incore.h"
-#include "fs_bits.h"
-/**
- * fs_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
- *
- */
-static void fs_setbit(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 / GFS_NBBY);
- bit = (block % GFS_NBBY) * GFS_BIT_SIZE;
- end = buffer + buflen;
-
- if(byte >= end){
- log_err("fs_setbit: byte >= end\n");
- exit(FSCK_ERROR);
- }
- cur_state = (*byte >> bit) & GFS_BIT_MASK;
-
- *byte ^= cur_state << bit;
- *byte |= new_state << bit;
-}
-
-static uint32_t fs_bitfit_core(struct fsck_sb *sbp, uint64_t goal, uint64_t start, uint64_t len,
- unsigned char old_state)
-{
- uint64_t block;
- struct block_query q;
-
- log_debug("Goal: %"PRIu64", Start: %"PRIu64" len: %"PRIu64"\n",
- goal, start, len);
- for(block = start+goal; block < start+len; block++) {
- block_check(sbp->bl, block, &q);
- switch(old_state) {
- case GFS_BLKST_FREE:
- switch(q.block_type) {
- case block_free:
- return block - start;
- }
- break;
- case GFS_BLKST_FREEMETA:
- switch(q.block_type) {
- case meta_free:
- return block - start;
- }
- break;
- case GFS_BLKST_USEDMETA:
- switch(q.block_type) {
- case inode_dir:
- case inode_file:
- case inode_lnk:
- case inode_blk:
- case inode_chr:
- case inode_fifo:
- case inode_sock:
- case indir_blk:
- case leaf_blk:
- case journal_blk:
- case meta_other:
- case meta_eattr:
- return block - start;
- }
- break;
- case GFS_BLKST_USED:
- switch(q.block_type) {
- case block_used:
- return block - start;
- }
- break;
- default:
- log_err("Invalid type");
- break;
- }
- }
- return BFITNOENT;
-}
-/**
- * fs_bitfit - Find a free block in the bitmaps
- * @buffer: the buffer that holds the bitmaps
- * @buflen: the length (in bytes) of the buffer
- * @goal: the block to try to allocate
- * @old_state: the state of the block we're looking for
- *
- * Return: the block number that was allocated
- */
-uint32_t fs_bitfit(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 / GFS_NBBY);
- bit = (goal % GFS_NBBY) * GFS_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) & GFS_BIT_MASK) == old_state){
- return blk;
- }
-
- bit += GFS_BIT_SIZE;
- if (bit >= 8){
- bit = 0;
- byte++;
- }
-
- blk++;
- }
- return BFITNOENT;
-}
-
-/**
- * fs_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 fs_bitcount(unsigned char *buffer, unsigned int buflen,
- unsigned char state)
-{
- unsigned char *byte, *end;
- unsigned int bit;
- uint32_t count = 0;
-
- byte = buffer;
- bit = 0;
- end = buffer + buflen;
-
- while (byte < end){
- if (((*byte >> bit) & GFS_BIT_MASK) == state)
- count++;
-
- bit += GFS_BIT_SIZE;
- if (bit >= 8){
- bit = 0;
- byte++;
- }
- }
- return count;
-}
-
-
-/**
- * fs_blkalloc_internal - allocate a single block
- * @rgd: the resource group descriptor
- * @goal: the goal block in the RG
- * @old_state: the type of block to find
- * @new_state: the resulting block type
- * @do_it: if FALSE, we just find the block we would allocate
- *
- *
- * Returns: returns the block allocated, or BFITNOENT on failure
- */
-uint32_t fs_blkalloc_internal(struct fsck_rgrp *rgd, uint32_t goal,
- unsigned char old_state,
- unsigned char new_state, int do_it)
-{
- struct fsck_sb *sdp = rgd->rd_sbd;
- uint32_t block = 0;
- log_debug("fs_blkalloc_internal got %u as goal\n", goal);
- goal = ((int)(goal - rgd->rd_ri.ri_data1) < 0)
- ? 0
- : goal - rgd->rd_ri.ri_data1;
-
-
- block = fs_bitfit_core(sdp, goal, rgd->rd_ri.ri_data1,
- rgd->rd_ri.ri_data, old_state);
-
-
- if(block == BFITNOENT) {
- log_debug("No bits left in old_state?\n"
- "\told_state = %u\n"
- "\tnew_state = %u\n"
- "\trg_free = %u\n"
- "\trg_freemeta = %u\n",
- old_state, new_state,
- rgd->rd_rg.rg_free,
- rgd->rd_rg.rg_freemeta);
- return BFITNOENT;
- }
-
- log_debug("fs_blkalloc_internal found block %u\n", block);
- switch(new_state) {
- case GFS_BLKST_FREE:
- block_set(sdp->bl, block + rgd->rd_ri.ri_data1, block_free);
- break;
- case GFS_BLKST_USED:
- block_set(sdp->bl, block + rgd->rd_ri.ri_data1, block_used);
- break;
- case GFS_BLKST_USEDMETA:
- block_set(sdp->bl, block + rgd->rd_ri.ri_data1, meta_other);
- break;
- case GFS_BLKST_FREEMETA:
- block_set(sdp->bl, block + rgd->rd_ri.ri_data1, meta_free);
- break;
- }
- return block;
-}
-
-
-/*
- * fs_get_bitmap - get value of FS bitmap
- * @sdp: super block
- * @blkno: block number relative to file system
- *
- * This function gets the value of a bit of the
- * file system bitmap.
- * Possible state values for a block in the bitmap are:
- * GFS_BLKST_FREE (0)
- * GFS_BLKST_USED (1)
- * GFS_BLKST_FREEMETA (2)
- * GFS_BLKST_USEDMETA (3)
- *
- * Returns: state on success, -1 on error
- */
-int fs_get_bitmap(struct fsck_sb *sdp, uint64 blkno, struct fsck_rgrp *rgd){
- int buf, val;
- uint32_t rgrp_block;
-/* struct fsck_rgrp *rgd;*/
- fs_bitmap_t *bits = NULL;
- unsigned int bit;
- unsigned char *byte;
- int local_rgd = 0;
-
- if(check_range(sdp, blkno)){
- log_warn("Block #%"PRIu64" is out of range.\n", blkno);
- return -1;
- }
- if(rgd == NULL) {
- local_rgd = 1;
- rgd = fs_blk2rgrpd(sdp, blkno);
- }
- if(rgd == NULL){
- log_err( "Unable to get rgrp for block #%"PRIu64"\n", blkno);
- return -1;
- }
- if(fs_rgrp_read(rgd, FALSE)){ /* FALSE:don't try to fix (done elsewhere) */
- log_err( "Unable to read rgrp.\n");
- return -1;
- }
-
- rgrp_block = (uint32_t)(blkno - rgd->rd_ri.ri_data1);
-
- for(buf= 0; buf < rgd->rd_ri.ri_length; buf++){
- bits = &(rgd->rd_bits[buf]);
- if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS_NBBY)){
- break;
- }
- }
-
- if(buf >= rgd->rd_ri.ri_length){
- log_err( "Unable to locate bitmap entry for block #%"PRIu64"\n",
- blkno);
- fs_rgrp_relse(rgd);
- return -1;
- }
-
- byte = (unsigned char *)((BH_DATA(rgd->rd_bh[buf]) + bits->bi_offset) +
- (rgrp_block/GFS_NBBY - bits->bi_start));
- bit = (rgrp_block % GFS_NBBY) * GFS_BIT_SIZE;
-
- val = ((*byte >> bit) & GFS_BIT_MASK);
- if(local_rgd) {
- fs_rgrp_relse(rgd);
- }
-
- return val;
-}
-
-
-/*
- * fs_set_bitmap
- * @sdp: super block
- * @blkno: block number relative to file system
- * @state: one of 4 possible states
- *
- * This function sets the value of a bit of the
- * file system bitmap.
- *
- * Returns: 0 on success, -1 on error
- */
-int fs_set_bitmap(struct fsck_sb *sdp, uint64 blkno, int state){
- int buf;
- uint32_t rgrp_block;
- fs_bitmap_t *bits = NULL;
- struct fsck_rgrp *rgd;
-
- if((state != GFS_BLKST_FREE) && (state != GFS_BLKST_USED) &&
- (state != GFS_BLKST_FREEMETA) && (state != GFS_BLKST_USEDMETA)){
- return -1;
- }
-
- rgd = fs_blk2rgrpd(sdp, blkno);
-
- if(!rgd) {
- log_err("Unable to get resource group for blkno %"PRIu64"\n",
- blkno);
- return -1;
- }
-
- if(fs_rgrp_read(rgd, FALSE)) {
- stack;
- return -1;
- }
- rgrp_block = (uint32_t)(blkno - rgd->rd_ri.ri_data1);
- for(buf= 0; buf < rgd->rd_ri.ri_length; buf++){
- bits = &(rgd->rd_bits[buf]);
- if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS_NBBY)){
- break;
- }
- }
- if (buf < rgd->rd_ri.ri_length) {
- fs_setbit((unsigned char *)BH_DATA(rgd->rd_bh[buf]) +
- bits->bi_offset,
- bits->bi_len,
- (rgrp_block - (bits->bi_start*GFS_NBBY)),
- state);
- if(write_buf(sdp, rgd->rd_bh[buf], 0)){
- fs_rgrp_relse(rgd);
- return -1;
- }
- }
- fs_rgrp_relse(rgd);
- return 0;
-}
diff --git a/gfs/gfs_fsck/fs_bits.h b/gfs/gfs_fsck/fs_bits.h
deleted file mode 100644
index 7d889bc..0000000
--- a/gfs/gfs_fsck/fs_bits.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __FS_BITS_H__
-#define __FS_BITS_H__
-
-#include "global.h"
-#include "rgrp.h"
-#include "fsck_incore.h"
-#include "fsck.h"
-
-#define BFITNOENT (0xFFFFFFFF)
-
-struct fs_bitmap
-{
- uint32 bi_offset; /* The offset in the buffer of the first byte */
- uint32 bi_start; /* The position of the first byte in this block */
- uint32 bi_len; /* The number of bytes in this block */
-};
-typedef struct fs_bitmap fs_bitmap_t;
-
-/* functions with blk #'s that are buffer relative */
-uint32_t fs_bitcount(unsigned char *buffer, unsigned int buflen,
- unsigned char state);
-uint32_t fs_bitfit(unsigned char *buffer, unsigned int buflen,
- uint32_t goal, unsigned char old_state);
-
-/* functions with blk #'s that are rgrp relative */
-uint32_t fs_blkalloc_internal(struct fsck_rgrp *rgd, uint32_t goal,
- unsigned char old_state,
- unsigned char new_state, int do_it);
-
-/* functions with blk #'s that are file system relative */
-int fs_get_bitmap(struct fsck_sb *sdp, uint64_t blkno, struct fsck_rgrp *rgd);
-int fs_set_bitmap(struct fsck_sb *sdp, uint64_t blkno, int state);
-
-#endif /* __FS_BITS_H__ */
diff --git a/gfs/gfs_fsck/fs_bmap.c b/gfs/gfs_fsck/fs_bmap.c
deleted file mode 100644
index ad4f8ac..0000000
--- a/gfs/gfs_fsck/fs_bmap.c
+++ /dev/null
@@ -1,529 +0,0 @@
-#include "util.h"
-#include "rgrp.h"
-#include "fs_inode.h"
-#include "bio.h"
-
-#include "fs_bmap.h"
-
-typedef struct metapath
-{
- uint64 mp_list[GFS_MAX_META_HEIGHT];
-}metapath_t;
-
-
-/**
- * fs_unstuff_dinode - Unstuff a dinode when the data has grown too big
- * @ip: The GFS inode to unstuff
- * * This routine unstuffs a dinode and returns it to a "normal" state such
- * that the height can be grown in the traditional way.
- *
- * Returns: 0 on success, -EXXXX on failure
- */
-int fs_unstuff_dinode(struct fsck_inode *ip)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- osi_buf_t *bh = NULL;
- osi_buf_t *dibh = NULL;
- int journaled = fs_is_jdata(ip);
- uint64 block = 0;
- int error;
-
- log_debug("Unstuffing inode %"PRIu64" - %u\n", ip->i_di.di_num.no_addr,
- journaled);
-
- if(!fs_is_stuffed(ip)){
- log_err("Trying to unstuff a dinode that is already unstuffed.\n");
- return -1;
- }
-
-
- error = get_and_read_buf(sdp, ip->i_num.no_addr, &dibh, 0);
- if (error) {
- stack;
- goto fail;
- }
-
- error = check_meta(dibh, GFS_METATYPE_DI);
- if(error) {
- stack;
- goto fail;
- }
-
- if (ip->i_di.di_size){
- log_err("Allocating new block for unstuffed dinode\n");
- if(journaled){
- error = fs_metaalloc(ip, &block);
- if (error) {
- stack;
- goto fail;
- }
- log_err("Got block %"PRIu64"\n", block);
- error = get_buf(sdp, block, &bh);
- if (error) {
- stack;
- goto fail;
- }
-
- set_meta(bh, GFS_METATYPE_JD, GFS_FORMAT_JD);
-
- memcpy(BH_DATA(bh)+sizeof(struct gfs_meta_header),
- BH_DATA(dibh)+sizeof(struct gfs_dinode),
- BH_SIZE(dibh)-sizeof(struct gfs_dinode));
-
- error = write_buf(sdp, bh, 0);
- if(error) {
- stack;
- goto fail;
- }
- relse_buf(sdp, bh);
- block_set(sdp->bl, block, journal_blk);
- }
- else{
- error = fs_blkalloc(ip, &block);
-
- if(error) {
- stack;
- goto fail;
- }
-
- error = get_buf(sdp, block, &bh);
- if (error) {
- stack;
- goto fail;
- }
-
- memcpy(BH_DATA(bh)+sizeof(struct gfs_meta_header),
- BH_DATA(dibh)+sizeof(struct gfs_dinode),
- BH_SIZE(dibh)-sizeof(struct gfs_dinode));
-
- error = write_buf(sdp, bh, 0);
- if(error) {
- stack;
- goto fail;
- }
- relse_buf(sdp, bh);
- block_set(sdp->bl, block, block_used);
- }
- }
-
- bh = NULL;
- /* Set up the pointer to the new block */
-
- memset(BH_DATA(dibh)+sizeof(struct gfs_dinode), 0,
- BH_SIZE(dibh)-sizeof(struct gfs_dinode));
-
- if (ip->i_di.di_size){
- ((uint64 *)(BH_DATA(dibh) + sizeof(struct gfs_dinode)))[0] = cpu_to_gfs64(block);
- ip->i_di.di_blocks++;
- }
-
- ip->i_di.di_height = 1;
-
- gfs_dinode_out(&ip->i_di, BH_DATA(dibh));
- if(write_buf(sdp, dibh, 0)){
- log_err("Dinode unstuffed, but unable to write back dinode.\n");
- goto fail;
- }
- relse_buf(sdp, dibh);
-
- return 0;
-
-
-
- fail:
- if(bh) relse_buf(sdp, bh);
- if(dibh) relse_buf(sdp, dibh);
-
- return error;
-}
-
-
-/**
- * calc_tree_height - Calculate the height of a metadata tree
- * @ip: The GFS inode
- * @size: The proposed size of the file
- *
- * Work out how tall a metadata tree needs to be in order to accommodate a
- * file of a particular size. If size is less than the current size of
- * the inode, then the current size of the inode is used instead of the
- * supplied one.
- *
- * Returns: the height the tree should be
- */
-
-static unsigned int calc_tree_height(struct fsck_inode *ip, uint64 size)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- uint64 *arr;
- unsigned int max, height;
-
- if (ip->i_di.di_size > size)
- size = ip->i_di.di_size;
-
- if (fs_is_jdata(ip)){
- arr = sdp->jheightsize;
- max = sdp->max_jheight;
- }
- else{
- arr = sdp->heightsize;
- max = sdp->max_height;
- }
- for (height = 0; height < max; height++)
- if (arr[height] >= size)
- break;
-
- return height;
-}
-
-
-/**
- * build_height - Build a metadata tree of the requested height
- * @ip: The GFS inode
- * @height: The height to build to
- *
- *
- * Returns: 0 on success, -EXXXX on failure
- */
-static int build_height(struct fsck_inode *ip, int height)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- osi_buf_t *bh, *dibh;
- uint64 block, *bp;
- unsigned int x;
- int new_block;
- int error;
-
- while (ip->i_di.di_height < height){
- error = get_and_read_buf(ip->i_sbd, ip->i_num.no_addr, &dibh, 0);
- if (error)
- goto fail;
-
- new_block = FALSE;
- bp = (uint64 *)(BH_DATA(dibh) + sizeof(struct gfs_dinode));
- for (x = 0; x < sdp->diptrs; x++, bp++)
- if (*bp){
- new_block = TRUE;
- break;
- }
-
-
- if (new_block){
- /* Get a new block, fill it with the old direct pointers and write it out */
- error = fs_metaalloc(ip, &block);
- if (error)
- goto fail_drelse;
-
- error = get_and_read_buf(sdp, block, &bh, 0);
- if (error)
- goto fail_drelse;
-
- set_meta(bh, GFS_METATYPE_IN, GFS_FORMAT_IN);
- /*
- gfs_buffer_copy_tail(bh, sizeof(struct gfs_indirect),
- dibh, sizeof(struct gfs_dinode));
- */
- log_err("ATTENTION -- Not doing copy_tail...\n");
- exit(FSCK_ERROR);
- error = -1;
- goto fail_drelse;
- if((error = write_buf(sdp, bh, 0))){
- log_err( "Unable to write new buffer #%"PRIu64".\n",
- BH_BLKNO(bh));
- goto fail_drelse;
- }
- relse_buf(sdp, bh);
- }
-
-
- /* Set up the new direct pointer and write it out to disk */
-
- memset(BH_DATA(dibh)+sizeof(struct gfs_dinode), 0,
- BH_SIZE(dibh)-sizeof(struct gfs_dinode));
-
- if (new_block){
- ((uint64 *)(BH_DATA(dibh) + sizeof(struct gfs_dinode)))[0] = cpu_to_gfs64(block);
- ip->i_di.di_blocks++;
- }
-
- ip->i_di.di_height++;
-
- gfs_dinode_out(&ip->i_di, BH_DATA(dibh));
- write_buf(sdp, dibh, 0);
- relse_buf(sdp, dibh);
- }
-
- return 0;
-
-
-
- fail_drelse:
- relse_buf(sdp, dibh);
-
- fail:
- return error;
-}
-
-
-static void find_metapath(struct fsck_inode *ip, metapath_t *mp, uint64 block)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- unsigned int i;
-
- for (i = ip->i_di.di_height; i--; ){
- mp->mp_list[i] = block % sdp->inptrs;
- block /= sdp->inptrs;
- }
-}
-
-
-/**
- * metapointer - Return pointer to start of metadata in a buffer
- * @bh: The buffer
- * @level: The metadata level (0 = dinode)
- * @mp: The metapath
- *
- * Return a pointer to the block number of the next level of the metadata
- * tree given a buffer containing the pointer to the current level of the
- * metadata tree.
- */
-
-static uint64 *metapointer(osi_buf_t *bh, unsigned int level, metapath_t *mp)
-{
- int head_size = (level > 0) ? sizeof(struct gfs_indirect) : sizeof(struct gfs_dinode);
- return ((uint64 *)(BH_DATA(bh) + head_size)) + mp->mp_list[level];
-}
-
-
-/**
- * get_metablock - Get the next metadata block in metadata tree
- * @ip: The GFS inode
- * @bh: Buffer containing the pointers to metadata blocks
- * @level: The level of the tree (0 = dinode)
- * @mp: The metapath
- * @create: Non-zero if we may create a new meatdata block
- * @new: Used to indicate if we did create a new metadata block
- * @block: the returned disk block number
- *
- * Given a metatree, complete to a particular level, checks to see if the next
- * level of the tree exists. If not the next level of the tree is created.
- * The block number of the next level of the metadata tree is returned.
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-static int get_metablock(struct fsck_inode *ip,
- osi_buf_t *bh, unsigned int level, metapath_t *mp,
- int create, int *new, uint64 *block)
-{
- uint64 *ptr = metapointer(bh, level, mp);
- int error = 0;
-
- *new = 0;
- *block = 0;
-
- if (*ptr){
- *block = gfs64_to_cpu(*ptr);
- goto out;
- }
-
- if (!create)
- goto out;
-
- error = fs_metaalloc(ip, block);
- if (error)
- goto out;
-
- *ptr = cpu_to_gfs64(*block);
- ip->i_di.di_blocks++;
- write_buf(ip->i_sbd, bh, 0);
-
- *new = 1;
-
- out:
- return error;
-}
-
-
-/**
- * get_datablock - Get datablock number from metadata block
- * @rgd: rgrp to allocate from if necessary
- * @ip: The GFS inode
- * @bh: The buffer containing pointers to datablocks
- * @mp: The metapath
- * @create: Non-zero if we may create a new data block
- * @new: Used to indicate if we created a new data block
- * @block: the returned disk block number
- *
- * Given a fully built metadata tree, checks to see if a particular data
- * block exists. It is created if it does not exist and the block number
- * on disk is returned.
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-static int get_datablock(struct fsck_inode *ip,
- osi_buf_t *bh, metapath_t *mp,
- int create, int *new, uint64 *block)
-{
- uint64 *ptr = metapointer(bh, ip->i_di.di_height - 1, mp);
- int error = 0;
-
- *new = 0;
- *block = 0;
-
-
- if (*ptr){
- *block = gfs64_to_cpu(*ptr);
- goto out;
- }
-
- if (!create)
- goto out;
-
- if (fs_is_jdata(ip)){
- error = fs_metaalloc(ip, block);
- if (error)
- goto out;
- }
- else {
- error = fs_blkalloc(ip, block);
- if (error)
- goto out;
- }
-
- *ptr = cpu_to_gfs64(*block);
- ip->i_di.di_blocks++;
- write_buf(ip->i_sbd, bh, 0);
-
- *new = 1;
-
- out:
- return error;
-}
-
-
-/**
- * fs_block_map - Map a block from an inode to a disk block
- * @ip: The GFS inode
- * @lblock: The logical block number
- * @new: Value/Result argument (1 = may create/did create new blocks)
- * @dblock: the disk block number of the start of an extent
- * @extlen: the size of the extent
- *
- * Find the block number on the current device which corresponds to an
- * inode's block. If the block had to be created, "new" will be set.
- *
- * Returns: 0 on success, -EXXX on failure
- */
-int fs_block_map(struct fsck_inode *ip, uint64 lblock, int *new,
- uint64 *dblock, uint32 *extlen)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- osi_buf_t *bh = NULL;
- metapath_t mp;
- int create = *new;
- unsigned int bsize;
- unsigned int height;
- unsigned int x, end_of_metadata;
- unsigned int nptrs;
- uint64 tmp_dblock;
- int tmp_new;
- int error = 0;
-
- *new = 0;
- *dblock = 0;
- if (extlen)
- *extlen = 0;
-
- if (fs_is_stuffed(ip)){
- *dblock = ip->i_num.no_addr;
- if (extlen)
- *extlen = 1;
- goto out;
- }
- bsize = (fs_is_jdata(ip)) ? sdp->jbsize : sdp->sb.sb_bsize;
-
- height = calc_tree_height(ip, (lblock + 1) * bsize);
- if (ip->i_di.di_height < height){
- if (!create){
- error = 0;
- goto fail;
- }
-
- error = build_height(ip, height);
- if (error)
- goto fail;
- }
-
-
- error = get_and_read_buf(ip->i_sbd, ip->i_num.no_addr, &bh, 0);
- if (error)
- goto fail;
-
-
- find_metapath(ip, &mp, lblock);
- end_of_metadata = ip->i_di.di_height - 1;
-
- for (x = 0; x < end_of_metadata; x++){
- error = get_metablock(ip, bh, x, &mp, create, new, dblock);
- relse_buf(ip->i_sbd, bh); bh = NULL;
- if (error)
- goto fail;
- if (!*dblock)
- goto out;
-
- error = get_and_read_buf(ip->i_sbd, *dblock, &bh, 0);
- if (error)
- goto fail;
- }
-
-
- error = get_datablock(ip, bh, &mp, create, new, dblock);
- if (error)
- goto fail_drelse;
-
- if (extlen && *dblock){
- *extlen = 1;
-
- if (!*new){
- nptrs = (end_of_metadata) ? sdp->inptrs : sdp->diptrs;
- while (++mp.mp_list[end_of_metadata] < nptrs){
- error = get_datablock(ip, bh, &mp, 0, &tmp_new,
- &tmp_dblock);
- if(error){
- log_err( "Unable to perform get_datablock.\n");
- goto fail;
- }
-
- if (*dblock + *extlen != tmp_dblock)
- break;
-
- (*extlen)++;
- }
- }
- }
-
-
- relse_buf(sdp, bh);
-
-
- out:
- if (*new){
- error = get_and_read_buf(sdp, ip->i_num.no_addr, &bh, 0);
- if (error)
- goto fail;
- gfs_dinode_out(&ip->i_di, BH_DATA(bh));
- write_buf(sdp, bh, 0);
- relse_buf(sdp, bh);
- }
- return 0;
-
-
-
- fail_drelse:
- if(bh)
- relse_buf(sdp, bh);
-
- fail:
- return error;
-}
diff --git a/gfs/gfs_fsck/fs_bmap.h b/gfs/gfs_fsck/fs_bmap.h
deleted file mode 100644
index 658a62e..0000000
--- a/gfs/gfs_fsck/fs_bmap.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __FS_BMAP_H__
-#define __FS_BMAP_H__
-
-#include "fsck_incore.h"
-
-int fs_unstuff_dinode(struct fsck_inode *ip);
-int fs_block_map(struct fsck_inode *ip, uint64 lblock, int *new,
- uint64 *dblock, uint32 *extlen);
-
-#endif /* __FS_BMAP_H__ */
diff --git a/gfs/gfs_fsck/fs_dir.c b/gfs/gfs_fsck/fs_dir.c
deleted file mode 100644
index c3db529..0000000
--- a/gfs/gfs_fsck/fs_dir.c
+++ /dev/null
@@ -1,1775 +0,0 @@
-#include "util.h"
-#include "file.h"
-#include "rgrp.h"
-#include "fsck_incore.h"
-#include "fs_inode.h"
-#include "bio.h"
-#include "link.h"
-#include "limits.h"
-#include "metawalk.h"
-#include "fs_dir.h"
-
-#define IS_LEAF (1)
-#define IS_DINODE (2)
-
-#define dir_hash(qstr) (gfs_dir_hash((char *)(qstr)->name, (qstr)->len))
-
-/* Detect directory is a stuffed inode */
-int fsck_inode_is_stuffed(struct fsck_inode *ip)
-{
- return !ip->i_di.di_height;
-}
-
-/**
- * dirent_first - Return the first dirent
- * @bh: The buffer
- * @dent: Pointer to list of dirents
- *
- * return first dirent whether bh points to leaf or stuffed dinode
- *
- * Returns: IS_LEAF or IS_DINODE
- */
-int dirent_first(osi_buf_t *bh, struct gfs_dirent **dent)
-{
- struct gfs_leaf *leaf;
- struct gfs_dinode *dinode;
-
- leaf = (struct gfs_leaf *)BH_DATA(bh);
-
- if (gfs32_to_cpu(leaf->lf_header.mh_type) == GFS_METATYPE_LF)
- {
- *dent = (struct gfs_dirent *)(BH_DATA(bh) + sizeof(struct gfs_leaf));
-
- return IS_LEAF;
- }
- else
- {
- dinode = (struct gfs_dinode *)BH_DATA(bh);
- if(gfs32_to_cpu(dinode->di_header.mh_type) != GFS_METATYPE_DI){
- log_err("buffer is not GFS_METATYPE_[DI | LF]\n");
- return -1;
- }
-
- *dent = (struct gfs_dirent *)(BH_DATA(bh) + sizeof(struct gfs_dinode));
-
- return IS_DINODE;
- }
-}
-
-
-/**
- * dirent_next - Next dirent
- * @bh: The buffer
- * @dent: Pointer to list of dirents
- *
- * Returns: 0 on success, error code otherwise
- */
-static int dirent_next(osi_buf_t *bh, struct gfs_dirent **dent)
-{
- struct gfs_dirent *tmp, *cur;
- char *bh_end;
- uint32 cur_rec_len;
-
- cur = *dent;
- bh_end = BH_DATA(bh) + BH_SIZE(bh);
-
- cur_rec_len = gfs16_to_cpu(cur->de_rec_len);
-
- if ((char *)cur + cur_rec_len >= bh_end){
- if((char *)cur + cur_rec_len != bh_end){
- log_err("Bad record length causing failure in dirent_next()\n");
- return -1;
- }
- return -ENOENT;
- }
-
- tmp = (struct gfs_dirent *)((char *)cur + cur_rec_len);
-
- if((char *)tmp + gfs16_to_cpu(tmp->de_rec_len) > bh_end){
- log_err("Bad record length causing failure in dirent_next\n");
- return -1;
- }
-
- /* only the first dent could ever have de_ino == 0 */
- if(!tmp->de_inum.no_formal_ino){
- char tmp_name[256];
-
- memcpy(tmp_name, cur+sizeof(struct gfs_dirent), gfs16_to_cpu(cur->de_name_len));
- tmp_name[gfs16_to_cpu(cur->de_name_len)] = '\0';
- log_err("dirent_next: "
- "A non-first dir entry has zero formal inode.\n");
- log_err("\tFaulty dirent after (%s) in block #%"PRIu64".\n",
- tmp_name, BH_BLKNO(bh));
-
- return -1;
- }
-
- *dent = tmp;
-
- return 0;
-}
-
-
-/**
- * dirent_del - Delete a dirent
- * @dip: The GFS inode
- * @bh: The buffer
- * @prev: The previous dirent
- * @cur: The current dirent
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int dirent_del(struct fsck_inode *dip, osi_buf_t *bh,
- struct gfs_dirent *prev, struct gfs_dirent *cur){
- uint32 cur_rec_len, prev_rec_len;
-
- dip->i_di.di_entries--;
- if(!cur->de_inum.no_formal_ino){
- log_err("dirent_del: "
- "Can not delete dirent with !no_formal_ino.\n");
- return -1;
- }
-
- /* If there is no prev entry, this is the first entry in the block.
- The de_rec_len is already as big as it needs to be. Just zero
- out the inode number and return. */
-
- if (!prev){
- cur->de_inum.no_formal_ino = 0; /* No endianess worries */
- if(write_buf(dip->i_sbd, bh, 0)){
- log_err("dirent_del: Bad write_buf.\n");
- return -EIO;
- }
- return 0;
- }
-
- /* Combine this dentry with the previous one. */
-
- prev_rec_len = gfs16_to_cpu(prev->de_rec_len);
- cur_rec_len = gfs16_to_cpu(cur->de_rec_len);
-
- if((char *)prev + prev_rec_len != (char *)cur){
- log_err("dirent_del: Bad bounds for directory entries.\n");
- return -1;
- }
-
- if((char *)cur + cur_rec_len > BH_DATA(bh) + BH_SIZE(bh)){
- log_err("dirent_del: Directory entry has record length"
- " longer than buffer.\n");
- return -1;
- }
-
- log_debug("Updating previous record from %u to %u\n",
- prev_rec_len, prev_rec_len+cur_rec_len);
- prev_rec_len += cur_rec_len;
- prev->de_rec_len = cpu_to_gfs16(prev_rec_len);
-
- if(write_buf(dip->i_sbd, bh, 0)){
- log_err("dirent_del: Bad write_buf.\n");
- return -EIO;
- }
-
- return 0;
-}
-
-
-/**
- * get_leaf - Get leaf
- * @dip:
- * @leaf_no:
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int get_leaf(struct fsck_inode *dip, uint64 leaf_no, osi_buf_t **bhp)
-{
- int error;
-
- error = get_and_read_buf(dip->i_sbd, leaf_no, bhp, 0);
-
- if (error) {
- log_err("Unable to read leaf buffer #%"PRIu64"\n", leaf_no);
- return error;
- }
-
- error = check_meta(*bhp, GFS_METATYPE_LF);
-
- if(error) {
- log_err("Metatype for block #%"PRIu64" is not type 'leaf'\n",
- leaf_no);
- relse_buf(dip->i_sbd, *bhp);
- }
- return error;
-}
-
-
-/**
- * get_first_leaf - Get first leaf
- * @dip: The GFS inode
- * @lindex:
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int get_first_leaf(struct fsck_inode *dip, uint32 lindex, osi_buf_t **bh_out)
-{
- uint64 leaf_no;
- int error;
-
- error = get_leaf_nr(dip, lindex, &leaf_no);
- if (!error)
- error = get_leaf(dip, leaf_no, bh_out);
-
- return error;
-}
-
-
-/**
- * get_next_leaf - Get next leaf
- * @dip: The GFS inode
- * @bh_in: The buffer
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int get_next_leaf(struct fsck_inode *dip,osi_buf_t *bh_in,osi_buf_t **bh_out)
-{
- struct gfs_leaf *leaf;
- int error;
-
- leaf = (struct gfs_leaf *)BH_DATA(bh_in);
-
- if (!leaf->lf_next)
- error = -ENOENT;
- else
- error = get_leaf(dip, gfs64_to_cpu(leaf->lf_next), bh_out);
- return error;
-}
-
-/**
- * leaf_search
- * @bh:
- * @id:
- * @dent_out:
- * @dent_prev:
- *
- * Returns:
- */
-static int leaf_search(osi_buf_t *bh, identifier_t *id,
- struct gfs_dirent **dent_out,
- struct gfs_dirent **dent_prev)
-{
- uint32 hash;
- struct gfs_dirent *dent, *prev = NULL;
- unsigned int entries = 0, x = 0;
- int type;
-
- type = dirent_first(bh, &dent);
-
- if (type == IS_LEAF){
- struct gfs_leaf *leaf = (struct gfs_leaf *)BH_DATA(bh);
- entries = gfs16_to_cpu(leaf->lf_entries);
- } else if (type == IS_DINODE) {
- struct gfs_dinode *dinode = (struct gfs_dinode *)(BH_DATA(bh));
- entries = gfs32_to_cpu(dinode->di_entries);
- } else {
- log_err("type != IS_LEAF && type != IS_DINODE\n");
- return -1;
- }
-
- if(id->type == ID_FILENAME){
- hash = dir_hash(id->filename);
-
- do{
- if (!dent->de_inum.no_formal_ino){
- prev = dent;
- continue;
- }
-
- if (gfs32_to_cpu(dent->de_hash) == hash &&
- fs_filecmp(id->filename, (char *)(dent + 1),
- gfs16_to_cpu(dent->de_name_len))){
- *dent_out = dent;
- if (dent_prev)
- *dent_prev = prev;
- return 0;
- }
-
- if(x >= entries){
- log_err("x >= entries (%u >= %u)\n", x, entries);
- return -1;
- }
- x++;
- prev = dent;
- } while (dirent_next(bh, &dent) == 0);
- } else if(id->type == ID_INUM){
- struct gfs_inum inum;
-
- do{
- if (!dent->de_inum.no_formal_ino){
- prev = dent;
- continue;
- }
-
- gfs_inum_in(&inum, (char *)&dent->de_inum);
-
- if(inum.no_addr == id->inum->no_addr){
- *dent_out = dent;
- if(dent_prev)
- *dent_prev = prev;
- return 0;
- }
-
- if(x >= entries){
- log_err("x >= entries (%u >= %u)\n", x, entries);
- return -1;
- }
- x++;
- prev = dent;
- } while (dirent_next(bh, &dent) == 0);
- } else {
- log_err("leaf_search: Invalid type for identifier.\n");
- exit(FSCK_ERROR);
- }
-
- return -ENOENT;
-}
-
-
-/**
- * linked_leaf_search - Linked leaf search
- * @dip: The GFS inode
- * @id:
- * @dent_out:
- * @dent_prev:
- * @bh_out:
- *
- * Returns: 0 on sucess, error code otherwise
- */
-
-static int linked_leaf_search(struct fsck_inode *dip, identifier_t *id,
- struct gfs_dirent **dent_out,
- struct gfs_dirent **dent_prev, osi_buf_t **bh_out)
-{
- osi_buf_t *bh = NULL, *bh_next;
- uint32 hsize, lindex;
- uint32 hash;
- int error = 0;
-
- hsize = 1 << dip->i_di.di_depth;
- if(hsize * sizeof(uint64) != dip->i_di.di_size){
- log_err("hsize * sizeof(uint64) != dip->i_di.di_size\n");
- return -1;
- }
-
- /* Figure out the address of the leaf node. */
-
- if(id->type == ID_FILENAME){
- hash = dir_hash(id->filename);
- lindex = hash >> (32 - dip->i_di.di_depth);
-
- error = get_first_leaf(dip, lindex, &bh_next);
- if (error){
- return error;
- }
-
- /* Find the entry */
- do{
- if (bh)
- relse_buf(dip->i_sbd, bh);
-
- bh = bh_next;
-
- error = leaf_search(bh, id, dent_out, dent_prev);
- switch (error){
- case 0:
- *bh_out = bh;
- return 0;
-
- case -ENOENT:
- break;
-
- default:
- relse_buf(dip->i_sbd, bh);
- return error;
- }
-
- error = get_next_leaf(dip, bh, &bh_next);
- }while (!error);
-
- relse_buf(dip->i_sbd, bh);
- } else if(id->type == ID_INUM){
- for(lindex=0; lindex < (1 << dip->i_di.di_depth); lindex++){
- error = get_first_leaf(dip, lindex, &bh_next);
- if (error){
- return error;
- }
-
- /* Find the entry */
- do{
- if (bh)
- relse_buf(dip->i_sbd, bh);
-
- bh = bh_next;
-
- error = leaf_search(bh, id, dent_out, dent_prev);
- switch (error){
- case 0:
- *bh_out = bh;
- return 0;
-
- case -ENOENT:
- break;
-
- default:
- relse_buf(dip->i_sbd, bh);
- return error;
- }
-
- error = get_next_leaf(dip, bh, &bh_next);
- }while (!error);
- }
- } else {
- log_err("linked_leaf_search: Invalid type for identifier.\n");
- exit(FSCK_ERROR);
- }
- return error;
-}
-
-
-/**
- * dir_e_search -
- * @dip: The GFS inode
- * @id:
- * @inode:
- *
- * Returns:
- */
-static int dir_e_search(struct fsck_inode *dip, identifier_t *id, unsigned int *type)
-{
- osi_buf_t *bh = NULL;
- struct gfs_dirent *dent;
- int error;
-
- error = linked_leaf_search(dip, id, &dent, NULL, &bh);
- if (error){
- return error;
- }
-
- if(id->type == ID_FILENAME){
- if(id->inum){
- log_err("dir_e_search: Illegal parameter. inum must be NULL.\n");
- exit(FSCK_ERROR);
- }
- if(!(id->inum = (struct gfs_inum *)malloc(sizeof(struct gfs_inum)))) {
- log_err("Unable to allocate inum structure\n");
- return -1;
- }
- if(!memset(id->inum, 0, sizeof(struct gfs_inum))) {
- log_err("Unable to zero inum structure\n");
- return -1;
- }
-
- gfs_inum_in(id->inum, (char *)&dent->de_inum);
- } else {
- if(id->filename){
- log_err("dir_e_search: Illegal parameter. name must be NULL.\n");
- exit(FSCK_ERROR);
- }
- if(!(id->filename = (osi_filename_t *)malloc(sizeof(osi_filename_t)))) {
- log_err("Unable to allocate osi_filename structure\n");
- return -1;
- }
- if(!(memset(id->filename, 0, sizeof(osi_filename_t)))) {
- log_err("Unable to zero osi_filename structure\n");
- return -1;
- }
-
- id->filename->len = gfs16_to_cpu(dent->de_name_len);
- if(!(id->filename->name = malloc(id->filename->len))) {
- log_err("Unable to allocate name in osi_filename structure\n");
- free(id->filename);
- return -1;
- }
- if(!(memset(id->filename->name, 0, id->filename->len))) {
- log_err("Unable to zero name in osi_filename structure\n");
- free(id->inum);
- free(id->filename);
- return -1;
- }
-
- memcpy(id->filename->name, (char *)dent+sizeof(struct gfs_dirent),
- id->filename->len);
- }
- if (type)
- *type = gfs16_to_cpu(dent->de_type);
-
- relse_buf(dip->i_sbd, bh);
-
- return 0;
-}
-
-
-/**
- * dir_l_search -
- * @dip: The GFS inode
- * @id:
- * @inode:
- *
- * Returns:
- */
-static int dir_l_search(struct fsck_inode *dip, identifier_t *id, unsigned int *type)
-{
- osi_buf_t *dibh;
- struct gfs_dirent *dent;
- int error;
-
- if(!fs_is_stuffed(dip)){
- log_err("A linear search was attempted on a directory "
- "that is not stuffed.\n");
- return -1;
- }
-
- error = get_and_read_buf(dip->i_sbd, dip->i_num.no_addr, &dibh, 0);
- if (error)
- goto out;
-
-
- error = leaf_search(dibh, id, &dent, NULL);
- if (error)
- goto out_drelse;
-
- if(id->type == ID_FILENAME){
- if(id->inum){
- log_err("dir_l_search: Illegal parameter. inum must be NULL.\n");
- exit(FSCK_ERROR);
- }
- id->inum = (struct gfs_inum *)malloc(sizeof(struct gfs_inum));
- // FIXME: don't dereference NULL on failed malloc
- memset(id->inum, 0, sizeof(struct gfs_inum));
-
- gfs_inum_in(id->inum, (char *)&dent->de_inum);
- } else {
- if(id->filename){
- log_err("dir_l_search: Illegal parameter. name must be NULL.\n");
- exit(FSCK_ERROR);
- }
- id->filename = (osi_filename_t *)malloc(sizeof(osi_filename_t));
- // FIXME: don't dereference NULL on failed malloc
- memset(id->filename, 0, sizeof(osi_filename_t));
-
- id->filename->len = gfs16_to_cpu(dent->de_name_len);
- id->filename->name = malloc(id->filename->len);
- // FIXME: don't dereference NULL on failed malloc
- memset(id->filename->name, 0, id->filename->len);
-
- memcpy(id->filename->name, (char *)dent+sizeof(struct gfs_dirent),
- id->filename->len);
- }
- if(type)
- *type = gfs16_to_cpu(dent->de_type);
-
-
- out_drelse:
- relse_buf(dip->i_sbd, dibh);
-
- out:
- return error;
-}
-
-
-/**
- * dir_make_exhash - Convet a stuffed directory into an ExHash directory
- * @dip: The GFS inode
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int dir_make_exhash(struct fsck_inode *dip)
-{
- struct fsck_sb *sdp = dip->i_sbd;
- struct gfs_dirent *dent;
- osi_buf_t *bh = NULL, *dibh = NULL;
- struct gfs_leaf *leaf;
- int y;
- uint32 x;
- uint64 *lp, bn;
- int error;
-
- /* Sanity checks */
-
- if(sizeof(struct gfs_leaf) > sizeof(struct gfs_dinode)){
- log_err(
- "dir_make_exhash: on-disk leaf is larger than on-disk dinode.\n"
- " Unable to expand directory.\n");
- return -1;
- }
-
- error = get_and_read_buf(dip->i_sbd, dip->i_num.no_addr, &dibh, 0);
- if (error)
- goto fail;
-
-
- error = fs_metaalloc(dip, &bn);
-
- if (error)
- goto fail_drelse;
-
-
- /* Turn over a new leaf */
-
- error = get_and_read_buf(sdp, bn, &bh, 0);
- if (error)
- goto fail_drelse;
-
- if(check_meta(bh, 0)){
- log_err("dir_make_exhash: Buffer has bad meta header.\n");
- goto fail_drelse;
- }
-
- set_meta(bh, GFS_METATYPE_LF, GFS_FORMAT_LF);
- memset(BH_DATA(bh) + sizeof(struct gfs_meta_header), 0,
- BH_SIZE(bh) - sizeof(struct gfs_meta_header));
-
- /* Fill in the leaf structure */
-
- leaf = (struct gfs_leaf *)BH_DATA(bh);
-
- if(dip->i_di.di_entries >= (1 << 16)){
- log_err(
- "dir_make_exhash: Too many directory entries.\n"
- " Unable to expand directory.\n");
- goto fail_drelse;
- }
- leaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE);
- leaf->lf_entries = cpu_to_gfs16(dip->i_di.di_entries);
-
-
- /* Copy dirents */
- memset(BH_DATA(bh)+sizeof(struct gfs_leaf), 0, BH_SIZE(bh)-sizeof(struct gfs_leaf));
- memcpy(BH_DATA(bh)+sizeof(struct gfs_leaf),
- BH_DATA(dibh)+sizeof(struct gfs_dinode),
- BH_SIZE(dibh)-sizeof(struct gfs_dinode));
-
- /* Find last entry */
-
- x = 0;
- dirent_first(bh, &dent);
-
- do
- {
- if (!dent->de_inum.no_formal_ino)
- continue;
-
- if (++x == dip->i_di.di_entries)
- break;
- }
- while (dirent_next(bh, &dent) == 0);
-
-
- /* Adjust the last dirent's record length
- (Remember that dent still points to the last entry.) */
-
- dent->de_rec_len = gfs16_to_cpu(dent->de_rec_len) +
- sizeof(struct gfs_dinode) - sizeof(struct gfs_leaf);
- dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len);
-
- if(write_buf(dip->i_sbd, bh, 0)){
- log_err("dir_make_exhash: bad write_buf()\n");
- goto fail_drelse;
- }
- relse_buf(dip->i_sbd, bh); bh=NULL;
-
- log_debug("Created a new leaf block at %"PRIu64"\n", bn);
-
- block_set(dip->i_sbd->bl, bn, leaf_blk);
- /* We're done with the new leaf block, now setup the new
- hash table. */
-
- memset(BH_DATA(dibh) + sizeof(struct gfs_dinode), 0,
- BH_SIZE(dibh) - sizeof(struct gfs_dinode));
-
- lp = (uint64 *)(BH_DATA(dibh) + sizeof(struct gfs_dinode));
-
- for (x = sdp->hash_ptrs; x--; lp++)
- *lp = cpu_to_gfs64(bn);
-
- dip->i_di.di_size = sdp->sb.sb_bsize / 2;
- dip->i_di.di_blocks++;
- dip->i_di.di_flags |= GFS_DIF_EXHASH;
- dip->i_di.di_payload_format = 0;
-
- for (x = sdp->hash_ptrs, y = -1; x; x >>= 1, y++) ;
- dip->i_di.di_depth = y;
-
- gfs_dinode_out(&dip->i_di, BH_DATA(dibh));
-
- if(write_buf(dip->i_sbd, dibh, 0)){
- log_err("dir_make_exhash: bad write_buf()\n");
- goto fail_drelse;
- }
- relse_buf(dip->i_sbd, dibh); dibh = NULL;
-
- return 0;
-
-
-
- fail_drelse:
- if(bh)
- relse_buf(dip->i_sbd, bh);
- if(dibh)
- relse_buf(dip->i_sbd, dibh);
-
- fail:
- return error;
-}
-
-
-/**
- * dir_split_leaf - Split a leaf block into two
- * @dip: The GFS inode
- * @lindex:
- * @leaf_no:
- *
- * Returns: 0 on success, error code on failure
- */
-static int dir_split_leaf(struct fsck_inode *dip, uint32 lindex, uint64 leaf_no)
-{
- struct fsck_sb *sdp = dip->i_sbd;
- osi_buf_t *nbh, *obh, *dibh;
- struct gfs_leaf *nleaf, *oleaf;
- struct gfs_dirent *dent, *prev = NULL, *next = NULL, *new;
- uint32 start, len, half_len, divider;
- uint64 bn, *lp;
- uint32 name_len;
- int x, moved = FALSE;
- int error;
-
- /* Allocate the new leaf block */
-
- error = fs_metaalloc(dip, &bn);
- if (error)
- goto fail;
-
-
- /* Get the new leaf block */
- error = get_and_read_buf(sdp, bn, &nbh, 0);
- if (error)
- goto fail;
-
- if(check_meta(nbh, 0)){
- log_err("dir_split_leaf: Buffer is not a meta buffer.\n");
- relse_buf(sdp, nbh);
- return -1;
- }
-
- set_meta(nbh, GFS_METATYPE_LF, GFS_FORMAT_LF);
-
- memset(BH_DATA(nbh)+sizeof(struct gfs_meta_header), 0,
- BH_SIZE(nbh)-sizeof(struct gfs_meta_header));
-
- nleaf = (struct gfs_leaf *)BH_DATA(nbh);
-
- nleaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE);
-
-
- /* Get the old leaf block */
-
- error = get_leaf(dip, leaf_no, &obh);
- if (error)
- goto fail_nrelse;
-
- oleaf = (struct gfs_leaf *)BH_DATA(obh);
-
-
- /* Compute the start and len of leaf pointers in the hash table. */
-
- len = 1 << (dip->i_di.di_depth - gfs16_to_cpu(oleaf->lf_depth));
- if(len == 1){
- log_err("dir_split_leaf: Corrupted leaf block encountered.\n");
- goto fail_orelse;
- }
- half_len = len >> 1;
-
- start = (lindex & ~(len - 1));
-
- log_debug("Splitting leaf: len = %u, half_len = %u\n", len, half_len);
-
- /* Change the pointers.
- Don't bother distinguishing stuffed from non-stuffed.
- This code is complicated enough already. */
-
- lp = (uint64 *)malloc(half_len * sizeof(uint64));
- // FIXME: don't dereference NULL on failed malloc
- memset(lp, 0, half_len * sizeof(uint64));
-
- error = readi(dip, (char *)lp, start * sizeof(uint64),
- half_len * sizeof(uint64));
- if (error != half_len * sizeof(uint64)){
- if (error >= 0)
- error = -EIO;
- goto fail_lpfree;
- }
-
- /* Change the pointers */
-
- for (x = 0; x < half_len; x++)
- lp[x] = cpu_to_gfs64(bn);
-
- error = writei(dip, (char *)lp, start * sizeof(uint64),
- half_len * sizeof(uint64));
-
- if (error != half_len * sizeof(uint64)){
- if (error >= 0)
- error = -EIO;
- goto fail_lpfree;
- }
-
- free(lp); lp = NULL; /* need to set lp for failure cases */
-
-
- /* Compute the divider */
-
- divider = (start + half_len) << (32 - dip->i_di.di_depth);
-
- /* Copy the entries */
-
- dirent_first(obh, &dent);
-
- do{
- next = dent;
- if (dirent_next(obh, &next))
- next = NULL;
-
- if (dent->de_inum.no_formal_ino &&
- (gfs32_to_cpu(dent->de_hash) < divider)){
- name_len = gfs16_to_cpu(dent->de_name_len);
-
- error = fs_dirent_alloc(dip, nbh, name_len, &new);
- if(error){
- log_err("dir_split_leaf: fs_dirent_alloc failed.\n");
- goto fail_orelse;
- }
-
- new->de_inum = dent->de_inum; /* No endianness worries */
- new->de_hash = dent->de_hash; /* No endianness worries */
- new->de_type = dent->de_type; /* No endianness worries */
- memcpy((char *)(new + 1), (char *)(dent + 1), name_len);
-
- nleaf->lf_entries = gfs16_to_cpu(nleaf->lf_entries) + 1;
- nleaf->lf_entries = cpu_to_gfs16(nleaf->lf_entries);
-
- dirent_del(dip, obh, prev, dent);
- /* Dirent del decrements entries, but we're
- * just shifting entries around, so increment
- * it again */
- dip->i_di.di_entries++;
-
- if(!gfs16_to_cpu(oleaf->lf_entries)){
- log_err("dir_split_leaf: old leaf contains no entries.\n");
- goto fail_orelse;
- }
- oleaf->lf_entries = gfs16_to_cpu(oleaf->lf_entries) - 1;
- oleaf->lf_entries = cpu_to_gfs16(oleaf->lf_entries);
-
- if (!prev)
- prev = dent;
-
- moved = TRUE;
- }
- else
- prev = dent;
-
- dent = next;
- }
- while (dent);
-
-
- /* If none of the entries got moved into the new leaf,
- artificially fill in the first entry. */
-
- if (!moved){
- error = fs_dirent_alloc(dip, nbh, 0, &new);
- if(error){
- log_err("dir_split_leaf: fs_dirent_alloc failed..\n");
- goto fail_orelse;
- }
- new->de_inum.no_formal_ino = 0;
- }
-
-
- oleaf->lf_depth = gfs16_to_cpu(oleaf->lf_depth) + 1;
- oleaf->lf_depth = cpu_to_gfs16(oleaf->lf_depth);
- nleaf->lf_depth = oleaf->lf_depth;
-
-
- error = get_and_read_buf(dip->i_sbd, dip->i_num.no_addr, &dibh, 0);
- if(error){
- log_err("dir_split_leaf: Unable to get inode buffer.\n");
- goto fail_orelse;
- }
-
- error = check_meta(dibh, GFS_METATYPE_DI);
- if(error){
- log_err("dir_split_leaf: Buffer #%"PRIu64" is not a directory "
- "inode.\n", BH_BLKNO(dibh));
- goto fail_drelse;
- }
-
- dip->i_di.di_blocks++;
-
- gfs_dinode_out(&dip->i_di, BH_DATA(dibh));
- if(write_buf(sdp, dibh, 0)){
- log_err("dir_split_leaf: Failed to write new directory inode.\n");
- goto fail_drelse;
- }
- relse_buf(sdp, dibh);
-
-
- if(write_buf(sdp, obh, 0)){
- log_err("dir_split_leaf: Failed to write back old leaf block.\n");
- goto fail_orelse;
- }
- relse_buf(sdp, obh);
- if(write_buf(sdp, nbh, 0)){
- log_err("dir_split_leaf: Failed to write new leaf block.\n");
- goto fail_nrelse;
- }
-
- log_debug("Created a new leaf block at %"PRIu64"\n", BH_BLKNO(nbh));
-
- block_set(dip->i_sbd->bl, BH_BLKNO(nbh), leaf_blk);
-
- relse_buf(sdp, nbh);
-
- return 0;
-
-
-
- fail_drelse:
- relse_buf(sdp, dibh);
-
- fail_lpfree:
- if(lp) free(lp);
-
- fail_orelse:
- relse_buf(sdp, obh);
-
- fail_nrelse:
- relse_buf(sdp, nbh);
-
- fail:
- return -1;
-}
-
-
-/**
- * dir_double_exhash - Double size of ExHash table
- * @dip: The GFS dinode
- *
- * Returns: 0 on success, -1 on failure
- */
-static int dir_double_exhash(struct fsck_inode *dip)
-{
- struct fsck_sb *sdp = dip->i_sbd;
- osi_buf_t *dibh;
- uint32 hsize;
- uint64 *buf;
- uint64 *from, *to;
- uint64 block;
- int x;
- int error = 0;
-
- /* Sanity Checks */
-
- hsize = 1 << dip->i_di.di_depth;
- if(hsize * sizeof(uint64) != dip->i_di.di_size){
- log_err("dir_double_exhash: "
- "hash size does not correspond to di_size.\n");
- return -1;
- }
-
-
- /* Allocate both the "from" and "to" buffers in one big chunk */
-
- buf = (uint64 *)malloc(3 * sdp->hash_bsize);
- if(!buf){
- log_err("dir_double_exhash: "
- "Unable to allocate memory for blk ptr list.\n");
- return -1;
- }
- memset(buf, 0, 3 * sdp->hash_bsize);
-
- for (block = dip->i_di.di_size / sdp->hash_bsize; block--;){
- error = readi(dip, (char *)buf, block * sdp->hash_bsize,
- sdp->hash_bsize);
- if (error != sdp->hash_bsize){
- if (error >= 0)
- error = -EIO;
- goto out;
- }
-
- from = buf;
- to = (uint64 *)((char *)buf + sdp->hash_bsize);
-
- for (x = sdp->hash_ptrs; x--; from++){
- *to++ = *from; /* No endianess worries */
- *to++ = *from;
- }
-
- error = writei(dip, (char *)buf + sdp->hash_bsize,
- block * sdp->sb.sb_bsize, sdp->sb.sb_bsize);
- if (error != sdp->sb.sb_bsize){
- if (error >= 0)
- error = -EIO;
- goto out;
- }
- }
-
- free(buf); buf=NULL;
-
-
- error = get_and_read_buf(sdp, dip->i_num.no_addr, &dibh, 0);
- if(error){
- log_err("dir_double_exhash: "
- "Unable to get inode buffer.\n");
- return -1;
- }
-
- error = check_meta(dibh, GFS_METATYPE_DI);
- if(error){
- log_err("dir_double_exhash: "
- "Buffer does not contain directory inode.\n");
- relse_buf(sdp, dibh);
- return -1;
- }
-
- dip->i_di.di_depth++;
-
- gfs_dinode_out(&dip->i_di, BH_DATA(dibh));
- if(write_buf(sdp, dibh, 0)){
- log_err("dir_double_exhash: "
- "Unable to write out directory inode.\n");
- relse_buf(sdp, dibh);
- return -1;
- }
-
- relse_buf(sdp, dibh);
-
- return 0;
-
-
- out:
- if(buf) free(buf);
-
- return error;
-}
-
-
-static int dir_e_del(struct fsck_inode *dip, osi_filename_t *filename){
- int lindex;
- int error;
- int found = 0;
- uint64 leaf_no;
- osi_buf_t *bh;
- identifier_t id;
- struct gfs_dirent *cur, *prev;
-
- id.type = ID_FILENAME;
- id.filename = filename;
- id.inum = NULL;
-
- lindex = (1 << (dip->i_di.di_depth))-1;
-
- for(; (lindex >= 0) && !found; lindex--){
- error = get_leaf_nr(dip, lindex, &leaf_no);
- if (error){
- log_err("dir_e_del: Unable to get leaf number.\n");
- return error;
- }
-
- while(leaf_no && !found){
- if(get_leaf(dip, leaf_no, &bh)){
- stack;
- return -1;
- }
-
- error = leaf_search(bh, &id, &cur, &prev);
- if(id.inum) free(id.inum);
-
- if(error){
- if(error != -ENOENT){
- log_err("dir_e_del: leaf_search failed.\n");
- relse_buf(dip->i_sbd, bh);
- return -1;
- }
- leaf_no = gfs64_to_cpu(((struct gfs_leaf *)BH_DATA(bh))->lf_next);
- relse_buf(dip->i_sbd, bh);
- } else {
- found = 1;
- }
- }
- }
-
- if(!found)
- return 1;
-
- if(dirent_del(dip, bh, prev, cur)){
- log_err("dir_e_del: dirent_del failed.\n");
- relse_buf(dip->i_sbd, bh);
- return -1;
- }
-
- relse_buf(dip->i_sbd, bh);
- return 0;
-}
-
-
-static int dir_l_del(struct fsck_inode *dip, osi_buf_t *dibh,
- osi_filename_t *filename){
- int error=0;
- int got_buf = 0;
- struct gfs_dirent *cur, *prev;
- identifier_t id;
-
- id.type = ID_FILENAME;
- id.filename = filename;
- id.inum = NULL;
-
- if(!fs_is_stuffed(dip)){
- log_crit("dir_l_del: Attempting linear delete on unstuffed"
- " dinode.\n");
- return -1;
- }
-
- if(!dibh) {
- error = get_and_read_buf(dip->i_sbd, dip->i_num.no_addr,
- &dibh, 0);
- if (error){
- log_err("dir_l_del: Failed to read in dinode buffer.\n");
- return -1;
- }
- got_buf = 1;
- }
-
- error = leaf_search(dibh, &id, &cur, &prev);
- if(id.inum) free(id.inum);
-
- if(error){
- if(error == -ENOENT){
- log_debug("dir_l_del found no entry\n");
- if(got_buf)
- relse_buf(dip->i_sbd, dibh);
- return 1;
- } else {
- log_err("dir_l_del: leaf_search failed.\n");
- if(got_buf)
- relse_buf(dip->i_sbd, dibh);
- return -1;
- }
- }
-
- if(dirent_del(dip, dibh, prev, cur)){
- stack;
- if(got_buf)
- relse_buf(dip->i_sbd, dibh);
- return -1;
- }
-
- if(got_buf)
- relse_buf(dip->i_sbd, dibh);
- return 0;
-}
-
-
-/*
- * fs_dirent_del
- * @dip
- * filename
- *
- * Delete a directory entry from a directory. This _only_
- * removes the directory entry - leaving the dinode in
- * place. (Likely without a link.)
- *
- * Returns: 0 on success (or if it doesn't already exist), -1 on failure
- */
-int fs_dirent_del(struct fsck_inode *dip, osi_buf_t *bh, osi_filename_t *filename){
- int error;
-
- if(dip->i_di.di_type != GFS_FILE_DIR){
- log_err("fs_dirent_del: parent inode is not a directory.\n");
- return -1;
- }
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH)
- error = dir_e_del(dip, filename);
- else
- error = dir_l_del(dip, bh, filename);
-
- return error;
-
-}
-
-
-/**
- * dir_e_add -
- * @dip: The GFS inode
- * @filename:
- * @inode:
- * @type:
- *
- */
-static int dir_e_add(struct fsck_inode *dip, osi_filename_t *filename,
- struct gfs_inum *inum, unsigned int type)
-{
- struct fsck_sb *sdp = dip->i_sbd;
- osi_buf_t *bh, *nbh, *dibh;
- struct gfs_leaf *leaf, *nleaf;
- struct gfs_dirent *dent;
- uint32 hsize, lindex;
- uint32 hash;
- uint64 leaf_no, bn;
- int error;
-
- restart:
-
- /* Sanity Checks */
-
- hsize = 1 << dip->i_di.di_depth;
- if(hsize * sizeof(uint64) != dip->i_di.di_size){
- log_err("dir_e_add: hash size and di_size do not correspond.\n");
- return -1;
- }
-
- /* Figure out the address of the leaf node. */
-
- hash = dir_hash(filename);
- lindex = hash >> (32 - dip->i_di.di_depth);
-
-
- error = get_leaf_nr(dip, lindex, &leaf_no);
- if (error){
- log_err("dir_e_add: Unable to get leaf number.\n");
- return error;
- }
-
-
- /* Add entry to the leaf */
-
- while (TRUE){
- error = get_leaf(dip, leaf_no, &bh);
- if (error){
- log_err("dir_e_add: Unable to get leaf #%"PRIu64"\n", leaf_no);
- return error;
- }
-
- leaf = (struct gfs_leaf *)BH_DATA(bh);
-
-
- if (fs_dirent_alloc(dip, bh, filename->len, &dent)){
- if (gfs16_to_cpu(leaf->lf_depth) < dip->i_di.di_depth){
- /* Can we split the leaf? */
- relse_buf(sdp, bh);
-
- error = dir_split_leaf(dip, lindex, leaf_no);
- if (error){
- log_err("dir_e_add: Unable to split leaf.\n");
- return error;
- }
-
- goto restart;
- }
- else if (dip->i_di.di_depth < GFS_DIR_MAX_DEPTH){
- /* Can we double the hash table? */
- relse_buf(sdp, bh);
-
- error = dir_double_exhash(dip);
- if (error){
- log_err("dir_e_add: Unable to double exhash.\n");
- return error;
- }
-
- goto restart;
- }
- else if (leaf->lf_next){
- /* Can we try the next leaf in the list? */
- leaf_no = gfs64_to_cpu(leaf->lf_next);
- relse_buf(sdp, bh);
- continue;
- }
- else {
- /* Create a new leaf and add it to the list. */
- error = fs_metaalloc(dip, &bn);
- if (error){
- relse_buf(sdp, bh);
- log_err("dir_e_add: "
- "Unable to allocate space for meta block.\n");
- return error;
- }
-
- error = get_and_read_buf(sdp, bn, &nbh, 0);
- if (error){
- relse_buf(sdp, bh);
- return error;
- }
-
- /*gfs_trans_add_bh(sdp, dip->i_gl, nbh);*/
- if(check_meta(nbh, 0)){
- log_err("dir_e_add: Buffer is not a meta buffer.\n");
- relse_buf(sdp, bh);
- relse_buf(sdp, nbh);
- return -1;
- }
- set_meta(nbh, GFS_METATYPE_LF, GFS_FORMAT_LF);
- /* Make sure the bitmap is updated */
- log_debug("Setting leaf block at %"PRIu64"\n",
- bn);
- block_set(dip->i_sbd->bl, bn, leaf_blk);
- memset(BH_DATA(nbh)+sizeof(struct gfs_meta_header), 0,
- BH_SIZE(nbh)-sizeof(struct gfs_meta_header));
-
- /*gfs_trans_add_bh(sdp, dip->i_gl, bh);*/
- leaf->lf_next = cpu_to_gfs64(bn);
-
- nleaf = (struct gfs_leaf *)BH_DATA(nbh);
- nleaf->lf_depth = leaf->lf_depth;
- nleaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE);
-
- if (fs_dirent_alloc(dip, nbh, filename->len, &dent)){
- log_err("dir_e_add: Uncircumventible error!\n");
- exit(FSCK_ERROR);
- }
-
- dip->i_di.di_blocks++;
-
- /* ATTENTION -- check for errors */
- write_buf(sdp, nbh, BW_WAIT);
- write_buf(sdp, bh, 0);
- relse_buf(sdp, bh);
-
- bh = nbh;
- leaf = nleaf;
- }
- }
-
-
- gfs_inum_out(inum, (char *)&dent->de_inum);
- dent->de_hash = cpu_to_gfs32(hash);
- dent->de_type = cpu_to_gfs16(type);
- memcpy((char *)(dent + 1), filename->name, filename->len);
-
- leaf->lf_entries = gfs16_to_cpu(leaf->lf_entries) + 1;
- leaf->lf_entries = cpu_to_gfs16(leaf->lf_entries);
-
- write_buf(sdp, bh, 0);
- relse_buf(sdp, bh);
-
- error = get_and_read_buf(dip->i_sbd, dip->i_num.no_addr, &dibh, 0);
- if(error){
- log_err("dir_e_add: Unable to get inode buffer.\n");
- return error;
- }
-
- error = check_meta(dibh, GFS_METATYPE_DI);
- if(error){
- log_err("dir_e_add: Buffer #%"PRIu64" is not a directory "
- "inode.\n", BH_BLKNO(dibh));
- relse_buf(sdp, dibh);
- return error;
- }
-
- dip->i_di.di_entries++;
- dip->i_di.di_mtime = dip->i_di.di_ctime = osi_current_time();
- log_debug("Entries for %"PRIu64" is %u\n", dip->i_di.di_num.no_addr,
- dip->i_di.di_entries);
-
- gfs_dinode_out(&dip->i_di, BH_DATA(dibh));
- write_buf(sdp, dibh, 0);
- relse_buf(sdp, dibh);
-
- return 0;
- }
-
- return -ENOENT;
-}
-
-
-/**
- * dir_l_add -
- * @dip: The GFS inode
- * @filename:
- * @inode:
- * @type:
- *
- * Returns:
- */
-
-static int dir_l_add(struct fsck_inode *dip, osi_filename_t *filename,
- struct gfs_inum *inum, unsigned int type)
-{
- osi_buf_t *dibh;
- struct gfs_dirent *dent;
- int error;
-
- /* Sanity checks */
-
- if(!fs_is_stuffed(dip)){
- log_err("dir_l_add: Attempting linear add on unstuffed dinode.\n");
- return -1;
- }
-
- error = get_and_read_buf(dip->i_sbd, dip->i_num.no_addr, &dibh, 0);
- if (error)
- goto out;
-
-
- if (fs_dirent_alloc(dip, dibh, filename->len, &dent))
- {
- /* no need to write buffer, it hasn't changed. */
- relse_buf(dip->i_sbd, dibh);
-
- error = dir_make_exhash(dip);
- /* DEBUG */
- log_debug("Changing Linear dir to Exhash dir - %s\n",
- (error)? "UNSUCCESSFUL": "SUCCESSFUL");
- if (!error)
- error = dir_e_add(dip, filename, inum, type);
-
- goto out;
- }
-
-
- gfs_inum_out(inum, (char *)&dent->de_inum);
- dent->de_hash = dir_hash(filename);
- dent->de_hash = cpu_to_gfs32(dent->de_hash);
- dent->de_type = cpu_to_gfs16(type);
- memcpy((char *)(dent + 1), filename->name, filename->len);
-
-
- dip->i_di.di_entries++;
- dip->i_di.di_mtime = dip->i_di.di_ctime = osi_current_time();
- log_debug("Entries for %"PRIu64" is %u\n", dip->i_di.di_num.no_addr,
- dip->i_di.di_entries);
- gfs_dinode_out(&dip->i_di, BH_DATA(dibh));
- if(write_buf(dip->i_sbd, dibh, 0)){
- log_err("dir_l_add: bad write_buf()\n");
- error = -EIO;
- }
-
- relse_buf(dip->i_sbd, dibh);
-
- out:
- if(error){
- char tmp_name[256];
- memset(tmp_name, 0, sizeof(tmp_name));
- memcpy(tmp_name, filename->name, filename->len);
- log_err("Unable to add \"%s\" to directory #%"PRIu64"\n",
- tmp_name, dip->i_num.no_addr);
- }
- return error;
-}
-
-
-
-/**
- * fs_dir_add - Add new filename into directory
- * @dip: The GFS inode
- * @filename: The new name
- * @inode: The inode number of the entry
- * @type: The type of the entry
- *
- * Returns: 0 on success, error code on failure
- */
-int fs_dir_add(struct fsck_inode *dip, osi_filename_t *filename,
- struct gfs_inum *inum, unsigned int type)
-{
- int error;
-
- if(dip->i_di.di_type != GFS_FILE_DIR){
- log_err("fs_dir_add: parent inode is not a directory.\n");
- return -1;
- }
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH)
- error = dir_e_add(dip, filename, inum, type);
- else
- error = dir_l_add(dip, filename, inum, type);
-
- return error;
-}
-
-
-/**
- * fs_dirent_alloc - Allocate a directory entry
- * @dip: The GFS inode
- * @bh: The buffer
- * @name_len: The length of the name
- * @dent_out: Pointer to list of dirents
- *
- * Returns: 0 on success, error code otherwise
- */
-int fs_dirent_alloc(struct fsck_inode *dip, osi_buf_t *bh,
- int name_len, struct gfs_dirent **dent_out)
-{
- struct fsck_sb *sdp = dip->i_sbd;
- struct gfs_dirent *dent, *new;
- struct gfs_leaf *leaf;
- struct gfs_dinode *dinode;
- unsigned int rec_len = GFS_DIRENT_SIZE(name_len);
- unsigned int entries = 0, offset = 0, x = 0;
- int type;
-
- type = dirent_first(bh, &dent);
-
- if (type == IS_LEAF){
- leaf = (struct gfs_leaf *)BH_DATA(bh);
- entries = gfs16_to_cpu(leaf->lf_entries);
- offset = sizeof(struct gfs_leaf);
- }
- else if (type == IS_DINODE) {
- dinode = (struct gfs_dinode *)BH_DATA(bh);
- entries = gfs32_to_cpu(dinode->di_entries);
- offset = sizeof(struct gfs_dinode);
- } else {
- log_err("fs_dirent_alloc: Buffer has bad metatype.\n");
- return -1;
- }
-
- if (!entries){
- dent->de_rec_len = BH_SIZE(bh) - offset;
- dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len);
- dent->de_name_len = cpu_to_gfs16(name_len);
-
- *dent_out = dent;
- write_buf(sdp, bh, 0);
- goto success;
- }
-
-
- do{
- uint32 cur_rec_len, cur_name_len;
-
- cur_rec_len = gfs16_to_cpu(dent->de_rec_len);
- cur_name_len = gfs16_to_cpu(dent->de_name_len);
-
- if ((!dent->de_inum.no_formal_ino && cur_rec_len >= rec_len) ||
- (cur_rec_len >= GFS_DIRENT_SIZE(cur_name_len) + rec_len)){
- if (dent->de_inum.no_formal_ino){
- new = (struct gfs_dirent *)((char *)dent + GFS_DIRENT_SIZE(cur_name_len));
- memset(new, 0, sizeof(struct gfs_dirent));
-
- new->de_rec_len = cpu_to_gfs16(cur_rec_len - GFS_DIRENT_SIZE(cur_name_len));
- new->de_name_len = cpu_to_gfs16(name_len);
-
- dent->de_rec_len = cur_rec_len - gfs16_to_cpu(new->de_rec_len);
- dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len);
-
- *dent_out = new;
- write_buf(sdp, bh, 0);
- goto success;
- }
-
- dent->de_name_len = cpu_to_gfs16(name_len);
-
- *dent_out = dent;
- write_buf(sdp, bh, 0);
- goto success;
- }
-
- if(x >= entries){
- log_err("fs_dirent_alloc: dirents contain bad length information.\n");
- return -1;
- }
-
- if (dent->de_inum.no_formal_ino)
- x++;
- }
- while(dirent_next(bh, &dent) == 0);
-
- return -ENOSPC;
-
- success:
- return 0;
-}
-
-
-/**
- * get_leaf_nr - Get a leaf number associated with the lindex
- * @dip: The GFS inode
- * @lindex:
- * @leaf_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int get_leaf_nr(struct fsck_inode *dip, uint32 lindex, uint64 *leaf_out)
-{
- uint64 leaf_no;
- int error = -1;
- error = readi(dip, (char *)&leaf_no,
- lindex * sizeof(uint64), sizeof(uint64));
- if (error != sizeof(uint64)){
- log_debug("get_leaf_nr: Bad internal read. (rtn = %d)\n",
- error);
- return (error < 0) ? error : -EIO;
- }
-
- *leaf_out = gfs64_to_cpu(leaf_no);
-
- return 0;
-}
-
-
-/**
- * put_leaf_nr - Put a leaf number associated with the lindex
- * @dip: The GFS inode
- * @lindex:
- * @leaf_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int put_leaf_nr(struct fsck_inode *dip, uint32 lindex, uint64 leaf_out)
-{
- uint64 leaf_no;
- int error = -1;
-
- leaf_no = cpu_to_gfs64(leaf_out);
-
- error = writei(dip, (char *)&leaf_no,
- lindex * sizeof(uint64), sizeof(uint64));
- if (error != sizeof(uint64)){
- log_debug("put_leaf_nr: Bad internal write. (rtn = %d)\n",
- error);
- return (error < 0) ? error : -EIO;
- }
-
- return 0;
-}
-
-
-/**
- * fs_filecmp - Compare two filenames
- * @file1: The first filename
- * @file2: The second filename
- * @len_of_file2: The length of the second file
- *
- * This routine compares two filenames and returns TRUE if they are equal.
- *
- * Returns: TRUE (!=0) if the files are the same, otherwise FALSE (0).
- */
-int fs_filecmp(osi_filename_t *file1, char *file2, int len_of_file2)
-{
- if (file1->len != len_of_file2){
- return FALSE;
- }
-
- if (osi_memcmp(file1->name, file2, file1->len)){
- return FALSE;
- }
- return TRUE;
-}
-
-
-/**
- * fs_dir_search - Search a directory
- * @dip: The GFS inode
- * @id
- * @type:
- *
- * This routine searches a directory for a file or another directory
- * given its identifier. The component of the identifier that is
- * not being used to search will be filled in and must be freed by
- * the caller.
- *
- * Returns: 0 if found, -1 on failure, -ENOENT if not found.
- */
-int fs_dir_search(struct fsck_inode *dip, identifier_t *id, unsigned int *type)
-{
- int error;
-
- if(dip->i_di.di_type != GFS_FILE_DIR){
- log_err("An attempt was made to search an inode "
- "that is not a directory.\n");
- return -1;
- }
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH)
- error = dir_e_search(dip, id, type);
- else
- error = dir_l_search(dip, id, type);
-
- return error;
-}
-
-/**
- * dirent_repair - attempt to repair a corrupt directory entry.
- * @bh - The buffer header that contains the bad dirent
- * @de - The directory entry in native format
- * @dent - The directory entry in on-disk format
- * @type - Type of directory (DIR_LINEAR or DIR_EXHASH)
- * @first - TRUE if this is the first dirent in the buffer
- *
- * This function tries to repair a corrupt directory entry. All we
- * know at this point is that the length field is wrong.
- */
-int dirent_repair(struct fsck_inode *ip, osi_buf_t *bh, struct gfs_dirent *de,
- struct gfs_dirent *dent, int type, int first)
-{
- char *bh_end, *p;
- int calc_de_name_len = 0;
-
- /* If this is a sentinel, just fix the length and move on */
- if (first && !de->de_inum.no_formal_ino) { /* Is it a sentinel? */
- if (type == DIR_LINEAR)
- de->de_rec_len = BH_SIZE(bh) -
- sizeof(struct gfs_dinode);
- else
- de->de_rec_len = BH_SIZE(bh) - sizeof(struct gfs_leaf);
- } else {
- bh_end = BH_DATA(bh) + BH_SIZE(bh);
- /* first, figure out a probable name length */
- p = (char *)dent + sizeof(struct gfs_dirent);
- while (*p && /* while there's a non-zero char and */
- p < bh_end) { /* not past end of buffer */
- calc_de_name_len++;
- p++;
- }
- if (!calc_de_name_len)
- return 1;
- /* There can often be noise at the end, so only */
- /* Trust the shorter of the two in case we have too much */
- /* Or rather, only trust ours if it's shorter. */
- if (!de->de_name_len || de->de_name_len > NAME_MAX ||
- calc_de_name_len < de->de_name_len) /* if dent is hosed */
- de->de_name_len = calc_de_name_len; /* use ours */
- de->de_rec_len = GFS_DIRENT_SIZE(de->de_name_len);
- }
- gfs_dirent_out(de, (char *)dent);
- write_buf(ip->i_sbd, bh, 0);
- return 0;
-}
-
-/**
- * dirblk_truncate - truncate a directory block
- */
-void dirblk_truncate(struct fsck_inode *ip, struct gfs_dirent *fixb,
- osi_buf_t *bh)
-{
- char *bh_end;
- struct gfs_dirent de;
- uint16_t old_rec_len;
-
- bh_end = BH_DATA(bh) + BH_SIZE(bh);
- /* truncate the block to save the most dentries. To do this we
- have to patch the previous dent. */
- gfs_dirent_in(&de, (char *)fixb);
- old_rec_len = de.de_rec_len;
- de.de_rec_len = bh_end - (char *)fixb;
- gfs_dirent_out(&de, (char *)fixb);
- write_buf(ip->i_sbd, bh, 0);
-}
diff --git a/gfs/gfs_fsck/fs_dir.h b/gfs/gfs_fsck/fs_dir.h
deleted file mode 100644
index f741723..0000000
--- a/gfs/gfs_fsck/fs_dir.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __FS_DIR_H__
-#define __FS_DIR_H__
-
-#include "osi_user.h"
-#include "fsck_incore.h"
-
-#define ID_FILENAME 0
-#define ID_INUM 1
-typedef struct identifier_s {
- int type;
-
- osi_filename_t *filename;
- struct gfs_inum *inum;
-} identifier_t;
-
-int dirent_del(struct fsck_inode *dip, osi_buf_t *bh,
- struct gfs_dirent *prev, struct gfs_dirent *cur);
-int fsck_inode_is_stuffed(struct fsck_inode *ip);
-int dirent_first(osi_buf_t *bh, struct gfs_dirent **dent);
-int get_leaf_nr(struct fsck_inode *dip, uint32 index, uint64 *leaf_out);
-int put_leaf_nr(struct fsck_inode *dip, uint32 index, uint64 leaf_out);
-int fs_filecmp(osi_filename_t *file1, char *file2, int len_of_file2);
-int fs_dirent_del(struct fsck_inode *dip, osi_buf_t *bh, osi_filename_t *filename);
-int fs_dir_add(struct fsck_inode *dip, osi_filename_t *filename,
- struct gfs_inum *inum, unsigned int type);
-int fs_dirent_alloc(struct fsck_inode *dip, osi_buf_t *bh,
- int name_len, struct gfs_dirent **dent_out);
-
-int fs_dir_search(struct fsck_inode *dip, identifier_t *id, unsigned int *type);
-int dirent_repair(struct fsck_inode *ip, osi_buf_t *bh, struct gfs_dirent *de,
- struct gfs_dirent *dent, int type, int first);
-void dirblk_truncate(struct fsck_inode *ip, struct gfs_dirent *fixb,
- osi_buf_t *bh);
-
-#endif /* __FS_DIR_H__ */
diff --git a/gfs/gfs_fsck/fs_inode.c b/gfs/gfs_fsck/fs_inode.c
deleted file mode 100644
index 61529a3..0000000
--- a/gfs/gfs_fsck/fs_inode.c
+++ /dev/null
@@ -1,602 +0,0 @@
-#include "util.h"
-#include "bio.h"
-#include "fs_bits.h"
-#include "fs_dir.h"
-#include "rgrp.h"
-#include "log.h"
-
-#include "fs_inode.h"
-
-#define ST_CREATE 1
-
-/**
- * fs_get_istruct - Get an inode given its number
- * @sdp: The GFS superblock
- * @inum: The inode number
- * @create: Flag to say if we are allowed to create a new struct fsck_inode
- * @ipp: pointer to put the returned inode in
- *
- * Returns: 0 on success, -1 on error
- */
-static int fs_get_istruct(struct fsck_sb *sdp, struct gfs_inum *inum,
- int create, struct fsck_inode **ipp)
-{
- struct fsck_inode *ip = NULL;
- int error = 0;
-
- if (!create){
- /* we are not currently tracking which inodes we already have */
- error = -1;
- goto out;
- }
-
- if(!(ip = (struct fsck_inode *)malloc(sizeof(struct fsck_inode)))) {
- log_err("Unable to allocate fsck_inode structure\n");
- error = -1;
- goto out;
- }
- if(!memset(ip, 0, sizeof(struct fsck_inode))) {
- log_err("Unable to zero fsck_inode structure\n");
- error = -1;
- goto out;
- }
-
- ip->i_num = *inum;
-
- ip->i_sbd = sdp;
-
- error = fs_copyin_dinode(ip, NULL);
- if (error){
- free(ip);
- ip = NULL;
- goto out;
- }
-
- out:
- *ipp = ip;
-
- return error;
-}
-
-
-/*
- * fs_copyin_dinode - read dinode from disk and store in inode
- * @ip: inode, sdp and inum must be set
- *
- * Returns: 0 on success, -1 on error
- */
-int fs_copyin_dinode(struct fsck_inode *ip, osi_buf_t *dibh)
-{
-/* osi_buf_t *dibh;*/
- int do_relse = 0;
- int error = 0;
-
- if(!dibh) {
- error = get_and_read_buf(ip->i_sbd,
- ip->i_num.no_addr, &dibh, 0);
- if (error) {
- stack;
- goto out;
- }
-
- if(check_meta(dibh, GFS_METATYPE_DI)){
- log_err("Block #%"PRIu64" is not a dinode.\n",
- ip->i_num.no_addr);
- relse_buf(ip->i_sbd, dibh);
- return -1;
- }
- do_relse = 1;
- }
- gfs_dinode_in(&ip->i_di, BH_DATA(dibh));
-
- if(do_relse)
- relse_buf(ip->i_sbd, dibh);
-
-
-
- out:
- return error;
-}
-
-
-/*
- * fs_copyout_dinode - given an inode, copy its dinode data to disk
- * @ip: the inode
- *
- * Returns: 0 on success, -1 on error
- */
-int fs_copyout_dinode(struct fsck_inode *ip){
- osi_buf_t *dibh;
- int error;
-
- error = get_and_read_buf(ip->i_sbd, ip->i_num.no_addr, &dibh, 0);
- if(error){
- log_err( "Unable to get a buffer to write dinode to disk.\n");
- return -1;
- }
-
- gfs_dinode_out(&ip->i_di, BH_DATA(dibh));
-
- if(write_buf(ip->i_sbd, dibh, 0)){
- log_err( "Unable to commit dinode buffer to disk.\n");
- relse_buf(ip->i_sbd, dibh);
- return -1;
- }
-
- relse_buf(ip->i_sbd, dibh);
- return 0;
-}
-
-/**
- * make_dinode - Fill in a new dinode structure
- * @dip: the directory this inode is being created in
- * @inum: the inode number
- * @type: the file type
- * @mode: the file permissions
- * @cred: a credentials structure
- *
- */
-
-static int make_dinode(struct fsck_inode *dip, struct gfs_inum *inum,
- unsigned int type, unsigned int mode, osi_cred_t *cred)
-{
- struct fsck_sb *sdp = dip->i_sbd;
- struct gfs_dinode di;
- osi_buf_t *dibh;
- struct fsck_rgrp *rgd;
- int error;
-
- error = get_and_read_buf(sdp, inum->no_addr, &dibh, 0);
- if (error)
- goto out;
-
- if(check_meta(dibh, 0)){
- log_err("make_dinode: Buffer #%"PRIu64" has no meta header.\n",
- BH_BLKNO(dibh));
- errors_found++;
- if(query(dip->i_sbd, "Add header? (y/n) ")){
- struct gfs_meta_header mh;
- memset(&mh, 0, sizeof(struct gfs_meta_header));
- mh.mh_magic = GFS_MAGIC;
- mh.mh_type = GFS_METATYPE_NONE;
- gfs_meta_header_out(&mh, BH_DATA(dibh));
- log_warn("meta header added.\n");
- errors_corrected++;
- } else {
- log_err("meta header not added. Failing make_dinode.\n");
- relse_buf(sdp, dibh);
- return -1;
- }
- }
-
- ((struct gfs_meta_header *)BH_DATA(dibh))->mh_type =
- cpu_to_gfs32(GFS_METATYPE_DI);
- ((struct gfs_meta_header *)BH_DATA(dibh))->mh_format =
- cpu_to_gfs32(GFS_FORMAT_DI);
-
- memset(BH_DATA(dibh) + sizeof(struct gfs_dinode), 0,
- BH_SIZE(dibh) - sizeof(struct gfs_dinode));
-
- memset(&di, 0, sizeof(struct gfs_dinode));
-
- gfs_meta_header_in(&di.di_header, BH_DATA(dibh));
-
- di.di_num = *inum;
-
- if (dip->i_di.di_mode & 02000)
- {
- di.di_mode = mode | ((type == GFS_FILE_DIR) ? 02000 : 0);
- di.di_gid = dip->i_di.di_gid;
- }
- else
- {
- di.di_mode = mode;
- di.di_gid = osi_cred_to_gid(cred);
- }
-
- di.di_uid = osi_cred_to_uid(cred);
- di.di_nlink = 1;
- di.di_blocks = 1;
- di.di_atime = di.di_mtime = di.di_ctime = osi_current_time();
-
- rgd = fs_blk2rgrpd(sdp, inum->no_addr);
- if(!rgd){
- log_err( "Unable to map block #%"PRIu64" to rgrp\n", inum->no_addr);
- exit(FSCK_ERROR);
- }
-
- di.di_rgrp = rgd->rd_ri.ri_addr;
- di.di_goal_rgrp = di.di_rgrp;
- di.di_goal_dblk = di.di_goal_mblk = inum->no_addr - rgd->rd_ri.ri_data1;
-
- di.di_type = type;
-
- gfs_dinode_out(&di, BH_DATA(dibh));
- if(write_buf(dip->i_sbd, dibh, 0)){
- log_err( "make_dinode: bad write_buf()\n");
- error = -EIO;
- }
-
- relse_buf(dip->i_sbd, dibh);
-
-
- out:
-
- return error;
-}
-
-#if 0
-/**
- * fs_change_nlink - Change nlink count on inode
- * @ip: The GFS inode
- * @diff: The change in the nlink count required
- *
- * Returns: 0 on success, -EXXXX on failure.
- */
-static int fs_change_nlink(struct fsck_inode *ip, int diff)
-{
- osi_buf_t *dibh;
- uint32 nlink;
- int error=0;
-
- nlink = ip->i_di.di_nlink + diff;
-
- if (diff < 0)
- if(nlink >= ip->i_di.di_nlink)
- log_err( "fs_change_nlink: Bad link count detected in dinode.\n");
-
- error = get_and_read_buf(ip->i_sbd, ip->i_num.no_addr, &dibh, 0);
- if (error)
- goto out;
-
- ip->i_di.di_nlink = nlink;
- ip->i_di.di_ctime = osi_current_time();
-
- gfs_dinode_out(&ip->i_di, BH_DATA(dibh));
- write_buf(ip->i_sbd, dibh, 0);
- relse_buf(ip->i_sbd,dibh);
-
- out:
- return error;
-}
-#endif
-/**
- * fs_lookupi - Look up a filename in a directory and return its inode
- * @dip: The directory to search
- * @name: The name of the inode to look for
- * @cred: The caller's credentials
- * @ipp: Used to return the found inode if any
- *
- * Returns: 0 on success, -EXXXX on failure
- */
-static int fs_lookupi(struct fsck_inode *dip, osi_filename_t *name,
- osi_cred_t *cred, struct fsck_inode **ipp)
-{
- struct fsck_sb *sdp = dip->i_sbd;
- int error = 0;
- identifier_t id;
-
- memset(&id, 0, sizeof(identifier_t));
- id.filename = name;
- id.type = ID_FILENAME;
-
- *ipp = NULL;
-
- if (!name->len || name->len > GFS_FNAMESIZE)
- {
- error = -ENAMETOOLONG;
- goto out;
- }
-
- if (fs_filecmp(name, (char *)".", 1))
- {
- *ipp = dip;
- goto out;
- }
-
- error = fs_dir_search(dip, &id, NULL);
- if (error){
- if (error == -ENOENT)
- error = 0;
- goto out;
- }
-
- error = fs_get_istruct(sdp, id.inum, ST_CREATE, ipp);
-
- out:
-
- if(id.inum) free(id.inum);
- return error;
-}
-
-static int fs_createi(struct fsck_inode *dip, osi_filename_t *name,
- unsigned int type, unsigned int mode, osi_cred_t *cred,
- int *new, struct fsck_inode **ipp)
-{
- osi_list_t *tmp=NULL;
- struct fsck_sb *sdp = dip->i_sbd;
- struct gfs_inum inum;
- int error;
- int allocate=0;
- identifier_t id;
-
- memset(&id, 0, sizeof(identifier_t));
-
- if (!name->len || name->len > GFS_FNAMESIZE){
- error = -ENAMETOOLONG;
- goto fail;
- }
-
- restart:
-
- /* Don't create entries in an unlinked directory */
- if (!dip->i_di.di_nlink){
- error = -EPERM;
- goto fail;
- }
-
- id.filename = name;
- id.type = ID_FILENAME;
-
- error = fs_dir_search(dip, &id, NULL);
- if(id.inum) free(id.inum);
- switch (error)
- {
- case -ENOENT:
- break;
-
- case 0:
- if (!new){
- error = -EEXIST;
- goto fail;
- } else {
- error = fs_lookupi(dip, name, cred, ipp);
- if (error)
- goto fail;
-
- if (*ipp){
- *new = FALSE;
- return 0;
- } else
- goto restart;
- }
- break;
-
- default:
- goto fail;
- }
-
- if (dip->i_di.di_entries == (uint32)-1){
- error = -EFBIG;
- goto fail;
- }
- if (type == GFS_FILE_DIR && dip->i_di.di_nlink == (uint32)-1){
- error = -EMLINK;
- goto fail;
- }
-
- retry:
- inum.no_addr = inum.no_formal_ino = 0;
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next){
- uint64 block;
- struct fsck_rgrp *rgd;
-
- rgd = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
- if(fs_rgrp_read(rgd, FALSE))
- return -1;
- if(rgd->rd_rg.rg_freemeta){
- block = fs_blkalloc_internal(rgd, dip->i_num.no_addr,
- GFS_BLKST_FREEMETA,
- GFS_BLKST_USEDMETA, 1);
- log_debug("Got block %"PRIu64"\n", block);
- if(block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- block += rgd->rd_ri.ri_data1;
- log_debug("Got block #%"PRIu64"\n", block);
- inum.no_addr = inum.no_formal_ino = block;
- rgd->rd_rg.rg_freemeta--;
- rgd->rd_rg.rg_useddi++;
-
- if(fs_rgrp_recount(rgd)){
- log_err( "fs_createi: Unable to recount rgrp blocks.\n");
- fs_rgrp_relse(rgd);
- error = -EIO;
- goto fail;
- }
-
- /* write out the rgrp */
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- write_buf(sdp, rgd->rd_bh[0], 0);
- fs_rgrp_relse(rgd);
- break;
- } else {
- if(allocate){
- if(!clump_alloc(rgd, 0)){
- block = fs_blkalloc_internal(rgd, dip->i_num.no_addr,
- GFS_BLKST_FREEMETA,
- GFS_BLKST_USEDMETA, 1);
- log_debug("Got block %"PRIu64"\n",
- block);
- if(block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- block += rgd->rd_ri.ri_data1;
-
- inum.no_addr = inum.no_formal_ino = block;
- rgd->rd_rg.rg_freemeta--;
- rgd->rd_rg.rg_useddi++;
-
- if(fs_rgrp_recount(rgd)){
- log_err( "fs_createi: Unable to recount rgrp blocks.\n");
- fs_rgrp_relse(rgd);
- error = -EIO;
- goto fail;
- }
-
- /* write out the rgrp */
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- write_buf(sdp, rgd->rd_bh[0], 0);
- fs_rgrp_relse(rgd);
- break;
- }
- }
- fs_rgrp_relse(rgd);
- }
- }
-
- if(!inum.no_addr){
- if(allocate){
- log_err( "No space available for new file or directory.\n");
- return -1;
- } else {
- allocate = 1;
- goto retry;
- }
- }
-
- error = fs_dir_add(dip, name, &inum, type);
- if (error)
- goto fail;
-
- error = make_dinode(dip, &inum, type, mode, cred);
- if (error)
- goto fail;
-
-
- error = fs_get_istruct(sdp, &inum, ST_CREATE, ipp);
- if (error)
- goto fail;
-
- if (new)
- *new = TRUE;
-
- return 0;
-
- fail:
- return error;
-}
-
-
-/*
- * fs_mkdir - make a directory
- * @dip - dir inode that is the parent of the new dir
- * @new_dir - name of the new dir
- * @mode - mode of new dir
- * @nip - returned inode ptr to the new directory
- *
- * This function has one main difference from the way a normal mkdir
- * works. It will not return an error if the directory already
- * exists. Instead it will return success and nip will point to the
- * inode that exists with the same name as new_dir.
- *
- * Returns: 0 on success, -1 on failure.
- */
-int fs_mkdir(struct fsck_inode *dip, const char *new_dir, int mode, struct fsck_inode **nip){
- int error;
- osi_cred_t creds;
- osi_buf_t *dibh;
- struct gfs_dinode *di;
- struct gfs_dirent *dent;
- struct fsck_inode *ip= NULL;
- struct fsck_sb *sdp = dip->i_sbd;
- osi_filename_t name;
- int new = 0;
-
- name.name = (unsigned char *)new_dir;
- name.len = strlen(new_dir);
- creds.cr_uid = getuid();
- creds.cr_gid = getgid();
-
- error = fs_createi(dip, &name, GFS_FILE_DIR, mode, &creds, &new, &ip);
-
- if (error)
- goto fail;
-
- if(!new){
- goto out;
- }
-
- if(!ip){
- log_err( "fs_mkdir: fs_createi() failed.\n");
- error = -1;
- goto fail;
- }
-
- ip->i_di.di_nlink = 2;
- ip->i_di.di_size = sdp->sb.sb_bsize - sizeof(struct gfs_dinode);
- ip->i_di.di_flags |= GFS_DIF_JDATA;
- ip->i_di.di_payload_format = GFS_FORMAT_DE;
- ip->i_di.di_entries = 2;
-
- error = get_and_read_buf(ip->i_sbd, ip->i_num.no_addr, &dibh, 0);
- if(error){
- log_err( "fs_mkdir: Unable to aquire directory buffer.\n");
- goto fail;
- }
-
- di = (struct gfs_dinode *)BH_DATA(dibh);
-
- error = fs_dirent_alloc(ip, dibh, 1, &dent);
- if(error){ /* This should never fail */
- log_err( "fs_mkdir: fs_dirent_alloc() failed for \".\" entry.\n");
- goto fail;
- }
-
- dent->de_inum = di->di_num; /* already GFS endian */
- dent->de_hash = gfs_dir_hash(".", 1);
- dent->de_hash = cpu_to_gfs32(dent->de_hash);
- dent->de_type = cpu_to_gfs16(GFS_FILE_DIR);
- memcpy((char *)(dent + 1), ".", 1);
- di->di_entries = cpu_to_gfs32(1);
-
- error = fs_dirent_alloc(ip, dibh, 2, &dent);
- if(error){ /* This should never fail */
- log_err( "fs_mkdir: fs_dirent_alloc() failed for \"..\" entry.\n");
- goto fail;
- }
- gfs_inum_out(&dip->i_num, (char *)&dent->de_inum);
- dent->de_hash = gfs_dir_hash("..", 2);
- dent->de_hash = cpu_to_gfs32(dent->de_hash);
- dent->de_type = cpu_to_gfs16(GFS_FILE_DIR);
- memcpy((char *)(dent + 1), "..", 2);
-
- gfs_dinode_out(&ip->i_di, (char *)di);
- if(write_buf(ip->i_sbd, dibh, 0)){
- log_err( "fs_mkdir: Bad write_buf()\n");
- error = -EIO;
- goto fail;
- }
-
- relse_buf(ip->i_sbd, dibh);
-
-
- /* FIXME: this may break stuff elsewhere, but since I'm
- * keeping track of the linkcount in-core, we shouldn't need
- * to do this...
-
- error = fs_change_nlink(dip, +1);
- if(error){
- log_err( "fs_mkdir: fs_change_nlink() failed.\n");
- goto fail;
- } */
-
- out:
- error=0;
- if(nip) {
- *nip = ip;
- }
- else if(ip) {
- free(ip);
- ip = NULL;
- }
- return 0;
- fail:
- if(ip)
- free(ip);
- return error;
-}
-
-
diff --git a/gfs/gfs_fsck/fs_inode.h b/gfs/gfs_fsck/fs_inode.h
deleted file mode 100644
index d1d2c2b..0000000
--- a/gfs/gfs_fsck/fs_inode.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef __FS_INODE_H__
-#define __FS_INODE_H__
-
-#include "fsck_incore.h"
-
-int fs_copyin_dinode(struct fsck_inode *ip, osi_buf_t *bh);
-int fs_copyout_dinode(struct fsck_inode *ip);
-int fs_mkdir(struct fsck_inode *dip, const char *new_dir, int mode, struct fsck_inode **nip);
-int fs_remove(struct fsck_inode *ip);
-
-static __inline__ int fs_is_stuffed(struct fsck_inode *ip)
-{
- return !ip->i_di.di_height;
-}
-
-static __inline__ int fs_is_jdata(struct fsck_inode *ip)
-{
- return ip->i_di.di_flags & GFS_DIF_JDATA;
-}
-
-
-#endif /* __FS_INODE_H__ */
diff --git a/gfs/gfs_fsck/fs_recovery.c b/gfs/gfs_fsck/fs_recovery.c
deleted file mode 100644
index 76980a2..0000000
--- a/gfs/gfs_fsck/fs_recovery.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include "util.h"
-#include "bio.h"
-
-#include "fs_recovery.h"
-
-/*
- * reconstruct_single_journal - write a fresh journal
- * @sdp: superblock
- * @jnum: journal number
- *
- * This function will write a fresh journal over the top of
- * the previous journal. All journal information is lost. This
- * process is basically stolen from write_journals() in the mkfs code.
- *
- * Returns: -1 on error, 0 otherwise
- */
-static int reconstruct_single_journal(struct fsck_sb *sdp, int jnum){
- struct gfs_log_header lh;
- struct gfs_jindex *jdesc = &(sdp->jindex[jnum]);
- uint32 seg, sequence;
- char buf[sdp->sb.sb_bsize];
-
- srandom(time(NULL));
- sequence = jdesc->ji_nsegment / (RAND_MAX + 1.0) * random();
-
- log_info("Clearing journal %d\n", jnum);
-
- for (seg = 0; seg < jdesc->ji_nsegment; seg++){
- memset(buf, 0, sdp->sb.sb_bsize);
- memset(&lh, 0, sizeof(struct gfs_log_header));
-
- lh.lh_header.mh_magic = GFS_MAGIC;
- lh.lh_header.mh_type = GFS_METATYPE_LH;
- lh.lh_header.mh_format = GFS_FORMAT_LH;
- lh.lh_header.mh_generation = 0x101674;
- lh.lh_flags = GFS_LOG_HEAD_UNMOUNT;
- lh.lh_first = jdesc->ji_addr + seg * sdp->sb.sb_seg_size;
- lh.lh_sequence = sequence;
-
- gfs_log_header_out(&lh, buf);
- gfs_log_header_out(&lh,
- buf + GFS_BASIC_BLOCK - sizeof(struct gfs_log_header));
-
- if(do_lseek(sdp->diskfd, lh.lh_first * sdp->sb.sb_bsize) ||
- do_write(sdp->diskfd, buf, sdp->sb.sb_bsize)){
- log_err("Unable to reconstruct journal %d.\n", jnum);
- return -1;
- }
-
- if (++sequence == jdesc->ji_nsegment)
- sequence = 0;
- }
- return 0;
-}
-
-
-/*
- * reconstruct_journals - write fresh journals
- * sdp: the super block
- *
- * Returns: 0 on success, -1 on failure
- */
-int reconstruct_journals(struct fsck_sb *sdp){
- int i;
-
- log_notice("Clearing journals (this may take a while)");
- for(i=0; i < sdp->journals; i++) {
- if((i % 2) == 0)
- log_at_notice(".");
- if(reconstruct_single_journal(sdp, i))
- return -1;
- }
- log_notice("\nJournals cleared.\n");
- return 0;
-}
diff --git a/gfs/gfs_fsck/fs_recovery.h b/gfs/gfs_fsck/fs_recovery.h
deleted file mode 100644
index 7460310..0000000
--- a/gfs/gfs_fsck/fs_recovery.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __FS_RECOVERY_H__
-#define __FS_RECOVERY_H__
-
-#include "fsck_incore.h"
-
-int reconstruct_journals(struct fsck_sb *sdp);
-
-#endif /* __FS_RECOVERY_H__ */
-
diff --git a/gfs/gfs_fsck/fsck.h b/gfs/gfs_fsck/fsck.h
deleted file mode 100644
index d9d0e57..0000000
--- a/gfs/gfs_fsck/fsck.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef _FSCK_H
-#define _FSCK_H
-
-
-#include "fsck_incore.h"
-#include "log.h"
-
-/*
- * Exit codes used by fsck-type programs
- * Copied from e2fsck's e2fsck.h
- */
-#define FSCK_OK 0 /* No errors */
-#define FSCK_NONDESTRUCT 1 /* File system errors corrected */
-#define FSCK_REBOOT 2 /* System should be rebooted */
-#define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */
-#define FSCK_ERROR 8 /* Operational error */
-#define FSCK_USAGE 16 /* Usage or syntax error */
-#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
-#define FSCK_LIBRARY 128 /* Shared library error */
-
-struct gfs_sb;
-struct fsck_sb;
-
-struct options {
- char *device;
- int yes:1;
- int no:1;
-};
-
-extern uint64_t last_fs_block, last_reported_block;
-extern int skip_this_pass, fsck_abort, fsck_query;
-extern int errors_found, errors_corrected;
-
-int initialize(struct fsck_sb *sbp);
-void destroy(struct fsck_sb *sbp);
-int block_mounters(struct fsck_sb *sbp, int block_em);
-int pass1(struct fsck_sb *sbp);
-int pass1b(struct fsck_sb *sbp);
-int pass1c(struct fsck_sb *sbp);
-int pass2(struct fsck_sb *sbp, struct options *opts);
-int pass3(struct fsck_sb *sbp, struct options *opts);
-int pass4(struct fsck_sb *sbp, struct options *opts);
-int pass5(struct fsck_sb *sbp, struct options *opts);
-
-/* FIXME: Hack to get this going for pass2 - this should be pulled out
- * of pass1 and put somewhere else... */
-int add_to_dir_list(struct fsck_sb *sbp, uint64_t block);
-
-#endif /* _FSCK_H */
diff --git a/gfs/gfs_fsck/fsck_incore.h b/gfs/gfs_fsck/fsck_incore.h
deleted file mode 100644
index 3b46b8a..0000000
--- a/gfs/gfs_fsck/fsck_incore.h
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef _FSCK_INCORE_H
-#define _FSCK_INCORE_H
-
-#include <stdint.h>
-#include "ondisk.h"
-#include "osi_list.h"
-#include "osi_user.h"
-#include "fs_bits.h"
-#include "block_list.h"
-
-#define SBF_RECONSTRUCT_JOURNALS (1)
-
-#define FSCK_HASH_SHIFT (13)
-#define FSCK_HASH_SIZE (1 << FSCK_HASH_SHIFT)
-#define FSCK_HASH_MASK (FSCK_HASH_SIZE - 1)
-
-struct fsck_sb;
-
-struct inode_info
-{
- osi_list_t list;
- uint64_t inode;
- uint32_t link_count; /* the number of links the inode
- * thinks it has */
- uint32_t counted_links; /* the number of links we've found */
-};
-
-struct dir_info
-{
- osi_list_t list;
- uint64_t dinode;
- uint64_t treewalk_parent;
- uint64_t dotdot_parent;
- uint8_t checked:1;
-
-};
-
-/* Use to manage in core bitmaps */
-
-struct bitmap_list
-{
- osi_list_t list;
- char *bm;
- struct fsck_rgrp *rgd;
-};
-
-/*
- * Incore inode structure
- */
-
-struct fsck_inode
-{
- struct fsck_sb *i_sbd; /* GFS superblock pointer */
- struct gfs_inum i_num;
- struct gfs_dinode i_di; /* Dinode Structure */
-};
-
-struct fsck_rgrp
-{
- struct fsck_sb *rd_sbd; /* ptr to in-core super block */
- osi_list_t rd_list; /* Link with superblock */
-
- struct gfs_rindex rd_ri; /* Resource Index structure */
- struct gfs_rgrp rd_rg; /* Resource Group structure */
-
- int32_t rd_open_count; /* # of open references on this rgrpd */
-
- fs_bitmap_t *rd_bits;
- osi_buf_t **rd_bh;
-};
-
-
-
-struct fsck_sb {
- struct gfs_sb sb; /* Super Block */
- int diskfd;
- uint32_t flags;
- char fsname[256];
-
- /* Special inodes */
- struct fsck_inode *lf_dip; /* lost-n-found dir inode */
- struct fsck_inode *jiinode;
- struct fsck_inode *riinode;
- struct fsck_inode *rooti;
-
- /* rgrp stuff */
- osi_list_t rglist; /* List of resource groups */
- unsigned int rgcount; /* Count of resource groups */
-
- /* journal stuff */
- unsigned int journals; /* Number of journals in the FS */
- uint32_t ji_nsegment; /* number of journal segments per journal */
- struct gfs_jindex *jindex; /* Array of Jindex structs for
- * this FS's journals */
- struct gfs_jindex jdesc; /* Jindex struct for this
- * machine's journal */
-
- /* Constants computed on mount */
- uint32_t fsb2bb_shift; /* Shift FS Block numbers to the left by
- this to get buffer cache blocks */
- uint32_t diptrs; /* Number of pointers in a dinode */
- uint32_t inptrs; /* Number of pointers in a indirect block */
- uint32_t jbsize; /* Size of a journaled data block */
- uint32_t hash_bsize; /* sizeof(exhash block) */
- uint32_t hash_ptrs; /* Number of points in a hash block */
- uint32_t max_height; /* Maximum height of a file's metadata tree */
- uint64_t heightsize[GFS_MAX_META_HEIGHT];
- uint32_t max_jheight; /* Max height of a journaled file's metadata tree */
- uint64_t jheightsize[GFS_MAX_META_HEIGHT];
-
- uint64_t last_fs_block;
- uint64_t last_data_block;
- uint64_t first_data_block;
-
- /* dir_list is used to keep track of directory inodes and
- * their parents */
- osi_list_t dir_hash[FSCK_HASH_SIZE];
-
- /* inode_list is used to keep track of the link count of
- * inodes */
- osi_list_t inode_hash[FSCK_HASH_SIZE];
-
- /* contains list of data and metadata blocks and various info
- * about each */
- struct block_list *bl;
-
- osi_list_t dup_list;
-
- /* fsck_opts is used to pass command line params around */
- struct options *opts;
-
-};
-
-
-
-
-#endif /* _FSCK_INCORE_H */
diff --git a/gfs/gfs_fsck/hash.c b/gfs/gfs_fsck/hash.c
deleted file mode 100644
index b151021..0000000
--- a/gfs/gfs_fsck/hash.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* This is the same hash algorithm used by the glocks in gfs */
-
-#include <stdint.h>
-#include <unistd.h>
-#include "fsck_incore.h"
-#include "hash.h"
-#include "osi_list.h"
-
-/**
- * hash_more_internal - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- * @hash: the hash from a previous call
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * This is the 32-bit FNV-1a hash from:
- * http://www.isthe.com/chongo/tech/comp/fnv/
- *
- * Hash guts
- *
- * Returns: the hash
- */
-
-static __inline__ uint32_t
-hash_more_internal(const void *data, unsigned int len, uint32_t hash)
-{
- unsigned char *p = (unsigned char *) data;
- unsigned char *e = p + len;
- uint32_t h = hash;
-
- while (p < e) {
- h ^= (uint32_t) (*p++);
- h *= 0x01000193;
- }
-
- return h;
-}
-
-/**
- * fsck_hash - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * This is the 32-bit FNV-1a hash from:
- * http://www.isthe.com/chongo/tech/comp/fnv/
- *
- * Returns: the hash
- */
-
-uint32_t
-fsck_hash(const void *data, unsigned int len)
-{
- uint32_t h = 0x811C9DC5;
- h = hash_more_internal(data, len, h);
- return h;
-}
-
-/**
- * fsck_hash_more - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- * @hash: the hash from a previous call
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * This is the 32-bit FNV-1a hash from:
- * http://www.isthe.com/chongo/tech/comp/fnv/
- *
- * This version let's you hash together discontinuous regions.
- * For example, to compute the combined hash of the memory in
- * (data1, len1), (data2, len2), and (data3, len3) you:
- *
- * h = fsck_hash(data1, len1);
- * h = fsck_hash_more(data2, len2, h);
- * h = fsck_hash_more(data3, len3, h);
- *
- * Returns: the hash
- */
-
-uint32_t
-fsck_hash_more(const void *data, unsigned int len, uint32_t hash)
-{
- uint32_t h;
- h = hash_more_internal(data, len, hash);
- return h;
-}
-
-
diff --git a/gfs/gfs_fsck/hash.h b/gfs/gfs_fsck/hash.h
deleted file mode 100644
index d5fe8e9..0000000
--- a/gfs/gfs_fsck/hash.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _HASH_H
-#define _HASH_H
-
-uint32_t fsck_hash(const void *data, unsigned int len);
-uint32_t fsck_hash_more(const void *data, unsigned int len, uint32_t hash);
-
-#endif /* _HASH_H */
diff --git a/gfs/gfs_fsck/initialize.c b/gfs/gfs_fsck/initialize.c
deleted file mode 100644
index 34233b5..0000000
--- a/gfs/gfs_fsck/initialize.c
+++ /dev/null
@@ -1,421 +0,0 @@
-#include <stdio.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "fsck_incore.h"
-#include "fsck.h"
-#include "util.h"
-#include "super.h"
-#include "fs_inode.h"
-#include "fs_recovery.h"
-#include "inode.h"
-#include "bio.h"
-
-/**
- * init_journals
- *
- * Go through journals and replay them - then clear them
- */
-static int init_journals(struct fsck_sb *sbp)
-{
-
- if(!sbp->opts->no) {
- /* Next, Replay the journals */
- if(sbp->flags & SBF_RECONSTRUCT_JOURNALS){
- if(reconstruct_journals(sbp)){
- stack;
- return 1;
- }
- } else {
- /* ATTENTION -- Journal replay is not supported */
- if(reconstruct_journals(sbp)){
- stack;
- return 1;
- }
- }
- }
- return 0;
-}
-
-/**
- * block_mounters
- *
- * Change the lock protocol so nobody can mount the fs
- *
- */
-int block_mounters(struct fsck_sb *sbp, int block_em)
-{
- if(block_em) {
- /* verify it starts with lock_ */
- if(!strncmp(sbp->sb.sb_lockproto, "lock_", 5)) {
- /* Change lock_ to fsck_ */
- memcpy(sbp->sb.sb_lockproto, "fsck_", 5);
- }
- /* FIXME: Need to do other verification in the else
- * case */
- } else {
- /* verify it starts with fsck_ */
- /* verify it starts with lock_ */
- if(!strncmp(sbp->sb.sb_lockproto, "fsck_", 5)) {
- /* Change fsck_ to lock_ */
- memcpy(sbp->sb.sb_lockproto, "lock_", 5);
- }
- }
-
- if(write_sb(sbp)) {
- stack;
- return -1;
- }
- return 0;
-}
-
-
-/*
- * empty_super_block - free all structures in the super block
- * sdp: the in-core super block
- *
- * This function frees all allocated structures within the
- * super block. It does not free the super block itself.
- *
- * Returns: Nothing
- */
-static void empty_super_block(struct fsck_sb *sdp)
-{
- uint32_t i;
-
- log_info("Freeing buffers.\n");
- if(sdp->riinode){
- free(sdp->riinode);
- sdp->riinode = NULL;
- }
- if(sdp->jiinode){
- free(sdp->jiinode);
- sdp->jiinode = NULL;
- }
- if(sdp->rooti){
- free(sdp->rooti);
- sdp->rooti = NULL;
- }
-
- if(sdp->jindex){
- free(sdp->jindex);
- sdp->jindex = NULL;
- }
- if(sdp->lf_dip) {
- free(sdp->lf_dip);
- sdp->lf_dip = NULL;
- }
- while(!osi_list_empty(&sdp->rglist)){
- struct fsck_rgrp *rgd;
- unsigned int x;
- rgd = osi_list_entry(sdp->rglist.next,
- struct fsck_rgrp, rd_list);
- osi_list_del(&rgd->rd_list);
- if(rgd->rd_bits)
- free(rgd->rd_bits);
- if(rgd->rd_bh) {
- for(x = 0; x < rgd->rd_ri.ri_length; x++) {
- if(rgd->rd_bh[x]) {
- if(BH_DATA(rgd->rd_bh[x])) {
- free(BH_DATA(rgd->rd_bh[x]));
- }
- free(rgd->rd_bh[x]);
- }
- }
- free(rgd->rd_bh);
- }
- free(rgd);
- }
-
- for(i = 0; i < FSCK_HASH_SIZE; i++) {
- while(!osi_list_empty(&sdp->inode_hash[i])) {
- struct inode_info *ii;
- ii = osi_list_entry(sdp->inode_hash[i].next,
- struct inode_info, list);
- osi_list_del(&ii->list);
- free(ii);
- }
- while(!osi_list_empty(&sdp->dir_hash[i])) {
- struct dir_info *di;
- di = osi_list_entry(sdp->dir_hash[i].next,
- struct dir_info, list);
- osi_list_del(&di->list);
- free(di);
- }
- }
-
- block_list_destroy(sdp->bl);
-}
-
-
-/**
- * set_block_ranges
- * @sdp: superblock
- *
- * Uses info in rgrps and jindex to determine boundaries of the
- * file system.
- *
- * Returns: 0 on success, -1 on failure
- */
-static int set_block_ranges(struct fsck_sb *sdp)
-{
- struct gfs_jindex *jdesc;
- struct fsck_rgrp *rgd;
- struct gfs_rindex *ri;
- osi_list_t *tmp;
- char buf[sdp->sb.sb_bsize];
- uint64 rmax = 0;
- uint64 jmax = 0;
- uint64 rmin = 0;
- uint64 i;
- int error;
-
- log_info("Setting block ranges...\n");
-
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next)
- {
- rgd = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
- ri = &rgd->rd_ri;
- if (ri->ri_data1 + ri->ri_data - 1 > rmax)
- rmax = ri->ri_data1 + ri->ri_data - 1;
- if (!rmin || ri->ri_data1 < rmin)
- rmin = ri->ri_data1;
- }
-
- last_fs_block = rmax;
-
- for (i = 0; i < sdp->journals; i++)
- {
- jdesc = &sdp->jindex[i];
-
- if ((jdesc->ji_addr+jdesc->ji_nsegment*sdp->sb.sb_seg_size-1)
- > jmax)
- jmax = jdesc->ji_addr + jdesc->ji_nsegment
- * sdp->sb.sb_seg_size - 1;
- }
-
- sdp->last_fs_block = (jmax > rmax) ? jmax : rmax;
- if (sdp->last_fs_block > 0xffffffff && sizeof(unsigned long) <= 4) {
- log_crit("This file system is too big for this computer to handle.\n");
- log_crit("Last fs block = 0x%llx, but sizeof(unsigned long) is %d bytes.\n",
- sdp->last_fs_block, sizeof(unsigned long));
- goto fail;
- }
-
- sdp->last_data_block = rmax;
- sdp->first_data_block = rmin;
-
- if(do_lseek(sdp->diskfd, (sdp->last_fs_block * sdp->sb.sb_bsize))){
- log_crit("Can't seek to last block in file system: %"
- PRIu64"\n", sdp->last_fs_block);
- goto fail;
- }
-
- memset(buf, 0, sdp->sb.sb_bsize);
- error = read(sdp->diskfd, buf, sdp->sb.sb_bsize);
- if (error != sdp->sb.sb_bsize){
- log_crit("Can't read last block in file system (%u), "
- "last_fs_block: %"PRIu64"\n",
- error, sdp->last_fs_block);
- goto fail;
- }
-
- return 0;
-
- fail:
- return -1;
-}
-
-
-/**
- * read_super_block
- * @sdp:
- *
- * Returns: 0 on success, -1 on failure
- */
-static int read_super_block(struct fsck_sb *sdp)
-{
- uint32_t i;
-
- sync();
-
- /********************************************************************
- ***************** First, initialize all lists **********************
- ********************************************************************/
- log_info("Initializing lists...\n");
- osi_list_init(&sdp->rglist);
- for(i = 0; i < FSCK_HASH_SIZE; i++) {
- osi_list_init(&sdp->dir_hash[i]);
- osi_list_init(&sdp->inode_hash[i]);
- }
-
- /********************************************************************
- ************ next, read in on-disk SB and set constants **********
- ********************************************************************/
- sdp->sb.sb_bsize = 512;
- if (sdp->sb.sb_bsize < GFS_BASIC_BLOCK)
- sdp->sb.sb_bsize = GFS_BASIC_BLOCK;
-
- if(sizeof(struct gfs_sb) > sdp->sb.sb_bsize){
- log_crit("GFS superblock is larger than the blocksize!\n");
- log_debug("sizeof(struct gfs_sb) > sdp->sb.sb_bsize\n");
- return -1;
- }
-
- if(read_sb(sdp) < 0){
- return -1;
- }
-
- return 0;
-}
-
-/**
- * fill_super_block
- * @sdp:
- *
- * Returns: 0 on success, -1 on failure
- */
-static int fill_super_block(struct fsck_sb *sdp)
-{
- struct fsck_inode *ip = NULL;
- /*******************************************************************
- ****************** Initialize important inodes ******************
- *******************************************************************/
-
- log_info("Initializing special inodes...\n");
- /* get ri inode */
- if(load_inode(sdp, sdp->sb.sb_rindex_di.no_addr, &ip)) {
- stack;
- return -1;
- }
- sdp->riinode = ip;
-
- /* get ji inode */
- if(load_inode(sdp, sdp->sb.sb_jindex_di.no_addr, &ip)) {
- stack;
- return -1;
- }
- sdp->jiinode = ip;
-
- /* get root dinode */
- if(!load_inode(sdp, sdp->sb.sb_root_di.no_addr, &ip)) {
- if(!check_inode(ip)) {
- sdp->rooti = ip;
- }
- else {
- free(ip);
- }
- } else {
- log_warn("Unable to load root inode\n");
- }
-
- /*******************************************************************
- ******* Fill in rgrp and journal indexes and related fields *****
- *******************************************************************/
-
- /* read in the ji data */
- if (ji_update(sdp)){
- log_err("Unable to read in ji inode.\n");
- return -1;
- }
-
- if(ri_update(sdp)){
- log_err("Unable to fill in resource group information.\n");
- goto fail;
- }
-
- /*******************************************************************
- ******* Now, set boundary fields in the super block *************
- *******************************************************************/
- if(set_block_ranges(sdp)){
- log_err("Unable to determine the boundaries of the"
- " file system.\n");
- goto fail;
- }
-
- sdp->bl = block_list_create(sdp->last_fs_block+1, gbmap);
- if (!sdp->bl)
- goto fail;
-
- return 0;
-
- fail:
- empty_super_block(sdp);
-
- return -1;
-}
-
-/**
- * initialize - initialize superblock pointer
- *
- */
-int initialize(struct fsck_sb *sbp)
-{
- if(sbp->opts->no) {
- if ((sbp->diskfd = open(sbp->opts->device, O_RDONLY)) < 0) {
- log_crit("Unable to open device: %s\n", sbp->opts->device);
- return FSCK_USAGE;
- }
- } else {
- /* read in sb from disk */
- if ((sbp->diskfd = open(sbp->opts->device, O_RDWR)) < 0){
- log_crit("Unable to open device: %s\n", sbp->opts->device);
- return FSCK_USAGE;
- }
- }
-
- /* initialize lists and read in the sb */
- if(read_super_block(sbp)) {
- stack;
- return FSCK_ERROR;
- }
-
- /* Change lock protocol to be fsck_* instead of lock_* */
- if(!sbp->opts->no) {
- if(block_mounters(sbp, 1)) {
- log_err("Unable to block other mounters\n");
- return FSCK_ERROR;
- }
- }
-
- /* initialize important inodes, fill the rgrp and journal indexes, etc */
- if(fill_super_block(sbp)) {
- if(!sbp->opts->no)
- block_mounters(sbp, 0);
- stack;
- return FSCK_ERROR;
- }
-
- /* verify various things */
-
- if(init_journals(sbp)) {
- if(!sbp->opts->no)
- block_mounters(sbp, 0);
- stack;
- return FSCK_ERROR;
- }
-
- return FSCK_OK;
-}
-
-static void destroy_sbp(struct fsck_sb *sbp)
-{
- if(!sbp->opts->no) {
- if(block_mounters(sbp, 0)) {
- log_warn("Unable to unblock other mounters - manual intevention required\n");
- log_warn("Use 'gfs_tool sb <device> proto' to fix\n");
- }
- log_info("Syncing the device.\n");
- fsync(sbp->diskfd);
- }
- empty_super_block(sbp);
- close(sbp->diskfd);
-}
-
-void destroy(struct fsck_sb *sbp)
-{
- destroy_sbp(sbp);
-
-}
diff --git a/gfs/gfs_fsck/inode.c b/gfs/gfs_fsck/inode.c
deleted file mode 100644
index b900429..0000000
--- a/gfs/gfs_fsck/inode.c
+++ /dev/null
@@ -1,335 +0,0 @@
-#include "fsck_incore.h"
-#include "fsck.h"
-#include "osi_user.h"
-#include "bio.h"
-#include "fs_inode.h"
-#include "inode.h"
-#include "rgrp.h"
-#include "util.h"
-#include "fs_dir.h"
-
-/* FIXME: Not crazy about this name vs. load_inode, but I'm not very
- * creative ATM */
-/* replaces fs_copyin_dinode */
-int copyin_inode(struct fsck_sb *sbp, osi_buf_t *bh, struct fsck_inode **inode)
-{
- struct fsck_inode *ip;
-
- if(!(ip = (struct fsck_inode *)malloc(sizeof(struct fsck_inode)))) {
- log_err("Unable to allocate memory for inode\n");
- return -1;
- }
- if(!memset(ip, 0, sizeof(struct fsck_inode))) {
- log_err("Unable to zero inode memory\n");
- return -1;
- }
- ip->i_sbd = sbp;
-
- ip->i_num.no_addr = ip->i_num.no_formal_ino = BH_BLKNO(bh);
- memset(&ip->i_di, 0, sizeof(struct gfs_dinode));
-
- gfs_dinode_in(&ip->i_di, BH_DATA(bh));
-
- *inode = ip;
-
- return 0;
-}
-
-int load_inode(struct fsck_sb *sbp, uint64_t block, struct fsck_inode **inode)
-{
- osi_buf_t *bh;
-
- if(get_and_read_buf(sbp, block, &bh, 0)){
- stack;
- log_err("Unable to retrieve block %"PRIu64"\n",
- block);
- return -1;
- }
-
- if(copyin_inode(sbp, bh, inode)) {
- stack;
- relse_buf(sbp, bh);
- return -1;
- }
-
- relse_buf(sbp, bh);
- return 0;
-}
-
-
-void free_inode(struct fsck_inode **inode)
-{
- free(*inode);
- inode = NULL;
-}
-
-
-int check_inode(struct fsck_inode *ip)
-{
- int error = 0;
- if(ip->i_di.di_header.mh_type != GFS_METATYPE_DI) {
- return -1;
- }
-
- if(ip->i_num.no_formal_ino != ip->i_di.di_num.no_formal_ino){
- log_err(
- "In-core and on-disk formal inode"
- "numbers do not match. %"PRIu64" %"PRIu64"\n",
- ip->i_num.no_formal_ino,
- ip->i_di.di_num.no_formal_ino);
- error = -1;
- }
-
- /* Handle a moved inode */
-
- if (ip->i_num.no_addr != ip->i_di.di_num.no_addr){
- log_err("\tBlock # used to read disk inode: %"PRIu64"\n"
- "\tBlock # recorded in disk inode : %"PRIu64"\n",
- ip->i_num.no_addr, ip->i_di.di_num.no_addr);
- error = -1;
- }
-
- return error;
-
-}
-
-
-
-/*int remove_inode(struct fsck_sb *sbp, uint64_t block)
-{
- struct fsck_inode *ip;
- load_inode(sbp, block, &ip);
- check_metatree(ip, &fxns);
- free_inode(&ip);
- return 0;
-}*/
-
-/**
- * fs_get_istruct - Get an inode given its number
- * @sdp: The GFS superblock
- * @inum: The inode number
- * @create: Flag to say if we are allowed to create a new struct fsck_inode
- * @ipp: pointer to put the returned inode in
- *
- * Returns: 0 on success, -1 on error
- */
-static int fs_get_istruct(struct fsck_sb *sdp, struct gfs_inum *inum,
- int create, struct fsck_inode **ipp)
-{
- struct fsck_inode *ip = NULL;
- int error = 0;
-
- if (!create){
- /* we are not currently tracking which inodes we already have */
- error = -1;
- goto out;
- }
-
- if(!(ip = (struct fsck_inode *)malloc(sizeof(struct fsck_inode)))) {
- log_err("Unable to allocate memory for inode\n");
- error = -1;
- goto out;
- }
- ip->i_num = *inum;
-
- ip->i_sbd = sdp;
-
- error = fs_copyin_dinode(ip, NULL);
- if (error){
- free(ip);
- ip = NULL;
- goto out;
- }
-
- out:
- *ipp = ip;
-
- return error;
-}
-
-
-
-/**
- * make_dinode - Fill in a new dinode structure
- * @dip: the directory this inode is being created in
- * @inum: the inode number
- * @type: the file type
- * @mode: the file permissions
- * @cred: a credentials structure
- *
- */
-
-static int make_dinode(struct fsck_inode *dip, struct fsck_sb *sdp,
- struct gfs_inum *inum,
- unsigned int type, unsigned int mode, osi_cred_t *cred)
-{
- struct gfs_dinode di;
- osi_buf_t *dibh;
- struct fsck_rgrp *rgd;
- int error;
-
- error = get_and_read_buf(sdp, inum->no_addr, &dibh, 0);
- if (error)
- goto out;
-
- if(check_meta(dibh, 0)){
- struct gfs_meta_header mh;
- log_debug("Buffer #%"PRIu64" has no meta header.\n",
- BH_BLKNO(dibh));
- memset(&mh, 0, sizeof(struct gfs_meta_header));
- mh.mh_magic = GFS_MAGIC;
- mh.mh_type = GFS_METATYPE_NONE;
- gfs_meta_header_out(&mh, BH_DATA(dibh));
- log_debug("meta header added.\n");
- }
-
- ((struct gfs_meta_header *)BH_DATA(dibh))->mh_type =
- cpu_to_gfs32(GFS_METATYPE_DI);
- ((struct gfs_meta_header *)BH_DATA(dibh))->mh_format =
- cpu_to_gfs32(GFS_FORMAT_DI);
-
- memset(BH_DATA(dibh) + sizeof(struct gfs_dinode), 0,
- BH_SIZE(dibh) - sizeof(struct gfs_dinode));
-
- memset(&di, 0, sizeof(struct gfs_dinode));
-
- gfs_meta_header_in(&di.di_header, BH_DATA(dibh));
-
- di.di_num = *inum;
-
- if (dip && (dip->i_di.di_mode & 02000))
- {
- di.di_mode = mode | ((type == GFS_FILE_DIR) ? 02000 : 0);
- di.di_gid = dip->i_di.di_gid;
- }
- else
- {
- di.di_mode = mode;
- di.di_gid = osi_cred_to_gid(cred);
- }
-
- di.di_uid = osi_cred_to_uid(cred);
- di.di_nlink = 1;
- di.di_blocks = 1;
- di.di_atime = di.di_mtime = di.di_ctime = osi_current_time();
-
- rgd = fs_blk2rgrpd(sdp, inum->no_addr);
- if(!rgd){
- log_crit("Unable to map block #%"PRIu64" to rgrp\n", inum->no_addr);
- exit(FSCK_ERROR);
- }
-
- di.di_rgrp = rgd->rd_ri.ri_addr;
- di.di_goal_rgrp = di.di_rgrp;
- di.di_goal_dblk = di.di_goal_mblk = inum->no_addr - rgd->rd_ri.ri_data1;
-
- di.di_type = type;
-
- gfs_dinode_out(&di, BH_DATA(dibh));
- if(write_buf(sdp, dibh, 0)){
- log_err("make_dinode: bad write_buf()\n");
- error = -EIO;
- }
-
- relse_buf(sdp, dibh);
-
-
- out:
-
- return error;
-}
-
-
-int create_inode(struct fsck_sb *sbp, unsigned int type, struct fsck_inode **ip)
-{
- uint64_t block;
- struct fsck_rgrp *rgd;
- osi_list_t *tmp;
- struct gfs_inum inum;
- int allocate=0;
- unsigned int mode = 0755;
- osi_cred_t cred;
- cred.cr_uid = getuid();
- cred.cr_gid = getgid();
- retry:
- inum.no_addr = inum.no_formal_ino = 0;
- /* Search for a resource group that has free space */
- osi_list_foreach(tmp, &sbp->rglist) {
- /* Create a new inode in that rgd */
- rgd = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
- if(fs_rgrp_read(rgd, FALSE)) {
- stack;
- return -1;
- }
- if(rgd->rd_rg.rg_freemeta){
- block = fs_blkalloc_internal(rgd, 0,
- GFS_BLKST_FREEMETA, GFS_BLKST_USEDMETA, 1);
- log_debug("Got block %"PRIu64"\n", block);
- if(block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- block += rgd->rd_ri.ri_data1;
-
- inum.no_addr = inum.no_formal_ino = block;
- /* FIXME: type isn't right */
- block_set(sbp->bl, block, type);
- /* write out the rgrp */
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- write_buf(sbp, rgd->rd_bh[0], 0);
- fs_rgrp_relse(rgd);
- break;
- }
- else {
- if(allocate && !clump_alloc(rgd, 0)){
- block = fs_blkalloc_internal(rgd, 0,
- GFS_BLKST_FREEMETA,
- GFS_BLKST_USEDMETA, 1);
- log_debug("Got block %"PRIu64"\n", block);
-
- if(block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- block += rgd->rd_ri.ri_data1;
-
- inum.no_addr = inum.no_formal_ino = block;
-
- /* FIXME: type isn't right */
- block_set(sbp->bl, block, type);
-
- /* write out the rgrp */
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- write_buf(sbp, rgd->rd_bh[0], 0);
- fs_rgrp_relse(rgd);
- break;
- }
- fs_rgrp_relse(rgd);
- }
- }
-
- if(!inum.no_addr){
- if(allocate){
- log_err("No space available for new file or directory.\n");
- return -1;
- } else {
- allocate = 1;
- goto retry;
- }
- }
-
- /* We need to setup the inode without attaching it to a directory */
- if(make_dinode(NULL, sbp, &inum, type, mode, &cred)) {
- stack;
- return -1;
- }
- if(fs_get_istruct(sbp, &inum, 1, ip)) {
- stack;
- return -1;
- }
-
- return 0;
-
-
-}
-
diff --git a/gfs/gfs_fsck/inode.h b/gfs/gfs_fsck/inode.h
deleted file mode 100644
index 3670c05..0000000
--- a/gfs/gfs_fsck/inode.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _INODE_H
-#define _INODE_H
-
-
-int copyin_inode(struct fsck_sb *sbp, osi_buf_t *bh, struct fsck_inode **ip);
-int load_inode(struct fsck_sb *sbp, uint64_t block, struct fsck_inode **ip);
-void free_inode(struct fsck_inode **inode);
-int check_inode(struct fsck_inode *ip);
-int create_inode(struct fsck_sb *sbp, unsigned int type,
- struct fsck_inode **ip);
-
-
-#endif /* _INODE_H */
diff --git a/gfs/gfs_fsck/inode_hash.c b/gfs/gfs_fsck/inode_hash.c
deleted file mode 100644
index 8173dcc..0000000
--- a/gfs/gfs_fsck/inode_hash.c
+++ /dev/null
@@ -1,74 +0,0 @@
-#include <stdint.h>
-#include "osi_list.h"
-#include "fsck_incore.h"
-#include "hash.h"
-#include "inode_hash.h"
-
-static uint32_t inode_hash(uint64_t block_no)
-{
- unsigned int h;
-
- h = fsck_hash(&block_no, sizeof (uint64_t));
- h &= FSCK_HASH_MASK;
-
- return h;
-}
-
-struct inode_info *inode_hash_search(osi_list_t *buckets, uint64_t key)
-{
- struct inode_info *ii;
- osi_list_t *tmp;
- osi_list_t *bucket = &buckets[inode_hash(key)];
-
- osi_list_foreach(tmp, bucket) {
- ii = osi_list_entry(tmp, struct inode_info, list);
- if(ii->inode == key) {
- return ii;
- }
- }
- return NULL;
-}
-
-int inode_hash_insert(osi_list_t *buckets, uint64_t key, struct inode_info *ii)
-{
- osi_list_t *tmp;
- osi_list_t *bucket = &buckets[inode_hash(key)];
- struct inode_info *itmp = NULL;
-
- if(osi_list_empty(bucket)) {
- osi_list_add(&ii->list, bucket);
- return 0;
- }
-
- osi_list_foreach(tmp, bucket) {
- itmp = osi_list_entry(tmp, struct inode_info, list);
- if(itmp->inode < key) {
- continue;
- } else {
- osi_list_add_prev(&ii->list, tmp);
- return 0;
- }
- }
- osi_list_add_prev(&ii->list, bucket);
- return 0;
-}
-
-
-int inode_hash_remove(osi_list_t *buckets, uint64_t key)
-{
- osi_list_t *tmp;
- osi_list_t *bucket = &buckets[inode_hash(key)];
- struct inode_info *itmp = NULL;
-
- if(osi_list_empty(bucket)) {
- return -1;
- }
- osi_list_foreach(tmp, bucket) {
- itmp = osi_list_entry(tmp, struct inode_info, list);
- if(itmp->inode == key) {
- osi_list_del(tmp);
- return 0;
- }
- }
- return -1;
-}
diff --git a/gfs/gfs_fsck/inode_hash.h b/gfs/gfs_fsck/inode_hash.h
deleted file mode 100644
index bd463c7..0000000
--- a/gfs/gfs_fsck/inode_hash.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _INODE_HASH_H
-#define _INODE_HASH_H
-
-struct inode_info *inode_hash_search(osi_list_t *buckets, uint64_t block_no);
-int inode_hash_insert(osi_list_t *buckets, uint64_t key, struct inode_info *ii);int inode_hash_remove(osi_list_t *buckets, uint64_t key);
-
-#endif /* _INODE_HASH_H */
diff --git a/gfs/gfs_fsck/link.c b/gfs/gfs_fsck/link.c
deleted file mode 100644
index d303937..0000000
--- a/gfs/gfs_fsck/link.c
+++ /dev/null
@@ -1,94 +0,0 @@
-#include <stdint.h>
-#include "fsck_incore.h"
-#include "inode_hash.h"
-#include "link.h"
-
-int set_link_count(struct fsck_sb *sbp, uint64_t inode_no, uint32_t count)
-{
- struct inode_info *ii = NULL;
- log_debug("Setting link count to %u for %"PRIu64"\n", count, inode_no);
- /* If the list has entries, look for one that matches
- * inode_no */
- ii = inode_hash_search(sbp->inode_hash, inode_no);
- if(ii) {
- if(ii->link_count) {
- log_err("Link count already set for inode #%"
- PRIu64"!\n");
- stack;
- return -1;
- }
- else {
- ii->link_count = count;
- }
- }
- else {
- /* If not match was found, add a new entry and set it's
- * link count to count*/
- if(!(ii = (struct inode_info *) malloc(sizeof(*ii)))) {
- log_err("Unable to allocate inode_info structure\n");
- stack;
- return -1;
- }
- memset(ii, 0, sizeof(*ii));
- ii->inode = inode_no;
- ii->link_count = count;
- inode_hash_insert(sbp->inode_hash, inode_no, ii);
- }
- return 0;
-
-
-}
-
-int increment_link(struct fsck_sb *sbp, uint64_t inode_no)
-{
- struct inode_info *ii = NULL;
-
- ii = inode_hash_search(sbp->inode_hash, inode_no);
- /* If the list has entries, look for one that matches
- * inode_no */
- if(ii) {
- ii->counted_links++;
- log_debug("Incremented counted links to %u for %"PRIu64"\n",
- ii->counted_links, inode_no);
- return 0;
- }
- log_debug("No match found when incrementing link for %"PRIu64"!\n",
- inode_no);
- /* If no match was found, add a new entry and set its
- * counted links to 1 */
- if(!(ii = (struct inode_info *) malloc(sizeof(*ii)))) {
- log_err("Unable to allocate inode_info structure\n");
- stack;
- return -1;
- }
- if(!memset(ii, 0, sizeof(*ii))) {
- log_err("Unable to zero inode_info structure\n");
- stack;
- return -1;
- }
- ii->inode = inode_no;
- ii->counted_links = 1;
- inode_hash_insert(sbp->inode_hash, inode_no, ii);
-
- return 0;
-}
-
-int decrement_link(struct fsck_sb *sbp, uint64_t inode_no)
-{
- struct inode_info *ii = NULL;
-
- ii = inode_hash_search(sbp->inode_hash, inode_no);
- /* If the list has entries, look for one that matches
- * inode_no */
- log_err("Decrementing %"PRIu64"\n", inode_no);
- if(ii) {
- ii->counted_links--;
- return 0;
- }
- log_debug("No match found when decrementing link for %"PRIu64"!\n",
- inode_no);
- return -1;
-
-}
-
-
diff --git a/gfs/gfs_fsck/link.h b/gfs/gfs_fsck/link.h
deleted file mode 100644
index 460bc26..0000000
--- a/gfs/gfs_fsck/link.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _LINK_H
-#define _LINK_H
-
-int set_link_count(struct fsck_sb *sbp, uint64_t inode_no, uint32_t count);
-int increment_link(struct fsck_sb *sbp, uint64_t inode_no);
-int decrement_link(struct fsck_sb *sbp, uint64_t inode_no);
-
-#endif /* _LINK_H */
diff --git a/gfs/gfs_fsck/log.c b/gfs/gfs_fsck/log.c
deleted file mode 100644
index 2d6476c..0000000
--- a/gfs/gfs_fsck/log.c
+++ /dev/null
@@ -1,148 +0,0 @@
-#include <stdio.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <libintl.h>
-
-#include <sys/select.h>
-#include <unistd.h>
-
-#include "fsck_incore.h"
-#include "log.h"
-
-#define _(String) gettext(String)
-
-struct log_state {
- int print_level;
-};
-static struct log_state _state = {MSG_NOTICE};
-
-void increase_verbosity(void)
-{
- _state.print_level++;
-}
-
-void decrease_verbosity(void)
-{
- _state.print_level--;
-}
-
-static void __attribute__((format(printf, 4, 0)))
-print_msg(int priority, const char *file, int line, const char *format, va_list args) {
-
- switch (priority) {
-
- case MSG_DEBUG:
- printf("(%s:%d)\t", file, line);
- vprintf(format, args);
- fflush(stdout);
- break;
- case MSG_INFO:
- case MSG_NOTICE:
- case MSG_WARN:
- vprintf(format, args);
- fflush(stdout);
- break;
- case MSG_ERROR:
- case MSG_CRITICAL:
- default:
- vfprintf(stderr, format, args);
- break;
- }
- return;
-}
-
-
-void __attribute__((format(printf, 5, 6)))
-print_fsck_log(int iif, int priority, const char *file, int line, const char *format, ...)
-{
-
- va_list args;
- const char *transform;
-
- va_start(args, format);
-
- transform = _(format);
-
- if((_state.print_level == priority) ||
- (!iif && (_state.print_level >= priority)))
- print_msg(priority, file, line, transform, args);
-
- va_end(args);
-}
-
-
-
-int __attribute__((format(printf, 2, 3)))
-query(struct fsck_sb *sbp, const char *format, ...)
-{
-
- va_list args;
- const char *transform;
- char response;
- fd_set rfds;
- struct timeval tv;
- int err = 0;
- int ret = 0;
-
- if(sbp->opts->yes)
- return 1;
- if(sbp->opts->no)
- return 0;
-
- fsck_query = TRUE;
- /* Watch stdin (fd 0) to see when it has input. */
- FD_ZERO(&rfds);
- FD_SET(STDIN_FILENO, &rfds);
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- /* Make sure there isn't extraneous input before asking the
- * user the question */
- while((err = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv))) {
- if(err < 0) {
- log_debug("Error in select() on stdin\n");
- break;
- }
- err = read(STDIN_FILENO, &response, sizeof(char));
-
- }
- query:
- va_start(args, format);
-
- transform = _(format);
-
- vprintf(transform, args);
-
- /* Make sure query is printed out */
- fflush(NULL);
-
- rescan:
- err = read(STDIN_FILENO, &response, sizeof(char));
-
- if(tolower(response) == 'y') {
- ret = 1;
- } else if (tolower(response) == 'n') {
- ret = 0;
- } else if ((response == ' ') || (response == '\t')) {
- goto rescan;
- } else {
- while(response != '\n')
- err = read(STDIN_FILENO, &response, sizeof(char));
- printf("Bad response, please type 'y' or 'n'.\n");
- va_end(args);
- goto query;
- }
-
- /* Clip the input */
- while((err = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv))) {
- if(err < 0) {
- log_debug("Error in select() on stdin\n");
- break;
- }
- err = read(STDIN_FILENO, &response, sizeof(char));
- }
-
- va_end(args);
- fsck_query = FALSE;
- return ret;
-}
diff --git a/gfs/gfs_fsck/log.h b/gfs/gfs_fsck/log.h
deleted file mode 100644
index 725d2ee..0000000
--- a/gfs/gfs_fsck/log.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef __LOG_H
-#define __LOG_H
-
-#define MSG_DEBUG 7
-#define MSG_INFO 6
-#define MSG_NOTICE 5
-#define MSG_WARN 4
-#define MSG_ERROR 3
-#define MSG_CRITICAL 2
-#define MSG_NULL 1
-
-
-
-#define print_log(iif, priority, format...) \
-do { \
- print_fsck_log(iif, priority, __FILE__, __LINE__, ## format); \
-} while(0)
-
-#define log_debug(format...) \
-do { \
- print_log(0, MSG_DEBUG, format); \
-} while(0)
-
-#define log_info(format...) \
-do { \
- print_log(0, MSG_INFO, format); \
-} while(0)
-
-#define log_notice(format...) \
-do { \
- print_log(0, MSG_NOTICE, format); \
-} while(0)
-
-#define log_warn(format...) \
-do { \
- print_log(0, MSG_WARN, format); \
-} while(0)
-
-#define log_err(format...) \
-do { \
- print_log(0, MSG_ERROR, format); \
-} while(0)
-
-#define log_crit(format...) \
-do { \
- print_log(0, MSG_CRITICAL, format); \
-} while(0)
-
-#define stack log_debug("<backtrace> - %s()\n", __func__)
-
-#define log_at_debug(format...) \
-do { \
- print_log(1, MSG_DEBUG, format); \
-} while(0)
-
-#define log_at_info(format...) \
-do { \
- print_log(1, MSG_INFO, format); \
-} while(0)
-
-#define log_at_notice(format...) \
-do { \
- print_log(1, MSG_NOTICE, format); \
-} while(0)
-
-#define log_at_warn(format...) \
-do { \
- print_log(1, MSG_WARN, format); \
-} while(0)
-
-#define log_at_err(format...) \
-do { \
- print_log(1, MSG_ERROR, format); \
-} while(0)
-
-#define log_at_crit(format...) \
-do { \
- print_log(1, MSG_CRITICAL, format); \
-} while(0)
-
-void increase_verbosity(void);
-void decrease_verbosity(void);
-void print_fsck_log(int iif, int priority, const char *file, int line, const char *format, ...);
-int query(struct fsck_sb *sbp, const char *format, ...);
-
-
-#endif /* __LOG_H */
diff --git a/gfs/gfs_fsck/lost_n_found.c b/gfs/gfs_fsck/lost_n_found.c
deleted file mode 100644
index 648e567..0000000
--- a/gfs/gfs_fsck/lost_n_found.c
+++ /dev/null
@@ -1,133 +0,0 @@
-#include "fs_dir.h"
-
-#include "lost_n_found.h"
-#include "link.h"
-#include "fs_inode.h"
-#include "bio.h"
-#include "inode.h"
-/* add_inode_to_lf - Add dir entry to lost+found for the inode
- * @ip: inode to add to lost + found
- *
- * This function adds an entry into the lost and found dir
- * for the given inode. The name of the entry will be
- * "lost_<ip->i_num.no_addr>".
- *
- * Returns: 0 on success, -1 on failure.
- */
-int add_inode_to_lf(struct fsck_inode *ip){
- char tmp_name[256];
- struct fsck_inode *lf_ip, *ri;
- osi_filename_t filename;
- struct block_query q;
-
- if(!ip->i_sbd->lf_dip) {
- log_info("Locating/Creating lost and found directory\n");
-
- load_inode(ip->i_sbd, ip->i_sbd->sb.sb_root_di.no_addr, &ri);
-
- if(fs_mkdir(ri, "l+f", 00700, &lf_ip)){
- log_err("Unable to create/locate l+f directory.\n");
- }
- free_inode(&ri);
- if(!lf_ip){
- log_warn("No l+f directory, can not add inode.\n");
- return -1;
- }
- log_notice("l+f directory at %"PRIu64"\n", lf_ip->i_num.no_addr);
-
- ip->i_sbd->lf_dip = lf_ip;
- if(block_check(ip->i_sbd->bl, lf_ip->i_num.no_addr, &q)) {
- stack;
- return -1;
- }
- if(q.block_type != inode_dir) {
- /* This is a new l+f directory, so set its
- * block type and increment link counts for
- * the directories */
- /* FIXME: i'd feel better about this if
- * fs_mkdir returned whether it created a new
- * directory or just found an old one, and we
- * used that instead of the block_type to run
- * this */
- block_set(ip->i_sbd->bl, lf_ip->i_num.no_addr, inode_dir);
- increment_link(ip->i_sbd, ip->i_sbd->sb.sb_root_di.no_addr);
- increment_link(ip->i_sbd, lf_ip->i_num.no_addr);
- increment_link(ip->i_sbd, lf_ip->i_num.no_addr);
- }
- } else {
- lf_ip = ip->i_sbd->lf_dip;
- }
-
- if(ip->i_num.no_addr == lf_ip->i_num.no_addr) {
- log_err("Trying to add l+f to itself...skipping");
- return 0;
- }
- switch(ip->i_di.di_type){
- case GFS_FILE_DIR:
- log_info("Adding .. entry pointing to l+f for %"PRIu64"\n",
- ip->i_num.no_addr);
- sprintf(tmp_name, "..");
- filename.len = strlen(tmp_name); /* no trailing NULL */
- if(!(filename.name = malloc(sizeof(char) * filename.len))) {
- log_err("Unable to allocate name\n");
- stack;
- return -1;
- }
- if(!memset(filename.name, 0, sizeof(char) * filename.len)) {
- log_err("Unable to zero name\n");
- stack;
- return -1;
- }
- memcpy(filename.name, tmp_name, filename.len);
-
- if(fs_dirent_del(ip, NULL, &filename)){
- log_warn("add_inode_to_lf: "
- "Unable to remove \"..\" directory entry.\n");
- }
-
- if(fs_dir_add(ip, &filename, &(lf_ip->i_num),
- lf_ip->i_di.di_type)){
- log_err("Failed to link \"..\" entry to l+f directory.\n");
- block_set(ip->i_sbd->bl, ip->i_num.no_addr, meta_inval);
- return 0;
- }
-
- free(filename.name);
- sprintf(tmp_name, "lost_dir_%"PRIu64, ip->i_num.no_addr);
- break;
- case GFS_FILE_REG:
- sprintf(tmp_name, "lost_file_%"PRIu64, ip->i_num.no_addr);
- break;
- default:
- sprintf(tmp_name, "lost_%"PRIu64, ip->i_num.no_addr);
- break;
- }
- filename.len = strlen(tmp_name); /* no trailing NULL */
- if(!(filename.name = malloc(sizeof(char) * filename.len))) {
- log_err("Unable to allocate name\n");
- stack;
- return -1;
- }
- if(!memset(filename.name, 0, sizeof(char) * filename.len)) {
- log_err("Unable to zero name\n");
- stack;
- return -1;
- }
- memcpy(filename.name, tmp_name, filename.len);
-
- if(fs_dir_add(lf_ip, &filename, &(ip->i_num), ip->i_di.di_type)){
- log_err("Failed to add inode #%"PRIu64" to l+f dir.\n",
- ip->i_num.no_addr);
- /* FIXME: don't return -1 here, just mark the inode bad */
- free(filename.name);
- block_set(ip->i_sbd->bl, ip->i_num.no_addr, meta_inval);
- return 0;
- }
- increment_link(ip->i_sbd, ip->i_num.no_addr);
- if(ip->i_di.di_type == GFS_FILE_DIR) {
- increment_link(ip->i_sbd, lf_ip->i_num.no_addr);
- }
- free(filename.name);
- log_notice("Added inode #%"PRIu64" to l+f dir\n", ip->i_num.no_addr);
- return 0;
-}
diff --git a/gfs/gfs_fsck/lost_n_found.h b/gfs/gfs_fsck/lost_n_found.h
deleted file mode 100644
index dde343a..0000000
--- a/gfs/gfs_fsck/lost_n_found.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __LOST_N_FOUND_H__
-#define __LOST_N_FOUND_H__
-
-#include "fsck_incore.h"
-
-int add_inode_to_lf(struct fsck_inode *ip);
-
-#endif /* __LOST_N_FOUND_H__ */
diff --git a/gfs/gfs_fsck/main.c b/gfs/gfs_fsck/main.c
deleted file mode 100644
index 78c8e4d..0000000
--- a/gfs/gfs_fsck/main.c
+++ /dev/null
@@ -1,290 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <libgen.h>
-#include <ctype.h>
-#include <signal.h>
-
-#include "copyright.cf"
-#include "fsck_incore.h"
-#include "fsck.h"
-#include "log.h"
-
-uint64_t last_fs_block, last_reported_block = -1;
-int skip_this_pass = FALSE, fsck_abort = FALSE, fsck_query = FALSE;
-int errors_found = 0, errors_corrected = 0;
-const char *pass = "";
-
-#if 0
-static void print_map(struct block_list *il, int count)
-{
- int i, j;
- struct block_query k;
-
- log_info("Printing map of blocks - 80 blocks per row\n");
- j = 0;
- for(i = 0; i < count; i++) {
- if(j > 79) {
- log_info("\n");
- j = 0;
- }
- else if(!(j %10) && j != 0) {
- log_info(" ");
- }
- j++;
- block_check(il, i, &k);
- log_info("%X", k.block_type);
-
- }
- log_info("\n");
-}
-#endif
-
-static void usage(char *name)
-{
- printf("Usage: %s [-hnqvVy] <device> \n", basename(name));
-}
-
-static void version(void)
-{
- printf("GFS fsck %s (built %s %s)\n",
- RELEASE_VERSION, __DATE__, __TIME__);
- printf("%s\n", REDHAT_COPYRIGHT);
-}
-
-static int read_cmdline(int argc, char **argv, struct options *opts)
-{
- int c;
-
- while((c = getopt(argc, argv, "hnqvyV")) != -1) {
- switch(c) {
-
- case 'h':
- usage(argv[0]);
- exit(FSCK_OK);
- break;
- case 'n':
- opts->no = 1;
- break;
- case 'q':
- decrease_verbosity();
- break;
- case 'v':
- increase_verbosity();
- break;
- case 'V':
- version();
- exit(FSCK_OK);
- break;
- case 'y':
- opts->yes = 1;
- break;
- case ':':
- case '?':
- fprintf(stderr, "Please use '-h' for usage.\n");
- exit(FSCK_USAGE);
- break;
- default:
- fprintf(stderr, "Bad programmer! You forgot to catch"
- " the %c flag\n", c);
- exit(FSCK_USAGE);
- break;
-
- }
- }
- if(argc > optind) {
- opts->device = (argv[optind]);
- if(!opts->device) {
- fprintf(stderr, "Please use '-h' for usage.\n");
- exit(FSCK_USAGE);
- }
- } else {
- fprintf(stderr, "No device specified. Use '-h' for usage.\n");
- exit(FSCK_USAGE);
- }
- return 0;
-}
-
-static void interrupt(int sig)
-{
- fd_set rfds;
- struct timeval tv;
- char response;
- int err;
- ssize_t amtread;
-
- if (fsck_query) /* if we're asking them a question */
- return; /* ignore the interrupt signal */
- FD_ZERO(&rfds);
- FD_SET(STDIN_FILENO, &rfds);
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- /* Make sure there isn't extraneous input before asking the
- * user the question */
- while((err = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv))) {
- if(err < 0) {
- log_debug("Error in select() on stdin\n");
- break;
- }
- err = read(STDIN_FILENO, &response, sizeof(char));
- }
- while (TRUE) {
- printf("\ngfs_fsck interrupted in %s: ", pass);
- if (!last_reported_block || last_reported_block == last_fs_block)
- printf("progress unknown.\n");
- else
- printf("processing block %" PRIu64 " out of %" PRIu64 "\n",
- last_reported_block, last_fs_block);
- printf("Do you want to abort gfs_fsck, skip the rest of %s or continue (a/s/c)?", pass);
-
- /* Make sure query is printed out */
- fflush(stdout);
- amtread = read(STDIN_FILENO, &response, sizeof(char));
-
- if(amtread && tolower(response) == 's') {
- skip_this_pass = TRUE;
- return;
- }
- else if (amtread && tolower(response) == 'a') {
- fsck_abort = TRUE;
- return;
- }
- else if (amtread && tolower(response) == 'c')
- return;
- else {
- while(response != '\n')
- amtread = read(STDIN_FILENO, &response,
- sizeof(char));
- printf("Bad response, please type 'c', 'a' or 's'.\n");
- continue;
- }
- }
-}
-
-int main(int argc, char **argv)
-{
- struct fsck_sb sb;
- struct options opts = {0};
- struct fsck_sb *sbp = &sb;
- int error = 0;
-
- memset(sbp, 0, sizeof(*sbp));
- sbp->opts = &opts;
-
- if((error = read_cmdline(argc, argv, &opts)))
- exit(error);
- setbuf(stdout, NULL);
- log_notice("Initializing fsck\n");
- if ((error = initialize(sbp)))
- exit(error);
-
- signal(SIGINT, interrupt);
- log_notice("Starting pass1\n");
- pass = "pass 1";
- last_reported_block = 0;
- if ((error = pass1(sbp)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice("Pass1 interrupted \n");
- }
- else
- log_notice("Pass1 complete \n");
-
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 1b";
- log_notice("Starting pass1b\n");
- if((error = pass1b(sbp)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice("Pass1b interrupted \n");
- }
- else
- log_notice("Pass1b complete \n");
- }
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 1c";
- log_notice("Starting pass1c\n");
- if((error = pass1c(sbp)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice("Pass1c interrupted \n");
- }
- else
- log_notice("Pass1c complete \n");
- }
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 2";
- log_notice("Starting pass2\n");
- if ((error = pass2(sbp, &opts)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice("Pass2 interrupted \n");
- }
- else
- log_notice("Pass2 complete \n");
- }
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 3";
- log_notice("Starting pass3\n");
- if ((error = pass3(sbp, &opts)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice("Pass3 interrupted \n");
- }
- else
- log_notice("Pass3 complete \n");
- }
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 4";
- log_notice("Starting pass4\n");
- if ((error = pass4(sbp, &opts)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice("Pass4 interrupted \n");
- }
- else
- log_notice("Pass4 complete \n");
- }
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 5";
- log_notice("Starting pass5\n");
- if ((error = pass5(sbp, &opts)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice("Pass5 interrupted \n");
- }
- else
- log_notice("Pass5 complete \n");
- log_notice("Writing changes to disk\n");
- } else {
- error = FSCK_CANCELED;
- }
-
- destroy(sbp);
- if (!error) {
- if (!errors_found)
- error = FSCK_OK;
- else if (errors_found == errors_corrected)
- error = FSCK_NONDESTRUCT;
- else
- error = FSCK_UNCORRECTED;
- }
- exit(error);
-}
-
-
-
diff --git a/gfs/gfs_fsck/metawalk.c b/gfs/gfs_fsck/metawalk.c
deleted file mode 100644
index 9ae00db..0000000
--- a/gfs/gfs_fsck/metawalk.c
+++ /dev/null
@@ -1,1088 +0,0 @@
-#include "fsck_incore.h"
-#include "fsck.h"
-#include "bio.h"
-#include "fs_dir.h"
-#include "inode.h"
-#include "util.h"
-#include "hash.h"
-
-#include "metawalk.h"
-
-/*
- * check_entries - check directory entries for a given block
- *
- * @ip - dinode associated with this leaf block
- * bh - buffer for the leaf block
- * type - type of block this is (linear or exhash)
- * @update - set to 1 if the block was updated
- * @count - set to the count entries
- * @pass - structure pointing to pass-specific functions
- *
- * returns: 0 - good block or it was repaired to be good
- * -1 - error occurred
- */
-static int check_entries(struct fsck_inode *ip, osi_buf_t *bh, int type,
- int *update, uint16_t *count,
- struct metawalk_fxns *pass)
-{
- struct gfs_leaf *leaf = NULL;
- struct gfs_dirent *dent;
- struct gfs_dirent de, *prev;
- int error = 0;
- char *bh_end;
- char *filename;
- int first = 1;
-
- bh_end = BH_DATA(bh) + BH_SIZE(bh);
-
- if(type == DIR_LINEAR) {
- dent = (struct gfs_dirent *)(BH_DATA(bh)
- + sizeof(struct gfs_dinode));
- }
- else if (type == DIR_EXHASH) {
- dent = (struct gfs_dirent *)(BH_DATA(bh)
- + sizeof(struct gfs_leaf));
- leaf = (struct gfs_leaf *)BH_DATA(bh);
- log_debug("Checking leaf %"PRIu64"\n", BH_BLKNO(bh));
- }
- else {
- log_err("Invalid directory type %d specified\n", type);
- return -1;
- }
-
- prev = NULL;
- if(!pass->check_dentry)
- return 0;
-
- while(1) {
- if (skip_this_pass || fsck_abort)
- return FSCK_OK;
- memset(&de, 0, sizeof(struct gfs_dirent));
- gfs_dirent_in(&de, (char *)dent);
- filename = (char *)dent + sizeof(struct gfs_dirent);
-
- if (de.de_rec_len < sizeof(struct gfs_dirent) +
- de.de_name_len ||
- (de.de_inum.no_formal_ino && !de.de_name_len && !first)) {
- log_err("Directory block %"
- PRIu64 ", entry %d of directory %"
- PRIu64 " is corrupt.\n", BH_BLKNO(bh),
- (*count) + 1, ip->i_di.di_num.no_addr);
- errors_found++;
- if (query(ip->i_sbd, "Attempt to repair it? (y/n) ")) {
- if (dirent_repair(ip, bh, &de, dent, type,
- first)) {
- if (first) /* make a new sentinel */
- dirblk_truncate(ip, dent, bh);
- else
- dirblk_truncate(ip, prev, bh);
- *update = 1;
- log_err("Unable to repair corrupt "
- "directory entry; the entry "
- "was removed instead.\n");
- errors_corrected++;
- return 0;
- } else {
- log_err("Corrupt directory entry "
- "repaired.\n");
- errors_corrected++;
- *update = 1;
- /* keep looping through dentries */
- }
- } else {
- log_err("Corrupt directory entry ignored, "
- "stopped after checking %d entries.\n",
- *count);
- return 0;
- }
- }
- if (!de.de_inum.no_formal_ino){
- if(first){
- log_debug("First dirent is a sentinel (place holder).\n");
- first = 0;
- } else {
- log_err("Directory entry with inode number of "
- "zero in leaf %"PRIu64" of directory "
- "%"PRIu64"!\n", BH_BLKNO(bh),
- ip->i_di.di_num.no_addr);
- errors_found++;
- if (query(ip->i_sbd,
- "Attempt to remove it? (y/n) ")) {
- dirblk_truncate(ip, prev, bh);
- *update = 1;
- log_err("The corrupt directory entry "
- "was removed.\n");
- errors_corrected++;
- } else {
- log_err("Corrupt directory entry "
- "ignored, stopped after "
- "checking %d entries.\n",
- *count);
- }
- return 0;
- }
- } else {
-
- error = pass->check_dentry(ip, dent, prev, bh,
- filename, update,
- count,
- pass->private);
- if(error < 0) {
- stack;
- return -1;
- }
- }
-
- if ((char *)dent + de.de_rec_len >= bh_end){
- log_debug("Last entry processed.\n");
- break;
- }
-
- /* If we didn't clear the dentry, or if we did, but it
- * was the first dentry, set prev */
- if(!error || first)
- prev = dent;
- first = 0;
- dent = (struct gfs_dirent *)((char *)dent + de.de_rec_len);
- }
- return 0;
-}
-
-/* Process a bad leaf pointer and ask to repair the first time. */
-/* The repair process involves extending the previous leaf's entries */
-/* so that they replace the bad ones. We have to hack up the old */
-/* leaf a bit, but it's better than deleting the whole directory, */
-/* which is what used to happen before. */
-static void warn_and_patch(struct fsck_inode *ip, uint64_t *leaf_no,
- uint64_t *bad_leaf, uint64_t old_leaf,
- uint64_t first_ok_leaf, int lindex, const char *msg)
-{
- if (*bad_leaf != *leaf_no) {
- log_err("Directory Inode %" PRIu64 " points to leaf %"
- PRIu64 " %s.\n", ip->i_di.di_num.no_addr, *leaf_no,
- msg);
- }
- errors_found++;
- if (*leaf_no == *bad_leaf ||
- query(ip->i_sbd, "Attempt to patch around it? (y/n) ")) {
- errors_corrected++;
- if (check_range(ip->i_sbd, old_leaf) == 0)
- put_leaf_nr(ip, lindex, old_leaf);
- else
- put_leaf_nr(ip, lindex, first_ok_leaf);
- log_err("Directory Inode %" PRIu64 ") repaired.\n",
- ip->i_di.di_num.no_addr);
- }
- else
- log_err("Bad leaf left in place.\n");
- *bad_leaf = *leaf_no;
- *leaf_no = old_leaf;
-}
-
-/* Checks all exhash directory leaf blocks (and their directory entries) */
-static int check_leaf_blks(struct fsck_inode *ip, int *update,
- struct metawalk_fxns *pass)
-{
- int error;
- struct gfs_leaf leaf, oldleaf;
- uint64_t leaf_no, old_leaf, bad_leaf = -1;
- uint64_t first_leaf_ptr = -1, first_ok_leaf = -1;
- osi_buf_t *lbh;
- int lindex;
- struct fsck_sb *sbp = ip->i_sbd;
- uint16_t count;
- int ref_count = 0, exp_count = 0;
-
- /* Find the first valid leaf pointer in range and use it as our "old"
- leaf. That way, bad blocks at the beginning will be overwritten
- with the first valid leaf. */
- first_ok_leaf = -1;
- for(lindex = 0; lindex < (1 << ip->i_di.di_depth); lindex++) {
- get_leaf_nr(ip, lindex, &first_ok_leaf);
- if (first_leaf_ptr == -1)
- first_leaf_ptr = first_ok_leaf;
- if(check_range(sbp, first_ok_leaf) == 0) {
- get_and_read_buf(sbp, first_ok_leaf, &lbh, 0);
- /* Make sure it's really a valid leaf block. */
- if (check_meta(lbh, GFS_METATYPE_LF) == 0) {
- relse_buf(sbp, lbh);
- break;
- }
- relse_buf(sbp, lbh);
- }
- }
- old_leaf = -1;
- memset(&oldleaf, 0, sizeof(oldleaf));
- for(lindex = 0; lindex < (1 << ip->i_di.di_depth); lindex++) {
- if (fsck_abort)
- break;
- if(get_leaf_nr(ip, lindex, &leaf_no)) {
- log_err("Unable to get leaf block number in dir %"
- PRIu64"\n"
- "\tDepth = %u\n"
- "\tlindex = %u\n",
- ip->i_num.no_addr,
- ip->i_di.di_depth,
- lindex);
- return -1;
- }
-
- /* GFS has multiple indirect pointers to the same leaf
- * until those extra pointers are needed, so skip the
- * dups */
- if (leaf_no == bad_leaf) {
- put_leaf_nr(ip, lindex, old_leaf); /* fill w/old leaf */
- ref_count++;
- continue;
- }
- else if(old_leaf == leaf_no) {
- ref_count++;
- continue;
- }
- if(check_range(sbp, old_leaf) == 0 && ref_count != exp_count){
- log_err("Dir #%"PRIu64" has an incorrect number "
- "of pointers to leaf #%"PRIu64"\n"
- "\tFound: %u, Expected: %u\n",
- ip->i_num.no_addr, old_leaf, ref_count,
- exp_count);
- errors_found++;
- if (query(ip->i_sbd, "Attempt to fix it? (y/n) ")) {
- int factor = 0, divisor = ref_count;
-
- errors_corrected++;
- get_and_read_buf(sbp, old_leaf, &lbh, 0);
- while (divisor > 1) {
- factor++;
- divisor /= 2;
- }
- gfs_leaf_in(&oldleaf, BH_DATA(lbh));
- oldleaf.lf_depth = ip->i_di.di_depth - factor;
- gfs_leaf_out(&oldleaf, BH_DATA(lbh));
- write_buf(sbp, lbh, 0);
- relse_buf(sbp, lbh);
- }
- else
- return 1;
- }
- ref_count = 1;
-
- count = 0;
- do {
- if (fsck_abort)
- break;
- /* Make sure the block number is in range. */
- if(check_range(ip->i_sbd, leaf_no)){
- log_err("Leaf block #%"PRIu64" is out of "
- "range for directory #%"PRIu64".\n",
- leaf_no, ip->i_di.di_num.no_addr);
- warn_and_patch(ip, &leaf_no, &bad_leaf,
- old_leaf, first_ok_leaf, lindex,
- "that is out of range");
- memcpy(&leaf, &oldleaf, sizeof(oldleaf));
- break;
- }
- *update = 0;
- /* Try to read in the leaf block. */
- if(get_and_read_buf(sbp, leaf_no, &lbh, 0)){
- log_err("Unable to read leaf block #%"
- PRIu64" for "
- "directory #%"PRIu64".\n",
- leaf_no, ip->i_di.di_num.no_addr);
- warn_and_patch(ip, &leaf_no, &bad_leaf,
- old_leaf, first_ok_leaf, lindex,
- "that cannot be read");
- memcpy(&leaf, &oldleaf, sizeof(oldleaf));
- relse_buf(sbp, lbh);
- break;
- }
- /* Make sure it's really a valid leaf block. */
- if (check_meta(lbh, GFS_METATYPE_LF)) {
- warn_and_patch(ip, &leaf_no, &bad_leaf,
- old_leaf, first_ok_leaf, lindex,
- "that is not really a leaf");
- memcpy(&leaf, &oldleaf, sizeof(oldleaf));
- relse_buf(sbp, lbh);
- break;
- }
- gfs_leaf_in(&leaf, BH_DATA(lbh));
- if(pass->check_leaf) {
- error = pass->check_leaf(ip, leaf_no, lbh,
- pass->private);
- }
-
- /* Make sure it's really a leaf. */
- if (leaf.lf_header.mh_type != GFS_METATYPE_LF) {
- log_err("Inode %" PRIu64 " points to bad leaf "
- PRIu64 ".\n", ip->i_di.di_num.no_addr,
- leaf_no);
- relse_buf(sbp, lbh);
- break;
- }
-
- exp_count = (1 << (ip->i_di.di_depth - leaf.lf_depth));
- log_debug("expected count %u - %u %u\n", exp_count,
- ip->i_di.di_depth, leaf.lf_depth);
- if(pass->check_dentry &&
- ip->i_di.di_type == GFS_FILE_DIR) {
- error = check_entries(ip, lbh, DIR_EXHASH,
- update, &count, pass);
-
- /* Since the buffer possibly got
- * updated directly, release it now,
- * and grab it again later if we need it. */
-
- relse_buf(sbp, lbh);
-
- if(error < 0) {
- stack;
- return -1;
- }
-
- if(update && (count != leaf.lf_entries)) {
-
- if(get_and_read_buf(sbp, leaf_no,
- &lbh, 0)){
- log_err("Unable to read leaf block #%"
- PRIu64" for "
- "directory #%"PRIu64".\n",
- leaf_no,
- ip->i_di.di_num.no_addr);
- return -1;
- }
- gfs_leaf_in(&leaf, BH_DATA(lbh));
-
- log_err("Leaf(%"PRIu64") entry count in directory %"PRIu64" doesn't match number of entries found - is %u, found %u\n", leaf_no, ip->i_num.no_addr, leaf.lf_entries, count);
- errors_found++;
- if(query(sbp, "Update leaf entry count? (y/n) ")) {
- errors_corrected++;
- leaf.lf_entries = count;
- gfs_leaf_out(&leaf, BH_DATA(lbh));
- write_buf(sbp, lbh, 0);
- log_warn("Leaf entry count updated\n");
- } else {
- log_err("Leaf entry count left in inconsistant state\n");
- }
- relse_buf(sbp, lbh);
- }
- /* FIXME: Need to get entry count and
- * compare it against leaf->lf_entries */
- break; /* not a chain; go back to outer loop */
- } else {
- relse_buf(sbp, lbh);
- if(!leaf.lf_next)
- break;
- leaf_no = leaf.lf_next;
- log_debug("Leaf chain detected.\n");
- }
- } while(1); /* while we have chained leaf blocks */
- old_leaf = leaf_no;
- memcpy(&oldleaf, &leaf, sizeof(oldleaf));
- } /* for every leaf block */
- return 0;
-}
-
-static int check_eattr_entries(struct fsck_inode *ip, osi_buf_t *bh,
- struct metawalk_fxns *pass)
-{
- struct gfs_ea_header *ea_hdr, *ea_hdr_prev = NULL;
- uint64_t *ea_data_ptr = NULL;
- int i;
- int error = 0;
- uint32_t offset = (uint32_t)sizeof(struct gfs_meta_header);
-
- if(!pass->check_eattr_entry) {
- return 0;
- }
-
- ea_hdr = (struct gfs_ea_header *)(BH_DATA(bh) +
- sizeof(struct gfs_meta_header));
-
- while(1){
- if (ea_hdr->ea_type == GFS_EATYPE_UNUSED)
- error = 0;
- else
- error = pass->check_eattr_entry(ip, bh, ea_hdr,
- ea_hdr_prev,
- pass->private);
- if(error < 0) {
- stack;
- return -1;
- }
- if(error == 0 && pass->check_eattr_extentry &&
- ea_hdr->ea_num_ptrs) {
- uint32_t tot_ealen = 0;
- struct fsck_sb *sdp = ip->i_sbd;
-
- ea_data_ptr = ((uint64_t *)((char *)ea_hdr +
- sizeof(struct gfs_ea_header) +
- ((ea_hdr->ea_name_len + 7) & ~7)));
-
- /* It is possible when a EA is shrunk
- ** to have ea_num_ptrs be greater than
- ** the number required for ** data.
- ** In this case, the EA ** code leaves
- ** the blocks ** there for **
- ** reuse........... */
-
- for(i = 0; i < ea_hdr->ea_num_ptrs; i++){
- if(pass->check_eattr_extentry(ip,
- ea_data_ptr,
- bh, ea_hdr,
- ea_hdr_prev,
- pass->private)) {
- errors_found++;
- if (query(ip->i_sbd,
- "Repair the bad Extended "
- "Attribute? (y/n) ")) {
- errors_corrected++;
- ea_hdr->ea_num_ptrs = i;
- ea_hdr->ea_data_len =
- cpu_to_be32(tot_ealen);
- *ea_data_ptr = 0;
- /* Endianness doesn't matter
- in this case because it's
- a single byte. */
- block_set(sdp->bl,
- ip->i_di.di_eattr,
- meta_eattr);
- write_buf(sdp, bh, 0);
- log_err("The EA was fixed.\n");
- } else {
- error = 1;
- log_err("The bad EA was not "
- "fixed.\n");
- }
- }
- tot_ealen += sdp->sb.sb_bsize -
- sizeof(struct gfs_meta_header);
- ea_data_ptr++;
- }
- }
- offset += gfs32_to_cpu(ea_hdr->ea_rec_len);
- if(ea_hdr->ea_flags & GFS_EAFLAG_LAST ||
- offset >= ip->i_sbd->sb.sb_bsize || ea_hdr->ea_rec_len == 0){
- break;
- }
- ea_hdr_prev = ea_hdr;
- ea_hdr = (struct gfs_ea_header *)
- ((char *)(ea_hdr) +
- gfs32_to_cpu(ea_hdr->ea_rec_len));
- }
-
- return error;
-}
-
-/**
- * check_leaf_eattr
- * @ip: the inode the eattr comes from
- * @block: block number of the leaf
- *
- * Returns: 0 on success, 1 if removal is needed, -1 on error
- */
-static int check_leaf_eattr(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, struct metawalk_fxns *pass)
-{
- osi_buf_t *bh = NULL;
- int error = 0;
- log_debug("Checking EA leaf block #%"PRIu64".\n", block);
-
- if(pass->check_eattr_leaf) {
- error = pass->check_eattr_leaf(ip, block, parent,
- &bh, pass->private);
- if(error < 0) {
- stack;
- return -1;
- }
- if(error > 0) {
- if (bh)
- relse_buf(ip->i_sbd, bh);
- return 1;
- }
- if (bh) {
- error = check_eattr_entries(ip, bh, pass);
- relse_buf(ip->i_sbd, bh);
- }
- return error;
- }
-
- return 0;
-}
-
-/**
- * check_indirect_eattr
- * @ip: the inode the eattr comes from
- * @indirect_block
- *
- * Returns: 0 on success -1 on error
- */
-static int check_indirect_eattr(struct fsck_inode *ip, uint64_t indirect,
- struct metawalk_fxns *pass)
-{
- int error = 0;
- uint64_t *ea_leaf_ptr, *end;
- uint64_t block;
- osi_buf_t *indirect_buf = NULL;
- struct fsck_sb *sdp = ip->i_sbd;
- int update_indir_block = 0;
- int first_ea_is_bad = 0;
- uint64_t di_eattr_save = ip->i_di.di_eattr;
-
- log_debug("Checking EA indirect block #%"PRIu64".\n", indirect);
-
- if (!pass->check_eattr_indir)
- return 0;
- error = pass->check_eattr_indir(ip, indirect, ip->i_di.di_num.no_addr,
- &indirect_buf, pass->private);
- if (!error) {
- int leaf_pointers = 0, leaf_pointer_errors = 0;
-
- ea_leaf_ptr = (uint64 *)(BH_DATA(indirect_buf)
- + sizeof(struct gfs_indirect));
- end = ea_leaf_ptr + ((sdp->sb.sb_bsize
- - sizeof(struct gfs_indirect)) / 8);
-
- while(*ea_leaf_ptr && (ea_leaf_ptr < end)){
- block = gfs64_to_cpu(*ea_leaf_ptr);
- leaf_pointers++;
- error = check_leaf_eattr(ip, block, indirect, pass);
- if (error) {
- leaf_pointer_errors++;
- if (!update_indir_block) {
- errors_found++;
- if (query(sdp, "Fix the indirect "
- "block too? (y/n) ")) {
- update_indir_block = 1;
- errors_corrected++;
- *ea_leaf_ptr = 0;
- }
- } else
- *ea_leaf_ptr = 0;
- }
- /* If the first eattr lead is bad, we can't have
- a hole, so we have to treat this as an unrecoverable
- eattr error and delete all eattr info. Calling
- finish_eattr_indir here causes ip->i_di.di_eattr = 0
- and that ensures that subsequent calls to
- check_leaf_eattr result in the eattr
- check_leaf_block nuking them all "due to previous
- errors" */
- if (leaf_pointers == 1 && leaf_pointer_errors == 1) {
- first_ea_is_bad = 1;
- if (pass->finish_eattr_indir)
- pass->finish_eattr_indir(ip,
- leaf_pointers,
- leaf_pointer_errors,
- pass->private);
- } else if (leaf_pointer_errors) {
- /* This is a bit tricky. We can't have eattr
- holes. So if we have 4 good eattrs, 1 bad
- eattr and 5 more good ones: GGGGBGGGGG,
- we need to tell check_leaf_eattr to delete
- all eattrs after the bad one. So we want:
- GGGG when we finish. To do that, we set
- di_eattr to 0 temporarily. */
- ip->i_di.di_eattr = 0;
- }
- ea_leaf_ptr++;
- }
- if (pass->finish_eattr_indir) {
- if (!first_ea_is_bad) {
- /* If the first ea is good but subsequent ones
- were bad and deleted, we need to restore
- the saved di_eattr block. */
- if (leaf_pointer_errors)
- ip->i_di.di_eattr = di_eattr_save;
- pass->finish_eattr_indir(ip, leaf_pointers,
- leaf_pointer_errors,
- pass->private);
- }
- if (leaf_pointer_errors == leaf_pointers) {
- fs_set_bitmap(sdp, indirect, GFS_BLKST_FREE);
- block_set(sdp->bl, indirect, block_free);
- error = 1;
- }
- }
- }
- if (indirect_buf)
- relse_buf(sdp, indirect_buf);
-
- return error;
-}
-
-/**
- * check_inode_eattr - check the EA's for a single inode
- * @ip: the inode whose EA to check
- *
- * Returns: 0 on success, -1 on error
- */
-int check_inode_eattr(struct fsck_inode *ip, struct metawalk_fxns *pass)
-{
- int error = 0;
-
- if(!ip->i_di.di_eattr)
- return 0;
-
- log_debug("Extended attributes exist for inode #%"PRIu64".\n",
- ip->i_num.no_formal_ino);
-
- if(ip->i_di.di_flags & GFS_DIF_EA_INDIRECT){
- if((error = check_indirect_eattr(ip, ip->i_di.di_eattr, pass)))
- stack;
- } else {
- error = check_leaf_eattr(ip, ip->i_di.di_eattr,
- ip->i_di.di_num.no_addr, pass);
- if (error)
- stack;
- }
-
- return error;
-}
-
-/**
- * build_metalist
- * @ip:
- * @mlp:
- */
-static int build_metalist(struct fsck_inode *ip, osi_list_t *mlp,
- struct metawalk_fxns *pass)
-{
- uint32 height = ip->i_di.di_height;
- osi_buf_t *bh, *nbh, *metabh;
- osi_list_t *prev_list, *cur_list, *tmp;
- int i, head_size;
- uint64 *ptr, block;
- int err;
-
- if(get_and_read_buf(ip->i_sbd, ip->i_di.di_num.no_addr, &metabh, 0)) {
- stack;
- return -1;
- }
-
- osi_list_add(&metabh->b_list, &mlp[0]);
-
- /* if(<there are no indirect blocks to check>) */
- if (height < 2)
- return 0;
- for (i = 1; i < height; i++){
- prev_list = &mlp[i - 1];
- cur_list = &mlp[i];
-
- for (tmp = prev_list->next; tmp != prev_list; tmp = tmp->next){
- bh = osi_list_entry(tmp, osi_buf_t, b_list);
-
- if (i > 1) {
- /* if this isn't really a block list skip it */
- if (check_meta(bh, GFS_METATYPE_IN))
- continue;
- head_size = sizeof(struct gfs_indirect);
- } else {
- /* if this isn't really a dinode, skip it */
- if (check_meta(bh, GFS_METATYPE_DI))
- continue;
- head_size = sizeof(struct gfs_dinode);
- }
-
- for (ptr = (uint64 *)(bh->b_data + head_size);
- (char *)ptr < (bh->b_data + bh->b_size);
- ptr++) {
- nbh = NULL;
-
- if (!*ptr)
- continue;
-
- block = gfs64_to_cpu(*ptr);
- err = pass->check_metalist(ip, block, &nbh,
- pass->private);
- if(err < 0) {
- stack;
- goto fail;
- }
- if(err > 0) {
- log_debug("Skipping block %"PRIu64
- "\n", block);
- continue;
- }
- if(!nbh) {
- if(get_and_read_buf(ip->i_sbd, block,
- &nbh, 0)) {
- stack;
- goto fail;
- }
- }
- osi_list_add(&nbh->b_list, cur_list);
- }
- }
- }
- return 0;
-
- fail:
- for (i = 0; i < GFS_MAX_META_HEIGHT; i++) {
- osi_list_t *list;
- list = &mlp[i];
- while (!osi_list_empty(list))
- {
- bh = osi_list_entry(list->next, osi_buf_t, b_list);
- osi_list_del(&bh->b_list);
- relse_buf(ip->i_sbd, bh);
- }
- }
- /* This is an error path, so we need to release the buffer here: */
- relse_buf(ip->i_sbd, metabh);
- return -1;
-}
-
-/**
- * check_metatree
- * @ip:
- * @rgd:
- *
- */
-int check_metatree(struct fsck_inode *ip, struct metawalk_fxns *pass)
-{
- osi_list_t metalist[GFS_MAX_META_HEIGHT];
- osi_list_t *list, *tmp;
- osi_buf_t *bh;
- uint64_t block, *ptr;
- uint32_t height = ip->i_di.di_height;
- int i, head_size;
- int update = 0;
- int error = 0;
-
- if (!height)
- goto end;
-
- for (i = 0; i < GFS_MAX_META_HEIGHT; i++)
- osi_list_init(&metalist[i]);
-
- /* create metalist for each level */
- if(build_metalist(ip, &metalist[0], pass)){
- stack;
- return -1;
- }
-
- /* We don't need to record directory blocks - they will be
- * recorded later...i think... */
- if (ip->i_di.di_type == GFS_FILE_DIR) {
- log_debug("Directory with height > 0 at %"PRIu64"\n",
- ip->i_di.di_num.no_addr);
- }
-
- /* check data blocks */
- list = &metalist[height - 1];
-
- for (tmp = list->next; tmp != list; tmp = tmp->next) {
- bh = osi_list_entry(tmp, osi_buf_t, b_list);
-
- if (height > 1) {
- /* if this isn't really a block list skip it */
- if (check_meta(bh, GFS_METATYPE_IN))
- continue;
- head_size = sizeof(struct gfs_indirect);
- } else {
- /* if this isn't really a dinode, skip it */
- if (check_meta(bh, GFS_METATYPE_DI))
- continue;
- head_size = sizeof(struct gfs_dinode);
- }
- ptr = (uint64 *)(bh->b_data + head_size);
-
- for ( ; (char *)ptr < (bh->b_data + bh->b_size); ptr++) {
- if (!*ptr)
- continue;
-
- block = gfs64_to_cpu(*ptr);
-
- if(pass->check_data &&
- (pass->check_data(ip, block, pass->private) < 0)) {
- stack;
- return -1;
- }
- }
- }
-
- /* free metalists */
- for (i = 0; i < GFS_MAX_META_HEIGHT; i++)
- {
- list = &metalist[i];
- while (!osi_list_empty(list))
- {
- bh = osi_list_entry(list->next, osi_buf_t, b_list);
- osi_list_del(&bh->b_list);
- relse_buf(ip->i_sbd, bh);
- }
- }
-
-end:
- if (ip->i_di.di_type == GFS_FILE_DIR) {
- /* check validity of leaf blocks and leaf chains */
- if (ip->i_di.di_flags & GFS_DIF_EXHASH) {
- error = check_leaf_blks(ip, &update, pass);
- if(error < 0)
- return -1;
- if(error > 0)
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Checks stuffed inode directories */
-static int check_linear_dir(struct fsck_inode *ip, osi_buf_t *bh, int *update,
- struct metawalk_fxns *pass)
-{
- int error = 0;
- uint16_t count = 0;
-
- error = check_entries(ip, bh, DIR_LINEAR, update, &count, pass);
- if(error < 0) {
- stack;
- return -1;
- }
-
- return error;
-}
-
-
-int check_dir(struct fsck_sb *sbp, uint64_t block, struct metawalk_fxns *pass)
-{
- osi_buf_t *bh;
- struct fsck_inode *ip;
- int update = 0;
- int error = 0;
-
- if(get_and_read_buf(sbp, block, &bh, 0)){
- log_err("Unable to retrieve block #%"PRIu64"\n",
- block);
- block_set(sbp->bl, block, meta_inval);
- return -1;
- }
-
- if(copyin_inode(sbp, bh, &ip)) {
- stack;
- relse_buf(sbp, bh);
- return -1;
- }
-
- if(ip->i_di.di_flags & GFS_DIF_EXHASH) {
- error = check_leaf_blks(ip, &update, pass);
- if(error < 0) {
- stack;
- free_inode(&ip);
- relse_buf(sbp, bh);
- return -1;
- }
- }
- else {
- error = check_linear_dir(ip, bh, &update, pass);
- if(error < 0) {
- stack;
- free_inode(&ip);
- relse_buf(sbp, bh);
- return -1;
- }
- }
-
- free_inode(&ip);
- relse_buf(sbp, bh);
-
- return error;
-}
-
-static int remove_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
- struct gfs_dirent *prev_de,
- osi_buf_t *bh, char *filename, int *update,
- uint16_t *count,
- void *private)
-{
- /* the metawalk_fxn's private field must be set to the dentry
- * block we want to clear */
- uint64_t *dentryblock = (uint64_t *) private;
- struct gfs_dirent dentry, *de;
-
- memset(&dentry, 0, sizeof(struct gfs_dirent));
- gfs_dirent_in(&dentry, (char *)dent);
- de = &dentry;
-
- if(de->de_inum.no_addr == *dentryblock) {
- *update = 1;
- if(dirent_del(ip, bh, prev_de, dent)) {
- stack;
- return -1;
- }
- }
- else {
- (*count)++;
- *update = 1;
- }
-
- return 0;
-
-}
-
-int remove_dentry_from_dir(struct fsck_sb *sbp, uint64_t dir,
- uint64_t dentryblock)
-{
- struct metawalk_fxns remove_dentry_fxns = {0};
- struct block_query q;
- int error;
-
- log_debug("Removing dentry %"PRIu64" from directory %"PRIu64"\n",
- dentryblock, dir);
- if(check_range(sbp, dir)) {
- log_err("Parent directory out of range\n");
- return 1;
- }
- remove_dentry_fxns.private = &dentryblock;
- remove_dentry_fxns.check_dentry = remove_dentry;
-
- if(block_check(sbp->bl, dir, &q)) {
- stack;
- return -1;
- }
- if(q.block_type != inode_dir) {
- log_info("Parent block is not a directory...ignoring\n");
- return 1;
- }
- /* Need to run check_dir with a private var of dentryblock,
- * and fxns that remove that dentry if found */
- error = check_dir(sbp, dir, &remove_dentry_fxns);
-
- return error;
-}
-
-/* FIXME: These should be merged with the hash routines in inode_hash.c */
-static uint32_t dinode_hash(uint64_t block_no)
-{
- unsigned int h;
-
- h = fsck_hash(&block_no, sizeof (uint64_t));
- h &= FSCK_HASH_MASK;
-
- return h;
-}
-
-int find_di(struct fsck_sb *sbp, uint64_t childblock, struct dir_info **dip)
-{
- osi_list_t *bucket = &sbp->dir_hash[dinode_hash(childblock)];
- osi_list_t *tmp;
- struct dir_info *di = NULL;
-
- osi_list_foreach(tmp, bucket) {
- di = osi_list_entry(tmp, struct dir_info, list);
- if(di->dinode == childblock) {
- *dip = di;
- return 0;
- }
- }
- *dip = NULL;
- return -1;
-
-}
-
-int dinode_hash_insert(osi_list_t *buckets, uint64_t key, struct dir_info *di)
-{
- osi_list_t *tmp;
- osi_list_t *bucket = &buckets[dinode_hash(key)];
- struct dir_info *dtmp = NULL;
-
- if(osi_list_empty(bucket)) {
- osi_list_add(&di->list, bucket);
- return 0;
- }
-
- osi_list_foreach(tmp, bucket) {
- dtmp = osi_list_entry(tmp, struct dir_info, list);
- if(dtmp->dinode < key) {
- continue;
- }
- else {
- osi_list_add_prev(&di->list, tmp);
- return 0;
- }
- }
- osi_list_add_prev(&di->list, bucket);
- return 0;
-}
-
-int dinode_hash_remove(osi_list_t *buckets, uint64_t key)
-{
- osi_list_t *tmp;
- osi_list_t *bucket = &buckets[dinode_hash(key)];
- struct dir_info *dtmp = NULL;
-
- if(osi_list_empty(bucket)) {
- return -1;
- }
- osi_list_foreach(tmp, bucket) {
- dtmp = osi_list_entry(tmp, struct dir_info, list);
- if(dtmp->dinode == key) {
- osi_list_del(tmp);
- return 0;
- }
- }
- return -1;
-}
-
-/**
- * free_block - free up a block given its block number
- */
-void free_block(struct fsck_sb *sdp, uint64_t block)
-{
- osi_buf_t *bh;
- struct fsck_rgrp *rgd;
-
- fs_set_bitmap(sdp, block, GFS_BLKST_FREE);
- /* Adjust the free space count for the freed block */
- rgd = fs_blk2rgrpd(sdp, block); /* find the rg for indir block */
- get_and_read_buf(sdp, rgd->rd_ri.ri_addr, &bh, 0);
- rgd->rd_rg.rg_free++; /* adjust the free count */
- gfs_rgrp_out(&rgd->rd_rg, bh->b_data); /* back to the buffer */
- relse_buf(sdp, bh); /* release the buffer */
-}
-
-/**
- * delete_blocks - delete blocks associated with an inode
- */
-int delete_blocks(struct fsck_inode *ip, uint64_t block, osi_buf_t **bh,
- const char *btype, void *private)
-{
- struct block_query q = {0};
-
- if (check_range(ip->i_sbd, block) == 0) {
- if (block_check(ip->i_sbd->bl, block, &q))
- return 0;
- if (!q.dup_block) {
- log_info("Deleting %s block %lld as part "
- "of inode %lld \n",
- btype, block, ip->i_di.di_num.no_addr);
- block_set(ip->i_sbd->bl, block, block_free);
- free_block(ip->i_sbd, block);
- }
- }
- return 0;
-}
-
-int delete_metadata(struct fsck_inode *ip, uint64_t block, osi_buf_t **bh,
- void *private)
-{
- return delete_blocks(ip, block, bh, "metadata", private);
-}
-
-int delete_data(struct fsck_inode *ip, uint64_t block, void *private)
-{
- return delete_blocks(ip, block, NULL, "data", private);
-}
-
-int delete_eattr_indir(struct fsck_inode *ip, uint64_t block, uint64_t parent,
- osi_buf_t **bh, void *private)
-{
- return delete_blocks(ip, block, NULL, "indirect extended attribute",
- private);
-}
-
-int delete_eattr_leaf(struct fsck_inode *ip, uint64_t block, uint64_t parent,
- osi_buf_t **bh, void *private)
-{
- return delete_blocks(ip, block, NULL, "extended attribute", private);
-}
diff --git a/gfs/gfs_fsck/metawalk.h b/gfs/gfs_fsck/metawalk.h
deleted file mode 100644
index 2d4eed2..0000000
--- a/gfs/gfs_fsck/metawalk.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _METAWALK_H
-#define _METAWALK_H
-
-#define DIR_LINEAR 1
-#define DIR_EXHASH 2
-
-struct metawalk_fxns;
-
-int check_inode_eattr(struct fsck_inode *ip, struct metawalk_fxns *pass);
-int check_metatree(struct fsck_inode *ip, struct metawalk_fxns *pass);
-int check_dir(struct fsck_sb *sbp, uint64_t block, struct metawalk_fxns *pass);
-int remove_dentry_from_dir(struct fsck_sb *sbp, uint64_t dir,
- uint64_t dentryblock);
-int find_di(struct fsck_sb *sbp, uint64_t childblock, struct dir_info **dip);
-int dinode_hash_insert(osi_list_t *buckets, uint64_t key, struct dir_info *di);
-int dinode_hash_remove(osi_list_t *buckets, uint64_t key);
-void free_block(struct fsck_sb *sdp, uint64_t block);
-int delete_blocks(struct fsck_inode *ip, uint64_t block, osi_buf_t **bh,
- const char *btype, void *private);
-int delete_metadata(struct fsck_inode *ip, uint64_t block, osi_buf_t **bh,
- void *private);
-int delete_data(struct fsck_inode *ip, uint64_t block, void *private);
-int delete_eattr_indir(struct fsck_inode *ip, uint64_t block, uint64_t parent,
- osi_buf_t **bh, void *private);
-int delete_eattr_leaf(struct fsck_inode *ip, uint64_t block, uint64_t parent,
- osi_buf_t **bh, void *private);
-
-/* metawalk_fxns: function pointers to check various parts of the fs
- *
- * The functions should return -1 on fatal errors, 1 if the block
- * should be skipped, and 0 on success
- *
- * private: Data that should be passed to the fxns
- * check_leaf:
- * check_metalist:
- * check_data:
- * check_eattr_indir:
- * check_eattr_leaf:
- * check_dentry:
- * check_eattr_entry:
- * check_eattr_extentry:
- */
-struct metawalk_fxns {
- void *private;
- int (*check_leaf) (struct fsck_inode *ip, uint64_t block,
- osi_buf_t *bh, void *private);
- int (*check_metalist) (struct fsck_inode *ip, uint64_t block,
- osi_buf_t **bh, void *private);
- int (*check_data) (struct fsck_inode *ip, uint64_t block,
- void *private);
- int (*check_eattr_indir) (struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh,
- void *private);
- int (*check_eattr_leaf) (struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh,
- void *private);
- int (*check_dentry) (struct fsck_inode *ip, struct gfs_dirent *de,
- struct gfs_dirent *prev,
- osi_buf_t *bh, char *filename, int *update,
- uint16_t *count,
- void *private);
- int (*check_eattr_entry) (struct fsck_inode *ip,
- osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private);
- int (*check_eattr_extentry) (struct fsck_inode *ip,
- uint64_t *ea_data_ptr,
- osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private);
- int (*finish_eattr_indir) (struct fsck_inode *ip, int leaf_pointers,
- int leaf_pointer_errors,
- void *private);
-};
-
-#endif /* _METAWALK_H */
diff --git a/gfs/gfs_fsck/ondisk.c b/gfs/gfs_fsck/ondisk.c
deleted file mode 100644
index d3a4938..0000000
--- a/gfs/gfs_fsck/ondisk.c
+++ /dev/null
@@ -1,1342 +0,0 @@
-#ifndef HELPER_PROGRAM
-
-#include "gfs.h"
-
-#define pv(struct, member, fmt) printk(" "#member" = "fmt"\n", struct->member);
-
-#else
-
-#include <stdio.h>
-#include <string.h>
-
-#include "global.h"
-#include "linux_endian.h"
-#include "ondisk.h"
-
-#define printk printf
-#define pv(struct, member, fmt) printf(" "#member" = "fmt"\n", struct->member);
-
-#endif /* !HELPER_PROGRAM */
-
-#define CPIN_08(s1, s2, member, count) {memcpy((s1->member), (s2->member), (count));}
-#define CPOUT_08(s1, s2, member, count) {memcpy((s2->member), (s1->member), (count));}
-#define CPIN_16(s1, s2, member) {(s1->member) = gfs16_to_cpu((s2->member));}
-#define CPOUT_16(s1, s2, member) {(s2->member) = cpu_to_gfs16((s1->member));}
-#define CPIN_32(s1, s2, member) {(s1->member) = gfs32_to_cpu((s2->member));}
-#define CPOUT_32(s1, s2, member) {(s2->member) = cpu_to_gfs32((s1->member));}
-#define CPIN_64(s1, s2, member) {(s1->member) = gfs64_to_cpu((s2->member));}
-#define CPOUT_64(s1, s2, member) {(s2->member) = cpu_to_gfs64((s1->member));}
-
-#define pa(struct, member, count) print_array(#member, struct->member, count, console);
-
-/**
- * print_array - Print out an array of bytes
- * @title: what to print before the array
- * @buf: the array
- * @count: the number of bytes
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-static void
-print_array(const char *title, char *buf, int count, int console)
-{
- int x;
-
- printk(" %s =\n", title);
- for (x = 0; x < count; x++) {
- printk("%.2X ", (unsigned char) buf[x]);
- if (x % 16 == 15)
- printk("\n");
- }
- if (x % 16)
- printk("\n");
-
-}
-
-/**
- * gfs_inum_in - Read in an inode number
- * @no: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_inum_in(struct gfs_inum *no, char *buf)
-{
- struct gfs_inum *str = (struct gfs_inum *) buf;
-
- CPIN_64(no, str, no_formal_ino);
- CPIN_64(no, str, no_addr);
-
-}
-
-/**
- * gfs_inum_out - Write out an inode number
- * @no: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_inum_out(struct gfs_inum *no, char *buf)
-{
- struct gfs_inum *str = (struct gfs_inum *) buf;
-
- CPOUT_64(no, str, no_formal_ino);
- CPOUT_64(no, str, no_addr);
-
-}
-
-/**
- * gfs_inum_print - Print out a inode number
- * @no: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_inum_print(struct gfs_inum *no, int console)
-{
-
- pv(no, no_formal_ino, "%" PRIu64);
- pv(no, no_addr, "%" PRIu64);
-
-}
-
-/**
- * gfs_meta_header_in - Read in a metadata header
- * @mh: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_meta_header_in(struct gfs_meta_header *mh, char *buf)
-{
- struct gfs_meta_header *str = (struct gfs_meta_header *) buf;
-
- CPIN_32(mh, str, mh_magic);
- CPIN_32(mh, str, mh_type);
- CPIN_64(mh, str, mh_generation);
- CPIN_32(mh, str, mh_format);
- CPIN_32(mh, str, mh_incarn);
-
-}
-
-/**
- * gfs_meta_header_in - Write out a metadata header
- * @mh: the cpu-order structure
- * @buf: the disk-order buffer
- *
- * Don't ever change the generation number in this routine.
- * It's done manually in increment_generation().
- */
-
-void
-gfs_meta_header_out(struct gfs_meta_header *mh, char *buf)
-{
- struct gfs_meta_header *str = (struct gfs_meta_header *) buf;
-
- CPOUT_32(mh, str, mh_magic);
- CPOUT_32(mh, str, mh_type);
- /*CPOUT_64(mh, str, mh_generation); */
- CPOUT_32(mh, str, mh_format);
- CPOUT_32(mh, str, mh_incarn);
-
-}
-
-/**
- * gfs_meta_header_print - Print out a metadata header
- * @mh: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_meta_header_print(struct gfs_meta_header *mh, int console)
-{
-
- pv(mh, mh_magic, "0x%.8X");
- pv(mh, mh_type, "%u");
- pv(mh, mh_generation, "%" PRIu64);
- pv(mh, mh_format, "%u");
- pv(mh, mh_incarn, "%u");
-
-}
-
-/**
- * gfs_sb_in - Read in a superblock
- * @sb: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_sb_in(struct gfs_sb *sb, char *buf)
-{
- struct gfs_sb *str = (struct gfs_sb *) buf;
-
- gfs_meta_header_in(&sb->sb_header, buf);
-
- CPIN_32(sb, str, sb_fs_format);
- CPIN_32(sb, str, sb_multihost_format);
- CPIN_32(sb, str, sb_flags);
-
- CPIN_32(sb, str, sb_bsize);
- CPIN_32(sb, str, sb_bsize_shift);
- CPIN_32(sb, str, sb_seg_size);
-
- gfs_inum_in(&sb->sb_jindex_di, (char *) &str->sb_jindex_di);
- gfs_inum_in(&sb->sb_rindex_di, (char *) &str->sb_rindex_di);
- gfs_inum_in(&sb->sb_root_di, (char *) &str->sb_root_di);
-
- CPIN_08(sb, str, sb_lockproto, GFS_LOCKNAME_LEN);
- CPIN_08(sb, str, sb_locktable, GFS_LOCKNAME_LEN);
-
- gfs_inum_in(&sb->sb_quota_di, (char *) &str->sb_quota_di);
- gfs_inum_in(&sb->sb_license_di, (char *) &str->sb_license_di);
-
- CPIN_08(sb, str, sb_reserved, 96);
-
-}
-
-/**
- * gfs_sb_out - Write out a superblock
- * @sb: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_sb_out(struct gfs_sb *sb, char *buf)
-{
- struct gfs_sb *str = (struct gfs_sb *) buf;
-
- gfs_meta_header_out(&sb->sb_header, buf);
-
- CPOUT_32(sb, str, sb_fs_format);
- CPOUT_32(sb, str, sb_multihost_format);
- CPOUT_32(sb, str, sb_flags);
-
- CPOUT_32(sb, str, sb_bsize);
- CPOUT_32(sb, str, sb_bsize_shift);
- CPOUT_32(sb, str, sb_seg_size);
-
- gfs_inum_out(&sb->sb_jindex_di, (char *) &str->sb_jindex_di);
- gfs_inum_out(&sb->sb_rindex_di, (char *) &str->sb_rindex_di);
- gfs_inum_out(&sb->sb_root_di, (char *) &str->sb_root_di);
-
- CPOUT_08(sb, str, sb_lockproto, GFS_LOCKNAME_LEN);
- CPOUT_08(sb, str, sb_locktable, GFS_LOCKNAME_LEN);
-
- gfs_inum_out(&sb->sb_quota_di, (char *) &str->sb_quota_di);
- gfs_inum_out(&sb->sb_license_di, (char *) &str->sb_license_di);
-
- CPOUT_08(sb, str, sb_reserved, 96);
-
-}
-
-/**
- * gfs_sb_print - Print out a superblock
- * @sb: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_sb_print(struct gfs_sb *sb, int console)
-{
-
- gfs_meta_header_print(&sb->sb_header, console);
-
- pv(sb, sb_fs_format, "%u");
- pv(sb, sb_multihost_format, "%u");
- pv(sb, sb_flags, "%u");
-
- pv(sb, sb_bsize, "%u");
- pv(sb, sb_bsize_shift, "%u");
- pv(sb, sb_seg_size, "%u");
-
- gfs_inum_print(&sb->sb_jindex_di, console);
- gfs_inum_print(&sb->sb_rindex_di, console);
- gfs_inum_print(&sb->sb_root_di, console);
-
- pv(sb, sb_lockproto, "%s");
- pv(sb, sb_locktable, "%s");
-
- gfs_inum_print(&sb->sb_quota_di, console);
- gfs_inum_print(&sb->sb_license_di, console);
-
- pa(sb, sb_reserved, 96);
-
-}
-
-/**
- * gfs_jindex_in - Read in a journal index structure
- * @jindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_jindex_in(struct gfs_jindex *jindex, char *buf)
-{
- struct gfs_jindex *str = (struct gfs_jindex *) buf;
-
- CPIN_64(jindex, str, ji_addr);
- CPIN_32(jindex, str, ji_nsegment);
- CPIN_32(jindex, str, ji_pad);
-
- CPIN_08(jindex, str, ji_reserved, 64);
-
-}
-
-/**
- * gfs_jindex_out - Write out a journal index structure
- * @jindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_jindex_out(struct gfs_jindex *jindex, char *buf)
-{
- struct gfs_jindex *str = (struct gfs_jindex *) buf;
-
- CPOUT_64(jindex, str, ji_addr);
- CPOUT_32(jindex, str, ji_nsegment);
- CPOUT_32(jindex, str, ji_pad);
-
- CPOUT_08(jindex, str, ji_reserved, 64);
-
-}
-
-/**
- * gfs_jindex_print - Print out a journal index structure
- * @ji: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_jindex_print(struct gfs_jindex *ji, int console)
-{
-
- pv(ji, ji_addr, "%" PRIu64);
- pv(ji, ji_nsegment, "%u");
- pv(ji, ji_pad, "%u");
-
- pa(ji, ji_reserved, 64);
-
-}
-
-/**
- * gfs_rindex_in - Read in a resource index structure
- * @rindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rindex_in(struct gfs_rindex *grindex, char *buf)
-{
- struct gfs_rindex *str = (struct gfs_rindex *) buf;
-
- CPIN_64(grindex, str, ri_addr);
- CPIN_32(grindex, str, ri_length);
- CPIN_32(grindex, str, ri_pad);
-
- CPIN_64(grindex, str, ri_data1);
- CPIN_32(grindex, str, ri_data);
-
- CPIN_32(grindex, str, ri_bitbytes);
-
- CPIN_08(grindex, str, ri_reserved, 64);
-
-}
-
-/**
- * gfs_rindex_out - Write out a resource index structure
- * @rindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rindex_out(struct gfs_rindex *grindex, char *buf)
-{
- struct gfs_rindex *str = (struct gfs_rindex *) buf;
-
- CPOUT_64(grindex, str, ri_addr);
- CPOUT_32(grindex, str, ri_length);
- CPOUT_32(grindex, str, ri_pad);
-
- CPOUT_64(grindex, str, ri_data1);
- CPOUT_32(grindex, str, ri_data);
-
- CPOUT_32(grindex, str, ri_bitbytes);
-
- CPOUT_08(grindex, str, ri_reserved, 64);
-
-}
-
-/**
- * gfs_rindex_print - Print out a resource index structure
- * @ri: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_rindex_print(struct gfs_rindex *ri, int console)
-{
-
- pv(ri, ri_addr, "%" PRIu64);
- pv(ri, ri_length, "%u");
- pv(ri, ri_pad, "%u");
-
- pv(ri, ri_data1, "%" PRIu64);
- pv(ri, ri_data, "%u");
-
- pv(ri, ri_bitbytes, "%u");
-
- pa(ri, ri_reserved, 64);
-
-}
-
-/**
- * gfs_rgrp_in - Read in a resource group header
- * @rgrp: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rgrp_in(struct gfs_rgrp *rgrp, char *buf)
-{
- struct gfs_rgrp *str = (struct gfs_rgrp *) buf;
-
- gfs_meta_header_in(&rgrp->rg_header, buf);
-
- CPIN_32(rgrp, str, rg_flags);
-
- CPIN_32(rgrp, str, rg_free);
-
- CPIN_32(rgrp, str, rg_useddi);
- CPIN_32(rgrp, str, rg_freedi);
- gfs_inum_in(&rgrp->rg_freedi_list, (char *) &str->rg_freedi_list);
-
- CPIN_32(rgrp, str, rg_usedmeta);
- CPIN_32(rgrp, str, rg_freemeta);
-
- CPIN_08(rgrp, str, rg_reserved, 64);
-
-}
-
-/**
- * gfs_rgrp_out - Write out a resource group header
- * @rgrp: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rgrp_out(struct gfs_rgrp *rgrp, char *buf)
-{
- struct gfs_rgrp *str = (struct gfs_rgrp *) buf;
-
- gfs_meta_header_out(&rgrp->rg_header, buf);
-
- CPOUT_32(rgrp, str, rg_flags);
-
- CPOUT_32(rgrp, str, rg_free);
-
- CPOUT_32(rgrp, str, rg_useddi);
- CPOUT_32(rgrp, str, rg_freedi);
- gfs_inum_out(&rgrp->rg_freedi_list, (char *) &str->rg_freedi_list);
-
- CPOUT_32(rgrp, str, rg_usedmeta);
- CPOUT_32(rgrp, str, rg_freemeta);
-
- CPOUT_08(rgrp, str, rg_reserved, 64);
-
-}
-
-/**
- * gfs_rgrp_print - Print out a resource group header
- * @rg: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_rgrp_print(struct gfs_rgrp *rg, int console)
-{
-
- gfs_meta_header_print(&rg->rg_header, console);
-
- pv(rg, rg_flags, "%u");
-
- pv(rg, rg_free, "%u");
-
- pv(rg, rg_useddi, "%u");
- pv(rg, rg_freedi, "%u");
- gfs_inum_print(&rg->rg_freedi_list, console);
-
- pv(rg, rg_usedmeta, "%u");
- pv(rg, rg_freemeta, "%u");
-
- pa(rg, rg_reserved, 64);
-
-}
-
-/**
- * gfs_quota_in - Read in a quota structures
- * @quota: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_in(struct gfs_quota *quota, char *buf)
-{
- struct gfs_quota *str = (struct gfs_quota *) buf;
-
- CPIN_64(quota, str, qu_limit);
- CPIN_64(quota, str, qu_warn);
- CPIN_64(quota, str, qu_value);
-
- CPIN_08(quota, str, qu_reserved, 64);
-
-}
-
-/**
- * gfs_quota_out - Write out a quota structure
- * @quota: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_out(struct gfs_quota *quota, char *buf)
-{
- struct gfs_quota *str = (struct gfs_quota *) buf;
-
- CPOUT_64(quota, str, qu_limit);
- CPOUT_64(quota, str, qu_warn);
- CPOUT_64(quota, str, qu_value);
-
- CPOUT_08(quota, str, qu_reserved, 64);
-
-}
-
-/**
- * gfs_quota_print - Print out a quota structure
- * @quota: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_quota_print(struct gfs_quota *quota, int console)
-{
-
- pv(quota, qu_limit, "%" PRIu64);
- pv(quota, qu_warn, "%" PRIu64);
- pv(quota, qu_value, "%" PRId64);
-
- pa(quota, qu_reserved, 64);
-
-}
-
-/**
- * gfs_dinode_in - Read in a dinode
- * @dinode: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dinode_in(struct gfs_dinode *dinode, char *buf)
-{
- struct gfs_dinode *str = (struct gfs_dinode *) buf;
-
- gfs_meta_header_in(&dinode->di_header, buf);
-
- gfs_inum_in(&dinode->di_num, (char *) &str->di_num);
-
- CPIN_32(dinode, str, di_mode);
- CPIN_32(dinode, str, di_uid);
- CPIN_32(dinode, str, di_gid);
- CPIN_32(dinode, str, di_nlink);
- CPIN_64(dinode, str, di_size);
- CPIN_64(dinode, str, di_blocks);
- CPIN_64(dinode, str, di_atime);
- CPIN_64(dinode, str, di_mtime);
- CPIN_64(dinode, str, di_ctime);
- CPIN_32(dinode, str, di_major);
- CPIN_32(dinode, str, di_minor);
-
- CPIN_64(dinode, str, di_rgrp);
- CPIN_64(dinode, str, di_goal_rgrp);
- CPIN_32(dinode, str, di_goal_dblk);
- CPIN_32(dinode, str, di_goal_mblk);
- CPIN_32(dinode, str, di_flags);
- CPIN_32(dinode, str, di_payload_format);
- CPIN_16(dinode, str, di_type);
- CPIN_16(dinode, str, di_height);
- CPIN_32(dinode, str, di_incarn);
- CPIN_16(dinode, str, di_pad);
-
- CPIN_16(dinode, str, di_depth);
- CPIN_32(dinode, str, di_entries);
-
- gfs_inum_in(&dinode->di_next_unused, (char *) &str->di_next_unused);
-
- CPIN_64(dinode, str, di_eattr);
-
- CPIN_08(dinode, str, di_reserved, 56);
-
-}
-
-/**
- * gfs_dinode_out - Write out a dinode
- * @dinode: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dinode_out(struct gfs_dinode *dinode, char *buf)
-{
- struct gfs_dinode *str = (struct gfs_dinode *) buf;
-
- gfs_meta_header_out(&dinode->di_header, buf);
-
- gfs_inum_out(&dinode->di_num, (char *) &str->di_num);
-
- CPOUT_32(dinode, str, di_mode);
- CPOUT_32(dinode, str, di_uid);
- CPOUT_32(dinode, str, di_gid);
- CPOUT_32(dinode, str, di_nlink);
- CPOUT_64(dinode, str, di_size);
- CPOUT_64(dinode, str, di_blocks);
- CPOUT_64(dinode, str, di_atime);
- CPOUT_64(dinode, str, di_mtime);
- CPOUT_64(dinode, str, di_ctime);
- CPOUT_32(dinode, str, di_major);
- CPOUT_32(dinode, str, di_minor);
-
- CPOUT_64(dinode, str, di_rgrp);
- CPOUT_64(dinode, str, di_goal_rgrp);
- CPOUT_32(dinode, str, di_goal_dblk);
- CPOUT_32(dinode, str, di_goal_mblk);
- CPOUT_32(dinode, str, di_flags);
- CPOUT_32(dinode, str, di_payload_format);
- CPOUT_16(dinode, str, di_type);
- CPOUT_16(dinode, str, di_height);
- CPOUT_32(dinode, str, di_incarn);
- CPOUT_16(dinode, str, di_pad);
-
- CPOUT_16(dinode, str, di_depth);
- CPOUT_32(dinode, str, di_entries);
-
- gfs_inum_out(&dinode->di_next_unused, (char *) &str->di_next_unused);
-
- CPOUT_64(dinode, str, di_eattr);
-
- CPOUT_08(dinode, str, di_reserved, 56);
-
-}
-
-/**
- * gfs_dinode_print - Print out a dinode
- * @di: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_dinode_print(struct gfs_dinode *di, int console)
-{
-
- gfs_meta_header_print(&di->di_header, console);
-
- gfs_inum_print(&di->di_num, console);
-
- pv(di, di_mode, "0%o");
- pv(di, di_uid, "%u");
- pv(di, di_gid, "%u");
- pv(di, di_nlink, "%u");
- pv(di, di_size, "%" PRIu64);
- pv(di, di_blocks, "%" PRIu64);
- pv(di, di_atime, "%" PRId64);
- pv(di, di_mtime, "%" PRId64);
- pv(di, di_ctime, "%" PRId64);
- pv(di, di_major, "%u");
- pv(di, di_minor, "%u");
-
- pv(di, di_rgrp, "%" PRIu64);
- pv(di, di_goal_rgrp, "%" PRIu64);
- pv(di, di_goal_dblk, "%u");
- pv(di, di_goal_mblk, "%u");
- pv(di, di_flags, "0x%.8X");
- pv(di, di_payload_format, "%u");
- pv(di, di_type, "%u");
- pv(di, di_height, "%u");
- pv(di, di_incarn, "%u");
- pv(di, di_pad, "%u");
-
- pv(di, di_depth, "%u");
- pv(di, di_entries, "%u");
-
- gfs_inum_print(&di->di_next_unused, console);
-
- pv(di, di_eattr, "%" PRIu64);
-
- pa(di, di_reserved, 56);
-
-}
-
-/**
- * gfs_indirect_in - copy in the header of an indirect block
- * @indirect: the in memory copy
- * @buf: the buffer copy
- *
- */
-
-void
-gfs_indirect_in(struct gfs_indirect *indirect, char *buf)
-{
- struct gfs_indirect *str = (struct gfs_indirect *) buf;
-
- gfs_meta_header_in(&indirect->in_header, buf);
-
- CPIN_08(indirect, str, in_reserved, 64);
-
-}
-
-/**
- * gfs_indirect_out - copy out the header of an indirect block
- * @indirect: the in memory copy
- * @buf: the buffer copy
- *
- */
-
-void
-gfs_indirect_out(struct gfs_indirect *indirect, char *buf)
-{
- struct gfs_indirect *str = (struct gfs_indirect *) buf;
-
- gfs_meta_header_out(&indirect->in_header, buf);
-
- CPOUT_08(indirect, str, in_reserved, 64);
-
-}
-
-/**
- * gfs_indirect_print - Print out a indirect block header
- * @indirect: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_indirect_print(struct gfs_indirect *indirect, int console)
-{
-
- gfs_meta_header_print(&indirect->in_header, console);
-
- pa(indirect, in_reserved, 64);
-
-}
-
-/**
- * gfs_dirent_in - Read in a directory entry
- * @dirent: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dirent_in(struct gfs_dirent *dirent, char *buf)
-{
- struct gfs_dirent *str = (struct gfs_dirent *) buf;
-
- gfs_inum_in(&dirent->de_inum, (char *) &str->de_inum);
- CPIN_32(dirent, str, de_hash);
- CPIN_16(dirent, str, de_rec_len);
- CPIN_16(dirent, str, de_name_len);
- CPIN_16(dirent, str, de_type);
-
- CPIN_08(dirent, str, de_reserved, 14);
-
-}
-
-/**
- * gfs_dirent_out - Write out a directory entry
- * @dirent: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dirent_out(struct gfs_dirent *dirent, char *buf)
-{
- struct gfs_dirent *str = (struct gfs_dirent *) buf;
-
- gfs_inum_out(&dirent->de_inum, (char *) &str->de_inum);
- CPOUT_32(dirent, str, de_hash);
- CPOUT_16(dirent, str, de_rec_len);
- CPOUT_16(dirent, str, de_name_len);
- CPOUT_16(dirent, str, de_type);
-
- CPOUT_08(dirent, str, de_reserved, 14);
-
-}
-
-/**
- * gfs_dirent_print - Print out a directory entry
- * @de: the cpu-order buffer
- * @name: the filename
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_dirent_print(struct gfs_dirent *de, char *name, int console)
-{
- char buf[GFS_FNAMESIZE + 1];
-
- gfs_inum_print(&de->de_inum, console);
- pv(de, de_hash, "0x%.8X");
- pv(de, de_rec_len, "%u");
- pv(de, de_name_len, "%u");
- pv(de, de_type, "%u");
-
- pa(de, de_reserved, 14);
-
- memset(buf, 0, GFS_FNAMESIZE + 1);
- memcpy(buf, name, de->de_name_len);
- printk(" name = %s\n", buf);
-
-}
-
-/**
- * gfs_leaf_in - Read in a directory leaf header
- * @leaf: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_leaf_in(struct gfs_leaf *leaf, char *buf)
-{
- struct gfs_leaf *str = (struct gfs_leaf *) buf;
-
- gfs_meta_header_in(&leaf->lf_header, buf);
-
- CPIN_16(leaf, str, lf_depth);
- CPIN_16(leaf, str, lf_entries);
- CPIN_32(leaf, str, lf_dirent_format);
- CPIN_64(leaf, str, lf_next);
-
- CPIN_08(leaf, str, lf_reserved, 64);
-
-}
-
-/**
- * gfs_leaf_out - Write out a directory leaf header
- * @leaf: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_leaf_out(struct gfs_leaf *leaf, char *buf)
-{
- struct gfs_leaf *str = (struct gfs_leaf *) buf;
-
- gfs_meta_header_out(&leaf->lf_header, buf);
-
- CPOUT_16(leaf, str, lf_depth);
- CPOUT_16(leaf, str, lf_entries);
- CPOUT_32(leaf, str, lf_dirent_format);
- CPOUT_64(leaf, str, lf_next);
-
- CPOUT_08(leaf, str, lf_reserved, 64);
-
-}
-
-/**
- * gfs_leaf_print - Print out a directory leaf header
- * @lf: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_leaf_print(struct gfs_leaf *lf, int console)
-{
-
- gfs_meta_header_print(&lf->lf_header, console);
-
- pv(lf, lf_depth, "%u");
- pv(lf, lf_entries, "%u");
- pv(lf, lf_dirent_format, "%u");
- pv(lf, lf_next, "%" PRIu64);
-
- pa(lf, lf_reserved, 64);
-
-}
-
-/**
- * gfs_log_header_in - Read in a log header
- * @head: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_log_header_in(struct gfs_log_header *head, char *buf)
-{
- struct gfs_log_header *str = (struct gfs_log_header *) buf;
-
- gfs_meta_header_in(&head->lh_header, buf);
-
- CPIN_32(head, str, lh_flags);
- CPIN_32(head, str, lh_pad);
-
- CPIN_64(head, str, lh_first);
- CPIN_64(head, str, lh_sequence);
-
- CPIN_64(head, str, lh_tail);
- CPIN_64(head, str, lh_last_dump);
-
- CPIN_08(head, str, lh_reserved, 64);
-
-}
-
-/**
- * gfs_log_header_out - Write out a log header
- * @head: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_log_header_out(struct gfs_log_header *head, char *buf)
-{
- struct gfs_log_header *str = (struct gfs_log_header *) buf;
-
- gfs_meta_header_out(&head->lh_header, buf);
-
- CPOUT_32(head, str, lh_flags);
- CPOUT_32(head, str, lh_pad);
-
- CPOUT_64(head, str, lh_first);
- CPOUT_64(head, str, lh_sequence);
-
- CPOUT_64(head, str, lh_tail);
- CPOUT_64(head, str, lh_last_dump);
-
- CPOUT_08(head, str, lh_reserved, 64);
-
-}
-
-/**
- * gfs_log_header_print - Print out a log header
- * @head: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_log_header_print(struct gfs_log_header *lh, int console)
-{
-
- gfs_meta_header_print(&lh->lh_header, console);
-
- pv(lh, lh_flags, "0x%.8X");
- pv(lh, lh_pad, "%u");
-
- pv(lh, lh_first, "%" PRIu64);
- pv(lh, lh_sequence, "%" PRIu64);
-
- pv(lh, lh_tail, "%" PRIu64);
- pv(lh, lh_last_dump, "%" PRIu64);
-
- pa(lh, lh_reserved, 64);
-
-}
-
-/**
- * gfs_desc_in - Read in a log descriptor
- * @desc: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_desc_in(struct gfs_log_descriptor *desc, char *buf)
-{
- struct gfs_log_descriptor *str = (struct gfs_log_descriptor *) buf;
-
- gfs_meta_header_in(&desc->ld_header, buf);
-
- CPIN_32(desc, str, ld_type);
- CPIN_32(desc, str, ld_length);
- CPIN_32(desc, str, ld_data1);
- CPIN_32(desc, str, ld_data2);
-
- CPIN_08(desc, str, ld_reserved, 64);
-
-}
-
-/**
- * gfs_desc_out - Write out a log descriptor
- * @desc: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_desc_out(struct gfs_log_descriptor *desc, char *buf)
-{
- struct gfs_log_descriptor *str = (struct gfs_log_descriptor *) buf;
-
- gfs_meta_header_out(&desc->ld_header, buf);
-
- CPOUT_32(desc, str, ld_type);
- CPOUT_32(desc, str, ld_length);
- CPOUT_32(desc, str, ld_data1);
- CPOUT_32(desc, str, ld_data2);
-
- CPOUT_08(desc, str, ld_reserved, 64);
-
-}
-
-/**
- * gfs_desc_print - Print out a log descriptor
- * @ld: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_desc_print(struct gfs_log_descriptor *ld, int console)
-{
-
- gfs_meta_header_print(&ld->ld_header, console);
-
- pv(ld, ld_type, "%u");
- pv(ld, ld_length, "%u");
- pv(ld, ld_data1, "%u");
- pv(ld, ld_data2, "%u");
-
- pa(ld, ld_reserved, 64);
-
-}
-
-/**
- * gfs_block_tag_in - Read in a block tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_block_tag_in(struct gfs_block_tag *tag, char *buf)
-{
- struct gfs_block_tag *str = (struct gfs_block_tag *) buf;
-
- CPIN_64(tag, str, bt_blkno);
- CPIN_32(tag, str, bt_flags);
- CPIN_32(tag, str, bt_pad);
-
-}
-
-/**
- * gfs_block_tag_out - Write out a block tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_block_tag_out(struct gfs_block_tag *tag, char *buf)
-{
- struct gfs_block_tag *str = (struct gfs_block_tag *) buf;
-
- CPOUT_64(tag, str, bt_blkno);
- CPOUT_32(tag, str, bt_flags);
- CPOUT_32(tag, str, bt_pad);
-
-}
-
-/**
- * gfs_block_tag_print - Print out a block tag
- * @tag: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_block_tag_print(struct gfs_block_tag *tag, int console)
-{
-
- pv(tag, bt_blkno, "%" PRIu64);
- pv(tag, bt_flags, "%u");
- pv(tag, bt_pad, "%u");
-
-}
-
-/**
- * gfs_quota_tag_in - Read in a quota tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_tag_in(struct gfs_quota_tag *tag, char *buf)
-{
- struct gfs_quota_tag *str = (struct gfs_quota_tag *) buf;
-
- CPIN_64(tag, str, qt_change);
- CPIN_32(tag, str, qt_flags);
- CPIN_32(tag, str, qt_id);
-
-}
-
-/**
- * gfs_quota_tag_out - Write out a quota tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_tag_out(struct gfs_quota_tag *tag, char *buf)
-{
- struct gfs_quota_tag *str = (struct gfs_quota_tag *) buf;
-
- CPOUT_64(tag, str, qt_change);
- CPOUT_32(tag, str, qt_flags);
- CPOUT_32(tag, str, qt_id);
-
-}
-
-/**
- * gfs_quota_tag_print - Print out a quota tag
- * @tag: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_quota_tag_print(struct gfs_quota_tag *tag, int console)
-{
-
- pv(tag, qt_change, "%" PRId64);
- pv(tag, qt_flags, "0x%.8X");
- pv(tag, qt_id, "%u");
-
-}
-
-/**
- * gfs_ea_header_in - Read in a Extended Attribute header
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_ea_header_in(struct gfs_ea_header *ea, char *buf)
-{
- struct gfs_ea_header *str = (struct gfs_ea_header *) buf;
-
- CPIN_32(ea, str, ea_rec_len);
- CPIN_32(ea, str, ea_data_len);
- ea->ea_name_len = str->ea_name_len;
- ea->ea_type = str->ea_type;
- ea->ea_flags = str->ea_flags;
- ea->ea_num_ptrs = str->ea_num_ptrs;
- CPIN_32(ea, str, ea_pad);
-
-}
-
-/**
- * gfs_ea_header_out - Write out a Extended Attribute header
- * @ea: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_ea_header_out(struct gfs_ea_header *ea, char *buf)
-{
- struct gfs_ea_header *str = (struct gfs_ea_header *) buf;
-
- CPOUT_32(ea, str, ea_rec_len);
- CPOUT_32(ea, str, ea_data_len);
- str->ea_name_len = ea->ea_name_len;
- str->ea_type = ea->ea_type;
- str->ea_flags = ea->ea_flags;
- str->ea_num_ptrs = ea->ea_num_ptrs;
- CPOUT_32(ea, str, ea_pad);
-
-}
-
-/**
- * gfs_ea_header_printt - Print out a Extended Attribute header
- * @ea: the cpu-order buffer
- * @console - TRUE if this should be printed to the console,
- * FALSE if it should be just printed to the incore debug
- * buffer
- *
- */
-
-void
-gfs_ea_header_print(struct gfs_ea_header *ea, int console)
-{
-
- pv(ea, ea_rec_len, "%u");
- pv(ea, ea_data_len, "%u");
- pv(ea, ea_name_len, "%u");
- pv(ea, ea_type, "%u");
- pv(ea, ea_flags, "%u");
- pv(ea, ea_num_ptrs, "%u");
- pv(ea, ea_pad, "%u");
-
-}
-
-static const uint32_t crc_32_tab[] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,
- 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb,
- 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447,
- 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75,
- 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11,
- 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
- 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b,
- 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49,
- 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
- 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3,
- 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af,
- 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d,
- 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9,
- 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767,
- 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703,
- 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
- 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d,
- 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b,
- 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
- 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5,
- 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1,
- 0x5a05df1b, 0x2d02ef8d
-};
-
-/**
- * gfs_dir_hash - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * The hash function is a 32-bit CRC of the data. The algorithm uses
- * the crc_32_tab table above.
- *
- * This may not be the fastest hash function, but it does a fair bit better
- * at providing uniform results than the others I've looked at. That's
- * really important for efficient directories.
- *
- * Returns: the hash
- */
-
-uint32_t
-gfs_dir_hash(const char *data, int len)
-{
- uint32_t hash = 0xFFFFFFFF;
-
- for (; len--; data++)
- hash = crc_32_tab[(hash ^ *data) & 0xFF] ^ (hash >> 8);
-
- hash = ~hash;
-
- return hash;
-}
diff --git a/gfs/gfs_fsck/ondisk.h b/gfs/gfs_fsck/ondisk.h
deleted file mode 100644
index 01875c0..0000000
--- a/gfs/gfs_fsck/ondisk.h
+++ /dev/null
@@ -1,2045 +0,0 @@
-/*
- * On-disk structures.
- *
- * THE BIG PICTURE of on-disk layout:
- *
- * GFS filesystem code views the entire filesystem, including journals, as
- * one contiguous group of blocks on one (perhaps virtual) storage device.
- * The filesystem space is shared, not distributed; each node in the cluster
- * must see the entire filesystem space.
- *
- * If the filesystem is spread across multiple physical storage devices,
- * volume management (device mapping) must be used to present the fileystem
- * space to GFS as one (virtual) device, with contiguous blocks.
- *
- * The superblock contains basic information about the filesytem, and appears
- * at a location 64 KBytes into the filesystem. The first 64 KBytes of the
- * filesystem are empty, providing a safety buffer against wayward volume
- * management software (that sometimes write data into the first few bytes of
- * a device) or administrators.
- *
- * After the superblock, the rest of the filesystem is divided into multiple
- * Resource Groups and several journals.
- *
- * The Resource Groups (RGs or rgrps) contain the allocatable blocks that are
- * used for storing files, directories, etc., and all of the associated
- * metadata. Each RG has its own set of block allocation statistics (within
- * the RG header), a number of blocks containing the block allocation bitmap,
- * and a large number of allocatable blocks for file data and metadata.
- * Multiple RGs allow multiple nodes to simultaneously allocate blocks from the
- * filesystem (using different RGs), enhancing parallel access. RG size and
- * number of RGs are determined by gfs_mkfs when creating the filesystem.
- * An administrator can specify RG size (see man gfs_mkfs).
- *
- * The journals contain temporary copies of metadata blocks, along with
- * other data, that allow GFS to recover the filesystem to a consistent state
- * (at least as far as metadata is concerned) if a node fails in the midst
- * of performing a write transaction. There must be one journal for each node
- * in the cluster. Since access to the entire filesystem space is shared,
- * if a node crashes, another node will be able to read the crashed node's
- * journal, and perform recovery.
- *
- * Currently, gfs_mkfs places the journals right in the middle of a freshly
- * created filesystem space, between 2 large groups of RGs. From a filesystem
- * layout perspective, this placement is not a requirement; the journals
- * could be placed anywhere within the filesystem space.
- *
- * New Resource Groups and Journals may be added to the filesystem after the
- * filesystem has been created, if the filesystem's (virtual) device is made
- * larger. See man gfs_grow and gfs_jadd.
- *
- * A few special hidden inodes are contained in a GFS filesystem. They do
- * not appear in any directories; instead, the superblock points to them
- * using block numbers for their location. The special inodes are:
- *
- * Root inode: Root directory of the filesystem
- * Resource Group Index: A file containing block numbers and sizes of all RGs
- * Journal Index: A file containing block numbers and sizes of all journals
- * Quota: A file containing all quota information for the filesystem
- * License: A file containing license information
- *
- * Note that there is NOTHING RELATED TO INTER-NODE LOCK MANAGEMENT ON-DISK.
- * Locking is handled completely off-disk, typically via LAN.
- *
- * NOTE:
- * If you add 8 byte fields to these structures, they must be 8 byte
- * aligned. 4 byte field must be 4 byte aligned, etc...
- *
- * All structures must be a multiple of 8 bytes long.
- *
- * GRIPES:
- * We should have forgetten about supporting 512B FS block sizes
- * and made the di_reserved field in the struct gfs_dinode structure
- * much bigger.
- *
- * de_rec_len in struct gfs_dirent should really have been a 32-bit value
- * as it now limits us to a 64k FS block size (with the current code
- * in dir.c).
- */
-
-#ifndef __GFS_ONDISK_DOT_H__
-#define __GFS_ONDISK_DOT_H__
-
-#define GFS_MAGIC (0x01161970) /* for all on-disk headers */
-#define GFS_BASIC_BLOCK (512) /* "basic block" = "sector" = 512B */
-#define GFS_BASIC_BLOCK_SHIFT (9)
-
-/* Controls how much data can be logged in-core before dumping log to disk */
-
-#define GFS_DUMPS_PER_LOG (4) /* 1/4 of on-disk journal size*/
-
-/* Lock numbers of the LM_TYPE_NONDISK type. These protect certain
- * cluster-wide operations (rather than on-disk entities).
- * Currently, the LIVE lock is not used for any real purpose. */
-
-#define GFS_MOUNT_LOCK (0) /* only one node can Mount at a time */
-#define GFS_LIVE_LOCK (1) /* shared by all mounted nodes */
-#define GFS_TRANS_LOCK (2) /* Transaction, protects jrnl recovery */
-#define GFS_RENAME_LOCK (3) /* only one node can Rename at a time */
-
-/* On-disk format (version) numbers for various metadata types,
- * used in gfs_meta_header */
-
-#define GFS_FORMAT_SB (100) /* Super-Block */
-#define GFS_FORMAT_RG (200) /* Resource Group Header */
-#define GFS_FORMAT_RB (300) /* Resource Group Block Alloc BitBlock */
-#define GFS_FORMAT_DI (400) /* "Disk" inode (dinode) */
-#define GFS_FORMAT_IN (500) /* Indirect dinode block list */
-#define GFS_FORMAT_LF (600) /* Leaf dinode block list */
-#define GFS_FORMAT_JD (700) /* Journal Data */
-#define GFS_FORMAT_LH (800) /* Log Header */
-#define GFS_FORMAT_LD (900) /* Log Descriptor */
-/* These don't have actual struct gfs_meta_header structures to go with them */
-#define GFS_FORMAT_JI (1000) /* Journal Index */
-#define GFS_FORMAT_RI (1100) /* Resource Group Index */
-#define GFS_FORMAT_DE (1200) /* Directory Entry */
-#define GFS_FORMAT_QU (1500) /* Quota */
-#define GFS_FORMAT_EA (1600) /* Extended Attribute */
-#define GFS_FORMAT_ED (1700) /* Extended Attribute data */
-/* These version #s are embedded in the superblock */
-#define GFS_FORMAT_FS (1309) /* Filesystem (all-encompassing) */
-#define GFS_FORMAT_MULTI (1401) /* Multi-Host */
-
-/*
- * An on-disk inode number
- * Initially, the on-disk block address of the inode block is assigned as the
- * formal (permanent) ID as well. Block address can change (to move inode
- * on-disk), but formal ID must stay unchanged once assigned.
- */
-
-#define gfs_inum_equal(ino1, ino2) \
-(((ino1)->no_formal_ino == (ino2)->no_formal_ino) && \
- ((ino1)->no_addr == (ino2)->no_addr))
-
-struct gfs_inum {
- uint64_t no_formal_ino; /* inode identifier */
- uint64_t no_addr; /* block # of dinode block */
-};
-
-/*
- * Generic metadata head structure
- *
- * Every inplace buffer logged in the journal must start
- * with a struct gfs_meta_header.
- *
- * In addition to telling what kind of metadata is in the block,
- * the metaheader contains the important generation and incarnation
- * numbers.
- *
- * The generation number is used during journal recovery to determine
- * whether an in-place block on-disk is older than an on-disk journaled copy
- * of the block. If so, GFS overwrites the in-place block with the journaled
- * version of the block.
- *
- * A meta block's generation number must increment monotonically across the
- * cluster, each time new contents are committed to the block. This means
- * that whenever GFS allocates a pre-existing metadata block, GFS must read
- * that block from disk (in case another node has incremented it). It also
- * means that GFS must sync the block (with incremented generation number)
- * to disk (both log and in-place blocks), not only after changing contents
- * of the block, but also after de-allocating the block (GFS can't just throw
- * away incore metadata for a file that it's just erased).
- *
- * The incarnation number is used only for on-disk (d)inodes. GFS increments
- * it each time it de-allocates a dinode block (i.e. each time the dinode
- * loses its identity with a particular file, directory, etc.). When the
- * dinode is later allocated (i.e. to be identified with a new file, etc.),
- * GFS copies the incarnation number into the VFS inode's i_generation member.
- * If GFS is used as the backing store for an NFS server, GFS uses this
- * i_generation number as part of the NFS filehandle, which differentiates
- * it from the previous identity of the dinode, and helps protect against
- * filesystem corruption that could happen with the use of outdated,
- * invalid, or malicious filehandles. See ops_export.c.
- *
- * GFS caches de-allocated meta-headers, to minimize disk reads.
- * See struct gfs_meta_header_cache.
- */
-
-#define GFS_METATYPE_NONE (0)
-#define GFS_METATYPE_SB (1) /* Super-Block */
-#define GFS_METATYPE_RG (2) /* Resource Group Header */
-#define GFS_METATYPE_RB (3) /* Resource Group Block Alloc BitBlock */
-#define GFS_METATYPE_DI (4) /* "Disk" inode (dinode) */
-#define GFS_METATYPE_IN (5) /* Indirect dinode block list */
-#define GFS_METATYPE_LF (6) /* Leaf dinode block list */
-#define GFS_METATYPE_JD (7) /* Journal Data */
-#define GFS_METATYPE_LH (8) /* Log Header (gfs_log_header) */
-#define GFS_METATYPE_LD (9) /* Log Descriptor (gfs_log_descriptor) */
-#define GFS_METATYPE_EA (10) /* Extended Attribute */
-#define GFS_METATYPE_ED (11) /* Extended Attribute data */
-
-
-#define GFS_META_CLUMP (64) /* # blocks to convert fm data to meta */
-
-struct gfs_meta_header {
- uint32_t mh_magic; /* GFS_MAGIC sanity check magic number */
- uint32_t mh_type; /* GFS_METATYPE_XX type of metadata block */
- uint64_t mh_generation; /* increment before writing to journal */
- uint32_t mh_format; /* GFS_FORMAT_XX (version # for this type) */
- uint32_t mh_incarn; /* increment when marking dinode "unused" */
-};
-
-/*
- * super-block structure
- *
- * One of these is at beginning of filesystem.
- * It's probably good if SIZEOF_SB <= GFS_BASIC_BLOCK (512 bytes)
- */
-
-/* Address of SuperBlock in GFS basic blocks. 1st 64K of filesystem is empty
- for safety against getting clobbered by wayward volume managers, etc.
- 64k was chosen because it's the largest GFS-supported fs block size. */
-#define GFS_SB_ADDR (128)
-
-/* The lock number for the superblock (must be zero) */
-#define GFS_SB_LOCK (0)
-#define GFS_CRAP_LOCK (1)
-
-/* Requirement: GFS_LOCKNAME_LEN % 8 == 0
- Includes: the fencing zero at the end */
-#define GFS_LOCKNAME_LEN (64)
-
-struct gfs_sb {
- /* Order is important; need to be able to read old superblocks
- in order to support on-disk version upgrades */
- struct gfs_meta_header sb_header;
-
- uint32_t sb_fs_format; /* GFS_FORMAT_FS (on-disk version) */
- uint32_t sb_multihost_format; /* GFS_FORMAT_MULTI */
- uint32_t sb_flags; /* ?? */
-
- uint32_t sb_bsize; /* fundamental FS block size in bytes */
- uint32_t sb_bsize_shift; /* log2(sb_bsize) */
- uint32_t sb_seg_size; /* Journal segment size in FS blocks */
-
- /* These special inodes do not appear in any on-disk directory. */
- struct gfs_inum sb_jindex_di; /* journal index inode */
- struct gfs_inum sb_rindex_di; /* resource group index inode */
- struct gfs_inum sb_root_di; /* root directory inode */
-
- /* Default inter-node locking protocol (lock module) and namespace */
- char sb_lockproto[GFS_LOCKNAME_LEN]; /* lock protocol name */
- char sb_locktable[GFS_LOCKNAME_LEN]; /* unique name for this FS */
-
- /* More special inodes */
- struct gfs_inum sb_quota_di; /* quota inode */
- struct gfs_inum sb_license_di; /* license inode */
-
- char sb_reserved[96];
-};
-
-/*
- * journal index structure
- *
- * One for each journal used by the filesystem.
- * These descriptors are packed contiguously within the jindex inode (file).
- */
-
-struct gfs_jindex {
- uint64_t ji_addr; /* starting block of the journal */
- uint32_t ji_nsegment; /* number (quantity) of segments in journal */
- uint32_t ji_pad;
-
- char ji_reserved[64];
-};
-
-/*
- * resource index structure
- *
- * One of these for each resource group in the filesystem.
- * These descriptors are packed contiguously within the rindex inode (file).
- * Also see struct gfs_rgrp.
- */
-
-struct gfs_rindex {
- uint64_t ri_addr; /* block # of 1st block (header) in rgrp */
- uint32_t ri_length; /* # fs blocks containing rgrp header & bitmap */
- uint32_t ri_pad;
-
- uint64_t ri_data1; /* block # of first data/meta block in rgrp */
- uint32_t ri_data; /* number (qty) of data/meta blocks in rgrp */
-
- uint32_t ri_bitbytes; /* total # bytes used by block alloc bitmap */
-
- char ri_reserved[64];
-};
-
-/*
- * resource group header structure
- *
- * One of these at beginning of the first block of an rgrp,
- * followed by block alloc bitmap data in remainder of first block.
- * Each resource group contains:
- * Header block, including block allocation statistics (struct gfs_rgrp)
- * and first part of block alloc bitmap.
- * Bitmap block(s), continuing block alloc bitmap started in header block.
- * Data/meta blocks, allocatable blocks containing file data and metadata.
- *
- * In older versions, now-unused (but previously allocated) dinodes were
- * saved for re-use in an on-disk linked list (chain). This is no longer
- * done, but support still exists for reclaiming dinodes from this list,
- * to support upgrades from older on-disk formats.
- */
-
-/* Each data block within rgrp is represented by 2 bits in the alloc bitmap */
-#define GFS_NBBY (4) /* # blocks represented by 1 bitmap byte */
-#define GFS_BIT_SIZE (2)
-#define GFS_BIT_MASK (0x00000003)
-
-/*
- * 4 possible block allocation states:
- * bit 0 = alloc(1)/free(0)
- * bit 1 = metadata(1)/data(0)
- */
-#define GFS_BLKST_FREE (0)
-#define GFS_BLKST_USED (1)
-#define GFS_BLKST_FREEMETA (2)
-#define GFS_BLKST_USEDMETA (3)
-
-struct gfs_rgrp {
- struct gfs_meta_header rg_header;
-
- uint32_t rg_flags; /* ?? */
-
- uint32_t rg_free; /* Number (qty) of free data blocks */
-
- /* Dinodes are USEDMETA, but are handled separately from other METAs */
- uint32_t rg_useddi; /* Number (qty) of dinodes (used or free) */
- uint32_t rg_freedi; /* Number (qty) of unused (free) dinodes */
- struct gfs_inum rg_freedi_list; /* 1st block in chain of free dinodes */
-
- /* These META statistics do not include dinodes (used or free) */
- uint32_t rg_usedmeta; /* Number (qty) of used metadata blocks */
- uint32_t rg_freemeta; /* Number (qty) of unused metadata blocks */
-
- char rg_reserved[64];
-};
-
-/*
- * quota structure
- */
-
-struct gfs_quota {
- uint64_t qu_limit;
- uint64_t qu_warn;
- int64_t qu_value;
-
- char qu_reserved[64];
-};
-
-/*
- * dinode (disk inode) structure
- * The ondisk representation of inodes
- * One for each file, directory, etc.
- * GFS does not put more than one inode in a single block.
- * The inode may be "stuffed", carrying file data along with metadata,
- * if the file data is small enough.
- * Otherwise, the inode block contains pointers to other blocks that contain
- * either file data or other pointers to other blocks (indirect addressing
- * via a metadata tree).
- */
-
-#define GFS_MAX_META_HEIGHT (10)
-#define GFS_DIR_MAX_DEPTH (17)
-
-/* Dinode types */
-#define GFS_FILE_NON (0)
-#define GFS_FILE_REG (1) /* regular file */
-#define GFS_FILE_DIR (2) /* directory */
-#define GFS_FILE_LNK (5) /* link */
-#define GFS_FILE_BLK (7) /* block device node */
-#define GFS_FILE_CHR (8) /* character device node */
-#define GFS_FILE_FIFO (101) /* fifo/pipe */
-#define GFS_FILE_SOCK (102) /* socket */
-
-/* Dinode flags */
-#define GFS_DIF_JDATA (0x00000001) /* jrnl all data for this file */
-#define GFS_DIF_EXHASH (0x00000002) /* hashed directory (leaves) */
-#define GFS_DIF_UNUSED (0x00000004) /* unused dinode */
-#define GFS_DIF_EA_INDIRECT (0x00000008) /* extended attribute, indirect*/
-#define GFS_DIF_DIRECTIO (0x00000010)
-#define GFS_DIF_IMMUTABLE (0x00000020) /* Can't change file */
-#define GFS_DIF_APPENDONLY (0x00000040) /* Can only add to end of file */
-#define GFS_DIF_NOATIME (0x00000080) /* Don't update access time
- (currently unused/ignored) */
-#define GFS_DIF_SYNC (0x00000100) /* Flush to disk, don't cache
- (currently unused/ignored) */
-#define GFS_DIF_INHERIT_DIRECTIO (0x40000000) /* new files get DIRECTIO flag */
-#define GFS_DIF_INHERIT_JDATA (0x80000000) /* new files get JDATA flag */
-
-struct gfs_dinode {
- struct gfs_meta_header di_header;
-
- struct gfs_inum di_num; /* formal inode # and block address */
-
- uint32_t di_mode; /* mode of file */
- uint32_t di_uid; /* owner's user id */
- uint32_t di_gid; /* owner's group id */
- uint32_t di_nlink; /* number (qty) of links to this file */
- uint64_t di_size; /* number (qty) of bytes in file */
- uint64_t di_blocks; /* number (qty) of blocks in file */
- int64_t di_atime; /* time last accessed */
- int64_t di_mtime; /* time last modified */
- int64_t di_ctime; /* time last changed */
-
- /* Non-zero only for character or block device nodes */
- uint32_t di_major; /* device major number */
- uint32_t di_minor; /* device minor number */
-
- /* Block allocation strategy */
- uint64_t di_rgrp; /* dinode rgrp block number */
- uint64_t di_goal_rgrp; /* rgrp to alloc from next */
- uint32_t di_goal_dblk; /* data block goal */
- uint32_t di_goal_mblk; /* metadata block goal */
-
- uint32_t di_flags; /* GFS_DIF_... */
-
- /* struct gfs_rindex, struct gfs_jindex, or struct gfs_dirent */
- uint32_t di_payload_format; /* GFS_FORMAT_... */
- uint16_t di_type; /* GFS_FILE_... type of file */
- uint16_t di_height; /* height of metadata (0 == stuffed) */
- uint32_t di_incarn; /* incarnation (unused, see gfs_meta_header) */
- uint16_t di_pad;
-
- /* These only apply to directories */
- uint16_t di_depth; /* Number of bits in the table */
- uint32_t di_entries; /* The # (qty) of entries in the directory */
-
- /* This formed an on-disk chain of unused dinodes */
- struct gfs_inum di_next_unused; /* used in old versions only */
-
- uint64_t di_eattr; /* extended attribute block number */
-
- char di_reserved[56];
-};
-
-/*
- * indirect block header
- *
- * A component of a dinode's indirect addressing metadata tree.
- * These are pointed to by pointers in dinodes or other indirect blocks.
- */
-
-struct gfs_indirect {
- struct gfs_meta_header in_header;
-
- char in_reserved[64];
-};
-
-/*
- * directory structure - many of these per directory file
- *
- * See comments at beginning of dir.c
- */
-
-#define GFS_FNAMESIZE (255)
-#define GFS_DIRENT_SIZE(name_len) ((sizeof(struct gfs_dirent) + (name_len) + 7) & ~7)
-
-struct gfs_dirent {
- struct gfs_inum de_inum; /* formal inode number and block address */
- uint32_t de_hash; /* hash of the filename */
- uint16_t de_rec_len; /* the length of the dirent */
- uint16_t de_name_len; /* the length of the name */
- uint16_t de_type; /* GFS_FILE_... type of dinode this points to */
-
- char de_reserved[14];
-};
-
-/*
- * Header of leaf directory nodes
- *
- * See comments at beginning of dir.c
- */
-
-struct gfs_leaf {
- struct gfs_meta_header lf_header;
-
- uint16_t lf_depth; /* Depth of leaf */
- uint16_t lf_entries; /* Number of dirents in leaf */
- uint32_t lf_dirent_format; /* GFS_FORMAT_DE (version #) */
- uint64_t lf_next; /* Next leaf, if overflow */
-
- char lf_reserved[64];
-};
-
-/*
- * Log header structure
- *
- * Two of these are in the first block of a transaction log:
- * 1) at beginning of block
- * 2) at end of first 512-byte sector within block
- */
-
-#define GFS_LOG_HEAD_UNMOUNT (0x00000001) /* log is clean, can unmount fs */
-
-struct gfs_log_header {
- struct gfs_meta_header lh_header;
-
- uint32_t lh_flags; /* GFS_LOG_HEAD_... */
- uint32_t lh_pad;
-
- uint64_t lh_first; /* Block number of first header in this trans */
- uint64_t lh_sequence; /* Sequence number of this transaction */
-
- uint64_t lh_tail; /* Block number of log tail */
- uint64_t lh_last_dump; /* Block number of last dump */
-
- char lh_reserved[64];
-};
-
-/*
- * Log type descriptor
- *
- * One of these for each chunk in a transaction
- */
-
-#define GFS_LOG_DESC_METADATA (300) /* metadata */
-/* ld_data1 is the number (quantity) of metadata blocks in the descriptor.
- ld_data2 is unused.
- */
-
-#define GFS_LOG_DESC_IUL (400) /* unlinked inode */
-/* ld_data1 is TRUE if this is a dump.
- ld_data2 is unused.
- FixMe!!! ld_data1 should be the number (quantity) of entries.
- ld_data2 should be "TRUE if this is a dump".
- */
-
-#define GFS_LOG_DESC_IDA (401) /* de-allocated inode */
-/* ld_data1 is unused.
- ld_data2 is unused.
- FixMe!!! ld_data1 should be the number (quantity) of entries.
- */
-
-#define GFS_LOG_DESC_Q (402) /* quota */
-/* ld_data1 is the number of quota changes in the descriptor.
- ld_data2 is TRUE if this is a dump.
- */
-
-#define GFS_LOG_DESC_LAST (500) /* final in a logged transaction */
-/* ld_data1 is unused.
- ld_data2 is unused.
- */
-
-struct gfs_log_descriptor {
- struct gfs_meta_header ld_header;
-
- uint32_t ld_type; /* GFS_LOG_DESC_... Type of this log chunk */
- uint32_t ld_length; /* Number of buffers in this chunk */
- uint32_t ld_data1; /* descriptor-specific field */
- uint32_t ld_data2; /* descriptor-specific field */
-
- char ld_reserved[64];
-};
-
-/*
- * Metadata block tags
- *
- * One for each logged block. Tells where block really belongs on-disk.
- * These descriptor tags are packed contiguously after a gfs_log_descriptor.
- */
-
-struct gfs_block_tag {
- uint64_t bt_blkno; /* inplace block number */
- uint32_t bt_flags; /* ?? */
- uint32_t bt_pad;
-};
-
-/*
- * Quota Journal Tag
- */
-
-#define GFS_QTF_USER (0x00000001)
-
-struct gfs_quota_tag {
- int64_t qt_change;
- uint32_t qt_flags; /* GFS_QTF_... */
- uint32_t qt_id;
-};
-
-/*
- * Extended attribute header format
- */
-
-#define GFS_EA_MAX_NAME_LEN (255)
-#define GFS_EA_MAX_DATA_LEN (65536)
-
-#define GFS_EATYPE_UNUSED (0)
-#define GFS_EATYPE_USR (1) /* user attribute */
-#define GFS_EATYPE_SYS (2) /* system attribute */
-#define GFS_EATYPE_SECURITY (3) /* security attribute */
-
-#define GFS_EATYPE_LAST (3)
-#define GFS_EATYPE_VALID(x) ((x) <= GFS_EATYPE_LAST)
-
-#define GFS_EAFLAG_LAST (0x01) /* last ea in block */
-
-struct gfs_ea_header {
- uint32_t ea_rec_len; /* total record length: hdr + name + data */
- uint32_t ea_data_len; /* data length, in bytes */
- uint8_t ea_name_len; /* no NULL pointer after the string */
- uint8_t ea_type; /* GFS_EATYPE_... */
- uint8_t ea_flags; /* GFS_EAFLAG_... */
- uint8_t ea_num_ptrs; /* # fs blocks needed for EA */
- uint32_t ea_pad;
-};
-
-/* Endian functions */
-
-#define GFS_ENDIAN_BIG
-
-#ifdef GFS_ENDIAN_BIG
-
-#define gfs16_to_cpu be16_to_cpu
-#define gfs32_to_cpu be32_to_cpu
-#define gfs64_to_cpu be64_to_cpu
-
-#define cpu_to_gfs16 cpu_to_be16
-#define cpu_to_gfs32 cpu_to_be32
-#define cpu_to_gfs64 cpu_to_be64
-
-#else /* GFS_ENDIAN_BIG */
-
-#define gfs16_to_cpu le16_to_cpu
-#define gfs32_to_cpu le32_to_cpu
-#define gfs64_to_cpu le64_to_cpu
-
-#define cpu_to_gfs16 cpu_to_le16
-#define cpu_to_gfs32 cpu_to_le32
-#define cpu_to_gfs64 cpu_to_le64
-
-#endif /* GFS_ENDIAN_BIG */
-
-/* Translation functions */
-
-void gfs_inum_in(struct gfs_inum *no, char *buf);
-void gfs_inum_out(struct gfs_inum *no, char *buf);
-void gfs_meta_header_in(struct gfs_meta_header *mh, char *buf);
-void gfs_meta_header_out(struct gfs_meta_header *mh, char *buf);
-void gfs_sb_in(struct gfs_sb *sb, char *buf);
-void gfs_sb_out(struct gfs_sb *sb, char *buf);
-void gfs_jindex_in(struct gfs_jindex *jindex, char *buf);
-void gfs_jindex_out(struct gfs_jindex *jindex, char *buf);
-void gfs_rindex_in(struct gfs_rindex *rindex, char *buf);
-void gfs_rindex_out(struct gfs_rindex *rindex, char *buf);
-void gfs_rgrp_in(struct gfs_rgrp *rgrp, char *buf);
-void gfs_rgrp_out(struct gfs_rgrp *rgrp, char *buf);
-void gfs_quota_in(struct gfs_quota *quota, char *buf);
-void gfs_quota_out(struct gfs_quota *quota, char *buf);
-void gfs_dinode_in(struct gfs_dinode *dinode, char *buf);
-void gfs_dinode_out(struct gfs_dinode *dinode, char *buf);
-void gfs_indirect_in(struct gfs_indirect *indirect, char *buf);
-void gfs_indirect_out(struct gfs_indirect *indirect, char *buf);
-void gfs_dirent_in(struct gfs_dirent *dirent, char *buf);
-void gfs_dirent_out(struct gfs_dirent *dirent, char *buf);
-void gfs_leaf_in(struct gfs_leaf *leaf, char *buf);
-void gfs_leaf_out(struct gfs_leaf *leaf, char *buf);
-void gfs_log_header_in(struct gfs_log_header *head, char *buf);
-void gfs_log_header_out(struct gfs_log_header *head, char *buf);
-void gfs_desc_in(struct gfs_log_descriptor *desc, char *buf);
-void gfs_desc_out(struct gfs_log_descriptor *desc, char *buf);
-void gfs_block_tag_in(struct gfs_block_tag *btag, char *buf);
-void gfs_block_tag_out(struct gfs_block_tag *btag, char *buf);
-void gfs_quota_tag_in(struct gfs_quota_tag *qtag, char *buf);
-void gfs_quota_tag_out(struct gfs_quota_tag *qtag, char *buf);
-void gfs_ea_header_in(struct gfs_ea_header *qtag, char *buf);
-void gfs_ea_header_out(struct gfs_ea_header *qtag, char *buf);
-
-/* Printing functions */
-
-void gfs_inum_print(struct gfs_inum *no, int console);
-void gfs_meta_header_print(struct gfs_meta_header *mh, int console);
-void gfs_sb_print(struct gfs_sb *sb, int console);
-void gfs_jindex_print(struct gfs_jindex *jindex, int console);
-void gfs_rindex_print(struct gfs_rindex *rindex, int console);
-void gfs_rgrp_print(struct gfs_rgrp *rgrp, int console);
-void gfs_quota_print(struct gfs_quota *quota, int console);
-void gfs_dinode_print(struct gfs_dinode *dinode, int console);
-void gfs_indirect_print(struct gfs_indirect *indirect, int console);
-void gfs_dirent_print(struct gfs_dirent *dirent, char *name, int console);
-void gfs_leaf_print(struct gfs_leaf *leaf, int console);
-void gfs_log_header_print(struct gfs_log_header *head, int console);
-void gfs_desc_print(struct gfs_log_descriptor *desc, int console);
-void gfs_block_tag_print(struct gfs_block_tag *tag, int console);
-void gfs_quota_tag_print(struct gfs_quota_tag *tag, int console);
-void gfs_ea_header_print(struct gfs_ea_header *ea, int console);
-
-/* The hash function for ExHash directories */
-
-uint32_t gfs_dir_hash(const char *data, int len);
-
-#endif /* __GFS_ONDISK_DOT_H__ */
-
-
-
-#ifdef WANT_GFS_CONVERSION_FUNCTIONS
-
-#define CPIN_08(s1, s2, member, count) {memcpy((s1->member), (s2->member), (count));}
-#define CPOUT_08(s1, s2, member, count) {memcpy((s2->member), (s1->member), (count));}
-#define CPIN_16(s1, s2, member) {(s1->member) = gfs16_to_cpu((s2->member));}
-#define CPOUT_16(s1, s2, member) {(s2->member) = cpu_to_gfs16((s1->member));}
-#define CPIN_32(s1, s2, member) {(s1->member) = gfs32_to_cpu((s2->member));}
-#define CPOUT_32(s1, s2, member) {(s2->member) = cpu_to_gfs32((s1->member));}
-#define CPIN_64(s1, s2, member) {(s1->member) = gfs64_to_cpu((s2->member));}
-#define CPOUT_64(s1, s2, member) {(s2->member) = cpu_to_gfs64((s1->member));}
-
-#define pa(struct, member, count) print_array(#member, struct->member, count);
-
-/**
- * print_array - Print out an array of bytes
- * @title: what to print before the array
- * @buf: the array
- * @count: the number of bytes
- *
- */
-
-static void
-print_array(char *title, char *buf, int count)
-{
- ENTER(GFN_PRINT_ARRAY)
- int x;
-
- printk(" %s =\n", title);
- for (x = 0; x < count; x++) {
- printk("%.2X ", (unsigned char)buf[x]);
- if (x % 16 == 15)
- printk("\n");
- }
- if (x % 16)
- printk("\n");
-
- RET(GFN_PRINT_ARRAY);
-}
-
-/**
- * gfs_inum_in - Read in an inode number
- * @no: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_inum_in(struct gfs_inum *no, char *buf)
-{
- ENTER(GFN_INUM_IN)
- struct gfs_inum *str = (struct gfs_inum *)buf;
-
- CPIN_64(no, str, no_formal_ino);
- CPIN_64(no, str, no_addr);
-
- RET(GFN_INUM_IN);
-}
-
-/**
- * gfs_inum_out - Write out an inode number
- * @no: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_inum_out(struct gfs_inum *no, char *buf)
-{
- ENTER(GFN_INUM_OUT)
- struct gfs_inum *str = (struct gfs_inum *)buf;
-
- CPOUT_64(no, str, no_formal_ino);
- CPOUT_64(no, str, no_addr);
-
- RET(GFN_INUM_OUT);
-}
-
-/**
- * gfs_inum_print - Print out a inode number
- * @no: the cpu-order buffer
- *
- */
-
-void
-gfs_inum_print(struct gfs_inum *no)
-{
- ENTER(GFN_INUM_PRINT)
- pv(no, no_formal_ino, "%"PRIu64);
- pv(no, no_addr, "%"PRIu64);
- RET(GFN_INUM_PRINT);
-}
-
-/**
- * gfs_meta_header_in - Read in a metadata header
- * @mh: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_meta_header_in(struct gfs_meta_header *mh, char *buf)
-{
- ENTER(GFN_META_HEADER_IN)
- struct gfs_meta_header *str = (struct gfs_meta_header *)buf;
-
- CPIN_32(mh, str, mh_magic);
- CPIN_32(mh, str, mh_type);
- CPIN_64(mh, str, mh_generation);
- CPIN_32(mh, str, mh_format);
- CPIN_32(mh, str, mh_incarn);
-
- RET(GFN_META_HEADER_IN);
-}
-
-/**
- * gfs_meta_header_in - Write out a metadata header
- * @mh: the cpu-order structure
- * @buf: the disk-order buffer
- *
- * Don't ever change the generation number in this routine.
- * It's done manually in increment_generation().
- */
-
-void
-gfs_meta_header_out(struct gfs_meta_header *mh, char *buf)
-{
- ENTER(GFN_META_HEADER_OUT)
- struct gfs_meta_header *str = (struct gfs_meta_header *)buf;
-
- CPOUT_32(mh, str, mh_magic);
- CPOUT_32(mh, str, mh_type);
-#if 0
- /* Don't do this!
- Mh_generation should only be change manually. */
- CPOUT_64(mh, str, mh_generation);
-#endif
- CPOUT_32(mh, str, mh_format);
- CPOUT_32(mh, str, mh_incarn);
-
- RET(GFN_META_HEADER_OUT);
-}
-
-/**
- * gfs_meta_header_print - Print out a metadata header
- * @mh: the cpu-order buffer
- *
- */
-
-void
-gfs_meta_header_print(struct gfs_meta_header *mh)
-{
- ENTER(GFN_META_HEADER_PRINT)
-
- pv(mh, mh_magic, "0x%.8X");
- pv(mh, mh_type, "%u");
- pv(mh, mh_generation, "%"PRIu64);
- pv(mh, mh_format, "%u");
- pv(mh, mh_incarn, "%u");
-
- RET(GFN_META_HEADER_PRINT);
-}
-
-/**
- * gfs_sb_in - Read in a superblock
- * @sb: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_sb_in(struct gfs_sb *sb, char *buf)
-{
- ENTER(GFN_SB_IN)
- struct gfs_sb *str = (struct gfs_sb *)buf;
-
- gfs_meta_header_in(&sb->sb_header, buf);
-
- CPIN_32(sb, str, sb_fs_format);
- CPIN_32(sb, str, sb_multihost_format);
- CPIN_32(sb, str, sb_flags);
-
- CPIN_32(sb, str, sb_bsize);
- CPIN_32(sb, str, sb_bsize_shift);
- CPIN_32(sb, str, sb_seg_size);
-
- gfs_inum_in(&sb->sb_jindex_di, (char *)&str->sb_jindex_di);
- gfs_inum_in(&sb->sb_rindex_di, (char *)&str->sb_rindex_di);
- gfs_inum_in(&sb->sb_root_di, (char *)&str->sb_root_di);
-
- CPIN_08(sb, str, sb_lockproto, GFS_LOCKNAME_LEN);
- CPIN_08(sb, str, sb_locktable, GFS_LOCKNAME_LEN);
-
- gfs_inum_in(&sb->sb_quota_di, (char *)&str->sb_quota_di);
- gfs_inum_in(&sb->sb_license_di, (char *)&str->sb_license_di);
-
- CPIN_08(sb, str, sb_reserved, 96);
-
- RET(GFN_SB_IN);
-}
-
-/**
- * gfs_sb_out - Write out a superblock
- * @sb: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_sb_out(struct gfs_sb *sb, char *buf)
-{
- ENTER(GFN_SB_OUT)
- struct gfs_sb *str = (struct gfs_sb *)buf;
-
- gfs_meta_header_out(&sb->sb_header, buf);
-
- CPOUT_32(sb, str, sb_fs_format);
- CPOUT_32(sb, str, sb_multihost_format);
- CPOUT_32(sb, str, sb_flags);
-
- CPOUT_32(sb, str, sb_bsize);
- CPOUT_32(sb, str, sb_bsize_shift);
- CPOUT_32(sb, str, sb_seg_size);
-
- gfs_inum_out(&sb->sb_jindex_di, (char *)&str->sb_jindex_di);
- gfs_inum_out(&sb->sb_rindex_di, (char *)&str->sb_rindex_di);
- gfs_inum_out(&sb->sb_root_di, (char *)&str->sb_root_di);
-
- CPOUT_08(sb, str, sb_lockproto, GFS_LOCKNAME_LEN);
- CPOUT_08(sb, str, sb_locktable, GFS_LOCKNAME_LEN);
-
- gfs_inum_out(&sb->sb_quota_di, (char *)&str->sb_quota_di);
- gfs_inum_out(&sb->sb_license_di, (char *)&str->sb_license_di);
-
- CPOUT_08(sb, str, sb_reserved, 96);
-
- RET(GFN_SB_OUT);
-}
-
-/**
- * gfs_sb_print - Print out a superblock
- * @sb: the cpu-order buffer
- *
- */
-
-void
-gfs_sb_print(struct gfs_sb *sb)
-{
- ENTER(GFN_SB_PRINT)
-
- gfs_meta_header_print(&sb->sb_header);
-
- pv(sb, sb_fs_format, "%u");
- pv(sb, sb_multihost_format, "%u");
- pv(sb, sb_flags, "%u");
-
- pv(sb, sb_bsize, "%u");
- pv(sb, sb_bsize_shift, "%u");
- pv(sb, sb_seg_size, "%u");
-
- gfs_inum_print(&sb->sb_jindex_di);
- gfs_inum_print(&sb->sb_rindex_di);
- gfs_inum_print(&sb->sb_root_di);
-
- pv(sb, sb_lockproto, "%s");
- pv(sb, sb_locktable, "%s");
-
- gfs_inum_print(&sb->sb_quota_di);
- gfs_inum_print(&sb->sb_license_di);
-
- pa(sb, sb_reserved, 96);
-
- RET(GFN_SB_PRINT);
-}
-
-/**
- * gfs_jindex_in - Read in a journal index structure
- * @jindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_jindex_in(struct gfs_jindex *jindex, char *buf)
-{
- ENTER(GFN_JINDEX_IN)
- struct gfs_jindex *str = (struct gfs_jindex *)buf;
-
- CPIN_64(jindex, str, ji_addr);
- CPIN_32(jindex, str, ji_nsegment);
- CPIN_32(jindex, str, ji_pad);
-
- CPIN_08(jindex, str, ji_reserved, 64);
-
- RET(GFN_JINDEX_IN);
-}
-
-/**
- * gfs_jindex_out - Write out a journal index structure
- * @jindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_jindex_out(struct gfs_jindex *jindex, char *buf)
-{
- ENTER(GFN_JINDEX_OUT)
- struct gfs_jindex *str = (struct gfs_jindex *)buf;
-
- CPOUT_64(jindex, str, ji_addr);
- CPOUT_32(jindex, str, ji_nsegment);
- CPOUT_32(jindex, str, ji_pad);
-
- CPOUT_08(jindex, str, ji_reserved, 64);
-
- RET(GFN_JINDEX_OUT);
-}
-
-/**
- * gfs_jindex_print - Print out a journal index structure
- * @ji: the cpu-order buffer
- *
- */
-
-void
-gfs_jindex_print(struct gfs_jindex *ji)
-{
- ENTER(GFN_JINDEX_PRINT)
-
- pv(ji, ji_addr, "%"PRIu64);
- pv(ji, ji_nsegment, "%u");
- pv(ji, ji_pad, "%u");
-
- pa(ji, ji_reserved, 64);
-
- RET(GFN_JINDEX_PRINT);
-}
-
-/**
- * gfs_rindex_in - Read in a resource index structure
- * @rindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rindex_in(struct gfs_rindex *rindex, char *buf)
-{
- ENTER(GFN_RINDEX_IN)
- struct gfs_rindex *str = (struct gfs_rindex *)buf;
-
- CPIN_64(rindex, str, ri_addr);
- CPIN_32(rindex, str, ri_length);
- CPIN_32(rindex, str, ri_pad);
-
- CPIN_64(rindex, str, ri_data1);
- CPIN_32(rindex, str, ri_data);
-
- CPIN_32(rindex, str, ri_bitbytes);
-
- CPIN_08(rindex, str, ri_reserved, 64);
-
- RET(GFN_RINDEX_IN);
-}
-
-/**
- * gfs_rindex_out - Write out a resource index structure
- * @rindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rindex_out(struct gfs_rindex *rindex, char *buf)
-{
- ENTER(GFN_RINDEX_OUT)
- struct gfs_rindex *str = (struct gfs_rindex *)buf;
-
- CPOUT_64(rindex, str, ri_addr);
- CPOUT_32(rindex, str, ri_length);
- CPOUT_32(rindex, str, ri_pad);
-
- CPOUT_64(rindex, str, ri_data1);
- CPOUT_32(rindex, str, ri_data);
-
- CPOUT_32(rindex, str, ri_bitbytes);
-
- CPOUT_08(rindex, str, ri_reserved, 64);
-
- RET(GFN_RINDEX_OUT);
-}
-
-/**
- * gfs_rindex_print - Print out a resource index structure
- * @ri: the cpu-order buffer
- *
- */
-
-void
-gfs_rindex_print(struct gfs_rindex *ri)
-{
- ENTER(GFN_RINDEX_PRINT)
-
- pv(ri, ri_addr, "%"PRIu64);
- pv(ri, ri_length, "%u");
- pv(ri, ri_pad, "%u");
-
- pv(ri, ri_data1, "%"PRIu64);
- pv(ri, ri_data, "%u");
-
- pv(ri, ri_bitbytes, "%u");
-
- pa(ri, ri_reserved, 64);
-
- RET(GFN_RINDEX_PRINT);
-}
-
-/**
- * gfs_rgrp_in - Read in a resource group header
- * @rgrp: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rgrp_in(struct gfs_rgrp *rgrp, char *buf)
-{
- ENTER(GFN_RGRP_IN)
- struct gfs_rgrp *str = (struct gfs_rgrp *)buf;
-
- gfs_meta_header_in(&rgrp->rg_header, buf);
-
- CPIN_32(rgrp, str, rg_flags);
-
- CPIN_32(rgrp, str, rg_free);
-
- CPIN_32(rgrp, str, rg_useddi);
- CPIN_32(rgrp, str, rg_freedi);
- gfs_inum_in(&rgrp->rg_freedi_list, (char *)&str->rg_freedi_list);
-
- CPIN_32(rgrp, str, rg_usedmeta);
- CPIN_32(rgrp, str, rg_freemeta);
-
- CPIN_08(rgrp, str, rg_reserved, 64);
-
- RET(GFN_RGRP_IN);
-}
-
-/**
- * gfs_rgrp_out - Write out a resource group header
- * @rgrp: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rgrp_out(struct gfs_rgrp *rgrp, char *buf)
-{
- ENTER(GFN_RGRP_OUT)
- struct gfs_rgrp *str = (struct gfs_rgrp *)buf;
-
- gfs_meta_header_out(&rgrp->rg_header, buf);
-
- CPOUT_32(rgrp, str, rg_flags);
-
- CPOUT_32(rgrp, str, rg_free);
-
- CPOUT_32(rgrp, str, rg_useddi);
- CPOUT_32(rgrp, str, rg_freedi);
- gfs_inum_out(&rgrp->rg_freedi_list, (char *)&str->rg_freedi_list);
-
- CPOUT_32(rgrp, str, rg_usedmeta);
- CPOUT_32(rgrp, str, rg_freemeta);
-
- CPOUT_08(rgrp, str, rg_reserved, 64);
-
- RET(GFN_RGRP_OUT);
-}
-
-/**
- * gfs_rgrp_print - Print out a resource group header
- * @rg: the cpu-order buffer
- *
- */
-
-void
-gfs_rgrp_print(struct gfs_rgrp *rg)
-{
- ENTER(GFN_RGRP_PRINT)
-
- gfs_meta_header_print(&rg->rg_header);
-
- pv(rg, rg_flags, "%u");
-
- pv(rg, rg_free, "%u");
-
- pv(rg, rg_useddi, "%u");
- pv(rg, rg_freedi, "%u");
- gfs_inum_print(&rg->rg_freedi_list);
-
- pv(rg, rg_usedmeta, "%u");
- pv(rg, rg_freemeta, "%u");
-
- pa(rg, rg_reserved, 64);
-
- RET(GFN_RGRP_PRINT);
-}
-
-/**
- * gfs_quota_in - Read in a quota structures
- * @quota: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_in(struct gfs_quota *quota, char *buf)
-{
- ENTER(GFN_QUOTA_IN)
- struct gfs_quota *str = (struct gfs_quota *)buf;
-
- CPIN_64(quota, str, qu_limit);
- CPIN_64(quota, str, qu_warn);
- CPIN_64(quota, str, qu_value);
-
- CPIN_08(quota, str, qu_reserved, 64);
-
- RET(GFN_QUOTA_IN);
-}
-
-/**
- * gfs_quota_out - Write out a quota structure
- * @quota: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_out(struct gfs_quota *quota, char *buf)
-{
- ENTER(GFN_QUOTA_OUT)
- struct gfs_quota *str = (struct gfs_quota *)buf;
-
- CPOUT_64(quota, str, qu_limit);
- CPOUT_64(quota, str, qu_warn);
- CPOUT_64(quota, str, qu_value);
-
- CPOUT_08(quota, str, qu_reserved, 64);
-
- RET(GFN_QUOTA_OUT);
-}
-
-/**
- * gfs_quota_print - Print out a quota structure
- * @quota: the cpu-order buffer
- *
- */
-
-void
-gfs_quota_print(struct gfs_quota *quota)
-{
- ENTER(GFN_QUOTA_PRINT)
-
- pv(quota, qu_limit, "%"PRIu64);
- pv(quota, qu_warn, "%"PRIu64);
- pv(quota, qu_value, "%"PRId64);
-
- pa(quota, qu_reserved, 64);
-
- RET(GFN_QUOTA_PRINT);
-}
-
-/**
- * gfs_dinode_in - Read in a dinode
- * @dinode: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dinode_in(struct gfs_dinode *dinode, char *buf)
-{
- ENTER(GFN_DINODE_IN)
- struct gfs_dinode *str = (struct gfs_dinode *)buf;
-
- gfs_meta_header_in(&dinode->di_header, buf);
-
- gfs_inum_in(&dinode->di_num, (char *)&str->di_num);
-
- CPIN_32(dinode, str, di_mode);
- CPIN_32(dinode, str, di_uid);
- CPIN_32(dinode, str, di_gid);
- CPIN_32(dinode, str, di_nlink);
- CPIN_64(dinode, str, di_size);
- CPIN_64(dinode, str, di_blocks);
- CPIN_64(dinode, str, di_atime);
- CPIN_64(dinode, str, di_mtime);
- CPIN_64(dinode, str, di_ctime);
- CPIN_32(dinode, str, di_major);
- CPIN_32(dinode, str, di_minor);
-
- CPIN_64(dinode, str, di_rgrp);
- CPIN_64(dinode, str, di_goal_rgrp);
- CPIN_32(dinode, str, di_goal_dblk);
- CPIN_32(dinode, str, di_goal_mblk);
- CPIN_32(dinode, str, di_flags);
- CPIN_32(dinode, str, di_payload_format);
- CPIN_16(dinode, str, di_type);
- CPIN_16(dinode, str, di_height);
- CPIN_32(dinode, str, di_incarn);
- CPIN_16(dinode, str, di_pad);
-
- CPIN_16(dinode, str, di_depth);
- CPIN_32(dinode, str, di_entries);
-
- gfs_inum_in(&dinode->di_next_unused, (char *)&str->di_next_unused);
-
- CPIN_64(dinode, str, di_eattr);
-
- CPIN_08(dinode, str, di_reserved, 56);
-
- RET(GFN_DINODE_IN);
-}
-
-/**
- * gfs_dinode_out - Write out a dinode
- * @dinode: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dinode_out(struct gfs_dinode *dinode, char *buf)
-{
- ENTER(GFN_DINODE_OUT)
- struct gfs_dinode *str = (struct gfs_dinode *)buf;
-
- gfs_meta_header_out(&dinode->di_header, buf);
-
- gfs_inum_out(&dinode->di_num, (char *)&str->di_num);
-
- CPOUT_32(dinode, str, di_mode);
- CPOUT_32(dinode, str, di_uid);
- CPOUT_32(dinode, str, di_gid);
- CPOUT_32(dinode, str, di_nlink);
- CPOUT_64(dinode, str, di_size);
- CPOUT_64(dinode, str, di_blocks);
- CPOUT_64(dinode, str, di_atime);
- CPOUT_64(dinode, str, di_mtime);
- CPOUT_64(dinode, str, di_ctime);
- CPOUT_32(dinode, str, di_major);
- CPOUT_32(dinode, str, di_minor);
-
- CPOUT_64(dinode, str, di_rgrp);
- CPOUT_64(dinode, str, di_goal_rgrp);
- CPOUT_32(dinode, str, di_goal_dblk);
- CPOUT_32(dinode, str, di_goal_mblk);
- CPOUT_32(dinode, str, di_flags);
- CPOUT_32(dinode, str, di_payload_format);
- CPOUT_16(dinode, str, di_type);
- CPOUT_16(dinode, str, di_height);
- CPOUT_32(dinode, str, di_incarn);
- CPOUT_16(dinode, str, di_pad);
-
- CPOUT_16(dinode, str, di_depth);
- CPOUT_32(dinode, str, di_entries);
-
- gfs_inum_out(&dinode->di_next_unused, (char *)&str->di_next_unused);
-
- CPOUT_64(dinode, str, di_eattr);
-
- CPOUT_08(dinode, str, di_reserved, 56);
-
- RET(GFN_DINODE_OUT);
-}
-
-/**
- * gfs_dinode_print - Print out a dinode
- * @di: the cpu-order buffer
- *
- */
-
-void
-gfs_dinode_print(struct gfs_dinode *di)
-{
- ENTER(GFN_DINODE_PRINT)
-
- gfs_meta_header_print(&di->di_header);
-
- gfs_inum_print(&di->di_num);
-
- pv(di, di_mode, "0%o");
- pv(di, di_uid, "%u");
- pv(di, di_gid, "%u");
- pv(di, di_nlink, "%u");
- pv(di, di_size, "%"PRIu64);
- pv(di, di_blocks, "%"PRIu64);
- pv(di, di_atime, "%"PRId64);
- pv(di, di_mtime, "%"PRId64);
- pv(di, di_ctime, "%"PRId64);
- pv(di, di_major, "%u");
- pv(di, di_minor, "%u");
-
- pv(di, di_rgrp, "%"PRIu64);
- pv(di, di_goal_rgrp, "%"PRIu64);
- pv(di, di_goal_dblk, "%u");
- pv(di, di_goal_mblk, "%u");
- pv(di, di_flags, "0x%.8X");
- pv(di, di_payload_format, "%u");
- pv(di, di_type, "%u");
- pv(di, di_height, "%u");
- pv(di, di_incarn, "%u");
- pv(di, di_pad, "%u");
-
- pv(di, di_depth, "%u");
- pv(di, di_entries, "%u");
-
- gfs_inum_print(&di->di_next_unused);
-
- pv(di, di_eattr, "%"PRIu64);
-
- pa(di, di_reserved, 56);
-
- RET(GFN_DINODE_PRINT);
-}
-
-/**
- * gfs_indirect_in - copy in the header of an indirect block
- * @indirect: the in memory copy
- * @buf: the buffer copy
- *
- */
-
-void
-gfs_indirect_in(struct gfs_indirect *indirect, char *buf)
-{
- ENTER(GFN_INDIRECT_IN)
- struct gfs_indirect *str = (struct gfs_indirect *)buf;
-
- gfs_meta_header_in(&indirect->in_header, buf);
-
- CPIN_08(indirect, str, in_reserved, 64);
-
- RET(GFN_INDIRECT_IN);
-}
-
-/**
- * gfs_indirect_out - copy out the header of an indirect block
- * @indirect: the in memory copy
- * @buf: the buffer copy
- *
- */
-
-void
-gfs_indirect_out(struct gfs_indirect *indirect, char *buf)
-{
- ENTER(GFN_INDIRECT_OUT)
- struct gfs_indirect *str = (struct gfs_indirect *)buf;
-
- gfs_meta_header_out(&indirect->in_header, buf);
-
- CPOUT_08(indirect, str, in_reserved, 64);
-
- RET(GFN_INDIRECT_OUT);
-}
-
-/**
- * gfs_indirect_print - Print out a indirect block header
- * @indirect: the cpu-order buffer
- *
- */
-
-void
-gfs_indirect_print(struct gfs_indirect *indirect)
-{
- ENTER(GFN_INDIRECT_PRINT)
-
- gfs_meta_header_print(&indirect->in_header);
-
- pa(indirect, in_reserved, 64);
-
- RET(GFN_INDIRECT_PRINT);
-}
-
-/**
- * gfs_dirent_in - Read in a directory entry
- * @dirent: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dirent_in(struct gfs_dirent *dirent, char *buf)
-{
- ENTER(GFN_DIRENT_IN)
- struct gfs_dirent *str = (struct gfs_dirent *)buf;
-
- gfs_inum_in(&dirent->de_inum, (char *)&str->de_inum);
- CPIN_32(dirent, str, de_hash);
- CPIN_16(dirent, str, de_rec_len);
- CPIN_16(dirent, str, de_name_len);
- CPIN_16(dirent, str, de_type);
-
- CPIN_08(dirent, str, de_reserved, 14);
-
- RET(GFN_DIRENT_IN);
-}
-
-/**
- * gfs_dirent_out - Write out a directory entry
- * @dirent: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dirent_out(struct gfs_dirent *dirent, char *buf)
-{
- ENTER(GFN_DIRENT_OUT)
- struct gfs_dirent *str = (struct gfs_dirent *)buf;
-
- gfs_inum_out(&dirent->de_inum, (char *)&str->de_inum);
- CPOUT_32(dirent, str, de_hash);
- CPOUT_16(dirent, str, de_rec_len);
- CPOUT_16(dirent, str, de_name_len);
- CPOUT_16(dirent, str, de_type);
-
- CPOUT_08(dirent, str, de_reserved, 14);
-
- RET(GFN_DIRENT_OUT);
-}
-
-/**
- * gfs_dirent_print - Print out a directory entry
- * @de: the cpu-order buffer
- * @name: the filename
- *
- */
-
-void
-gfs_dirent_print(struct gfs_dirent *de, char *name)
-{
- ENTER(GFN_DIRENT_PRINT)
- char buf[GFS_FNAMESIZE + 1];
-
- gfs_inum_print(&de->de_inum);
- pv(de, de_hash, "0x%.8X");
- pv(de, de_rec_len, "%u");
- pv(de, de_name_len, "%u");
- pv(de, de_type, "%u");
-
- pa(de, de_reserved, 14);
-
- memset(buf, 0, GFS_FNAMESIZE + 1);
- memcpy(buf, name, de->de_name_len);
- printk(" name = %s\n", buf);
-
- RET(GFN_DIRENT_PRINT);
-}
-
-/**
- * gfs_leaf_in - Read in a directory leaf header
- * @leaf: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_leaf_in(struct gfs_leaf *leaf, char *buf)
-{
- ENTER(GFN_LEAF_IN)
- struct gfs_leaf *str = (struct gfs_leaf *)buf;
-
- gfs_meta_header_in(&leaf->lf_header, buf);
-
- CPIN_16(leaf, str, lf_depth);
- CPIN_16(leaf, str, lf_entries);
- CPIN_32(leaf, str, lf_dirent_format);
- CPIN_64(leaf, str, lf_next);
-
- CPIN_08(leaf, str, lf_reserved, 64);
-
- RET(GFN_LEAF_IN);
-}
-
-/**
- * gfs_leaf_out - Write out a directory leaf header
- * @leaf: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_leaf_out(struct gfs_leaf *leaf, char *buf)
-{
- ENTER(GFN_LEAF_OUT)
- struct gfs_leaf *str = (struct gfs_leaf *)buf;
-
- gfs_meta_header_out(&leaf->lf_header, buf);
-
- CPOUT_16(leaf, str, lf_depth);
- CPOUT_16(leaf, str, lf_entries);
- CPOUT_32(leaf, str, lf_dirent_format);
- CPOUT_64(leaf, str, lf_next);
-
- CPOUT_08(leaf, str, lf_reserved, 64);
-
- RET(GFN_LEAF_OUT);
-}
-
-/**
- * gfs_leaf_print - Print out a directory leaf header
- * @lf: the cpu-order buffer
- *
- */
-
-void
-gfs_leaf_print(struct gfs_leaf *lf)
-{
- ENTER(GFN_LEAF_PRINT)
-
- gfs_meta_header_print(&lf->lf_header);
-
- pv(lf, lf_depth, "%u");
- pv(lf, lf_entries, "%u");
- pv(lf, lf_dirent_format, "%u");
- pv(lf, lf_next, "%"PRIu64);
-
- pa(lf, lf_reserved, 64);
-
- RET(GFN_LEAF_PRINT);
-}
-
-/**
- * gfs_log_header_in - Read in a log header
- * @head: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_log_header_in(struct gfs_log_header *head, char *buf)
-{
- ENTER(GFN_LOG_HEADER_IN)
- struct gfs_log_header *str = (struct gfs_log_header *)buf;
-
- gfs_meta_header_in(&head->lh_header, buf);
-
- CPIN_32(head, str, lh_flags);
- CPIN_32(head, str, lh_pad);
-
- CPIN_64(head, str, lh_first);
- CPIN_64(head, str, lh_sequence);
-
- CPIN_64(head, str, lh_tail);
- CPIN_64(head, str, lh_last_dump);
-
- CPIN_08(head, str, lh_reserved, 64);
-
- RET(GFN_LOG_HEADER_IN);
-}
-
-/**
- * gfs_log_header_out - Write out a log header
- * @head: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_log_header_out(struct gfs_log_header *head, char *buf)
-{
- ENTER(GFN_LOG_HEADER_OUT)
- struct gfs_log_header *str = (struct gfs_log_header *)buf;
-
- gfs_meta_header_out(&head->lh_header, buf);
-
- CPOUT_32(head, str, lh_flags);
- CPOUT_32(head, str, lh_pad);
-
- CPOUT_64(head, str, lh_first);
- CPOUT_64(head, str, lh_sequence);
-
- CPOUT_64(head, str, lh_tail);
- CPOUT_64(head, str, lh_last_dump);
-
- CPOUT_08(head, str, lh_reserved, 64);
-
- RET(GFN_LOG_HEADER_OUT);
-}
-
-/**
- * gfs_log_header_print - Print out a log header
- * @head: the cpu-order buffer
- *
- */
-
-void
-gfs_log_header_print(struct gfs_log_header *lh)
-{
- ENTER(GFN_LOG_HEADER_PRINT)
-
- gfs_meta_header_print(&lh->lh_header);
-
- pv(lh, lh_flags, "0x%.8X");
- pv(lh, lh_pad, "%u");
-
- pv(lh, lh_first, "%"PRIu64);
- pv(lh, lh_sequence, "%"PRIu64);
-
- pv(lh, lh_tail, "%"PRIu64);
- pv(lh, lh_last_dump, "%"PRIu64);
-
- pa(lh, lh_reserved, 64);
-
- RET(GFN_LOG_HEADER_PRINT);
-}
-
-/**
- * gfs_desc_in - Read in a log descriptor
- * @desc: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_desc_in(struct gfs_log_descriptor *desc, char *buf)
-{
- ENTER(GFN_DESC_IN)
- struct gfs_log_descriptor *str = (struct gfs_log_descriptor *)buf;
-
- gfs_meta_header_in(&desc->ld_header, buf);
-
- CPIN_32(desc, str, ld_type);
- CPIN_32(desc, str, ld_length);
- CPIN_32(desc, str, ld_data1);
- CPIN_32(desc, str, ld_data2);
-
- CPIN_08(desc, str, ld_reserved, 64);
-
- RET(GFN_DESC_IN);
-}
-
-/**
- * gfs_desc_out - Write out a log descriptor
- * @desc: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_desc_out(struct gfs_log_descriptor *desc, char *buf)
-{
- ENTER(GFN_DESC_OUT)
- struct gfs_log_descriptor *str = (struct gfs_log_descriptor *)buf;
-
- gfs_meta_header_out(&desc->ld_header, buf);
-
- CPOUT_32(desc, str, ld_type);
- CPOUT_32(desc, str, ld_length);
- CPOUT_32(desc, str, ld_data1);
- CPOUT_32(desc, str, ld_data2);
-
- CPOUT_08(desc, str, ld_reserved, 64);
-
- RET(GFN_DESC_OUT);
-}
-
-/**
- * gfs_desc_print - Print out a log descriptor
- * @ld: the cpu-order buffer
- *
- */
-
-void
-gfs_desc_print(struct gfs_log_descriptor *ld)
-{
- ENTER(GFN_DESC_PRINT)
-
- gfs_meta_header_print(&ld->ld_header);
-
- pv(ld, ld_type, "%u");
- pv(ld, ld_length, "%u");
- pv(ld, ld_data1, "%u");
- pv(ld, ld_data2, "%u");
-
- pa(ld, ld_reserved, 64);
-
- RET(GFN_DESC_PRINT);
-}
-
-/**
- * gfs_block_tag_in - Read in a block tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_block_tag_in(struct gfs_block_tag *tag, char *buf)
-{
- ENTER(GFN_BLOCK_TAG_IN)
- struct gfs_block_tag *str = (struct gfs_block_tag *)buf;
-
- CPIN_64(tag, str, bt_blkno);
- CPIN_32(tag, str, bt_flags);
- CPIN_32(tag, str, bt_pad);
-
- RET(GFN_BLOCK_TAG_IN);
-}
-
-/**
- * gfs_block_tag_out - Write out a block tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_block_tag_out(struct gfs_block_tag *tag, char *buf)
-{
- ENTER(GFN_BLOCK_TAG_OUT)
- struct gfs_block_tag *str = (struct gfs_block_tag *)buf;
-
- CPOUT_64(tag, str, bt_blkno);
- CPOUT_32(tag, str, bt_flags);
- CPOUT_32(tag, str, bt_pad);
-
- RET(GFN_BLOCK_TAG_OUT);
-}
-
-/**
- * gfs_block_tag_print - Print out a block tag
- * @tag: the cpu-order buffer
- *
- */
-
-void
-gfs_block_tag_print(struct gfs_block_tag *tag)
-{
- ENTER(GFN_BLOCK_TAG_PRINT)
-
- pv(tag, bt_blkno, "%"PRIu64);
- pv(tag, bt_flags, "%u");
- pv(tag, bt_pad, "%u");
-
- RET(GFN_BLOCK_TAG_PRINT);
-}
-
-/**
- * gfs_quota_tag_in - Read in a quota tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_tag_in(struct gfs_quota_tag *tag, char *buf)
-{
- ENTER(GFN_QUOTA_TAG_IN)
- struct gfs_quota_tag *str = (struct gfs_quota_tag *)buf;
-
- CPIN_64(tag, str, qt_change);
- CPIN_32(tag, str, qt_flags);
- CPIN_32(tag, str, qt_id);
-
- RET(GFN_QUOTA_TAG_IN);
-}
-
-/**
- * gfs_quota_tag_out - Write out a quota tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_tag_out(struct gfs_quota_tag *tag, char *buf)
-{
- ENTER(GFN_QUOTA_TAG_OUT)
- struct gfs_quota_tag *str = (struct gfs_quota_tag *)buf;
-
- CPOUT_64(tag, str, qt_change);
- CPOUT_32(tag, str, qt_flags);
- CPOUT_32(tag, str, qt_id);
-
- RET(GFN_QUOTA_TAG_OUT);
-}
-
-/**
- * gfs_quota_tag_print - Print out a quota tag
- * @tag: the cpu-order buffer
- *
- */
-
-void
-gfs_quota_tag_print(struct gfs_quota_tag *tag)
-{
- ENTER(GFN_QUOTA_TAG_PRINT)
-
- pv(tag, qt_change, "%"PRId64);
- pv(tag, qt_flags, "0x%.8X");
- pv(tag, qt_id, "%u");
-
- RET(GFN_QUOTA_TAG_PRINT);
-}
-
-/**
- * gfs_ea_header_in - Read in a Extended Attribute header
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_ea_header_in(struct gfs_ea_header *ea, char *buf)
-{
- ENTER(GFN_EA_HEADER_IN)
- struct gfs_ea_header *str = (struct gfs_ea_header *)buf;
-
- CPIN_32(ea, str, ea_rec_len);
- CPIN_32(ea, str, ea_data_len);
- ea->ea_name_len = str->ea_name_len;
- ea->ea_type = str->ea_type;
- ea->ea_flags = str->ea_flags;
- ea->ea_num_ptrs = str->ea_num_ptrs;
- CPIN_32(ea, str, ea_pad);
-
- RET(GFN_EA_HEADER_IN);
-}
-
-/**
- * gfs_ea_header_out - Write out a Extended Attribute header
- * @ea: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_ea_header_out(struct gfs_ea_header *ea, char *buf)
-{
- ENTER(GFN_EA_HEADER_OUT)
- struct gfs_ea_header *str = (struct gfs_ea_header *)buf;
-
- CPOUT_32(ea, str, ea_rec_len);
- CPOUT_32(ea, str, ea_data_len);
- str->ea_name_len = ea->ea_name_len;
- str->ea_type = ea->ea_type;
- str->ea_flags = ea->ea_flags;
- str->ea_num_ptrs = ea->ea_num_ptrs;
- CPOUT_32(ea, str, ea_pad);
-
- RET(GFN_EA_HEADER_OUT);
-}
-
-/**
- * gfs_ea_header_printt - Print out a Extended Attribute header
- * @ea: the cpu-order buffer
- *
- */
-
-void
-gfs_ea_header_print(struct gfs_ea_header *ea, char *name)
-{
- ENTER(GFN_EA_HEADER_PRINT)
- char buf[GFS_EA_MAX_NAME_LEN + 1];
-
- pv(ea, ea_rec_len, "%u");
- pv(ea, ea_data_len, "%u");
- pv(ea, ea_name_len, "%u");
- pv(ea, ea_type, "%u");
- pv(ea, ea_flags, "%u");
- pv(ea, ea_num_ptrs, "%u");
- pv(ea, ea_pad, "%u");
-
- memset(buf, 0, GFS_EA_MAX_NAME_LEN + 1);
- memcpy(buf, name, ea->ea_name_len);
- printk(" name = %s\n", buf);
-
- RET(GFN_EA_HEADER_PRINT);
-}
-
-static const uint32_t crc_32_tab[] =
-{
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-/**
- * gfs_dir_hash - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * The hash function is a 32-bit CRC of the data. The algorithm uses
- * the crc_32_tab table above.
- *
- * This may not be the fastest hash function, but it does a fair bit better
- * at providing uniform results than the others I've looked at. That's
- * really important for efficient directories.
- *
- * Returns: the hash
- */
-
-uint32_t
-gfs_dir_hash(const char *data, int len)
-{
- ENTER(GFN_DIR_HASH)
- uint32_t hash = 0xFFFFFFFF;
-
- for (; len--; data++)
- hash = crc_32_tab[(hash ^ *data) & 0xFF] ^ (hash >> 8);
-
- hash = ~hash;
-
- RETURN(GFN_DIR_HASH, hash);
-}
-
-#endif /* WANT_GFS_CONVERSION_FUNCTIONS */
-
diff --git a/gfs/gfs_fsck/pass1.c b/gfs/gfs_fsck/pass1.c
deleted file mode 100644
index 386041b..0000000
--- a/gfs/gfs_fsck/pass1.c
+++ /dev/null
@@ -1,1124 +0,0 @@
-/* pass1 checks inodes for format & type, duplicate blocks, & incorrect
- * block count.
- *
- * It builds up tables that contains the state of each block (free,
- * block in use, metadata type, etc), as well as bad blocks and
- * duplicate blocks. (See block_list.[ch] for more info)
- *
- */
-
-#include <stdio.h>
-
-#include "fsck_incore.h"
-#include "fsck.h"
-#include "bio.h"
-#include "fs_dir.h"
-#include "fs_inode.h"
-#include "util.h"
-#include "block_list.h"
-#include "log.h"
-#include "inode_hash.h"
-#include "inode.h"
-#include "link.h"
-#include "metawalk.h"
-
-struct block_count {
- uint64_t indir_count;
- uint64_t data_count;
- uint64_t ea_count;
-};
-
-static int leaf(struct fsck_inode *ip, uint64_t block, osi_buf_t *bh,
- void *private);
-static int check_metalist(struct fsck_inode *ip, uint64_t block,
- osi_buf_t **bh, void *private);
-static int check_data(struct fsck_inode *ip, uint64_t block, void *private);
-static int check_eattr_indir(struct fsck_inode *ip, uint64_t indirect,
- uint64_t parent, osi_buf_t **bh,
- void *private);
-static int check_eattr_leaf(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh,
- void *private);
-static int check_eattr_entries(struct fsck_inode *ip, osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private);
-static int check_extended_leaf_eattr(struct fsck_inode *ip, uint64_t *data_ptr,
- osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private);
-static int finish_eattr_indir(struct fsck_inode *ip, int leaf_pointers,
- int leaf_pointer_errors, void *private);
-
-struct metawalk_fxns pass1_fxns = {
- .private = NULL,
- .check_leaf = leaf,
- .check_metalist = check_metalist,
- .check_data = check_data,
- .check_eattr_indir = check_eattr_indir,
- .check_eattr_leaf = check_eattr_leaf,
- .check_dentry = NULL,
- .check_eattr_entry = check_eattr_entries,
- .check_eattr_extentry = check_extended_leaf_eattr,
- .finish_eattr_indir = finish_eattr_indir,
-};
-
-static int leaf(struct fsck_inode *ip, uint64_t block, osi_buf_t *bh,
- void *private)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- struct block_count *bc = (struct block_count *) private;
-
- log_debug("\tLeaf block at %15"PRIu64"\n", BH_BLKNO(bh));
- block_set(sdp->bl, BH_BLKNO(bh), leaf_blk);
- bc->indir_count++;
- return 0;
-}
-
-static int check_metalist(struct fsck_inode *ip, uint64_t block,
- osi_buf_t **bh, void *private)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- struct block_query q = {0};
- int found_dup = 0;
- osi_buf_t *nbh;
- struct block_count *bc = (struct block_count *)private;
-
- *bh = NULL;
-
- if (check_range(ip->i_sbd, block)){ /* blk outside of FS */
- block_set(sdp->bl, ip->i_di.di_num.no_addr, bad_block);
- log_debug("Bad indirect block pointer (out of range).\n");
-
- return 1;
- }
- if(block_check(sdp->bl, block, &q)) {
- stack;
- return -1;
- }
- if(q.block_type != block_free) {
- log_err("Found duplicate block referenced as metadata in "
- "indirect block - was marked %d\n", q.block_type);
- block_mark(sdp->bl, block, dup_block);
- found_dup = 1;
- }
- get_and_read_buf(ip->i_sbd, block, &nbh, 0);
-
- if (check_meta(nbh, GFS_METATYPE_IN)){
- log_debug("Bad indirect block pointer (points to "
- "something that is not an indirect block).\n");
- if(!found_dup) {
- block_set(sdp->bl, block, meta_inval);
- relse_buf(ip->i_sbd, nbh);
- return 1;
- }
-
- relse_buf(ip->i_sbd, nbh);
- } else /* blk check ok */
- *bh = nbh;
-
- if (!found_dup) {
- log_debug("Setting %" PRIu64 " to indirect block.\n", block);
- block_set(sdp->bl, block, indir_blk);
- }
- bc->indir_count++;
-
- return 0;
-}
-
-static int check_data(struct fsck_inode *ip, uint64_t block, void *private)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- struct block_query q = {0};
- osi_buf_t *data_bh;
- struct block_count *bc = (struct block_count *) private;
- int error = 0, btype;
-
- if (check_range(ip->i_sbd, block)) {
- log_err("inode %lld has a bad data block pointer "
- "%lld (out of range)\n",
- ip->i_di.di_num.no_addr, block);
- /* Mark the owner of this block with the bad_block
- * designator so we know to check it for out of range
- * blocks later */
- block_set(ip->i_sbd->bl, ip->i_di.di_num.no_addr, bad_block);
-
- return 1;
- }
-
- if(get_and_read_buf(ip->i_sbd, block, &data_bh, 0)) {
- stack;
- block_set(sdp->bl, ip->i_di.di_num.no_addr, meta_inval);
- return 1;
- }
- if(block_check(sdp->bl, block, &q)) {
- stack;
- log_err("Found bad block referenced as data at %"
- PRIu64 " (0x%"PRIx64 ")\n", block, block);
- relse_buf(sdp, data_bh);
- return -1;
- }
- if (ip->i_di.di_flags & GFS_DIF_JDATA){
- if(check_meta(data_bh, GFS_METATYPE_JD)) {
- log_err("Block #%"PRIu64" in inode %"PRIu64" does not have "
- "correct meta header. Is %u should be %u\n",
- block, ip->i_di.di_num.no_addr,
- gfs32_to_cpu(((struct gfs_meta_header *)
- BH_DATA((data_bh)))->mh_type),
- GFS_METATYPE_JD);
- block_set(sdp->bl, ip->i_di.di_num.no_addr,
- meta_inval);
- relse_buf(sdp, data_bh);
- return 1;
- }
-
- if(q.block_type != block_free) {
- log_err("Found duplicate block referenced as "
- "journaled data at %" PRIu64"\n", block);
- if (q.block_type != meta_inval) {
- block_mark(sdp->bl, block, dup_block);
- relse_buf(sdp, data_bh);
- /* If the prev ref was as data, this is likely
- a data block, so keep the block count for
- both refs. */
- if (q.block_type == block_used)
- bc->data_count++;
- return 1;
- }
- /* An explanation is in order here. At this point we
- found a duplicate block, a block that was already
- referenced somewhere else. We'll resolve those
- duplicates in pass1b. However, if the block is
- marked "invalid" that's a special case. It's likely
- that the block was discovered to be invalid
- metadata--i.e. doesn't have a metadata header.
- However, it still may be a valid data block, since
- they won't have metadata headers. In that case,
- the block is marked as duplicate, but also as a
- journaled data block. */
- error = 1;
- log_debug("Marking %" PRIu64 " as journaled data "
- "block\n", block);
- block_unmark(sdp->bl, block, meta_inval);
- block_mark(sdp->bl, block, dup_block);
- }
- block_mark(sdp->bl, block, journal_blk);
- } else {
- if(q.block_type != block_free) {
- log_err("Found duplicate block referenced as data "
- "at %" PRIu64"\n", block);
- if (q.block_type != meta_inval) {
- block_mark(sdp->bl, block, dup_block);
- bc->data_count++;
- relse_buf(sdp, data_bh);
- return 1;
- }
- error = 1;
- log_debug("Marking %"PRIu64 " as data block\n", block);
- block_unmark(sdp->bl, block, meta_inval);
- block_mark(sdp->bl, block, dup_block);
- }
- block_mark(sdp->bl, block, block_used);
- }
- relse_buf(sdp, data_bh);
- /* This is also confusing, so I'll clarify. There are two bitmaps:
- (1) The bitmap that fsck uses to keep track of what block
- type has been discovered, and (2) The rgrp bitmap. Function
- gfs_block_set is used to set the former and set_bitmap
- is used to set the latter. In this function we need to set both
- because we found a "data" block that could be "meta" in the rgrp
- bitmap. If we don't we could run into the data block again as
- metadata when we're traversing the metadata with next_rg_meta
- in func pass1(). If that happens, it will look at the block,
- say "hey this isn't metadata" and mark it incorrectly as an
- invalid metadata block and free it. Ordinarily, fsck will wait
- until pass5 to sync (2) so that it agrees with (1). However, in
- this case, it's better to do it upfront. The duplicate solving
- code in pass1b.c is better at resolving metadata referencing a
- data block than it is at resolving a data block referencing a
- metadata block. */
- btype = fs_get_bitmap(ip->i_sbd, block, NULL);
- if (btype != GFS_BLKST_USED && btype != GFS_BLKST_USEDMETA) {
- const char *allocdesc[] = {"free space", "data",
- "free metadata", "metadata",
- "reserved"};
-
- if (ip->i_di.di_flags & GFS_DIF_JDATA) {
- log_err("Block #%llu seems to be journaled data, but "
- "is marked as %s.\n",
- (unsigned long long)block, allocdesc[btype]);
- errors_found++;
- if(query(sdp, "Okay to mark it as 'journaled data'? "
- "(y/n)")) {
- errors_corrected++;
- fs_set_bitmap(sdp, block, GFS_BLKST_USEDMETA);
- log_err("The block was reassigned as "
- "journaled data.\n");
- } else {
- log_err("The invalid block was ignored.\n");
- }
- } else {
- log_err("Block #%llu seems to be data, but "
- "is marked as %s.\n",
- (unsigned long long)block, allocdesc[btype]);
- errors_found++;
- if(query(sdp, "Okay to mark it as 'data'? "
- "(y/n)")) {
- errors_corrected++;
- fs_set_bitmap(sdp, block, GFS_BLKST_USED);
- log_err("The block was reassigned as "
- "journaled data.\n");
- } else {
- log_err("The invalid block was ignored.\n");
- }
- }
- }
- bc->data_count++;
- return error;
-}
-
-static int remove_inode_eattr(struct fsck_inode *ip, struct block_count *bc,
- int duplicate)
-{
- osi_buf_t *dibh = NULL;
-
- if (!duplicate) {
- fs_set_bitmap(ip->i_sbd, ip->i_di.di_eattr,
- GFS_BLKST_FREEMETA);
- block_set(ip->i_sbd->bl, ip->i_di.di_eattr, meta_free);
- }
- ip->i_di.di_eattr = 0;
- bc->ea_count = 0;
- ip->i_di.di_blocks = 1 + bc->indir_count + bc->data_count;
- ip->i_di.di_flags &= ~GFS_DIF_EA_INDIRECT;
- if (get_and_read_buf(ip->i_sbd, ip->i_num.no_addr, &dibh, 0)) {
- log_err("The bad Extended Attribute could not be fixed.\n");
- bc->ea_count++;
- return 1;
- }
- gfs_dinode_out(&ip->i_di, BH_DATA(dibh));
- if (write_buf(ip->i_sbd, dibh, 0) < 0) {
- stack;
- log_crit("The bad Extended Attribute remains.\n");
- relse_buf(ip->i_sbd, dibh);
- return -1;
- } else {
- log_warn("The bad Extended Attribute was removed.\n");
- }
- relse_buf(ip->i_sbd, dibh);
- return 0;
-}
-
-static int ask_remove_inode_eattr(struct fsck_inode *ip,
- struct block_count *bc)
-{
- log_err("Inode %lld has unrecoverable Extended Attribute "
- "errors.\n", (unsigned long long)ip->i_di.di_num.no_addr);
- errors_found++;
- if (query(ip->i_sbd, "Clear all Extended Attributes from the "
- "inode? (y/n) ")) {
- struct block_query q;
-
- if(block_check(ip->i_sbd->bl, ip->i_di.di_eattr, &q)) {
- stack;
- return -1;
- }
- if (!remove_inode_eattr(ip, bc, q.dup_block)) {
- errors_corrected++;
- log_err("Extended attributes were removed.\n");
- } else
- log_err("Unable to remove inode eattr pointer; "
- "the error remains.\n");
- } else {
- log_err("Extended attributes were not removed.\n");
- }
- return 0;
-}
-
-/* clear_eas - clear the extended attributes for an inode
- *
- * @ip - in core inode pointer
- * @bc - pointer to a block count structure
- * block - the block that had the problem
- * duplicate - if this is a duplicate block, don't set it "free"
- * emsg - what to tell the user about the eas being checked
- * Returns: 1 if the EA is fixed, else 0 if it was not fixed.
- */
-static int clear_eas(struct fsck_inode *ip, struct block_count *bc,
- uint64_t block, int duplicate, const char *emsg)
-{
- struct fsck_sb *sdp = ip->i_sbd;
-
- log_err("Inode #%" PRIu64 " (0x%" PRIx64 "): %s",
- ip->i_di.di_num.no_addr, ip->i_di.di_num.no_addr, emsg);
- log_err(" at block #%" PRIu64 ".\n", block);
- errors_found++;
- if (query(sdp, "Clear the bad Extended Attribute? (y/n) ")) {
- if (block == ip->i_di.di_eattr) {
- remove_inode_eattr(ip, bc, duplicate);
- log_warn("The bad Extended Attribute was removed.\n");
- } else if (!duplicate) {
- block_set(sdp->bl, block, meta_free);
- fs_set_bitmap(sdp, block, GFS_BLKST_FREEMETA);
- log_err("The bad Extended Attribute was "
- "removed.\n");
- }
- errors_corrected++;
- return 1;
- } else {
- log_err("The bad Extended Attribute was not fixed.\n");
- bc->ea_count++;
- return 0;
- }
-}
-
-static int check_eattr_indir(struct fsck_inode *ip, uint64_t indirect,
- uint64_t parent, osi_buf_t **bh, void *private)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- int ret = 0;
- struct block_query q = {0};
- struct block_count *bc = (struct block_count *) private;
-
- /* This inode contains an eattr - it may be invalid, but the
- * eattr attributes points to a non-zero block */
- if(check_range(sdp, indirect)) {
- /*log_warn("EA indirect block #%"PRIu64" is out of range.\n",
- indirect);
- block_set(sdp->bl, parent, bad_block);*/
- /* Doesn't help to mark this here - this gets checked
- * in pass1c */
- return 1;
- }
- if(block_check(sdp->bl, indirect, &q)) {
- stack;
- return -1;
- }
-
- /* Special duplicate processing: If we have an EA block,
- check if it really is an EA. If it is, let duplicate
- handling sort it out. If it isn't, clear it but don't
- count it as a duplicate. */
- if(get_and_read_buf(sdp, indirect, bh, 0)) {
- log_warn("Unable to read Extended Attribute indirect block "
- "#%"PRIu64".\n", indirect);
- block_set(sdp->bl, indirect, meta_inval);
- return 1;
- }
- if(check_meta(*bh, GFS_METATYPE_IN)) {
- if(q.block_type != block_free) {
- if (!clear_eas(ip, bc, indirect, 1,
- "Bad indirect Extended Attribute "
- "duplicate found")) {
- block_mark(sdp->bl, indirect, dup_block);
- bc->ea_count++;
- }
- return 1;
- }
- clear_eas(ip, bc, indirect, 0,
- "Extended Attribute indirect block has incorrect "
- "type");
- return 1;
- }
- if(q.block_type != block_free) { /* Duplicate? */
- log_err("Inode #%" PRIu64 "Duplicate Extended Attribute "
- "indirect block found at #%"PRIu64".\n",
- ip->i_di.di_num.no_addr, indirect);
- block_mark(sdp->bl, indirect, dup_block);
- bc->ea_count++;
- ret = 1;
- } else {
- log_debug("Setting #%" PRIu64
- ") to indirect Extended Attribute block\n",
- indirect);
- block_set(sdp->bl, BH_BLKNO(*bh), indir_blk);
- bc->ea_count++;
- }
- return ret;
-}
-
-static int finish_eattr_indir(struct fsck_inode *ip, int leaf_pointers,
- int leaf_pointer_errors, void *private)
-{
- struct block_count *bc = (struct block_count *) private;
-
- if (leaf_pointer_errors == leaf_pointers) /* All eas were bad */
- return ask_remove_inode_eattr(ip, bc);
- log_debug("Marking inode #%lld with extended attribute block\n",
- (unsigned long long)ip->i_di.di_num.no_addr);
- /* Mark the inode as having an eattr in the block map
- so pass1c can check it. */
- block_mark(ip->i_sbd->bl, ip->i_di.di_num.no_addr, eattr_block);
- if (!leaf_pointer_errors)
- return 0;
- log_err("Inode %lld has recoverable indirect "
- "Extended Attribute errors.\n",
- (unsigned long long)ip->i_di.di_num.no_addr);
- errors_found++;
- if (query(ip->i_sbd, "Okay to fix the block count for the inode? "
- "(y/n) ")) {
- ip->i_di.di_blocks = 1 + bc->indir_count +
- bc->data_count + bc->ea_count;
- errors_corrected++;
- log_err("Block count fixed.\n");
- return 1;
- }
- log_err("Block count not fixed.\n");
- return 1;
-}
-
-static int check_leaf_block(struct fsck_inode *ip, uint64_t block, int btype,
- osi_buf_t **bh, void *private)
-{
- osi_buf_t *leaf_bh = NULL;
- struct fsck_sb *sdp = ip->i_sbd;
- struct block_query q = {0};
- struct block_count *bc = (struct block_count *) private;
-
- if(block_check(sdp->bl, block, &q)) {
- stack;
- return -1;
- }
- /* Special duplicate processing: If we have an EA block, check if it
- really is an EA. If it is, let duplicate handling sort it out.
- If it isn't, clear it but don't count it as a duplicate. */
- if(get_and_read_buf(sdp, block, &leaf_bh, 0)){
- log_err("Unable to read leaf block %lld.\n", block);
- return -1;
- }
- if(check_meta(leaf_bh, btype)) {
- if(q.block_type != block_free) { /* Duplicate? */
- clear_eas(ip, bc, block, 1,
- "Bad Extended Attribute duplicate found");
- } else {
- clear_eas(ip, bc, block, 0,
- "Extended Attribute leaf block "
- "has incorrect type");
- }
- relse_buf(sdp, leaf_bh);
- return 1;
- }
- if(q.block_type != block_free) { /* Duplicate? */
- log_debug("Duplicate block found at #%lld.\n",
- (unsigned long long)block);
- block_mark(sdp->bl, block, dup_block);
- bc->ea_count++;
- relse_buf(sdp, leaf_bh);
- return 1;
- }
- if (ip->i_di.di_eattr == 0) {
- /* Can only get in here if there were unrecoverable ea
- errors that caused clear_eas to be called. What we
- need to do here is remove the subsequent ea blocks. */
- clear_eas(ip, bc, block, 0,
- "Extended Attribute block removed due to "
- "previous errors.\n");
- relse_buf(sdp, leaf_bh);
- return 1;
- }
- log_debug("Setting block #%lld (0x%llx) to eattr block\n",
- (unsigned long long)block, (unsigned long long)block);
- /* Point of confusion: We've got to set the ea block itself to
- gfs2_meta_eattr here. Elsewhere we mark the inode with
- gfs2_eattr_block meaning it contains an eattr for pass1c. */
- block_set(sdp->bl, block, meta_eattr);
- bc->ea_count++;
- *bh = leaf_bh;
- return 0;
-}
-
-/**
- * check_extended_leaf_eattr
- * @ip
- * @el_blk: block number of the extended leaf
- *
- * An EA leaf block can contain EA's with pointers to blocks
- * where the data for that EA is kept. Those blocks still
- * have the gfs meta header of type GFS_METATYPE_EA
- *
- * Returns: 0 if correct[able], -1 if removal is needed
- */
-static int check_extended_leaf_eattr(struct fsck_inode *ip, uint64_t *data_ptr,
- osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private)
-{
- uint64_t el_blk = gfs64_to_cpu(*data_ptr);
- struct fsck_sb *sdp = ip->i_sbd;
- osi_buf_t *bh = NULL;
- int error;
-
- if(check_range(sdp, el_blk)){
- log_err("Inode #%" PRIu64 ": Extended Attribute block %" PRIu64
- " has an extended leaf block #%" PRIu64 " that is out "
- "of range.\n", ip->i_di.di_num.no_addr,
- ip->i_di.di_eattr, el_blk);
- block_set(sdp->bl, ip->i_di.di_eattr, bad_block);
- return 1;
- }
- error = check_leaf_block(ip, el_blk, GFS_METATYPE_ED, &bh, private);
- if (bh)
- relse_buf(sdp, bh);
- return error;
-}
-
-static int check_eattr_leaf(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh, void *private)
-{
- struct fsck_sb *sdp = ip->i_sbd;
-
- /* This inode contains an eattr - it may be invalid, but the
- * eattr attributes points to a non-zero block.
- * Clarification: If we're here we're checking a leaf block, and the
- * source dinode needs to be marked as having extended attributes.
- * That instructs pass1c to check the contents of the ea blocks. */
- log_debug("Setting inode %" PRIu64 ") as having eattr "
- "block\n", ip->i_num.no_addr);
- block_mark(sdp->bl, ip->i_num.no_addr, eattr_block);
- if(check_range(sdp, block)){
- log_warn("Inode #%" PRIu64 " Extended Attribute leaf block "
- "#%" PRIu64 " is out of range.\n",
- ip->i_num.no_addr, block);
- block_set(sdp->bl, ip->i_di.di_eattr, bad_block);
- return 1;
- }
- return check_leaf_block(ip, block, GFS_METATYPE_EA, bh, private);
-}
-
-static int check_eattr_entries(struct fsck_inode *ip,
- osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- char ea_name[256];
-
- if(!ea_hdr->ea_name_len){
- /* Skip this entry for now */
- return 1;
- }
-
- memset(ea_name, 0, sizeof(ea_name));
- strncpy(ea_name, (char *)ea_hdr + sizeof(struct gfs_ea_header),
- ea_hdr->ea_name_len);
-
- if(!GFS_EATYPE_VALID(ea_hdr->ea_type) &&
- ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
- /* Skip invalid entry */
- return 1;
- }
-
- if(ea_hdr->ea_num_ptrs){
- uint32_t avail_size;
- int max_ptrs;
-
- avail_size = sdp->sb.sb_bsize - sizeof(struct gfs_meta_header);
- max_ptrs = (gfs32_to_cpu(ea_hdr->ea_data_len)+avail_size-1)/avail_size;
-
- if(max_ptrs > ea_hdr->ea_num_ptrs) {
- return 1;
- } else {
- log_debug(" Pointers Required: %d\n"
- " Pointers Reported: %d\n",
- max_ptrs, ea_hdr->ea_num_ptrs);
- }
- }
- return 0;
-}
-
-static int clear_metalist(struct fsck_inode *ip, uint64_t block,
- osi_buf_t **bh, void *private)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- struct block_query q = {0};
-
- *bh = NULL;
-
- if(block_check(sdp->bl, block, &q)) {
- stack;
- return -1;
- }
- if(!q.dup_block) {
- block_set(sdp->bl, block, block_free);
- return 0;
- }
- return 0;
-}
-
-static int clear_data(struct fsck_inode *ip, uint64_t block, void *private)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- struct block_query q = {0};
-
- if(block_check(sdp->bl, block, &q)) {
- stack;
- return -1;
- }
- if(!q.dup_block) {
- block_set(sdp->bl, block, block_free);
- return 0;
- }
- return 0;
-
-}
-
-static int clear_leaf(struct fsck_inode *ip, uint64_t block,
- osi_buf_t *bh, void *private)
-{
- struct block_query q = {0};
- struct fsck_sb *sdp = ip->i_sbd;
-
- log_crit("Clearing leaf %"PRIu64"\n", block);
-
- if(block_check(sdp->bl, block, &q)) {
- stack;
- return -1;
- }
- if(!q.dup_block) {
- log_crit("Setting leaf #%" PRIu64 " invalid\n", block);
- if(block_set(sdp->bl, block, block_free)) {
- stack;
- return -1;
- }
- return 0;
- }
- return 0;
-}
-
-int add_to_dir_list(struct fsck_sb *sbp, uint64_t block)
-{
- struct dir_info *di = NULL;
- struct dir_info *newdi;
-
- /* FIXME: This list should probably be a b-tree or
- * something...but since most of the time we're going to be
- * tacking the directory onto the end of the list, it doesn't
- * matter too much */
- find_di(sbp, block, &di);
- if(di) {
- log_err("Attempting to add directory block %"PRIu64
- " which is already in list\n", block);
- return -1;
- }
-
- if(!(newdi = (struct dir_info *) malloc(sizeof(*newdi)))) {
- log_crit("Unable to allocate dir_info structure\n");
- return -1;
- }
- if(!memset(newdi, 0, sizeof(*newdi))) {
- log_crit("Error while zeroing dir_info structure\n");
- return -1;
- }
-
- newdi->dinode = block;
- dinode_hash_insert(sbp->dir_hash, block, newdi);
- return 0;
-}
-
-
-static int handle_di(struct fsck_sb *sdp, osi_buf_t *bh, uint64_t block, int mfree)
-{
- struct block_query q = {0};
- struct fsck_inode *ip;
- int error;
- struct block_count bc = {0};
- struct metawalk_fxns invalidate_metatree = {0};
- invalidate_metatree.check_metalist = clear_metalist;
- invalidate_metatree.check_data = clear_data;
- invalidate_metatree.check_leaf = clear_leaf;
-
- if(copyin_inode(sdp, bh, &ip)) {
- stack;
- return -1;
- }
-
- if (ip->i_di.di_flags & GFS_DIF_UNUSED){
- if(mfree) {
- if(block_set(sdp->bl, block, meta_free)) {
- stack;
- goto fail;
- }
- goto success;
- } else {
- log_err("Found unused inode marked in-use\n");
- errors_found++;
- if(query(sdp, "Clear unused inode at block %"
- PRIu64"? (y/n) ", block)) {
- if(block_set(sdp->bl, block, meta_inval)) {
- stack;
- goto fail;
- }
- errors_corrected++;
- goto success;
- } else {
- log_err("Unused inode still marked in-use\n");
- }
- }
-
- } else {
- if(mfree) {
- if(block_set(sdp->bl, block, meta_free)) {
- stack;
- goto fail;
- }
- goto success;
- }
- }
-
- if (ip->i_di.di_num.no_addr != block) {
- log_err("Bad dinode Address. "
- "Found %"PRIu64", "
- "Expected %"PRIu64"\n",
- ip->i_di.di_num.no_addr, block);
- errors_found++;
- if(query(sdp, "Fix address in inode at block %"
- PRIu64"? (y/n) ", block)) {
- ip->i_di.di_num.no_addr =
- ip->i_di.di_num.no_formal_ino =
- block;
- if(fs_copyout_dinode(ip)){
- log_crit("Bad dinode address can not be reset.\n");
- goto fail;
- } else {
- errors_corrected++;
- log_err("Bad dinode address reset.\n");
- }
- } else {
- log_err("Address in inode at block %"PRIu64
- " not fixed\n", block);
- }
-
- }
-
- if(block_check(sdp->bl, block, &q)) {
- stack;
- goto fail;
- }
- if(q.block_type != block_free) {
- log_err("Found duplicate block referenced as an inode at #%"
- PRIu64"\n", block);
- if(block_mark(sdp->bl, block, dup_block)) {
- stack;
- goto fail;
- }
- goto success;
- }
-
- switch(ip->i_di.di_type) {
-
- case GFS_FILE_DIR:
- if(block_set(sdp->bl, block, inode_dir)) {
- stack;
- goto fail;
- }
- if(add_to_dir_list(sdp, block)) {
- stack;
- goto fail;
- }
- break;
- case GFS_FILE_REG:
- if(block_set(sdp->bl, block, inode_file)) {
- stack;
- goto fail;
- }
- break;
- case GFS_FILE_LNK:
- if(block_set(sdp->bl, block, inode_lnk)) {
- stack;
- goto fail;
- }
- break;
- case GFS_FILE_BLK:
- if(block_set(sdp->bl, block, inode_blk)) {
- stack;
- goto fail;
- }
- break;
- case GFS_FILE_CHR:
- if(block_set(sdp->bl, block, inode_chr)) {
- stack;
- goto fail;
- }
- break;
- case GFS_FILE_FIFO:
- if(block_set(sdp->bl, block, inode_fifo)) {
- stack;
- goto fail;
- }
- break;
- case GFS_FILE_SOCK:
- if(block_set(sdp->bl, block, inode_sock)) {
- stack;
- goto fail;
- }
- break;
- default:
- if(block_set(sdp->bl, block, meta_inval)) {
- stack;
- goto fail;
- }
- fs_set_bitmap(sdp, block, GFS_BLKST_FREE);
- goto success;
- }
- if(set_link_count(ip->i_sbd, ip->i_num.no_formal_ino,
- ip->i_di.di_nlink)) {
- stack;
- goto fail;
- }
-
- /* FIXME: fix height and depth here - wasn't implemented in
- * old fsck either, so no biggy... */
- if (ip->i_di.di_height < compute_height(sdp, ip->i_di.di_size)){
- log_warn("Dinode #%"PRIu64" has bad height "
- "Found %u, Expected >= %u\n",
- ip->i_di.di_num.no_addr, ip->i_di.di_height,
- compute_height(sdp, ip->i_di.di_size));
- /* once implemented, remove continue statement */
- log_warn("Marking inode %lld invalid\n",
- ip->i_di.di_num.no_addr);
- if(block_set(sdp->bl, block, meta_inval)) {
- stack;
- goto fail;
- }
- fs_set_bitmap(sdp, block, GFS_BLKST_FREE);
- goto success;
- }
-
- if (ip->i_di.di_type == (GFS_FILE_DIR &&
- (ip->i_di.di_flags & GFS_DIF_EXHASH))) {
- if (((1 << ip->i_di.di_depth) * sizeof(uint64_t)) !=
- ip->i_di.di_size) {
- log_warn("Directory dinode #%"PRIu64" has bad depth. "
- "Found %u, Expected %u\n",
- ip->i_di.di_num.no_addr, ip->i_di.di_depth,
- (1 >> (ip->i_di.di_size/sizeof(uint64))));
- /* once implemented, remove continue statement */
- log_warn("Marking inode %lld invalid\n",
- ip->i_di.di_num.no_addr);
- if(block_set(sdp->bl, block, meta_inval)) {
- stack;
- goto fail;
- }
- fs_set_bitmap(sdp, block, GFS_BLKST_FREE);
- goto success;
- }
- }
-
- pass1_fxns.private = &bc;
-
- error = check_metatree(ip, &pass1_fxns);
- if(fsck_abort || error < 0) {
- return 0;
- }
- if(error > 0) {
- log_warn("Marking inode %lld invalid\n",
- ip->i_di.di_num.no_addr);
- /* FIXME: Must set all leaves invalid as well */
- check_metatree(ip, &invalidate_metatree);
- block_set(ip->i_sbd->bl, ip->i_di.di_num.no_addr, meta_inval);
- fs_set_bitmap(sdp, block, GFS_BLKST_FREE);
- free(ip);
- return 0;
- }
-
- error = check_inode_eattr(ip, &pass1_fxns);
-
- if (error && !(ip->i_di.di_flags & GFS_DIF_EA_INDIRECT))
- ask_remove_inode_eattr(ip, &bc);
-
- if (ip->i_di.di_blocks !=
- (1 + bc.indir_count + bc.data_count + bc.ea_count)) {
- osi_buf_t *di_bh;
-
- log_err("Ondisk block count does not match what fsck"
- " found for inode %"PRIu64"\n", ip->i_di.di_num.no_addr);
- log_info("inode has: %lld, but fsck counts: Dinode:1 + indir:"
- "%lld + data: %lld + ea: %lld\n",
- ip->i_di.di_blocks, bc.indir_count, bc.data_count,
- bc.ea_count);
- errors_found++;
- if(query(sdp, "Fix ondisk block count? (y/n) ")) {
- ip->i_di.di_blocks = 1 + bc.indir_count +
- bc.data_count + bc.ea_count;
- if(get_and_read_buf(sdp, ip->i_di.di_num.no_addr,
- &di_bh, 0)){
- stack;
- log_crit("Bad block count remains\n");
- } else {
- gfs_dinode_out(&ip->i_di, BH_DATA(di_bh));
- if(write_buf(ip->i_sbd, di_bh, 0) < 0){
- stack;
- log_crit("Bad block count remains\n");
- } else {
- errors_corrected++;
- log_err("Bad block count fixed\n");
- }
- relse_buf(sdp, di_bh);
- }
- } else {
- log_err("Bad block count for %"PRIu64" not fixed\n",
- ip->i_di.di_num.no_addr);
- }
- }
-
- success:
- free(ip);
- return 0;
-
- fail:
- free(ip);
- return -1;
-
-}
-
-
-static int scan_meta(struct fsck_sb *sdp, osi_buf_t *bh, uint64_t block, int mfree)
-{
- if (check_meta(bh, 0)) {
- errors_found++;
- log_err("Found invalid metadata block at %"PRIu64"\n", block);
- if(block_set(sdp->bl, block, meta_inval)) {
- stack;
- return -1;
- }
- if(query(sdp, "Okay to free the invalid block? (y/n)")) {
- errors_corrected++;
- fs_set_bitmap(sdp, block, GFS_BLKST_FREE);
- log_err("The invalid block was freed.\n");
- } else {
- log_err("The invalid block was ignored.\n");
- }
- return 0;
- }
-
- log_debug("Checking metadata block %"PRIu64"\n", block);
-
- if (!check_type(bh, GFS_METATYPE_DI)) {
- if(handle_di(sdp, bh, block, mfree)) {
- stack;
- return -1;
- }
- }
- /* Ignore everything else - they should be hit by the handle_di step.
- * Don't check NONE either, because check_meta passes everything if
- * GFS_METATYPE_NONE is specified.
- * Hopefully, other metadata types such as indirect blocks will be
- * handled when the inode itself is processed, and if it's not, it
- * should be caught in pass5. */
- return 0;
-}
-
-/**
- * pass1 - walk through inodes and check inode state
- *
- * this walk can be done using root inode and depth first search,
- * watching for repeat inode numbers
- *
- * format & type
- * link count
- * duplicate blocks
- * bad blocks
- * inodes size
- * dir info
- */
-int pass1(struct fsck_sb *sbp)
-{
- osi_buf_t *bh;
- osi_list_t *tmp;
- uint64_t block;
- struct fsck_rgrp *rgd;
- int first;
- uint64_t i;
- uint64_t j;
- uint64_t blk_count;
- uint64_t offset;
- uint64_t rg_count = 0;
- int mfree = 0;
-
- /* FIXME: What other metadata should we look for? */
-
- /* Mark the journal blocks as 'other metadata' */
- for (i = 0; i < sbp->journals; i++) {
- struct gfs_jindex *ji;
- ji = &sbp->jindex[i];
- for(j = ji->ji_addr;
- j < ji->ji_addr + (ji->ji_nsegment * sbp->sb.sb_seg_size);
- j++) {
- if(block_set(sbp->bl, j, journal_blk)) {
- stack;
- return FSCK_ERROR;
- }
- }
- }
-
-
- /* So, do we do a depth first search starting at the root
- * inode, or use the rg bitmaps, or just read every fs block
- * to find the inodes? If we use the depth first search, why
- * have pass3 at all - if we use the rg bitmaps, pass5 is at
- * least partially invalidated - if we read every fs block,
- * things will probably be intolerably slow. The current fsck
- * uses the rg bitmaps, so maybe that's the best way to start
- * things - we can change the method later if necessary.
- */
-
- for (tmp = sbp->rglist.next; tmp != &sbp->rglist;
- tmp = tmp->next, rg_count++){
- log_info("Checking metadata in Resource Group %"PRIu64"\n",
- rg_count);
- rgd = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
- if(fs_rgrp_read(rgd, FALSE)){
- stack;
- return FSCK_ERROR;
- }
- log_debug("RG at %"PRIu64" is %u long\n", rgd->rd_ri.ri_addr,
- rgd->rd_ri.ri_length);
- for (i = 0; i < rgd->rd_ri.ri_length; i++) {
- if(block_set(sbp->bl, rgd->rd_ri.ri_addr + i,
- meta_other)){
- stack;
- return FSCK_ERROR;
- }
- }
-
- offset = sizeof(struct gfs_rgrp);
- blk_count = 1;
- first = 1;
-
- while (1) {
- /* "block" is relative to the entire file system */
- if(next_rg_meta_free(rgd, &block, first, &mfree))
- break;
- warm_fuzzy_stuff(block);
- if (fsck_abort) /* if asked to abort */
- return FSCK_OK;
- if (skip_this_pass) {
- printf("Skipping pass 1 is not a good idea.\n");
- skip_this_pass = FALSE;
- fflush(stdout);
- }
- if(get_and_read_buf(sbp, block, &bh, 0)){
- stack;
- log_crit("Unable to retrieve block %"PRIu64
- "\n", block);
- fs_rgrp_relse(rgd);
- return FSCK_ERROR;
- }
-
- if(scan_meta(sbp, bh, block, mfree)) {
- stack;
- relse_buf(sbp, bh);
- fs_rgrp_relse(rgd);
- return FSCK_ERROR;
- }
- relse_buf(sbp, bh);
- first = 0;
- }
- fs_rgrp_relse(rgd);
- }
-
- return FSCK_OK;
-}
diff --git a/gfs/gfs_fsck/pass1b.c b/gfs/gfs_fsck/pass1b.c
deleted file mode 100644
index 7a89d32..0000000
--- a/gfs/gfs_fsck/pass1b.c
+++ /dev/null
@@ -1,563 +0,0 @@
-#include "fsck_incore.h"
-#include "fsck.h"
-#include "osi_list.h"
-#include "bio.h"
-#include "fs_inode.h"
-#include "block_list.h"
-#include "util.h"
-#include "inode.h"
-#include "inode_hash.h"
-#include "metawalk.h"
-
-struct inode_with_dups {
- osi_list_t list;
- uint64_t block_no;
- int dup_count;
- int ea_only;
- uint64_t parent;
- char *name;
-};
-
-struct blocks {
- osi_list_t list;
- uint64_t block_no;
- osi_list_t ref_inode_list;
-};
-
-struct fxn_info {
- uint64_t block;
- int found;
- int ea_only; /* The only dups were found in EAs */
-};
-
-struct dup_handler {
- struct blocks *b;
- struct inode_with_dups *id;
- int ref_inode_count;
- int ref_count;
-};
-
-static inline void inc_if_found(uint64_t block, int not_ea, void *private) {
- struct fxn_info *fi = (struct fxn_info *) private;
- if(block == fi->block) {
- (fi->found)++;
- if(not_ea)
- fi->ea_only = 0;
- }
-}
-
-static int check_metalist(struct fsck_inode *ip, uint64_t block,
- osi_buf_t **bh, void *private)
-{
- inc_if_found(block, 1, private);
-
- return 0;
-}
-
-static int check_data(struct fsck_inode *ip, uint64_t block, void *private)
-{
- inc_if_found(block, 1, private);
-
- return 0;
-}
-
-static int check_eattr_indir(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh, void *private)
-{
- struct fsck_sb *sbp = ip->i_sbd;
- osi_buf_t *indir_bh = NULL;
-
- inc_if_found(block, 0, private);
- if(get_and_read_buf(sbp, block, &indir_bh, 0)){
- log_warn("Unable to read EA leaf block #%"PRIu64".\n",
- block);
- return 1;
- }
-
- *bh = indir_bh;
-
- return 0;
-}
-
-static int check_eattr_leaf(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh, void *private)
-{
- struct fsck_sb *sbp = ip->i_sbd;
- osi_buf_t *leaf_bh = NULL;
-
- inc_if_found(block, 0, private);
- if(get_and_read_buf(sbp, block, &leaf_bh, 0)){
- log_err("Unable to read EA leaf block #%"PRIu64".\n",
- block);
- return 1;
- }
-
- *bh = leaf_bh;
- return 0;
-}
-
-static int check_eattr_entry(struct fsck_inode *ip, osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private)
-{
- return 0;
-}
-
-static int check_eattr_extentry(struct fsck_inode *ip, uint64_t *ea_data_ptr,
- osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private)
-{
- uint64_t block = gfs64_to_cpu(*ea_data_ptr);
-
- inc_if_found(block, 0, private);
-
- return 0;
-}
-
-static int find_dentry(struct fsck_inode *ip, struct gfs_dirent *de,
- struct gfs_dirent *prev,
- osi_buf_t *bh, char *filename, int *update,
- uint16_t *count, void *priv)
-{
- osi_list_t *tmp1, *tmp2;
- struct blocks *b;
- struct inode_with_dups *id;
- struct gfs_leaf leaf;
-
- osi_list_foreach(tmp1, &ip->i_sbd->dup_list) {
- b = osi_list_entry(tmp1, struct blocks, list);
- osi_list_foreach(tmp2, &b->ref_inode_list) {
- id = osi_list_entry(tmp2, struct inode_with_dups,
- list);
- if(id->name)
- /* We can only have one parent of
- * inodes that contain duplicate
- * blocks... */
- continue;
- if(id->block_no == de->de_inum.no_addr) {
- id->name = strdup(filename);
- id->parent = ip->i_di.di_num.no_addr;
- log_debug("Duplicate block %"PRIu64
- " is in file or directory %"PRIu64
- " named %s\n", id->block_no,
- ip->i_di.di_num.no_addr, filename);
- /* If there are duplicates of
- * duplicates, I guess we'll miss them
- * here */
- break;
- }
- }
- }
- /* Return the number of leaf entries so metawalk doesn't flag this
- leaf as having none. */
- gfs_leaf_in(&leaf, bh->b_data);
- *count = leaf.lf_entries;
- return 0;
-}
-
-static int clear_dup_metalist(struct fsck_inode *ip, uint64_t block,
- osi_buf_t **bh, void *private)
-{
- struct dup_handler *dh = (struct dup_handler *) private;
-
- if(dh->ref_count == 1)
- return 1;
- if(block == dh->b->block_no) {
- log_err("Found duplicate reference in inode \"%s\" at block #%"
- PRIu64 " to block #%"PRIu64"\n",
- dh->id->name ? dh->id->name : "unknown name",
- ip->i_di.di_num.no_addr, block);
- log_err("Inode %s is in directory %"PRIu64"\n",
- dh->id->name ? dh->id->name : "",
- dh->id->parent);
- inode_hash_remove(ip->i_sbd->inode_hash, ip->i_di.di_num.no_addr);
- /* Setting the block to invalid means the inode is
- * cleared in pass2 */
- block_set(ip->i_sbd->bl, ip->i_di.di_num.no_addr, meta_inval);
- }
- return 0;
-}
-static int clear_dup_data(struct fsck_inode *ip, uint64_t block, void *private)
-{
- return clear_dup_metalist(ip, block, NULL, private);
-}
-static int clear_dup_eattr_indir(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh,
- void *private)
-{
- struct dup_handler *dh = (struct dup_handler *) private;
- /* Can't use fxns from eattr.c since we need to check the ref
- * count */
- *bh = NULL;
- if(dh->ref_count == 1)
- return 1;
- if(block == dh->b->block_no) {
- log_err("Found dup in inode \"%s\" (block #%"PRIu64
- ") with block #%"PRIu64"\n",
- dh->id->name ? dh->id->name : "unknown name",
- ip->i_di.di_num.no_addr, block);
- log_err("inode %s is in directory %"PRIu64"\n",
- dh->id->name ? dh->id->name : "",
- dh->id->parent);
- block_set(ip->i_sbd->bl, ip->i_di.di_eattr, meta_inval);
- }
-
- return 0;
-}
-static int clear_dup_eattr_leaf(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh, void *private)
-{
- struct dup_handler *dh = (struct dup_handler *) private;
- if(dh->ref_count == 1)
- return 1;
- if(block == dh->b->block_no) {
- log_err("Found dup in inode \"%s\" (block #%"PRIu64
- ") with block #%"PRIu64"\n",
- dh->id->name ? dh->id->name : "unknown name",
- ip->i_di.di_num.no_addr, block);
- log_err("inode %s is in directory %"PRIu64"\n",
- dh->id->name ? dh->id->name : "",
- dh->id->parent);
-
- /* mark the main eattr block invalid */
- block_set(ip->i_sbd->bl, ip->i_di.di_eattr, meta_inval);
- }
-
- return 0;
-}
-
-static int clear_eattr_entry (struct fsck_inode *ip,
- osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- char ea_name[256];
-
- if(!ea_hdr->ea_name_len){
- /* Skip this entry for now */
- return 1;
- }
-
- memset(ea_name, 0, sizeof(ea_name));
- strncpy(ea_name, (char *)ea_hdr + sizeof(struct gfs_ea_header),
- ea_hdr->ea_name_len);
-
- if(!GFS_EATYPE_VALID(ea_hdr->ea_type) &&
- ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
- /* Skip invalid entry */
- return 1;
- }
-
- if(ea_hdr->ea_num_ptrs){
- uint32 avail_size;
- int max_ptrs;
-
- avail_size = sdp->sb.sb_bsize - sizeof(struct gfs_meta_header);
- max_ptrs = (gfs32_to_cpu(ea_hdr->ea_data_len)+avail_size-1)/avail_size;
-
- if(max_ptrs > ea_hdr->ea_num_ptrs) {
- return 1;
- } else {
- log_debug(" Pointers Required: %d\n"
- " Pointers Reported: %d\n",
- max_ptrs,
- ea_hdr->ea_num_ptrs);
- }
- }
- return 0;
-}
-
-static int clear_eattr_extentry(struct fsck_inode *ip, uint64_t *ea_data_ptr,
- osi_buf_t *leaf_bh, struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev, void *private)
-{
- uint64_t block = gfs64_to_cpu(*ea_data_ptr);
- struct dup_handler *dh = (struct dup_handler *) private;
- if(dh->ref_count == 1)
- return 1;
- if(block == dh->b->block_no) {
- log_err("Found dup in inode \"%s\" (block #%"PRIu64
- ") with block #%"PRIu64"\n",
- dh->id->name ? dh->id->name : "unknown name",
- ip->i_di.di_num.no_addr, block);
- log_err("inode %s is in directory %"PRIu64"\n",
- dh->id->name ? dh->id->name : "",
- dh->id->parent);
- /* mark the main eattr block invalid */
- block_set(ip->i_sbd->bl, ip->i_di.di_eattr, meta_inval);
- }
-
- return 0;
-
-}
-
-/* Finds all references to duplicate blocks in the metadata */
-static int find_block_ref(struct fsck_sb *sbp, uint64_t inode, struct blocks *b)
-{
- struct fsck_inode *ip;
- struct fxn_info myfi = {b->block_no, 0, 1};
- struct inode_with_dups *id = NULL;
- struct metawalk_fxns find_refs = {
- .private = (void*) &myfi,
- .check_leaf = NULL,
- .check_metalist = check_metalist,
- .check_data = check_data,
- .check_eattr_indir = check_eattr_indir,
- .check_eattr_leaf = check_eattr_leaf,
- .check_dentry = NULL,
- .check_eattr_entry = check_eattr_entry,
- .check_eattr_extentry = check_eattr_extentry,
- };
-
- if(load_inode(sbp, inode, &ip)) {
- stack;
- return -1;
- }
- log_debug("Checking inode %"PRIu64"'s metatree for references to "
- "block %"PRIu64"\n", inode, b->block_no);
- if(check_metatree(ip, &find_refs)) {
- stack;
- free_inode(&ip);
- return -1;
- }
- log_debug("Done checking metatree\n");
- /* Check for ea references in the inode */
- if(check_inode_eattr(ip, &find_refs) < 0){
- stack;
- free_inode(&ip);
- return -1;
- }
- if (myfi.found) {
- if(!(id = malloc(sizeof(*id)))) {
- log_crit("Unable to allocate inode_with_dups structure\n");
- return -1;
- }
- if(!(memset(id, 0, sizeof(*id)))) {
- log_crit("Unable to zero inode_with_dups structure\n");
- return -1;
- }
- log_debug("Found %d entries with block %"PRIu64
- " in inode #%"PRIu64"\n",
- myfi.found, b->block_no, inode);
- id->dup_count = myfi.found;
- id->block_no = inode;
- id->ea_only = myfi.ea_only;
- osi_list_add_prev(&id->list, &b->ref_inode_list);
- }
- free_inode(&ip);
- return 0;
-}
-
-/* Finds all blocks marked in the duplicate block bitmap */
-static int find_dup_blocks(struct fsck_sb *sbp)
-{
- uint64_t block_no = 0;
- struct blocks *b;
-
- while (!find_next_block_type(sbp->bl, dup_block, &block_no)) {
- if(!(b = malloc(sizeof(*b)))) {
- log_crit("Unable to allocate blocks structure\n");
- return -1;
- }
- if(!memset(b, 0, sizeof(*b))) {
- log_crit("Unable to zero blocks structure\n");
- return -1;
- }
- b->block_no = block_no;
- osi_list_init(&b->ref_inode_list);
- log_notice("Found dup block at %"PRIu64"\n", block_no);
- osi_list_add(&b->list, &sbp->dup_list);
- block_no++;
- }
- return 0;
-}
-
-static int handle_dup_blk(struct fsck_sb *sbp, struct blocks *b)
-{
- osi_list_t *tmp;
- struct inode_with_dups *id;
- struct metawalk_fxns clear_dup_fxns = {
- .private = NULL,
- .check_leaf = NULL,
- .check_metalist = clear_dup_metalist,
- .check_data = clear_dup_data,
- .check_eattr_indir = clear_dup_eattr_indir,
- .check_eattr_leaf = clear_dup_eattr_leaf,
- .check_dentry = NULL,
- .check_eattr_entry = clear_eattr_entry,
- .check_eattr_extentry = clear_eattr_extentry,
- };
- struct fsck_inode *ip;
- struct dup_handler dh = {0};
-
- osi_list_foreach(tmp, &b->ref_inode_list) {
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- dh.ref_inode_count++;
- dh.ref_count += id->dup_count;
- }
- /* A single reference to the block implies a possible situation where
- a data pointer points to a metadata block. In other words, the
- duplicate reference in the file system is (1) Metadata block X and
- (2) A dinode reference such as a data pointer pointing to block X.
- We can't really check for that in pass1 because user data might
- just _look_ like metadata by coincidence, and at the time we're
- checking, we might not have processed the referenced block.
- Here in pass1b we're sure. */
- if (dh.ref_count == 1) {
- osi_buf_t *bh;
- uint32_t cmagic;
-
- get_and_read_buf(sbp, b->block_no, &bh, 0);
- cmagic = ((struct gfs_meta_header *)(bh->b_data))->mh_magic;
- relse_buf(sbp, bh);
- if (be32_to_cpu(cmagic) == GFS_MAGIC) {
- tmp = b->ref_inode_list.next;
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- log_warn("Inode %s (%lld) has a reference to "
- "data block %"PRIu64", but "
- "the block is really metadata.\n",
- id->name, id->block_no, b->block_no);
- errors_found++;
- if (query(sbp, "Clear the inode? (y/n) ")) {
- errors_corrected++;
- log_warn("Clearing inode %lld...\n",
- id->block_no);
- load_inode(sbp, id->block_no, &ip);
- inode_hash_remove(ip->i_sbd->inode_hash,
- ip->i_di.di_num.no_addr);
- /* Setting the block to invalid means the inode
- is cleared in pass2 */
- block_set(sbp->bl, ip->i_di.di_num.no_addr,
- meta_inval);
- free_inode(&ip);
- } else {
- log_warn("The bad inode was not cleared.");
- }
- return 0;
- }
- }
-
- log_notice("Block %"PRIu64" has %d inodes referencing it for "
- "a total of %d duplicate references.\n",
- b->block_no, dh.ref_inode_count, dh.ref_count);
-
- osi_list_foreach(tmp, &b->ref_inode_list) {
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- log_warn("Inode %s (%lld) has %d reference(s) to block %"PRIu64
- "\n", id->name, id->block_no, id->dup_count,
- b->block_no);
- }
- osi_list_foreach(tmp, &b->ref_inode_list) {
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- errors_found++;
- if (!query(sbp, "Okay to clear inode %lld? (y/n) ",
- id->block_no)) {
- log_warn("The inode %lld was not cleared...\n",
- id->block_no);
- continue;
- }
- errors_corrected++;
- log_warn("Clearing inode %lld...\n", id->block_no);
- load_inode(sbp, id->block_no, &ip);
- dh.b = b;
- dh.id = id;
- clear_dup_fxns.private = (void *) &dh;
- /* Clear the EAs for the inode first */
- check_inode_eattr(ip, &clear_dup_fxns);
- /* If the dup wasn't only in the EA, clear the inode */
- if(!id->ea_only)
- check_metatree(ip, &clear_dup_fxns);
-
- block_set(sbp->bl, id->block_no, meta_inval);
- free_inode(&ip);
- dh.ref_inode_count--;
- if(dh.ref_inode_count == 1)
- break;
- /* Inode is marked invalid and is removed in pass2 */
- /* FIXME: other option should be to duplicate the
- * block for each duplicate and point the metadata at
- * the cloned blocks */
- }
- return 0;
-
-}
-
-/* Pass 1b handles finding the previous inode for a duplicate block
- * When found, store the inodes pointing to the duplicate block for
- * use in pass2 */
-int pass1b(struct fsck_sb *sbp)
-{
- struct blocks *b;
- uint64_t i;
- struct block_query q;
- osi_list_t *tmp = NULL, *x;
- struct metawalk_fxns find_dirents = {0};
- int rc = FSCK_OK;
-
- find_dirents.check_dentry = &find_dentry;
-
- osi_list_init(&sbp->dup_list);
- /* Shove all blocks marked as duplicated into a list */
- log_info("Looking for duplicate blocks...\n");
- find_dup_blocks(sbp);
-
- /* If there were no dups in the bitmap, we don't need to do anymore */
- if(osi_list_empty(&sbp->dup_list)) {
- log_info("No duplicate blocks found\n");
- return FSCK_OK;
- }
-
- /* Rescan the fs looking for pointers to blocks that are in
- * the duplicate block map */
- log_info("Scanning filesystem for inodes containing duplicate blocks...\n");
- log_debug("Filesystem has %"PRIu64" blocks total\n", sbp->last_fs_block);
- for(i = 0; i < sbp->last_fs_block; i += 1) {
- warm_fuzzy_stuff(i);
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- goto out;
- log_debug("Scanning block %"PRIu64" for inodes\n", i);
- if(block_check(sbp->bl, i, &q)) {
- stack;
- rc = FSCK_ERROR;
- goto out;
- }
- if((q.block_type == inode_dir) ||
- (q.block_type == inode_file) ||
- (q.block_type == inode_lnk) ||
- (q.block_type == inode_blk) ||
- (q.block_type == inode_chr) ||
- (q.block_type == inode_fifo) ||
- (q.block_type == inode_sock)) {
- osi_list_foreach_safe(tmp, &sbp->dup_list, x) {
- b = osi_list_entry(tmp, struct blocks, list);
- if(find_block_ref(sbp, i, b)) {
- stack;
- rc = FSCK_ERROR;
- goto out;
- }
- }
- }
- if(q.block_type == inode_dir) {
- check_dir(sbp, i, &find_dirents);
- }
- }
-
- /* Fix dups here - it's going to slow things down a lot to fix
- * it later */
- log_info("Handling duplicate blocks\n");
-out:
- /*osi_list_foreach(tmp, &sbp->dup_list) {*/
- while (!osi_list_empty(&sbp->dup_list)) {
- b = osi_list_entry(sbp->dup_list.next, struct blocks, list);
- if (!skip_this_pass && !rc) /* no error & not asked to skip the rest */
- handle_dup_blk(sbp, b);
- osi_list_del(&b->list);
- free(b);
- }
- return rc;
-}
diff --git a/gfs/gfs_fsck/pass1c.c b/gfs/gfs_fsck/pass1c.c
deleted file mode 100644
index 2e68173..0000000
--- a/gfs/gfs_fsck/pass1c.c
+++ /dev/null
@@ -1,290 +0,0 @@
-#include "fsck.h"
-#include "fsck_incore.h"
-#include "fs_inode.h"
-#include "bio.h"
-#include "inode.h"
-#include "util.h"
-#include "block_list.h"
-#include "metawalk.h"
-
-static int remove_eattr_entry(struct fsck_sb *sdp, osi_buf_t *leaf_bh,
- struct gfs_ea_header *curr,
- struct gfs_ea_header *prev)
-{
- if(!prev)
- curr->ea_type = GFS_EATYPE_UNUSED;
- else {
- uint32_t tmp32 = gfs32_to_cpu(curr->ea_rec_len) +
- gfs32_to_cpu(prev->ea_rec_len);
- prev->ea_rec_len = cpu_to_gfs32(tmp32);
- if (curr->ea_flags & GFS_EAFLAG_LAST)
- prev->ea_flags |= GFS_EAFLAG_LAST;
- }
- if(write_buf(sdp, leaf_bh, 0)){
- stack;
- log_err("EA removal failed.\n");
- return -1;
- }
- log_err("Bad Extended Attribute at block #%"PRIu64" removed.\n",
- BH_BLKNO(leaf_bh));
- return 0;
-}
-
-static int ask_remove_eattr_entry(struct fsck_sb *sdp, osi_buf_t *leaf_bh,
- struct gfs_ea_header *curr,
- struct gfs_ea_header *prev,
- int fix_curr, int fix_curr_len)
-{
- errors_found++;
- if (query(sdp, "Remove the bad Extended Attribute? (y/n) ")) {
- if (fix_curr)
- curr->ea_flags |= GFS_EAFLAG_LAST;
- if (fix_curr_len) {
- uint32_t max_size = sdp->sb.sb_bsize;
- uint32_t offset = (uint32_t)(((unsigned long)curr) -
- ((unsigned long)leaf_bh->b_data));
- curr->ea_rec_len = cpu_to_be32(max_size - offset);
- }
- if (remove_eattr_entry(sdp, leaf_bh, curr, prev)) {
- stack;
- return -1;
- }
- errors_corrected++;
- } else {
- log_err("Bad Extended Attribute not removed.\n");
- }
- return 1;
-}
-
-static int ask_remove_eattr(struct fsck_inode *ip)
-{
- errors_found++;
- if (query(ip->i_sbd, "Remove the bad Extended Attribute? (y/n) ")) {
- ip->i_di.di_eattr = 0;
- if (fs_copyout_dinode(ip))
- log_err("Bad Extended Attribute could not be "
- "removed.\n");
- else {
- errors_corrected++;
- log_err("Bad Extended Attribute removed.\n");
- }
- } else
- log_err("Bad Extended Attribute not removed.\n");
- return 1;
-}
-
-static int check_eattr_indir(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh,
- void *private)
-{
- int *update = (int *) private;
- struct fsck_sb *sbp = ip->i_sbd;
- struct block_query q;
- osi_buf_t *indir_bh = NULL;
-
- *update = 0;
- if(check_range(sbp, block)) {
- log_err("Extended attributes indirect block #%llu"
- " for inode #%llu is out of range.\n",
- (unsigned long long)block,
- (unsigned long long)ip->i_num.no_addr);
- return ask_remove_eattr(ip);
- }
- else if (block_check(sbp->bl, block, &q)) {
- stack;
- return -1;
- }
- else if(q.block_type != indir_blk) {
- log_err("Extended attributes indirect block #%llu"
- " for inode #%llu is invalid.\n",
- (unsigned long long)block,
- (unsigned long long)ip->i_num.no_addr);
- return ask_remove_eattr(ip);
- }
- else if(get_and_read_buf(sbp, block, &indir_bh, 0)){
- log_warn("Unable to read Extended Attribute leaf block "
- "#%"PRIu64".\n", block);
- return ask_remove_eattr(ip);
- }
-
- *bh = indir_bh;
- return 0;
-}
-
-static int check_eattr_leaf(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh, void *private)
-{
- struct fsck_sb *sbp = ip->i_sbd;
- struct block_query q;
- osi_buf_t *leaf_bh;
-
- if(check_range(sbp, block)) {
- log_err("Extended attributes leaf block #%"PRIu64
- " for inode #%" PRIu64 " is out of range.\n",
- block, ip->i_num.no_addr);
- return ask_remove_eattr(ip);
- }
- else if (block_check(sbp->bl, block, &q)) {
- stack;
- return -1;
- }
- else if(q.block_type != meta_eattr) {
- log_err("Extended attributes leaf block #%"PRIu64
- " for inode #%" PRIu64 " is invalid.\n",
- block, ip->i_num.no_addr);
- return ask_remove_eattr(ip);
- }
- else if(get_and_read_buf(sbp, block, &leaf_bh, 0)){
- log_warn("Unable to read Extended attributes leaf block "
- "#%"PRIu64".\n", block);
- return ask_remove_eattr(ip);
- }
-
- *bh = leaf_bh;
- return 0;
-}
-
-static int check_eattr_entry(struct fsck_inode *ip,
- osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private)
-{
- struct fsck_sb *sdp = ip->i_sbd;
- char ea_name[256];
- uint32_t offset = (uint32_t)(((unsigned long)ea_hdr) -
- ((unsigned long)BH_DATA(leaf_bh)));
- uint32_t max_size = sdp->sb.sb_bsize;
- if(!ea_hdr->ea_rec_len){
- log_err("EA has rec length == 0\n");
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 1, 1);
- }
- if(offset + gfs32_to_cpu(ea_hdr->ea_rec_len) > max_size){
- log_err("EA rec length too long\n");
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 1, 1);
- }
- if(offset + gfs32_to_cpu(ea_hdr->ea_rec_len) == max_size &&
- (ea_hdr->ea_flags & GFS_EAFLAG_LAST) == 0){
- log_err("last EA has no last entry flag\n");
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- }
- if(!ea_hdr->ea_name_len){
- log_err("EA has name length == 0\n");
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- }
-
- memset(ea_name, 0, sizeof(ea_name));
- strncpy(ea_name, (char *)ea_hdr + sizeof(struct gfs_ea_header),
- ea_hdr->ea_name_len);
-
- if(!GFS_EATYPE_VALID(ea_hdr->ea_type) &&
- ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
- log_err("EA (%s) type is invalid (%d > %d).\n",
- ea_name, ea_hdr->ea_type, GFS_EATYPE_LAST);
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- }
-
- if(ea_hdr->ea_num_ptrs){
- uint32 avail_size;
- int max_ptrs;
-
- avail_size = sdp->sb.sb_bsize - sizeof(struct gfs_meta_header);
- max_ptrs = (gfs32_to_cpu(ea_hdr->ea_data_len)+avail_size-1)/avail_size;
-
- if(max_ptrs > ea_hdr->ea_num_ptrs){
- log_err("EA (%s) has incorrect number of pointers.\n", ea_name);
- log_err(" Required: %d\n"
- " Reported: %d\n",
- max_ptrs, ea_hdr->ea_num_ptrs);
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- } else {
- log_debug(" Pointers Required: %d\n"
- " Pointers Reported: %d\n",
- max_ptrs, ea_hdr->ea_num_ptrs);
- }
- }
- return 0;
-}
-
-static int check_eattr_extentry(struct fsck_inode *ip, uint64_t *ea_ptr,
- osi_buf_t *leaf_bh,
- struct gfs_ea_header *ea_hdr,
- struct gfs_ea_header *ea_hdr_prev,
- void *private)
-{
- struct block_query q;
- struct fsck_sb *sbp = ip->i_sbd;
-
- if(block_check(sbp->bl, gfs64_to_cpu(*ea_ptr), &q)) {
- stack;
- return -1;
- }
- if(q.block_type != meta_eattr) {
- if(remove_eattr_entry(sbp, leaf_bh, ea_hdr, ea_hdr_prev)){
- stack;
- return -1;
- }
- return 1;
- }
- return 0;
-}
-
-/* Go over all inodes with extended attributes and verify the EAs are
- * valid */
-int pass1c(struct fsck_sb *sbp)
-{
- uint64_t block_no = 0;
- osi_buf_t *bh;
- struct fsck_inode *ip = NULL;
- int update = 0;
- struct metawalk_fxns pass1c_fxns = { 0 };
- int error = 0;
-
- pass1c_fxns.check_eattr_indir = &check_eattr_indir;
- pass1c_fxns.check_eattr_leaf = &check_eattr_leaf;
- pass1c_fxns.check_eattr_entry = &check_eattr_entry;
- pass1c_fxns.check_eattr_extentry = &check_eattr_extentry;
- pass1c_fxns.private = (void *) &update;
-
- log_info("Looking for inodes containing ea blocks...\n");
- while (!find_next_block_type(sbp->bl, eattr_block, &block_no)) {
-
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return FSCK_OK;
- log_info("EA in inode %"PRIu64"\n", block_no);
- if(get_and_read_buf(sbp, block_no, &bh, 0)) {
- stack;
- return FSCK_ERROR;
- }
- if(copyin_inode(sbp, bh, &ip)) {
- stack;
- return FSCK_ERROR;
- }
-
- block_unmark(sbp->bl, block_no, eattr_block);
- log_debug("Found eattr at %"PRIu64"\n", ip->i_di.di_eattr);
- /* FIXME: Handle walking the eattr here */
- error = check_inode_eattr(ip, &pass1c_fxns);
- if(error < 0) {
- stack;
- return FSCK_ERROR;
- }
-
- if(update) {
- gfs_dinode_out(&ip->i_di, BH_DATA(bh));
- write_buf(sbp, bh, 0);
- }
-
- free_inode(&ip);
- relse_buf(sbp, bh);
-
- block_no++;
- }
- return FSCK_OK;
-}
diff --git a/gfs/gfs_fsck/pass2.c b/gfs/gfs_fsck/pass2.c
deleted file mode 100644
index 31c5ad7..0000000
--- a/gfs/gfs_fsck/pass2.c
+++ /dev/null
@@ -1,962 +0,0 @@
-#include "stdio.h"
-#include "fsck_incore.h"
-#include "fsck.h"
-#include "block_list.h"
-#include "bio.h"
-#include "fs_inode.h"
-#include "fs_dir.h"
-#include "util.h"
-#include "log.h"
-#include "inode_hash.h"
-#include "inode.h"
-#include "link.h"
-#include "metawalk.h"
-#include "eattr.h"
-
-#define MAX_FILENAME 256
-
-struct dir_status {
- uint8_t dotdir:1;
- uint8_t dotdotdir:1;
- struct block_query q;
- uint32_t entry_count;
-};
-
-
-/* Set children's parent inode in dir_info structure - ext2 does not set
- * dotdot inode here, but instead in pass3 - should we? */
-static int set_parent_dir(struct fsck_sb *sbp, uint64_t childblock,
- uint64_t parentblock)
-{
- struct dir_info *di;
-
- if(!find_di(sbp, childblock, &di)) {
- if(di->dinode == childblock) {
- if (di->treewalk_parent) {
- log_err("Another directory (%"PRIu64
- ") already contains"
- " this child - checking %"PRIu64"\n",
- di->treewalk_parent, parentblock);
- return 1;
- }
- di->treewalk_parent = parentblock;
- }
- } else {
- log_err("Unable to find block %"PRIu64" in dir_info list\n",
- childblock);
- return -1;
- }
-
- return 0;
-}
-
-/* Set's the child's '..' directory inode number in dir_info structure */
-static int set_dotdot_dir(struct fsck_sb *sbp, uint64_t childblock,
- uint64_t parentblock)
-{
- struct dir_info *di;
-
- if(!find_di(sbp, childblock, &di)) {
- if(di->dinode == childblock) {
- /* Special case for root inode because we set
- * it earlier */
- if(di->dotdot_parent && sbp->sb.sb_root_di.no_addr
- != di->dinode) {
- /* This should never happen */
- log_crit("dotdot parent already set for"
- " block %"PRIu64" -> %"PRIu64"\n",
- childblock, di->dotdot_parent);
- return -1;
- }
- di->dotdot_parent = parentblock;
- }
- } else {
- log_err("Unable to find block %"PRIu64" in dir_info list\n",
- childblock);
- return -1;
- }
-
- return 0;
-
-}
-
-static int check_eattr_indir(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh, void *private)
-{
-
- osi_buf_t *indir_bh;
-
- if(get_and_read_buf(ip->i_sbd, block, &indir_bh, 0)){
- log_warn("Unable to read EA indir block #%"PRIu64".\n",
- block);
- block_set(ip->i_sbd->bl, block, meta_inval);
- return 1;
- }
- *bh = indir_bh;
-
- return 0;
-}
-static int check_eattr_leaf(struct fsck_inode *ip, uint64_t block,
- uint64_t parent, osi_buf_t **bh, void *private)
-{
- osi_buf_t *leaf_bh = NULL;
-
- if(get_and_read_buf(ip->i_sbd, block, &leaf_bh, 0)){
- log_warn("Unable to read EA leaf block #%"PRIu64".\n",
- block);
- block_set(ip->i_sbd->bl, block, meta_inval);
- return 1;
- }
- *bh = leaf_bh;
-
- return 0;
-}
-
-static int check_file_type(uint16_t de_type, uint8_t block_type)
-{
- switch(block_type) {
- case inode_dir:
- if(de_type != GFS_FILE_DIR)
- return 1;
- break;
- case inode_file:
- if(de_type != GFS_FILE_REG)
- return 1;
- break;
- case inode_lnk:
- if(de_type != GFS_FILE_LNK)
- return 1;
- break;
- case inode_blk:
- if(de_type != GFS_FILE_BLK)
- return 1;
- break;
- case inode_chr:
- if(de_type != GFS_FILE_CHR)
- return 1;
- break;
- case inode_fifo:
- if(de_type != GFS_FILE_FIFO)
- return 1;
- break;
- case inode_sock:
- if(de_type != GFS_FILE_SOCK)
- return 1;
- break;
- default:
- log_err("Invalid block type\n");
- return -1;
- break;
- }
- return 0;
-}
-
-struct metawalk_fxns pass2_fxns_delete = {
- .private = NULL,
- .check_metalist = delete_metadata,
- .check_data = delete_data,
- .check_eattr_indir = delete_eattr_indir,
- .check_eattr_leaf = delete_eattr_leaf,
-};
-
-/* FIXME: should maybe refactor this a bit - but need to deal with
- * FIXMEs internally first */
-static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
- struct gfs_dirent *prev_de,
- osi_buf_t *bh, char *filename, int *update,
- uint16_t *count, void *priv)
-{
- struct fsck_sb *sbp = ip->i_sbd;
- struct block_query q = {0};
- char tmp_name[MAX_FILENAME];
- uint64_t entryblock;
- struct dir_status *ds = (struct dir_status *) priv;
- int error;
- struct fsck_inode *entry_ip = NULL;
- struct metawalk_fxns clear_eattrs = {0};
- struct gfs_dirent dentry, *de;
-
- memset(&dentry, 0, sizeof(struct gfs_dirent));
- gfs_dirent_in(&dentry, (char *)dent);
- de = &dentry;
-
- clear_eattrs.check_eattr_indir = clear_eattr_indir;
- clear_eattrs.check_eattr_leaf = clear_eattr_leaf;
- clear_eattrs.check_eattr_entry = clear_eattr_entry;
- clear_eattrs.check_eattr_extentry = clear_eattr_extentry;
-
- entryblock = de->de_inum.no_addr;
-
- /* Start of checks */
- if (de->de_rec_len < GFS_DIRENT_SIZE(de->de_name_len)){
- log_err("Dir entry with bad record or name length\n"
- "\tRecord length = %u\n"
- "\tName length = %u\n",
- de->de_rec_len,
- de->de_name_len);
- block_set(sbp->bl, ip->i_num.no_addr, meta_inval);
- return 1;
- /* FIXME: should probably delete the entry here at the
- * very least - maybe look at attempting to fix it */
- }
-
- if (de->de_hash != gfs_dir_hash(filename, de->de_name_len)){
- log_err("Dir entry with bad hash or name length\n"
- "\tHash found = %u\n"
- "\tName found = %s\n"
- "\tName length found = %u\n"
- "\tHash expected = %u\n",
- de->de_hash,
- filename,
- de->de_name_len,
- gfs_dir_hash(filename, de->de_name_len));
- return 1;
- }
- /* FIXME: This should probably go to the top of the fxn, and
- * references to filename should be replaced with tmp_name */
- memset(tmp_name, 0, MAX_FILENAME);
- if(de->de_name_len < MAX_FILENAME)
- strncpy(tmp_name, filename, de->de_name_len);
- else
- strncpy(tmp_name, filename, MAX_FILENAME - 1);
-
- if(check_range(ip->i_sbd, entryblock)) {
- log_err("Block # referenced by directory entry %s is out of range\n",
- tmp_name);
- errors_found++;
- if(query(ip->i_sbd, "Clear directory entry tp out of range block? (y/n) ")) {
- log_err("Clearing %s\n", tmp_name);
- if(dirent_del(ip, bh, prev_de, dent))
- log_err("Error encountered while removing bad "
- "directory entry. Skipping.\n");
- else
- errors_corrected++;
- *update = 1;
- return 1;
- } else {
- log_err("Directory entry to out of range block remains\n");
- (*count)++;
- ds->entry_count++;
- return 0;
- }
- }
- if(block_check(sbp->bl, de->de_inum.no_addr, &q)) {
- stack;
- return -1;
- }
- /* Get the status of the directory inode */
- if(q.bad_block) {
- /* This entry's inode has bad blocks in it */
-
- /* Handle bad blocks */
- log_err("Found a bad directory entry: %s at block %lld.\n",
- filename, de->de_inum.no_addr);
-
- errors_found++;
- if(query(sbp, "Delete the inode containing bad blocks? "
- "(y/n)")) {
- errors_corrected++;
- if (!load_inode(sbp, de->de_inum.no_addr, &entry_ip)) {
- check_inode_eattr(entry_ip,
- &pass2_fxns_delete);
- check_metatree(entry_ip, &pass2_fxns_delete);
- free_inode(&entry_ip);
- }
- dirent_del(ip, bh, prev_de, dent);
- block_set(sbp->bl, de->de_inum.no_addr, meta_free);
- *update = 1;
- log_warn("The inode containing bad blocks was "
- "deleted.\n");
- return 1;
- } else {
- log_warn("Entry to inode containing bad blocks remains\n");
- (*count)++;
- ds->entry_count++;
- return 0;
- }
-
- }
- if(q.block_type != inode_dir && q.block_type != inode_file &&
- q.block_type != inode_lnk && q.block_type != inode_blk &&
- q.block_type != inode_chr && q.block_type != inode_fifo &&
- q.block_type != inode_sock) {
- log_err("Directory entry '%s' for block %" PRIu64
- " in dir inode %" PRIu64 " block type %d: %s.\n",
- tmp_name, de->de_inum.no_addr, ip->i_num.no_addr,
- q.block_type, q.block_type == meta_inval ?
- "previously marked invalid" : "is not an inode");
-
- errors_found++;
- if(query(sbp, "Clear directory entry to non-inode block? "
- "(y/n) ")) {
- osi_buf_t *bhi;
-
- if(dirent_del(ip, bh, prev_de, dent)) {
- log_err("Error encountered while removing bad "
- "directory entry. Skipping.\n");
- return -1;
- }
- errors_corrected++;
- *update = 1;
- log_warn("Directory entry '%s' cleared\n", tmp_name);
-
- /* If it was previously marked invalid (i.e. known
- to be bad, not just a free block, etc.) then
- delete any metadata it holds. If not, return. */
- if (q.block_type != meta_inval)
- return 1;
-
- /* Now try to clear the dinode, if it is an dinode */
- get_and_read_buf(sbp, de->de_inum.no_addr, &bhi, 0);
- error = check_meta(bhi, GFS_METATYPE_DI);
- relse_buf(sbp, bhi);
- if (error)
- return 1; /* not a dinode: nothing to delete */
-
- if (!load_inode(sbp, de->de_inum.no_addr, &entry_ip)) {
- check_inode_eattr(entry_ip,
- &pass2_fxns_delete);
- check_metatree(entry_ip, &pass2_fxns_delete);
- free_inode(&entry_ip);
- }
- block_set(sbp->bl, de->de_inum.no_addr, block_free);
- return 1;
- } else {
- log_err("Directory entry to non-inode block remains\n");
- (*count)++;
- ds->entry_count++;
- return 0;
- }
- }
-
- error = check_file_type(de->de_type, q.block_type);
- if(error < 0) {
- stack;
- return -1;
- }
- if(error > 0) {
- log_warn("Type in dir entry (%s, %"PRIu64") conflicts with "
- "type in dinode. (Dir entry is stale.)\n",
- tmp_name, de->de_inum.no_addr);
- errors_found++;
- if(query(sbp, "Clear stale directory entry? (y/n) ")) {
- load_inode(sbp, de->de_inum.no_addr, &entry_ip);
- check_inode_eattr(entry_ip, &clear_eattrs);
- free_inode(&entry_ip);
-
- if(dirent_del(ip, bh, prev_de, dent))
- log_err("Error encountered while removing bad "
- "directory entry. Skipping.\n");
- else {
- errors_corrected++;
- *update = 1;
- log_err("Stale directory entry deleted\n");
- }
- return 1;
- } else {
- log_err("Stale directory entry remains\n");
- (*count)++;
- ds->entry_count++;
- return 0;
- }
- }
-
- if(!strcmp(".", tmp_name)) {
- log_debug("Found . dentry\n");
-
- if(ds->dotdir) {
- log_err("already found '.' entry\n");
- errors_found++;
- if(query(sbp, "Clear duplicate '.' entry? (y/n) ")) {
-
- errors_corrected++;
- load_inode(sbp, de->de_inum.no_addr, &entry_ip);
- check_inode_eattr(entry_ip, &clear_eattrs);
- free_inode(&entry_ip);
-
- dirent_del(ip, bh, prev_de, dent);
- *update = 1;
- return 1;
- } else {
- log_err("Duplicate '.' entry remains\n");
- /* FIXME: Should we continue on here
- * and check the rest of the '.'
- * entry? */
- increment_link(sbp, de->de_inum.no_addr);
- (*count)++;
- ds->entry_count++;
- return 0;
- }
- }
-
- /* GFS does not rely on '.' being in a certain
- * location */
-
- /* check that '.' refers to this inode */
- if(de->de_inum.no_addr != ip->i_num.no_addr) {
- log_err("'.' entry's value incorrect."
- " Points to %"PRIu64
- " when it should point to %"
- PRIu64".\n",
- de->de_inum.no_addr,
- ip->i_num.no_addr);
- errors_found++;
- if(query(sbp, "remove '.' reference? (y/n) ")) {
- errors_corrected++;
- load_inode(sbp, de->de_inum.no_addr, &entry_ip);
- check_inode_eattr(entry_ip, &clear_eattrs);
- free_inode(&entry_ip);
-
- dirent_del(ip, bh, prev_de, dent);
- *update = 1;
- return 1;
-
- } else {
- log_err("Invalid '.' reference remains\n");
- /* Not setting ds->dotdir here since
- * this '.' entry is invalid */
- increment_link(sbp, de->de_inum.no_addr);
- (*count)++;
- ds->entry_count++;
- return 0;
- }
- }
-
- ds->dotdir = 1;
- increment_link(sbp, de->de_inum.no_addr);
- (*count)++;
- ds->entry_count++;
-
- return 0;
- }
- if(!strcmp("..", tmp_name)) {
- log_debug("Found .. dentry\n");
- if(ds->dotdotdir) {
- log_err("already found '..' entry\n");
- errors_found++;
- if(query(sbp, "Clear duplicate '..' entry? (y/n) ")) {
-
- errors_corrected++;
- load_inode(sbp, de->de_inum.no_addr, &entry_ip);
- check_inode_eattr(entry_ip, &clear_eattrs);
- free_inode(&entry_ip);
-
- dirent_del(ip, bh, prev_de, dent);
- *update = 1;
- return 1;
- } else {
- log_err("Duplicate '..' entry remains\n");
- /* FIXME: Should we continue on here
- * and check the rest of the '..'
- * entry? */
- increment_link(sbp, de->de_inum.no_addr);
- (*count)++;
- ds->entry_count++;
- return 0;
- }
- }
-
- if(q.block_type != inode_dir) {
- log_err("Found '..' entry pointing to"
- " something that's not a directory");
- errors_found++;
- if(query(sbp, "Clear bad '..' directory entry? (y/n) ")) {
- errors_corrected++;
- load_inode(sbp, de->de_inum.no_addr, &entry_ip);
- check_inode_eattr(entry_ip, &clear_eattrs);
- free_inode(&entry_ip);
-
- dirent_del(ip, bh, prev_de, dent);
- *update = 1;
- return 1;
- } else {
- log_err("Bad '..' directory entry remains\n");
- increment_link(sbp, de->de_inum.no_addr);
- (*count)++;
- ds->entry_count++;
- return 0;
- }
- }
- /* GFS does not rely on '..' being in a
- * certain location */
-
- /* Add the address this entry is pointing to
- * to this inode's dotdot_parent in
- * dir_info */
- if(set_dotdot_dir(sbp, ip->i_num.no_addr,
- entryblock)) {
- stack;
- return -1;
- }
-
- ds->dotdotdir = 1;
- increment_link(sbp, de->de_inum.no_addr);
- *update = (sbp->opts->no ? 0 : 1);
- (*count)++;
- ds->entry_count++;
- return 0;
- }
-
- /* After this point we're only concerned with
- * directories */
- if(q.block_type != inode_dir) {
- log_debug("Found non-dir inode dentry\n");
- increment_link(sbp, de->de_inum.no_addr);
- *update = (sbp->opts->no ? 0 : 1);
- (*count)++;
- ds->entry_count++;
- return 0;
- }
-
- log_debug("Found plain directory dentry\n");
- error = set_parent_dir(sbp, entryblock, ip->i_num.no_addr);
- if(error > 0) {
- log_err("Hard link to block %"PRIu64" detected.\n", filename, entryblock);
-
- errors_found++;
- if(query(sbp, "Clear hard link to directory? (y/n) ")) {
- errors_corrected++;
- *update = 1;
-
- dirent_del(ip, bh, prev_de, dent);
- log_warn("Directory entry %s cleared\n", filename);
-
- return 1;
- } else {
- log_err("Hard link to directory remains\n");
- (*count)++;
- ds->entry_count++;
- return 0;
- }
- }
- else if (error < 0) {
- stack;
- return -1;
- }
- increment_link(sbp, de->de_inum.no_addr);
- *update = (sbp->opts->no ? 0 : 1);
- (*count)++;
- ds->entry_count++;
- /* End of checks */
- return 0;
-}
-
-
-struct metawalk_fxns pass2_fxns = {
- .private = NULL,
- .check_leaf = NULL,
- .check_metalist = NULL,
- .check_data = NULL,
- .check_eattr_indir = check_eattr_indir,
- .check_eattr_leaf = check_eattr_leaf,
- .check_dentry = check_dentry,
- .check_eattr_entry = NULL,
-};
-
-
-
-
-static int build_rooti(struct fsck_sb *sbp)
-{
- struct fsck_inode *ip;
- osi_buf_t *bh;
- get_and_read_buf(sbp, GFS_SB_ADDR >> sbp->fsb2bb_shift, &bh, 0);
- /* Create a new inode ondisk */
- create_inode(sbp, GFS_FILE_DIR, &ip);
- /* Attach it to the superblock's sb_root_di address */
- sbp->sb.sb_root_di.no_addr =
- sbp->sb.sb_root_di.no_formal_ino = ip->i_num.no_addr;
- /* Write out sb change */
- gfs_sb_out(&sbp->sb, BH_DATA(bh));
- write_buf(sbp, bh, 1);
- relse_buf(sbp, bh);
- sbp->rooti = ip;
-
- if(fs_dir_add(ip, &(osi_filename_t){(unsigned char *)".", 1},
- &(ip->i_num), ip->i_di.di_type)){
- stack;
- log_err("Unable to add \".\" entry to new root inode\n");
- return -1;
- }
-
- if(fs_dir_add(ip, &(osi_filename_t){(unsigned char *)"..", 2},
- &ip->i_num, ip->i_di.di_type)){
- stack;
- log_err("Unable to add \"..\" entry to new root inode\n");
- return -1;
- }
-
- block_set(sbp->bl, ip->i_num.no_addr, inode_dir);
- add_to_dir_list(sbp, ip->i_num.no_addr);
-
- /* Attach l+f to it */
- if(fs_mkdir(sbp->rooti, "l+f", 00700, &(sbp->lf_dip))){
- log_err("Unable to create/locate l+f directory.\n");
- return -1;
- }
-
- if(sbp->lf_dip){
- log_debug("Lost and Found directory inode is at "
- "block #%"PRIu64".\n",
- sbp->lf_dip->i_num.no_addr);
- }
- block_set(sbp->bl, sbp->lf_dip->i_num.no_addr, inode_dir);
-
- add_to_dir_list(sbp, sbp->lf_dip->i_num.no_addr);
-
- return 0;
-}
-
-/* Check root inode and verify it's in the bitmap */
-static int check_root_dir(struct fsck_sb *sbp)
-{
- uint64_t rootblock;
- struct dir_status ds = {0};
- struct fsck_inode *ip;
- osi_buf_t b, *bh = &b;
- osi_filename_t filename;
- char tmp_name[256];
- int update=0, error = 0;
- /* Read in the root inode, look at its dentries, and start
- * reading through them */
- rootblock = sbp->sb.sb_root_di.no_addr;
-
- /* FIXME: check this block's validity */
-
- if(block_check(sbp->bl, rootblock, &ds.q)) {
- log_crit("Can't get root block %"PRIu64" from block list\n",
- rootblock);
- /* FIXME: Need to check if the root block is out of
- * the fs range and if it is, rebuild it. Still can
- * error out if the root block number is valid, but
- * block_check fails */
- return -1;
-/* if(build_rooti(sbp)) {
- stack;
- return -1;
- }*/
- }
-
- /* if there are errors with the root inode here, we need to
- * create a new root inode and get it all setup - of course,
- * everything will be in l+f then, but we *need* a root inode
- * before we can do any of that.
- */
- if(ds.q.block_type != inode_dir) {
- log_err("Block %"PRIu64" marked as root inode in"
- " superblock not a directory\n", rootblock);
- errors_found++;
- if(query(sbp, "Create new root inode? (y/n) ")) {
- if(build_rooti(sbp)) {
- stack;
- return -1;
- }
- errors_corrected++;
- } else {
- log_err("Cannot continue without valid root inode\n");
- return -1;
- }
- }
-
- rootblock = sbp->sb.sb_root_di.no_addr;
- pass2_fxns.private = (void *) &ds;
- if(ds.q.bad_block) {
- /* First check that the directory's metatree is valid */
- load_inode(sbp, rootblock, &ip);
- if(check_metatree(ip, &pass2_fxns)) {
- stack;
- free_inode(&ip);
- return -1;
- }
- free_inode(&ip);
- }
- error = check_dir(sbp, rootblock, &pass2_fxns);
- if(error < 0) {
- stack;
- return -1;
- }
- if (error > 0) {
- block_set(sbp->bl, rootblock, meta_inval);
- }
-
- if(get_and_read_buf(sbp, rootblock, &bh, 0)){
- log_err("Unable to retrieve block #%"PRIu64"\n",
- rootblock);
- block_set(sbp->bl, rootblock, meta_inval);
- return -1;
- }
-
- if(copyin_inode(sbp, bh, &ip)) {
- stack;
- relse_buf(sbp, bh);
- return -1;
- }
-
- if(check_inode_eattr(ip, &pass2_fxns)) {
- stack;
- return -1;
- }
- /* FIXME: Should not have to do this here - fs_dir_add reads
- * the buffer too though, and commits the change to disk, so I
- * have to reread the buffer after calling it if I'm going to
- * make more changes */
- relse_buf(sbp, bh);
-
- if(!ds.dotdir) {
- log_err("No '.' entry found\n");
- errors_found++;
- if (query(sbp, "Is it okay to add '.' entry? (y/n) ")) {
- sprintf(tmp_name, ".");
- filename.len = strlen(tmp_name); /* no trailing NULL */
- if(!(filename.name =
- malloc(sizeof(char) * filename.len))) {
- log_err("Unable to allocate name string\n");
- stack;
- return -1;
- }
- if(!(memset(filename.name, 0, sizeof(char) *
- filename.len))) {
- log_err("Unable to zero name string\n");
- stack;
- return -1;
- }
- memcpy(filename.name, tmp_name, filename.len);
- log_warn("Adding '.' entry\n");
- if(fs_dir_add(ip, &filename, &(ip->i_num),
- ip->i_di.di_type)){
- log_err("Failed to link \".\" entry to "
- "directory.\n");
- return -1;
- }
- errors_corrected++;
- increment_link(ip->i_sbd, ip->i_num.no_addr);
- ds.entry_count++;
- free(filename.name);
- update = 1;
- } else
- log_err("The directory was not fixed.\n");
- }
- free_inode(&ip);
- if(get_and_read_buf(sbp, rootblock, &bh, 0)){
- log_err("Unable to retrieve block #%"PRIu64"\n",
- rootblock);
- block_set(sbp->bl, rootblock, meta_inval);
- return -1;
- }
-
- if(copyin_inode(sbp, bh, &ip)) {
- stack;
- relse_buf(sbp, bh);
- return -1;
- }
-
- if(ip->i_di.di_entries != ds.entry_count) {
- log_err("Entries is %d - should be %d for %"PRIu64"\n",
- ip->i_di.di_entries, ds.entry_count, ip->i_di.di_num.no_addr);
- errors_found++;
- if(query(sbp, "Fix entries for %"PRIu64"? (y/n) ",
- ip->i_di.di_num.no_addr)) {
- ip->i_di.di_entries = ds.entry_count;
- log_err("Entries updated\n");
- errors_corrected++;
- update = 1;
- } else {
- log_err("Entries for %"PRIu64" left out of sync\n",
- ip->i_di.di_num.no_addr);
- }
- }
-
- if(update) {
- gfs_dinode_out(&ip->i_di, BH_DATA(bh));
- write_buf(sbp, bh, 0);
- }
-
- free_inode(&ip);
- relse_buf(sbp, bh);
- return 0;
-}
-
-/* What i need to do in this pass is check that the dentries aren't
- * pointing to invalid blocks...and verify the contents of each
- * directory. and start filling in the directory info structure*/
-
-/**
- * pass2 - check pathnames
- *
- * verify root inode
- * directory name length
- * entries in range
- */
-int pass2(struct fsck_sb *sbp, struct options *opts)
-{
- uint64_t i;
- struct block_query q;
- struct dir_status ds = {0};
- struct fsck_inode *ip;
- osi_buf_t b, *bh = &b;
- osi_filename_t filename;
- char tmp_name[256];
- int error = 0;
- int need_update = 0;
-
- if(check_root_dir(sbp)) {
- stack;
- return FSCK_ERROR;
- }
-
- log_info("Checking directory inodes.\n");
- /* Grab each directory inode, and run checks on it */
- for(i = 0; i < sbp->last_fs_block; i++) {
- need_update = 0;
- warm_fuzzy_stuff(i);
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return FSCK_OK;
-
- /* Skip the root inode - it's checked above */
- if(i == sbp->sb.sb_root_di.no_addr)
- continue;
-
- if(block_check(sbp->bl, i, &q)) {
- log_err("Can't get block %"PRIu64 " from block list\n",
- i);
- return FSCK_ERROR;
- }
-
- if(q.block_type != inode_dir)
- continue;
-
- log_debug("Checking directory inode at block %"PRIu64"\n", i);
-
-
- memset(&ds, 0, sizeof(ds));
- pass2_fxns.private = (void *) &ds;
- if(ds.q.bad_block) {
- /* First check that the directory's metatree
- * is valid */
- load_inode(sbp, i, &ip);
- if(check_metatree(ip, &pass2_fxns)) {
- stack;
- free_inode(&ip);
- return FSCK_ERROR;
- }
- free_inode(&ip);
- }
- error = check_dir(sbp, i, &pass2_fxns);
- if(error < 0) {
- stack;
- return FSCK_ERROR;
- }
- if (error > 0) {
- struct dir_info *di = NULL;
- error = find_di(sbp, i, &di);
- if(error < 0) {
- stack;
- return FSCK_ERROR;
- }
- if(error == 0) {
- /* FIXME: factor */
- errors_found++;
- if(query(sbp, "Remove directory entry for bad"
- " inode %"PRIu64" in %"PRIu64
- "? (y/n)", i, di->treewalk_parent)) {
- error = remove_dentry_from_dir(sbp,
- di->treewalk_parent,
- i);
- if(error < 0) {
- stack;
- return FSCK_ERROR;
- }
- if(error > 0) {
- log_warn("Unable to find dentry for %"
- PRIu64" in %"PRIu64"\n",
- i, di->treewalk_parent);
- }
- errors_corrected++;
- log_warn("Directory entry removed\n");
- } else {
- log_err("Directory entry to invalid inode remains\n");
- }
- }
- block_set(sbp->bl, i, meta_inval);
- }
- if(get_and_read_buf(sbp, i, &bh, 0)){
- /* This shouldn't happen since we were able to
- * read it before */
- log_err("Unable to retrieve block #%"PRIu64
- " for directory\n",
- i);
- return FSCK_ERROR;
- }
-
- if(copyin_inode(sbp, bh, &ip)) {
- stack;
- relse_buf(sbp, bh);
- return FSCK_ERROR;
- }
-
- if(!ds.dotdir) {
- log_err("No '.' entry found for directory inode at "
- "block %" PRIu64 "\n", i);
- errors_found++;
- if (query(sbp,
- "Is it okay to add '.' entry? (y/n) ")) {
- sprintf(tmp_name, ".");
- filename.len = strlen(tmp_name); /* no trailing
- NULL */
- if(!(filename.name = malloc(sizeof(char) *
- filename.len))) {
- log_err("Unable to allocate name\n");
- stack;
- return FSCK_ERROR;
- }
- if(!memset(filename.name, 0, sizeof(char) *
- filename.len)) {
- log_err("Unable to zero name\n");
- stack;
- return FSCK_ERROR;
- }
- memcpy(filename.name, tmp_name, filename.len);
-
- if(fs_dir_add(ip, &filename, &(ip->i_num),
- ip->i_di.di_type)){
- log_err("Failed to link \".\" entry "
- "to directory.\n");
- return FSCK_ERROR;
- }
- errors_corrected++;
- increment_link(ip->i_sbd, ip->i_num.no_addr);
- ds.entry_count++;
- free(filename.name);
- log_err("The directory was fixed.\n");
- need_update = 1;
- } else {
- log_err("The directory was not fixed.\n");
- }
- }
-
- if(ip->i_di.di_entries != ds.entry_count) {
- log_err("Entries is %d - should be %d for inode "
- "block %" PRIu64 "\n",
- ip->i_di.di_entries, ds.entry_count,
- ip->i_di.di_num.no_addr);
- errors_found++;
- if (query(sbp, "Fix the entry count? (y/n) ")) {
- errors_corrected++;
- ip->i_di.di_entries = ds.entry_count;
- need_update = 1;
- } else {
- log_err("The entry count was not fixed.\n");
- }
- }
- if (need_update) {
- gfs_dinode_out(&ip->i_di, BH_DATA(bh));
- write_buf(sbp, bh, 0);
- free_inode(&ip);
- relse_buf(sbp, bh);
- }
- }
- return FSCK_OK;
-}
-
-
-
diff --git a/gfs/gfs_fsck/pass3.c b/gfs/gfs_fsck/pass3.c
deleted file mode 100644
index 08ee24f..0000000
--- a/gfs/gfs_fsck/pass3.c
+++ /dev/null
@@ -1,281 +0,0 @@
-#include <stdio.h>
-#include "osi_list.h"
-#include "fsck_incore.h"
-#include "fsck.h"
-#include "inode.h"
-#include "lost_n_found.h"
-#include "block_list.h"
-#include "fs_dir.h"
-#include "link.h"
-#include "metawalk.h"
-
-static int attach_dotdot_to(struct fsck_sb *sbp, uint64_t newdotdot,
- uint64_t olddotdot, uint64_t block)
-{
- osi_filename_t filename;
- struct fsck_inode *ip, *pip;
-
- load_inode(sbp, block, &ip);
- load_inode(sbp, newdotdot, &pip);
- /* FIXME: Need to add some interactive
- * options here and come up with a
- * good default for non-interactive */
- /* FIXME: do i need to correct the
- * '..' entry for this directory in
- * this case? */
-
- filename.len = strlen("..");
- if(!(filename.name = malloc(sizeof(char) * filename.len + 1))) {
- log_err("Unable to allocate name\n");
- free_inode(&ip);
- free_inode(&pip);
- stack;
- return -1;
- }
- if(!memset(filename.name, 0, (sizeof(char) * filename.len + 1))) {
- log_err("Unable to zero name\n");
- free_inode(&ip);
- free_inode(&pip);
- stack;
- return -1;
- }
- memcpy(filename.name, "..", filename.len);
- if(fs_dirent_del(ip, NULL, &filename))
- log_warn("Unable to remove \"..\" directory entry.\n");
- else
- decrement_link(sbp, olddotdot);
- if(fs_dir_add(ip, &filename, &pip->i_num,
- pip->i_di.di_type)){
- log_err("Failed to link \"..\" entry to directory.\n");
- block_set(ip->i_sbd->bl, ip->i_num.no_addr, meta_inval);
- free_inode(&ip);
- free_inode(&pip);
- return -1;
- }
- increment_link(sbp, newdotdot);
- free_inode(&ip);
- free_inode(&pip);
- return 0;
-}
-
-static struct dir_info *mark_and_return_parent(struct fsck_sb *sbp,
- struct dir_info *di)
-{
- struct dir_info *pdi;
-
- struct block_query q_dotdot, q_treewalk;
-
- di->checked = 1;
-
- if(!di->treewalk_parent)
- return NULL;
-
- if(di->dotdot_parent != di->treewalk_parent) {
- log_warn(".. and treewalk conections are not the same for %"PRIu64
- "\n", di->dinode);
- log_notice("%"PRIu64" %"PRIu64"\n", di->dotdot_parent, di->treewalk_parent);
- if(block_check(sbp->bl, di->dotdot_parent, &q_dotdot)) {
- log_err("Unable to find block %"PRIu64
- " in block map\n",
- di->dotdot_parent);
- return NULL;
- }
- if(block_check(sbp->bl, di->treewalk_parent, &q_treewalk)) {
- log_err("Unable to find block %"PRIu64
- " in block map\n",
- di->treewalk_parent);
- return NULL;
- }
- /* if the dotdot entry isn't a directory, but the
- * treewalk is, treewalk is correct - if the treewalk
- * entry isn't a directory, but the dotdot is, dotdot
- * is correct - if both are directories, which do we
- * choose? if neither are directories, we have a
- * problem - need to move this directory into l+f
- */
- if(q_dotdot.block_type != inode_dir) {
- if(q_treewalk.block_type != inode_dir) {
- log_err( "Orphaned directory, move to l+f\n");
- return NULL;
- }
- else {
- log_warn("Treewalk parent is correct,"
- " fixing dotdot -> %"PRIu64"\n",
- di->treewalk_parent);
- attach_dotdot_to(sbp, di->treewalk_parent,
- di->dotdot_parent, di->dinode);
- di->dotdot_parent = di->treewalk_parent;
- }
- }
- else {
- if(q_treewalk.block_type != inode_dir) {
- int error = 0;
- log_warn(".. parent is valid, but treewalk"
- "is bad - reattaching to l+f");
-
- /* FIXME: add a dinode for this entry instead? */
- errors_found++;
- if(query(sbp, "Remove directory entry for bad"
- " inode %"PRIu64" in %"PRIu64
- "? (y/n)", di->dinode,
- di->treewalk_parent)) {
- error = remove_dentry_from_dir(sbp,
- di->treewalk_parent,
- di->dinode);
- if(error < 0) {
- stack;
- return NULL;
- }
- if(error > 0) {
- log_warn("Unable to find dentry for %"
- PRIu64" in %"PRIu64"\n",
- di->dinode, di->treewalk_parent);
- }
- errors_corrected++;
- log_warn("Directory entry removed\n");
- } else {
- log_err("Directory entry to invalid inode remains\n");
- }
- log_info("Marking directory unlinked\n");
-
- return NULL;
- }
- else {
- log_err("Both .. and treewalk parents are "
- "directories, going with treewalk for "
- "now...\n");
- attach_dotdot_to(sbp, di->treewalk_parent,
- di->dotdot_parent, di->dinode);
- di->dotdot_parent = di->treewalk_parent;
- }
- }
- }
- else {
- if(block_check(sbp->bl, di->dotdot_parent, &q_dotdot)) {
- log_err("Unable to find parent block %"PRIu64
- " in block map\n",
- di->dotdot_parent);
- return NULL;
- }
- if(q_dotdot.block_type != inode_dir) {
- log_err("Orphaned directory, move to l+f (Block #%"
- PRIu64")\n", di->dinode);
- return NULL;
- }
- }
- find_di(sbp, di->dotdot_parent, &pdi);
-
- return pdi;
-}
-
-/**
- * pass3 - check connectivity of directories
- *
- * handle disconnected directories
- * handle lost+found directory errors (missing, not a directory, no space)
- */
-int pass3(struct fsck_sb *sbp, struct options *opts)
-{
- osi_list_t *tmp;
- struct dir_info *di, *tdi;
- struct fsck_inode *ip;
- struct block_query q;
- int i;
-
- find_di(sbp, sbp->sb.sb_root_di.no_addr, &di);
- if(di) {
- log_info("Marking root inode connected\n");
- di->checked = 1;
- }
-
- /* Go through the directory list, working up through the parents
- * until we find one that's been checked already. If we don't
- * find a parent, put in lost+found.
- */
- log_info("Checking directory linkage.\n");
- for(i = 0; i < FSCK_HASH_SIZE; i++) {
- osi_list_foreach(tmp, &sbp->dir_hash[i]) {
- di = osi_list_entry(tmp, struct dir_info, list);
- while(!di->checked) {
- /* FIXME: Change this so it returns success or
- * failure and put the parent inode in a
- * param */
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return FSCK_OK;
- tdi = mark_and_return_parent(sbp, di);
-
- /* FIXME: Factor this ? */
- if(!tdi) {
- if(block_check(sbp->bl, di->dinode, &q)) {
- stack;
- return FSCK_ERROR;
- }
- if(q.bad_block) {
- log_err("Found unlinked directory containing"
- "bad block\n");
- errors_found++;
- if(query(sbp, "Clear unlinked directory with bad blocks? (y/n) ")) {
- block_set(sbp->bl, di->dinode, block_free);
- errors_corrected++;
- break;
- } else {
- log_err("Unlinked directory with bad blocks remains\n");
- }
- }
- if(q.block_type != inode_dir &&
- q.block_type != inode_file &&
- q.block_type != inode_lnk &&
- q.block_type != inode_blk &&
- q.block_type != inode_chr &&
- q.block_type != inode_fifo &&
- q.block_type != inode_sock) {
- log_err("Unlinked block marked as inode not an inode\n");
- block_set(sbp->bl, di->dinode, block_free);
- log_err("Cleared\n");
- break;
- }
-
- log_err("Found unlinked directory %"PRIu64"\n", di->dinode);
- load_inode(sbp, di->dinode, &ip);
- /* Don't skip zero size directories
- * with eattrs */
- if(!ip->i_di.di_size && !ip->i_di.di_eattr){
- log_err("Unlinked directory has zero size.\n");
- errors_found++;
- if(query(sbp, "Remove zero-size unlinked directory? (y/n) ")) {
- errors_corrected++;
- block_set(sbp->bl, di->dinode, block_free);
- free_inode(&ip);
- break;
- } else {
- log_err("Zero-size unlinked directory remains\n");
- }
- }
- errors_found++;
- if(query(sbp, "Add unlinked directory to l+f? (y/n) ")) {
- errors_corrected++;
- if(add_inode_to_lf(ip)) {
- stack;
- free_inode(&ip);
- return FSCK_ERROR;
- }
- log_warn("Directory relinked to l+f\n");
- } else {
- log_err("Unlinked directory remains unlinked\n");
- }
- free_inode(&ip);
- break;
- }
- else {
- log_debug("Directory at block %" PRIu64 " connected\n",
- di->dinode);
- }
- di = tdi;
- }
- }
- }
- if(sbp->lf_dip)
- log_debug("At end of pass3, l+f entries is %u\n",
- sbp->lf_dip->i_di.di_entries);
- return FSCK_OK;
-}
diff --git a/gfs/gfs_fsck/pass4.c b/gfs/gfs_fsck/pass4.c
deleted file mode 100644
index cb4255e..0000000
--- a/gfs/gfs_fsck/pass4.c
+++ /dev/null
@@ -1,233 +0,0 @@
-#include "stdio.h"
-#include "fsck_incore.h"
-#include "fsck.h"
-#include "bio.h"
-#include "fs_inode.h"
-#include "inode_hash.h"
-#include "inode.h"
-#include "lost_n_found.h"
-#include "metawalk.h"
-
-struct metawalk_fxns pass4_fxns_delete = {
- .private = NULL,
- .check_metalist = delete_metadata,
- .check_data = delete_data,
- .check_eattr_indir = delete_eattr_indir,
- .check_eattr_leaf = delete_eattr_leaf,
-};
-
-/* Updates the link count of an inode to what the fsck has seen for
- * link count */
-static int fix_inode_count(struct fsck_sb *sbp, struct inode_info *ii,
- struct fsck_inode *ip)
-{
- log_info("Fixing inode count for %"PRIu64"\n",
- ip->i_di.di_num.no_addr);
- if(ip->i_di.di_nlink == ii->counted_links)
- return 0;
- ip->i_di.di_nlink = ii->counted_links;
-
- log_debug("Changing inode %"PRIu64" to have %u links\n",
- ip->i_di.di_num.no_addr, ii->counted_links);
-
- fs_copyout_dinode(ip);
-
- return 0;
-}
-
-static int scan_inode_list(struct fsck_sb *sbp, osi_list_t *list) {
- osi_list_t *tmp;
- struct inode_info *ii;
- struct fsck_inode *ip;
- int lf_addition = 0;
- struct block_query q;
-
- /* FIXME: should probably factor this out into a generic
- * scanning fxn */
- osi_list_foreach(tmp, list) {
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return 0;
- if(!(ii = osi_list_entry(tmp, struct inode_info, list))) {
- log_crit("osi_list_foreach broken in scan_info_list!!\n");
- exit(FSCK_ERROR);
- }
- /* Don't check reference counts on the special gfs files */
- if((ii->inode == sbp->sb.sb_rindex_di.no_addr) ||
- (ii->inode == sbp->sb.sb_jindex_di.no_addr) ||
- (ii->inode == sbp->sb.sb_quota_di.no_addr) ||
- (ii->inode == sbp->sb.sb_license_di.no_addr))
- continue;
- log_debug("Checking reference count on inode at block %"PRIu64
- "\n", ii->inode);
- if(ii->counted_links == 0) {
- log_err("Found unlinked inode at %"PRIu64"\n",
- ii->inode);
- if(block_check(sbp->bl, ii->inode, &q)) {
- stack;
- return -1;
- }
- if(q.bad_block) {
- log_err("Unlinked inode contains"
- "bad blocks\n",
- ii->inode);
- errors_found++;
- if(query(sbp, "Delete unlinked inode with bad "
- "blocks? (y/n) ")) {
- errors_corrected++;
- load_inode(sbp, ii->inode, &ip);
- check_inode_eattr(ip,
- &pass4_fxns_delete);
- check_metatree(ip, &pass4_fxns_delete);
- free_inode(&ip);
- block_set(sbp->bl, ii->inode,
- block_free);
- log_err("Unlinked inode with bad blocks cleared\n");
- continue;
- } else
- log_err("Unlinked inode with bad blocks not cleared\n");
- }
- if(q.block_type != inode_dir &&
- q.block_type != inode_file &&
- q.block_type != inode_lnk &&
- q.block_type != inode_blk &&
- q.block_type != inode_chr &&
- q.block_type != inode_fifo &&
- q.block_type != inode_sock) {
- log_err("Unlinked block marked as an inode is "
- "not an inode (%d)\n", q.block_type);
- errors_found++;
- if(query(sbp, "Delete unlinked inode"
- "? (y/n) ")) {
- errors_corrected++;
- if (!load_inode(sbp, ii->inode, &ip)) {
- check_inode_eattr(ip,
- &pass4_fxns_delete);
- check_metatree(ip,
- &pass4_fxns_delete);
- }
- block_set(sbp->bl, ii->inode,
- block_free);
- free_inode(&ip);
- log_err("The inode was deleted\n");
- } else
- log_err("The inode was not deleted\n");
-
- continue;
- }
- if(load_inode(sbp, ii->inode, &ip)) {
- stack;
- return -1;
- }
- if(!sbp->opts->no) {
- /* We don't want to clear zero-size files with
- * eattrs - there might be relevent info in
- * them. */
- if(!ip->i_di.di_size && !ip->i_di.di_eattr){
- log_err("Unlinked inode has zero "
- "size\n");
- errors_found++;
- if(query(sbp, "Clear zero-size "
- "unlinked inode? (y/n) ")) {
- errors_corrected++;
- block_set(sbp->bl, ii->inode,
- block_free);
- free_inode(&ip);
- log_err("Unlinked inode with "
- "zero size cleared\n");
- continue;
- } else
- log_err("Unlinked inode with "
- "zero size not "
- "cleared\n");
- }
- errors_found++;
- if(query(sbp, "Add unlinked inode to l+f? "
- "(y/n)")) {
- if(add_inode_to_lf(ip)) {
- stack;
- free_inode(&ip);
- log_err("Unable to unlinked "
- "inode to l+f\n");
- return -1;
- } else {
- fix_inode_count(sbp, ii, ip);
- lf_addition = 1;
- errors_corrected++;
- log_err("Unlinked inode added "
- "to l+f\n");
- }
- } else
- log_err("Unlinked inode left "
- "unlinked\n");
- }
- free_inode(&ip);
- }
- else if(ii->link_count != ii->counted_links) {
- log_err("Link count inconsistent for inode %"PRIu64
- " - %u %u\n",
- ii->inode, ii->link_count, ii->counted_links);
- /* Read in the inode, adjust the link count,
- * and write it back out */
- errors_found++;
- if(query(sbp, "Update link count for inode %"
- PRIu64"? (y/n) ", ii->inode)) {
- errors_corrected++;
- load_inode(sbp, ii->inode, &ip);
- fix_inode_count(sbp, ii, ip);
- free_inode(&ip);
- log_warn("Link count updated for inode %"
- PRIu64"\n", ii->inode);
- } else {
- log_err("Link count for inode %"
- PRIu64" still incorrect\n", ii->inode);
- }
- }
- log_debug("block %"PRIu64" has link count %d\n", ii->inode,
- ii->link_count);
- }
-
- if (lf_addition) {
- if(!(ii = inode_hash_search(sbp->inode_hash,
- sbp->lf_dip->i_num.no_addr))) {
- log_crit("Unable to find l+f inode in inode_hash!!\n");
- return -1;
- } else {
- fix_inode_count(sbp, ii, sbp->lf_dip);
- }
- }
-
- return 0;
-}
-
-/**
- * pass4 - Check reference counts (pass 2 & 6 in current fsck)
- *
- * handle unreferenced files
- * lost+found errors (missing, not a directory, no space)
- * adjust link count
- * handle unreferenced inodes of other types
- * handle bad blocks
- */
-int pass4(struct fsck_sb *sbp, struct options *opts)
-{
- uint32_t i;
- osi_list_t *list;
- if(sbp->lf_dip)
- log_debug("At beginning of pass4, l+f entries is %u\n",
- sbp->lf_dip->i_di.di_entries);
- log_info("Checking inode reference counts.\n");
- for (i = 0; i < FSCK_HASH_SIZE; i++) {
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return FSCK_OK;
- list = &sbp->inode_hash[i];
- if(scan_inode_list(sbp, list)) {
- stack;
- return FSCK_ERROR;
- }
- }
-
- if(sbp->lf_dip)
- log_debug("At end of pass4, l+f entries is %u\n",
- sbp->lf_dip->i_di.di_entries);
- return FSCK_OK;
-}
diff --git a/gfs/gfs_fsck/pass5.c b/gfs/gfs_fsck/pass5.c
deleted file mode 100644
index 9916664..0000000
--- a/gfs/gfs_fsck/pass5.c
+++ /dev/null
@@ -1,394 +0,0 @@
-#include <stdio.h>
-#include "fsck_incore.h"
-#include "fsck.h"
-#include "ondisk.h"
-#include "fs_bits.h"
-#include "bio.h"
-#include "util.h"
-
-#ifdef DEBUG
-int rgrp_countbits(unsigned char *buffer, unsigned int buflen,
- uint32_t *bit_array)
-{
- unsigned char *byte, *end;
- unsigned int bit;
- unsigned char state;
-
- byte = buffer;
- bit = 0;
- end = buffer + buflen;
-
- while (byte < end){
- state = ((*byte >> bit) & GFS_BIT_MASK);
- switch (state) {
- case GFS_BLKST_FREE:
- bit_array[0]++;
- break;
- case GFS_BLKST_USED:
- bit_array[1]++;
- break;
- case GFS_BLKST_FREEMETA:
- bit_array[2]++;
- break;
- case GFS_BLKST_USEDMETA:
- bit_array[3]++;
- break;
- default:
- log_err("Invalid state %d found at byte %u, bit %u\n",
- state, byte, bit);
- return -1;
- break;
- }
-
- bit += GFS_BIT_SIZE;
- if (bit >= 8){
- bit = 0;
- byte++;
- }
- }
- return 0;
-}
-
-int fsck_countbits(struct fsck_sb *sbp, uint64_t start_blk, uint64_t count,
- uint32_t *bit_array)
-{
- uint64_t i;
- struct block_query q;
- for(i = start_blk; i < start_blk+count; i++) {
- block_check(sbp->bl, i, &q);
- switch(q.block_type) {
- case block_free:
- bit_array[0]++;
- break;
- case block_used:
- bit_array[1]++;
- break;
- case meta_free:
- case meta_inval:
- bit_array[2]++;
- break;
- case indir_blk:
- case inode_dir:
- case inode_file:
- case leaf_blk:
- case journal_blk:
- case meta_other:
- case meta_eattr:
- bit_array[3]++;
- break;
- default:
- log_err("Invalid state %d found at block%"PRIu64"\n",
- q.block_type, i);
- return -1;
- break;
- }
- }
- return 0;
-}
-
-
-int count_bmaps(struct fsck_rgrp *rgp)
-{
- uint32_t i;
- uint32_t bit_array_rgrp[4] = {0};
- uint32_t bit_array_fsck[4] = {0};
- fs_bitmap_t *bits;
-
- for(i = 0; i < rgp->rd_ri.ri_length; i++) {
- bits = &rgp->rd_bits[i];
- rgrp_countbits(BH_DATA(rgp->rd_bh[i]) + bits->bi_offset,
- bits->bi_len, bit_array_rgrp);
- }
- log_err("rgrp: free %u used %u meta_free %u meta_used %u\n",
- bit_array_rgrp[0], bit_array_rgrp[1],
- bit_array_rgrp[2], bit_array_rgrp[3]);
- fsck_countbits(rgp->rd_sbd, rgp->rd_ri.ri_data1,
- rgp->rd_ri.ri_data, bit_array_fsck);
- log_err("fsck: free %u used %u meta_free %u meta_used %u\n",
- bit_array_fsck[0], bit_array_fsck[1],
- bit_array_fsck[2], bit_array_fsck[3]);
-
- for(i = 0; i < 4; i++) {
- if(bit_array_rgrp[i] != bit_array_fsck[i]) {
- log_err("Bitmap count in index %d differ: "
- "ondisk %d, fsck %d\n", i,
- bit_array_rgrp[i], bit_array_fsck[i]);
- }
- }
- return 0;
-}
-#endif /* DEBUG */
-
-static int convert_mark(enum mark_block mark, uint32_t *count)
-{
- switch(mark) {
-
- case meta_inval:
- /* Convert invalid metadata to free blocks */
- case block_free:
- count[0]++;
- return GFS_BLKST_FREE;
-
- case meta_free:
- count[4]++;
- return GFS_BLKST_FREEMETA;
-
- case block_used:
- return GFS_BLKST_USED;
-
- case inode_dir:
- case inode_file:
- case inode_lnk:
- case inode_blk:
- case inode_chr:
- case inode_fifo:
- case inode_sock:
- count[1]++;
- return GFS_BLKST_USEDMETA;
-
- case indir_blk:
- case leaf_blk:
- case journal_blk:
- case meta_other:
- case meta_eattr:
- count[3]++;
- return GFS_BLKST_USEDMETA;
-
- default:
- log_err("Invalid state %d found\n", mark);
- return -1;
-
- }
- return -1;
-}
-
-static const char *block_type_string(struct block_query *q)
-{
- const char *blktyp[] = {"free", "used", "indirect data", "directory",
- "file", "symlink", "block dev", "char dev",
- "fifo", "socket", "dir leaf", "journ data",
- "other meta", "free meta", "meta eattr",
- "bad blk", "dup block", "eattr", "invalid"};
- if (q->block_type < 18)
- return (blktyp[q->block_type]);
- return blktyp[18];
-}
-
-static int check_block_status(struct fsck_sb *sbp, char *buffer, unsigned int buflen,
- uint64_t *rg_block, uint64_t rg_data, uint32_t *count)
-{
- unsigned char *byte, *end;
- unsigned int bit;
- unsigned char rg_status, block_status;
- struct block_query q;
- uint64_t block;
-
- byte = (unsigned char *)buffer;
- bit = 0;
- end = (unsigned char *)buffer + buflen;
-
- while(byte < end) {
- rg_status = ((*byte >> bit) & GFS_BIT_MASK);
- block = rg_data + *rg_block;
- warm_fuzzy_stuff(block);
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return 0;
- block_check(sbp->bl, block, &q);
-
- block_status = convert_mark(q.block_type, count);
-
- if(rg_status != block_status) {
- log_debug("Ondisk is %u - FSCK thinks it is %u (%u)\n",
- rg_status, block_status, q.block_type);
- if((rg_status == GFS_BLKST_FREEMETA) &&
- (block_status == GFS_BLKST_FREE)) {
- if(!sbp->opts->no) {
- errors_found++;
- log_info("Converting free metadata "
- "block at %" PRIu64 " to a "
- "free data block\n", block);
- if(fs_set_bitmap(sbp, block, block_status)) {
- log_warn("Failed to convert free metadata block to free data block at %PRIu64.\n", block);
- }
- else {
- log_err("Succeeded.\n");
- errors_corrected++;
- }
- }
- /* If we have free_meta blocks but -n was
- specified, we can't convert them. But it's
- also not technically an error. */
- }
- else {
- const char *blockstatus[] = {"Free", "Data",
- "Free Meta",
- "Metadata"};
-
- log_err("ondisk and fsck bitmaps differ at"
- " block %"PRIu64"\n", block);
- log_err("Ondisk status is %u (%s) but FSCK "
- "thinks it should be ",
- rg_status, blockstatus[rg_status]);
- log_err("%u (%s)\n", block_status,
- blockstatus[block_status]);
- log_err("Metadata type is %u (%s)\n",
- q.block_type,
- block_type_string(&q));
-
- errors_found++;
- if(query(sbp, "Fix bitmap for block %"
- PRIu64"? (y/n) ", block)) {
- if(fs_set_bitmap(sbp, block, block_status))
- log_err("Failed.\n");
- else {
- log_err("Succeeded.\n");
- errors_corrected++;
- }
- } else
- log_err("Bitmap at block %"PRIu64
- " left inconsistent\n", block);
- }
- }
- (*rg_block)++;
- bit += GFS_BIT_SIZE;
- if (bit >= 8){
- bit = 0;
- byte++;
- }
- }
-
- return 0;
-}
-
-#define FREE_COUNT 1
-#define USED_INODE_COUNT 2
-#define FREE_INODE_COUNT 4
-#define USED_META_COUNT 8
-#define FREE_META_COUNT 16
-#define CONVERT_FREEMETA_TO_FREE (FREE_COUNT | FREE_META_COUNT)
-
-static int update_rgrp(struct fsck_rgrp *rgp, uint32_t *count, int rgcount)
-{
- uint32_t i;
- fs_bitmap_t *bits;
- uint64_t rg_block = 0;
- uint8_t bmap = 0;
-
- for(i = 0; i < rgp->rd_ri.ri_length; i++) {
- bits = &rgp->rd_bits[i];
-
- /* update the bitmaps */
- check_block_status(rgp->rd_sbd,
- BH_DATA(rgp->rd_bh[i]) + bits->bi_offset,
- bits->bi_len, &rg_block,
- rgp->rd_ri.ri_data1, count);
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return 0;
- }
-
- /* Compare the rgrps counters with what we found */
- if(rgp->rd_rg.rg_free != count[0]) {
- bmap |= FREE_COUNT;
- }
- if(rgp->rd_rg.rg_useddi != count[1]) {
- bmap |= USED_INODE_COUNT;
- }
- if(rgp->rd_rg.rg_freedi != count[2]) {
- bmap |= FREE_INODE_COUNT;
- }
- if(rgp->rd_rg.rg_usedmeta != count[3]) {
- bmap |= USED_META_COUNT;
- }
- if(rgp->rd_rg.rg_freemeta != count[4]) {
- bmap |= FREE_META_COUNT;
- }
-
- if(bmap && !(bmap & ~CONVERT_FREEMETA_TO_FREE)) {
- log_notice("Converting %d unused metadata blocks to free data blocks...\n",
- rgp->rd_rg.rg_freemeta - count[4]);
- rgp->rd_rg.rg_free = count[0];
- rgp->rd_rg.rg_freemeta = count[4];
- gfs_rgrp_out(&rgp->rd_rg, BH_DATA(rgp->rd_bh[0]));
- if(!rgp->rd_sbd->opts->no) {
- write_buf(rgp->rd_sbd, rgp->rd_bh[0], 0);
- }
- } else if(bmap) {
- /* actually adjust counters and write out to disk */
- if(bmap & FREE_COUNT) {
- log_err("RG #%d free count inconsistent: is %u should be %u\n",
- rgcount, rgp->rd_rg.rg_free, count[0] );
- rgp->rd_rg.rg_free = count[0];
- }
- if(bmap & USED_INODE_COUNT) {
- log_err("RG #%d used inode count inconsistent: is %u should be %u\n",
- rgcount, rgp->rd_rg.rg_useddi, count[1]);
- rgp->rd_rg.rg_useddi = count[1];
- }
- if(bmap & FREE_INODE_COUNT) {
- log_err("RG #%d free inode count inconsistent: is %u should be %u\n",
- rgcount, rgp->rd_rg.rg_freedi, count[2]);
- rgp->rd_rg.rg_freedi = count[2];
- }
- if(bmap & USED_META_COUNT) {
- log_err("RG #%d used meta count inconsistent: is %u should be %u\n",
- rgcount, rgp->rd_rg.rg_usedmeta, count[3]);
- rgp->rd_rg.rg_usedmeta = count[3];
- }
- if(bmap & FREE_META_COUNT) {
- log_err("RG #%d free meta count inconsistent: is %u should be %u\n",
- rgcount, rgp->rd_rg.rg_freemeta, count[4]);
- rgp->rd_rg.rg_freemeta = count[4];
- }
-
- errors_found++;
- if(query(rgp->rd_sbd,
- "Update resource group counts? (y/n) ")) {
- errors_corrected++;
- log_warn("Resource group counts updated\n");
- /* write out the rgrp */
- gfs_rgrp_out(&rgp->rd_rg, BH_DATA(rgp->rd_bh[0]));
- write_buf(rgp->rd_sbd, rgp->rd_bh[0], 0);
- } else {
- log_err("Resource group counts left inconsistent\n");
- }
- }
-
- return 0;
-}
-
-/**
- * pass5 - check resource groups
- *
- * fix free block maps
- * fix used inode maps
- */
-int pass5(struct fsck_sb *sbp, struct options *opts)
-{
- osi_list_t *tmp;
- struct fsck_rgrp *rgp = NULL;
- uint32_t count[5];
- uint64_t rg_count = 1;
-
- /* Reconcile RG bitmaps with fsck bitmap */
- for(tmp = sbp->rglist.next; tmp != &sbp->rglist; tmp = tmp->next){
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return FSCK_OK;
- log_info("Updating Resource Group %"PRIu64"\n", rg_count);
- memset(count, 0, sizeof(*count) * 5);
- rgp = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
-
- if(fs_rgrp_read(rgp, FALSE)){
- stack;
- return FSCK_ERROR;
- }
- /* Compare the bitmaps and report the differences */
- update_rgrp(rgp, count, rg_count);
- rg_count++;
- fs_rgrp_relse(rgp);
- }
- /* Fix up superblock info based on this - don't think there's
- * anything to do here... */
-
-
- return FSCK_OK;
-}
diff --git a/gfs/gfs_fsck/rgrp.c b/gfs/gfs_fsck/rgrp.c
deleted file mode 100644
index 68d405e..0000000
--- a/gfs/gfs_fsck/rgrp.c
+++ /dev/null
@@ -1,633 +0,0 @@
-#include "util.h"
-#include "bio.h"
-#include "fs_bits.h"
-#include "fs_inode.h"
-#include "fsck_incore.h"
-#include "fsck.h"
-#include "rgrp.h"
-#include "inode.h"
-
-/**
- * fs_compute_bitstructs - Compute the bitmap sizes
- * @rgd: The resource group descriptor
- *
- * Returns: 0 on success, -1 on error
- */
-int fs_compute_bitstructs(struct fsck_rgrp *rgd)
-{
- struct fsck_sb *sdp = rgd->rd_sbd;
- fs_bitmap_t *bits;
- uint32 length = rgd->rd_ri.ri_length;
- uint32 bytes_left, bytes;
- int x;
-
- /* Max size of an rg is 2GB. A 2GB RG with (minimum) 512-byte blocks
- has 4194304 blocks. We can represent 4 blocks in one bitmap byte.
- Therefore, all 4194304 blocks can be represented in 1048576 bytes.
- Subtract a metadata header for each 512-byte block and we get
- 488 bytes of bitmap per block. Divide 1048576 by 488 and we can
- be assured we should never have more than 2149 of them. */
- if (length > 2149 || length == 0) {
- log_err("Invalid length %u found in rindex.\n", length);
- return -1;
- }
- if(!(rgd->rd_bits = (fs_bitmap_t *)malloc(length * sizeof(fs_bitmap_t)))) {
- log_err("Unable to allocate bitmap structure\n");
- stack;
- return -1;
- }
- if(!memset(rgd->rd_bits, 0, length * sizeof(fs_bitmap_t))) {
- free(rgd->rd_bits);
- log_err("Unable to zero bitmap structure\n");
- stack;
- return -1;
- }
-
- bytes_left = rgd->rd_ri.ri_bitbytes;
-
- for (x = 0; x < length; x++){
- bits = &rgd->rd_bits[x];
-
- if (length == 1){
- bytes = bytes_left;
- bits->bi_offset = sizeof(struct gfs_rgrp);
- bits->bi_start = 0;
- bits->bi_len = bytes;
- }
- else if (x == 0){
- bytes = sdp->sb.sb_bsize - sizeof(struct gfs_rgrp);
- bits->bi_offset = sizeof(struct gfs_rgrp);
- bits->bi_start = 0;
- bits->bi_len = bytes;
- }
- else if (x + 1 == length){
- bytes = bytes_left;
- bits->bi_offset = sizeof(struct gfs_meta_header);
- bits->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
- bits->bi_len = bytes;
- }
- else{
- bytes = sdp->sb.sb_bsize - sizeof(struct gfs_meta_header);
- bits->bi_offset = sizeof(struct gfs_meta_header);
- bits->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
- bits->bi_len = bytes;
- }
-
- bytes_left -= bytes;
- }
-
- if(bytes_left){
- log_err( "fs_compute_bitstructs: Too many blocks in rgrp to "
- "fit into available bitmap.\n");
- free(rgd->rd_bits);
- return -1;
- }
-
- if((rgd->rd_bits[length - 1].bi_start +
- rgd->rd_bits[length - 1].bi_len) * GFS_NBBY != rgd->rd_ri.ri_data){
- log_err( "fs_compute_bitstructs: # of blks in rgrp do not equal "
- "# of blks represented in bitmap.\n"
- "\tbi_start = %u\n"
- "\tbi_len = %u\n"
- "\tGFS_NBBY = %u\n"
- "\tri_data = %u\n",
- rgd->rd_bits[length - 1].bi_start,
- rgd->rd_bits[length - 1].bi_len,
- GFS_NBBY,
- rgd->rd_ri.ri_data);
- free(rgd->rd_bits);
- return -1;
- }
-
-
- if(!(rgd->rd_bh = (osi_buf_t **)malloc(length * sizeof(osi_buf_t *)))) {
- log_err("Unable to allocate osi_buf structure\n");
- stack;
- free(rgd->rd_bits);
- return -1;
- }
- if(!memset(rgd->rd_bh, 0, length * sizeof(osi_buf_t *))) {
- log_err("Unable to zero osi_buf structure\n");
- stack;
- free(rgd->rd_bits);
- return -1;
- }
-
- return 0;
-}
-
-
-/**
- * blk2rgrpd - Find resource group for a given data block number
- * @sdp: The GFS superblock
- * @n: The data block number
- *
- * Returns: Ths resource group, or NULL if not found
- */
-struct fsck_rgrp *fs_blk2rgrpd(struct fsck_sb *sdp, uint64 blk)
-{
- osi_list_t *tmp;
- struct fsck_rgrp *rgd = NULL;
- struct gfs_rindex *ri;
-
- for(tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next){
- rgd = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
- ri = &rgd->rd_ri;
-
- if (ri->ri_data1 <= blk && blk < ri->ri_data1 + ri->ri_data){
- break;
- } else
- rgd = NULL;
- }
- return rgd;
-}
-
-/**
- * fs_rgrp_read - read in the resource group information from disk.
- * @rgd - resource group structure
- * @repair_if_corrupted - If TRUE, rgrps found to be corrupt should be repaired
- * according to the index. If FALSE, no corruption is fixed.
- */
-int fs_rgrp_read(struct fsck_rgrp *rgd, int repair_if_corrupted)
-{
- struct fsck_sb *sdp = rgd->rd_sbd;
- unsigned int x, length = rgd->rd_ri.ri_length;
- int error;
-
- if(rgd->rd_open_count){
- rgd->rd_open_count++;
- return 0;
- }
-
- for (x = 0; x < length; x++){
- if(rgd->rd_bh[x]){
- log_err("Programmer error! Bitmaps are already present in rgrp.\n");
- exit(FSCK_ERROR);
- }
- error = get_and_read_buf(sdp, rgd->rd_ri.ri_addr + x,
- &(rgd->rd_bh[x]), 0);
- if (error) {
- log_err("Unable to read rgrp from disk.\n");
- goto fail;
- }
-
- if(check_meta(rgd->rd_bh[x], (x) ? GFS_METATYPE_RB : GFS_METATYPE_RG)){
- log_err("Block #%"PRIu64" (0x%"PRIx64") (%d of %d) is neither"
- " GFS_METATYPE_RB nor GFS_METATYPE_RG.\n",
- BH_BLKNO(rgd->rd_bh[x]), BH_BLKNO(rgd->rd_bh[x]),
- (int)x+1, (int)length);
- if (repair_if_corrupted) {
- errors_found++;
- if (query(sdp, "Fix the RG? (y/n)")) {
- log_err("Attempting to repair the RG.\n");
- if (x) {
- struct gfs_meta_header mh;
-
- memset(&mh, 0, sizeof(mh));
- mh.mh_magic = GFS_MAGIC;
- mh.mh_type = GFS_METATYPE_RB;
- mh.mh_format = GFS_FORMAT_RB;
- gfs_meta_header_out(&mh,
- BH_DATA(rgd->rd_bh[x]));
- } else {
- memset(&rgd->rd_rg, 0,
- sizeof(struct gfs_rgrp));
- rgd->rd_rg.rg_header.mh_magic =
- GFS_MAGIC;
- rgd->rd_rg.rg_header.mh_type =
- GFS_METATYPE_RG;
- rgd->rd_rg.rg_header.mh_format =
- GFS_FORMAT_RG;
- rgd->rd_rg.rg_free =
- rgd->rd_ri.ri_data;
- gfs_rgrp_out(&rgd->rd_rg,
- BH_DATA(rgd->rd_bh[x]));
- }
- write_buf(sdp, rgd->rd_bh[x], BW_WAIT);
- errors_corrected++;
- }
- }
- else {
- error = -1;
- goto fail;
- }
- }
- }
-
- gfs_rgrp_in(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- rgd->rd_open_count = 1;
-
- return 0;
-
- fail:
- for (x = 0; x < length; x++){
- if (rgd->rd_bh[x]) {
- relse_buf(sdp, rgd->rd_bh[x]);
- rgd->rd_bh[x] = NULL;
- }
- }
-
- log_err("Resource group or index is corrupted.\n");
- return error;
-}
-
-void fs_rgrp_relse(struct fsck_rgrp *rgd)
-{
- int x, length = rgd->rd_ri.ri_length;
-
- rgd->rd_open_count--;
- if(rgd->rd_open_count){
- ;
- } else {
- for (x = 0; x < length; x++){
- if (rgd->rd_bh[x]) {
- relse_buf(rgd->rd_sbd, rgd->rd_bh[x]);
- rgd->rd_bh[x] = NULL;
- }
- }
- }
-}
-
-#if 0 /* no one calls this, so don't waste memory for it: */
-/**
- * rgrp_verify - Verify that a resource group is consistent
- * @sdp: the filesystem
- * @rgd: the rgrp
- *
- * Returns: 0 if ok, -1 on error
- */
-int fs_rgrp_verify(struct fsck_rgrp *rgd)
-{
- fs_bitmap_t *bits = NULL;
- uint32 length = rgd->rd_ri.ri_length;
- uint32 count[4], tmp;
- int buf, x;
-
- for (x = 0; x < 4; x++){
- count[x] = 0;
-
- for (buf = 0; buf < length; buf++){
- bits = &rgd->rd_bits[buf];
- count[x] += fs_bitcount(BH_DATA(rgd->rd_bh[buf]) + bits->bi_offset,
- bits->bi_len, x);
- }
- }
-
- if(count[0] != rgd->rd_rg.rg_free){
- log_err("free data mismatch: %u != %u\n",
- count[0], rgd->rd_rg.rg_free);
- return -1;
- }
-
- tmp = rgd->rd_ri.ri_data -
- (rgd->rd_rg.rg_usedmeta + rgd->rd_rg.rg_freemeta) -
- (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi) -
- rgd->rd_rg.rg_free;
-
- if(count[1] != tmp){
- log_err("used data mismatch: %u != %u\n",
- count[1], tmp);
- return -1;
- }
- if(count[2] != rgd->rd_rg.rg_freemeta){
- log_err("free metadata mismatch: %u != %u\n",
- count[2], rgd->rd_rg.rg_freemeta);
- return -1;
- }
-
- tmp = rgd->rd_rg.rg_usedmeta +
- (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi);
-
- if(count[3] != tmp){
- log_err("used metadata mismatch: %u != %u\n",
- count[3], tmp);
- return -1;
- }
- return 0;
-}
-#endif
-
-/**
- * fs_rgrp_recount - adjust block tracking numbers
- * rgd: resource group
- *
- * The resource groups keep track of how many free blocks, used blocks,
- * etc there are. This function readjusts those numbers based on the
- * current state of the bitmap.
- *
- * Returns: 0 on success, -1 on failure
- */
-int fs_rgrp_recount(struct fsck_rgrp *rgd){
- int i,j;
- fs_bitmap_t *bits = NULL;
- uint32 length = rgd->rd_ri.ri_length;
- uint32 count[4], tmp;
-
- for(i=0; i < 4; i++){
- count[i] = 0;
- for(j = 0; j < length; j++){
- bits = &rgd->rd_bits[j];
- count[i] += fs_bitcount((unsigned char *)
- BH_DATA(rgd->rd_bh[j]) +
- bits->bi_offset,
- bits->bi_len, i);
- }
- }
- if(count[0] != rgd->rd_rg.rg_free){
- log_warn("\tAdjusting free block count (%u -> %u).\n",
- rgd->rd_rg.rg_free, count[0]);
- rgd->rd_rg.rg_free = count[0];
- }
- if(count[2] != rgd->rd_rg.rg_freemeta){
- log_warn("\tAdjusting freemeta block count (%u -> %u).\n",
- rgd->rd_rg.rg_freemeta, count[2]);
- rgd->rd_rg.rg_freemeta = count[2];
- }
- tmp = rgd->rd_rg.rg_usedmeta +
- (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi);
-
- if(count[3] != tmp){
- int first = 1;
- struct fsck_sb *sdp = rgd->rd_sbd;
- uint32 useddi = 0;
- uint32 freedi = 0;
- uint64 block;
- struct fsck_inode *ip;
-
- while (1){ /* count the used dinodes */
- if(next_rg_metatype(rgd, &block,
- GFS_METATYPE_DI, first)){
- break;
- }
- first = 0;
- if(load_inode(sdp, block, &ip)) {
- stack;
- continue;
- }
-
- if (ip->i_di.di_flags & GFS_DIF_UNUSED){
- freedi++;
- continue;
- }
- free_inode(&ip);
- useddi++;
- }
-
- if(useddi != rgd->rd_rg.rg_useddi){
- log_warn("\tAdjusting used dinode block count (%u -> %u).\n",
- rgd->rd_rg.rg_useddi, useddi);
- rgd->rd_rg.rg_useddi = useddi;
- }
- if(freedi != rgd->rd_rg.rg_freedi){
- log_warn("\tAdjusting free dinode block count (%u -> %u).\n",
- rgd->rd_rg.rg_freedi, freedi);
- rgd->rd_rg.rg_freedi = freedi;
- }
- if(rgd->rd_rg.rg_usedmeta != count[3] - (freedi + useddi)){
- log_warn("\tAdjusting used meta block count (%u -> %u).\n",
- rgd->rd_rg.rg_usedmeta,
- (count[3] - (freedi + useddi)));
- rgd->rd_rg.rg_usedmeta = count[3] - (freedi + useddi);
- }
- }
-
- tmp = rgd->rd_ri.ri_data -
- (rgd->rd_rg.rg_usedmeta + rgd->rd_rg.rg_freemeta) -
- (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi) -
- rgd->rd_rg.rg_free;
-
- if(count[1] != tmp){
- log_err("Could not reconcile rgrp block counts.\n");
- return -1;
- }
- return 0;
-}
-
-
-
-/**
- * clump_alloc - Allocate a clump of metadata
- * @rgd: the resource group descriptor
- * @goal: the goal block in the RG
- *
- * Returns: 0 on success, -1 on failure
- */
-int clump_alloc(struct fsck_rgrp *rgd, uint32 goal)
-{
- struct fsck_sb *sdp = rgd->rd_sbd;
- struct gfs_meta_header mh;
- osi_buf_t *bh[GFS_META_CLUMP] = {0};
- uint32 block;
- int i,j;
- int error = 0;
-
- memset(&mh, 0, sizeof(struct gfs_meta_header));
- mh.mh_magic = GFS_MAGIC;
- mh.mh_type = GFS_METATYPE_NONE;
-
- if(rgd->rd_rg.rg_free < GFS_META_CLUMP){
- log_debug(" Not enough free blocks in rgrp.\n");
- return -1;
- }
-
- for (i = 0; i < GFS_META_CLUMP; i++){
- block = fs_blkalloc_internal(rgd, goal,
- GFS_BLKST_FREE,
- GFS_BLKST_FREEMETA, TRUE);
- log_debug("Got block %u\n", block);
-
- if(block == BFITNOENT) {
- log_err("Unable to get enough blocks\n");
- goto fail;
- }
- block += rgd->rd_ri.ri_data1;
- block_set(rgd->rd_sbd->bl, block, meta_free);
- if(get_buf(sdp, block, &(bh[i]))){
- log_err("Unable to allocate new buffer.\n");
- goto fail;
- }
- gfs_meta_header_out(&mh, BH_DATA(bh[i]));
-
- goal = block;
- }
-
- log_debug("64 Meta blocks (%"PRIu64" - %"PRIu64"), allocated in rgrp 0x%lx\n",
- (rgd->rd_ri.ri_data1 + block)-63,
- (rgd->rd_ri.ri_data1 + block),
- (unsigned long)rgd);
- for (j = 0; j < GFS_META_CLUMP; j++){
-
- error = write_buf(sdp, bh[j], BW_WAIT);
- if (error){
- log_err("Unable to write allocated metablock to disk.\n");
- goto fail;
- }
- }
-
- if(rgd->rd_rg.rg_free < GFS_META_CLUMP){
- log_err("More blocks were allocated from rgrp "
- "than are available.\n");
- goto fail;
- }
- rgd->rd_rg.rg_free -= GFS_META_CLUMP;
- rgd->rd_rg.rg_freemeta += GFS_META_CLUMP;
-
- for (i = 0; i < GFS_META_CLUMP; i++)
- relse_buf(sdp, bh[i]);
-
- return 0;
-
- fail:
- log_debug("clump_alloc failing...\n");
- for(--i; i >=0; i--){
- fs_set_bitmap(sdp, BH_BLKNO(bh[i]), GFS_BLKST_FREE);
- /*relse_buf(sdp, bh[i]);*/
- }
- return -1;
-}
-
-
-/**
- * fs_blkalloc - Allocate a data block
- * @ip: the inode to allocate the data block for
- * @block: the block allocated
- *
- * Returns: 0 on success, -1 on failure
- */
-int fs_blkalloc(struct fsck_inode *ip, uint64 *block)
-{
- osi_list_t *tmp;
- struct fsck_sb *sdp = ip->i_sbd;
- struct fsck_rgrp *rgd;
- uint32 goal;
- int same;
-
- for(tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next){
- rgd = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
-
- if(!rgd){
- log_err( "fs_blkalloc: Bad rgrp list!\n");
- return -1;
- }
-
- if(fs_rgrp_read(rgd, FALSE)){
- log_err( "fs_blkalloc: Unable to read rgrp.\n");
- return -1;
- }
-
- if(!rgd->rd_rg.rg_free){
- fs_rgrp_relse(rgd);
- continue;
- }
-
- same = (rgd->rd_ri.ri_addr == ip->i_di.di_goal_rgrp);
- goal = (same) ? ip->i_di.di_goal_dblk : 0;
-
- *block = fs_blkalloc_internal(rgd, goal,
- GFS_BLKST_FREE,
- GFS_BLKST_USED, TRUE);
-
- log_debug("Got block %"PRIu64"\n", *block);
- if(*block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- if (!same){
- ip->i_di.di_goal_rgrp = rgd->rd_ri.ri_addr;
- ip->i_di.di_goal_mblk = 0;
- }
-
- *block += rgd->rd_ri.ri_data1;
- ip->i_di.di_goal_dblk = *block;
-
- rgd->rd_rg.rg_free--;
-
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- if(write_buf(sdp, rgd->rd_bh[0], 0)){
- log_err( "Unable to write out rgrp block #%"
- PRIu64".\n",
- BH_BLKNO(rgd->rd_bh[0]));
- fs_rgrp_relse(rgd);
- return -1;
- }
- fs_rgrp_relse(rgd);
- return 0;
- }
-
- return 1;
-}
-
-
-/**
- * fs_metaalloc - Allocate a metadata block to a file
- * @ip: the file
- * @block: the block allocated
- *
- * Returns: 0 on success, -1 on failure
- */
-int fs_metaalloc(struct fsck_inode *ip, uint64 *block)
-{
- osi_list_t *tmp;
- struct fsck_sb *sdp = ip->i_sbd;
- struct fsck_rgrp *rgd;
- uint32 goal;
- int same;
- int error = 0;
-
- /* ATTENTION -- maybe we should try to allocate from goal rgrp first */
- for(tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next){
- rgd = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
-
- if(!rgd){
- log_err( "fs_metaalloc: Bad rgrp list!\n");
- return -1;
- }
-
- if(fs_rgrp_read(rgd, FALSE)){
- log_err( "fs_metaalloc: Unable to read rgrp.\n");
- return -1;
- }
-
- same = (rgd->rd_ri.ri_addr == ip->i_di.di_goal_rgrp);
- goal = (same) ? ip->i_di.di_goal_mblk : 0;
-
- if (!rgd->rd_rg.rg_freemeta){
- error = clump_alloc(rgd, goal);
- if (error){
- fs_rgrp_relse(rgd);
- continue;
- }
- }
-
-
- if(!rgd->rd_rg.rg_freemeta){
- fs_rgrp_relse(rgd);
- continue;
- }
- *block = fs_blkalloc_internal(rgd, goal,
- GFS_BLKST_FREEMETA,
- GFS_BLKST_USEDMETA, TRUE);
- log_debug("Got block %"PRIu64"\n", *block);
- if(*block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- if (!same){
- ip->i_di.di_goal_rgrp = rgd->rd_ri.ri_addr;
- ip->i_di.di_goal_dblk = 0;
- }
- *block += rgd->rd_ri.ri_data1;
- ip->i_di.di_goal_mblk = *block;
-
- rgd->rd_rg.rg_freemeta--;
- rgd->rd_rg.rg_usedmeta++;
-
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- write_buf(sdp, rgd->rd_bh[0], 0);
- fs_rgrp_relse(rgd);
- /* if we made it this far, then we are ok */
- return 0;
- }
-
- return -1;
-}
diff --git a/gfs/gfs_fsck/rgrp.h b/gfs/gfs_fsck/rgrp.h
deleted file mode 100644
index 1312ba6..0000000
--- a/gfs/gfs_fsck/rgrp.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _RGRP_H
-#define _RGRP_H
-
-struct fsck_sb;
-struct fsck_rgrp;
-struct fsck_inode;
-
-int fs_compute_bitstructs(struct fsck_rgrp *rgd);
-struct fsck_rgrp *fs_blk2rgrpd(struct fsck_sb *sdp, uint64_t blk);
-
-int fs_rgrp_read(struct fsck_rgrp *rgd, int repair_if_corrupted);
-void fs_rgrp_relse(struct fsck_rgrp *rgd);
-int fs_rgrp_verify(struct fsck_rgrp *rgd);
-int fs_rgrp_recount(struct fsck_rgrp *rgd);
-
-int clump_alloc(struct fsck_rgrp *rgd, uint32_t goal);
-int fs_blkalloc(struct fsck_inode *ip, uint64_t *block);
-int fs_metaalloc(struct fsck_inode *ip, uint64_t *block);
-
-#endif /* _RGRP_H */
diff --git a/gfs/gfs_fsck/super.c b/gfs/gfs_fsck/super.c
deleted file mode 100644
index 0a13ce2..0000000
--- a/gfs/gfs_fsck/super.c
+++ /dev/null
@@ -1,1435 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <errno.h>
-
-#include "osi_list.h"
-#include "osi_user.h"
-#include "bio.h"
-#include "util.h"
-#include "file.h"
-#include "rgrp.h"
-#include "fsck.h"
-#include "ondisk.h"
-#include "super.h"
-#include "fsck_incore.h"
-
-#ifndef BLKGETSIZE64
-#define BLKGETSIZE64 _IOR(0x12, 114, size_t)
-#endif
-
-#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
-#define ri_compare(rg, ondisk, expected, field, fmt) \
- if (ondisk.field != expected.field) { \
- log_warn("rgindex #%d " #field " discrepancy: index 0x%" fmt \
- " != expected: 0x%" fmt "\n", \
- rg + 1, ondisk.field, expected.field); \
- ondisk.field = expected.field; \
- rgindex_modified = TRUE; \
- }
-
-struct mkfs_subdevice
-{
- uint64 start;
- uint64 length;
- int is_journal;
-};
-
-struct mkfs_device
-{
- unsigned int nsubdev;
- struct mkfs_subdevice *subdev;
-};
-
-static uint64 total_journal_space;
-
-/**
- * check_sb - Check superblock
- * @sdp: the filesystem
- * @sb: The superblock
- *
- * Checks the version code of the FS is one that we understand how to
- * read and that the sizes of the various on-disk structures have not
- * changed.
- *
- * Returns: 0 on success, -1 on failure
- */
-static int check_sb(struct fsck_sb *sdp, struct gfs_sb *sb)
-{
- int error = 0;
- if (sb->sb_header.mh_magic != GFS_MAGIC ||
- sb->sb_header.mh_type != GFS_METATYPE_SB){
- log_crit("Either the super block is corrupted, or this "
- "is not a GFS filesystem\n");
- log_debug("Header magic: %X Header Type: %X\n",
- sb->sb_header.mh_magic,
- sb->sb_header.mh_type);
- error = -EINVAL;
- goto out;
- }
-
- /* If format numbers match exactly, we're done. */
- if (sb->sb_fs_format != GFS_FORMAT_FS ||
- sb->sb_multihost_format != GFS_FORMAT_MULTI){
- log_warn("Old file system detected.\n");
- }
-
- out:
- return error;
-}
-
-
-/*
- * read_sb: read the super block from disk
- * sdp: in-core super block
- *
- * This function reads in the super block from disk and
- * initializes various constants maintained in the super
- * block
- *
- * Returns: 0 on success, -1 on failure.
- */
-int read_sb(struct fsck_sb *sdp)
-{
- osi_buf_t *bh;
- uint64 space = 0;
- unsigned int x;
- int error;
- error = get_and_read_buf(sdp, GFS_SB_ADDR >> sdp->fsb2bb_shift, &bh, 0);
- if (error){
- log_crit("Unable to read superblock\n");
- goto out;
- }
-
- gfs_sb_in(&sdp->sb, BH_DATA(bh));
-
- relse_buf(sdp, bh);
-
- error = check_sb(sdp, &sdp->sb);
- if (error)
- goto out;
-
-/* FIXME: Need to verify all this */
- /* FIXME: What's this 9? */
- sdp->fsb2bb_shift = sdp->sb.sb_bsize_shift - 9;
- sdp->diptrs =
- (sdp->sb.sb_bsize - sizeof(struct gfs_dinode)) /
- sizeof(uint64);
- sdp->inptrs =
- (sdp->sb.sb_bsize - sizeof(struct gfs_indirect)) /
- sizeof(uint64);
- sdp->jbsize = sdp->sb.sb_bsize - sizeof(struct gfs_meta_header);
- /* FIXME: Why is this /2 */
- sdp->hash_bsize = sdp->sb.sb_bsize / 2;
- sdp->hash_ptrs = sdp->hash_bsize / sizeof(uint64);
- sdp->heightsize[0] = sdp->sb.sb_bsize -
- sizeof(struct gfs_dinode);
- sdp->heightsize[1] = sdp->sb.sb_bsize * sdp->diptrs;
- for (x = 2; ; x++){
- space = sdp->heightsize[x - 1] * sdp->inptrs;
- /* FIXME: Do we really need this first check?? */
- if (space / sdp->inptrs != sdp->heightsize[x - 1] ||
- space % sdp->inptrs != 0)
- break;
- sdp->heightsize[x] = space;
- }
- sdp->max_height = x;
- if(sdp->max_height > GFS_MAX_META_HEIGHT){
- log_err("Bad max metadata height.\n");
- error = -1;
- goto out;
- }
-
- sdp->jheightsize[0] = sdp->sb.sb_bsize -
- sizeof(struct gfs_dinode);
- sdp->jheightsize[1] = sdp->jbsize * sdp->diptrs;
- for (x = 2; ; x++){
- space = sdp->jheightsize[x - 1] * sdp->inptrs;
- if (space / sdp->inptrs != sdp->jheightsize[x - 1] ||
- space % sdp->inptrs != 0)
- break;
- sdp->jheightsize[x] = space;
- }
- sdp->max_jheight = x;
- if(sdp->max_jheight > GFS_MAX_META_HEIGHT){
- log_err("Bad max jheight.\n");
- error = -1;
- }
-
- out:
-
- return error;
-}
-
-
-/*
- * ji_update - fill in journal info
- * ip: the journal index inode
- *
- * Given the inode for the journal index, read in all
- * the journal indexes.
- *
- * Returns: 0 on success, -1 on failure
- */
-int ji_update(struct fsck_sb *sdp)
-{
- struct fsck_inode *ip = sdp->jiinode;
- char buf[sizeof(struct gfs_jindex)];
- unsigned int j;
- int error=0;
-
-
- if(ip->i_di.di_size % sizeof(struct gfs_jindex) != 0){
- log_err("The size reported in the journal index"
- " inode is not a\n"
- "\tmultiple of the size of a journal index.\n");
- return -1;
- }
-
- if(!(sdp->jindex = (struct gfs_jindex *)malloc(ip->i_di.di_size))) {
- log_err("Unable to allocate journal index\n");
- return -1;
- }
- if(!memset(sdp->jindex, 0, ip->i_di.di_size)) {
- log_err("Unable to zero journal index\n");
- return -1;
- }
- total_journal_space = 0;
-
- for (j = 0; ; j++) {
- struct gfs_jindex *journ;
- error = readi(ip, buf, j * sizeof(struct gfs_jindex),
- sizeof(struct gfs_jindex));
- if(!error)
- break;
- if (error != sizeof(struct gfs_jindex)){
- log_err("An error occurred while reading the"
- " journal index file.\n");
- goto fail;
- }
-
- journ = sdp->jindex + j;
- gfs_jindex_in(journ, buf);
- sdp->ji_nsegment = journ->ji_nsegment;
- total_journal_space += journ->ji_nsegment * sdp->sb.sb_seg_size;
- }
-
-
- if(j * sizeof(struct gfs_jindex) != ip->i_di.di_size){
- log_err("journal inode size invalid\n");
- log_debug("j * sizeof(struct gfs_jindex) !="
- " ip->i_di.di_size\n");
- log_debug("%d != %d\n",
- j * sizeof(struct gfs_jindex), ip->i_di.di_size);
- goto fail;
- }
- sdp->journals = j;
- log_debug("%d journals found.\n", j);
-
- return 0;
-
- fail:
- free(sdp->jindex);
- return -1;
-}
-
-/**
- * rgrplength2bitblocks - Stolen from gfs_mkfs.
- *
- * @sdp: the superblock
- * @length: the number of blocks in a RG
- *
- * Give a number of blocks in a RG, figure out the number of blocks
- * needed for bitmaps.
- *
- * Returns: the number of bitmap blocks
- */
-
-static uint32 rgrplength2bitblocks(struct fsck_sb *sdp, uint32 length)
-{
- uint32 bitbytes;
- uint32 old_blocks = 0, blocks;
- int tries = 0;
-
- for (;;) {
- bitbytes = (length - old_blocks) / GFS_NBBY;
- blocks = 1;
-
- if (bitbytes > sdp->sb.sb_bsize - sizeof(struct gfs_rgrp)) {
- bitbytes -= sdp->sb.sb_bsize - sizeof(struct gfs_rgrp);
- blocks += DIV_RU(bitbytes, (sdp->sb.sb_bsize -
- sizeof(struct gfs_meta_header)));
- }
- if (blocks == old_blocks)
- break;
- old_blocks = blocks;
- if (tries++ > 10) {
- blocks = 0;
- break;
- }
- }
- return blocks;
-}
-
-/*
- * gfs_rgindex_rebuild - rebuild a corrupt Resource Group (RG) index manually
- * where trust_lvl == distrust
- *
- * If this routine is called, it means we have RGs in odd/unexpected places,
- * and there is a corrupt RG. In other words, we can't trust the RG index
- * is completely sane, and the RGs don't fit on nice neat fs boundaries.
- * So we have no choice but to go through the count them by hand.
- * We've tried twice to recover the RGs and RG index, and failed. This is
- * our last chance to remedy the situation.
- *
- * In some cases, we have no choice but to trust the rgindex file. Since
- * it is completely hidden from the users, if we find an inconsistency,
- * it's safer to assume the index is correct and the RG is corrupt rather
- * than the RG is correct and the index is bad. This routine goes to great
- * lengths to determine which is the case and figure it out regardless.
- *
- * This routine tries to minimize performance impact by:
- * 1. Skipping through the filesystem at known increments when possible.
- * 2. Shuffle through every block when RGs are not found at the predicted
- * locations.
- *
- * Note: A GFS filesystem is built by gfs_mkfs into several "subdevices."
- * These are just logical divisions of the logical volume. The gfs_mkfs
- * program considers two types of subdevices: RG-subdevices and journal
- * subdevices. RG subdevices contain one or more RGs. Journal subdevices
- * contain one or more journals. For the purposes of gfs_fsck, when I talk
- * about subdevices, I'm talking about RG-subdevices only. For a freshly
- * created GFS filesystem, the logical volume will be broken apart like this:
- *
- * RG-subdevice 0: n Resource Groups
- * Journal subdevice
- * RG-subdevice 1: n Resource Groups (same as RG-subdevice 0)
- *
- * If the filesystem has been resized via gfs_grow, there will be more
- * RG-subdevices containing more RGs. However, gfs_fsck treats them all
- * as "subdevice 2."
- *
- * NOTE: When giving messages to the users, I am referring to them as
- * "sections" 1, 2, and 3 because "subdevice" sounds too confusing.
- *
- * If an RG is not found at a predicted location, it either means that
- * there is a corrupted RG, or else the RG has been added after the fact
- * by gfs_grow. We can only predict the locations for RGs within a subdevice,
- * but the subdevice boundaries are not that predictable. (Actually, they
- * are, but since we're dealing with a likely corrupt filesystem, I don't
- * want to rely on good data too much to do it this way.)
- *
- * I am, however, going to rely on the fact that the first original subdevice
- * will have the same number of RGs as the second original subdevice.
- * Other RGs found after that will be considered "extra."
- */
-static int gfs_rgindex_rebuild(struct fsck_sb *sdp, osi_list_t *ret_list,
- unsigned int *num_rgs)
-{
- osi_buf_t *bh; /* buffer handle */
- uint64 subdevice_size, fs_total_size;
- int number_of_rgs; /* #RGs this subdevice.
- min of 2 per segment * 2 segments = 4 */
- int rg_number; /* real RG number (0 - x) */
- int subd;
- int error, corrupt_rgs;
- int rgi, rgs_per_subd;
- uint64 blok, block_of_last_rg;
- uint64 block_bump;
- uint64 shortest_dist_btwn_rgs[2]; /* one for each subdevice */
- uint64 first_rg_dist[2], initial_first_rg_dist[2];
- struct fsck_rgrp *calc_rgd, *prev_rgd;
- struct gfs_rgrp tmp_rgrp;
- osi_list_t *tmp;
- int rg_was_fnd = FALSE;
- struct gfs_rindex buf, tmpndx;
- uint64 fs_size_from_rgindex = 0;
- int index_entries_per_subd = 0, subd_ndx_entry, rg;
- uint64_t last_known_ri_addr = 0, prev_known_ri_addr = 0;
- uint32_t last_known_ri_length = 0;
- uint32_t last_known_ri_data = 0;
- int section3_bump_size = 0;
- uint64 start_block, end_block = 0;
-
- osi_list_init(ret_list);
- *num_rgs = 0;
- /* Get the total size of the device */
- error = ioctl(sdp->diskfd, BLKGETSIZE64,
- &fs_total_size); /* Size in bytes */
- fs_total_size /= sdp->sb.sb_bsize;
- log_debug("fs_total_size = 0x%" PRIX64 " blocks.\n", fs_total_size);
- block_of_last_rg = 0;
- subdevice_size = 0;
- rgs_per_subd = 0;
- /* ----------------------------------------------------------------- */
- /* First, figure out the exact end of the second subdevice. */
- /* That will tell us where the third RG-subdevice should start. */
- /* We need to keep track of how many entries are in the index before */
- /* we hit the journal blocks. That will tell us how many index */
- /* entries will be in the first subdevice, and the second subdevice */
- /* should have the same number. After that, we don't care. */
- /* Note: we're using values in the rgindex, even though we don't */
- /* trust it. We're relatively okay because we're just trying to */
- /* find the highest RG value for the second subdevice. */
- /* ----------------------------------------------------------------- */
- subd = 0;
- index_entries_per_subd = 0;
- subd_ndx_entry = 0;
- for (rg = 0; ; rg++) {
- uint64 end_of_rg;
-
- error = readi(sdp->riinode,
- (char *)&buf, rg * sizeof(struct gfs_rindex),
- sizeof(struct gfs_rindex));
- if (!error) /* if end of file */
- break; /* stop looking */
- gfs_rindex_in(&tmpndx, (char *)&buf); /* read in the index */
- subd_ndx_entry++;
- if (!subd) { /* if we're still in the first subdevice */
- if (tmpndx.ri_addr >= sdp->jindex->ji_addr + total_journal_space) {
- subd++; /* this rgindex belongs to the second subdevice */
- prev_known_ri_addr = 0;
- last_known_ri_addr = 0;
- subd_ndx_entry = 1;
- }
- else {
- index_entries_per_subd++;
- /* Check if this is the last index entry for subdevice */
- if (tmpndx.ri_addr + tmpndx.ri_length + tmpndx.ri_data >=
- sdp->jindex->ji_addr - GFS_NBBY) {
- subd++; /* NEXT rgindex belongs to the second subdevice */
- subd_ndx_entry = 0;
- prev_known_ri_addr = 0;
- last_known_ri_addr = 0;
- continue;
- }
- }
- }
- end_of_rg = tmpndx.ri_addr + tmpndx.ri_length + tmpndx.ri_data;
- /* ----------------------------------------------------------------- */
- /* Make sure the rgindex looks relatively sane. After all, */
- /* at this stage of the game, we don't trust it. */
- /* ----------------------------------------------------------------- */
- if (subd && end_of_rg > sdp->jindex->ji_addr + total_journal_space &&
- end_of_rg <= fs_total_size) { /* looks relatively sane */
- /* Save some data values we can fall back on: */
- prev_known_ri_addr = last_known_ri_addr;
- last_known_ri_addr = tmpndx.ri_addr;
- last_known_ri_length = tmpndx.ri_length;
- last_known_ri_data = tmpndx.ri_data;
- if (fs_size_from_rgindex < end_of_rg)
- fs_size_from_rgindex = end_of_rg;
- /* Quit after we hit the same number of entries as 1st subdevice */
- if (subd_ndx_entry >= index_entries_per_subd)
- break;
- }
- else if (!subd && end_of_rg < sdp->jindex->ji_addr &&
- end_of_rg > 0) { /* looks relatively sane */
- /* Save some data values we can fall back on: */
- prev_known_ri_addr = last_known_ri_addr;
- last_known_ri_addr = tmpndx.ri_addr;
- last_known_ri_length = tmpndx.ri_length;
- last_known_ri_data = tmpndx.ri_data;
- if (fs_size_from_rgindex < end_of_rg)
- fs_size_from_rgindex = end_of_rg;
- }
- else { /* Otherwise we have a corrupt index entry */
- log_debug("Likely damage to rgindex entry %d.\n",
- subd_ndx_entry + (subd * index_entries_per_subd));
- if (prev_known_ri_addr) {
- /* Try to extrapolate from the previous one */
- tmpndx.ri_addr = last_known_ri_addr +
- (last_known_ri_addr - prev_known_ri_addr);
- tmpndx.ri_length = last_known_ri_length;
- tmpndx.ri_data = last_known_ri_data;
- log_debug("Extrapolating addr=0x%" PRIx64 ", length=0x%x, "
- "data=%x\n", tmpndx.ri_addr,
- tmpndx.ri_length, tmpndx.ri_data);
- end_of_rg = tmpndx.ri_addr + tmpndx.ri_length +
- tmpndx.ri_data;
- if (end_of_rg > sdp->jindex->ji_addr +
- total_journal_space &&
- end_of_rg <= fs_total_size) { /* looks relatively okay */
- /* Adjust data values we can fall back on: */
- last_known_ri_addr = tmpndx.ri_addr;
- if (fs_size_from_rgindex < end_of_rg)
- fs_size_from_rgindex = end_of_rg;
- /* Quit after we hit the same number of entries as
- the first subdevice/section */
- if (subd_ndx_entry >= index_entries_per_subd)
- break;
- }
- } /* if we have a good previous */
- else {
- log_debug("Not enough data to figure it out--skipped.\n");
- }
- } /* corrupt RG index entry */
- } /* for all RGs in the index */
- log_debug("Index entries/section=%d, third section addr = 0x%"PRIx64"\n",
- index_entries_per_subd, fs_size_from_rgindex);
- initial_first_rg_dist[0] = first_rg_dist[0] = sdp->jindex->ji_addr -
- ((GFS_SB_ADDR >> sdp->fsb2bb_shift) + 1);
- initial_first_rg_dist[1] = first_rg_dist[1] = sdp->jindex->ji_addr;
- /* ----------------------------------------------------------------- */
- /* Now let's figure out the space between RGs for the first subd, */
- /* and the second subd. Subsequent RGs will be unpredictable. */
- /* We need to know the distance between RGs because if one is */
- /* corrupt or overwritten, we need to salvage it at the correct */
- /* location. For example, if RG #2 is nuked, at first glance, it */
- /* appears as if our RGs are twice as far apart as they should be. */
- /* So we should chase down a couple to get more than one opinion. */
- /* If several RGs are nuked, sorry, I'll only go so far to recover. */
- /* This check will be slower because we have to read blocks 1 by 1. */
- /* Luckily, we only have to do a few this way. */
- /* Later, we can bump ahead by the amount we find here. */
- /* ----------------------------------------------------------------- */
- subdevice_size = sdp->jindex->ji_addr; /* addr of first journal */;
- for (subd = 0; subd < 2; subd++) {
- if (!subd)
- start_block = (GFS_SB_ADDR >> sdp->fsb2bb_shift) + 1;
- else
- start_block = sdp->jindex->ji_addr + total_journal_space;
- block_of_last_rg = start_block;
- number_of_rgs = 0;
- shortest_dist_btwn_rgs[subd] = subdevice_size;
- for (blok = start_block; blok < fs_total_size; blok++) {
- error = get_and_read_buf(sdp, blok, &bh, 0);
- if (error){
- log_crit("Unable to read block 0x%" PRIX64 "\n", blok);
- return -1;
- }
- if ((blok == start_block) || /* If first RG block or */
- !check_type(bh, GFS_METATYPE_RG)) { /* we found an RG */
- log_debug("%d:RG found at block 0x%" PRIx64 "\n", subd + 1,
- blok);
- /* If we spilled into the next subdevice, quit. */
- if (blok + GFS_NBBY >= start_block + subdevice_size) {
- log_debug("This is in the next subdevice--skipping.\n");
- break;
- }
- gfs_rgrp_in(&tmp_rgrp, BH_DATA(bh));
- if (blok == start_block) {
- shortest_dist_btwn_rgs[subd] = subdevice_size;
- log_debug("Start of section %d.\n", subd + 1);
- }
- else {
- uint64 rgdist;
-
- rgdist = blok - block_of_last_rg;
- log_debug("%d:dist 0x%" PRIx64 " = 0x% " PRIx64
- " - 0x%" PRIx64, subd + 1, rgdist,
- blok, block_of_last_rg);
- /* ----------------------------------------------------- */
- /* We found another RG. Check to see if we need to set */
- /* the first_rg_dist based on whether it's still at its */
- /* initial value (i.e. the whole subdevice size). */
- /* The first rg distance is different from the rest */
- /* because of the superblock and 64K dead space */
- /* ----------------------------------------------------- */
- if (first_rg_dist[subd] == initial_first_rg_dist[subd])
- first_rg_dist[subd] = rgdist;
- if (rgdist < shortest_dist_btwn_rgs[subd])
- {
- shortest_dist_btwn_rgs[subd] = rgdist;
- log_debug("(shortest so far)\n");
- }
- else
- log_debug("\n");
- }
- number_of_rgs++; /* number of RGs this subdevice */
- /* --------------------------------------------------------- */
- /* Check to see if we're the last RG we want to examine. */
- /* If so, forget checking the next index entry and exit. */
- /* (The next index entry may be for the next RG anyway). */
- /* --------------------------------------------------------- */
- if (number_of_rgs >= 4 ||
- number_of_rgs >= index_entries_per_subd)
- break;
- /* --------------------------------------------------------- */
- /* Read in the index entry for the NEXT RG in line and */
- /* compare the RG size difference with what we know. */
- /* --------------------------------------------------------- */
- rg_number = number_of_rgs + (subd * index_entries_per_subd);
- error = readi(sdp->riinode, (char *)&buf,
- rg_number * sizeof(struct gfs_rindex),
- sizeof(struct gfs_rindex));
- if (error) { /* if we read some data (no error really) */
- gfs_rindex_in(&tmpndx, (char *)&buf);
- if (tmpndx.ri_addr > start_block &&
- tmpndx.ri_addr < fs_total_size &&
- tmpndx.ri_addr != blok &&
- tmpndx.ri_addr - blok <
- shortest_dist_btwn_rgs[subd]) {
- shortest_dist_btwn_rgs[subd] =
- tmpndx.ri_addr - blok;
- log_debug("Section %d RG %d(%d): shortest=0x%"PRIx64
- "\n", subd + 1, number_of_rgs, rg_number,
- shortest_dist_btwn_rgs[subd]);
- }
- }
- block_of_last_rg = blok;
- /* --------------------------------------------------------- */
- /* We can't just check every block because some of the files */
- /* in the fs (i.e. inside an RG) might have data that looks */
- /* exactly like a valid RG. Sounds farfetched, but it's not, */
- /* based on my own experiences. */
- /* In my experience, the RG locations are spaced differently */
- /* from their used and free space numbers because of the way */
- /* gfs_mkfs puts them. In other words, the RG locations */
- /* according to the index will be different from the sum of */
- /* the space they take. Why? I don't know, but maybe it */
- /* has to do with the variable size of bitmaps. */
- /* At any rate, used+free can get us close, but not exact. */
- /* Therefore, we have to search for the RG after that. */
- /* --------------------------------------------------------- */
- if (!error &&
- ((tmp_rgrp.rg_useddi + tmp_rgrp.rg_free + 1) >> 2) ==
- (tmpndx.ri_addr >> 2)) {
- blok = tmpndx.ri_addr - 1; /* go by the index */
- log_debug("I(0x%" PRIx64 ")\n", blok);
- }
- /* If this is the second section, we know for sure that */
- /* the block length can't be smaller than section 1's */
- /* rg length. Might as well skip ahead. */
- else if (subd == 1) {
- blok += shortest_dist_btwn_rgs[0];
- log_debug("2(0x%" PRIx64 ")\n", blok);
- } else {
- blok += tmp_rgrp.rg_useddi + tmp_rgrp.rg_free;
- log_debug("R(0x%" PRIx64 ")\n", blok);
- }
- } /* If first RG block or RG */
- relse_buf(sdp, bh); /* release the read buffer */
- } /* for blok */
- /* -------------------------------------------------------------- */
- /* Sanity-check our first_rg_dist. If RG #2 got nuked, the */
- /* first_rg_dist would measure from #1 to #3, which would be bad. */
- /* We need to take remedial measures to fix it (from the index). */
- /* -------------------------------------------------------------- */
- if (first_rg_dist[subd] >= shortest_dist_btwn_rgs[subd] +
- (shortest_dist_btwn_rgs[subd] / 4)) {
- log_debug("%d:Shortest dist is: 0x%" PRIx64 "\n", subd + 1,
- shortest_dist_btwn_rgs[subd]);
- /* read in the second RG index entry for this subd. */
- readi(sdp->riinode, (char *)&buf,
- (1 + (subd * index_entries_per_subd)) *
- sizeof(struct gfs_rindex),
- sizeof(struct gfs_rindex));
- gfs_rindex_in(&tmpndx, (char *)&buf);
- if (tmpndx.ri_addr > start_block) { /* sanity check */
- log_warn("RG %d is damaged: recomputing RG dist from index: ",
- 2 + (subd * index_entries_per_subd));
- first_rg_dist[subd] = tmpndx.ri_addr - start_block;
- log_warn("0x%" PRIx64 "\n", first_rg_dist[subd]);
- }
- else {
- log_warn("RG index %d is damaged: extrapolating RG dist: ",
- 2 + (subd * index_entries_per_subd));
- first_rg_dist[subd] = (subdevice_size - start_block) %
- ((index_entries_per_subd - 1) *
- shortest_dist_btwn_rgs[subd]);
- log_warn("0x%" PRIx64 "\n", first_rg_dist[subd]);
- }
- } /* if first RG distance is within tolerance */
- log_debug("First RG distance: 0x%" PRIx64 "\n", first_rg_dist[subd]);
- log_debug("Section %d: distance between RGs: 0x%" PRIx64 "\n",
- subd + 1, shortest_dist_btwn_rgs[subd]);
- log_debug("Section size: 0x%" PRIx64 "\n", subdevice_size);
- /* If our rindex was all bad, we may have an improper count of RGs per
- section. We may also not know where the third section should start.
- We need those for later. */
- if (subd == 0) {
- if (shortest_dist_btwn_rgs[subd] != 0) {
- unsigned long long blocks_b4_sb;
- unsigned long long index_entries;
-
- blocks_b4_sb = (16 * (4096 / sdp->sb.sb_bsize));
- index_entries = (subdevice_size - blocks_b4_sb) /
- shortest_dist_btwn_rgs[subd];
- if (index_entries_per_subd != index_entries) {
- log_debug("rindex entries per section "
- "changed from %lld to %lld\n",
- index_entries_per_subd,
- index_entries);
- index_entries_per_subd = index_entries;
- }
- }
- if (fs_size_from_rgindex == 0) {
- fs_size_from_rgindex = (sdp->jindex->ji_addr +
- total_journal_space) +
- subdevice_size;
- log_debug("Fixed zero fs_size_from_rgindex "
- "due to rindex corruption.\n");
- log_debug("New fs_size_from_rgindex value: "
- "%lld (0x%" PRIx64 ")\n",
- fs_size_from_rgindex,
- fs_size_from_rgindex);
- }
- }
- } /* for subd */
- number_of_rgs = 0; /* reset this because it is reused below */
- /* ----------------------------------------------------------------- */
- /* Start reading the filesystem starting with the block after the */
- /* superblock, which should be the first RG. */
- /* The problem is that gfs_grow puts the RGs at unpredictable */
- /* locations. If the fs was only grown once, that would be */
- /* predictable. But if it grows twice, by different amounts, then */
- /* our RGs could be anywhere. After carefully studying the problem */
- /* I've determined that the best thing we can do is to trust the */
- /* rgindex and hope to God it's correct. That's the only way we're */
- /* going to be able to recover RGs in the third section. */
- /* ----------------------------------------------------------------- */
- /* I know it looks like prev_rgd should be set to NULL inside the
- following for loop, but that actually causes the last rindex
- entry to be improperly left with 0 values for ri_data and
- ri_bitbytes. So leave "prev_rgd = NULL" right here: */
- prev_rgd = NULL;
- block_bump = first_rg_dist[0];
- corrupt_rgs = 0;
- for (subd = 0; subd < 3; subd++) { /* third subdevice is for all RGs
- extended past the normal 2 with
- gfs_grow, etc. */
- if (subd == 0) {
- start_block = (GFS_SB_ADDR >> sdp->fsb2bb_shift) + 1;
- end_block = subdevice_size - 1;
- }
- else if (subd == 1) {
- start_block = sdp->jindex->ji_addr + total_journal_space;
- /* Moral dilemma: should we go to the last block or should */
- /* we trust the index? If they're close to one another, */
- /* let's use the index. */
- if ((fs_size_from_rgindex >> 2) ==
- ((start_block + subdevice_size - 1) >> 2)) /* if we're close */
- end_block = fs_size_from_rgindex - 1; /* trust the index */
- else /* otherwise */
- end_block = start_block + subdevice_size - 1; /* go to end */
- }
- else {
- /* Section 3 should start the block after section 2. However, */
- /* gfs_grow sometimes foolishly decides to put it as much as three */
- /* blocks early. So we need to check for this special case. */
- for (start_block = end_block - 2;
- start_block < end_block + 1; start_block++) {
- error = get_and_read_buf(sdp, start_block, &bh, 0);
- rg_was_fnd = (!check_type(bh, GFS_METATYPE_RG));
- relse_buf(sdp, bh); /* release the read buffer */
- if (rg_was_fnd)
- break;
- }
- end_block = fs_total_size - 1;
- if (start_block + GFS_NBBY >= end_block)
- break;
- }
- log_warn("Section %d: 0x%" PRIx64 " - 0x%" PRIx64 "\n", subd + 1,
- start_block, end_block);
- for (blok = start_block; blok <= end_block; blok += block_bump) {
- uint64 fwd_block;
- int bitmap_was_fnd;
-
- log_debug("Block 0x%" PRIx64 "\n", blok);
- error = get_and_read_buf(sdp, blok, &bh, 0);
- if (error) {
- log_crit("Unable to read block 0x%" PRIX64 "\n", blok);
- return -1;
- }
- rg_was_fnd = (!check_type(bh, GFS_METATYPE_RG));
- relse_buf(sdp, bh); /* release the read buffer */
- if (!rg_was_fnd && subd == 2) {
- if (section3_bump_size) {
- log_warn("Lost track of Section 3 rg length.\n");
- blok -= block_bump; /* back up in case we overshot it */
- section3_bump_size = 0;
- block_bump = 1;
- }
- if (block_bump == 1)
- continue;
- }
- /* ------------------------------------------------------------- */
- /* For the first and second subdevice, we know the RG size. */
- /* Since we're bumping by that amount, this better be an RG. */
- /* ------------------------------------------------------------- */
- /* Allocate a new RG and index. */
- calc_rgd = (struct fsck_rgrp *)malloc(sizeof(struct fsck_rgrp));
- // FIXME: handle failed malloc
- memset(calc_rgd, 0, sizeof(struct fsck_rgrp));
- calc_rgd->rd_sbd = sdp; /* hopefully this is not used */
- osi_list_add_prev(&calc_rgd->rd_list, ret_list);
- calc_rgd->rd_ri.ri_length = 1;
- calc_rgd->rd_ri.ri_addr = blok;
- if (!rg_was_fnd) { /* if not an RG */
- /* ----------------------------------------------------- */
- /* This SHOULD be an RG but isn't. */
- /* ----------------------------------------------------- */
- corrupt_rgs++;
- if (corrupt_rgs < 5)
- log_debug("Missing or damaged RG at block 0x%" PRIx64 \
- "\n", blok);
- else {
- log_crit("Error: too many bad RGs.\n");
- return -1;
- }
- }
- /* ------------------------------------------------ */
- /* Now go through and count the bitmaps for this RG */
- /* ------------------------------------------------ */
- bitmap_was_fnd = FALSE;
- for (fwd_block = blok + 1; fwd_block < fs_total_size;
- fwd_block++) {
- error = get_and_read_buf(sdp, fwd_block, &bh, 0);
- if (error){
- log_crit("Unable to read block 0x%" PRIX64 "\n",
- fwd_block);
- return -1;
- }
- bitmap_was_fnd = (!check_type(bh, GFS_METATYPE_RB));
- relse_buf(sdp, bh);
- if (bitmap_was_fnd) /* if a bitmap */
- calc_rgd->rd_ri.ri_length++;
- else
- break; /* end of bitmap, so call it quits. */
- } /* for subsequent bitmaps */
- calc_rgd->rd_ri.ri_data1 = calc_rgd->rd_ri.ri_addr +
- calc_rgd->rd_ri.ri_length;
- if (prev_rgd) {
- prev_rgd->rd_ri.ri_data = block_bump -
- rgrplength2bitblocks(sdp, block_bump);
- prev_rgd->rd_ri.ri_data -= prev_rgd->rd_ri.ri_data %
- GFS_NBBY;
- prev_rgd->rd_ri.ri_bitbytes = prev_rgd->rd_ri.ri_data /
- GFS_NBBY;
- log_debug("Prev ri_data set to: %" PRIx32 ".\n",
- prev_rgd->rd_ri.ri_data);
- /*prev_rgd->rd_ri.ri_data = block_bump;*/
- }
- number_of_rgs++;
- rgs_per_subd++;
- block_of_last_rg = blok;
- if (subd == 2) { /* if beyond the normal RGs into gfs_grow RGs */
- /* -------------------------------------------------------- */
- /* RG location is rounded down to the nearest multiple of */
- /* GFS_NBBY, so RG location is only known within a 4 block */
- /* range. It's better to use the rgindex to figure out */
- /* the address of the next RG and bump by the difference. */
- /* However, there's another complication: gfs_grow has */
- /* been known to add RGs to the index in a non-ascending */
- /* order. Therefore, we can't assume the Nth entry in the */
- /* index corresponds to the Nth RG on disk. Wish it was. */
- /* Instead, we have to read all of the rgindex until we */
- /* find an entry that has the smallest address greater than */
- /* the block we're on (blok). */
- /* -------------------------------------------------------- */
- if (section3_bump_size == 0) {
- uint64_t rgndx_next_block, highest_riaddr;
-
- rgndx_next_block = end_block;
- highest_riaddr = 0;
- for (rgi = 0; ; rgi++) {
- error = readi(sdp->riinode, (char *)&buf,
- rgi * sizeof(struct gfs_rindex),
- sizeof(struct gfs_rindex));
- if (!error) /* if end of the rgindex */
- break; /* stop processing for more RGs */
- gfs_rindex_in(&tmpndx, (char *)&buf);
- /* if this index entry is the next RG physically */
- if (tmpndx.ri_addr > blok &&
- tmpndx.ri_addr < rgndx_next_block) {
- rgndx_next_block = tmpndx.ri_addr; /* remember it */
- }
- if (tmpndx.ri_addr > highest_riaddr)
- highest_riaddr= tmpndx.ri_addr;
- }
- /* A special exception must be made for the last RG because we */
- /* won't have a "next highest" entry in the rindex. */
- if (blok == highest_riaddr)
- block_bump = end_block - blok + 1;
- else if (rgndx_next_block == end_block) {
- if (block_bump != 1) {
- log_warn("\nUnable to use rindex; "
- "doing block-by-block search.\n");
- log_warn("This will be slow, so be patient.\n");
- rgndx_next_block = blok + 1;
- block_bump = 1;
- } else {
- if (prev_rgd &&
- block_bump != blok -
- prev_rgd->rd_ri.ri_addr) {
- log_warn("I think I figured it out.\n");
- block_bump = blok -
- prev_rgd->rd_ri.ri_addr;
- section3_bump_size = block_bump;
- }
- }
- } else
- block_bump = rgndx_next_block - blok;
- }
- }
- else {
- if (blok == start_block)
- block_bump = first_rg_dist[subd];
- else
- block_bump = shortest_dist_btwn_rgs[subd];
- }
- if (block_bump == 1 && prev_rgd && subd == 2) {
- uint64_t last_distance = blok - prev_rgd->rd_ri.ri_addr;
-
- error = get_and_read_buf(sdp, blok + last_distance, &bh, 0);
- rg_was_fnd = (!check_type(bh, GFS_METATYPE_RG));
- relse_buf(sdp, bh); /* release the read buffer */
- if (rg_was_fnd)
- block_bump = last_distance;
- }
- log_warn("%c RG %d at block 0x%" PRIX64 " %s",
- (rg_was_fnd ? ' ' : '*'), number_of_rgs, blok,
- (rg_was_fnd ? "intact" : "*** DAMAGED ***"));
- log_warn(" [length 0x%" PRIx64 "]\n", block_bump);
- prev_rgd = calc_rgd;
- } /* for blocks in subdevice */
- } /* for subdevices */
- /* ------------------------------------------------------------------- */
- /* if we got to the end of the fs, we still need to fix the allocation */
- /* information for the very last RG. */
- /* ------------------------------------------------------------------- */
- if (prev_rgd && !prev_rgd->rd_ri.ri_data) {
- log_debug("Prev ri_data set to: %" PRIx32 ".\n", block_bump);
- prev_rgd->rd_ri.ri_data = block_bump -
- rgrplength2bitblocks(sdp, block_bump);
- prev_rgd->rd_ri.ri_data -= prev_rgd->rd_ri.ri_data % GFS_NBBY;
- prev_rgd->rd_ri.ri_bitbytes = prev_rgd->rd_ri.ri_data / GFS_NBBY;
- prev_rgd = NULL; /* make sure we don't use it later */
- }
- /* else No previous to fix. */
- /* ---------------------------- */
- /* Now dump out the information */
- /* ---------------------------- */
- log_debug("RG index rebuilt as follows:\n");
- for (tmp = ret_list->next, rgi = 0; tmp != ret_list;
- tmp = tmp->next, rgi++) {
- calc_rgd = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
- log_debug("%d: %x / 0x%" PRIx64 " / 0x%08X / 0x%08X\n",
- rgi + 1, calc_rgd->rd_ri.ri_length, calc_rgd->rd_ri.ri_data1,
- calc_rgd->rd_ri.ri_data, calc_rgd->rd_ri.ri_bitbytes);
- }
- *num_rgs = number_of_rgs;
- log_debug("Number of RGs = %d.\n", number_of_rgs);
- return 0;
-}
-
-/**
- * calc_device_journals - morphed from gfs_mkfs's add_journals_to_device()
- * journals: The number of journals
- * jsize: The journal size
- * @dvice: The mkfs device structure to be used
- *
- */
-static void calc_device_journals(struct fsck_sb *sdp, uint32 jsize,
- struct mkfs_device *dvice)
-{
- struct mkfs_subdevice *old;
- unsigned int x;
-
- jsize = jsize * (1 << 20) / GFS_BASIC_BLOCK;
- old = dvice->subdev;
-
- dvice->nsubdev = sdp->journals + 2;
- dvice->subdev = malloc(dvice->nsubdev * sizeof(struct mkfs_subdevice));
- memset(dvice->subdev, 0, (dvice->nsubdev *
- sizeof(struct mkfs_subdevice)));
-
- dvice->subdev[0].start = old->start;
- dvice->subdev[0].length = (old->length - sdp->journals * jsize) / 2;
-
- for (x = 1; x <= sdp->journals; x++) {
- dvice->subdev[x].start = dvice->subdev[x - 1].start +
- dvice->subdev[x - 1].length;
- dvice->subdev[x].length = jsize;
- dvice->subdev[x].is_journal = TRUE;
- }
-
- dvice->subdev[x].start = dvice->subdev[x - 1].start +
- dvice->subdev[x - 1].length;
- dvice->subdev[x].length = dvice->subdev[0].length;
-
- free(old);
-}
-
-/**
- * fix_device_geometry - round off address and lengths and convert to FS blocks
- * @comline: the command line
- * @device: the description of the underlying device
- *
- */
-
-static void fix_device_geometry(struct fsck_sb *sdp, struct mkfs_device *dvice)
-{
- unsigned int x;
- uint64 offset, len;
- uint32 bbsize = sdp->sb.sb_bsize >> GFS_BASIC_BLOCK_SHIFT;
-
- /* Make sure all the subdevices are aligned */
- for (x = 0; x < dvice->nsubdev; x++) {
- offset = dvice->subdev[x].start;
- len = dvice->subdev[x].length;
-
- if (offset % bbsize) {
- len -= bbsize - (offset % bbsize);
- offset += bbsize - (offset % bbsize);
- }
-
- dvice->subdev[x].start = offset / bbsize;
- dvice->subdev[x].length = len / bbsize;
- }
-}
-
-/*
- * gfs_rgindex_calculate - calculate what the rgindex should look like
- * in a perfect world (trust_lvl == open_minded)
- *
- * Calculate what the rgindex should look like if no gfs_grow-like operations
- * were performed, so we can later check if all RG index entries are sane.
- *
- * This function goes in blind, assuming the entire rgindex is destroyed.
- * That way, we can rebuild it if really is trashed.
- *
- * However, this won't work if the filesystem has been extended or shrunk.
- * If the RGs aren't where we expect them to be, we have to take more drastic
- * measures to recover them.
- *
- * Assumes: journal index file is minimally sane.
- *
- * We need to check if the address and length values are okay.
- * First RG should start after the superblock at block #x11
- * Number of RGs=subdevice size / (2^rgsize/block size)
- *
- * Returns: 0 on success, -1 on failure
- * Sets: ret_list to a linked list of fsck_rgrp structs representing
- * what we think the rgindex should really look like.
- */
-static int gfs_rgindex_calculate(struct fsck_sb *sdp, osi_list_t *ret_list,
- unsigned int *num_rgs)
-{
- osi_buf_t *bh; /* buffer handle */
- uint64 subdevice_size, fs_total_size;
- int number_of_rgs; /* min of 4 per segment * 2 segments = 8 */
- int error;
- int rgi, rgs_per_subd;
- uint64 subdevice_start;
- uint64 prev_addr = 0, prev_length = 0, length = 0;
- uint64 blocks;
- struct fsck_rgrp *calc_rgd;
- struct gfs_rindex buf, tmpndx;
- struct mkfs_device dvice;
- uint32 jsize;
- struct mkfs_subdevice *sdev;
- int x;
-
- memset(&dvice, 0, sizeof(dvice));
-
- osi_list_init(ret_list);
- *num_rgs = 0;
- /* Get the total size of the device */
- error = ioctl(sdp->diskfd, BLKGETSIZE64,
- &fs_total_size); /* Size in bytes */
-
- dvice.subdev = malloc(sizeof(struct mkfs_subdevice));
- dvice.subdev->start = 0;
- dvice.subdev->length = fs_total_size >> GFS_BASIC_BLOCK_SHIFT;
- dvice.subdev->is_journal = 0;
-
- fs_total_size /= sdp->sb.sb_bsize;
- log_debug("fs_total_size = 0x%" PRIX64 " blocks.\n", fs_total_size);
-
- /* The end of the first subdevice is also where the first journal is.*/
- subdevice_size = sdp->jindex->ji_addr; /* addr of 1st journal (blks) */
- jsize = sdp->ji_nsegment * sdp->sb.sb_seg_size * sdp->sb.sb_bsize;
- /* Round up to the nearest megabyte */
- jsize = (jsize + (1024*1024) - 1) / (1024*1024);
-
- log_debug("subdevice_size = 0x%" PRIX64 ".\n", subdevice_size);
- log_debug("jsize = 0x%x\n", jsize);
-
- calc_device_journals(sdp, jsize, &dvice);
- fix_device_geometry(sdp, &dvice);
-
- /* ----------------------------------------------------------------- */
- /* Read the first block of the subdevice and make sure it's an RG. */
- /* ----------------------------------------------------------------- */
- subdevice_start = dvice.subdev[sdp->journals + 1].start;
- error = get_and_read_buf(sdp, subdevice_start, &bh, 0);
- if (error){
- log_crit("Unable to read start of last subdevice.\n");
- return -1;
- }
- if(check_type(bh, GFS_METATYPE_RG)){
- log_warn("The middle RG is not on an even boundary (fs has grown?)\n");
- relse_buf(sdp, bh);
- return -1;
- }
- log_debug("First RG is okay.\n");
- /* --------------------------------------------------------------------- */
- /* Calculate how many RGs there are supposed to be based on the */
- /* rgindex filesize. Remember that our trust level is open-minded here. */
- /* If the filesize of the rgindex file is not a multiple of our rgindex */
- /* structures, then something's wrong and we can't trust the index. */
- /* --------------------------------------------------------------------- */
- number_of_rgs = sdp->riinode->i_di.di_size / sizeof(struct gfs_rindex);
- *num_rgs = number_of_rgs;
- log_warn("number_of_rgs = %d.\n", number_of_rgs);
- if (sdp->riinode->i_di.di_size % sizeof(struct gfs_rindex)) {
- log_warn("WARNING: rgindex file is corrupt.\n");
- return -1;
- }
- /* --------------------------------------------------------------------- */
- /* Check to see if the filesystem has been extended via gfs_grow. */
- /* If so, our assumptions will be wrong and we can't continue. */
- /* Instead, we need to progress to level 3 and dig deeper for the RGs. */
- /* We'll know if the filesystem has been extended by whether or not the */
- /* RG that's midway is on the wrong side of the journals. */
- /* For example, if we have 50 RGs, we'd expect 25 to be on one side of */
- /* the journals, and 25 to be on the other side. If we find out that */
- /* RG number 25 (index 1, or 24 index 0) is on the other side, we grew. */
- /* --------------------------------------------------------------------- */
- rgi = (number_of_rgs / 2) - 1;
- error = readi(sdp->riinode,
- (char *)&buf, rgi * sizeof(struct gfs_rindex),
- sizeof(struct gfs_rindex));
- if (!error) { /* if end of file */
- log_warn("Error reading RG index.\n");
- return -1; /* stop looking */
- }
- gfs_rindex_in(&tmpndx, (char *)&buf); /* read in the index entry. */
- if (tmpndx.ri_addr >= sdp->jindex->ji_addr) { /* wrong side of journals */
- log_warn("This filesystem has probably been resized by gfs_grow.\n");
- return -1; /* stop looking */
- }
- /* --------------------------------------------------------------------- */
- /* Now that we know how many RGs there should be, we can calculate */
- /* exactly where we think they should be and build our index with it. */
- /* --------------------------------------------------------------------- */
- rgs_per_subd = (number_of_rgs / 2);
- for (x = 0; x < dvice.nsubdev; x++) {
- sdev = &dvice.subdev[x];
-
- if (sdev->is_journal)
- continue;
- /* If this is the first subdevice reserve space for the
- superblock */
-
- if (!x)
- sdev->length -= (GFS_SB_ADDR * GFS_BASIC_BLOCK /
- sdp->sb.sb_bsize) + 1;
- for (rgi = 0; rgi < rgs_per_subd; rgi++) {
- calc_rgd = (struct fsck_rgrp *)
- malloc(sizeof(struct fsck_rgrp));
- memset(calc_rgd, 0, sizeof(struct fsck_rgrp));
- calc_rgd->rd_sbd = sdp; /* this may not be used */
- if (rgi) {
- calc_rgd->rd_ri.ri_addr = prev_addr +
- prev_length;
- length = sdev->length / rgs_per_subd;
- } else {
- calc_rgd->rd_ri.ri_addr = sdev->start;
- length = sdev->length - (rgs_per_subd - 1) *
- (sdev->length / rgs_per_subd);
- if (!x)
- calc_rgd->rd_ri.ri_addr +=
- (GFS_SB_ADDR *
- GFS_BASIC_BLOCK /
- sdp->sb.sb_bsize) + 1;
- }
- osi_list_add_prev(&calc_rgd->rd_list, ret_list);
-
- log_info("ri_addr[%d] = 0x%"PRIx64 " / ", rgi,
- calc_rgd->rd_ri.ri_addr);
- blocks = length - rgrplength2bitblocks(sdp, length);
- blocks -= blocks % GFS_NBBY;
- calc_rgd->rd_ri.ri_length =
- rgrplength2bitblocks(sdp, length);
- calc_rgd->rd_ri.ri_data1 = calc_rgd->rd_ri.ri_addr +
- calc_rgd->rd_ri.ri_length;
- calc_rgd->rd_ri.ri_data = blocks;
- calc_rgd->rd_ri.ri_bitbytes =
- calc_rgd->rd_ri.ri_data / GFS_NBBY;
- log_info("%d / %08x / %08x / %08x\n",
- calc_rgd->rd_ri.ri_length,
- calc_rgd->rd_ri.ri_data1,
- calc_rgd->rd_ri.ri_data,
- calc_rgd->rd_ri.ri_bitbytes);
- prev_addr = calc_rgd->rd_ri.ri_addr;
- prev_length = length;
- }
- } /* for */
- relse_buf(sdp, bh); /* release the read buffer if we have one */
- return 0;
-}
-
-/*
- * ri_cleanup - free up the memory we previously allocated.
- */
-static void ri_cleanup(osi_list_t *rglist)
-{
- struct fsck_rgrp *rgd;
-
- while(!osi_list_empty(rglist)){
- rgd = osi_list_entry(rglist->next, struct fsck_rgrp, rd_list);
- if(rgd->rd_bits)
- free(rgd->rd_bits);
- if(rgd->rd_bh)
- free(rgd->rd_bh);
- osi_list_del(&rgd->rd_list);
- free(rgd);
- }
-}
-
-/**
- * ri_update - attach rgrps to the super block
- * @sdp:
- *
- * Given the rgrp index inode, link in all rgrps into the super block
- * and be sure that they can be read.
- *
- * If we encounter problems with any RGs, it either means we have a corrupt
- * RG or a corrupt RG file entry (which is less likely). We make up to three
- * attempts to do this. First, we trust that the RG index is correct and
- * read the RGs. If that fails, we become a little less trusting and
- * try to calculate what the RG index should look like in a perfect world.
- * If that doesn't work, we become even less trusting and go to great lengths
- * to figure out exactly where those RGs should be and what the index should
- * look like.
- *
- * Returns: 0 on success, -1 on failure.
- */
-int ri_update(struct fsck_sb *sdp)
-{
- struct fsck_rgrp *rgd, *expected_rgd;
- osi_list_t expected_rglist; /* List of expected resource groups */
- osi_list_t *tmp;
- struct gfs_rindex buf;
- unsigned int rg, calc_rg_count = 0;
- int error, count1 = 0, count2 = 0;
- int fix_grow_problems = 0, grow_problems = 0;
- enum rgindex_trust_level { /* how far can we trust our RG index? */
- blind_faith = 0, /* We'd like to trust the rgindex. We always used to
- before bz 179069. This should cover most cases. */
- open_minded = 1, /* At least 1 RG is corrupt. Try to calculate what it
- should be, in a perfect world where our RGs are all
- on even boundaries. Blue sky. Chirping birds. */
- distrust = 2 /* The world isn't perfect, our RGs are not on nice neat
- boundaries. The fs must have been messed with by
- gfs_grow or something. Count the RGs by hand. */
- } trust_lvl;
-
- log_info("Validating Resource Group index.\n");
- for (trust_lvl = blind_faith; trust_lvl <= distrust; trust_lvl++) {
- log_info("Level %d check.\n", trust_lvl + 1);
- count1 = count2 = 0;
- /* ---------------------------------------------------------------- */
- /* Step 1 - Calculate or figure out our own RG index */
- /* ---------------------------------------------------------------- */
- if (trust_lvl == blind_faith) { /* For now, assume rgindex is gospel */
- osi_list_init(&expected_rglist);
- error = FALSE;
- }
- else if (trust_lvl == open_minded) { /* If we can't trust RG index */
- /* Calculate our own RG index for comparison */
- error = gfs_rgindex_calculate(sdp, &expected_rglist,
- &calc_rg_count);
- if (error) { /* If calculated RGs don't reasonably match the fs */
- log_info("(failed--trying again at level 3)\n");
- ri_cleanup(&sdp->rglist);
- continue; /* Try again, this time counting them manually */
- }
- }
- else if (trust_lvl == distrust) { /* If we can't trust RG index */
- error = gfs_rgindex_rebuild(sdp, &expected_rglist,
- &calc_rg_count); /* count the RGs. */
- if (error) { /* If calculated RGs don't reasonably match the fs */
- log_info("(failed--giving up)\n");
- goto fail; /* try again, this time counting them manually */
- }
- }
- /* ---------------------------------------------------------------- */
- /* Step 2 - Read the real RG index and check its integrity */
- /* ---------------------------------------------------------------- */
- for (rg = 0; ; rg++) {
- int rgindex_modified;
-
- rgindex_modified = FALSE;
- error = readi(sdp->riinode, (char *)&buf,
- rg * sizeof(struct gfs_rindex),
- sizeof(struct gfs_rindex));
- if (!error) /* if no data was read */
- break; /* we found the end of the rg index file */
- if (error != sizeof(struct gfs_rindex)) {
- log_err("Unable to read resource group index #%u.\n", rg);
- goto fail;
- }
- if (trust_lvl != blind_faith && osi_list_empty(&expected_rglist))
- break;
-
- rgd = (struct fsck_rgrp *)malloc(sizeof(struct fsck_rgrp));
- // FIXME: handle failed malloc
- memset(rgd, 0, sizeof(struct fsck_rgrp));
- rgd->rd_sbd = sdp;
- osi_list_add_prev(&rgd->rd_list, &sdp->rglist);
- gfs_rindex_in(&rgd->rd_ri, (char *)&buf);
- if (trust_lvl != blind_faith) {
- expected_rgd = osi_list_entry(expected_rglist.next,
- struct fsck_rgrp, rd_list);
- /* --------------------------------------------------------- */
- /* Now compare the index to the one we calculated / rebuilt */
- /* Since this is fsck and fsck's job is to fix filesystem */
- /* corruption, it's probably better to trust the calculated */
- /* value and discard what's reported on disk. */
- /* --------------------------------------------------------- */
- ri_compare(rg, rgd->rd_ri, expected_rgd->rd_ri,
- ri_addr, PRIx64);
- ri_compare(rg, rgd->rd_ri, expected_rgd->rd_ri,
- ri_length, PRIx32);
- ri_compare(rg, rgd->rd_ri, expected_rgd->rd_ri,
- ri_data1, PRIx64);
- ri_compare(rg, rgd->rd_ri, expected_rgd->rd_ri,
- ri_data, PRIx32);
- ri_compare(rg, rgd->rd_ri, expected_rgd->rd_ri,
- ri_bitbytes, PRIx32);
- /* If we modified the index, write it back to disk. */
- if (rgindex_modified) {
- errors_found++;
- if(query(sdp, "Fix the index? (y/n)")) {
- gfs_rindex_out(&rgd->rd_ri, (char *)&buf);
- error = writei(sdp->riinode, (char *)&buf,
- rg * sizeof(struct gfs_rindex),
- sizeof(struct gfs_rindex));
- if (error != sizeof(struct gfs_rindex)) {
- log_err("Unable to fix resource group index %u.\n",
- rg + 1);
- goto fail;
- } else {
- errors_corrected++;
- }
- }
- else
- log_err("RG index not fixed.\n");
- }
- osi_list_del(&expected_rgd->rd_list);
- free(expected_rgd);
- } /* if we can't trust the rg index */
- else { /* blind faith -- just check for the gfs_grow problem */
- if (rgd->rd_ri.ri_data == (uint32_t)-4) {
- if (!fix_grow_problems) {
- log_err("A problem with the rindex file caused by gfs_grow was detected.\n");
- errors_found++;
- if(query(sdp, "Fix the rindex problem? (y/n)")) {
- errors_corrected++;
- fix_grow_problems = 1;
- }
- }
- /* Keep a counter in case we hit it more than once. */
- grow_problems++;
- osi_list_del(&rgd->rd_list); /* take it out of the equation */
- free(rgd);
- continue;
- } else if (fix_grow_problems) {
- /* Once we detect the gfs_grow rindex problem, we have to */
- /* rewrite the entire rest of the rindex file, starting */
- /* with the entry AFTER the one that has the problem. */
- gfs_rindex_out(&rgd->rd_ri, (char *)&buf);
- error = writei(sdp->riinode, (char *)&buf,
- (rg - grow_problems) *
- sizeof(struct gfs_rindex),
- sizeof(struct gfs_rindex));
- if (error != sizeof(struct gfs_rindex)) {
- log_err("Unable to fix rindex entry %u.\n",
- rg + 1);
- goto fail;
- }
- }
- }
- error = fs_compute_bitstructs(rgd);
- if (error)
- break;
- rgd->rd_open_count = 0;
- count1++;
- } /* for all RGs in the index */
- rg -= grow_problems;
- if (!error) {
- log_info("%u resource groups found.\n", rg);
- if (trust_lvl != blind_faith && rg != calc_rg_count)
- log_warn("Resource group count discrepancy. Index says %d. " \
- "Should be %d.\n", rg, calc_rg_count);
- /* ------------------------------------------------------------- */
- /* Step 3 - Read the real RGs and check their integrity. */
- /* Now we can somewhat trust the rgindex and the RG addresses, */
- /* so let's read them in, check them and optionally fix them. */
- /* ------------------------------------------------------------- */
- error = FALSE;
- for (tmp = sdp->rglist.next; !error && tmp != &sdp->rglist;
- tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
- error = fs_rgrp_read(rgd, trust_lvl);
- if (error)
- log_err("Unable to read in rgrp descriptor.\n");
- else
- fs_rgrp_relse(rgd);
- count2++;
- }
- if (!error && count1 != count2){
- log_err("Rgrps allocated (%d) does not equal"
- " rgrps read (%d).\n", count1, count2);
- error = -1;
- }
- sdp->rgcount = count1;
- }
- if (fix_grow_problems) {
- osi_buf_t *dibh;
-
- get_and_read_buf(sdp, sdp->sb.sb_rindex_di.no_addr, &dibh, 0);
- sdp->riinode->i_di.di_size = rg * sizeof(struct gfs_rindex);
- gfs_dinode_out(&sdp->riinode->i_di, BH_DATA(dibh));
- write_buf(sdp, dibh, 0);
- grow_problems = fix_grow_problems = 0;
- relse_buf(sdp, dibh);
- }
- if (!error) { /* if no problems encountered with the rgs */
- log_info("(passed)\n");
- break; /* no reason to distrust what we saw. Otherwise, we
- reiterate and become a little less trusting. */
- }
- else {
- if (trust_lvl < distrust)
- log_info("(failed--trying again at level 2)\n");
- else
- log_info("(failed--recovery impossible)\n");
- }
- ri_cleanup(&sdp->rglist);
- } /* for trust_lvl */
- return 0;
-
- fail:
- ri_cleanup(&sdp->rglist);
- return -1;
-}
-
-int write_sb(struct fsck_sb *sbp)
-{
- int error = 0;
- osi_buf_t *bh;
-
- error = get_and_read_buf(sbp, GFS_SB_ADDR >> sbp->fsb2bb_shift, &bh, 0);
- if (error){
- log_crit("Unable to read superblock\n");
- goto out;
- }
-
- gfs_sb_out(&sbp->sb, BH_DATA(bh));
-
- if((error = write_buf(sbp, bh, BW_WAIT))) {
- stack;
- goto out;
- }
-
- relse_buf(sbp, bh);
-out:
- return error;
-
-}
-
diff --git a/gfs/gfs_fsck/super.h b/gfs/gfs_fsck/super.h
deleted file mode 100644
index 702c804..0000000
--- a/gfs/gfs_fsck/super.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _SUPER_H
-#define _SUPER_H
-
-#include "fsck_incore.h"
-
-int read_sb(struct fsck_sb *sdp);
-int ji_update(struct fsck_sb *sdp);
-int ri_update(struct fsck_sb *sdp);
-int write_sb(struct fsck_sb *sdp);
-
-#endif /* _SUPER_H */
diff --git a/gfs/gfs_fsck/util.c b/gfs/gfs_fsck/util.c
deleted file mode 100644
index 81aeb69..0000000
--- a/gfs/gfs_fsck/util.c
+++ /dev/null
@@ -1,333 +0,0 @@
-#include "bio.h"
-#include "fs_bits.h"
-
-#include "util.h"
-#include "log.h"
-
-/**
- * compute_height
- * @sdp:
- * @sz:
- *
- */
-int compute_height(struct fsck_sb *sdp, uint64 sz)
-{
- unsigned int height;
- uint64 space, old_space;
- unsigned int bsize = sdp->sb.sb_bsize;
-
- if (sz <= (bsize - sizeof(struct gfs_dinode)))
- return 0;
-
- height = 1;
- space = sdp->diptrs * bsize;
-
- while (sz > space)
- {
- old_space = space;
-
- height++;
- space *= sdp->inptrs;
-
- if (space / sdp->inptrs != old_space ||
- space % sdp->inptrs != 0)
- break;
- }
-
- return height;
-}
-
-
-/*
- * check_range - check if blkno is within FS limits
- * @sdp: super block
- * @blkno: block number
- *
- * Returns: 0 if ok, -1 if out of bounds
- */
-int check_range(struct fsck_sb *sdp, uint64 blkno){
- if((blkno > sdp->last_fs_block) ||
- (blkno < sdp->first_data_block))
- return -1;
- return 0;
-}
-
-
-/*
- * set_meta - set the meta header of a buffer
- * @bh
- * @type
- *
- * Returns: 0 if ok, -1 on error
- */
-int set_meta(osi_buf_t *bh, int type, int format){
- struct gfs_meta_header header;
-
- if(!check_meta(bh, 0)){
- log_debug("Setting metadata\n");
- ((struct gfs_meta_header *)BH_DATA(bh))->mh_type = cpu_to_gfs32(type);
- ((struct gfs_meta_header *)BH_DATA(bh))->mh_format = cpu_to_gfs32(format);
- } else {
- memset(&header, 0, sizeof(struct gfs_meta_header));
- header.mh_magic = GFS_MAGIC;
- header.mh_type = type;
- header.mh_format = format;
-
- gfs_meta_header_out(&header, BH_DATA(bh));
- }
- return 0;
-}
-
-
-
-
-/*
- * check_meta - check the meta header of a buffer
- * @bh: buffer to check
- * @type: meta type (or 0 if don't care)
- *
- * Returns: 0 if ok, -1 on error
- */
-int check_meta(osi_buf_t *bh, int type){
- uint32 check_magic = ((struct gfs_meta_header *)BH_DATA((bh)))->mh_magic;
- uint32 check_metatype = ((struct gfs_meta_header *)BH_DATA((bh)))->mh_type;
-
- check_magic = gfs32_to_cpu(check_magic);
- check_metatype = gfs32_to_cpu(check_metatype);
- if((check_magic != GFS_MAGIC) || (type && (check_metatype != type))){
- log_debug("For %"PRIu64" Expected %X:%X - got %X:%X\n", BH_BLKNO(bh), GFS_MAGIC, type,
- check_magic, check_metatype);
- return -1;
- }
- return 0;
-}
-
-/*
- * check_type - check the meta type of a buffer
- * @bh: buffer to check
- * @type: meta type
- *
- * Returns: 0 if ok, -1 on error
- */
-int check_type(osi_buf_t *bh, int type){
- uint32 check_magic = ((struct gfs_meta_header *)BH_DATA((bh)))->mh_magic;
- uint32 check_metatype = ((struct gfs_meta_header *)BH_DATA((bh)))->mh_type;
-
- check_magic = gfs32_to_cpu(check_magic);
- check_metatype = gfs32_to_cpu(check_metatype);
- if((check_magic != GFS_MAGIC) || (check_metatype != type)){
- return -1;
- }
- return 0;
-}
-
-/**
- * next_rg_meta
- * @rgd:
- * @block:
- * @first: if set, start at zero and ignore block
- *
- * The position to start looking from is *block. When a block
- * is found, it is returned in block.
- *
- * Returns: 0 on success, -1 when finished
- */
-int next_rg_meta(struct fsck_rgrp *rgd, uint64 *block, int first)
-{
- fs_bitmap_t *bits = NULL;
- uint32 length = rgd->rd_ri.ri_length;
- uint32 blk = (first)? 0: (uint32)((*block+1)-rgd->rd_ri.ri_data1);
- int i;
-
- if(!first && (*block < rgd->rd_ri.ri_data1)){
- log_err("next_rg_meta: Start block is outside rgrp bounds.\n");
- exit(FSCK_ERROR);
- }
-
- for(i=0; i < length; i++){
- bits = &rgd->rd_bits[i];
- if(blk < bits->bi_len*GFS_NBBY){
- break;
- }
- blk -= bits->bi_len*GFS_NBBY;
- }
-
-
- for(; i < length; i++){
- bits = &rgd->rd_bits[i];
-
- blk = fs_bitfit((unsigned char *)BH_DATA(rgd->rd_bh[i]) + bits->bi_offset,
- bits->bi_len, blk, GFS_BLKST_USEDMETA);
-
- if(blk != BFITNOENT){
- *block = blk + (bits->bi_start * GFS_NBBY) + rgd->rd_ri.ri_data1;
- break;
- }
-
- blk=0;
- }
-
- if(i == length){
- return -1;
- }
- return 0;
-}
-
-/**
- * next_rg_meta_free - finds free or used metadata
- * @rgd:
- * @block:
- * @first: if set, start at zero and ignore block
- *
- * The position to start looking from is *block. When a block
- * is found, it is returned in block.
- *
- * Returns: 0 on success, -1 when finished
- */
-int next_rg_meta_free(struct fsck_rgrp *rgd, uint64 *block, int first, int *mfree)
-{
- fs_bitmap_t *bits = NULL;
- uint32 length = rgd->rd_ri.ri_length;
- uint32 blk = (first)? 0: (uint32)((*block+1)-rgd->rd_ri.ri_data1);
- uint32 ublk, fblk;
- int i;
-
- if(!first && (*block < rgd->rd_ri.ri_data1)){
- log_err("next_rg_meta: Start block is outside rgrp bounds.\n");
- exit(FSCK_ERROR);
- }
-
- for(i=0; i < length; i++){
- bits = &rgd->rd_bits[i];
- if(blk < bits->bi_len*GFS_NBBY){
- break;
- }
- blk -= bits->bi_len*GFS_NBBY;
- }
-
-
- for(; i < length; i++){
- bits = &rgd->rd_bits[i];
-
- ublk = fs_bitfit((unsigned char *)BH_DATA(rgd->rd_bh[i]) + bits->bi_offset,
- bits->bi_len, blk, GFS_BLKST_USEDMETA);
-
- fblk = fs_bitfit((unsigned char *)BH_DATA(rgd->rd_bh[i]) + bits->bi_offset,
- bits->bi_len, blk, GFS_BLKST_FREEMETA);
- if(ublk < fblk) {
- blk = ublk;
- *mfree = 0;
- } else {
- blk = fblk;
- *mfree = 1;
- }
- if(blk != BFITNOENT){
- *block = blk + (bits->bi_start * GFS_NBBY) + rgd->rd_ri.ri_data1;
- break;
- }
-
- blk=0;
- }
-
- if(i == length){
- return -1;
- }
- return 0;
-}
-
-
-/**
- * next_rg_metatype
- * @rgd:
- * @block:
- * @type: the type of metadata we're looking for
- * @first: if set we should start at block zero and block is ignored
- *
- * Returns: 0 on success, -1 on error or finished
- */
-int next_rg_metatype(struct fsck_rgrp *rgd, uint64 *block, uint32 type, int first)
-{
- struct fsck_sb *sdp = rgd->rd_sbd;
- osi_buf_t *bh=NULL;
-
- do{
- relse_buf(sdp, bh);
- if(next_rg_meta(rgd, block, first))
- return -1;
-
- if(get_and_read_buf(sdp, *block, &bh, 0)){
- log_err("next_rg_metatype: Unable to read meta block "
- "#%"PRIu64" from disk\n", *block);
- exit(FSCK_ERROR);
- }
-
- if(check_meta(bh,0)){
- log_err("next_rg_metatype: next_rg_meta returned block #%"PRIu64",\n"
- " which is not a valid meta block.\n", *block);
- exit(FSCK_ERROR);
- }
-
- first = 0;
- } while(check_meta(bh, type));
- relse_buf(sdp, bh);
-
- return 0;
-}
-
-
-
-#if 0
-/**
- * search_list
- * @list
- * @addr
- *
- * Returns: di_info_t ptr if found, NULL otherwise
- */
-struct di_info *search_list(osi_list_t *list, uint64 addr)
-{
- osi_list_t *tmp;
- struct di_info *dinfo;
-
- for (tmp = list->next; tmp != list; tmp = tmp->next)
- {
- dinfo = osi_list_entry(tmp, struct di_info, din_list);
-
- if (dinfo->din_addr == addr)
- return(dinfo);
- }
-
- return NULL;
-}
-#endif
-
-/* Put out a warm, fuzzy message every second so the user */
-/* doesn't think we hung. (This may take a long time). */
-/* We only check whether to report every one percent because */
-/* checking every block kills performance. We only report */
-/* every second because we don't need 100 extra messages in */
-/* logs made from verbose mode. */
-void warm_fuzzy_stuff(uint64_t block)
-{
- static uint64_t one_percent = 0;
- static struct timeval tv;
- static uint32_t seconds = 0;
-
- if (!one_percent)
- one_percent = last_fs_block / 100;
- if (block - last_reported_block >= one_percent) {
- last_reported_block = block;
- gettimeofday(&tv, NULL);
- if (!seconds)
- seconds = tv.tv_sec;
- if (tv.tv_sec - seconds) {
- static uint64_t percent;
-
- seconds = tv.tv_sec;
- if (last_fs_block) {
- percent = (block * 100) / last_fs_block;
- log_notice("\r%" PRIu64 " percent complete.\r", percent);
- }
- }
- }
-}
diff --git a/gfs/gfs_fsck/util.h b/gfs/gfs_fsck/util.h
deleted file mode 100644
index 7a4a041..0000000
--- a/gfs/gfs_fsck/util.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef __UTIL_H__
-#define __UTIL_H__
-
-#include "fsck_incore.h"
-
-#define do_lseek(fd, off) \
- ((lseek((fd), (off), SEEK_SET) == (off)) ? 0 : -1)
-
-#define do_read(fd, buff, len) \
- ((read((fd), (buff), (len)) == (len)) ? 0 : -1)
-
-#define do_write(fd, buff, len) \
- ((write((fd), (buff), (len)) == (len)) ? 0 : -1)
-
-
-int compute_height(struct fsck_sb *sdp, uint64 sz);
-int check_range(struct fsck_sb *sdp, uint64 blkno);
-int set_meta(osi_buf_t *bh, int type, int format);
-int check_type(osi_buf_t *bh, int type);
-int check_meta(osi_buf_t *bh, int type);
-int next_rg_meta(struct fsck_rgrp *rgd, uint64 *block, int first);
-int next_rg_meta_free(struct fsck_rgrp *rgd, uint64 *block, int first, int *free);
-int next_rg_metatype(struct fsck_rgrp *rgd, uint64 *block, uint32 type, int first);
-struct di_info *search_list(osi_list_t *list, uint64 addr);
-void warm_fuzzy_stuff(uint64_t block);
-
-#endif /* __UTIL_H__ */
diff --git a/gfs/gfs_grow/Makefile b/gfs/gfs_grow/Makefile
deleted file mode 100644
index 9c54b12..0000000
--- a/gfs/gfs_grow/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-TARGET= gfs_grow
-
-SBINDIRT=$(TARGET)
-
-all: depends ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= main.o \
- ondisk.o
-
-CFLAGS += -DHELPER_PROGRAM -D_FILE_OFFSET_BITS=64
-CFLAGS += -I${gfskincdir}
-CFLAGS += -I$(S)/../include -I$(S)/../libgfs
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L../libgfs -lgfs
-LDFLAGS += -L${libdir}
-
-LDDEPS += ../libgfs/libgfs.a
-
-${TARGET}: ${OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-depends:
- $(MAKE) -C ../libgfs all
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs/gfs_grow/main.c b/gfs/gfs_grow/main.c
deleted file mode 100644
index ecb8b36..0000000
--- a/gfs/gfs_grow/main.c
+++ /dev/null
@@ -1,974 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <sys/ioctl.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "gfs_ondisk.h"
-#define __user
-#include "gfs_ioctl.h"
-#include "osi_list.h"
-#include "libgfs.h"
-
-#include "copyright.cf"
-
-struct rglist_entry {
- osi_list_t list;
- struct gfs_rindex ri;
- struct gfs_rgrp rg;
-};
-
-struct jilist_entry {
- osi_list_t list;
- struct gfs_jindex ji;
-};
-
-/*
- * verbose: 0 = no messages, 1 = normal, 2 = everything
- * test: 0 = normal, 1 = don't actually write data, but do everything else
- * fspath: path to root of mounted GFS filesystem
- * device: the device upon which the GFS filesystem is mounted
- * fsoptions: the mount options used
- * devsize: the size of the device (in filesystem blocks, rounded down)
- * fssize: the size of the filesystem (in filesystem blocks, rounded down)
- * override_device_size: if non-zero, this is used for the device size
- */
-static int verbose = 1;
-static int test = 0;
-static char fspath[4096];
-static char device[1024];
-static char fsoptions[4096];
-static uint64_t devsize;
-static uint64_t fssize;
-static uint64_t override_device_size = 0;
-
-/*
- * fs_sb: the superblock read from the mounted filesystem
- * rglist_current: list of resource groups currently making up the filesystem
- * rglist_new: where we put the new resource groups to be written
- * jilist_current: list of current journals in the filesystem
- */
-static struct gfs_sb fs_sb;
-static osi_list_decl(rglist_current);
-static osi_list_decl(rglist_new);
-static osi_list_decl(jilist_current);
-
-/**
- * device_geometry - Find out the size of a block device
- * @device: The name of the device
- *
- * Returns: The size of the device in FS blocks
- */
-
-static uint64_t
-device_geometry(char *device_g)
-{
- int fd;
- uint64_t bytes;
- int error;
-
- if (override_device_size)
- bytes = override_device_size;
- else {
- fd = open(device_g, O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "gfs_grow: can't open %s: %s\n",
- device_g, strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- error = device_size(fd, &bytes);
- if (error) {
- fprintf(stderr,
- "gfs_grow: can't determine size of %s: %s\n",
- device_g, strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- close(fd);
- }
-
- return bytes >> fs_sb.sb_bsize_shift;
-}
-
-/**
- * jread - Read from journaled file using ioctl()
- * @fd: The fd to read from
- * @file: The file to read
- * @buf: The buffer to fill
- * @size: The amount of data to read
- * @offset: The offset to read from
- *
- * Returns: Error code, or amount of data read
- */
-
-static int
-jread(int fd, const char *file, void *buf, uint64_t size, uint64_t *offset)
-{
- struct gfs_ioctl gi;
- char *argv[] = {
- (char *)"do_hfile_read",
- (char *)file
- };
- int error;
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = buf;
- gi.gi_size = size;
- gi.gi_offset = *offset;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error > 0)
- *offset += error;
-
- return error;
-}
-
-/**
- * jwrite - Write to journaled file using ioctl()
- * @fd: The fd to write to
- * @file: The file to write
- * @buf: The buffer to write
- * @size: The amount of data to write
- * @offset: The offset at which to write the data
- *
- * Returns: Error code, or the amount of data written
- */
-
-static int
-jwrite(int fd, const char *file, void *buf, uint64_t size, uint64_t *offset)
-{
- struct gfs_ioctl gi;
- char *argv[] = {
- (char *)"do_hfile_write",
- (char *)file
- };
- int error;
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = buf;
- gi.gi_size = size;
- gi.gi_offset = *offset;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error > 0)
- *offset += error;
-
- return error;
-}
-
-/**
- * filesystem_size - Calculate the size of the filesystem
- *
- * Reads the lists of journals and resource groups in order to
- * work out where the last block of the filesystem is located.
- *
- * Returns: The calculated size
- */
-
-static uint64_t
-filesystem_size(void)
-{
- osi_list_t *tmp, *head;
- struct rglist_entry *rgl;
- struct jilist_entry *jil;
- uint64_t size = 0;
- uint64_t extent;
-
- tmp = head = &rglist_current;
- for (;;) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- rgl = osi_list_entry(tmp, struct rglist_entry, list);
- extent = rgl->ri.ri_addr + rgl->ri.ri_length + rgl->ri.ri_data;
- if (extent > size)
- size = extent;
- }
-
- tmp = head = &jilist_current;
- for (;;) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- jil = osi_list_entry(tmp, struct jilist_entry, list);
- extent = jil->ji.ji_addr + jil->ji.ji_nsegment * fs_sb.sb_seg_size;
- if (extent > size)
- size = extent;
- }
-
- return size;
-}
-
-/**
- * gfs_jientry - Get journal index entry
- * @fd: The fd of the journal index
- * @offset: The offset at which the journal entry appears
- *
- * Reads a single entry from the journal index file and
- * adds it to the list of current journal entries.
- *
- * Returns: 1 on EOF, 0 otherwise
- */
-
-static int
-get_jientry(int fd, uint64_t *offset)
-{
- char buffer[sizeof(struct gfs_jindex)];
- int len = jread(fd, "jindex", buffer,
- sizeof(struct gfs_jindex), offset);
- struct jilist_entry *jil;
-
- if (len != sizeof(struct gfs_jindex)) {
- if (len == 0)
- return 1;
- fprintf(stderr, "Erk! Read odd size from jindex (%d)\n", len);
- exit(EXIT_FAILURE);
- }
- if ((jil = malloc(sizeof(struct jilist_entry))) == NULL) {
- perror("jilist_entry");
- exit(EXIT_FAILURE);
- }
- memset(jil, 0, sizeof(struct jilist_entry));
- gfs_jindex_in(&jil->ji, buffer);
- osi_list_add(&jil->list, &jilist_current);
- return 0;
-}
-
-/**
- * read_journals - Read the whole journal index
- * @fs_fd: An fd for some file or directory within the mounted GFS filesystem
- *
- */
-
-static void
-read_journals(int fs_fd)
-{
- uint64_t offset = 0;
- while (get_jientry(fs_fd, &offset) == 0)
- /* do nothing */;
-}
-
-/**
- * get_rgrp - Read a single rindex entry
- * @fd: The fd for the rindex file
- * @offset: The offset at which to read the rindex entry
- *
- * Reads a single rindex entry and adds it to the list of current
- * resource group entries.
- *
- * Returns: 1 on EOF, 0 otherwise
- */
-
-static int
-get_rgrp(int fd, uint64_t *offset)
-{
- char buffer[sizeof(struct gfs_rindex)];
- int len = jread(fd, "rindex", buffer,
- sizeof(struct gfs_rindex), offset);
- struct rglist_entry *rgl;
-
- if (len != sizeof(struct gfs_rindex)) {
- if (len == 0)
- return 1;
- fprintf(stderr, "Erk! Read odd size from rindex (%d)\n", len);
- exit(EXIT_FAILURE);
- }
- if ((rgl = malloc(sizeof(struct rglist_entry))) == NULL) {
- perror("rglist_entry");
- exit(EXIT_FAILURE);
- }
- memset(rgl, 0, sizeof(struct rglist_entry));
- gfs_rindex_in(&rgl->ri, buffer);
- osi_list_add(&rgl->list, &rglist_current);
- return 0;
-}
-
-/**
- * read_rgrps - Reads the contents of the rindex file
- * @fs_fd: An fd for any file or directory within the mounted GFS filesytem
- *
- */
-
-static void
-read_rgrps(int fs_fd)
-{
- uint64_t offset = 0;
- while (get_rgrp(fs_fd, &offset) == 0)
- /* do nothing */;
-}
-
-/**
- * write_a_block - Write a block to the current device
- * @where: The position to write the block (in filesystem blocks)
- * @rg: The (optional) resource group to write
- *
- * Writes a single disk block to the device. It has a safety check which
- * prevents it writing to the device at a position within the control of
- * the active filesystem. If @rg is NULL, it writes a single block of
- * zeros with a meta_header, otherwise the resource group is copied
- * into the start of the block.
- */
-
-static void
-write_a_block(int fd, struct gfs_rgrp *rg)
-{
- char buffer[4096];
-
- memset(buffer, 0, fs_sb.sb_bsize);
- if (rg)
- gfs_rgrp_out(rg, buffer);
- else {
- struct gfs_meta_header mh;
-
- mh.mh_magic = GFS_MAGIC;
- mh.mh_type = GFS_METATYPE_RB;
- mh.mh_format = GFS_FORMAT_RB;
- gfs_meta_header_out(&mh, buffer);
- }
- if (write(fd, buffer, fs_sb.sb_bsize) != fs_sb.sb_bsize) {
- perror("write_zero_block");
- exit(EXIT_FAILURE);
- }
-}
-
-/**
- * write_whole_rgrp - Write a complete rgrp, including bitmaps
- * @rgl: The information about the resource group
- *
- * Writes a complete rgrp, including any bitmap blocks required
- * by calling write_a_block() a number of times. Calls sync() to
- * ensure data really reached disk.
- */
-
-static void
-write_whole_rgrp(int fd, struct rglist_entry *rgl)
-{
- uint32_t l;
- uint32_t nzb = rgl->ri.ri_length;
- uint64_t fsoffset = rgl->ri.ri_addr * (uint64_t) fs_sb.sb_bsize;
-
- if (fsoffset < fssize) {
- fprintf(stderr,
- "Sanity check failed: Caught trying to write to live filesystem!\n");
- exit(EXIT_FAILURE);
- }
- if (lseek(fd, fsoffset, SEEK_SET) != fsoffset) {
- perror(device);
- exit(EXIT_FAILURE);
- }
- write_a_block(fd, &rgl->rg);
- for (l = 1; l < nzb; l++)
- write_a_block(fd, NULL);
-}
-
-/**
- * get_length - Use stat() to get the length of a file
- * @fd: The fd of the file whose length we wish to know
- *
- * Returns: The length
- */
-
-static uint64_t
-get_length(int fd, const char *file)
-{
- struct gfs_ioctl gi;
- char *argv[] = {
- (char *)"get_hfile_stat",
- (char *)file
- };
- struct gfs_dinode di;
- int error;
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&di;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size) {
- perror("stat");
- fprintf(stderr, "Failed to get size of file. Aborting.\n");
- exit(EXIT_FAILURE);
- }
-
- return di.di_size;
-}
-
-/**
- * write_rindex - Writes new records to the end of the rindex file
- * @fs_fd: A fd of any file or directory withint the GFS filesystem
- *
- * This is the critical function in expanding a filesystem. It does the
- * actual write to the rindex which causes the GFS filesystem to see the
- * new resource groups which were previously added.
- */
-
-static void
-write_rindex(int fs_fd)
-{
- osi_list_t *tmp, *head;
- struct rglist_entry *rgl;
- char *buffer;
- int b, data_per_blk, data_per_page, firstblock;
- int chunks_this_page, page_freebytes, data_this_page;
- long page_size;
- uint64_t offset, size;
-
- page_size = sysconf(_SC_PAGESIZE);
- buffer = malloc(page_size * 2);
- if (!buffer) {
- fprintf(stderr, "Error: out of memory.\n");
- exit(EXIT_FAILURE);
- }
- offset = get_length(fs_fd, "rindex");
-
- /*
- * This is the critical section.
- * If things mess up here, it could be very difficult to put right
- */
- tmp = head = &rglist_new;
- firstblock = 1;
- data_per_blk = fs_sb.sb_bsize - sizeof(struct gfs_meta_header);
- data_per_page = (page_size / fs_sb.sb_bsize) * data_per_blk;
- for (;;) {
- size = 0;
- /* We used to write new rindex entries out one by one.
- However, that can be very slow, especially if there's a
- load on the file system. That's because each write is
- done with the glock sync option and the journal will need
- to be synced before the glock is freed up for the next
- write. (The rindex file is journaled data). If the block
- size matches the page size, the syncs happen much faster.
- If the block size is smaller, it takes a huge amount of
- time to get all the blocks to settle within the page.
-
- What I'm trying to do here is optimize our writes so
- that multiple blocks may be allocated during a single
- write request, all under the same glock, in order to
- get a page-full of data written. This makes the syncing
- go much faster. The exception is the very first write
- (see note below). */
- data_this_page = offset % data_per_page;
- page_freebytes = page_size - data_this_page;
- if (page_freebytes < sizeof(struct gfs_rindex))
- page_freebytes = data_per_page;
- chunks_this_page = (page_freebytes /
- sizeof(struct gfs_rindex)) + 1;
- for (b = 0; b < chunks_this_page; b++) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- rgl = osi_list_entry(tmp, struct rglist_entry, list);
- gfs_rindex_out(&rgl->ri, buffer + size);
- size += sizeof(struct gfs_rindex);
- /* Write the first block on its own. This minimizes
- the chance of running out of blocks on a nearly
- full file system. Once that first block is written,
- the file system should have more free blocks to
- allocate in chunks. */
- if (firstblock) {
- firstblock = 0;
- break;
- }
- }
- if (size &&
- jwrite(fs_fd, "rindex", buffer, size, &offset) != size) {
- perror("write: rindex");
- fprintf(stderr, "Aborting...\n");
- exit(EXIT_FAILURE);
- }
- if (tmp == head)
- break;
- }
- /*
- * This is the end of the critical section
- */
- free(buffer);
-}
-
-/**
- * write_rgrps - Write the new resource groups to disk
- * @fs_fd: An fd from any file or directory on the GFS mounted filesystem
- *
- * This first writes out the new resource group information to the
- * area of the disk beyond the area the filesystem is currently
- * using and then calls write_rindex() to make the filesystem see
- * the newly written resource groups.
- */
-
-static void
-write_rgrps(int fs_fd)
-{
- osi_list_t *tmp, *head;
- struct rglist_entry *rgl;
- int fd = open(device, O_RDWR);
-
- if (fd < 0) {
- perror(device);
- exit(EXIT_FAILURE);
- }
- tmp = head = &rglist_new;
- for (;;) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- rgl = osi_list_entry(tmp, struct rglist_entry, list);
- write_whole_rgrp(fd, rgl);
- }
- sync();
- close(fd);
-
- sync();
- sync();
- sync();
-
- write_rindex(fs_fd);
-
- sync();
- sync();
- sync();
-}
-
-/**
- * gather_info - Gathers all the information about the existing filesystem
- *
- */
-
-static void
-gather_info(void)
-{
- int fd;
- struct gfs_ioctl gi;
- char *argv[] = { (char *)"get_super" };
- int error;
-
- fd = open(fspath, O_RDONLY);
- if (fd < 0) {
- perror(fspath);
- exit(EXIT_FAILURE);
- }
-
- gi.gi_argc = 1;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&fs_sb;
- gi.gi_size = sizeof(struct gfs_sb);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size) {
- perror("ioctl: GFS_GET_SUPER");
- exit(EXIT_FAILURE);
- }
-
- read_rgrps(fd);
- read_journals(fd);
- close(fd);
- devsize = device_geometry(device);
- fssize = filesystem_size();
-}
-
-/**
- * print_rgrps - Print information about resource groups
- * @lh: The list of resource groups to print
- *
- */
-
-static void
-print_rgrps(osi_list_t *lh)
-{
- osi_list_t *tmp, *head;
- struct rglist_entry *rgl;
- int n = 0;
-
- tmp = head = lh;
- for (;;) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- rgl = osi_list_entry(tmp, struct rglist_entry, list);
- n++;
- printf("RI: Addr %"PRIu64", RgLen %u, Start %"PRIu64", DataLen %u, BmapLen %u\n",
- rgl->ri.ri_addr, rgl->ri.ri_length,
- rgl->ri.ri_data1, rgl->ri.ri_data, rgl->ri.ri_bitbytes);
- }
- printf("RGRP: %d Resource groups in total\n", n);
-}
-
-/**
- * print_journals - Print a list of journals
- *
- */
-
-static void
-print_journals(osi_list_t *lh)
-{
- osi_list_t *tmp, *head;
- struct jilist_entry *jil;
- int n = 0;
-
- tmp = head = lh;
- for (;;) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- jil = osi_list_entry(tmp, struct jilist_entry, list);
- n++;
- printf("JI: Addr %"PRIu64" NumSeg %u SegSize %u\n",
- jil->ji.ji_addr, jil->ji.ji_nsegment, fs_sb.sb_seg_size);
- }
- printf("JRNL: %d Journals in total\n", n);
-}
-
-/**
- * print_info - Print out various bits of (interesting?) information
- *
- */
-
-static void
-print_info(void)
-{
- printf("FS: Mount Point: %s\n", fspath);
- printf("FS: Device: %s\n", device);
- printf("FS: Options: %s\n", fsoptions);
- printf("FS: Size: %"PRIu64"\n", fssize);
- if (verbose > 1) {
- printf("RGRP: Current Resource Group List:\n");
- print_rgrps(&rglist_current);
- printf("JRNL: Current Journal List:\n");
- print_journals(&jilist_current);
- }
- printf("DEV: Size: %"PRIu64"\n", devsize);
- if (verbose > 1) {
- printf("RGRP: New Resource Group List:\n");
- print_rgrps(&rglist_new);
- }
-}
-
-#define RGRP_STUFFED_BLKS(sb) (((sb)->sb_bsize - sizeof(struct gfs_rgrp)) * GFS_NBBY)
-#define RGRP_BITMAP_BLKS(sb) (((sb)->sb_bsize - sizeof(struct gfs_meta_header)) * GFS_NBBY)
-
-/**
- * rgrp_length - Calculate the length of a resource group
- * @size: The total size of the resource group
- *
- */
-
-static uint64_t
-rgrp_length(uint64_t size)
-{
- uint64_t bitbytes = RGRP_BITMAP_BLKS(&fs_sb) + 1;
- uint64_t stuff = RGRP_STUFFED_BLKS(&fs_sb) + 1;
- uint64_t blocks = 1;
-
- if (size < stuff)
- goto out;
- size -= stuff;
- while (size > bitbytes) {
- blocks++;
- size -= bitbytes;
- }
- if (size)
- blocks++;
- out:
- return blocks;
-}
-
-/**
- * make_rgrp - Make a new rglist_entry
- * @offset: The offset at which the new rgrp will go
- * @size: The size of the new rgrp
- *
- * Returns: The end of the new resource group
- */
-
-static uint64_t
-make_rgrp(uint64_t offset, uint64_t size)
-{
- struct rglist_entry *rgl = malloc(sizeof(struct rglist_entry));
- if (rgl == NULL)
- exit(EXIT_FAILURE);
- memset(rgl, 0, sizeof(struct rglist_entry));
-
- rgl->ri.ri_addr = offset;
- rgl->ri.ri_length = rgrp_length(size);
- rgl->ri.ri_data1 = offset + rgl->ri.ri_length;
- rgl->ri.ri_data = size - rgl->ri.ri_length;
-
- /* Round down to nearest multiple of GFS_NBBY */
- while (rgl->ri.ri_data & 0x03)
- rgl->ri.ri_data--;
-
- rgl->ri.ri_bitbytes = rgl->ri.ri_data / GFS_NBBY;
-
- rgl->rg.rg_header.mh_magic = GFS_MAGIC;
- rgl->rg.rg_header.mh_type = GFS_METATYPE_RG;
- rgl->rg.rg_header.mh_format = GFS_FORMAT_RG;
- rgl->rg.rg_free = rgl->ri.ri_data;
-
- osi_list_add_prev(&rgl->list, &rglist_new);
- return offset + size;
-}
-
-/**
- * create_rgrps - Create a list of the new rgrps
- *
- */
-
-static void
-create_rgrps(void)
-{
- uint64_t space = devsize - fssize;
- uint64_t optimal_rgrp_size = RGRP_STUFFED_BLKS(&fs_sb) +
- 14 * RGRP_BITMAP_BLKS(&fs_sb) + 15;
- uint64_t rgrps = space / optimal_rgrp_size;
- uint64_t offset = fssize;
- uint64_t rgsize;
- uint64_t n;
-
- if (space % optimal_rgrp_size)
- rgrps++;
- rgsize = optimal_rgrp_size;
-
- for (n = 0; n < rgrps; n++)
- offset = make_rgrp(offset, (n != 0) ? rgsize :
- (space - ((rgrps - 1) * rgsize)));
-
- if (offset > devsize) {
- fprintf(stderr, "Calculation error: Out of bounds\n");
- exit(EXIT_FAILURE);
- }
-}
-
-/**
- * update_fs - Actually perform the filesystem update
- *
- */
-
-static void
-update_fs(void)
-{
- int fd = open(fspath, O_RDONLY);
- if (fd < 0) {
- perror(fspath);
- exit(EXIT_FAILURE);
- }
- if (verbose)
- printf("Preparing to write new FS information...\n");
- write_rgrps(fd);
- if (verbose)
- printf("Done.\n");
- close(fd);
-}
-
-/**
- * find_fs - Find the filesystem which the user specified
- * @name: The name of a device or mount point
- *
- * Returns: 0 if the filesystem is located, 1 otherwise
- */
-
-static int
-find_fs(const char *name)
-{
- FILE *fp = fopen("/proc/mounts", "r");
- char buffer[4096];
- char fstype[80];
- int fsdump, fspass;
- char *realname;
-
- realname = realpath(name, NULL);
- if (!realname) {
- perror(name);
- return -1;
- }
- if (fp == NULL) {
- perror("open: /proc/mounts");
- exit(EXIT_FAILURE);
- }
- while ((fgets(buffer, 4095, fp)) != NULL) {
- buffer[4095] = 0;
- if (strstr(buffer, realname) == 0)
- continue;
- if (sscanf(buffer, "%s %s %s %s %d %d", device, fspath, fstype,
- fsoptions, &fsdump, &fspass) != 6)
- continue;
- if (strcmp(fstype, "gfs") != 0)
- continue;
- if ((strcmp(device, realname) != 0) &&
- (strcmp(fspath, realname) != 0))
- continue;
- fclose(fp);
- free(realname);
- return 0;
- }
- fprintf(stderr, "GFS Filesystem %s not found\n", name);
- fclose(fp);
- free(realname);
- return 1;
-}
-
-/**
- * delete_rgrp_list - Delete a list of rgrps
- * @list: The list to delete
- *
- */
-
-static void
-delete_rgrp_list(osi_list_t *list)
-{
- struct rglist_entry *rg;
-
- while (!osi_list_empty(list)) {
- rg = osi_list_entry(list->next, struct rglist_entry, list);
- osi_list_del(&rg->list);
- free(rg);
- }
-}
-
-/**
- * delete_jrnl_list - Delete a list of journals
- * @list: the list to delete
- *
- */
-
-static void
-delete_jrnl_list(osi_list_t *list)
-{
- struct jilist_entry *ji;
-
- while (!osi_list_empty(list)) {
- ji = osi_list_entry(list->next, struct jilist_entry, list);
- osi_list_del(&ji->list);
- free(ji);
- }
-}
-
-/**
- * usage - Print out the usage message
- *
- * This function does not include documentation for the -D option
- * since normal users have no use for it at all. The -D option is
- * only for developers. It intended use is in combination with the
- * -T flag to find out what the result would be of trying different
- * device sizes without actually having to try them manually.
- */
-
-static void
-usage(void)
-{
- fprintf(stdout,
- "Usage:\n"
- "\n"
- "gfs_grow [options] /path/to/filesystem\n"
- "\n"
- "Options:\n"
- " -h Usage information\n"
- " -q Quiet, reduce verbosity\n"
- " -T Test, do everything except update FS\n"
- " -V Version information\n"
- " -v Verbose, increase verbosity\n");
-}
-
-/**
- * main - Tha main function
- * @argc: The argument count
- * @argv: The argument vector
- *
- * Runs through the filesystem expansion code for each of the specified
- * filesystems. Each filesystem specified on the command line has the
- * same options applied to it. You'll need to run the program multiple times
- * if you want to use it on several different filesystems with different
- * options for each. If you forget to specify a filesystem, then it is
- * assumed that the program has run successfully, since its done everything
- * asked of it, and it exits without printing a message.
- *
- * Returns: 0 on success, -1 otherwise
- */
-
-int
-main(int argc, char *argv[])
-{
- int opt;
- int error = 0;
-
- while ((opt = getopt(argc, argv, "VD:hqTv?")) != EOF) {
- switch (opt) {
- case 'D': /* This option is for testing only */
- override_device_size = atoi(optarg);
- override_device_size <<= 20;
- break;
- case 'V':
- printf("%s %s (built %s %s)\n", argv[0],
- RELEASE_VERSION, __DATE__, __TIME__);
- printf("%s\n", REDHAT_COPYRIGHT);
- exit(0);
- case 'h':
- usage();
- exit(0);
- case 'q':
- if (verbose)
- verbose--;
- break;
- case 'T':
- test = 1;
- break;
- case 'v':
- verbose++;
- break;
- case ':':
- case '?':
- /* Unknown flag */
- fprintf(stderr, "Please use '-h' for usage.\n");
- exit(EXIT_FAILURE);
- default:
- fprintf(stderr, "Bad programmer! You forgot"
- " to catch the %c flag\n", opt);
- exit(EXIT_FAILURE);
- break;
- }
- }
-
- if (optind == argc) {
- usage();
- exit(EXIT_FAILURE);
- }
-
- while ((argc - optind) > 0) {
- if (find_fs(argv[optind++])) {
- error = 1;
- continue;
- }
- gather_info();
- if (fssize > devsize) {
- error = 1;
- fprintf(stderr,
- "Filesystem thinks device is bigger than it really is.... skipping\n");
- continue;
- }
- if ((devsize - fssize) < 100) {
- error = 1;
- fprintf(stderr,
- "Device has grown by less than 100 blocks.... skipping\n");
- continue;
- }
- create_rgrps();
- if (verbose)
- print_info();
- if (!test)
- update_fs();
- delete_rgrp_list(&rglist_current);
- delete_rgrp_list(&rglist_new);
- delete_jrnl_list(&jilist_current);
- }
-
- return error;
-}
diff --git a/gfs/gfs_grow/ondisk.c b/gfs/gfs_grow/ondisk.c
deleted file mode 100644
index 191c688..0000000
--- a/gfs/gfs_grow/ondisk.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "linux_endian.h"
-#include "gfs_ondisk.h"
-
-#define printk printf
-#define pv(struct, member, fmt) printf(" "#member" = "fmt"\n", struct->member);
-
-#define ENTER(x)
-#define EXIT(x)
-#define RET(x) return
-#define RETURN(x, y) return y
-
-#define WANT_GFS_CONVERSION_FUNCTIONS
-#include "gfs_ondisk.h"
diff --git a/gfs/gfs_jadd/Makefile b/gfs/gfs_jadd/Makefile
deleted file mode 100644
index 0d41942..0000000
--- a/gfs/gfs_jadd/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-TARGET= gfs_jadd
-
-SBINDIRT=$(TARGET)
-
-all: depends ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= main.o \
- ondisk.o
-
-CFLAGS += -DHELPER_PROGRAM -D_FILE_OFFSET_BITS=64
-CFLAGS += -I${gfskincdir}
-CFLAGS += -I$(S)/../include -I$(S)/../libgfs
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L../libgfs -lgfs
-LDFLAGS += -L${libdir}
-
-LDDEPS += ../libgfs/libgfs.a
-
-${TARGET}: ${OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-depends:
- $(MAKE) -C ../libgfs all
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs/gfs_jadd/main.c b/gfs/gfs_jadd/main.c
deleted file mode 100644
index 5f0affd..0000000
--- a/gfs/gfs_jadd/main.c
+++ /dev/null
@@ -1,928 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <sys/ioctl.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "gfs_ondisk.h"
-#define __user
-#include "gfs_ioctl.h"
-#include "osi_list.h"
-#include "libgfs.h"
-
-#include "copyright.cf"
-
-#define BLOCK_END(buffer, type) ((buffer) + GFS_BASIC_BLOCK - sizeof(type))
-
-struct rglist_entry {
- osi_list_t list;
- struct gfs_rindex ri;
- struct gfs_rgrp rg;
-};
-
-struct jilist_entry {
- osi_list_t list;
- struct gfs_jindex ji;
-};
-
-/*
- * verbose: 0 = no messages, 1 = normal, 2 = everything
- * test: 0 = normal, 1 = don't actually write data, but do everything else
- * fspath: path to root of mounted GFS filesystem
- * device: the device upon which the GFS filesystem is mounted
- * fsoptions: the mount options used
- * devsize: the size of the device (in filesystem blocks, rounded down)
- * fssize: the size of the filesystem (in filesystem blocks, rounded down)
- * override_device_size: if non-zero, this is used for the device size
- * number_of_journals: Number of journals to add to each fs
- * journal_size: The size of each journal, in MB
- * journal_size_blocks: The size of each journal in fs blocks
- */
-static int verbose = 1;
-static int test = 0;
-static char fspath[4096];
-static char device[1024];
-static char fsoptions[4096];
-static uint64_t devsize;
-static uint64_t fssize;
-static uint64_t override_device_size = 0;
-static unsigned int number_of_journals = 1;
-static uint64_t journal_size = 128;
-static uint64_t journal_size_blocks;
-
-/*
- * fs_sb: the superblock read from the mounted filesystem
- * rglist_current: list of resource groups currently making up the filesystem
- * jilist_current: list of current journals in the filesystem
- * jilist_new: where we put the new resource groups to be written
- */
-static struct gfs_sb fs_sb;
-static osi_list_decl(rglist_current);
-static osi_list_decl(jilist_current);
-static osi_list_decl(jilist_new);
-
-/**
- * device_geometry - Find out the size of a block device
- * @device: The name of the device
- *
- * Returns: The size of the device in FS blocks
- */
-
-static uint64_t
-device_geometry(char *device_g)
-{
- int fd;
- uint64_t bytes;
- int error;
-
- if (override_device_size)
- bytes = override_device_size;
- else {
- fd = open(device_g, O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "gfs_jadd: can't open %s: %s\n",
- device_g, strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- error = device_size(fd, &bytes);
- if (error) {
- fprintf(stderr,
- "gfs_grow: can't determine size of %s: %s\n",
- device_g, strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- close(fd);
- }
-
- return bytes >> fs_sb.sb_bsize_shift;
-}
-
-/**
- * jread - Read from journaled file using ioctl()
- * @fd: The fd to read from
- * @file: The file to read
- * @buf: The buffer to fill
- * @size: The amount of data to read
- * @offset: The offset to read from
- *
- * Returns: Error code, or amount of data read
- */
-
-static int
-jread(int fd, const char *file, void *buf, uint64_t size, uint64_t *offset)
-{
- struct gfs_ioctl gi;
- char *argv[] = {
- (char *)"do_hfile_read",
- (char *)file
- };
- int error;
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = buf;
- gi.gi_size = size;
- gi.gi_offset = *offset;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error > 0)
- *offset += error;
-
- return error;
-}
-
-/**
- * jwrite - Write to journaled file using ioctl()
- * @fd: The fd to write to
- * @file: The file to write
- * @buf: The buffer to write
- * @size: The amount of data to write
- * @offset: The offset at which to write the data
- *
- * Returns: Error code, or the amount of data written
- */
-
-static int
-jwrite(int fd, const char *file, void *buf, uint64_t size, uint64_t *offset)
-{
- struct gfs_ioctl gi;
- char *argv[] = {
- (char *)"do_hfile_write",
- (char *)file
- };
- int error;
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = buf;
- gi.gi_size = size;
- gi.gi_offset = *offset;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error > 0)
- *offset += error;
-
- return error;
-}
-
-/**
- * filesystem_size - Calculate the size of the filesystem
- *
- * Reads the lists of journals and resource groups in order to
- * work out where the last block of the filesystem is located.
- *
- * Returns: The calculated size
- */
-
-static uint64_t
-filesystem_size(void)
-{
- osi_list_t *tmp, *head;
- struct rglist_entry *rgl;
- struct jilist_entry *jil;
- uint64_t size = 0;
- uint64_t extent;
-
- tmp = head = &rglist_current;
- for (;;) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- rgl = osi_list_entry(tmp, struct rglist_entry, list);
- extent = rgl->ri.ri_addr + rgl->ri.ri_length + rgl->ri.ri_data;
- if (extent > size)
- size = extent;
- }
-
- tmp = head = &jilist_current;
- for (;;) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- jil = osi_list_entry(tmp, struct jilist_entry, list);
- extent = jil->ji.ji_addr + jil->ji.ji_nsegment * fs_sb.sb_seg_size;
- if (extent > size)
- size = extent;
- }
-
- return size;
-}
-
-/**
- * gfs_jientry - Get journal index entry
- * @fd: The fd of the journal index
- * @offset: The offset at which the journal entry appears
- *
- * Reads a single entry from the journal index file and
- * adds it to the list of current journal entries.
- *
- * Returns: 1 on EOF, 0 otherwise
- */
-
-static int
-get_jientry(int fd, uint64_t *offset)
-{
- char buffer[sizeof(struct gfs_jindex)];
- int len = jread(fd, "jindex", buffer,
- sizeof(struct gfs_jindex), offset);
- struct jilist_entry *jil;
-
- if (len != sizeof(struct gfs_jindex)) {
- if (len == 0)
- return 1;
- fprintf(stderr, "Erk! Read odd size from jindex (%d)\n", len);
- exit(EXIT_FAILURE);
- }
- if ((jil = malloc(sizeof(struct jilist_entry))) == NULL) {
- perror("jilist_entry");
- exit(EXIT_FAILURE);
- }
- memset(jil, 0, sizeof(struct jilist_entry));
- gfs_jindex_in(&jil->ji, buffer);
- osi_list_add(&jil->list, &jilist_current);
- return 0;
-}
-
-/**
- * read_journals - Read the whole journal index
- * @fs_fd: An fd for some file or directory within the mounted GFS filesystem
- *
- */
-
-static void
-read_journals(int fs_fd)
-{
- uint64_t offset = 0;
- while (get_jientry(fs_fd, &offset) == 0)
- /* do nothing */;
-}
-
-/**
- * get_rgrp - Read a single rindex entry
- * @fd: The fd for the rindex file
- * @offset: The offset at which to read the rindex entry
- *
- * Reads a single rindex entry and adds it to the list of current
- * resource group entries.
- *
- * Returns: 1 on EOF, 0 otherwise
- */
-
-static int
-get_rgrp(int fd, uint64_t *offset)
-{
- char buffer[sizeof(struct gfs_rindex)];
- int len = jread(fd, "rindex", buffer,
- sizeof(struct gfs_rindex), offset);
- struct rglist_entry *rgl;
-
- if (len != sizeof(struct gfs_rindex)) {
- if (len == 0)
- return 1;
- fprintf(stderr, "Erk! Read odd size from rindex (%d)\n", len);
- exit(EXIT_FAILURE);
- }
- if ((rgl = malloc(sizeof(struct rglist_entry))) == NULL) {
- perror("rglist_entry");
- exit(EXIT_FAILURE);
- }
- memset(rgl, 0, sizeof(struct rglist_entry));
- gfs_rindex_in(&rgl->ri, buffer);
- osi_list_add(&rgl->list, &rglist_current);
- return 0;
-}
-
-/**
- * read_rgrps - Reads the contents of the rindex file
- * @fs_fd: An fd for any file or directory within the mounted GFS filesytem
- *
- */
-
-static void
-read_rgrps(int fs_fd)
-{
- uint64_t offset = 0;
- while (get_rgrp(fs_fd, &offset) == 0)
- /* do nothing */;
-}
-
-/**
- * write_a_block - Write a block to the current device
- * @where: The position to write the block (in filesystem blocks)
- *
- * Writes a single disk block to the device. It has a safety check which
- * prevents it writing to the device at a position within the control of
- * the active filesystem.
- */
-
-static void
-write_a_block(uint64_t where, uint64_t seq)
-{
- char buffer[4096];
- uint64_t fsoffset = where * (uint64_t) fs_sb.sb_bsize;
- int fd = open(device, O_RDWR);
- struct gfs_log_header lh;
-
- memset(&lh, 0, sizeof(struct gfs_log_header));
-
- lh.lh_header.mh_magic = GFS_MAGIC;
- lh.lh_header.mh_type = GFS_METATYPE_LH;
- lh.lh_header.mh_format = GFS_FORMAT_LH;
- lh.lh_flags = GFS_LOG_HEAD_UNMOUNT;
- lh.lh_first = where;
- lh.lh_sequence = seq;
-
- if (fd < 0) {
- perror(device);
- exit(EXIT_FAILURE);
- }
- if (where < fssize) {
- fprintf(stderr,
- "Sanity check failed: Caught trying to write to live filesystem!\n");
- exit(EXIT_FAILURE);
- }
-
- memset(buffer, 0, 4096);
- gfs_log_header_out(&lh, buffer);
- gfs_log_header_out(&lh, BLOCK_END(buffer, struct gfs_log_header));
-
- if (lseek(fd, fsoffset, SEEK_SET) != fsoffset) {
- perror(device);
- exit(EXIT_FAILURE);
- }
- if (write(fd, buffer, fs_sb.sb_bsize) != fs_sb.sb_bsize) {
- perror("write_a_block");
- exit(EXIT_FAILURE);
- }
- close(fd);
-}
-
-/**
- * write_whole_journal - Write a complete journal to the disk
- * @jil: The information about the journal
- *
- * Write a complete new journal on disk.
- */
-
-static void
-write_whole_journal(struct jilist_entry *jil)
-{
- uint64_t seg;
- uint64_t offset;
-
- for (seg = 0; seg < jil->ji.ji_nsegment; seg++) {
- offset = seg * fs_sb.sb_seg_size;
- write_a_block(jil->ji.ji_addr + offset, offset);
- }
-
- sync();
-}
-
-/**
- * get_length - Use stat() to get the length of a file
- * @fd: The fd of the file whose length we wish to know
- *
- * Returns: The length
- */
-
-static uint64_t
-get_length(int fd, const char *file)
-{
- struct gfs_ioctl gi;
- char *argv[] = {
- (char *)"get_hfile_stat",
- (char *)file
- };
- struct gfs_dinode di;
- int error;
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&di;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size) {
- perror("stat");
- fprintf(stderr, "Failed to get size of file. Aborting.\n");
- exit(EXIT_FAILURE);
- }
-
- return di.di_size;
-}
-
-/**
- * write_jindex - Writes new records to the end of the jindex file
- * @fs_fd: A fd of any file or directory withint the GFS filesystem
- *
- * This is the critical function in adding journals. It does the
- * actual write to the jindex which causes the GFS filesystem to see the
- * new journals which were previously added.
- */
-
-static void
-write_jindex(int fs_fd)
-{
- osi_list_t *tmp, *head;
- struct jilist_entry *jil;
- char buffer[sizeof(struct gfs_jindex)];
- uint64_t offset;
-
- offset = get_length(fs_fd, "jindex");
-
- /*
- * This is the critical section.
- * If things mess up here, it could be very difficult to put right
- */
- tmp = head = &jilist_new;
- for (;;) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- jil = osi_list_entry(tmp, struct jilist_entry, list);
- gfs_jindex_out(&jil->ji, buffer);
- if (jwrite(fs_fd, "jindex", buffer,
- sizeof(struct gfs_jindex), &offset) !=
- sizeof(struct gfs_jindex)) {
- perror("write: jindex");
- fprintf(stderr, "Aborting...\n");
- exit(EXIT_FAILURE);
- }
- }
- /*
- * This is the end of the critical section
- */
-}
-
-/**
- * write_journals - Write the new journals to disk
- * @fs_fd: An fd from any file or directory on the GFS mounted filesystem
- *
- * This first writes out the new journal information to the
- * area of the disk beyond the area the filesystem is currently
- * using and then calls write_jindex() to make the filesystem see
- * the newly written journal.
- */
-
-static void
-write_journals(int fs_fd)
-{
- osi_list_t *tmp, *head;
- struct jilist_entry *jil;
-
- tmp = head = &jilist_new;
- for (;;) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- jil = osi_list_entry(tmp, struct jilist_entry, list);
- write_whole_journal(jil);
- }
-
- sync();
- sync();
- sync();
-
- write_jindex(fs_fd);
-
- sync();
- sync();
- sync();
-}
-
-/**
- * gather_info - Gathers all the information about the existing filesystem
- *
- */
-
-static void
-gather_info(void)
-{
- int fd;
- struct gfs_ioctl gi;
- char *argv[] = {
- (char *)"get_super"
- };
- int error;
-
- fd = open(fspath, O_RDONLY);
- if (fd < 0) {
- perror(fspath);
- exit(EXIT_FAILURE);
- }
-
- gi.gi_argc = 1;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&fs_sb;
- gi.gi_size = sizeof(struct gfs_sb);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size) {
- perror("ioctl: GFS_GET_SUPER");
- exit(EXIT_FAILURE);
- }
-
- read_rgrps(fd);
- read_journals(fd);
- close(fd);
- devsize = device_geometry(device);
- fssize = filesystem_size();
-
- journal_size_blocks = journal_size << (20 - fs_sb.sb_bsize_shift);
- /*
- * Round size down to integer number of segments
- */
- while (journal_size_blocks % fs_sb.sb_seg_size) {
- journal_size_blocks--;
- journal_size -= fs_sb.sb_bsize;
- }
-}
-
-/**
- * print_rgrps - Print information about resource groups
- * @lh: The list of resource groups to print
- *
- */
-
-static void
-print_rgrps(osi_list_t *lh)
-{
- osi_list_t *tmp, *head;
- struct rglist_entry *rgl;
- int n = 0;
-
- tmp = head = lh;
- for (;;) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- rgl = osi_list_entry(tmp, struct rglist_entry, list);
- n++;
- printf("RI: Addr %"PRIu64", RgLen %u, Start %"PRIu64", DataLen %u, BmapLen %u\n",
- rgl->ri.ri_addr, rgl->ri.ri_length,
- rgl->ri.ri_data1, rgl->ri.ri_data, rgl->ri.ri_bitbytes);
- }
- printf("RGRP: %d Resource groups in total\n", n);
-}
-
-/**
- * print_journals - Print a list of journals
- *
- */
-
-static void
-print_journals(osi_list_t *lh)
-{
- osi_list_t *tmp, *head;
- struct jilist_entry *jil;
- int n = 0;
-
- tmp = head = lh;
- for (;;) {
- tmp = tmp->next;
- if (tmp == head)
- break;
- jil = osi_list_entry(tmp, struct jilist_entry, list);
- n++;
- printf("JI: Addr %"PRIu64" NumSeg %u SegSize %u\n",
- jil->ji.ji_addr, jil->ji.ji_nsegment, fs_sb.sb_seg_size);
- }
- printf("JRNL: %d Journals in total\n", n);
-}
-
-/**
- * print_info - Print out various bits of (interesting?) information
- *
- */
-
-static void
-print_info(void)
-{
- printf("FS: Mount Point: %s\n", fspath);
- printf("FS: Device: %s\n", device);
- printf("FS: Options: %s\n", fsoptions);
- printf("FS: Size: %"PRIu64"\n", fssize);
- if (verbose > 1) {
- printf("RGRP: Current Resource Group List:\n");
- print_rgrps(&rglist_current);
- printf("JRNL: Current Journal List:\n");
- print_journals(&jilist_current);
- }
- printf("DEV: Size: %"PRIu64"\n", devsize);
- if (verbose > 1) {
- printf("JRNL: New Journal List:\n");
- print_journals(&jilist_new);
- }
-}
-
-/**
- * make_journal - Make a new jilist_entry
- * @offset: The offset at which the new journal will go
- * @size: The size of the new journal in fs blocks
- *
- */
-
-static uint64_t
-make_journal(uint64_t offset, uint64_t size)
-{
- struct jilist_entry *jil = malloc(sizeof(struct jilist_entry));
- if (jil == NULL) {
- perror("jilist_entry");
- exit(EXIT_FAILURE);
- }
- memset(jil, 0, sizeof(struct jilist_entry));
-
- if (offset % fs_sb.sb_seg_size) {
- size -= fs_sb.sb_seg_size - (offset % fs_sb.sb_seg_size);
- offset += fs_sb.sb_seg_size - (offset % fs_sb.sb_seg_size);
- }
-
- jil->ji.ji_addr = offset;
- jil->ji.ji_nsegment = size / fs_sb.sb_seg_size;
-
- osi_list_add(&jil->list, &jilist_new);
- return offset + size;
-}
-
-/**
- * create_journals - Create a list of the new journals
- *
- */
-
-static int
-create_journals(void)
-{
- uint64_t offset = fssize;
- int n;
-
- if ((journal_size_blocks * number_of_journals) > (devsize - fssize)) {
- fprintf(stderr,
- "Requested size (%" PRIu64
- " blocks) greater than available space (%" PRIu64
- " blocks)\n", journal_size_blocks * number_of_journals,
- devsize - fssize);
- return -1;
- }
-
- for (n = 0; n < number_of_journals; n++)
- offset = make_journal(offset, journal_size_blocks);
-
- if (offset > devsize) {
- fprintf(stderr, "Calculation error: Out of bounds\n");
- exit(EXIT_FAILURE);
- }
-
- return 0;
-}
-
-/**
- * update_fs - Actually perform the filesystem update
- *
- */
-
-static void
-update_fs(void)
-{
- int fd = open(fspath, O_RDONLY);
- if (fd < 0) {
- perror(fspath);
- exit(EXIT_FAILURE);
- }
- if (verbose)
- printf("Preparing to write new FS information...\n");
- write_journals(fd);
- if (verbose)
- printf("Done.\n");
- close(fd);
-}
-
-/**
- * find_fs - Find the filesystem which the user specified
- * @name: The name of a device or mount point
- *
- * Returns: 0 if the filesystem is located, 1 otherwise
- */
-
-static int
-find_fs(const char *name)
-{
- FILE *fp = fopen("/proc/mounts", "r");
- char buffer[4096];
- char fstype[80];
- int fsdump, fspass;
- char *realname;
-
- realname = realpath(name, NULL);
- if (!realname) {
- perror(name);
- return -1;
- }
- if (fp == NULL) {
- perror("open: /proc/mounts");
- exit(EXIT_FAILURE);
- }
- while ((fgets(buffer, 4095, fp)) != NULL) {
- buffer[4095] = 0;
- if (strstr(buffer, realname) == 0)
- continue;
- if (sscanf(buffer, "%s %s %s %s %d %d", device, fspath, fstype,
- fsoptions, &fsdump, &fspass) != 6)
- continue;
- if (strcmp(fstype, "gfs") != 0)
- continue;
- if ((strcmp(device, realname) != 0) &&
- (strcmp(fspath, realname) != 0))
- continue;
- fclose(fp);
- free(realname);
- return 0;
- }
- fprintf(stderr, "GFS Filesystem %s not found\n", name);
- fclose(fp);
- free(realname);
- return 1;
-}
-
-/**
- * delete_rgrp_list - Delete a list of rgrps
- * @list: The list to delete
- *
- */
-
-static void
-delete_rgrp_list(osi_list_t *list)
-{
- struct rglist_entry *rg;
-
- while (!osi_list_empty(list)) {
- rg = osi_list_entry(list->next, struct rglist_entry, list);
- osi_list_del(&rg->list);
- free(rg);
- }
-}
-
-/**
- * delete_jrnl_list - Delete a list of journals
- * @list: The list to delete
- *
- */
-
-static void
-delete_jrnl_list(osi_list_t *list)
-{
- struct jilist_entry *ji;
-
- while (!osi_list_empty(list)) {
- ji = osi_list_entry(list->next, struct jilist_entry, list);
- osi_list_del(&ji->list);
- free(ji);
- }
-}
-
-/**
- * usage - Print out the usage message
- *
- * This function does not include documentation for the -D option
- * since normal users have no use for it at all. The -D option is
- * only for developers. It intended use is in combination with the
- * -T flag to find out what the result would be of trying different
- * device sizes without actually having to try them manually.
- */
-
-static void
-usage(void)
-{
- fprintf(stdout,
- "Usage:\n"
- "\n"
- "gfs_jadd [options] /path/to/filesystem\n"
- "\n"
- "Options:\n"
- " -h Print this usage information.\n"
- " -J <MB> Size of journals in MB (minimum 32, default 128)\n"
- " -j <num> Number of journals to add (default 1)\n"
- " -q Quiet, reduce verbosity\n"
- " -T Test, do everything except update FS\n"
- " -V Version information\n"
- " -v Verbose, increase verbosity\n");
-}
-
-/**
- * main - Tha main function
- * @argc: The argument count
- * @argv: The argument vector
- *
- * Runs through the filesystem expansion code for each of the specified
- * filesystems. Each filesystem specified on the command line has the
- * same options applied to it. You'll need to run the program multiple times
- * if you want to use it on several different filesystems with different
- * options for each. If you forget to specify a filesystem, then it is
- * assumed that the program has run successfully, since its done everything
- * asked of it, and it exits without printing a message.
- *
- * Returns: 0 on success, -1 otherwise
- */
-
-int
-main(int argc, char *argv[])
-{
- int opt;
- int error = 0;
-
- while ((opt = getopt(argc, argv, "D:Vhj:J:vqT?")) != EOF) {
- switch (opt) {
- case 'D': /* This option is for testing only */
- override_device_size = atoi(optarg);
- override_device_size <<= 20;
- break;
- case 'V':
- printf("%s %s (built %s %s)\n", argv[0],
- RELEASE_VERSION, __DATE__, __TIME__);
- printf("%s\n", REDHAT_COPYRIGHT);
- exit(0);
- case 'h':
- usage();
- exit(0);
- case 'j':
- number_of_journals = atoi(optarg);
- if (number_of_journals < 1) {
- fprintf(stderr,
- "Erk! Number of journals must be 1 or greater.\n");
- usage();
- exit(EXIT_FAILURE);
- }
- break;
- case 'J':
- journal_size = atoi(optarg);
- if (journal_size < 32) {
- fprintf(stderr,
- "Erk! Specified journal size of %"
- PRIu64 " is too small.\n",
- journal_size);
- usage();
- exit(EXIT_FAILURE);
- }
- break;
- case 'q':
- if (verbose)
- verbose--;
- break;
- case 'T':
- test = 1;
- break;
- case 'v':
- verbose++;
- break;
- case ':':
- case '?':
- fprintf(stderr, "Please use '-h' for usage.\n");
- exit(EXIT_FAILURE);
- default:
- fprintf(stderr, "Bad programmer! You forgot"
- " to catch the %c flag\n", opt);
- exit(EXIT_FAILURE);
- break;
- }
- }
-
- if (optind == argc) {
- usage();
- exit(EXIT_FAILURE);
- }
-
- while ((argc - optind) > 0) {
- if (find_fs(argv[optind++])) {
- error = 1;
- continue;
- }
- gather_info();
- if (fssize > devsize) {
- fprintf(stderr,
- "Filesystem thinks device is bigger than it really is.... skipping\n");
- error = 1;
- continue;
- }
- if (create_journals()) {
- error = 1;
- continue;
- }
- if (verbose)
- print_info();
- if (!test)
- update_fs();
- delete_rgrp_list(&rglist_current);
- delete_jrnl_list(&jilist_current);
- delete_jrnl_list(&jilist_new);
- }
-
- return error;
-}
diff --git a/gfs/gfs_jadd/ondisk.c b/gfs/gfs_jadd/ondisk.c
deleted file mode 100644
index 191c688..0000000
--- a/gfs/gfs_jadd/ondisk.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "linux_endian.h"
-#include "gfs_ondisk.h"
-
-#define printk printf
-#define pv(struct, member, fmt) printf(" "#member" = "fmt"\n", struct->member);
-
-#define ENTER(x)
-#define EXIT(x)
-#define RET(x) return
-#define RETURN(x, y) return y
-
-#define WANT_GFS_CONVERSION_FUNCTIONS
-#include "gfs_ondisk.h"
diff --git a/gfs/gfs_mkfs/Makefile b/gfs/gfs_mkfs/Makefile
deleted file mode 100644
index 93f9093..0000000
--- a/gfs/gfs_mkfs/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-TARGET= mkfs.gfs
-
-FORCESBINT= $(TARGET)
-
-all: depends ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= device_geometry.o \
- fs_geometry.o \
- locking.o \
- main.o \
- ondisk.o \
- structures.o
-
-CFLAGS += -DHELPER_PROGRAM -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
-CFLAGS += -I${gfskincdir}
-CFLAGS += -I$(S)/../include -I$(S)/../libgfs
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L../libgfs -lgfs
-LDFLAGS += -L${libdir}
-
-LDDEPS += ../libgfs/libgfs.a
-
-${TARGET}: ${OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-depends:
- $(MAKE) -C ../libgfs all
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs/gfs_mkfs/device_geometry.c b/gfs/gfs_mkfs/device_geometry.c
deleted file mode 100644
index 6152bca..0000000
--- a/gfs/gfs_mkfs/device_geometry.c
+++ /dev/null
@@ -1,153 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <assert.h>
-#include <time.h>
-#include <sys/param.h>
-
-#include "global.h"
-#include "gfs_ondisk.h"
-#include "osi_list.h"
-#include "mkfs_gfs.h"
-#include "libgfs.h"
-
-/**
- * device_geometry - Get the size of a device
- * @comline: the command line
- * @device: the structure the geometry is returned in
- *
- */
-
-void device_geometry(commandline_t *comline, mkfs_device_t *device)
-{
- int fd;
- uint64 bytes;
- int error;
-
- fd = open(comline->device, O_RDONLY | O_CLOEXEC);
- if (fd < 0)
- die("can't open %s: %s\n", comline->device, strerror(errno));
-
- error = device_size(fd, &bytes);
- if (error)
- die("can't determine size of %s: %s\n", comline->device, strerror(errno));
-
- close(fd);
-
- if (comline->debug)
- printf("\nPartition size = %"PRIu64"\n", bytes >> 9);
-
- device->nsubdev = 1;
-
- type_zalloc(device->subdev, mkfs_subdevice_t, 1);
-
- device->subdev->start = 0;
- device->subdev->length = bytes >> 9;
-}
-
-/**
- * add_journals_to_device - carve space out of a mkfs_device_t to add journals
- * @comline: the command line arguments
- * @device: the mkfs_device_t
- *
- */
-
-void add_journals_to_device(commandline_t *comline, mkfs_device_t *device)
-{
- mkfs_subdevice_t *old;
- uint64 jsize;
- unsigned int x;
-
- MKFS_ASSERT(device->nsubdev == 1 &&
- !device->subdev->is_journal, );
-
- if (!comline->journals)
- die("No journals specified (use -j)\n");
-
- if (!comline->jsize)
- die("journal size is zero (use -J)\n");
-
- jsize = comline->jsize * (1 << 20) / GFS_BASIC_BLOCK;
-
- if (comline->journals * jsize > device->subdev->length)
- die("Partition too small for number/size of journals\n");
-
- old = device->subdev;
-
- device->nsubdev = comline->journals + 2;
- type_zalloc(device->subdev, mkfs_subdevice_t, device->nsubdev);
-
- device->subdev[0].start = old->start;
- device->subdev[0].length = (old->length - comline->journals * jsize) / 2;
-
- for (x = 1; x <= comline->journals; x++) {
- device->subdev[x].start = device->subdev[x - 1].start + device->subdev[x - 1].length;
- device->subdev[x].length = jsize;
- device->subdev[x].is_journal = TRUE;
- }
-
- device->subdev[x].start = device->subdev[x - 1].start + device->subdev[x - 1].length;
- device->subdev[x].length = device->subdev[0].length;
-
- free(old);
-}
-
-/**
- * fix_device_geometry - round off address and lengths and convert to FS blocks
- * @comline: the command line
- * @device: the description of the underlying device
- *
- */
-
-void fix_device_geometry(commandline_t *comline, mkfs_device_t *device)
-{
- unsigned int x;
- uint64 offset, len;
- uint32 bbsize = comline->bsize >> 9;
-
- if (comline->debug) {
- printf("\nDevice Geometry: (in basic blocks)\n");
- for (x = 0; x < device->nsubdev; x++)
- printf(" SubDevice #%d: %s: start = %"PRIu64", len = %"PRIu64"\n",
- x,
- (device->subdev[x].is_journal) ? "journal" : "data",
- device->subdev[x].start,
- device->subdev[x].length);
- }
-
- /* Make sure all the subdevices are aligned */
-
- for (x = 0; x < device->nsubdev; x++) {
- offset = device->subdev[x].start;
- len = device->subdev[x].length;
-
- if (len < 100 * bbsize)
- die("subdevice %d is way too small (%"PRIu64" bytes)\n", x, len * GFS_BASIC_BLOCK);
-
- if (offset % bbsize) {
- len -= bbsize - (offset % bbsize);
- offset += bbsize - (offset % bbsize);
- }
-
- device->subdev[x].start = offset / bbsize;
- device->subdev[x].length = len / bbsize;
- }
-
- if (comline->debug) {
- printf("\nDevice Geometry: (in FS blocks)\n");
- for (x = 0; x < device->nsubdev; x++)
- printf(" SubDevice #%d: %s: start = %"PRIu64", len = %"PRIu64"\n",
- x,
- (device->subdev[x].is_journal) ? "journal" : "data",
- device->subdev[x].start,
- device->subdev[x].length);
-
- printf("\njournals = %u\n", comline->journals);
- }
-}
diff --git a/gfs/gfs_mkfs/fs_geometry.c b/gfs/gfs_mkfs/fs_geometry.c
deleted file mode 100644
index dc9857a..0000000
--- a/gfs/gfs_mkfs/fs_geometry.c
+++ /dev/null
@@ -1,180 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <assert.h>
-#include <time.h>
-
-#include "global.h"
-#include "gfs_ondisk.h"
-#include "osi_list.h"
-
-#include "mkfs_gfs.h"
-
-/**
- * how_many_rgrps - figure out how many RG to put in a subdevice
- * @comline: the command line
- * @sdev: the subdevice
- *
- * Returns: the number of RGs
- */
-
-static uint64 how_many_rgrps(commandline_t *comline, mkfs_subdevice_t *sdev)
-{
- uint64 nrgrp;
- unsigned int min = (comline->expert) ? 1 : 4;
-
- while (TRUE) {
- nrgrp = DIV_RU(sdev->length, (comline->rgsize << 20) / comline->bsize);
-
- if (nrgrp < min)
- nrgrp = min;
-
- if (comline->rgsize_specified || /* If user specified an rg size or */
- nrgrp <= MKFS_EXCESSIVE_RGS || /* not an excessive # of rgs or */
- comline->rgsize >= 2048) /* we've reached the max rg size */
- break;
-
- comline->rgsize += MKFS_DEFAULT_RGSIZE; /* Try again w/bigger rgs */
- }
-
- if (comline->debug)
- printf(" rg sz = %"PRIu32"\n nrgrp = %"PRIu64"\n", comline->rgsize,
- nrgrp);
-
- return nrgrp;
-}
-
-/**
- * compute_rgrp_layout - figure out where the RG in a FS are
- * @comline: the command line
- * @device: the device layout
- * @rlist: the list of resource groups
- *
- * Returns: a list of rgrp_list_t structures
- */
-
-void compute_rgrp_layout(commandline_t *comline, mkfs_device_t *device, osi_list_t *rlist)
-{
- mkfs_subdevice_t *sdev;
- rgrp_list_t *rl, *rlast = NULL;
- osi_list_t *tmp;
- uint64 rgrp, nrgrp;
- unsigned int x;
- int first_sdev = TRUE;
-
- for (x = 0; x < device->nsubdev; x++) {
- sdev = &device->subdev[x];
-
- if (!sdev->is_journal) {
- /* If this is the 1st subdevice reserve space for the superblock */
-
- if (first_sdev)
- sdev->length -= comline->sb_addr + 1;
-
- if (comline->debug)
- printf("\nData Subdevice %u\n", x);
-
- nrgrp = how_many_rgrps(comline, sdev);
-
- for (rgrp = 0; rgrp < nrgrp; rgrp++) {
- type_zalloc(rl, rgrp_list_t, 1);
-
- rl->subdevice = x;
-
- if (rgrp) {
- rl->rg_offset = rlast->rg_offset + rlast->rg_length;
- rl->rg_length = sdev->length / nrgrp;
- }
- else {
- rl->rg_offset = sdev->start;
- rl->rg_length = sdev->length - (nrgrp - 1) * (sdev->length / nrgrp);
-
- if (first_sdev)
- rl->rg_offset += comline->sb_addr + 1;
- }
-
- osi_list_add_prev(&rl->list, rlist);
-
- rlast = rl;
- }
-
- first_sdev = FALSE;
-
- comline->rgrps += nrgrp;
- }
- }
-
- if (comline->debug) {
- printf("\n");
-
- for (tmp = rlist->next; tmp != rlist; tmp = tmp->next) {
- rl = osi_list_entry(tmp, rgrp_list_t, list);
- printf("subdevice %u: rg_o = %"PRIu64", rg_l = %"PRIu64" blocks (%"PRIu64"MB)\n",
- rl->subdevice, rl->rg_offset, rl->rg_length,
- rl->rg_length * comline->bsize / (1024 * 1024));
- }
- }
-}
-
-/**
- * compute_journal_layout - figure out where the journals in a FS are
- * @comline: the command line
- * @device: the device layout
- * @jlist: the list of journals
- *
- * Returns: a list of journal_list_t structures
- */
-
-void compute_journal_layout(commandline_t *comline, mkfs_device_t *device, osi_list_t *jlist)
-{
- mkfs_subdevice_t *sdev;
- journal_list_t *jl;
- osi_list_t *tmp;
- unsigned int x, j = 0;
- uint64 boffset, bcount;
- unsigned int min_jsize = (comline->expert) ? 1 : 32;
-
- for (x = 0; x < device->nsubdev; x++) {
- sdev = &device->subdev[x];
-
- if (sdev->is_journal) {
- type_zalloc(jl, journal_list_t, 1);
-
- /* Align the journals on seg_size boundries */
-
- boffset = sdev->start;
- bcount = sdev->length;
-
- if ((bcount + comline->seg_size) * comline->bsize < min_jsize << 20)
- die("journal %d is too small (minimum size is %u MB)\n", j, min_jsize);
-
- if (boffset % comline->seg_size) {
- bcount -= comline->seg_size - (boffset % comline->seg_size);
- boffset += comline->seg_size - (boffset % comline->seg_size);
- }
-
- jl->start = boffset;
- jl->segments = bcount / comline->seg_size;
-
- osi_list_add_prev(&jl->list, jlist);
-
- j++;
- }
- }
-
- if (comline->debug) {
- printf("\n");
-
- for (tmp = jlist->next, j = 0; tmp != jlist; tmp = tmp->next, j++) {
- jl = osi_list_entry(tmp, journal_list_t, list);
- printf("journal %u: start = %"PRIu64", segments = %u\n",
- j, jl->start, jl->segments);
- }
- }
-}
diff --git a/gfs/gfs_mkfs/locking.c b/gfs/gfs_mkfs/locking.c
deleted file mode 100644
index 4f66836..0000000
--- a/gfs/gfs_mkfs/locking.c
+++ /dev/null
@@ -1,102 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "global.h"
-#include "gfs_ondisk.h"
-#include "osi_list.h"
-
-#include "mkfs_gfs.h"
-
-
-
-
-
-/**
- * test_locking - Make sure the GFS is set up to use the right lock protocol
- * @lockproto: the lock protocol to mount
- * @locktable: the locktable name
- * @estr: returns the a string describing the error
- * @elen: the length of @estr
- *
- * Returns: 0 if things are ok, -1 on error (with estr set)
- */
-
-int test_locking(char *lockproto, char *locktable, char *estr, unsigned int elen)
-{
- char *c;
-
- if (strcmp(lockproto, "lock_nolock") == 0)
- {
- /* Nolock is always ok. */
- }
- else if (strcmp(lockproto, "lock_gulm") == 0 ||
- strcmp(lockproto, "lock_dlm") == 0)
- {
- for (c = locktable; *c; c++)
- {
- if (isspace(*c))
- {
- snprintf(estr, elen, "locktable error: contains space characters");
- return -1;
- }
- if (!isprint(*c))
- {
- snprintf(estr, elen, "locktable error: contains unprintable characters");
- return -1;
- }
- }
-
- c = strstr(locktable, ":");
- if (!c)
- {
- snprintf(estr, elen, "locktable error: missing colon in the locktable");
- return -1;
- }
-
- if (c == locktable)
- {
- snprintf(estr, elen, "locktable error: missing cluster name");
- return -1;
- }
-
- if (c - locktable > 16)
- {
- snprintf(estr, elen, "locktable error: cluster name too long");
- return -1;
- }
-
- c++;
- if (!c)
- {
- snprintf(estr, elen, "locktable error: missing filesystem name");
- return -1;
- }
-
- if (strstr(c, ":"))
- {
- snprintf(estr, elen, "locktable error: more than one colon present");
- return -1;
- }
-
- if (!strlen(c))
- {
- snprintf(estr, elen, "locktable error: missing filesystem name");
- return -1;
- }
-
- if (strlen(c) > 16)
- {
- snprintf(estr, elen, "locktable error: filesystem name too long");
- return -1;
- }
- }
- else
- {
- snprintf(estr, elen, "lockproto error: %s unknown", lockproto);
- return -1;
- }
-
- return 0;
-}
diff --git a/gfs/gfs_mkfs/main.c b/gfs/gfs_mkfs/main.c
deleted file mode 100644
index 4c8a8e0..0000000
--- a/gfs/gfs_mkfs/main.c
+++ /dev/null
@@ -1,504 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <assert.h>
-#include <time.h>
-#include <mntent.h>
-#include <poll.h>
-#include <signal.h>
-
-#include "global.h"
-#include "gfs_ondisk.h"
-#include "osi_list.h"
-#include "libgfs.h"
-#include "copyright.cf"
-
-#define EXTERN
-#include "mkfs_gfs.h"
-
-
-
-#define OPTION_STRING ("b:DhJ:j:Op:qr:s:t:VX")
-
-
-
-
-
-/**
- * print_usage - print out usage information
- *
- */
-
-static void print_usage(void)
-{
- printf("Usage:\n");
- printf("\n");
- printf("%s [options] <device>\n", prog_name);
- printf("\n");
- printf("Options:\n");
- printf("\n");
- printf(" -b <bytes> Filesystem block size\n");
- printf(" -D Enable debugging code\n");
- printf(" -h Print this help, then exit\n");
- printf(" -J <MB> Size of journals\n");
- printf(" -j <num> Number of journals\n");
- printf(" -O Don't ask for confirmation\n");
- printf(" -p <name> Name of the locking protocol\n");
- printf(" -q Don't print anything\n");
- printf(" -r <MB> Resource Group Size\n");
- printf(" -s <blocks> Journal segment size\n");
- printf(" -t <name> Name of the lock table\n");
- printf(" -V Print program version information, then exit\n");
-}
-
-
-/**
- * decode_arguments - decode command line arguments and fill in the commandline_t
- * @argc:
- * @argv:
- * @comline: the decoded command line arguments
- *
- */
-
-static void decode_arguments(int argc, char *argv[], commandline_t *comline)
-{
- int cont = TRUE;
- int optchar;
-
- while (cont)
- {
- optchar = getopt(argc, argv, OPTION_STRING);
-
- switch (optchar)
- {
- case 'b':
- comline->bsize = atoi(optarg);
- break;
-
-
- case 'D':
- comline->debug = TRUE;
- break;
-
-
- case 'h':
- print_usage();
- exit(EXIT_SUCCESS);
- break;
-
-
- case 'J':
- comline->jsize = atoi(optarg);
- break;
-
-
- case 'j':
- comline->journals = atoi(optarg);
- break;
-
-
- case 'O':
- comline->override = TRUE;
- break;
-
-
- case 'p':
- if (strlen(optarg) >= GFS_LOCKNAME_LEN)
- die("lock protocol name %s is too long\n", optarg);
- strcpy(comline->lockproto, optarg);
- break;
-
-
- case 'q':
- comline->quiet = TRUE;
- break;
-
-
- case 'r':
- comline->rgsize_specified = TRUE;
- comline->rgsize = atoi(optarg);
- break;
-
-
- case 's':
- comline->seg_size = atoi(optarg);
- break;
-
-
- case 't':
- if (strlen(optarg) >= GFS_LOCKNAME_LEN)
- die("lock table name %s is too long\n", optarg);
- strcpy(comline->locktable, optarg);
- break;
-
-
- case 'V':
- printf("gfs_mkfs %s (built %s %s)\n", RELEASE_VERSION, __DATE__, __TIME__);
- printf("%s\n", REDHAT_COPYRIGHT);
- exit(EXIT_SUCCESS);
- break;
-
-
- case 'X':
- comline->expert = TRUE;
- break;
-
-
- case ':':
- case '?':
- fprintf(stderr, "Please use '-h' for usage.\n");
- exit(EXIT_FAILURE);
- break;
-
-
- case EOF:
- cont = FALSE;
- break;
-
-
- default:
- die("unknown option: %c\n", optchar);
- break;
- };
- }
-
-
- if (optind < argc)
- {
- comline->device = argv[optind];
- optind++;
- }
- else
- die("no device specified (try -h for help)\n");
-
-
-
- if (optind < argc)
- die("Unrecognized option: %s\n", argv[optind]);
-
-
- if (comline->debug)
- {
- printf("Command Line Arguments:\n");
- printf(" proto = %s\n", comline->lockproto);
- printf(" table = %s\n", comline->locktable);
- printf(" bsize = %u\n", comline->bsize);
- printf(" seg_size = %u\n", comline->seg_size);
- printf(" journals = %u\n", comline->journals);
- printf(" jsize = %u\n", comline->jsize);
- printf(" rgsize = %u\n", comline->rgsize);
- printf(" debug = %d\n", comline->debug);
- printf(" device = %s\n", comline->device);
- }
-}
-
-static int get_file_output(int fd, char *buffer, size_t buflen)
-{
- struct pollfd pf = { .fd = fd, .events = POLLIN|POLLRDHUP };
- int flags;
- int pos = 0;
- int rv;
-
- flags = fcntl(fd, F_GETFL, 0);
- if (flags < 0)
- return flags;
-
- flags |= O_NONBLOCK;
- rv = fcntl(fd, F_SETFL, flags);
- if (rv < 0)
- return rv;
-
- while (1) {
- rv = poll(&pf, 1, 10 * 1000);
- if (rv == 0)
- break;
- if (rv < 0)
- return rv;
- if (pf.revents & POLLIN) {
- rv = read(fd, buffer + pos,
- buflen - pos);
- if (rv < 0) {
- if (errno == EAGAIN)
- continue;
- return rv;
- }
- if (rv == 0)
- break;
- pos += rv;
- if (pos >= buflen)
- return -1;
- buffer[pos] = 0;
- continue;
- }
- if (pf.revents & (POLLRDHUP | POLLHUP | POLLERR))
- break;
- }
- return 0;
-}
-
-static void check_dev_content(const char *devname)
-{
- struct sigaction sa;
- char content[1024] = { 0, };
- char * const args[] = {
- (char *)"/usr/bin/file",
- (char *)"-bs",
- (char *)devname,
- NULL };
- int p[2];
- int ret;
- int pid;
-
- ret = sigaction(SIGCHLD, NULL, &sa);
- if (ret)
- return;
- sa.sa_handler = SIG_IGN;
- sa.sa_flags |= (SA_NOCLDSTOP | SA_NOCLDWAIT);
- ret = sigaction(SIGCHLD, &sa, NULL);
- if (ret)
- goto fail;
-
- ret = pipe(p);
- if (ret)
- goto fail;
-
- pid = fork();
-
- if (pid < 0) {
- close(p[1]);
- goto fail;
- }
-
- if (pid) {
- close(p[1]);
- ret = get_file_output(p[0], content, sizeof(content));
- if (ret) {
-fail:
- printf("Content of file or device unknown (do you have GNU fileutils installed?)\n");
- } else {
- if (*content == 0)
- goto fail;
- printf("It appears to contain: %s", content);
- }
- close(p[0]);
- return;
- }
-
- close(p[0]);
- dup2(p[1], STDOUT_FILENO);
- close(STDIN_FILENO);
- exit(execv(args[0], args));
-}
-
-/**
- * are_you_sure - protect lusers from themselves
- * @comline: the command line
- *
- */
-
-static void are_you_sure(commandline_t *comline)
-{
- char input[32];
- int fd;
-
- fd = open(comline->device, O_RDONLY | O_CLOEXEC);
- if (fd < 0)
- die("Error: device %s not found.\n", comline->device);
- printf("This will destroy any data on %s.\n",
- comline->device);
- check_dev_content(comline->device);
- close(fd);
- printf("\nAre you sure you want to proceed? [y/n] ");
- if (fgets(input, 32, stdin) == NULL || input[0] != 'y')
- die("aborted\n");
- else
- printf("\n");
-}
-
-
-/**
- * check_mount - check to see if device is mounted/busy
- * @
- *
- */
-
-static void check_mount(char *device)
-{
- struct stat st_buf;
- int fd;
-
- if (stat(device, &st_buf) < 0)
- die("could not stat device %s\n", device);
- if (!S_ISBLK(st_buf.st_mode))
- die("%s is not a block device\n", device);
-
- fd = open(device, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
-
- if (fd < 0) {
- if (errno == EBUSY) {
- die("device %s is busy\n", device);
- }
- }
- else {
- close(fd);
- }
-
- return;
-}
-
-
-/**
- * print_results - print out summary information
- * @comline: the command line
- *
- */
-
-static void print_results(commandline_t *comline)
-{
- if (comline->quiet)
- return;
-
- if (comline->expert)
- printf("Expert mode: on\n");
-
- printf("Device: %s\n", comline->device);
-
- printf("Blocksize: %u\n", comline->bsize);
- printf("Filesystem Size: %"PRIu64"\n", comline->fssize);
-
- printf("Journals: %u\n", comline->journals);
- printf("Resource Groups: %"PRIu64"\n", comline->rgrps);
-
- printf("Locking Protocol: %s\n", comline->lockproto);
- printf("Lock Table: %s\n", comline->locktable);
-
- printf("\nSyncing...\n");
-
- sync();
-
- printf("All Done\n");
-}
-
-
-/**
- * main - do everything
- * @argc:
- * @argv:
- *
- * Returns: 0 on success, non-0 on failure
- */
-
-int main(int argc, char *argv[])
-{
- commandline_t comline;
- mkfs_device_t device;
- osi_list_t rlist;
- osi_list_t jlist;
- unsigned int x;
-
- prog_name = argv[0];
-
- osi_list_init(&rlist);
- osi_list_init(&jlist);
-
- /* Process the command line arguments */
-
- memset(&comline, 0, sizeof(commandline_t));
- comline.bsize = MKFS_DEFAULT_BSIZE;
- comline.seg_size = MKFS_DEFAULT_SEG_SIZE;
- comline.jsize = MKFS_DEFAULT_JSIZE;
- comline.rgsize = MKFS_DEFAULT_RGSIZE;
- comline.rgsize_specified = FALSE;
- strcpy(comline.lockproto, MKFS_DEFAULT_LOCKPROTO);
-
- decode_arguments(argc, argv, &comline);
-
- check_mount(comline.device);
-
- if (!comline.expert) {
- char buf[256];
- if (test_locking(comline.lockproto, comline.locktable, buf, 256))
- die("%s\n", buf);
- }
-
- /* Block sizes must be a power of two from 512 to 65536 */
-
- for (x = 512; x; x <<= 1)
- if (x == comline.bsize)
- break;
-
- if (!x || comline.bsize > 65536)
- die("block size must be a power of two between 512 and 65536\n");
-
- comline.sb_addr = GFS_SB_ADDR * GFS_BASIC_BLOCK / comline.bsize;
-
- if (comline.seg_size < 2)
- die("segment size too small\n");
-
- if (!comline.expert && (uint64)comline.seg_size * comline.bsize > 4194304)
- die("segment size too large\n");
-
- if (comline.expert) {
- if (1 > comline.rgsize || comline.rgsize > 2048)
- die("bad resource group size\n");
- }
- else {
- if (32 > comline.rgsize || comline.rgsize > 2048)
- die("bad resource group size\n");
- }
-
- /* Get the device geometry */
-
- memset(&device, 0, sizeof(mkfs_device_t));
-
- device_geometry(&comline, &device);
- add_journals_to_device(&comline, &device);
-
- fix_device_geometry(&comline, &device);
-
- /* Compute the resource group layouts */
-
- compute_rgrp_layout(&comline, &device, &rlist);
-
- compute_journal_layout(&comline, &device, &jlist);
-
- /* Start writing stuff out */
-
- comline.fd = open(comline.device, O_RDWR | O_CLOEXEC);
- if (comline.fd < 0)
- die("can't open device %s\n", comline.device);
-
- if (!comline.override)
- are_you_sure(&comline);
-
- write_mkfs_sb(&comline, &rlist);
-
- /* Figure out where we start allocating in rgrp 0 */
- comline.rgrp0_next = comline.sbd->sd_sb.sb_root_di.no_addr + 1;
-
- write_jindex(&comline, &jlist);
-
- write_rindex(&comline, &rlist);
-
- write_root(&comline);
-
- write_quota(&comline);
-
- write_license(&comline);
-
- write_rgrps(&comline, &rlist);
-
- write_journals(&comline, &jlist);
-
- close(comline.fd);
- free(comline.sbd);
- print_results(&comline);
-
- exit(EXIT_SUCCESS);
-}
diff --git a/gfs/gfs_mkfs/mkfs_gfs.h b/gfs/gfs_mkfs/mkfs_gfs.h
deleted file mode 100644
index cb00342..0000000
--- a/gfs/gfs_mkfs/mkfs_gfs.h
+++ /dev/null
@@ -1,181 +0,0 @@
-#ifndef __MKFS_GFS_DOT_H__
-#define __MKFS_GFS_DOT_H__
-
-
-/* Extern Macro */
-
-#ifndef EXTERN
-#define EXTERN extern
-#define INIT(X)
-#else
-#undef EXTERN
-#define EXTERN
-#define INIT(X) =X
-#endif
-
-
-#define die(fmt, args...) \
-do \
-{ \
- fprintf(stderr, "%s: ", prog_name); \
- fprintf(stderr, fmt, ##args); \
- exit(EXIT_FAILURE); \
-} \
-while (0)
-
-#define MKFS_ASSERT(x, todo) \
-do \
-{ \
- if (!(x)) \
- { \
- {todo} \
- die("assertion failed on line %d of file %s\n", __LINE__, __FILE__); \
- } \
-} \
-while (0)
-
-#define type_zalloc(ptr, type, count) \
-do \
-{ \
- (ptr) = (type *)malloc(sizeof(type) * (count)); \
- if ((ptr)) \
- memset((char *)(ptr), 0, sizeof(type) * (count)); \
- else \
- die("unable to allocate memory on line %d of file %s\n", \
- __LINE__, __FILE__); \
-} \
-while (0)
-
-#define type_alloc(ptr, type, count) \
-do \
-{ \
- (ptr) = (type *)malloc(sizeof(type) * (count)); \
- if (!(ptr)) \
- die("unable to allocate memory on line %d of file %s\n", \
- __LINE__, __FILE__); \
-} \
-while (0)
-
-#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
-
-
-
-
-
-struct mkfs_subdevice
-{
- uint64 start;
- uint64 length;
- int is_journal;
-};
-typedef struct mkfs_subdevice mkfs_subdevice_t;
-
-
-struct mkfs_device
-{
- unsigned int nsubdev;
- mkfs_subdevice_t *subdev;
-};
-typedef struct mkfs_device mkfs_device_t;
-
-
-struct commandline
-{
- char lockproto[GFS_LOCKNAME_LEN];
- char locktable[GFS_LOCKNAME_LEN];
-
- uint32 bsize; /* The block size of the FS */
- uint32 seg_size; /* The journal segment size */
- uint32 journals; /* Number of journals */
- uint32 jsize; /* Size of journals */
- uint32 rgsize; /* The Resource Group size */
- int rgsize_specified; /* Did the user specify a rg size? */
-
- int debug; /* Print out debugging information? */
- int quiet; /* No messages */
- int expert;
- int override;
-
- char *device; /* device */
-
-
- /* Not specified on the command line, but... */
-
- uint64 rgrps; /* Number of rgrps */
- int fd; /* fd of the device */
- struct gfs_sbd *sbd; /* A copy of the superblock */
- uint64 fssize; /* size of the filesystem */
-
- uint64 sb_addr;
-
- uint64 rgrp0_next; /* The address of the next available block in rgrp 0 */
-};
-typedef struct commandline commandline_t;
-
-
-struct rgrp_list
-{
- osi_list_t list;
-
- uint32 subdevice; /* The subdevice who holds this resource group */
-
- uint64 rg_offset; /* The offset of the beginning of this resource group */
- uint64 rg_length; /* The length of this resource group */
-
- struct gfs_rindex *ri;
-};
-typedef struct rgrp_list rgrp_list_t;
-
-
-struct journal_list
-{
- osi_list_t list;
-
- uint64 start;
- uint32 segments;
-};
-typedef struct journal_list journal_list_t;
-
-
-EXTERN char *prog_name;
-
-
-#define MKFS_DEFAULT_BSIZE (4096)
-#define MKFS_DEFAULT_SEG_SIZE (16)
-#define MKFS_DEFAULT_JSIZE (128)
-#define MKFS_DEFAULT_RGSIZE (256)
-#define MKFS_DEFAULT_LOCKPROTO "lock_dlm"
-#define MKFS_EXCESSIVE_RGS (10000)
-
-/* device_geometry.c */
-
-void device_geometry(commandline_t *comline, mkfs_device_t *device);
-void add_journals_to_device(commandline_t *comline, mkfs_device_t *device);
-void fix_device_geometry(commandline_t *comline, mkfs_device_t *device);
-
-
-/* fs_geometry.c */
-
-void compute_rgrp_layout(commandline_t *comline, mkfs_device_t *device, osi_list_t *rlist);
-void compute_journal_layout(commandline_t *comline, mkfs_device_t *device, osi_list_t *jlist);
-
-
-/* locking.c */
-
-int test_locking(char *lockproto, char *locktable, char *estr, unsigned int elen);
-
-
-/* structures.c */
-
-void write_mkfs_sb(commandline_t *comline, osi_list_t *rlist);
-void write_jindex(commandline_t *comline, osi_list_t *jlist);
-void write_rindex(commandline_t *comline, osi_list_t *rlist);
-void write_root(commandline_t *comline);
-void write_quota(commandline_t *comline);
-void write_license(commandline_t *comline);
-void write_rgrps(commandline_t *comline, osi_list_t *rlist);
-void write_journals(commandline_t *comline, osi_list_t *jlist);
-
-
-#endif /* __MKFS_GFS_DOT_H__ */
-
diff --git a/gfs/gfs_mkfs/ondisk.c b/gfs/gfs_mkfs/ondisk.c
deleted file mode 100644
index f0955a5..0000000
--- a/gfs/gfs_mkfs/ondisk.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-
-#include "global.h"
-#include "linux_endian.h"
-
-#define printk printf
-#define pv(struct, member, fmt) printf(" "#member" = "fmt"\n", struct->member);
-
-#define ENTER(x)
-#define EXIT(x)
-#define RET(x) return
-#define RETURN(x, y) return y
-
-#define WANT_GFS_CONVERSION_FUNCTIONS
-#include "gfs_ondisk.h"
-
diff --git a/gfs/gfs_mkfs/structures.c b/gfs/gfs_mkfs/structures.c
deleted file mode 100644
index 2376f27..0000000
--- a/gfs/gfs_mkfs/structures.c
+++ /dev/null
@@ -1,845 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <assert.h>
-#include <time.h>
-
-#include "global.h"
-#include "gfs_ondisk.h"
-#include "osi_list.h"
-#include "linux_endian.h"
-#include "libgfs.h"
-#include "mkfs_gfs.h"
-
-
-#define MKFS_ROOT_MODE (0755)
-#define MKFS_HIDDEN_MODE (0600)
-
-/**
- * rgblocks2bitblocks - blerg
- * @bsize: the FS block size
- * @rgblocks: The total number of the blocks in the RG
- * Also, returns the number of allocateable blocks
- * @bitblocks: Returns the number of bitmap blocks
- *
- * Give a number of blocks in a RG, figure out the number of blocks
- * needed for bitmaps.
- *
- */
-
-static void
-rgblocks2bitblocks(unsigned int bsize,
- uint32_t *rgblocks,
- uint32_t *bitblocks)
-{
- unsigned int bitbytes_provided, last = 0;
- unsigned int bitbytes_needed;
-
- *bitblocks = 1;
- bitbytes_provided = bsize - sizeof(struct gfs_rgrp);
-
- for (;;) {
- bitbytes_needed = (*rgblocks - *bitblocks) / GFS_NBBY;
-
- if (bitbytes_provided >= bitbytes_needed) {
- if (last >= bitbytes_needed)
- (*bitblocks)--;
- break;
- }
-
- last = bitbytes_provided;
- (*bitblocks)++;
- bitbytes_provided += bsize - sizeof(struct gfs_meta_header);
- }
-
- *rgblocks = bitbytes_needed * GFS_NBBY;
-}
-
-
-/**
- * write_mkfs_sb - write the superblock
- * @comline: the command line
- * @rlist: the list of RGs
- *
- */
-
-void write_mkfs_sb(commandline_t *comline, osi_list_t *rlist)
-{
- struct gfs_sbd *sbd;
- uint64 jindex_dinode;
- char buf[comline->bsize];
- int x;
-
- memset(buf, 0, comline->bsize);
-
- for (x = 0; x < comline->sb_addr; x++) {
- do_lseek(comline->fd, x * comline->bsize);
- do_write(comline->fd, buf, comline->bsize);
- }
-
- /* Figure out the location of the journal index inode */
- {
- rgrp_list_t *rl = osi_list_entry(rlist->next, rgrp_list_t, list);
- uint32_t rgblocks, bitblocks;
-
- rgblocks = rl->rg_length;
- rgblocks2bitblocks(comline->bsize, &rgblocks, &bitblocks);
-
- jindex_dinode = rl->rg_offset + bitblocks;
- }
-
- /* Now, fill in the superblock */
-
- type_zalloc(sbd, struct gfs_sbd, 1);
- comline->sbd = sbd;
-
- sbd->sd_sb.sb_header.mh_magic = GFS_MAGIC;
- sbd->sd_sb.sb_header.mh_type = GFS_METATYPE_SB;
- sbd->sd_sb.sb_header.mh_format = GFS_FORMAT_SB;
-
- sbd->sd_sb.sb_fs_format = GFS_FORMAT_FS;
- sbd->sd_sb.sb_multihost_format = GFS_FORMAT_MULTI;
-
- sbd->sd_sb.sb_bsize = comline->bsize;
- sbd->sd_sb.sb_bsize_shift = ffs(comline->bsize) - 1;
- sbd->sd_sb.sb_seg_size = comline->seg_size;
-
- compute_constants(sbd);
-
- sbd->sd_sb.sb_jindex_di.no_formal_ino = jindex_dinode;
- sbd->sd_sb.sb_jindex_di.no_addr = jindex_dinode;
- sbd->sd_sb.sb_rindex_di.no_formal_ino = jindex_dinode + 1;
- sbd->sd_sb.sb_rindex_di.no_addr = jindex_dinode + 1;
- sbd->sd_sb.sb_root_di.no_formal_ino = jindex_dinode + 4;
- sbd->sd_sb.sb_root_di.no_addr = jindex_dinode + 4;
-
- strcpy(sbd->sd_sb.sb_lockproto, comline->lockproto);
- strcpy(sbd->sd_sb.sb_locktable, comline->locktable);
-
- sbd->sd_sb.sb_quota_di.no_formal_ino = jindex_dinode + 2;
- sbd->sd_sb.sb_quota_di.no_addr = jindex_dinode + 2;
- sbd->sd_sb.sb_license_di.no_formal_ino = jindex_dinode + 3;
- sbd->sd_sb.sb_license_di.no_addr = jindex_dinode + 3;
- sbd->sd_fsb2bb_shift = sbd->sd_sb.sb_bsize_shift - GFS_BASIC_BLOCK_SHIFT;
-
- write_sb(comline->fd, sbd);
- if (comline->debug) {
- printf("\nSuperblock:\n");
- gfs_sb_print(&sbd->sd_sb);
- }
-}
-
-/**
- * build_tree - build the pointers and indirect blocks for a file
- * @comline: the command line
- * @di: the dinode
- * @addr: the start of the file
- * @blocks: the number of blocks in the file
- *
- */
-
-static void build_tree(commandline_t *comline, struct gfs_dinode *di, uint64 addr, unsigned int blocks)
-{
- struct gfs_indirect ind;
- char *buf;
- unsigned int x, offset;
- unsigned int height;
- unsigned int indblocks;
- uint64 tmp_addr;
- unsigned int tmp_blocks;
-
- di->di_height = compute_height(comline->sbd, di->di_size);
-
- if (di->di_height == 1) {
- type_zalloc(buf, char, comline->bsize);
-
- for (x = 0; x < blocks; x++)
- ((uint64 *)(buf + sizeof(struct gfs_dinode)))[x] = cpu_to_gfs64(addr + x);
-
- gfs_dinode_out(di, buf);
-
- do_lseek(comline->fd, di->di_num.no_addr * comline->bsize);
- do_write(comline->fd, buf, comline->bsize);
-
- free(buf);
- }
- else {
- tmp_addr = addr;
- tmp_blocks = blocks;
-
- for (height = di->di_height; height > 1; height--) {
- memset(&ind, 0, sizeof(struct gfs_indirect));
- ind.in_header.mh_magic = GFS_MAGIC;
- ind.in_header.mh_type = GFS_METATYPE_IN;
- ind.in_header.mh_format = GFS_FORMAT_IN;
-
- indblocks = DIV_RU((tmp_blocks * sizeof(uint64)),
- (comline->bsize - sizeof(struct gfs_indirect)));
-
- type_zalloc(buf, char, indblocks * comline->bsize);
-
- offset = 0;
- for (x = 0; x < tmp_blocks; x++) {
- if (!(offset % comline->bsize)) {
- gfs_indirect_out(&ind, buf + offset);
- offset += sizeof(struct gfs_indirect);
- }
-
- *((uint64 *)(buf + offset)) = cpu_to_gfs64(tmp_addr + x);
- offset += sizeof(uint64);
- }
-
- do_lseek(comline->fd, comline->rgrp0_next * comline->bsize);
- do_write(comline->fd, buf, indblocks * comline->bsize);
-
- free(buf);
-
- tmp_addr = comline->rgrp0_next;
- tmp_blocks = indblocks;
-
- di->di_blocks += indblocks;
-
- comline->rgrp0_next += indblocks;
- }
- type_zalloc(buf, char, comline->bsize);
-
- for (x = 0; x < tmp_blocks; x++)
- ((uint64 *)(buf + sizeof(struct gfs_dinode)))[x] = cpu_to_gfs64(tmp_addr + x);
-
- gfs_dinode_out(di, buf);
-
- do_lseek(comline->fd, di->di_num.no_addr * comline->bsize);
- do_write(comline->fd, buf, comline->bsize);
-
- free(buf);
- }
-}
-
-
-/**
- * fill_jindex - create the journal index data
- * @comline: the command line
- * @jlist: the list of journals
- *
- * Returns: a pointer data for the jindex
- */
-
-static char *fill_jindex(commandline_t *comline, osi_list_t *jlist)
-{
- journal_list_t *jl;
- struct gfs_jindex ji;
- osi_list_t *tmp;
- char *buf;
- unsigned int j = 0;
-
- type_alloc(buf, char, comline->journals * sizeof(struct gfs_jindex));
-
- for (tmp = jlist->next; tmp != jlist; tmp = tmp->next) {
- jl = osi_list_entry(tmp, journal_list_t, list);
-
- memset(&ji, 0, sizeof(struct gfs_jindex));
-
- ji.ji_addr = jl->start;
- ji.ji_nsegment = jl->segments;
-
- gfs_jindex_out(&ji, buf + j * sizeof(struct gfs_jindex));
-
- j++;
- }
-
- if (comline->debug) {
- printf("\nJournal Index data:\n");
-
- for (j = 0; j < comline->journals; j++) {
- gfs_jindex_in(&ji, buf + j * sizeof(struct gfs_jindex));
-
- printf("\n Journal %d\n", j);
- gfs_jindex_print(&ji);
- }
- }
-
- return buf;
-}
-
-/**
- * write_jindex - write out the journal index
- * @comline: the command line
- * @jlist: the list of journals
- *
- */
-
-void write_jindex(commandline_t *comline, osi_list_t *jlist)
-{
- struct gfs_dinode di;
- struct gfs_meta_header jd;
- char *buf, *data;
- uint64 addr;
- unsigned int blocks;
- unsigned int x, left, jbsize = comline->bsize - sizeof(struct gfs_meta_header);
-
- memset(&di, 0, sizeof(struct gfs_dinode));
-
- di.di_header.mh_magic = GFS_MAGIC;
- di.di_header.mh_type = GFS_METATYPE_DI;
- di.di_header.mh_format = GFS_FORMAT_DI;
-
- di.di_num = comline->sbd->sd_sb.sb_jindex_di;
-
- di.di_mode = MKFS_HIDDEN_MODE;
- di.di_nlink = 1;
- di.di_size = comline->journals * sizeof(struct gfs_jindex);
- di.di_blocks = 1;
- di.di_atime = di.di_mtime = di.di_ctime = time(NULL);
-
- di.di_flags = GFS_DIF_JDATA;
- di.di_payload_format = GFS_FORMAT_JI;
- di.di_type = GFS_FILE_REG;
-
- data = fill_jindex(comline, jlist);
-
- if (di.di_size < comline->bsize - sizeof(struct gfs_dinode)) {
- type_zalloc(buf, char, comline->bsize);
-
- gfs_dinode_out(&di, buf);
-
- memcpy(buf + sizeof(struct gfs_dinode), data, comline->journals * sizeof(struct gfs_jindex));
-
- do_lseek(comline->fd, di.di_num.no_addr * comline->bsize);
- do_write(comline->fd, buf, comline->bsize);
-
- free(buf);
- }
- else {
- blocks = DIV_RU(di.di_size, (comline->bsize - sizeof(struct gfs_meta_header)));
- di.di_blocks += blocks;
-
- addr = comline->rgrp0_next;
- memset(&jd, 0, sizeof(struct gfs_meta_header));
- jd.mh_magic = GFS_MAGIC;
- jd.mh_type = GFS_METATYPE_JD;
- jd.mh_format = GFS_FORMAT_JD;
-
- type_zalloc(buf, char, blocks * comline->bsize);
-
- left = comline->journals * sizeof(struct gfs_jindex);
- for (x = 0; x < blocks; x++) {
- gfs_meta_header_out(&jd, buf + x * comline->bsize);
- memcpy(buf + x * comline->bsize + sizeof(struct gfs_meta_header),
- data + x * jbsize,
- (left > jbsize) ? jbsize : left);
- left -= jbsize;
- }
-
- do_lseek(comline->fd, addr * comline->bsize);
- do_write(comline->fd, buf, blocks * comline->bsize);
-
- free(buf);
-
- comline->rgrp0_next += blocks;
-
- build_tree(comline, &di, addr, blocks);
- }
-
- free(data);
-
- if (comline->debug) {
- printf("\nJournal index dinode:\n");
- gfs_dinode_print(&di);
- }
-}
-
-
-/**
- * fill_rindex - create the resource group index data
- * @comline: the command line
- * @rlist: the list of RGs
- *
- * Returns: a pointer data for the rindex
- */
-
-static char *fill_rindex(commandline_t *comline, osi_list_t *rlist)
-{
- struct gfs_rindex *ri, grindex;
- rgrp_list_t *rl;
- osi_list_t *tmp;
- char *buf;
- unsigned int r = 0;
- uint32 rgblocks, bitblocks;
-
- type_alloc(buf, char, comline->rgrps * sizeof(struct gfs_rindex));
-
- for (tmp = rlist->next; tmp != rlist; tmp = tmp->next) {
- rl = osi_list_entry(tmp, rgrp_list_t, list);
-
- rgblocks = rl->rg_length;
- rgblocks2bitblocks(comline->bsize, &rgblocks, &bitblocks);
-
- type_zalloc(ri, struct gfs_rindex, 1);
- rl->ri = ri;
-
- ri->ri_addr = rl->rg_offset;
- ri->ri_length = bitblocks;
-
- ri->ri_data1 = rl->rg_offset + bitblocks;
- ri->ri_data = rgblocks;
-
- ri->ri_bitbytes = rgblocks / GFS_NBBY;
-
- gfs_rindex_out(ri, buf + r * sizeof(struct gfs_rindex));
-
- comline->fssize += rgblocks;
-
- r++;
- }
-
- if (comline->debug) {
- printf("\nResource Index data:\n");
-
- for (r = 0; r < comline->rgrps; r++) {
- gfs_rindex_in(&grindex, buf + r * sizeof(struct gfs_rindex));
-
- printf("\n Resource index %d\n", r);
- gfs_rindex_print(&grindex);
- }
- }
- return buf;
-}
-
-/**
- * write_rindex - write out the resource group index
- * @comline: the command line
- * @jlist: the list of RGs
- *
- */
-
-void write_rindex(commandline_t *comline, osi_list_t *rlist)
-{
- struct gfs_dinode di;
- struct gfs_meta_header jd;
- char *buf, *data;
- uint64 addr;
- unsigned int blocks;
- unsigned int x, left, jbsize = comline->bsize - sizeof(struct gfs_meta_header);
-
- memset(&di, 0, sizeof(struct gfs_dinode));
-
- di.di_header.mh_magic = GFS_MAGIC;
- di.di_header.mh_type = GFS_METATYPE_DI;
- di.di_header.mh_format = GFS_FORMAT_DI;
-
- di.di_num = comline->sbd->sd_sb.sb_rindex_di;
-
- di.di_mode = MKFS_HIDDEN_MODE;
- di.di_nlink = 1;
- di.di_size = comline->rgrps * sizeof(struct gfs_rindex);
- di.di_blocks = 1;
- di.di_atime = di.di_mtime = di.di_ctime = time(NULL);
-
- di.di_flags = GFS_DIF_JDATA;
- di.di_payload_format = GFS_FORMAT_RI;
- di.di_type = GFS_FILE_REG;
-
- data = fill_rindex(comline, rlist);
-
- if (di.di_size < comline->bsize - sizeof(struct gfs_dinode)) {
- type_zalloc(buf, char, comline->bsize);
-
- gfs_dinode_out(&di, buf);
-
- memcpy(buf + sizeof(struct gfs_dinode), data, comline->rgrps * sizeof(struct gfs_rindex));
-
- do_lseek(comline->fd, di.di_num.no_addr * comline->bsize);
- do_write(comline->fd, buf, comline->bsize);
-
- free(buf);
- }
- else {
- blocks = DIV_RU(di.di_size, (comline->bsize - sizeof(struct gfs_meta_header)));
- di.di_blocks += blocks;
-
- addr = comline->rgrp0_next;
-
- memset(&jd, 0, sizeof(struct gfs_meta_header));
- jd.mh_magic = GFS_MAGIC;
- jd.mh_type = GFS_METATYPE_JD;
- jd.mh_format = GFS_FORMAT_JD;
-
- type_zalloc(buf, char, blocks * comline->bsize);
-
- left = comline->rgrps * sizeof(struct gfs_rindex);
- for (x = 0; x < blocks; x++) {
- gfs_meta_header_out(&jd, buf + x * comline->bsize);
- memcpy(buf + x * comline->bsize + sizeof(struct gfs_meta_header),
- data + x * jbsize,
- (left > jbsize) ? jbsize : left);
- left -= jbsize;
- }
-
- do_lseek(comline->fd, addr * comline->bsize);
- do_write(comline->fd, buf, blocks * comline->bsize);
-
- free(buf);
-
- comline->rgrp0_next += blocks;
-
- build_tree(comline, &di, addr, blocks);
- }
-
- free(data);
-
- if (comline->debug) {
- printf("\nResource index dinode:\n");
- gfs_dinode_print(&di);
- }
-}
-
-
-/**
- * write_root - write out the root dinode
- * @comline: the command line
- *
- */
-
-void write_root(commandline_t *comline)
-{
- struct gfs_dinode di;
- struct gfs_dirent de;
- char buf[comline->bsize];
-
- memset(&di, 0, sizeof(struct gfs_dinode));
- memset(buf, 0, comline->bsize);
-
- di.di_header.mh_magic = GFS_MAGIC;
- di.di_header.mh_type = GFS_METATYPE_DI;
- di.di_header.mh_format = GFS_FORMAT_DI;
-
- di.di_num = comline->sbd->sd_sb.sb_root_di;
-
- di.di_mode = MKFS_ROOT_MODE;
- di.di_nlink = 2;
- di.di_size = comline->bsize - sizeof(struct gfs_dinode);
- di.di_blocks = 1;
- di.di_atime = di.di_mtime = di.di_ctime = time(NULL);
-
- di.di_flags = GFS_DIF_JDATA;
- di.di_payload_format = GFS_FORMAT_DE;
- di.di_type = GFS_FILE_DIR;
-
- di.di_entries = 2;
-
- gfs_dinode_out(&di, buf);
-
- /* Fill in . */
-
- memset(&de, 0, sizeof(struct gfs_dirent));
-
- de.de_inum = comline->sbd->sd_sb.sb_root_di;
- de.de_hash = gfs_dir_hash(".", 1);
- de.de_rec_len = GFS_DIRENT_SIZE(1);
- de.de_name_len = 1;
- de.de_type = GFS_FILE_DIR;
-
- gfs_dirent_out(&de, buf + sizeof(struct gfs_dinode));
- memcpy(buf + sizeof(struct gfs_dinode) + sizeof(struct gfs_dirent), ".", 1);
-
- if (comline->debug) {
- printf("\nRoot Dinode dirent:\n");
- gfs_dirent_print(&de, ".");
- }
-
- /* Fill in .. */
-
- memset(&de, 0, sizeof(struct gfs_dirent));
-
- de.de_inum = comline->sbd->sd_sb.sb_root_di;
- de.de_hash = gfs_dir_hash("..", 2);
- de.de_rec_len = comline->bsize - GFS_DIRENT_SIZE(1) - sizeof(struct gfs_dinode);
- de.de_name_len = 2;
- de.de_type = GFS_FILE_DIR;
-
- gfs_dirent_out(&de, buf + sizeof(struct gfs_dinode) + GFS_DIRENT_SIZE(1));
- memcpy(buf + sizeof(struct gfs_dinode) + GFS_DIRENT_SIZE(1) + sizeof(struct gfs_dirent), "..", 2);
-
- if (comline->debug) {
- printf("\nRoot Dinode dirent:\n");
- gfs_dirent_print(&de, "..");
- }
-
- do_lseek(comline->fd, di.di_num.no_addr * comline->bsize);
- do_write(comline->fd, buf, comline->bsize);
-
- if (comline->debug) {
- printf("\nRoot dinode:\n");
- gfs_dinode_print(&di);
- }
-}
-
-/**
- * write_quota - write out the quota dinode
- * @comline: the command line
- *
- */
-
-void write_quota(commandline_t *comline)
-{
- struct gfs_dinode di;
- struct gfs_quota qu;
-
- char buf[comline->bsize];
-
- memset(&di, 0, sizeof(struct gfs_dinode));
- memset(buf, 0, comline->bsize);
-
- di.di_header.mh_magic = GFS_MAGIC;
- di.di_header.mh_type = GFS_METATYPE_DI;
- di.di_header.mh_format = GFS_FORMAT_DI;
-
- di.di_num = comline->sbd->sd_sb.sb_quota_di;
-
- di.di_mode = MKFS_HIDDEN_MODE;
- di.di_nlink = 1;
- di.di_size = 2 * sizeof(struct gfs_quota);
- di.di_blocks = 1;
- di.di_atime = di.di_mtime = di.di_ctime = time(NULL);
-
- di.di_flags = GFS_DIF_JDATA;
- di.di_payload_format = GFS_FORMAT_QU;
- di.di_type = GFS_FILE_REG;
-
- gfs_dinode_out(&di, buf);
-
- /* Fill in the root user quota */
-
- memset(&qu, 0, sizeof(struct gfs_quota));
- qu.qu_value = comline->rgrp0_next - comline->sbd->sd_sb.sb_jindex_di.no_addr;
-
- gfs_quota_out(&qu, buf + sizeof(struct gfs_dinode));
-
- if (comline->debug) {
- printf("\nRoot user quota:\n");
- gfs_quota_print(&qu);
- }
-
- /* Fill in the root group quota */
-
- memset(&qu, 0, sizeof(struct gfs_quota));
- qu.qu_value = comline->rgrp0_next - comline->sbd->sd_sb.sb_jindex_di.no_addr;
-
- gfs_quota_out(&qu, buf + sizeof(struct gfs_dinode) + sizeof(struct gfs_quota));
-
- if (comline->debug) {
- printf("\nRoot group quota:\n");
- gfs_quota_print(&qu);
- }
-
- do_lseek(comline->fd, di.di_num.no_addr * comline->bsize);
- do_write(comline->fd, buf, comline->bsize);
-
- if (comline->debug) {
- printf("\nQuota dinode:\n");
- gfs_dinode_print(&di);
- }
-}
-
-/**
- * write_license - write out the quota dinode
- * @comline: the command line
- *
- */
-
-void write_license(commandline_t *comline)
-{
- struct gfs_dinode di;
-
- char buf[comline->bsize];
-
- memset(&di, 0, sizeof(struct gfs_dinode));
- memset(buf, 0, comline->bsize);
-
- di.di_header.mh_magic = GFS_MAGIC;
- di.di_header.mh_type = GFS_METATYPE_DI;
- di.di_header.mh_format = GFS_FORMAT_DI;
-
- di.di_num = comline->sbd->sd_sb.sb_license_di;
-
- di.di_mode = MKFS_HIDDEN_MODE;
- di.di_nlink = 1;
- di.di_size = 0;
- di.di_blocks = 1;
- di.di_atime = di.di_mtime = di.di_ctime = time(NULL);
-
- di.di_flags = GFS_DIF_JDATA;
- di.di_payload_format = GFS_FORMAT_QU;
- di.di_type = GFS_FILE_REG;
-
- gfs_dinode_out(&di, buf);
-
- do_lseek(comline->fd, di.di_num.no_addr * comline->bsize);
- do_write(comline->fd, buf, comline->bsize);
-
-
- if (comline->debug) {
- printf("\nLicense dinode:\n");
- gfs_dinode_print(&di);
- }
-}
-
-/**
- * write_rgrps - write out the resource group headers
- * @comline: the command line
- * @rlist: the RG list
- *
- */
-
-void write_rgrps(commandline_t *comline, osi_list_t *rlist)
-{
- struct gfs_rgrp rg;
- struct gfs_meta_header rb;
- rgrp_list_t *rl;
- osi_list_t *tmp;
- char *buf, *data;
- unsigned int x, offset;
- unsigned int byte, bit;
- unsigned int blk_count;
- unsigned int r = 0;
-
- memset(&rb, 0, sizeof(struct gfs_meta_header));
- rb.mh_magic = GFS_MAGIC;
- rb.mh_type = GFS_METATYPE_RB;
- rb.mh_format = GFS_FORMAT_RB;
-
- for (tmp = rlist->next; tmp != rlist; tmp = tmp->next) {
- rl = osi_list_entry(tmp, rgrp_list_t, list);
-
- memset(&rg, 0, sizeof(struct gfs_rgrp));
- rg.rg_header.mh_magic = GFS_MAGIC;
- rg.rg_header.mh_type = GFS_METATYPE_RG;
- rg.rg_header.mh_format = GFS_FORMAT_RG;
- rg.rg_free = rl->ri->ri_data;
-
- type_zalloc(data, char, rl->ri->ri_bitbytes);
- type_zalloc(buf, char, rl->ri->ri_length * comline->bsize);
-
- /* Deal with the special case of the first dinode */
-
- if (!r) {
- if (comline->rgrp0_next > rl->ri->ri_data1 + rl->ri->ri_data)
- die("RG 0 is full.\n");
-
- /* Compensate for the hidden dinodes */
-
- *data = (GFS_BLKST_USEDMETA << 3 * GFS_BIT_SIZE) |
- (GFS_BLKST_USEDMETA << 2 * GFS_BIT_SIZE) |
- (GFS_BLKST_USEDMETA << GFS_BIT_SIZE) |
- GFS_BLKST_USEDMETA;
- *(data + 1) = GFS_BLKST_USEDMETA;
- rg.rg_free -= 5;
- rg.rg_useddi = 5;
-
- /* Compensate for the data the hidden dinodes point to */
-
- for (x = rl->ri->ri_data1 + 5; x < comline->rgrp0_next; x++) {
- byte = (x - rl->ri->ri_data1) / GFS_NBBY;
- bit = (x - rl->ri->ri_data1) % GFS_NBBY;
-
- data[byte] |= GFS_BLKST_USEDMETA << (bit * GFS_BIT_SIZE);
-
- rg.rg_free--;
- rg.rg_usedmeta++;
- }
- }
-
- gfs_rgrp_out(&rg, buf);
- offset = sizeof(struct gfs_rgrp);
- blk_count = 1;
-
- for (x = 0; x < rl->ri->ri_bitbytes; x++) {
- if (!(offset % comline->bsize)) {
- gfs_meta_header_out(&rb, buf + offset);
- offset += sizeof(struct gfs_meta_header);
- blk_count++;
- }
-
- buf[offset] = data[x];
- offset++;
- }
-
- if (blk_count != rl->ri->ri_length)
- die("RG underflow (rg = %u, blk_count = %u, rl->ri->ri_length = %u)\n",
- r, blk_count, rl->ri->ri_length);
-
- do_lseek(comline->fd, rl->ri->ri_addr * comline->bsize);
- do_write(comline->fd, buf, rl->ri->ri_length * comline->bsize);
-
- free(buf);
- free(data);
-
- if (comline->debug) {
- printf("\nResource group header %d\n", r);
- gfs_rgrp_print(&rg);
- }
-
- r++;
- }
-}
-
-/**
- * write_journals - write out the journal log headers
- * @comline: the command line
- * @rlist: the RG list
- *
- */
-
-void write_journals(commandline_t *comline, osi_list_t *jlist)
-{
- struct gfs_log_header lh;
- journal_list_t *jl;
- osi_list_t *tmp;
- char buf[comline->bsize];
- uint32 seg, sequence;
- int x = 0;
-
- srandom(time(NULL));
-
- for (tmp = jlist->next; tmp != jlist; tmp = tmp->next) {
- jl = osi_list_entry(tmp, journal_list_t, list);
-
- if (comline->debug)
- printf("Starting journal %d\n", x++);
-
- sequence = jl->segments / (RAND_MAX + 1.0) * random();
-
- for (seg = 0; seg < jl->segments; seg++) {
- memset(buf, 0, comline->bsize);
- memset(&lh, 0, sizeof(struct gfs_log_header));
-
- lh.lh_header.mh_magic = GFS_MAGIC;
- lh.lh_header.mh_type = GFS_METATYPE_LH;
- lh.lh_header.mh_format = GFS_FORMAT_LH;
- lh.lh_flags = GFS_LOG_HEAD_UNMOUNT;
- lh.lh_first = jl->start + seg * comline->seg_size;
- lh.lh_sequence = sequence;
- /* Don't care about tail */
- /* Don't care about log dump */
-
- gfs_log_header_out(&lh, buf);
- gfs_log_header_out(&lh, buf + GFS_BASIC_BLOCK - sizeof(struct gfs_log_header));
-
- do_lseek(comline->fd, lh.lh_first * comline->bsize);
- do_write(comline->fd, buf, comline->bsize);
-
- if (++sequence == jl->segments)
- sequence = 0;
-
- if (!(seg % 100))
- if (comline->debug)
- printf("seg #%u\n", seg);
- }
- }
-}
diff --git a/gfs/gfs_quota/Makefile b/gfs/gfs_quota/Makefile
deleted file mode 100644
index 3a4e114..0000000
--- a/gfs/gfs_quota/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-TARGET= gfs_quota
-
-SBINDIRT=$(TARGET)
-
-all: ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= check.o \
- main.o \
- names.o \
- ondisk.o \
- layout.o
-
-CFLAGS += -DHELPER_PROGRAM -D_FILE_OFFSET_BITS=64
-CFLAGS += -I${gfskincdir}
-CFLAGS += -I$(S)/../include
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L${libdir}
-
-${TARGET}: ${OBJS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs/gfs_quota/check.c b/gfs/gfs_quota/check.c
deleted file mode 100644
index a8fca14..0000000
--- a/gfs/gfs_quota/check.c
+++ /dev/null
@@ -1,651 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <time.h>
-#include <dirent.h>
-#include <limits.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "linux_endian.h"
-#include "gfs_ondisk.h"
-#define __user
-#include "gfs_ioctl.h"
-#include "osi_list.h"
-
-#include "gfs_quota.h"
-
-struct values {
- osi_list_t v_list;
-
- uint32_t v_id;
- int64_t v_blocks;
-};
-typedef struct values values_t;
-
-struct hardlinks {
- osi_list_t hl_list;
-
- ino_t hl_ino;
-};
-typedef struct hardlinks hardlinks_t;
-
-/**
- * add_value - add a ID / Allocated Blocks pair to the list
- * @list: the list
- * @id: the ID number
- * @blocks: the number of blocks to add
- *
- */
-
-static void
-add_value(osi_list_t *list, uint32_t id, int64_t blocks)
-{
- osi_list_t *tmp;
- values_t *v;
-
- for (tmp = list->next; tmp != list; tmp = tmp->next) {
- v = osi_list_entry(tmp, values_t, v_list);
- if (v->v_id != id)
- continue;
-
- v->v_blocks += blocks;
-
- osi_list_del(&v->v_list);
- osi_list_add(&v->v_list, list);
-
- return;
- }
-
- type_zalloc(v, values_t, 1);
-
- v->v_id = id;
- v->v_blocks = blocks;
-
- osi_list_add(&v->v_list, list);
-}
-
-/**
- * test_and_add_hard_link - Add a inode that has hard links to the list
- * @list: the list of inodes with hard links
- * @ino: the number of the inode to add
- *
- * Returns: Returns TRUE if the inode was already on the list, FALSE if it wasn't
- */
-
-static int
-test_and_add_hard_link(osi_list_t *list, ino_t ino)
-{
- osi_list_t *tmp;
- hardlinks_t *hl;
-
- for (tmp = list->next; tmp != list; tmp = tmp->next) {
- hl = osi_list_entry(tmp, hardlinks_t, hl_list);
- if (hl->hl_ino != ino)
- continue;
-
- return TRUE;
- }
-
- type_zalloc(hl, hardlinks_t, 1);
-
- hl->hl_ino = ino;
-
- osi_list_add(&hl->hl_list, list);
-
- return FALSE;
-}
-
-/**
- * scan_fs - recursively scan a filesystem and figure out what IDs have what
- * @device: the device the filesystem is on
- * @dirname: the name of the directory to read
- * @uid: returned list of UIDs for this FS
- * @gid: returned list of GIDs for this FS
- * @hl: returned list of hard links for this FS
- *
- */
-
-static void
-scan_fs(dev_t device, char *dirname,
- osi_list_t *uid, osi_list_t *gid, osi_list_t *hl)
-{
- DIR *dir;
- struct dirent *de;
- struct stat st;
- char *name;
- int error;
-
- dir = opendir(dirname);
- if (!dir)
- die("can't open directory %s: %s\n", dirname, strerror(errno));
-
- while ((de = readdir(dir))) {
- if (strcmp(de->d_name, "..") == 0)
- continue;
-
- type_alloc(name, char,
- strlen(dirname) + strlen(de->d_name) + 2);
- if (dirname[strlen(dirname) - 1] == '/')
- sprintf(name, "%s%s", dirname, de->d_name);
- else
- sprintf(name, "%s/%s", dirname, de->d_name);
-
- error = lstat(name, &st);
- if (error)
- die("can't stat file %s: %s\n", name, strerror(errno));
-
- if (st.st_dev != device)
- die("umount %s and try again\n", name);
-
- if (S_ISDIR(st.st_mode)) {
- if (strcmp(de->d_name, ".") == 0) {
- add_value(uid, st.st_uid, st.st_blocks);
- add_value(gid, st.st_gid, st.st_blocks);
- } else
- scan_fs(device, name, uid, gid, hl);
- } else if (st.st_nlink == 1 ||
- !test_and_add_hard_link(hl, st.st_ino)) {
- add_value(uid, st.st_uid, st.st_blocks);
- add_value(gid, st.st_gid, st.st_blocks);
- }
-
- free(name);
- }
-
- closedir(dir);
-}
-
-/**
- * read_quota_file - read the quota file and return list of its contents
- * @comline: the command line arguments
- * @uid: returned list of UIDs for the filesystem
- * @gid: returned list of GIDs for the filesystem
- *
- */
-
-static void
-read_quota_file(commandline_t *comline, osi_list_t *uid, osi_list_t *gid)
-{
- int fd;
- struct gfs_sb sb;
- uint64_t hidden_blocks;
- struct gfs_ioctl gi;
- char buf[sizeof(struct gfs_quota)];
- struct gfs_quota q;
- uint64_t offset = 0;
- uint32_t id;
- int error;
-
- fd = open(comline->filesystem, O_RDONLY);
- if (fd < 0)
- die("can't open file %s: %s\n", comline->filesystem,
- strerror(errno));
-
- check_for_gfs(fd, comline->filesystem);
-
- do_get_super(fd, &sb);
-
- hidden_blocks = compute_hidden_blocks(comline, fd);
-
- do {
- char *argv[] = {
- (char *)"do_hfile_read",
- (char *)"quota"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = buf;
- gi.gi_size = sizeof(struct gfs_quota);
- gi.gi_offset = offset;
-
- memset(buf, 0, sizeof(struct gfs_quota));
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error < 0)
- die("can't read quota file (%d): %s\n",
- error, strerror(errno));
-
- gfs_quota_in(&q, buf);
-
- id = (offset / sizeof(struct gfs_quota)) >> 1;
- if (!id)
- q.qu_value -= hidden_blocks;
- q.qu_value <<= sb.sb_bsize_shift - 9;
-
- if (q.qu_value) {
- if (id * sizeof(struct gfs_quota) * 2 == offset)
- add_value(uid, id, q.qu_value);
- else
- add_value(gid, id, q.qu_value);
- }
-
- offset += sizeof(struct gfs_quota);
- } while (error == sizeof(struct gfs_quota));
-
- close(fd);
-}
-
-/**
- * print_list - print the contents of an ID list
- * @str: a string describing the list
- * @list: the list
- *
- */
-
-static void
-print_list(const char *str, osi_list_t *list)
-{
-#if 0
- osi_list_t *tmp;
- values_t *v;
-
- for (tmp = list->next; tmp != list; tmp = tmp->next) {
- v = osi_list_entry(tmp, values_t, v_list);
- printf("%s %10u: %"PRId64"\n", str, v->v_id, v->v_blocks);
- }
-#endif
-}
-
-/**
- * do_compare - compare to ID lists and see if they match
- * @type: the type of list (UID or GID)
- * @fs_list: the list derived from scaning the FS
- * @qf_list: the list derived from reading the quota file
- *
- * Returns: TRUE if there was a mismatch
- */
-
-static int
-do_compare(const char *type, osi_list_t *fs_list, osi_list_t *qf_list)
-{
- osi_list_t *tmp1, *tmp2;
- values_t *v1, *v2;
- int found;
- int mismatch = FALSE;
-
- for (tmp1 = fs_list->next; tmp1 != fs_list; tmp1 = tmp1->next) {
- v1 = osi_list_entry(tmp1, values_t, v_list);
-
- found = FALSE;
-
- for (tmp2 = qf_list->next; tmp2 != qf_list; tmp2 = tmp2->next) {
- v2 = osi_list_entry(tmp2, values_t, v_list);
- if (v1->v_id != v2->v_id)
- continue;
-
- if (v1->v_blocks != v2->v_blocks) {
- printf("mismatch: %s %u: scan = %"PRId64", quotafile = %"PRId64"\n",
- type, v1->v_id,
- v1->v_blocks, v2->v_blocks);
- mismatch = TRUE;
- }
-
- osi_list_del(&v2->v_list);
- free(v2);
-
- found = TRUE;
- break;
- }
-
- if (!found) {
- printf("mismatch: %s %u: scan = %"PRId64", quotafile = %"PRId64"\n",
- type, v1->v_id,
- v1->v_blocks, (int64_t)0);
- mismatch = TRUE;
- }
- }
-
- for (tmp2 = qf_list->next; tmp2 != qf_list; tmp2 = tmp2->next) {
- v2 = osi_list_entry(tmp2, values_t, v_list);
-
- printf("mismatch: %s %u: scan = %"PRId64", quotafile = %"PRId64"\n",
- type, v2->v_id,
- (int64_t)0, v2->v_blocks);
- mismatch = TRUE;
- }
-
- return mismatch;
-}
-
-/**
- * verify_pathname - make sure the path on the command line is a mount point
- * @comline: the command line arguments
- *
- * Returns: the device the filesystem is on
- */
-
-static dev_t
-verify_pathname(commandline_t *comline)
-{
- struct stat st1, st2;
- dev_t device;
- char *name;
- int error;
-
- if (!*comline->filesystem)
- die("need a filesystem to work on\n");
-
- error = lstat(comline->filesystem, &st1);
- if (error)
- die("can't stat %s: %s\n", comline->filesystem,
- strerror(errno));
-
- if (!S_ISDIR(st1.st_mode))
- die("%s must be a directory\n", comline->filesystem);
-
- device = st1.st_dev;
-
- for (;;) {
- type_alloc(name, char, strlen(comline->filesystem) + 4);
- sprintf(name, "%s/..", comline->filesystem);
-
- error = lstat(name, &st2);
- if (error)
- die("can't stat %s: %s\n", name, strerror(errno));
-
- if (st2.st_dev != device || st2.st_ino == st1.st_ino) {
- free(name);
- break;
- }
-
- if (!realpath(name, comline->filesystem))
- die("error resolving filesystem pathname: %s\n",
- strerror(errno));
-
- free(name);
-
- st1 = st2;
- }
-
- return device;
-}
-
-/**
- * do_check - Check what's in the quota file
- * @comline: the struct containing the parsed command line arguments
- *
- */
-
-void
-do_check(commandline_t *comline)
-{
- dev_t device;
- osi_list_t fs_uid, fs_gid, qf_uid, qf_gid;
- osi_list_t hl;
- int mismatch;
-
- osi_list_init(&fs_uid);
- osi_list_init(&fs_gid);
- osi_list_init(&qf_uid);
- osi_list_init(&qf_gid);
- osi_list_init(&hl);
-
- device = verify_pathname(comline);
-
- scan_fs(device, comline->filesystem, &fs_uid, &fs_gid, &hl);
- read_quota_file(comline, &qf_uid, &qf_gid);
-
- print_list("fs user ", &fs_uid);
- print_list("fs group", &fs_gid);
- print_list("qf user ", &qf_uid);
- print_list("qf group", &qf_gid);
-
- mismatch = do_compare("user", &fs_uid, &qf_uid);
- mismatch |= do_compare("group", &fs_gid, &qf_gid);
-
- if (mismatch)
- exit(EXIT_FAILURE);
-}
-
-/**
- * set_list - write a list of IDs into the quota file
- * @comline: the command line arguments
- * @user: TRUE if this is a list of UIDs, FALSE if it is a list of GIDs
- * @list: the list of IDs and block counts
- * @multiplier: multiply block counts by this
- *
- */
-
-static void
-set_list(commandline_t *comline, int user, osi_list_t *list, int64_t multiplier)
-{
- int fd;
- struct gfs_sb sb;
- osi_list_t *tmp;
- values_t *v;
- uint64_t offset;
- int64_t value;
- struct gfs_ioctl gi;
- char buf[256];
- int error;
-
- fd = open(comline->filesystem, O_RDONLY);
- if (fd < 0)
- die("can't open file %s: %s\n", comline->filesystem,
- strerror(errno));
-
- check_for_gfs(fd, comline->filesystem);
- do_get_super(fd, &sb);
-
- for (tmp = list->next; tmp != list; tmp = tmp->next) {
- v = osi_list_entry(tmp, values_t, v_list);
-
- offset = (2 * (uint64_t)v->v_id + ((user) ? 0 : 1)) *
- sizeof(struct gfs_quota);
- offset += (unsigned long)(&((struct gfs_quota *)NULL)->qu_value);
-
- value = v->v_blocks * multiplier;
- value >>= sb.sb_bsize_shift - 9;
- value = cpu_to_gfs64(value);
-
- {
- char *argv[] = {
- (char *)"do_hfile_write",
- (char *)"quota"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&value;
- gi.gi_size = sizeof(int64_t);
- gi.gi_offset = offset;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != sizeof(int64_t))
- die("can't write quota file (%d): %s\n",
- error, strerror(errno));
- }
-
- sprintf(buf, "%s:%u",
- (user) ? "u" : "g",
- v->v_id);
-
- {
- char *argv[] = {
- (char *)"do_quota_refresh",
- (char *)buf
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error)
- die("can't refresh the quota LVB 1: %s\n",
- strerror(errno));
- }
- }
-
- close(fd);
-}
-
-/**
- * add_hidden - add in the hidden file block count into the root UID and GID
- * @comline: the command line arguments
- *
- */
-
-static void
-add_hidden(commandline_t *comline)
-{
- int fd;
- uint64_t hidden_blocks;
- uint64_t offset = (unsigned long)(&((struct gfs_quota *)NULL)->qu_value);
- struct gfs_ioctl gi;
- int64_t value;
- unsigned int pass = 0;
- char buf[256];
- int error;
-
- fd = open(comline->filesystem, O_RDONLY);
- if (fd < 0)
- die("can't open file %s: %s\n", comline->filesystem,
- strerror(errno));
-
- check_for_gfs(fd, comline->filesystem);
-
- hidden_blocks = compute_hidden_blocks(comline, fd);
-
- for (;;) {
- {
- char *argv[] = {
- (char *)"do_hfile_read",
- (char *)"quota"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&value;
- gi.gi_size = sizeof(int64_t);
- gi.gi_offset = offset;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != sizeof(int64_t))
- die("can't read quota file (%d): %s\n",
- error, strerror(errno));
- }
-
- value = gfs64_to_cpu(value);
- value += hidden_blocks;
- value = cpu_to_gfs64(value);
-
- {
- char *argv[] = {
- (char *)"do_hfile_write",
- (char *)"quota"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&value;
- gi.gi_size = sizeof(int64_t);
- gi.gi_offset = offset;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != sizeof(int64_t))
- die("can't write quota file (%d): %s\n",
- error, strerror(errno));
- }
-
- sprintf(buf, "%s:%u",
- (pass) ? "g" : "u",
- 0);
-
- {
- char *argv[] = {
- (char *)"do_quota_refresh",
- (char *)buf
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error)
- die("can't refresh the quota LVB 2: %s\n",
- strerror(errno));
- }
-
- if (!pass) {
- offset += sizeof(struct gfs_quota);
- pass = 1;
- } else
- break;
- }
-
- close(fd);
-}
-
-/**
- * do_init - initialize the quota file
- * @comline: the command line arguments
- *
- */
-
-void
-do_init(commandline_t *comline)
-{
- dev_t device;
- osi_list_t fs_uid, fs_gid, qf_uid, qf_gid;
- osi_list_t hl;
- values_t *v;
-
- osi_list_init(&fs_uid);
- osi_list_init(&fs_gid);
- osi_list_init(&qf_uid);
- osi_list_init(&qf_gid);
- osi_list_init(&hl);
-
- device = verify_pathname(comline);
-
- scan_fs(device, comline->filesystem, &fs_uid, &fs_gid, &hl);
- read_quota_file(comline, &qf_uid, &qf_gid);
-
- type_zalloc(v, values_t, 1);
- v->v_id = 0;
- v->v_blocks = 0;
- osi_list_add(&v->v_list, &qf_uid);
-
- type_zalloc(v, values_t, 1);
- v->v_id = 0;
- v->v_blocks = 0;
- osi_list_add(&v->v_list, &qf_gid);
-
- print_list("fs user ", &fs_uid);
- print_list("fs group", &fs_gid);
- print_list("qf user ", &qf_uid);
- print_list("qf group", &qf_gid);
-
- /* Yes, do the set_list() calls twice. Gotta get around
- the fact that writing to the quota file causes
- quota changes */
-
- set_list(comline, TRUE, &qf_uid, 0);
- set_list(comline, FALSE, &qf_gid, 0);
- set_list(comline, TRUE, &fs_uid, 1);
- set_list(comline, FALSE, &fs_gid, 1);
-
- do_sync(comline);
- do_sync(comline);
-
- set_list(comline, TRUE, &qf_uid, 0);
- set_list(comline, FALSE, &qf_gid, 0);
- set_list(comline, TRUE, &fs_uid, 1);
- set_list(comline, FALSE, &fs_gid, 1);
-
- do_sync(comline);
-
- add_hidden(comline);
-
- do_sync(comline);
-
- do_check(comline);
-}
diff --git a/gfs/gfs_quota/gfs_quota.h b/gfs/gfs_quota/gfs_quota.h
deleted file mode 100644
index ea224b1..0000000
--- a/gfs/gfs_quota/gfs_quota.h
+++ /dev/null
@@ -1,98 +0,0 @@
-#ifndef __GFS_QUOTA_DOT_H__
-#define __GFS_QUOTA_DOT_H__
-
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#define die(fmt, args...) \
-do { \
- fprintf(stderr, "%s: ", prog_name); \
- fprintf(stderr, fmt, ##args); \
- exit(EXIT_FAILURE); \
-} while (0)
-
-#define type_zalloc(ptr, type, count) \
-do { \
- (ptr) = (type *)malloc(sizeof(type) * (count)); \
- if ((ptr)) \
- memset((char *)(ptr), 0, sizeof(type) * (count)); \
- else \
- die("unable to allocate memory on line %d of file %s\n", \
- __LINE__, __FILE__); \
-} while (0)
-
-#define type_alloc(ptr, type, count) \
-do { \
- (ptr) = (type *)malloc(sizeof(type) * (count)); \
- if (!(ptr)) \
- die("unable to allocate memory on line %d of file %s\n", \
- __LINE__, __FILE__); \
-} while (0)
-
-#define GQ_OP_LIST (12)
-#define GQ_OP_SYNC (13)
-#define GQ_OP_GET (14)
-#define GQ_OP_LIMIT (15)
-#define GQ_OP_WARN (16)
-#define GQ_OP_CHECK (17)
-#define GQ_OP_INIT (18)
-
-#define GQ_ID_USER (23)
-#define GQ_ID_GROUP (24)
-
-#define GQ_UNITS_MEGABYTE (0)
-#define GQ_UNITS_KILOBYTE (34)
-#define GQ_UNITS_FSBLOCK (35)
-#define GQ_UNITS_BASICBLOCK (36)
-
-struct commandline {
- unsigned int operation;
-
- uint64_t new_value;
- int new_value_set;
-
- unsigned int id_type;
- uint32_t id;
-
- unsigned int units;
-
- int no_hidden_file_blocks;
- int numbers;
-
- char filesystem[PATH_MAX];
-};
-typedef struct commandline commandline_t;
-
-extern char *prog_name;
-
-/* main.c */
-
-void check_for_gfs(int fd, char *path);
-void do_get_super(int fd, struct gfs_sb *sb);
-void do_sync(commandline_t *comline);
-uint64_t compute_hidden_blocks(commandline_t *comline, int fd);
-void print_quota(commandline_t *comline,
- int user, uint32_t id,
- struct gfs_quota *q,
- struct gfs_sb *sb);
-
-/* check.c */
-
-void do_check(commandline_t *comline);
-void do_init(commandline_t *comline);
-
-/* names.c */
-
-uint32_t name_to_id(int user, char *name, int numbers);
-char *id_to_name(int user, uint32_t id, int numbers);
-
-/* layout.c */
-
-void print_quota_file(commandline_t *comline);
-#endif /* __GFS_QUOTA_DOT_H__ */
diff --git a/gfs/gfs_quota/layout.c b/gfs/gfs_quota/layout.c
deleted file mode 100644
index f629bbb..0000000
--- a/gfs/gfs_quota/layout.c
+++ /dev/null
@@ -1,601 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-
-#define __user
-#include "gfs_ioctl.h"
-#include "gfs_ondisk.h"
-
-#include "osi_list.h"
-#include "linux_endian.h"
-
-#include "gfs_quota.h"
-
-#define LAYOUT_DATA_QUANTUM (4194304)
-
-struct extent {
- osi_list_t list;
-
- uint64_t offset;
- uint64_t start;
- unsigned int len;
-};
-typedef struct extent extent_t;
-
-struct buffer {
- osi_list_t list;
- uint64_t blkno;
- char *data;
-
- int touched;
-};
-typedef struct buffer buffer_t;
-
-struct lblk_range {
- osi_list_t list;
-
- uint64_t start;
- unsigned int len;
-};
-typedef struct lblk_range lblk_range_t;
-
-struct world {
- char *buf_data;
- unsigned int buf_size;
- int buf_count;
- osi_list_t blist;
- osi_list_t elist;
-
- struct gfs_sb sb;
- unsigned int diptrs;
- unsigned int inptrs;
- unsigned int jbsize;
- unsigned int hash_bsize;
- unsigned int hash_ptrs;
-
- buffer_t *dibh;
- struct gfs_dinode di;
-};
-typedef struct world world_t;
-
-typedef void (*pointer_call_t) (world_t *w,
- unsigned int height, uint64_t bn, void *data);
-
-static lblk_range_t *lblk_range_list;
-static unsigned int j_blk_size;
-
-/**
- * add_lblk_range - Add a range of logical block numbers to lblk_list
- * @lblk_list: the list to add to
- * @start: the starting block number of the range
- * @len: the length of the range
- *
- */
-
-static void
-add_lblk_range(lblk_range_t *lblk_list, uint64_t start, unsigned int len)
-{
- lblk_range_t *tmp;
-
- tmp = malloc(sizeof(lblk_range_t));
- if (!tmp)
- die("out of memory\n");
-
- tmp->start = start;
- tmp->len = len;
-
- osi_list_add_prev(&tmp->list, &lblk_list->list);
-}
-
-/**
- * build_list - build a list of buffer_t's to represent the data from the kernel
- * @w: the world structure
- *
- */
-
-static void
-build_list(world_t *w)
-{
- buffer_t *b;
- unsigned int x;
-
- for (x = 0; x < w->buf_count; x += sizeof(uint64_t) + w->sb.sb_bsize) {
- b = malloc(sizeof(buffer_t));
- if (!b)
- die("out of memory\n");
-
- memset(b, 0, sizeof(buffer_t));
-
- b->blkno = *(uint64_t *) (w->buf_data + x);
- b->data = w->buf_data + x + sizeof(uint64_t);
-
- osi_list_add_prev(&b->list, &w->blist);
- }
-
- if (x != w->buf_count)
- die("the kernel passed back unaligned data\n");
-}
-
-/**
- * check_list - check the buffers passed back by the kernel
- * @w: the world
- *
- */
-
-static void
-check_list(world_t *w)
-{
- osi_list_t *tmp;
- buffer_t *b;
- struct gfs_meta_header mh;
- const char *type;
-
- for (tmp = w->blist.next; tmp != &w->blist; tmp = tmp->next) {
- b = osi_list_entry(tmp, buffer_t, list);
-
- gfs_meta_header_in(&mh, b->data);
-
- if (mh.mh_magic != GFS_MAGIC)
- die("bad magic number on block\n");
-
- switch (mh.mh_type) {
- case GFS_METATYPE_DI:
- type = "GFS_METATYPE_DI";
-
- if (w->dibh)
- die("more than one dinode in file\n");
- else {
- w->dibh = b;
- gfs_dinode_in(&w->di, b->data);
-
- b->touched = TRUE;
- }
- break;
- case GFS_METATYPE_IN:
- type = "GFS_METATYPE_IN";
- break;
- case GFS_METATYPE_LF:
- type = "GFS_METATYPE_LF";
- break;
- case GFS_METATYPE_JD:
- type = "GFS_METATYPE_JD";
- break;
- case GFS_METATYPE_EA:
- type = "GFS_METATYPE_EA";
- break;
- case GFS_METATYPE_ED:
- die("GFS_METATYPE_ED shouldn't be present\n");
- default:
- die("strange meta type\n");
- }
- }
-
- if (!w->dibh)
- die("no dinode\n");
-}
-
-/**
- * getbuf - get the buffer_t for a given block number
- * @w: the world
- * @blkno: the block number
- *
- * Returns: the buffer_t
- */
-
-static buffer_t *
-getbuf(world_t *w, uint64_t blkno)
-{
- osi_list_t *tmp;
- buffer_t *b;
-
- for (tmp = w->blist.next; tmp != &w->blist; tmp = tmp->next) {
- b = osi_list_entry(tmp, buffer_t, list);
- if (b->blkno == blkno) {
- osi_list_del(&b->list);
- osi_list_add(&b->list, &w->blist);
-
- b->touched = TRUE;
-
- return b;
- }
- }
-
- die("buffer not found\n");
-}
-
-/**
- * recursive_scan - call a function for each block pointer in a file
- * @w: the world
- * @height: the height of the block being pointed to
- * @block: the block being pointed to
- * @pc: the function to call
- * @data: private data for the @pc function
- *
- */
-
-static void
-recursive_scan(world_t *w, unsigned int height,
- uint64_t block, pointer_call_t pc, void *data)
-{
- buffer_t *b = NULL;
- uint64_t *top, *bottom;
- uint64_t bn;
-
- if (!height) {
- b = w->dibh;
-
- top = (uint64_t *) (b->data + sizeof(struct gfs_dinode));
- bottom =
- (uint64_t *) (b->data + sizeof(struct gfs_dinode)) +
- w->diptrs;
- } else {
- b = getbuf(w, block);
-
- top = (uint64_t *) (b->data + sizeof(struct gfs_indirect));
- bottom =
- (uint64_t *) (b->data + sizeof(struct gfs_indirect)) +
- w->inptrs;
- }
-
- for (; top < bottom; top++) {
- bn = gfs64_to_cpu(*top);
-
- pc(w, height, bn, data);
-
- if (bn && height < w->di.di_height - 1)
- recursive_scan(w, height + 1, bn, pc, data);
- }
-}
-
-/**
- * add_extent - add an extend to the list of the file's data extents
- * @w: the world
- * @offset: the starting logical block of the extent
- * @start: the starting disk block of the extent
- * @len: the number of blocks in the extent
- *
- */
-
-static void
-add_extent(world_t *w, uint64_t offset, uint64_t start, unsigned int len)
-{
- extent_t *e;
-
- e = malloc(sizeof(extent_t));
- if (!e)
- die("out of memory\n");
-
- memset(e, 0, sizeof(extent_t));
-
- e->offset = offset;
- e->start = start;
- e->len = len;
-
- osi_list_add_prev(&e->list, &w->elist);
-}
-
-struct do_pf_s {
- unsigned int height;
- uint64_t offset;
- uint64_t start;
- uint64_t skip;
- unsigned int len;
-};
-typedef struct do_pf_s do_pf_t;
-
-/**
- * do_pf: called for every pointer in the file (prints/collects extent info)
- * @w: the world
- * @height: the height of the block containing the pointer
- * @bn: the contents of the pointer
- * @data: a do_pf_t structure
- *
- */
-
-static void
-do_pf(world_t *w, unsigned int height, uint64_t bn, void *data)
-{
- do_pf_t *pf = (do_pf_t *) data;
- unsigned int x;
- uint64_t skip;
-
- if (pf->height < height + 1)
- return;
-
- if (!bn) {
- if (pf->height == height + 1)
- pf->skip++;
- else {
- x = pf->height - height - 1;
- skip = w->inptrs;
- while (--x)
- skip *= w->inptrs;
- pf->skip += skip;
- }
-
- return;
- }
-
- if (pf->height == height + 1) {
- if (pf->start + pf->len == bn && pf->len == pf->skip) {
- pf->len++;
- pf->skip++;
- } else {
- if (pf->start) {
- if (pf->height == w->di.di_height) {
- add_extent(w, pf->offset, pf->start,
- pf->len);
- add_lblk_range(lblk_range_list,
- pf->offset, pf->len);
- }
- }
-
- pf->offset += pf->skip;
- pf->start = bn;
- pf->len = 1;
- pf->skip = 1;
- }
- }
-}
-
-/**
- * get_dblk_ranges - Run through the file and add valid data block ranges to
- * lblk_range_list
- * @w: the world
- *
- */
-
-static void
-get_dblk_ranges(world_t *w)
-{
- do_pf_t pf;
- unsigned int h;
-
- for (h = 1; h <= w->di.di_height; h++) {
-
- memset(&pf, 0, sizeof(do_pf_t));
- pf.height = h;
-
- recursive_scan(w, 0, 0, do_pf, &pf);
-
- if (pf.start) {
- if (h == w->di.di_height) {
- add_extent(w, pf.offset, pf.start, pf.len);
- add_lblk_range(lblk_range_list, pf.offset,
- pf.len);
- }
- }
- }
-}
-
-/**
- * compute_layout - Computes the layout and store the valid data page ranges
- * in lblk_range_list
- * @argc:
- * @argv:
- *
- */
-
-static void
-compute_layout(char *path)
-{
- world_t w;
- int fd;
- int retry = TRUE;
- struct gfs_ioctl gi;
- int error;
-
- memset(&w, 0, sizeof(world_t));
- w.buf_size = LAYOUT_DATA_QUANTUM;
- osi_list_init(&w.blist);
- osi_list_init(&w.elist);
-
-
- fd = open(path, O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", path, strerror(errno));
-
- check_for_gfs(fd, path);
-
- {
- char *argv[] = {
- (char *)"get_super"
- };
-
- gi.gi_argc = 1;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&w.sb;
- gi.gi_size = sizeof(struct gfs_sb);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("error doing get_super (%d): %s\n",
- error, strerror(errno));
- }
-
- w.diptrs = (w.sb.sb_bsize - sizeof(struct gfs_dinode)) /
- sizeof(uint64_t);
- w.inptrs = (w.sb.sb_bsize - sizeof(struct gfs_indirect)) /
- sizeof(uint64_t);
- w.jbsize = w.sb.sb_bsize - sizeof(struct gfs_meta_header);
- j_blk_size = w.jbsize;
- w.hash_bsize = w.sb.sb_bsize / 2;
- w.hash_ptrs = w.hash_bsize / sizeof(uint64_t);
-
- for (;;) {
- char *argv[] = {
- (char *)"get_file_meta_quota"
- };
-
- w.buf_data = malloc(w.buf_size);
- if (!w.buf_data)
- die("out of memory\n");
-
- gi.gi_argc = 1;
- gi.gi_argv = argv;
- gi.gi_data = w.buf_data;
- gi.gi_size = w.buf_size;
-
- w.buf_count = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (w.buf_count >= 0)
- break;
-
- if (errno == ENOMEM) {
- if (retry) {
- free(w.buf_data);
- w.buf_size += LAYOUT_DATA_QUANTUM;
- continue;
- } else
- die("%u bytes isn't enough memory\n",
- w.buf_size);
- }
- die("error doing get_file_meta: %s\n",
- strerror(errno));
- }
-
- build_list(&w);
- check_list(&w);
-
- get_dblk_ranges(&w);
-
- close(fd);
-}
-
-/**
- * print_quota_range - print the quota information in the given sequence of
- * blocks
- * @argc:
- * @argv:
- *
- */
-static void
-print_quota_range(commandline_t *comline, int type, uint64_t start,
- unsigned int len)
-{
- uint64_t blk_offt, blk_end_offt, offset;
- uint64_t quo;
- unsigned int rem;
- int fd;
- struct gfs_sb sb;
- struct gfs_ioctl gi;
- char buf[sizeof(struct gfs_quota)];
- struct gfs_quota q;
- uint64_t hidden_blocks = 0;
- uint32_t id;
- int error;
-
- blk_offt = start * (uint64_t)j_blk_size;
- blk_end_offt = blk_offt + (uint64_t)(len * j_blk_size);
-
- quo = blk_offt / (uint64_t)(2 * sizeof(struct gfs_quota));
- rem = blk_offt % (uint64_t)(2 * sizeof(struct gfs_quota));
-
- offset = type == GQ_ID_USER ? blk_offt :
- blk_offt + sizeof(struct gfs_quota);
-
- if (rem && type == GQ_ID_USER)
- offset = (quo + 1) * (uint64_t)(2 * sizeof(struct gfs_quota));
-
- if (rem && type == GQ_ID_GROUP) {
- if (rem <= sizeof(struct gfs_quota))
- offset = quo * (uint64_t)(2 * sizeof(struct gfs_quota))
- + sizeof(struct gfs_quota);
- else
- offset = (quo + 1) *
- (uint64_t)(2 * sizeof(struct gfs_quota)) +
- sizeof(struct gfs_quota);
- }
-
- fd = open(comline->filesystem, O_RDONLY);
- if (fd < 0)
- die("can't open file %s: %s\n", comline->filesystem,
- strerror(errno));
-
- check_for_gfs(fd, comline->filesystem);
- do_get_super(fd, &sb);
-
- if (comline->no_hidden_file_blocks)
- hidden_blocks = compute_hidden_blocks(comline, fd);
-
- do {
- char *argv[] = {
- (char *)"do_hfile_read",
- (char *)"quota"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = buf;
- gi.gi_size = sizeof(struct gfs_quota);
- gi.gi_offset = offset;
-
- memset(buf, 0, sizeof(struct gfs_quota));
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error < 0)
- die("can't read quota file: %s\n",
- strerror(errno));
-
- gfs_quota_in(&q, buf);
-
- id = (offset / sizeof(struct gfs_quota)) >> 1;
- if (!id && comline->no_hidden_file_blocks)
- q.qu_value -= hidden_blocks;
-
- if (q.qu_limit || q.qu_warn || q.qu_value)
- print_quota(comline, type == GQ_ID_GROUP ? FALSE : TRUE,
- id, &q, &sb);
-
- offset += 2 * sizeof(struct gfs_quota);
- } while ((error == sizeof(struct gfs_quota)) &&
- (offset < blk_end_offt));
-
- close(fd);
-}
-
-void
-print_quota_file(commandline_t *comline)
-{
- lblk_range_t lblk_range, *bar;
- osi_list_t *t, *x;
-
- lblk_range_list = &lblk_range;
-
- osi_list_init(&lblk_range_list->list);
-
- compute_layout(comline->filesystem);
-
- if (osi_list_empty(&lblk_range_list->list)) {
- /* stuffed quota inode */
- print_quota_range(comline, GQ_ID_USER, 0, 1);
- print_quota_range(comline, GQ_ID_GROUP, 0, 1);
- } else {
- /* print the user quotas */
- osi_list_foreach(t, &lblk_range_list->list) {
- bar = osi_list_entry(t, lblk_range_t, list);
- print_quota_range(comline, GQ_ID_USER, bar->start,
- bar->len);
- }
- /* print the group quotas */
- osi_list_foreach(t, &lblk_range_list->list) {
- bar = osi_list_entry(t, lblk_range_t, list);
- print_quota_range(comline, GQ_ID_GROUP, bar->start,
- bar->len);
- }
- /* free the list */
- osi_list_foreach_safe(t, &lblk_range_list->list, x) {
- bar = osi_list_entry(t, lblk_range_t, list);
- osi_list_del(&bar->list);
- free(bar);
- }
- }
-}
diff --git a/gfs/gfs_quota/main.c b/gfs/gfs_quota/main.c
deleted file mode 100644
index 0bc6d51..0000000
--- a/gfs/gfs_quota/main.c
+++ /dev/null
@@ -1,759 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <time.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/mount.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "linux_endian.h"
-#include "gfs_ondisk.h"
-#define __user
-#include "gfs_ioctl.h"
-
-#include "copyright.cf"
-
-#include "gfs_quota.h"
-
-/* Constants */
-
-#define OPTION_STRING ("bdf:g:hkl:mnsu:V")
-
-char *prog_name;
-
-/**
- * print_usage - print usage info to the user
- *
- */
-
-static void
-print_usage(void)
-{
- printf("Usage:\n");
- printf("\n");
- printf("%s <list|sync|get|limit|warn|check|init> [options]\n",
- prog_name);
- printf("\n");
- printf("Actions:\n");
- printf(" list list the whole quota file\n");
- printf(" sync sync out unsynced quotas\n");
- printf(" get get quota values for an ID\n");
- printf(" limit set a quota limit value for an ID\n");
- printf(" warn set a quota warning value for an ID\n");
- printf(" check check the quota file\n");
- printf(" init initialize the quota file\n");
- printf("\n");
- printf("Options:\n");
- printf(" -b sizes are in FS blocks\n");
- printf(" -d don't include hidden inode blocks\n");
- printf(" -f <directory> the filesystem to work on\n");
- printf(" -g <gid> get/set a group ID\n");
- printf(" -h Print this help, then exit\n");
- printf(" -k sizes are in KB\n");
- printf(" -l <size> the new limit or warn value\n");
- printf(" -m sizes are in MB\n");
- printf(" -n print out UID/GID numbers instead of names\n");
- printf(" -s sizes are in 512-byte blocks\n");
- printf(" -u <uid> get/set a user ID\n");
- printf(" -V Print program version information, then exit\n");
-}
-
-/**
- * check_for_gfs - Check to see if a descriptor is a file on a GFS filesystem
- * @fd: the file descriptor
- * @path: the path used to open the descriptor
- *
- */
-
-void
-check_for_gfs(int fd, char *path)
-{
- unsigned int magic = 0;
- int error;
-
- error = ioctl(fd, GFS_IOCTL_IDENTIFY, &magic);
- if (error || magic != GFS_MAGIC)
- die("%s is not a GFS file/filesystem\n", path);
-}
-
-/**
- * do_get_super
- * fd:
- * sb:
- *
- */
-
-void
-do_get_super(int fd, struct gfs_sb *sb)
-{
- struct gfs_ioctl gi;
- char *argv[] = {
- (char *)"get_super"
- };
- int error;
-
- gi.gi_argc = 1;
- gi.gi_argv = argv;
- gi.gi_data = (char *)sb;
- gi.gi_size = sizeof(struct gfs_sb);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("can't read the superblock (%d): %s\n",
- error, strerror(errno));
-}
-
-/**
- * decode_arguments - parse command line arguments
- * @argc: well, it's argc...
- * @argv: well, it's argv...
- * @comline: the structure filled in with the parsed arguments
- *
- * Function description
- *
- * Returns: what is returned
- */
-
-static void
-decode_arguments(int argc, char *argv[], commandline_t *comline)
-{
- int cont = TRUE;
- int optchar;
-
- while (cont) {
- optchar = getopt(argc, argv, OPTION_STRING);
-
- switch (optchar) {
- case 'u':
- comline->id_type = GQ_ID_USER;
- comline->id = name_to_id(TRUE, optarg, comline->numbers);
- break;
-
- case 'g':
- comline->id_type = GQ_ID_GROUP;
- comline->id = name_to_id(FALSE, optarg, comline->numbers);
- break;
-
- case 'l':
- if (!isdigit(*optarg))
- die("argument to -l must be a number\n");
- sscanf(optarg, "%"SCNu64, &comline->new_value);
- comline->new_value_set = TRUE;
- break;
-
- case 'f':
- if (!realpath(optarg, comline->filesystem))
- die("can't find %s: %s\n", optarg,
- strerror(errno));
- break;
-
- case 'm':
- comline->units = GQ_UNITS_MEGABYTE;
- break;
-
- case 'k':
- comline->units = GQ_UNITS_KILOBYTE;
- break;
-
- case 'b':
- comline->units = GQ_UNITS_FSBLOCK;
- break;
-
- case 's':
- comline->units = GQ_UNITS_BASICBLOCK;
- break;
-
- case 'd':
- comline->no_hidden_file_blocks = TRUE;
- break;
-
- case 'n':
- comline->numbers = TRUE;
- break;
-
- case 'V':
- printf("gfs_quota %s (built %s %s)\n", RELEASE_VERSION,
- __DATE__, __TIME__);
- printf("%s\n", REDHAT_COPYRIGHT);
- exit(EXIT_SUCCESS);
- break;
-
- case 'h':
- print_usage();
- exit(EXIT_SUCCESS);
- break;
-
- case ':':
- case '?':
- fprintf(stderr, "Please use '-h' for usage.\n");
- exit(EXIT_FAILURE);
- break;
-
- case EOF:
- cont = FALSE;
- break;
-
- default:
- die("unknown option: %c\n", optchar);
- break;
- };
- }
-
- while (optind < argc) {
- if (strcmp(argv[optind], "list") == 0 ||
- strcmp(argv[optind], "dump") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_LIST;
- } else if (strcmp(argv[optind], "sync") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_SYNC;
- } else if (strcmp(argv[optind], "get") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_GET;
- } else if (strcmp(argv[optind], "limit") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_LIMIT;
- } else if (strcmp(argv[optind], "warn") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_WARN;
- } else if (strcmp(argv[optind], "check") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_CHECK;
- } else if (strcmp(argv[optind], "init") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_INIT;
- } else
- die("unknown option %s\n", argv[optind]);
-
- optind++;
- }
-}
-
-/**
- * compute_hidden_blocks - figure out how much space the hidden inodes use
- * @comline: the struct containing the parsed command line arguments
- * @fd: the filedescriptor to the filesystem
- *
- * Returns: the number of hidden blocks
- */
-
-uint64_t
-compute_hidden_blocks(commandline_t *comline, int fd)
-{
- struct gfs_dinode di;
- struct gfs_ioctl gi;
- uint64_t hidden_blocks = 0;
- int error;
-
- {
- char *argv[] = {
- (char *)"get_hfile_stat",
- (char *)"jindex"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&di;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("can't stat jindex (%d): %s\n",
- error, strerror(errno));
- hidden_blocks += di.di_blocks;
- }
-
- {
- char *argv[] = {
- (char *)"get_hfile_stat",
- (char *)"rindex"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&di;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("can't stat rindex (%d): %s\n",
- error, strerror(errno));
- hidden_blocks += di.di_blocks;
- }
-
- {
- char *argv[] = {
- (char *)"get_hfile_stat",
- (char *)"quota"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&di;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("can't stat quota file (%d): %s\n",
- error, strerror(errno));
- hidden_blocks += di.di_blocks;
- }
-
- {
- char *argv[] = {
- (char *)"get_hfile_stat",
- (char *)"license"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&di;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("can't stat license file (%d): %s\n",
- error, strerror(errno));
- hidden_blocks += di.di_blocks;
- }
-
- return hidden_blocks;
-}
-
-/**
- * print_quota - Print out a quota entry
- * @comline: the struct containing the parsed command line arguments
- * @user: TRUE if this is a user quota, FALSE if it's a group quota
- * @id: the ID
- * @q: the quota value
- * @sb: the superblock of the filesystem this quota belongs to
- *
- */
-
-void
-print_quota(commandline_t *comline,
- int user, uint32_t id,
- struct gfs_quota *q,
- struct gfs_sb *sb)
-{
- printf("%-5s %10s: ", (user) ? "user" : "group",
- id_to_name(user, id, comline->numbers));
-
- switch (comline->units) {
- case GQ_UNITS_MEGABYTE:
- printf("limit: %-10.1f warn: %-10.1f value: %-10.1f\n",
- (double) q->qu_limit * sb->sb_bsize / 1048576,
- (double) q->qu_warn * sb->sb_bsize / 1048576,
- (double) q->qu_value * sb->sb_bsize / 1048576);
- break;
-
- case GQ_UNITS_KILOBYTE:
- if (sb->sb_bsize == 512)
- printf("limit: %-10"PRIu64" warn: %-10"PRIu64"value: %-10"PRId64"\n",
- q->qu_limit / 2,
- q->qu_warn / 2,
- q->qu_value / 2);
- else
- printf("limit: %-10"PRIu64" warn: %-10"PRIu64"value: %-10"PRId64"\n",
- q->qu_limit << (sb->sb_bsize_shift - 10),
- q->qu_warn << (sb->sb_bsize_shift - 10),
- q->qu_value << (sb->sb_bsize_shift - 10));
- break;
-
- case GQ_UNITS_FSBLOCK:
- printf("limit: %-10"PRIu64" warn: %-10"PRIu64" value: %-10"PRId64"\n",
- q->qu_limit, q->qu_warn, q->qu_value);
- break;
-
- case GQ_UNITS_BASICBLOCK:
- printf("limit: %-10"PRIu64" warn: %-10"PRIu64" value: %-10"PRId64"\n",
- q->qu_limit << (sb->sb_bsize_shift - 9),
- q->qu_warn << (sb->sb_bsize_shift - 9),
- q->qu_value << (sb->sb_bsize_shift - 9));
- break;
-
- default:
- die("bad units\n");
- break;
- }
-}
-
-/**
- * do_list - List all the quota data for a filesystem
- * @comline: the struct containing the parsed command line arguments
- *
- */
-
-static void
-do_list(commandline_t *comline)
-{
- print_quota_file(comline);
-}
-
-/**
- * do_sync_one - sync the quotas on one GFS filesystem
- * @path: a file/directory in the filesystem
- *
- */
-
-static void
-do_sync_one(char *filesystem)
-{
- int fd;
- char *argv[] = {
- (char *)"do_quota_sync"
- };
- struct gfs_ioctl gi;
- int error;
-
- fd = open(filesystem, O_RDONLY);
- if (fd < 0)
- die("can't open file %s: %s\n", filesystem, strerror(errno));
-
- check_for_gfs(fd, filesystem);
-
- gi.gi_argc = 1;
- gi.gi_argv = argv;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error)
- die("can't sync quotas: %s\n", strerror(errno));
-
- close(fd);
-}
-
-/**
- * do_sync - sync out unsyned quotas
- * @comline: the struct containing the parsed command line arguments
- *
- */
-
-void
-do_sync(commandline_t *comline)
-{
- sync();
-
- if (*comline->filesystem)
- do_sync_one(comline->filesystem);
- else {
- char buf[256], device[256], path[256], type[256];
- FILE *file;
-
- file = fopen("/proc/mounts", "r");
- if (!file)
- die("can't open /proc/mounts: %s\n", strerror(errno));
-
- while (fgets(buf, 256, file)) {
- if (sscanf(buf, "%s %s %s", device, path, type) != 3)
- continue;
- if (strcmp(type, "gfs") != 0)
- continue;
-
- do_sync_one(path);
- }
-
- fclose(file);
- }
-}
-
-/**
- * do_get_one - Get a quota value from one FS
- * @comline: the struct containing the parsed command line arguments
- * @filesystem: the filesystem to get from
- *
- */
-
-static void
-do_get_one(commandline_t *comline, char *filesystem)
-{
- int fd;
- char buf[256];
- struct gfs_ioctl gi;
- struct gfs_quota q;
- struct gfs_sb sb;
- int error;
-
- fd = open(filesystem, O_RDONLY);
- if (fd < 0)
- die("can't open file %s: %s\n", comline->filesystem,
- strerror(errno));
-
- check_for_gfs(fd, filesystem);
-
- sprintf(buf, "%s:%u",
- (comline->id_type == GQ_ID_USER) ? "u" : "g",
- comline->id);
-
- {
- char *argv[] = {
- (char *)"do_quota_read",
- (char *)buf
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&q;
- gi.gi_size = sizeof(struct gfs_quota);
-
- memset(&q, 0, sizeof(struct gfs_quota));
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error < 0)
- die("can't get quota info (%d): %s\n",
- error, strerror(errno));
- }
-
- if (comline->no_hidden_file_blocks && !comline->id)
- q.qu_value -= compute_hidden_blocks(comline, fd);
-
- do_get_super(fd, &sb);
-
- print_quota(comline,
- (comline->id_type == GQ_ID_USER), comline->id,
- &q, &sb);
-
- close(fd);
-}
-
-/**
- * do_get - Get a quota value
- * @comline: the struct containing the parsed command line arguments
- *
- */
-
-static void
-do_get(commandline_t *comline)
-{
- int first = TRUE;
-
- if (*comline->filesystem)
- do_get_one(comline, comline->filesystem);
- else {
- char buf[256], device[256], path[256], type[256];
- FILE *file;
-
- file = fopen("/proc/mounts", "r");
- if (!file)
- die("can't open /proc/mounts: %s\n", strerror(errno));
-
- while (fgets(buf, 256, file)) {
- if (sscanf(buf, "%s %s %s", device, path, type) != 3)
- continue;
- if (strcmp(type, "gfs") != 0)
- continue;
-
- if (first)
- first = FALSE;
- else
- printf("\n");
-
- printf("%s:\n", path);
- do_get_one(comline, path);
- }
-
- fclose(file);
- }
-}
-
-/**
- * do_set - Set a quota value
- * @comline: the struct containing the parsed command line arguments
- *
- */
-
-static void
-do_set(commandline_t *comline)
-{
- int fd;
- uint64_t offset;
- struct gfs_ioctl gi;
- struct gfs_sb sb;
- uint64_t new_value;
- char buf[256];
- int error;
-
- if (!*comline->filesystem)
- die("need a filesystem to work on\n");
- if (!comline->new_value_set)
- die("need a new value\n");
-
- fd = open(comline->filesystem, O_RDONLY);
- if (fd < 0)
- die("can't open file %s: %s\n", comline->filesystem,
- strerror(errno));
-
- check_for_gfs(fd, comline->filesystem);
-
- switch (comline->id_type) {
- case GQ_ID_USER:
- offset = (2 * (uint64_t)comline->id) * sizeof(struct gfs_quota);
- break;
-
- case GQ_ID_GROUP:
- offset = (2 * (uint64_t)comline->id + 1) * sizeof(struct gfs_quota);
- break;
-
- default:
- die("invalid user/group ID\n");
- break;
- }
-
- switch (comline->operation) {
- case GQ_OP_LIMIT:
- offset += (unsigned long)(&((struct gfs_quota *) NULL)->qu_limit);
- break;
-
- case GQ_OP_WARN:
- offset += (unsigned long)(&((struct gfs_quota *) NULL)->qu_warn);
- break;
-
- default:
- die("invalid operation\n");
- break;
- };
-
- do_get_super(fd, &sb);
-
- switch (comline->units) {
- case GQ_UNITS_MEGABYTE:
- new_value = comline->new_value << (20 - sb.sb_bsize_shift);
- break;
-
- case GQ_UNITS_KILOBYTE:
- if (sb.sb_bsize == 512)
- new_value = comline->new_value * 2;
- else
- new_value = comline->new_value >> (sb.sb_bsize_shift - 10);
- break;
-
- case GQ_UNITS_FSBLOCK:
- new_value = comline->new_value;
- break;
-
- case GQ_UNITS_BASICBLOCK:
- new_value = comline->new_value >> (sb.sb_bsize_shift - 9);
- break;
-
- default:
- die("bad units\n");
- break;
- }
-
- new_value = cpu_to_gfs64(new_value);
-
- {
- char *argv[] = {
- (char *)"do_hfile_write",
- (char *)"quota"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&new_value;
- gi.gi_size = sizeof(uint64_t);
- gi.gi_offset = offset;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("can't write quota file (%d): %s\n",
- error, strerror(errno));
- }
-
- sprintf(buf, "%s:%u",
- (comline->id_type == GQ_ID_USER) ? "u" : "g",
- comline->id);
-
- {
- char *argv[] = {
- (char *)"do_quota_refresh",
- (char *)buf
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error)
- die("can't refresh the quota LVB: %s\n",
- strerror(errno));
- }
-
- close(fd);
-}
-
-/**
- * main - Do everything
- * @argc: well, it's argc...
- * @argv: well, it's argv...
- *
- * Returns: exit status
- */
-
-int
-main(int argc, char *argv[])
-{
- commandline_t comline;
-
- prog_name = argv[0];
-
- memset(&comline, 0, sizeof(commandline_t));
-
- decode_arguments(argc, argv, &comline);
-
- switch (comline.operation) {
- case GQ_OP_LIST:
- do_list(&comline);
- break;
-
- case GQ_OP_SYNC:
- do_sync(&comline);
- break;
-
- case GQ_OP_GET:
- do_get(&comline);
- break;
-
- case GQ_OP_LIMIT:
- case GQ_OP_WARN:
- do_set(&comline);
- break;
-
- case GQ_OP_CHECK:
- do_sync(&comline);
- do_sync(&comline);
- do_check(&comline);
- break;
-
- case GQ_OP_INIT:
- do_sync(&comline);
- do_sync(&comline);
- do_init(&comline);
- break;
-
- default:
- if (!comline.id_type) {
- comline.id_type = GQ_ID_USER;
- comline.id = geteuid();
- }
- do_get(&comline);
- break;
- }
-
- exit(EXIT_SUCCESS);
-}
diff --git a/gfs/gfs_quota/names.c b/gfs/gfs_quota/names.c
deleted file mode 100644
index fd4ade8..0000000
--- a/gfs/gfs_quota/names.c
+++ /dev/null
@@ -1,84 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <time.h>
-#include <dirent.h>
-#include <limits.h>
-#include <pwd.h>
-#include <grp.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "gfs_ondisk.h"
-
-#include "gfs_quota.h"
-
-uint32_t
-name_to_id(int user, char *name, int numbers)
-{
- struct passwd *u;
- struct group *g;
- uint32_t id;
- int ok = FALSE;
-
- if (numbers) {
- } else if (user) {
- u = getpwnam(name);
- if (u) {
- id = u->pw_uid;
- ok = TRUE;
- }
- } else {
- g = getgrnam(name);
- if (g) {
- id = g->gr_gid;
- ok = TRUE;
- }
- }
-
- if (!ok) {
- if (!isdigit(name[0]))
- die("can't find %s %s\n",
- (user) ? "user" : "group",
- name);
- sscanf(name, "%u", &id);
- }
-
- return id;
-}
-
-char *
-id_to_name(int user, uint32_t id, int numbers)
-{
- struct passwd *u;
- struct group *g;
- static char name[256];
- int ok = FALSE;
-
- if (numbers) {
- } else if (user) {
- u = getpwuid(id);
- if (u) {
- strcpy(name, u->pw_name);
- ok = TRUE;
- }
- } else {
- g = getgrgid(id);
- if (g) {
- strcpy(name, g->gr_name);
- ok = TRUE;
- }
- }
-
- if (!ok)
- sprintf(name, "%u", id);
-
- return name;
-}
diff --git a/gfs/gfs_quota/ondisk.c b/gfs/gfs_quota/ondisk.c
deleted file mode 100644
index 191c688..0000000
--- a/gfs/gfs_quota/ondisk.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "linux_endian.h"
-#include "gfs_ondisk.h"
-
-#define printk printf
-#define pv(struct, member, fmt) printf(" "#member" = "fmt"\n", struct->member);
-
-#define ENTER(x)
-#define EXIT(x)
-#define RET(x) return
-#define RETURN(x, y) return y
-
-#define WANT_GFS_CONVERSION_FUNCTIONS
-#include "gfs_ondisk.h"
diff --git a/gfs/gfs_tool/Makefile b/gfs/gfs_tool/Makefile
deleted file mode 100644
index 31a8cf8..0000000
--- a/gfs/gfs_tool/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-TARGET= gfs_tool
-
-SBINDIRT=$(TARGET)
-
-all: ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= counters.o \
- df.o \
- layout.o \
- main.o \
- misc.o \
- ondisk.o \
- sb.o \
- tune.o \
- util.o
-
-CFLAGS += -D_FILE_OFFSET_BITS=64
-CFLAGS += -I${gfskincdir}
-CFLAGS += -I$(S)/../include
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L${libdir}
-
-${TARGET}: ${OBJS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs/gfs_tool/counters.c b/gfs/gfs_tool/counters.c
deleted file mode 100644
index 80f3de3..0000000
--- a/gfs/gfs_tool/counters.c
+++ /dev/null
@@ -1,204 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-
-#define __user
-#include "gfs_ioctl.h"
-#include "osi_list.h"
-
-#include "gfs_tool.h"
-
-#define SIZE (4096)
-
-struct token_list {
- osi_list_t list;
- char *token;
- unsigned int last;
-};
-
-static osi_list_decl(token_list);
-
-/**
- * find_update_last - find and update the last value of a token
- * @token: the token to look for
- * @this: the current value of the token
- *
- * Returns: the last value of the token
- */
-
-static unsigned int
-find_update_last(char *token, unsigned int this)
-{
- osi_list_t *tmp, *head;
- struct token_list *tl;
- unsigned int last;
-
- for (head = &token_list, tmp = head->next; tmp != head; tmp = tmp->next) {
- tl = osi_list_entry(tmp, struct token_list, list);
- if (strcmp(tl->token, token))
- continue;
-
- last = tl->last;
- tl->last = this;
- return last;
- }
-
- tl = malloc(sizeof (struct token_list) + strlen(token) + 1);
- if (!tl)
- die("out of memory\n");
- tl->token = (char *) (tl + 1);
- strcpy(tl->token, token);
- tl->last = this;
- osi_list_add(&tl->list, &token_list);
-
- return 0;
-}
-
-/**
- * print_line - print out a counter
- * @token: the name of the counter
- * @description: the text description of the counter
- * @option: an optional modifier
- * @value: the value of the counter
- *
- */
-
-static void
-print_line(char *token, char *description, char *option, char *value)
-{
- static unsigned int sd_log_seg_free;
- unsigned int this, last;
-
- if (!strcmp(token, "sd_log_seg_free"))
- sscanf(value, "%u", &sd_log_seg_free);
-
- else if (!strcmp(token, "ji_nsegment")) {
- sscanf(value, "%u", &this);
- printf("%39s %.2f%%\n",
- "log space used",
- 100.0 * (this - sd_log_seg_free) / this);
-
- } else if (continuous && !strcmp(option, "diff")) {
- sscanf(value, "%u", &this);
- last = find_update_last(token, this);
- printf("%39s %-10s %d/s\n",
- description, value,
- (this - last + interval - 1) / interval);
-
- } else
- printf("%39s %s\n", description, value);
-}
-
-/**
- * parse_line: break up a chunk of data into counter fields
- * @buf: the data
- * @count: the number of bytes of data
- *
- */
-
-static void
-parse_lines(char *buf, unsigned int count)
-{
- char line[SIZE];
- char part1[SIZE], part2[SIZE], part3[SIZE], part4[SIZE];
- char *c, *c2;
- unsigned int x;
-
- printf("\n");
-
- while (count) {
- for (c = line; count; c++) {
- *c = *buf;
- buf++;
- count--;
- if (*c == '\n')
- break;
- }
- *c = 0;
-
- *part1 = *part2 = *part3 = *part4 = 0;
-
- for (c = line, x = 0; (c2 = strsep(&c, ":")); x++) {
- if (!*c2)
- continue;
-
- if (x == 0)
- strcpy(part1, c2);
- else if (x == 1)
- strcpy(part2, c2);
- else if (x == 2)
- strcpy(part3, c2);
- else
- strcpy(part4, c2);
- }
-
- if (x == 4)
- print_line(part1, part2, part3, part4);
- }
-}
-
-/**
- * print_counters - print out the current countersable parameters for a filesystem
- * @argc:
- * @argv:
- *
- */
-
-void
-print_counters(int argc, char **argv)
-{
- char *fs;
- int fd;
-
- if (optind < argc)
- fs = argv[optind++];
- else
- die("Usage: gfs_tool counters <mountpoint>\n");
-
- fd = open(fs, O_RDONLY);
- if (fd < 0)
- die("can't open file %s: %s\n", fs, strerror(errno));
-
- check_for_gfs(fd, fs);
-
- for (;;) {
- struct gfs_ioctl gi;
- char *local_argv[] = {
- (char *)"get_counters"
- };
- char data[SIZE];
- int error;
-
- gi.gi_argc = 1;
- gi.gi_argv = local_argv;
- gi.gi_data = data;
- gi.gi_size = SIZE;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error < 0)
- die("can't get counters: %s\n", strerror(errno));
-
- if (debug)
- error = write(STDOUT_FILENO, data, error);
-
- parse_lines(data, error);
-
- if (!continuous)
- break;
-
- fflush(stdout);
-
- sleep(interval);
- }
-
- close(fd);
-}
diff --git a/gfs/gfs_tool/decipher_lockstate_dump b/gfs/gfs_tool/decipher_lockstate_dump
deleted file mode 100644
index 10080a5..0000000
--- a/gfs/gfs_tool/decipher_lockstate_dump
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/perl
-
-foreach $arg (@ARGV)
-{
- if ($arg eq '-nosort')
- {
- $nosort = 1;
- }
- else
- {
- push(@files, $arg);
- }
-}
-
-
-foreach $file (@files)
-{
- open(FILE, "< $file") || die "decipher_lockstate_dump: can't open file %s: $!\n";
-
- while ($line = <FILE>)
- {
- $line =~ s/\n/ \n/;
-
- if ($line =~ /^Glock/)
- {
- $locks[$ln++] .= "\n" if (!$nosort && $notfirst++);
- $line =~ s/\((0),/\(reserved[$1],/;
- $line =~ s/\((1),/\(nondisk[$1],/;
- $line =~ s/\((2),/\(inode[$1],/;
- $line =~ s/\((3),/\(rgrp[$1],/;
- $line =~ s/\((4),/\(meta[$1],/;
- $line =~ s/\((5),/\(iopen[$1],/;
- $line =~ s/\((6),/\(flock[$1],/;
- $line =~ s/\((7),/\(jid[$1],/;
- $line =~ s/\((8),/\(quota[$1],/;
-
- $line =~ s/\(nondisk(\S+), (0)\)/\(nondisk$1, mount[$2]\)/;
- $line =~ s/\(nondisk(\S+), (1)\)/\(nondisk$1, live[$2]\)/;
- $line =~ s/\(nondisk(\S+), (2)\)/\(nondisk$1, trans[$2]\)/;
- $line =~ s/\(nondisk(\S+), (3)\)/\(nondisk$1, rename[$2]\)/;
-
- $line =~ s/\(meta(\S+), (0)\)/\(meta$1, super[$2]\)/;
- $line =~ s/\(meta(\S+), (1)\)/\(meta$1, crap[$2]\)/;
-
- if ($line =~ /\(quota\S+, (\d+)\)/)
- {
- $qid = (($1 % 2) ? "Group" : "User") . int($1 / 2) . "[$1]";
- $line =~ s/\(quota(\S+), \d+\)/\(quota$1, $qid\)/;
- }
- }
- if ($line =~ /gl_flags/)
- {
- $line =~ s/ (0) / plug[$1] /;
- $line =~ s/ (1) / lock[$1] /;
- $line =~ s/ (2) / sticky[$1] /;
- $line =~ s/ (3) / prefetch[$1]/;
- $line =~ s/ (4) / sync[$1] /;
- $line =~ s/ (5) / dirty[$1] /;
- $line =~ s/ (6) / skip_waiters2[$1] /;
- $line =~ s/ (7) / greedy[$1] /;
- }
- if ($line =~ /state/)
- {
- $line =~ s/(0)/unlocked[$1]/;
- $line =~ s/(1)/exclusive[$1]/;
- $line =~ s/(2)/deferred[$1]/;
- $line =~ s/(3)/shared[$1]/;
- }
- if ($line =~ /gh_flags/)
- {
- $line =~ s/ (0) / try[$1] /;
- $line =~ s/ (1) / try_1cb[$1] /;
- $line =~ s/ (2) / noexp[$1] /;
- $line =~ s/ (3) / any[$1] /;
- $line =~ s/ (4) / priority[$1] /;
- $line =~ s/ (5) / local_excl[$1] /;
- $line =~ s/ (6) / async[$1] /;
- $line =~ s/ (7) / exact[$1] /;
- $line =~ s/ (8) / skip[$1] /;
- $line =~ s/ (9) / atime[$1] /;
- $line =~ s/ (10) / nocache[$1] /;
- $line =~ s/ (11) / sync[$1] /;
- $line =~ s/ (12) / nocancel[$1] /;
- }
- if ($line =~ /gh_iflags/)
- {
- $line =~ s/ (0) / mutex[$1] /;
- $line =~ s/ (1) / promote[$1] /;
- $line =~ s/ (2) / demote[$1] /;
- $line =~ s/ (3) / greedy[$1] /;
- $line =~ s/ (4) / alloced[$1] /;
- $line =~ s/ (5) / dealloc[$1] /;
- $line =~ s/ (6) / holder[$1] /;
- $line =~ s/ (7) / first[$1] /;
- $line =~ s/ (8) / recurse[$1] /;
- $line =~ s/ (9) / aborted[$1] /;
- }
- if ($line =~ /owner/)
- {
- $line =~ s/(-1)/none[$1]/;
- }
- if ($line =~ /type/)
- {
- $line =~ s/(0)/none[$1]/;
- $line =~ s/(1)/regular[$1]/;
- $line =~ s/(2)/directory[$1]/;
- $line =~ s/(5)/symbolic link[$1]/;
- $line =~ s/(7)/block device[$1]/;
- $line =~ s/(8)/character device[$1]/;
- $line =~ s/(101)/fifo[$1]/;
- $line =~ s/(102)/socket[$1]/;
- }
- if ($line =~ /i_flags/)
- {
- $line =~ s/ (0) / qd_locked[$1] /;
- $line =~ s/ (1) / paged[$1] /;
- $line =~ s/ (2) / sw_paged[$1] /;
- }
-
- $locks[$ln] .= $line;
- $ln++ if ($nosort);
- }
-
- close(FILE);
-}
-
-
- at locks = sort funky @locks unless ($nosort);
-
-
-foreach $lock (@locks)
-{
- print $lock;
-}
-
-
-
-sub funky
-{
- my($a_iopen, $b_iopen) = (0, 0);
- my($a_locked, $b_locked) = (0, 0);
- my($a_queued, $b_queued) = (0, 0);
- my($a_unlocked, $b_unlocked) = (0, 0);
-
-
- $a_iopen = 1 if ($a =~ /iopen/);
- $b_iopen = 1 if ($b =~ /iopen/);
-
- $a_locked = 1 if ($a =~ /gl_flags.*lock.*\n/);
- $b_locked = 1 if ($b =~ /gl_flags.*lock.*\n/);
-
- $a_queued = 1 if ($a =~ /Request/ ||
- $a =~ /Holder/ ||
- $a =~ /Waiter/);
- $b_queued = 1 if ($b =~ /Request/ ||
- $b =~ /Holder/ ||
- $b =~ /Waiter/);
-
- $a_unlocked = 1 if ($a =~ /gl_state.*unlocked.*\n/);
- $b_unlocked = 1 if ($b =~ /gl_state.*unlocked.*\n/);
-
-
- return ($a_iopen <=> $b_iopen) if ($a_iopen != $b_iopen);
- return -($a_locked <=> $b_locked) if ($a_locked != $b_locked);
- return -($a_queued <=> $b_queued) if ($a_queued != $b_queued);
- return ($a_unlocked <=> $b_unlocked) if ($a_unlocked != $b_unlocked);
-
-
- return 0;
-}
-
-
diff --git a/gfs/gfs_tool/df.c b/gfs/gfs_tool/df.c
deleted file mode 100644
index 2bedb11..0000000
--- a/gfs/gfs_tool/df.c
+++ /dev/null
@@ -1,318 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-
-#define __user
-#include "gfs_ioctl.h"
-#include "gfs_ondisk.h"
-
-#include "gfs_tool.h"
-
-#define SIZE (4096)
-
-/**
- * anthropomorphize - make a uint64_t number more human
- */
-static const char *anthropomorphize(uint64_t inhuman_value)
-{
- const char *symbols = " KMGTPE";
- int i;
- uint64_t val = inhuman_value;
- static char out_val[32];
-
- memset(out_val, 0, sizeof(out_val));
- for (i = 0; i < 6 && val > 1024; i++)
- val /= 1024;
- sprintf(out_val, "%"PRIu64"%c", val, symbols[i]);
- return out_val;
-}
-
-/**
- * printit - parse out and print values according to the output type
- */
-static void printit(char *stat_gfs, const char *label, uint64_t used,
- uint64_t free_space, unsigned int percentage)
-{
- uint64_t block_size = name2u64(stat_gfs, "bsize");
-
- switch (output_type) {
- case OUTPUT_BLOCKS:
- printf(" %-15s%-15"PRIu64"%-15"PRIu64"%-15"PRIu64"%u%%\n",
- label, used + free_space, used, free_space, percentage);
- break;
- case OUTPUT_K:
- printf(" %-15s%-15"PRIu64"%-15"PRIu64"%-15"PRIu64"%u%%\n",
- label, ((used + free_space) * block_size) / 1024,
- (used * block_size) / 1024, (free_space * block_size) / 1024,
- percentage);
- break;
- case OUTPUT_HUMAN:
- /* Need to do three separate printfs here because function
- anthropomorphize re-uses the same static space. */
- printf(" %-15s%-15s", label,
- anthropomorphize((used + free_space) * block_size));
- printf("%-15s", anthropomorphize(used * block_size));
- printf("%-15s%u%%\n", anthropomorphize(free_space * block_size),
- percentage);
- break;
- }
-}
-
-/**
- * do_df_one - print out information about one filesystem
- * @path: the path to the filesystem
- *
- */
-
-static void
-do_df_one(char *path)
-{
- int fd;
- struct gfs_ioctl gi;
- char stat_gfs[SIZE], args[SIZE], lockstruct[SIZE];
- struct gfs_sb sb;
- struct gfs_dinode ji, ri;
- uint64_t journals, rgrps;
- uint64_t used_data;
- unsigned int flags;
- unsigned int percentage;
- int error;
-
-
- fd = open(path, O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", path, strerror(errno));
-
- check_for_gfs(fd, path);
-
-
- {
- char *argv[] = {
- (char *)"get_stat_gfs"
- };
-
- gi.gi_argc = 1;
- gi.gi_argv = argv;
- gi.gi_data = stat_gfs;
- gi.gi_size = SIZE;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error < 0)
- die("error doing get_stat_gfs (%d): %s\n",
- error, strerror(errno));
- }
- {
- char *argv[] = {
- (char *)"get_super"
- };
-
- gi.gi_argc = 1;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&sb;
- gi.gi_size = sizeof(struct gfs_sb);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("error doing get_super (%d): %s\n",
- error, strerror(errno));
- }
- {
- char *argv[] = {
- (char *)"get_args"
- };
-
- gi.gi_argc = 1;
- gi.gi_argv = argv;
- gi.gi_data = args;
- gi.gi_size = SIZE;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error < 0)
- die("error doing get_args (%d): %s\n",
- error, strerror(errno));
- }
- {
- char *argv[] = {
- (char *)"get_lockstruct"
- };
-
- gi.gi_argc = 1;
- gi.gi_argv = argv;
- gi.gi_data = lockstruct;
- gi.gi_size = SIZE;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error < 0)
- die("error doing get_lockstruct (%d): %s\n",
- error, strerror(errno));
- }
- {
- char *argv[] = {
- (char *)"get_hfile_stat",
- (char *)"jindex"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&ji;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("error doing get_hfile_stat for jindex (%d): %s\n",
- error, strerror(errno));
- }
- {
- char *argv[] = {
- (char *)"get_hfile_stat",
- (char *)"rindex"
- };
-
- gi.gi_argc = 2;
- gi.gi_argv = argv;
- gi.gi_data = (char *)&ri;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("error doing get_hfile_stat for rindex (%d): %s\n",
- error, strerror(errno));
- }
-
-
- close(fd);
-
-
- journals = ji.di_size;
- if (journals % sizeof(struct gfs_jindex))
- die("bad jindex size\n");
- journals /= sizeof(struct gfs_jindex);
-
- rgrps = ri.di_size;
- if (rgrps % sizeof(struct gfs_rindex))
- die("bad rindex size\n");
- rgrps /= sizeof(struct gfs_rindex);
-
-
- used_data = name2u64(stat_gfs, "total_blocks") -
- name2u64(stat_gfs, "free") -
- (name2u64(stat_gfs, "used_dinode") + name2u64(stat_gfs, "free_dinode")) -
- (name2u64(stat_gfs, "used_meta") + name2u64(stat_gfs, "free_meta"));
-
-
- printf("%s:\n", path);
- printf(" SB lock proto = \"%s\"\n", sb.sb_lockproto);
- printf(" SB lock table = \"%s\"\n", sb.sb_locktable);
- printf(" SB ondisk format = %u\n", sb.sb_fs_format);
- printf(" SB multihost format = %u\n", sb.sb_multihost_format);
- printf(" Block size = %u\n", name2u32(stat_gfs, "bsize"));
- printf(" Journals = %"PRIu64"\n", journals);
- printf(" Resource Groups = %"PRIu64"\n", rgrps);
- printf(" Mounted lock proto = \"%s\"\n",
- (name2value(args, "lockproto")[0]) ?
- name2value(args, "lockproto") : sb.sb_lockproto);
- printf(" Mounted lock table = \"%s\"\n",
- (name2value(args, "locktable")[0]) ?
- name2value(args, "locktable") : sb.sb_locktable);
- printf(" Mounted host data = \"%s\"\n", name2value(args, "hostdata"));
- printf(" Journal number = %u\n", name2u32(lockstruct, "jid"));
- flags = name2u32(lockstruct, "flags");
- printf(" Lock module flags = %x", flags);
- printf("\n");
- printf(" Local flocks = %s\n", (name2u32(args, "localflocks")) ? "TRUE" : "FALSE");
- printf(" Local caching = %s\n", (name2u32(args, "localcaching")) ? "TRUE" : "FALSE");
- printf(" Oopses OK = %s\n", (name2u32(args, "oopses_ok")) ? "TRUE" : "FALSE");
- printf("\n");
- switch (output_type) {
- case OUTPUT_BLOCKS:
- printf(" %-15s%-15s%-15s%-15s%-15s\n", "Type", "Total Blocks",
- "Used Blocks", "Free Blocks", "use%");
- break;
- case OUTPUT_K:
- printf(" %-15s%-15s%-15s%-15s%-15s\n", "Type", "Total K",
- "Used K", "Free K", "use%");
- break;
- case OUTPUT_HUMAN:
- printf(" %-15s%-15s%-15s%-15s%-15s\n", "Type", "Total",
- "Used", "Free", "use%");
- break;
- }
- printf(" ------------------------------------------------------------------------\n");
-
- percentage = (name2u64(stat_gfs, "used_dinode") + name2u64(stat_gfs, "free_dinode")) ?
- (100.0 * name2u64(stat_gfs, "used_dinode") / (name2u64(stat_gfs, "used_dinode") +
- name2u64(stat_gfs, "free_dinode")) + 0.5) : 0;
- printit(stat_gfs, "inodes", name2u64(stat_gfs, "used_dinode"),
- name2u64(stat_gfs, "free_dinode"), percentage);
-
- percentage = (name2u64(stat_gfs, "used_meta") + name2u64(stat_gfs, "free_meta")) ?
- (100.0 * name2u64(stat_gfs, "used_meta") / (name2u64(stat_gfs, "used_meta") +
- name2u64(stat_gfs, "free_meta")) + 0.5) : 0;
- printit(stat_gfs, "metadata", name2u64(stat_gfs, "used_meta"),
- name2u64(stat_gfs, "free_meta"), percentage);
-
- percentage = (used_data + name2u64(stat_gfs, "free")) ?
- (100.0 * used_data / (used_data + name2u64(stat_gfs, "free")) + 0.5) : 0;
- printit(stat_gfs, "data", used_data, name2u64(stat_gfs, "free"),
- percentage);
-}
-
-
-/**
- * print_df - print out information about filesystems
- * @argc:
- * @argv:
- *
- */
-
-void
-print_df(int argc, char **argv)
-{
- if (optind < argc) {
- char buf[PATH_MAX];
-
- if (!realpath(argv[optind], buf))
- die("can't determine real path: %s\n", strerror(errno));
-
- do_df_one(buf);
-
- return;
- }
-
- {
- FILE *file;
- char buf[256], device[256], path[256], type[256];
- int first = TRUE;
-
- file = fopen("/proc/mounts", "r");
- if (!file)
- die("can't open /proc/mounts: %s\n", strerror(errno));
-
- while (fgets(buf, 256, file)) {
- if (sscanf(buf, "%s %s %s", device, path, type) != 3)
- continue;
- if (strcmp(type, "gfs") != 0)
- continue;
-
- if (first)
- first = FALSE;
- else
- printf("\n");
-
- do_df_one(path);
- }
-
- fclose(file);
- }
-}
-
-
diff --git a/gfs/gfs_tool/gfs_tool.h b/gfs/gfs_tool/gfs_tool.h
deleted file mode 100644
index db9cdf4..0000000
--- a/gfs/gfs_tool/gfs_tool.h
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef __GFS_TOOL_DOT_H__
-#define __GFS_TOOL_DOT_H__
-
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#define die(fmt, args...) \
-do { \
- fprintf(stderr, "%s: ", prog_name); \
- fprintf(stderr, fmt, ##args); \
- exit(EXIT_FAILURE); \
-} while (0)
-
-
-#define OUTPUT_BLOCKS 0
-#define OUTPUT_K 1
-#define OUTPUT_HUMAN 2
-
-extern char *prog_name;
-extern char *action;
-extern int override;
-extern int expert;
-extern int debug;
-extern int continuous;
-extern int interval;
-extern int output_type;
-
-/* From counters.c */
-
-void print_counters(int argc, char **argv);
-
-
-/* From df.c */
-
-void print_df(int argc, char **argv);
-
-
-/* From layout.c */
-
-void print_layout(int argc, char **argv);
-
-
-/* From main.c */
-
-void print_usage(void);
-
-
-/* From misc.c */
-
-void do_file_flush(int argc, char **argv);
-void do_freeze(int argc, char **argv);
-void margs(int argc, char **argv);
-void print_lockdump(int argc, char **argv);
-void set_flag(int argc, char **argv);
-void print_stat(int argc, char **argv);
-void print_sb(int argc, char **argv);
-void print_jindex(int argc, char **argv);
-void print_rindex(int argc, char **argv);
-void print_quota(int argc, char **argv);
-void print_list(void);
-void reclaim_metadata(int argc, char **argv);
-void do_shrink(int argc, char **argv);
-void do_withdraw(int argc, char **argv);
-
-
-/* From sb.c */
-
-void do_sb(int argc, char **argv);
-
-
-/* From tune.c */
-
-void get_tune(int argc, char **argv);
-void set_tune(int argc, char **argv);
-
-
-/* From util.c */
-
-void check_for_gfs(int fd, char *path);
-char *get_list(void);
-char **str2lines(char *str);
-char *mp2cookie(char *mp, int ioctl_ok);
-char *name2value(char *str, const char *name);
-uint32_t name2u32(char *str, const char *name);
-uint64_t name2u64(char *str, const char *name);
-
-
-#endif /* __GFS_TOOL_DOT_H__ */
diff --git a/gfs/gfs_tool/layout.c b/gfs/gfs_tool/layout.c
deleted file mode 100644
index ad6411d..0000000
--- a/gfs/gfs_tool/layout.c
+++ /dev/null
@@ -1,845 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-
-#define __user
-#include "gfs_ioctl.h"
-#include "gfs_ondisk.h"
-
-#include "osi_list.h"
-#include "linux_endian.h"
-
-#include "gfs_tool.h"
-
-#define LAYOUT_DATA_QUANTUM (4194304)
-
-struct extent {
- osi_list_t list;
-
- uint64_t offset;
- uint64_t start;
- unsigned int len;
-};
-typedef struct extent extent_t;
-
-struct buffer {
- osi_list_t list;
- uint64_t blkno;
- char *data;
-
- int touched;
-};
-typedef struct buffer buffer_t;
-
-struct world {
- char *buf_data;
- unsigned int buf_size;
- int buf_count;
- osi_list_t blist;
- osi_list_t elist;
-
- struct gfs_sb sb;
- unsigned int diptrs;
- unsigned int inptrs;
- unsigned int jbsize;
- unsigned int hash_bsize;
- unsigned int hash_ptrs;
-
- buffer_t *dibh;
- struct gfs_dinode di;
-};
-typedef struct world world_t;
-
-typedef void (*pointer_call_t) (world_t *w,
- unsigned int height, uint64_t bn, void *data);
-typedef void (*leaf_call_t) (world_t *w,
- uint32_t index, uint32_t len, uint64_t leaf_no,
- void *data);
-
-/**
- * build_list - build a list of buffer_t's to represent the data from the kernel
- * @w: the world structure
- *
- */
-
-static void
-build_list(world_t *w)
-{
- buffer_t *b;
- unsigned int x;
-
- for (x = 0; x < w->buf_count; x += sizeof(uint64_t) + w->sb.sb_bsize) {
- b = malloc(sizeof(buffer_t));
- if (!b)
- die("out of memory\n");
-
- memset(b, 0, sizeof(buffer_t));
-
- b->blkno = *(uint64_t *) (w->buf_data + x);
- b->data = w->buf_data + x + sizeof(uint64_t);
-
- osi_list_add_prev(&b->list, &w->blist);
- }
-
- if (x != w->buf_count)
- die("the kernel passed back unaligned data\n");
-}
-
-/**
- * check_list - check the buffers passed back by the kernel
- * @w: the world
- *
- */
-
-static void
-check_list(world_t *w)
-{
- osi_list_t *tmp;
- buffer_t *b;
- struct gfs_meta_header mh;
- const char *type;
-
- for (tmp = w->blist.next; tmp != &w->blist; tmp = tmp->next) {
- b = osi_list_entry(tmp, buffer_t, list);
-
- gfs_meta_header_in(&mh, b->data);
-
- if (mh.mh_magic != GFS_MAGIC)
- die("bad magic number on block\n");
-
- switch (mh.mh_type) {
- case GFS_METATYPE_DI:
- type = "GFS_METATYPE_DI";
-
- if (w->dibh)
- die("more than one dinode in file\n");
- else {
- w->dibh = b;
- gfs_dinode_in(&w->di, b->data);
-
- b->touched = TRUE;
- }
-
- break;
- case GFS_METATYPE_IN:
- type = "GFS_METATYPE_IN";
- break;
- case GFS_METATYPE_LF:
- type = "GFS_METATYPE_LF";
- break;
- case GFS_METATYPE_JD:
- type = "GFS_METATYPE_JD";
- break;
- case GFS_METATYPE_EA:
- type = "GFS_METATYPE_EA";
- break;
- case GFS_METATYPE_ED:
- die("GFS_METATYPE_ED shouldn't be present\n");
- default:
- die("strange meta type\n");
- }
- }
-
- if (!w->dibh)
- die("no dinode\n");
-}
-
-/**
- * getbuf - get the buffer_t for a given block number
- * @w: the world
- * @blkno: the block number
- *
- * Returns: the buffer_t
- */
-
-static buffer_t *
-getbuf(world_t *w, uint64_t blkno)
-{
- osi_list_t *tmp;
- buffer_t *b;
-
- for (tmp = w->blist.next; tmp != &w->blist; tmp = tmp->next) {
- b = osi_list_entry(tmp, buffer_t, list);
- if (b->blkno == blkno) {
- osi_list_del(&b->list);
- osi_list_add(&b->list, &w->blist);
-
- b->touched = TRUE;
-
- return b;
- }
- }
-
- die("buffer not found\n");
-}
-
-/**
- * recursive_scan - call a function for each block pointer in a file
- * @w: the world
- * @height: the height of the block being pointed to
- * @block: the block being pointed to
- * @pc: the function to call
- * @data: private data for the @pc function
- *
- */
-
-static void
-recursive_scan(world_t *w,
- unsigned int height, uint64_t block, pointer_call_t pc, void *data)
-{
- buffer_t *b = NULL;
- uint64_t *top, *bottom;
- uint64_t bn;
-
- if (!height) {
- b = w->dibh;
-
- top = (uint64_t *) (b->data + sizeof(struct gfs_dinode));
- bottom =
- (uint64_t *) (b->data + sizeof(struct gfs_dinode)) +
- w->diptrs;
- } else {
- b = getbuf(w, block);
-
- top = (uint64_t *) (b->data + sizeof(struct gfs_indirect));
- bottom =
- (uint64_t *) (b->data + sizeof(struct gfs_indirect)) +
- w->inptrs;
- }
-
- for (; top < bottom; top++) {
- bn = gfs64_to_cpu(*top);
-
- pc(w, height, bn, data);
-
- if (bn && height < w->di.di_height - 1)
- recursive_scan(w, height + 1, bn, pc, data);
- }
-}
-
-/**
- * bmap - return the buffer_t for a given logical block in the file
- * @w: the world
- * @lbn: the logical block number
- *
- * Returns: the buffer_t
- */
-
-static buffer_t *
-bmap(world_t *w, uint64_t lbn)
-{
- osi_list_t *tmp;
- extent_t *e;
-
- for (tmp = w->elist.next; tmp != &w->elist; tmp = tmp->next) {
- e = osi_list_entry(tmp, extent_t, list);
-
- if (e->offset <= lbn && lbn < e->offset + e->len)
- return getbuf(w, e->start + lbn - e->offset);
- }
-
- return NULL;
-}
-
-/**
- * journaled_read - read some of the contents of a journaled file
- * @w: the world
- * @buf: the buffer to read into
- * @offset: the offset to read from
- * @size: the number of bytes to read
- *
- */
-
-static void
-journaled_read(world_t *w, char *buf, uint64_t offset, unsigned int size)
-{
- buffer_t *b;
- uint64_t lbn;
- unsigned int o, chunk;
-
- if (!(w->di.di_flags & GFS_DIF_JDATA))
- die("not a journaled file\n");
-
- if (!w->di.di_height) {
- if (offset >= w->sb.sb_bsize - sizeof(struct gfs_dinode))
- memset(buf, 0, size);
- else {
- chunk =
- w->sb.sb_bsize - sizeof(struct gfs_dinode) -
- offset;
- if (chunk > size)
- chunk = size;
- memcpy(buf,
- w->dibh->data + sizeof(struct gfs_dinode) +
- offset, chunk);
- if (chunk < size)
- memset(buf + chunk, 0, size - chunk);
- }
- } else
- while (size) {
- lbn = offset / w->jbsize;
- o = offset % w->jbsize;
- chunk = (size > w->jbsize - o) ? (w->jbsize - o) : size;
-
- b = bmap(w, lbn);
- if (b)
- memcpy(buf,
- b->data +
- sizeof(struct gfs_meta_header) + o,
- chunk);
- else
- memset(buf, 0, chunk);
-
- buf += chunk;
- offset += chunk;
- size -= chunk;
- }
-}
-
-/**
- * foreach_leaf - call a function for each leaf in a directory
- * @w: the world
- * @lc: the function to call for each each
- * @data: private data to pass to it
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-static void
-foreach_leaf(world_t *w, leaf_call_t lc, void *data)
-{
- buffer_t *b;
- struct gfs_leaf leaf;
- uint32_t hsize, len;
- uint32_t ht_offset, lp_offset, ht_offset_cur = -1;
- uint32_t lindex = 0;
- uint64_t lp[w->hash_ptrs];
- uint64_t leaf_no;
-
- hsize = 1 << w->di.di_depth;
- if (hsize * sizeof(uint64_t) != w->di.di_size)
- die("bad hash table size\n");
-
- while (lindex < hsize) {
- lp_offset = lindex % w->hash_ptrs;
- ht_offset = lindex - lp_offset;
-
- if (ht_offset_cur != ht_offset) {
- journaled_read(w, (char *) lp,
- ht_offset * sizeof(uint64_t),
- w->hash_bsize);
- ht_offset_cur = ht_offset;
- }
-
- leaf_no = gfs64_to_cpu(lp[lp_offset]);
- if (!leaf_no)
- die("NULL leaf pointer\n");
-
- b = getbuf(w, leaf_no);
- gfs_leaf_in(&leaf, b->data);
-
- len = 1 << (w->di.di_depth - leaf.lf_depth);
-
- lc(w, lindex, len, leaf_no, data);
-
- lindex += len;
- }
-
- if (lindex != hsize)
- die("screwed up directory\n");
-}
-
-/**
- * add_extent - add an extend to the list of the file's data extents
- * @w: the world
- * @offset: the starting logical block of the extent
- * @start: the starting disk block of the extent
- * @len: the number of blocks in the extent
- *
- */
-
-static void
-add_extent(world_t *w, uint64_t offset, uint64_t start, unsigned int len)
-{
- extent_t *e;
-
- e = malloc(sizeof(extent_t));
- if (!e)
- die("out of memory\n");
-
- memset(e, 0, sizeof(extent_t));
-
- e->offset = offset;
- e->start = start;
- e->len = len;
-
- osi_list_add_prev(&e->list, &w->elist);
-}
-
-struct do_pf_s {
- unsigned int height;
- uint64_t offset;
- uint64_t start;
- uint64_t skip;
- unsigned int len;
-};
-typedef struct do_pf_s do_pf_t;
-
-/**
- * do_pf: called for every pointer in the file (prints/collects extent info)
- * @w: the world
- * @height: the height of the block containing the pointer
- * @bn: the contents of the pointer
- * @data: a do_pf_t structure
- *
- */
-
-static void
-do_pf(world_t *w, unsigned int height, uint64_t bn, void *data)
-{
- do_pf_t *pf = (do_pf_t *) data;
- unsigned int x;
- uint64_t skip;
-
- if (pf->height < height + 1)
- return;
-
- if (!bn) {
- if (pf->height == height + 1)
- pf->skip++;
- else {
- x = pf->height - height - 1;
- skip = w->inptrs;
- while (--x)
- skip *= w->inptrs;
- pf->skip += skip;
- }
-
- return;
- }
-
- if (pf->height == height + 1) {
- if (pf->start + pf->len == bn && pf->len == pf->skip) {
- pf->len++;
- pf->skip++;
- } else {
- if (pf->start) {
- printf(" %-20" PRIu64 " %-20" PRIu64 " %-20"
- PRIu64 " %u\n", pf->offset,
- pf->offset + pf->len - 1, pf->start,
- pf->len);
- if (pf->height == w->di.di_height)
- add_extent(w, pf->offset, pf->start,
- pf->len);
- }
-
- pf->offset += pf->skip;
- pf->start = bn;
- pf->len = 1;
- pf->skip = 1;
- }
- }
-}
-
-/**
- * print_file - print out the extent lists for all the heights of a file
- * @w: the world
- *
- */
-
-static void
-print_file(world_t *w)
-{
- do_pf_t pf;
- unsigned int h;
- const char *type;
-
- switch (w->di.di_type) {
- case GFS_FILE_REG:
- type = "File";
- break;
- case GFS_FILE_DIR:
- type = "Directory";
- break;
- case GFS_FILE_LNK:
- type = "Symbolic Link";
- break;
- case GFS_FILE_BLK:
- type = "Block Device";
- break;
- case GFS_FILE_CHR:
- type = "Character Device";
- break;
- case GFS_FILE_FIFO:
- type = "FIFO";
- break;
- case GFS_FILE_SOCK:
- type = "Socket";
- break;
- default:
- die("strange file type\n");
- };
-
- printf("%s dinode:\n", type);
- printf(" %" PRIu64 "\n", w->di.di_num.no_addr);
-
- if (!w->di.di_height) {
- if (w->di.di_type == GFS_FILE_DIR) {
- if (w->di.di_flags & GFS_DIF_EXHASH)
- printf("\nStuffed hash table\n");
- } else
- printf("\nStuffed file data\n");
-
- return;
- }
-
- for (h = 1; h <= w->di.di_height; h++) {
- if (w->di.di_type == GFS_FILE_DIR)
- type =
- (h == w->di.di_height) ? "hash table" : "indirect";
- else
- type = (h == w->di.di_height) ? "data" : "indirect";
-
- printf("\n");
- printf("At height %u (%s):\n", h, type);
- printf(" %-20s %-20s %-20s %s\n",
- "From LBlock", "To LBlock", "DBlock", "Blocks");
-
- memset(&pf, 0, sizeof(do_pf_t));
- pf.height = h;
-
- recursive_scan(w, 0, 0, do_pf, &pf);
-
- if (pf.start) {
- printf(" %-20" PRIu64 " %-20" PRIu64 " %-20" PRIu64
- " %u\n", pf.offset, pf.offset + pf.len - 1,
- pf.start, pf.len);
- if (h == w->di.di_height)
- add_extent(w, pf.offset, pf.start, pf.len);
- }
- }
-}
-
-/**
- * do_lc - print out info about a leaf block
- * @w: the world
- * @index: the index of the leaf
- * @len: the number of pointers to the leaf
- * @leaf_no: the leaf block number
- * @data: unused
- *
- */
-
-static void
-do_lc(world_t *w, uint32_t lindex, uint32_t len, uint64_t leaf_no, void *data)
-{
- buffer_t *b;
- struct gfs_leaf leaf;
- uint64_t blk;
-
- for (blk = leaf_no; blk; blk = leaf.lf_next) {
- b = getbuf(w, blk);
- gfs_leaf_in(&leaf, b->data);
-
- printf(" %.8X %.8X %-20" PRIu64
- " %u\n", lindex << (32 - w->di.di_depth),
- ((lindex + len) << (32 - w->di.di_depth)) - 1, blk,
- leaf.lf_entries);
- }
-
-}
-
-/**
- * print_leaves - print out the location of the exhash leaves
- * @w: the world
- *
- */
-
-static void
-print_leaves(world_t *w)
-{
- printf("\n");
-
- if (w->di.di_flags & GFS_DIF_EXHASH) {
- printf("Leaves:\n");
- printf(" %-20s %-20s %-20s %s\n",
- "From Hash", "To Hash", "DBlock", "Entries");
- foreach_leaf(w, do_lc, NULL);
- } else
- printf("Stuffed directory data\n");
-}
-
-/**
- * print_eattr_data - print out the locations of the eattr data blocks
- * @w: the world
- *
- */
-
-#define MAKE_MULT8(x) (((x) + 7) & ~7)
-#define GFS_EA_REC_LEN(ea) gfs32_to_cpu((ea)->ea_rec_len)
-#define GFS_EA_IS_STUFFED(ea) (!(ea)->ea_num_ptrs)
-#define GFS_EA_IS_LAST(ea) ((ea)->ea_flags & GFS_EAFLAG_LAST)
-#define GFS_EA2NAME(ea) ((char *)((struct gfs_ea_header *)(ea) + 1))
-#define GFS_EA2DATAPTRS(ea) \
-((uint64_t *)(GFS_EA2NAME(ea) + MAKE_MULT8((ea)->ea_name_len)))
-#define GFS_EA2NEXT(ea) \
-((struct gfs_ea_header *)((char *)(ea) + GFS_EA_REC_LEN(ea)))
-#define GFS_EA_BH2FIRST(b) \
-((struct gfs_ea_header *)((b)->data + \
- sizeof(struct gfs_meta_header)))
-
-static void
-print_eattr_data(world_t *w, uint64_t eblkno, int *first)
-{
- struct gfs_ea_header *ea;
-
- ea = GFS_EA_BH2FIRST(getbuf(w, eblkno));
- for (;;) {
- if (!GFS_EA_IS_STUFFED(ea)) {
- char name[300];
- uint64_t *p, blkno;
- uint64_t d;
- unsigned int l;
- unsigned int x;
- int c;
-
- if (*first) {
- printf("\nExtended Attributes data blocks:\n");
- printf(" %-20s %-10s %s\n",
- "DBlock", "Blocks", "Name");
- *first = FALSE;
- }
-
- if (ea->ea_type == GFS_EATYPE_UNUSED)
- strcpy(name, "unused");
- else {
- switch (ea->ea_type) {
- case GFS_EATYPE_USR:
- strcpy(name, "user.");
- break;
- case GFS_EATYPE_SYS:
- strcpy(name, "system.");
- break;
- default:
- strcpy(name, "unknown.");
- break;
- }
- x = strlen(name);
- memcpy(name + x,
- GFS_EA2NAME(ea), ea->ea_name_len);
- name[x + ea->ea_name_len] = 0;
- }
-
- d = 0;
- l = 0;
- x = 0;
- c = FALSE;
-
- p = GFS_EA2DATAPTRS(ea);
- for (x = 0; x < ea->ea_num_ptrs; x++) {
- blkno = gfs64_to_cpu(*p);
- if (d + l == blkno)
- l++;
- else {
- if (d) {
- printf(" %-20" PRIu64
- " %-10u %s\n", d, l,
- name);
- if (!c) {
- strcat(name, " (cont)");
- c = TRUE;
- }
- }
- d = blkno;
- l = 1;
- }
- p++;
- }
- printf(" %-20" PRIu64 " %-10u %s\n", d, l, name);
- }
- if (GFS_EA_IS_LAST(ea))
- break;
- ea = GFS_EA2NEXT(ea);
- }
-}
-
-/**
- * print_eattr - print out the locations of the eattr blocks
- * @w: the world
- *
- */
-
-static void
-print_eattr(world_t *w)
-{
- int first = TRUE;
-
- if (w->di.di_flags & GFS_DIF_EA_INDIRECT) {
- buffer_t *b = getbuf(w, w->di.di_eattr);
- uint64_t *blkno;
- unsigned int x;
-
- printf("\nExtended Attribute indirect block:\n");
- printf(" %" PRIu64 "\n", w->di.di_eattr);
-
- printf("\nExtended Attribute blocks:\n");
- blkno = (uint64_t *) (b->data + sizeof(struct gfs_indirect));
- for (x = 0; x < w->inptrs; x++) {
- if (!*blkno)
- break;
- printf(" %" PRIu64 "\n", gfs64_to_cpu(*blkno));
- blkno++;
- }
-
- blkno = (uint64_t *) (b->data + sizeof(struct gfs_indirect));
- for (x = 0; x < w->inptrs; x++) {
- if (!*blkno)
- break;
- print_eattr_data(w, gfs64_to_cpu(*blkno), &first);
- blkno++;
- }
- } else {
- printf("\nExtended Attribute block:\n");
- printf(" %" PRIu64 "\n", w->di.di_eattr);
-
- print_eattr_data(w, w->di.di_eattr, &first);
- }
-}
-
-/**
- * check_for_untouched_buffers -
- * @w: the world
- *
- */
-
-static void
-check_for_untouched_buffers(world_t *w)
-{
- osi_list_t *tmp;
- buffer_t *b;
-
- for (tmp = w->blist.next; tmp != &w->blist; tmp = tmp->next) {
- b = osi_list_entry(tmp, buffer_t, list);
- if (b->touched)
- continue;
-
- printf("Buffer %" PRIu64 " untouched\n", b->blkno);
- }
-}
-
-/**
- * print_layout - print out the ondisk layout of a file
- * @argc:
- * @argv:
- *
- */
-
-void
-print_layout(int argc, char **argv)
-{
- world_t w;
- char *path;
- int fd;
- int retry = TRUE;
- struct gfs_ioctl gi;
- int error;
-
- memset(&w, 0, sizeof(world_t));
- w.buf_size = LAYOUT_DATA_QUANTUM;
- osi_list_init(&w.blist);
- osi_list_init(&w.elist);
-
- if (optind == argc)
- die("Usage: gfs_tool layout <filename> [buffersize]\n");
-
- path = argv[optind++];
- if (optind < argc ) {
- w.buf_size = atoi(argv[3]);
- retry = FALSE;
- }
-
- fd = open(path, O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", path, strerror(errno));
-
- check_for_gfs(fd, path);
-
- {
- char *local_argv[] = {
- (char *)"get_super"
- };
-
- gi.gi_argc = 1;
- gi.gi_argv = local_argv;
- gi.gi_data = (char *)&w.sb;
- gi.gi_size = sizeof(struct gfs_sb);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("error doing get_super (%d): %s\n",
- error, strerror(errno));
- }
-
- w.diptrs = (w.sb.sb_bsize - sizeof(struct gfs_dinode)) /
- sizeof(uint64_t);
- w.inptrs = (w.sb.sb_bsize - sizeof(struct gfs_indirect)) /
- sizeof(uint64_t);
- w.jbsize = w.sb.sb_bsize - sizeof(struct gfs_meta_header);
- w.hash_bsize = w.sb.sb_bsize / 2;
- w.hash_ptrs = w.hash_bsize / sizeof(uint64_t);
-
- for (;;) {
- char *local_argv[] = {
- (char *)"get_file_meta"
- };
-
- w.buf_data = malloc(w.buf_size);
- if (!w.buf_data)
- die("out of memory\n");
-
- gi.gi_argc = 1;
- gi.gi_argv = local_argv;
- gi.gi_data = w.buf_data;
- gi.gi_size = w.buf_size;
-
- w.buf_count = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (w.buf_count >= 0)
- break;
-
- if (errno == ENOMEM) {
- if (retry) {
- free(w.buf_data);
- w.buf_size += LAYOUT_DATA_QUANTUM;
- continue;
- } else
- die("%u bytes isn't enough memory\n",
- w.buf_size);
- }
- die("error doing get_file_meta: %s\n",
- strerror(errno));
- }
-
- build_list(&w);
- check_list(&w);
-
- print_file(&w);
-
- if (w.di.di_type == GFS_FILE_DIR)
- print_leaves(&w);
-
- if (w.di.di_eattr)
- print_eattr(&w);
-
- check_for_untouched_buffers(&w);
-
- close(fd);
-}
diff --git a/gfs/gfs_tool/main.c b/gfs/gfs_tool/main.c
deleted file mode 100644
index 03b88d5..0000000
--- a/gfs/gfs_tool/main.c
+++ /dev/null
@@ -1,274 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-
-#include "copyright.cf"
-
-#include "gfs_tool.h"
-
-char *prog_name;
-char *action = NULL;
-int override = FALSE;
-int expert = FALSE;
-int debug = FALSE;
-int continuous = FALSE;
-int interval = 1;
-int output_type = OUTPUT_BLOCKS;
-
-static const char *usage[] = {
- "Clear a flag on a inode\n",
- " gfs_tool clearflag flag <filenames>\n",
- "\n",
- "Print the counters for a filesystem\n",
- " gfs_tool counters <mountpoint>\n",
- "\n",
- "Do a GFS specific \"df\"\n",
- " gfs_tool df <mountpoint>\n",
- "\n",
- "Force files from a machine's cache\n",
- " gfs_tool flush <filenames>\n",
- "\n",
- "Freeze a GFS cluster:\n",
- " gfs_tool freeze <mountpoint>\n",
- "\n",
- "Print the superblock of a mounted filesystem:\n",
- " gfs_tool getsb <mountpoint>\n",
- "\n",
- "Get tuneable parameters for a filesystem\n",
- " gfs_tool gettune <mountpoint>\n",
- "\n",
- "Print the journal index of a mounted filesystem:\n",
- " gfs_tool jindex <mountpoint>\n",
- "\n",
- "Print out the ondisk layout for a file:\n",
- " gfs_tool layout <filename> [buffersize]\n",
- "\n",
- "List filesystems:\n",
- " gfs_tool list\n",
- "\n",
- "Have GFS dump its lock state:\n",
- " gfs_tool lockdump <mountpoint> [buffersize]\n",
- "\n",
- "Provide arguments for next mount:\n",
- " gfs_tool margs <mountarguments>\n",
- "\n",
- "Print the quota file of a mounted filesystem:\n",
- " gfs_tool quota <mountpoint>\n",
- "\n",
- "Free unused disk inodes:\n",
- " gfs_tool reclaim <mountpoint>\n",
- "\n",
- "Print the resource group index of a mounted filesystem:\n",
- " gfs_tool rindex <mountpoint>\n",
- "\n",
- "Tune a GFS superblock\n",
- " gfs_tool sb <device> proto [newval]\n",
- " gfs_tool sb <device> table [newval]\n",
- " gfs_tool sb <device> ondisk [newval]\n",
- " gfs_tool sb <device> multihost [newval]\n",
- " gfs_tool sb <device> all\n",
- "\n",
- "Set a flag on a inode\n",
- " gfs_tool setflag flag <filenames>\n",
- "\n",
- "Tune a running filesystem\n",
- " gfs_tool settune <mountpoint> <parameter> <value>\n",
- "\n",
- "Shrink a filesystem's inode cache:\n",
- " gfs_tool shrink <mountpoint>\n",
- "\n",
- "Print file stat data:\n",
- " gfs_tool stat <filename>\n",
- "\n",
- "Unfreeze a GFS cluster:\n",
- " gfs_tool unfreeze <mountpoint>\n",
- "\n",
- "Print tool version information\n",
- " gfs_tool version\n",
- "\n",
- "Withdraw this machine from participating in a filesystem:\n",
- " gfs_tool withdraw <mountpoint>\n",
- "",
-};
-
-/**
- * print_usage - print out usage information
- *
- */
-
-void
-print_usage(void)
-{
- int x;
-
- for (x = 0; usage[x][0]; x++)
- printf("%s", usage[x]);
-}
-
-/**
- * print_version -
- *
- */
-
-static void
-print_version(void)
-{
- printf("gfs_tool %s (built %s %s)\n",
- RELEASE_VERSION,
- __DATE__, __TIME__);
- printf("%s\n",
- REDHAT_COPYRIGHT);
-}
-
-/**
- * decode_arguments -
- * @argc:
- * @argv:
- *
- */
-
-static void
-decode_arguments(int argc, char *argv[])
-{
- int cont = TRUE;
- int optchar;
-
- output_type = OUTPUT_BLOCKS;
- while (cont) {
- optchar = getopt(argc, argv, "cDhHki:OVX");
-
- switch (optchar) {
- case 'c':
- continuous = TRUE;
- break;
-
- case 'D':
- debug = TRUE;
- break;
-
- case 'h':
- print_usage();
- exit(EXIT_SUCCESS);
-
- case 'H':
- output_type = OUTPUT_HUMAN;
- break;
-
- case 'i':
- sscanf(optarg, "%u", &interval);
- break;
-
- case 'k':
- output_type = OUTPUT_K;
- break;
-
- case 'O':
- override = TRUE;
- break;
-
- case 'V':
- print_version();
- exit(EXIT_SUCCESS);
-
- case 'X':
- expert = TRUE;
- break;
-
- case EOF:
- cont = FALSE;
- break;
-
- default:
- die("unknown option: %c\n", optchar);
- };
- }
-
- if (optind < argc) {
- action = argv[optind];
- optind++;
- } else
- die("no action specified\n");
-}
-
-/**
- * main - Do everything
- * @argc:
- * @argv:
- *
- */
-
-int
-main(int argc, char *argv[])
-{
- prog_name = argv[0];
-
- if (argc < 2) {
- print_usage();
- exit(EXIT_SUCCESS);
- }
-
- decode_arguments(argc, argv);
-
- if (FALSE) {
- /* Do Nothing */
- } else if (strcmp(action, "clearflag") == 0)
- set_flag(argc, argv);
- else if (strcmp(action, "counters") == 0)
- print_counters(argc, argv);
- else if (strcmp(action, "df") == 0)
- print_df(argc, argv);
- else if (strcmp(action, "flush") == 0)
- do_file_flush(argc, argv);
- else if (strcmp(action, "freeze") == 0)
- do_freeze(argc, argv);
- else if (strcmp(action, "getsb") == 0)
- print_sb(argc, argv);
- else if (strcmp(action, "gettune") == 0)
- get_tune(argc, argv);
- else if (strcmp(action, "jindex") == 0)
- print_jindex(argc, argv);
- else if (strcmp(action, "layout") == 0)
- print_layout(argc, argv);
- else if (strcmp(action, "list") == 0)
- print_list();
- else if (strcmp(action, "lockdump") == 0)
- print_lockdump(argc, argv);
- else if (strcmp(action, "margs") == 0)
- margs(argc, argv);
- else if (strcmp(action, "quota") == 0)
- print_quota(argc, argv);
- else if (strcmp(action, "reclaim") == 0)
- reclaim_metadata(argc, argv);
- else if (strcmp(action, "rindex") == 0)
- print_rindex(argc, argv);
- else if (strcmp(action, "sb") == 0)
- do_sb(argc, argv);
- else if (strcmp(action, "setflag") == 0)
- set_flag(argc, argv);
- else if (strcmp(action, "settune") == 0)
- set_tune(argc, argv);
- else if (strcmp(action, "shrink") == 0)
- do_shrink(argc, argv);
- else if (strcmp(action, "stat") == 0)
- print_stat(argc, argv);
- else if (strcmp(action, "unfreeze") == 0)
- do_freeze(argc, argv);
- else if (strcmp(action, "version") == 0)
- print_version();
- else if (strcmp(action, "withdraw") == 0)
- do_withdraw(argc, argv);
- else
- die("unknown action: %s\n",
- action);
-
- exit(EXIT_SUCCESS);
-}
diff --git a/gfs/gfs_tool/misc.c b/gfs/gfs_tool/misc.c
deleted file mode 100644
index 08b14d2..0000000
--- a/gfs/gfs_tool/misc.c
+++ /dev/null
@@ -1,755 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-
-#define __user
-#include "gfs_ioctl.h"
-#include "gfs_ondisk.h"
-
-#include "gfs_tool.h"
-
-/**
- * do_file_flush -
- * @argc:
- * @argv:
- *
- */
-
-void
-do_file_flush(int argc, char **argv)
-{
- char *gi_argv[] = {
- (char *)"do_file_flush"
- };
- struct gfs_ioctl gi;
- int fd;
- int error;
-
- if (optind == argc)
- die("Usage: gfs_tool flush <filenames>\n");
-
- gi.gi_argc = 1;
- gi.gi_argv = gi_argv;
-
- for (; optind < argc; optind++) {
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", argv[optind], strerror(errno));
-
- check_for_gfs(fd, argv[optind]);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error)
- die("error doing do_file_flush (%d): %s\n",
- error, strerror(errno));
-
- close(fd);
- }
-}
-
-/**
- * do_freeze - freeze a GFS filesystem
- * @argc:
- * @argv:
- *
- */
-
-void
-do_freeze(int argc, char **argv)
-{
- char *command = argv[optind - 1];
- char *cookie;
- int fd;
- char buf[256];
- int x;
-
- if (optind == argc)
- die("Usage: gfs_tool %s <mountpoint>\n",
- command);
-
- cookie = mp2cookie(argv[optind], FALSE);
- x = sprintf(buf, "%s %s\n", command, cookie);
-
- fd = open("/proc/fs/gfs", O_RDWR);
- if (fd < 0)
- die("can't open /proc/fs/gfs: %s\n",
- strerror(errno));
-
- if (write(fd, buf, x) != x)
- die("can't write %s command: %s\n",
- command, strerror(errno));
- if (read(fd, buf, 256))
- die("can't %s %s: %s\n",
- command, argv[optind], strerror(errno));
-
- close(fd);
- sync();
-}
-
-/**
- * print_lockdump -
- * @argc:
- * @argv:
- *
- */
-
-void
-print_lockdump(int argc, char **argv)
-{
- int fd;
- char *mp, *cookie;
- unsigned int size = 4194304;
- char *data;
- char command[256];
- int retry = TRUE;
- int x, count;
-
-
- if (optind < argc)
- mp = argv[optind++];
- else
- die("Usage: gfs_tool lockdump <mountpoint> [buffersize]\n");
-
- if (optind < argc) {
- sscanf(argv[optind++], "%u", &size);
- retry = FALSE;
- }
-
- cookie = mp2cookie(mp, FALSE);
- x = sprintf(command, "lockdump %s\n", cookie);
-
-
- fd = open("/proc/fs/gfs", O_RDWR);
- if (fd < 0)
- die("can't open /proc/fs/gfs: %s\n",
- strerror(errno));
-
- for (;;) {
- data = malloc(size);
- if (!data)
- die("out of memory\n");
-
- if (write(fd, command, x) != x)
- die("can't write lockdump command: %s\n",
- strerror(errno));
- count = read(fd, data, size);
- if (count >= 0)
- break;
-
- if (errno == ENOMEM) {
- if (retry) {
- free(data);
- size += 4194304;
- continue;
- } else
- die("%u bytes isn't enough memory\n", size);
- }
- die("error doing lockdump: %s\n",
- strerror(errno));
- }
-
- close(fd);
-
-
- x = write(STDOUT_FILENO, data, count);
-
- free(data);
-}
-
-/**
- * margs -
- * @argc:
- * @argv:
- *
- */
-
-void
-margs(int argc, char **argv)
-{
- int fd;
- char *buf;
- unsigned int x;
-
- if (optind == argc)
- die("Usage: gfs_tool margs <mountarguments>\n");
-
- x = strlen(argv[optind]) + 7;
- buf = malloc(x + 1);
- if (!buf)
- die("out of memory\n");
- sprintf(buf, "margs %s\n", argv[optind]);
-
- fd = open("/proc/fs/gfs", O_RDWR);
- if (fd < 0)
- die("can't open /proc/fs/gfs: %s\n",
- strerror(errno));
-
- if (write(fd, buf, x) != x)
- die("can't write margs command: %s\n",
- strerror(errno));
- if (read(fd, buf, x))
- die("can't set mount args: %s\n",
- strerror(errno));
-
- close(fd);
-}
-
-/**
- * print_flags - print the flags in a dinode's di_flags field
- * @di: the dinode structure
- *
- */
-
-static void
-print_flags(struct gfs_dinode *di)
-{
- if (di->di_flags) {
- printf("Flags:\n");
- if (di->di_flags & GFS_DIF_JDATA)
- printf(" jdata\n");
- if (di->di_flags & GFS_DIF_EXHASH)
- printf(" exhash\n");
- if (di->di_flags & GFS_DIF_UNUSED)
- printf(" unused\n");
- if (di->di_flags & GFS_DIF_EA_INDIRECT)
- printf(" ea_indirect\n");
- if (di->di_flags & GFS_DIF_DIRECTIO)
- printf(" directio\n");
- if (di->di_flags & GFS_DIF_IMMUTABLE)
- printf(" immutable\n");
- if (di->di_flags & GFS_DIF_APPENDONLY)
- printf(" appendonly\n");
-#if 0
- if (di->di_flags & GFS_DIF_NOATIME)
- printf(" noatime\n");
- if (di->di_flags & GFS_DIF_SYNC)
- printf(" sync\n");
-#endif
- if (di->di_flags & GFS_DIF_INHERIT_DIRECTIO)
- printf(" inherit_directio\n");
- if (di->di_flags & GFS_DIF_INHERIT_JDATA)
- printf(" inherit_jdata\n");
- }
-}
-
-/**
- * set_flag - set or clear flags in some dinodes
- * @argc:
- * @argv:
- *
- */
-
-void
-set_flag(int argc, char **argv)
-{
- struct gfs_dinode di;
- const char *set;
- char *flag;
- struct gfs_ioctl gi;
- int fd;
- int error;
-
- if (optind == argc) {
- di.di_flags = 0xFFFFFFFF;
- print_flags(&di);
- return;
- }
-
- set = (strcmp(argv[optind - 1], "setflag") == 0) ? "set" : "clear";
- flag = argv[optind++];
-
- for (; optind < argc; optind++) {
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", argv[optind], strerror(errno));
-
- check_for_gfs(fd, argv[optind]);
-
- {
- char *gi_argv[] = {
- (char *)"set_file_flag",
- (char *)set,
- (char *)flag
- };
- gi.gi_argc = 3;
- gi.gi_argv = gi_argv;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error)
- die("can't change flag on %s: %s\n", argv[optind], strerror(errno));
- }
-
- close(fd);
- }
-}
-
-/**
- * print_stat - print out the struct gfs_dinode for a file
- * @argc:
- * @argv:
- *
- */
-
-void
-print_stat(int argc, char **argv)
-{
- int fd;
- char *gi_argv[] = {
- (char *)"get_file_stat"
- };
- struct gfs_ioctl gi;
- struct gfs_dinode di;
- int error;
-
- if (optind == argc)
- die("Usage: gfs_tool stat <filename>\n");
-
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", argv[optind], strerror(errno));
-
- check_for_gfs(fd, argv[optind]);
-
- gi.gi_argc = 1;
- gi.gi_argv = gi_argv;
- gi.gi_data = (char *)&di;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("error doing get_file_stat (%d): %s\n",
- error, strerror(errno));
-
- close(fd);
-
- gfs_dinode_print(&di);
- printf("\n");
- print_flags(&di);
-}
-
-/**
- * print_sb - the superblock
- * @argc:
- * @argv:
- *
- */
-
-void
-print_sb(int argc, char **argv)
-{
- int fd;
- char *gi_argv[] = {
- (char *)"get_super"
- };
- struct gfs_ioctl gi;
- struct gfs_sb sb;
- int error;
-
- if (optind == argc)
- die("Usage: gfs_tool getsb <mountpoint>\n");
-
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", argv[optind], strerror(errno));
-
- check_for_gfs(fd, argv[optind]);
-
- gi.gi_argc = 1;
- gi.gi_argv = gi_argv;
- gi.gi_data = (char *)&sb;
- gi.gi_size = sizeof(struct gfs_sb);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("error doing get_super (%d): %s\n",
- error, strerror(errno));
-
- close(fd);
-
- gfs_sb_print(&sb);
-}
-
-/**
- * print_jindex - print out the journal index
- * @argc:
- * @argv:
- *
- */
-
-void
-print_jindex(int argc, char **argv)
-{
- int fd;
- struct gfs_ioctl gi;
- uint64_t offset;
- unsigned int x;
- int error;
-
-
- if (optind == argc)
- die("Usage: gfs_tool jindex <mountpoint>\n");
-
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", argv[optind], strerror(errno));
-
- check_for_gfs(fd, argv[optind]);
-
-
- {
- char *local_argv[] = {
- (char *)"get_hfile_stat",
- (char *)"jindex"
- };
- struct gfs_dinode di;
-
- gi.gi_argc = 2;
- gi.gi_argv = local_argv;
- gi.gi_data = (char *)&di;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("error doing get_hfile_stat (%d): %s\n",
- error, strerror(errno));
-
- gfs_dinode_print(&di);
- }
-
-
- for (offset = 0, x = 0; ; offset += sizeof(struct gfs_jindex), x++) {
- char *local_argv[] = {
- (char *)"do_hfile_read",
- (char *)"jindex"
- };
- char buf[sizeof(struct gfs_jindex)];
- struct gfs_jindex ji;
-
- gi.gi_argc = 2;
- gi.gi_argv = local_argv;
- gi.gi_data = buf;
- gi.gi_size = sizeof(struct gfs_jindex);
- gi.gi_offset = offset;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (!error)
- break;
- if (error != sizeof(struct gfs_jindex))
- die("error doing do_hfile_read (%d): %s\n",
- error, strerror(errno));
-
- gfs_jindex_in(&ji, buf);
-
- printf("\nJournal %u:\n\n", x);
- gfs_jindex_print(&ji);
- }
-
-
- close(fd);
-}
-
-/**
- * print_rindex - print out the journal index
- * @argc:
- * @argv:
- *
- */
-
-void
-print_rindex(int argc, char **argv)
-{
- int fd;
- struct gfs_ioctl gi;
- uint64_t offset;
- unsigned int x;
- int error;
-
-
- if (optind == argc)
- die("Usage: gfs_tool rindex <mountpoint>\n");
-
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", argv[optind], strerror(errno));
-
- check_for_gfs(fd, argv[optind]);
-
-
- {
- char *local_argv[] = {
- (char *)"get_hfile_stat",
- (char *)"rindex"
- };
- struct gfs_dinode di;
-
- gi.gi_argc = 2;
- gi.gi_argv = local_argv;
- gi.gi_data = (char *)&di;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("error doing get_hfile_stat (%d): %s\n",
- error, strerror(errno));
-
- gfs_dinode_print(&di);
- }
-
-
- for (offset = 0, x = 0; ; offset += sizeof(struct gfs_rindex), x++) {
- char *local_argv[] = {
- (char *)"do_hfile_read",
- (char *)"rindex"
- };
- char buf[sizeof(struct gfs_rindex)];
- struct gfs_rindex ri;
-
- gi.gi_argc = 2;
- gi.gi_argv = local_argv;
- gi.gi_data = buf;
- gi.gi_size = sizeof(struct gfs_rindex);
- gi.gi_offset = offset;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (!error)
- break;
- if (error != sizeof(struct gfs_rindex))
- die("error doing do_hfile_read (%d): %s\n",
- error, strerror(errno));
-
- gfs_rindex_in(&ri, buf);
-
- printf("\nRG %u:\n\n", x);
- gfs_rindex_print(&ri);
- }
-
-
- close(fd);
-}
-
-/**
- * print_quota - print out the journal index
- * @argc:
- * @argv:
- *
- */
-
-void
-print_quota(int argc, char **argv)
-{
- int fd;
- struct gfs_ioctl gi;
- uint64_t offset;
- unsigned int x;
- int error;
-
-
- if (optind == argc)
- die("Usage: gfs_tool quota <mountpoint>\n");
-
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", argv[optind], strerror(errno));
-
- check_for_gfs(fd, argv[optind]);
-
-
- {
- char *local_argv[] = {
- (char *)"get_hfile_stat",
- (char *)"quota"
- };
- struct gfs_dinode di;
-
- gi.gi_argc = 2;
- gi.gi_argv = local_argv;
- gi.gi_data = (char *)&di;
- gi.gi_size = sizeof(struct gfs_dinode);
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (error != gi.gi_size)
- die("error doing get_hfile_stat (%d): %s\n",
- error, strerror(errno));
-
- gfs_dinode_print(&di);
- }
-
-
- for (offset = 0, x = 0; ; offset += sizeof(struct gfs_quota), x++) {
- char *local_argv[] = {
- (char *)"do_hfile_read",
- (char *)"quota"
- };
- char buf[sizeof(struct gfs_quota)];
- struct gfs_quota q;
-
- gi.gi_argc = 2;
- gi.gi_argv = local_argv;
- gi.gi_data = buf;
- gi.gi_size = sizeof(struct gfs_quota);
- gi.gi_offset = offset;
-
- error = ioctl(fd, GFS_IOCTL_SUPER, &gi);
- if (!error)
- break;
- if (error != sizeof(struct gfs_quota))
- die("error doing do_hfile_read (%d): %s\n",
- error, strerror(errno));
-
- gfs_quota_in(&q, buf);
-
- if (q.qu_limit || q.qu_warn || q.qu_value) {
- printf("\nQuota %s %u:\n\n", (x & 1) ? "group" : "user", x >> 1);
- gfs_quota_print(&q);
- }
- }
-
-
- close(fd);
-}
-
-/**
- * print_list - print the list of mounted filesystems
- *
- */
-
-void
-print_list(void)
-{
- char *list = get_list();
- printf("%s", list);
-}
-
-/**
- * reclaim_metadata - reclaim unused metadata blocks
- * @argc:
- * @argv:
- *
- * This routine uses an ioctl command to quiesce the cluster and then
- * hunt down and free all disk inodes that have been freed. This will
- * gain back meta data blocks to be used for data (or metadata) again.
- *
- */
-
-void
-reclaim_metadata(int argc, char **argv)
-{
- int fd;
- char *gi_argv[] = {
- (char *)"do_reclaim"
- };
- struct gfs_ioctl gi;
- char buf[256];
-
- if (optind == argc)
- die("Usage: gfs_tool reclaim <mountpoint>\n");
-
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", argv[optind], strerror(errno));
-
- check_for_gfs(fd, argv[optind]);
-
- if (!override) {
- printf("Don't do this if this file system is being exported by NFS (on any machine).\n");
- printf("\nAre you sure you want to proceed? [y/n] ");
- if (fgets(buf, 255, stdin) == NULL || buf[0] != 'y')
- die("aborted\n");
-
- printf("\n");
- }
-
- gi.gi_argc = 1;
- gi.gi_argv = gi_argv;
- gi.gi_data = buf;
- gi.gi_size = 256;
-
- if (ioctl(fd, GFS_IOCTL_SUPER, &gi) < 0)
- die("error doing do_reclaim: %s\n", strerror(errno));
-
- close(fd);
-
- printf("Reclaimed:\n");
- printf("%s", buf);
-}
-
-/**
- * do_shrink - shrink the inode cache for a filesystem
- * @argc:
- * @argv:
- *
- */
-
-void
-do_shrink(int argc, char **argv)
-{
- int fd;
- char *gi_argv[] = {
- (char *)"do_shrink"
- };
- struct gfs_ioctl gi;
-
- if (optind == argc)
- die("Usage: gfs_tool shrink <mountpoint>\n");
-
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n",
- argv[optind], strerror(errno));
-
- check_for_gfs(fd, argv[optind]);
-
- gi.gi_argc = 1;
- gi.gi_argv = gi_argv;
-
- if (ioctl(fd, GFS_IOCTL_SUPER, &gi))
- die("error doing ioctl: %s\n",
- strerror(errno));
-
- close(fd);
-}
-
-/**
- * do_withdraw - freeze a GFS filesystem
- * @argc:
- * @argv:
- *
- */
-
-void
-do_withdraw(int argc, char **argv)
-{
- char *cookie;
- int fd;
- char buf[256];
- int x;
-
- if (optind == argc)
- die("Usage: gfs_tool withdraw <mountpoint>\n");
-
- cookie = mp2cookie(argv[optind], FALSE);
- x = sprintf(buf, "withdraw %s\n", cookie);
-
- fd = open("/proc/fs/gfs", O_RDWR);
- if (fd < 0)
- die("can't open /proc/fs/gfs: %s\n",
- strerror(errno));
-
- if (write(fd, buf, x) != x)
- die("can't write withdraw command: %s\n",
- strerror(errno));
- if (read(fd, buf, 256))
- die("can't withdraw %s: %s\n",
- argv[optind], strerror(errno));
-
- close(fd);
-}
diff --git a/gfs/gfs_tool/ondisk.c b/gfs/gfs_tool/ondisk.c
deleted file mode 100644
index eeda916..0000000
--- a/gfs/gfs_tool/ondisk.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include "linux_endian.h"
-#include "gfs_ondisk.h"
-
-#define printk printf
-#define pv(struct, member, fmt) \
-printf(" "#member" = "fmt"\n", struct->member);
-
-#define ENTER(x)
-#define EXIT(x)
-#define RET(x) return
-#define RETURN(x, y) return y
-
-#define WANT_GFS_CONVERSION_FUNCTIONS
-#include "gfs_ondisk.h"
-
-
diff --git a/gfs/gfs_tool/parse_lockdump b/gfs/gfs_tool/parse_lockdump
deleted file mode 100644
index 9e77599..0000000
--- a/gfs/gfs_tool/parse_lockdump
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/perl
-
-&do_input(@ARGV);
-
-print 'Entries: ', scalar(@gl), "\n";
-print 'Glocks: ', scalar(keys(%gl)), "\n";
-print 'PIDs: ', scalar(keys(%pid)), "\n";
-print "\n";
-
-for ($x = 0; $x < @gl; $x++)
-{
- if (!$done[$x])
- {
- @chain = &find_chain($x);
- $req = 0;
-
- print scalar(@chain), " chain:\n";
-
- foreach $y (@chain)
- {
- print $gl[$y];
- $req++ if ($gl[$y] =~ /request/i);
- $done[$y]++;
- }
-
- print "$req requests\n";
- print "\n";
-
- $chains++;
- }
-}
-
-for ($x = 0; $x < @gl; $x++)
-{
- die "parse_lockdump: something is hosed\n" unless ($done[$x] == 1);
-}
-
-print "Chains: $chains\n";
-
-
-
-
-
-sub do_input
-{
- my(@host) = @_;
- my($host);
- local(*FILE);
- my($line);
- my($gl);
-
- foreach $host (@host)
- {
- open(FILE, "< $host") || die;
-
- while ($line = <FILE>)
- {
- if ($line eq "\n")
- {
- &file($host, $gl);
- $gl = '';
- }
- else
- {
- $gl .= $line;
- }
- }
-
- if ($gl ne '')
- {
- &file($host, $gl);
- $gl = '';
- }
-
- close(FILE);
- }
-}
-
-
-# Builds:
-#
-# @gl: A list of all the glock sections read in
-# @name: Contains the name of the glock of each member of @gl
-# @pid: Contains the pids contained in each member of @gl
-# %gl: Maps a lockname to the members of @gl that coorespond to that name
-# %pid: Maps a pid to the members of @gl that correspond to that pid
-
-sub file
-{
- my($host, $gl) = @_;
- my($x);
- my($name, $pid);
-
- ($name) = $gl =~ /^Glock (\(.*\))/;
-
- push(@gl, "$host $gl");
- $x = @gl - 1;
- push(@name, $name);
-
- $gl{$name} .= "$x ";
-
- foreach (split("\n", $gl))
- {
- if (/owner = (\d+)/)
- {
- $pid = "$host:$1";
-
- if (!&is_in($pid, split(' ', $pid[$x])))
- {
- $pid[$x] .= "$pid ";
- $pid{$pid} .= "$x ";
- }
- }
- }
-}
-
-
-sub find_chain
-{
- my($x, @chain) = @_;
- my($y, $z);
- my($name, $pid);
-
- $name = $name[$x];
-
- foreach $y (split(' ', $gl{$name}))
- {
- push(@chain, $y);
- }
-
- foreach $y (split(' ', $gl{$name}))
- {
- foreach $pid (split(' ', $pid[$y]))
- {
- foreach $z (split(' ', $pid{$pid}))
- {
- @chain = &find_chain($z, @chain) unless (&is_in($z, @chain));
- }
- }
- }
-
- return @chain;
-}
-
-
-sub is_in
-{
- my($val, @list) = @_;
-
- foreach (@list)
- {
- return 1 if ($_ eq $val);
- }
-
- return 0;
-}
-
-
diff --git a/gfs/gfs_tool/sb.c b/gfs/gfs_tool/sb.c
deleted file mode 100644
index 130e039..0000000
--- a/gfs/gfs_tool/sb.c
+++ /dev/null
@@ -1,152 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-
-#include "gfs_ondisk.h"
-
-#include "gfs_tool.h"
-
-#define do_lseek(fd, off) \
-do { \
- if (lseek((fd), (off), SEEK_SET) != (off)) \
- die("bad seek: %s on line %d of file %s\n", \
- strerror(errno),__LINE__, __FILE__); \
-} while (0)
-
-#define do_read(fd, buff, len) \
-do { \
- if (read((fd), (buff), (len)) != (len)) \
- die("bad read: %s on line %d of file %s\n", \
- strerror(errno), __LINE__, __FILE__); \
-} while (0)
-
-#define do_write(fd, buff, len) \
-do { \
- if (write((fd), (buff), (len)) != (len)) \
- die("bad write: %s on line %d of file %s\n", \
- strerror(errno), __LINE__, __FILE__); \
-} while (0)
-
-/**
- * do_sb - examine/modify a unmounted FS' superblock
- * @argc:
- * @argv:
- *
- */
-
-void
-do_sb(int argc, char **argv)
-{
- char *device, *field, *newval = NULL;
- int fd;
- unsigned char buf[GFS_BASIC_BLOCK];
- char input[256];
- struct gfs_sb sb;
-
- if (optind == argc)
- die("Usage: gfs_tool sb <device> <field> [newval]\n");
-
- device = argv[optind++];
-
- if (optind == argc)
- die("Usage: gfs_tool sb <device> <field> [newval]\n");
-
- field = argv[optind++];
-
- if (optind < argc) {
- if (strcmp(field, "all") == 0)
- die("can't specify new value for \"all\"\n");
- newval = argv[optind++];
- }
-
-
- fd = open(device, (newval) ? O_RDWR : O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", device, strerror(errno));
-
- if (newval && !override) {
- printf("You shouldn't change any of these values if the filesystem is mounted.\n");
- printf("\nAre you sure? [y/n] ");
- if (fgets(input, 255, stdin) == NULL || input[0] != 'y')
- die("aborted\n");
-
- printf("\n");
- }
-
- do_lseek(fd, GFS_SB_ADDR * GFS_BASIC_BLOCK);
- do_read(fd, buf, GFS_BASIC_BLOCK);
-
- gfs_sb_in(&sb, (char *)buf);
-
- if (sb.sb_header.mh_magic != GFS_MAGIC ||
- sb.sb_header.mh_type != GFS_METATYPE_SB)
- die("there isn't a GFS filesystem on %s\n", device);
-
- if (strcmp(field, "proto") == 0) {
- printf("current lock protocol name = \"%s\"\n",
- sb.sb_lockproto);
-
- if (newval) {
- if (strlen(newval) >= GFS_LOCKNAME_LEN)
- die("new lockproto name is too long\n");
- strcpy(sb.sb_lockproto, newval);
- printf("new lock protocol name = \"%s\"\n",
- sb.sb_lockproto);
- }
- } else if (strcmp(field, "table") == 0) {
- printf("current lock table name = \"%s\"\n",
- sb.sb_locktable);
-
- if (newval) {
- if (strlen(newval) >= GFS_LOCKNAME_LEN)
- die("new locktable name is too long\n");
- strcpy(sb.sb_locktable, newval);
- printf("new lock table name = \"%s\"\n",
- sb.sb_locktable);
- }
- } else if (strcmp(field, "ondisk") == 0) {
- printf("current ondisk format = %u\n",
- sb.sb_fs_format);
-
- if (newval) {
- sb.sb_fs_format = atoi(newval);
- printf("new ondisk format = %u\n",
- sb.sb_fs_format);
- }
- } else if (strcmp(field, "multihost") == 0) {
- printf("current multihost format = %u\n",
- sb.sb_multihost_format);
-
- if (newval) {
- sb.sb_multihost_format = atoi(newval);
- printf("new multihost format = %u\n",
- sb.sb_multihost_format);
- }
- } else if (strcmp(field, "all") == 0) {
- gfs_sb_print(&sb);
- newval = FALSE;
- } else
- die("unknown field %s\n", field);
-
- if (newval) {
- gfs_sb_out(&sb, (char *)buf);
-
- do_lseek(fd, GFS_SB_ADDR * GFS_BASIC_BLOCK);
- do_write(fd, buf, GFS_BASIC_BLOCK);
-
- fsync(fd);
-
- printf("Done\n");
- }
-
- close(fd);
-}
diff --git a/gfs/gfs_tool/tune.c b/gfs/gfs_tool/tune.c
deleted file mode 100644
index 9e3af67..0000000
--- a/gfs/gfs_tool/tune.c
+++ /dev/null
@@ -1,141 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-
-#define __user
-#include "gfs_ioctl.h"
-
-#include "gfs_tool.h"
-
-#define SIZE (4096)
-
-/**
- * get_tune - print out the current tuneable parameters for a filesystem
- * @argc:
- * @argv:
- *
- */
-
-void
-get_tune(int argc, char **argv)
-{
- int fd;
- char *gi_argv[] = {
- (char *)"get_tune"
- };
- struct gfs_ioctl gi;
- char str[SIZE], str2[SIZE];
- char **lines, **l;
-
- if (optind == argc)
- die("Usage: gfs_tool gettune <mountpoint>\n");
-
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0)
- die("can't open file %s: %s\n",
- argv[optind], strerror(errno));
-
- check_for_gfs(fd, argv[optind]);
-
- gi.gi_argc = 1;
- gi.gi_argv = gi_argv;
- gi.gi_data = str;
- gi.gi_size = SIZE;
-
- if (ioctl(fd, GFS_IOCTL_SUPER, &gi) < 0)
- die("error doing get_tune: %s\n",
- strerror(errno));
-
- close(fd);
-
- strcpy(str2, str);
- lines = str2lines(str2);
-
- for (l = lines; **l; l++) {
- char *p;
- for (p = *l; *p; p++)
- if (*p == ' ') {
- *p++ = 0;
- break;
- }
-
- if (strcmp(*l, "version") == 0)
- continue;
- if (strcmp(*l, "quota_scale_num") == 0) {
- printf("quota_scale = %.4f (%u, %u)\n",
- (double)name2u32(str, "quota_scale_num") / name2u32(str, "quota_scale_den"),
- name2u32(str, "quota_scale_num"), name2u32(str, "quota_scale_den"));
- continue;
- }
- if (strcmp(*l, "quota_scale_den") == 0)
- continue;
-
- printf("%s = %s\n", *l, p);
- }
-}
-
-/**
- * set_tune - set a tuneable parameter
- * @argc:
- * @argv:
- *
- */
-
-void
-set_tune(int argc, char **argv)
-{
- char *mp, *param, *value;
- int fd;
- struct gfs_ioctl gi;
- char buf[256];
-
- if (optind == argc)
- die("Usage: gfs_tool settune <mountpoint> <parameter> <value>\n");
- mp = argv[optind++];
- if (optind == argc)
- die("Usage: gfs_tool settune <mountpoint> <parameter> <value>\n");
- param = argv[optind++];
- if (optind == argc)
- die("Usage: gfs_tool settune <mountpoint> <parameter> <value>\n");
- value = argv[optind++];
-
- fd = open(mp, O_RDONLY);
- if (fd < 0)
- die("can't open file %s: %s\n",
- mp, strerror(errno));
-
- check_for_gfs(fd, mp);
-
- if (strcmp(param, "quota_scale") == 0) {
- float s;
- sscanf(value, "%f", &s);
- sprintf(buf, "%u %u", (unsigned int)(s * 10000.0 + 0.5), 10000);
- value = buf;
- }
-
- {
- char *local_argv[] = {
- (char *)"set_tune",
- (char *)param,
- (char *)value
- };
-
- gi.gi_argc = 3;
- gi.gi_argv = local_argv;
-
- if (ioctl(fd, GFS_IOCTL_SUPER, &gi))
- die("can't change tunable parameter %s: %s\n",
- param, strerror(errno));
- }
-
- close(fd);
-}
diff --git a/gfs/gfs_tool/util.c b/gfs/gfs_tool/util.c
deleted file mode 100644
index f467b7e..0000000
--- a/gfs/gfs_tool/util.c
+++ /dev/null
@@ -1,272 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-#include <libgen.h>
-
-#define __user
-#include "gfs_ioctl.h"
-#include "gfs_ondisk.h"
-
-#include "gfs_tool.h"
-
-/**
- * check_for_gfs - Check to see if a descriptor is a file on a GFS filesystem
- * @fd: the file descriptor
- * @path: the path used to open the descriptor
- *
- */
-
-void
-check_for_gfs(int fd, char *path)
-{
- unsigned int magic = 0;
- int error;
-
- error = ioctl(fd, GFS_IOCTL_IDENTIFY, &magic);
- if (error || magic != GFS_MAGIC)
- die("%s is not a GFS file/filesystem\n",
- path);
-}
-
-/**
- * get_list - Get the list of GFS filesystems
- *
- * Returns: a NULL terminated string
- */
-
-#define LIST_SIZE (1048576)
-
-char *
-get_list(void)
-{
- char *list;
- int fd;
- int x;
-
- list = malloc(LIST_SIZE);
- if (!list)
- die("out of memory\n");
-
- fd = open("/proc/fs/gfs", O_RDWR);
- if (fd < 0)
- die("can't open /proc/fs/gfs: %s\n",
- strerror(errno));
-
- if (write(fd, "list", 4) != 4)
- die("can't write list command: %s\n",
- strerror(errno));
- x = read(fd, list, LIST_SIZE - 1);
- if (x < 0)
- die("can't get list of filesystems: %s\n",
- strerror(errno));
-
- close(fd);
-
- list[x] = 0;
-
- return list;
-}
-
-/**
- * str2lines - parse a string into lines
- * @list: the list
- *
- * Returns: An array of character pointers
- */
-
-char **
-str2lines(char *str)
-{
- char *p;
- unsigned int n = 0;
- char **lines;
- unsigned int x = 0;
-
- for (p = str; *p; p++)
- if (*p == '\n')
- n++;
-
- lines = malloc((n + 1) * sizeof(char *));
- if (!lines)
- die("out of memory\n");
-
- for (lines[x] = p = str; *p; p++)
- if (*p == '\n') {
- *p = 0;
- lines[++x] = p + 1;
- }
-
- return lines;
-}
-
-/**
- * mp2cookie - Find the cookie for a filesystem given its mountpoint
- * @mp:
- * @ioctl_ok: If this is FALSE, it's not acceptable to open() the mountpoint
- *
- * Returns: the cookie
- */
-
-char *
-mp2cookie(char *mp, int ioctl_ok)
-{
- char *cookie;
- char *list, **lines;
- FILE *file;
- char line[256], device[256], dev_id[256];
- unsigned int x;
- struct stat st;
-
- cookie = malloc(256);
- if (!cookie)
- die("out of memory\n");
- list = get_list();
- lines = str2lines(list);
-
- file = fopen("/proc/mounts", "r");
- if (!file)
- die("can't open /proc/mounts: %s\n",
- strerror(errno));
-
- memset(dev_id, 0, sizeof(dev_id));
- while (fgets(line, 256, file)) {
- char path[256], type[256];
-
- if (sscanf(line, "%s %s %s", device, path, type) != 3)
- continue;
- if (strcmp(path, mp))
- continue;
- if (strcmp(type, "gfs"))
- die("%s is not a GFS filesystem\n", mp);
-
- if (stat(device, &st))
- continue;
- sprintf(dev_id, "%u:%u", major(st.st_rdev),minor(st.st_rdev));
- break;
- }
-
- fclose(file);
-
- for (x = 0; *lines[x]; x++) {
- char device_id[256];
- sscanf(lines[x], "%s %s", cookie, device_id);
- if (dev_id[0]) {
- if (strcmp(device_id, dev_id) == 0)
- return cookie;
- } else {
- if (strcmp(cookie, mp) == 0)
- return cookie;
- }
- }
-
- if (ioctl_ok) {
- struct gfs_ioctl gi;
- char *argv[] = {
- (char *)"get_cookie"
- };
- int fd;
-
- gi.gi_argc = 1;
- gi.gi_argv = argv;
- gi.gi_data = cookie;
- gi.gi_size = 256;
-
- fd = open(mp, O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n",
- mp, strerror(errno));
-
- check_for_gfs(fd, mp);
-
- if (ioctl(fd, GFS_IOCTL_SUPER, &gi) < 0)
- die("can't get cookie for %s: %s\n",
- mp, strerror(errno));
-
- close(fd);
-
- return cookie;
- }
-
- die("unknown mountpoint %s\n", mp);
-}
-
-/**
- * name2value - find the value of a name-value pair in a string
- * @str_in:
- * @name:
- *
- * Returns: the value string in a static buffer
- */
-
-char *
-name2value(char *str_in, const char *name)
-{
- char str[strlen(str_in) + 1];
- static char value[256];
- char **lines;
- unsigned int x;
- unsigned int len = strlen(name);
-
- strcpy(str, str_in);
- value[0] = 0;
-
- lines = str2lines(str);
-
- for (x = 0; *lines[x]; x++)
- if (memcmp(lines[x], name, len) == 0 &&
- lines[x][len] == ' ') {
- strcpy(value, lines[x] + len + 1);
- break;
- }
-
- free(lines);
-
- return value;
-}
-
-/**
- * name2u32 - find the value of a name-value pair in a string
- * @str_in:
- * @name:
- *
- * Returns: the value uint32
- */
-
-uint32_t
-name2u32(char *str, const char *name)
-{
- char *value = name2value(str, name);
- uint32_t x = 0;
-
- sscanf(value, "%u", &x);
-
- return x;
-}
-
-/**
- * name2u64 - find the value of a name-value pair in a string
- * @str_in:
- * @name:
- *
- * Returns: the value uint64
- */
-
-uint64_t
-name2u64(char *str, const char *name)
-{
- char *value = name2value(str, name);
- uint64_t x = 0;
-
- sscanf(value, "%"SCNu64, &x);
-
- return x;
-}
diff --git a/gfs/include/global.h b/gfs/include/global.h
deleted file mode 100644
index 02c3eff..0000000
--- a/gfs/include/global.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef __GLOBAL_DOT_H__
-#define __GLOBAL_DOT_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#if defined(__KERNEL__) || defined(_KERNEL)
-#error "don't use global.h in kernel space"
-#endif
-
-
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-
-
-#include <inttypes.h>
-
-typedef uint64_t uint64;
-typedef uint32_t uint32;
-typedef uint16_t uint16;
-typedef uint8_t uint8;
-typedef int64_t int64;
-typedef int32_t int32;
-typedef int16_t int16;
-typedef int8_t int8;
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __GLOBAL_H__ */
diff --git a/gfs/include/linux_endian.h b/gfs/include/linux_endian.h
deleted file mode 100644
index 43089d2..0000000
--- a/gfs/include/linux_endian.h
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef __LINUX_ENDIAN_DOT_H__
-#define __LINUX_ENDIAN_DOT_H__
-
-
-#include <endian.h>
-#include <byteswap.h>
-
-
-/* I'm not sure which versions of alpha glibc/gcc are broken,
- so fix all of them. */
-#ifdef __alpha__
-#undef bswap_64
-static __inline__ unsigned long bswap_64(unsigned long x)
-{
- unsigned int h = x >> 32;
- unsigned int l = x;
-
- h = bswap_32(h);
- l = bswap_32(l);
-
- return ((unsigned long)l << 32) | h;
-}
-#endif /* __alpha__ */
-
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-
-#define be16_to_cpu(x) (x)
-#define be32_to_cpu(x) (x)
-#define be64_to_cpu(x) (x)
-
-#define cpu_to_be16(x) (x)
-#define cpu_to_be32(x) (x)
-#define cpu_to_be64(x) (x)
-
-#define le16_to_cpu(x) (bswap_16((x)))
-#define le32_to_cpu(x) (bswap_32((x)))
-#define le64_to_cpu(x) (bswap_64((x)))
-
-#define cpu_to_le16(x) (bswap_16((x)))
-#define cpu_to_le32(x) (bswap_32((x)))
-#define cpu_to_le64(x) (bswap_64((x)))
-
-#endif /* __BYTE_ORDER == __BIG_ENDIAN */
-
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-
-#define be16_to_cpu(x) (bswap_16((x)))
-#define be32_to_cpu(x) (bswap_32((x)))
-#define be64_to_cpu(x) (bswap_64((x)))
-
-#define cpu_to_be16(x) (bswap_16((x)))
-#define cpu_to_be32(x) (bswap_32((x)))
-#define cpu_to_be64(x) (bswap_64((x)))
-
-#define le16_to_cpu(x) (x)
-#define le32_to_cpu(x) (x)
-#define le64_to_cpu(x) (x)
-
-#define cpu_to_le16(x) (x)
-#define cpu_to_le32(x) (x)
-#define cpu_to_le64(x) (x)
-
-#endif /* __BYTE_ORDER == __LITTLE_ENDIAN */
-
-
-#endif /* __LINUX_ENDIAN_DOT_H__ */
diff --git a/gfs/include/list.h b/gfs/include/list.h
deleted file mode 100644
index 566b377..0000000
--- a/gfs/include/list.h
+++ /dev/null
@@ -1,325 +0,0 @@
-/* Copied from include/linux/list.h */
-
-#ifndef _LINUX_LIST_H
-#define _LINUX_LIST_H
-
-/**
- * container_of - cast a member of a structure out to the containing structure
- *
- * @ptr: the pointer to the member.
- * @type: the type of the container struct this is embedded in.
- * @member: the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
-
-/*
- * These are non-NULL pointers that will result in page faults
- * under normal circumstances, used to verify that nobody uses
- * non-initialized list entries.
- */
-#define LIST_POISON1 ((void *) 0x00100100)
-#define LIST_POISON2 ((void *) 0x00200200)
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
-
-#define INIT_LIST_HEAD(ptr) do { \
- (ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head * prev, struct list_head * next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty on entry does not return true after this, the entry is
- * in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
-}
-
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
- */
-static inline void list_del_init(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- INIT_LIST_HEAD(entry);
-}
-
-/**
- * list_move - delete from one list and add as another's head
- * @list: the entry to move
- * @head: the head that will precede our entry
- */
-static inline void list_move(struct list_head *list, struct list_head *head)
-{
- __list_del(list->prev, list->next);
- list_add(list, head);
-}
-
-/**
- * list_move_tail - delete from one list and add as another's tail
- * @list: the entry to move
- * @head: the head that will follow our entry
- */
-static inline void list_move_tail(struct list_head *list,
- struct list_head *head)
-{
- __list_del(list->prev, list->next);
- list_add_tail(list, head);
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(const struct list_head *head)
-{
- return head->next == head;
-}
-
-/**
- * list_empty_careful - tests whether a list is
- * empty _and_ checks that no other CPU might be
- * in the process of still modifying either member
- *
- * NOTE: using list_empty_careful() without synchronization
- * can only be safe if the only activity that can happen
- * to the list entry is list_del_init(). Eg. it cannot be used
- * if another CPU could re-list_add() it.
- *
- * @head: the list to test.
- */
-static inline int list_empty_careful(const struct list_head *head)
-{
- struct list_head *next = head->next;
- return (next == head) && (next == head->prev);
-}
-
-static inline void __list_splice(struct list_head *list,
- struct list_head *head)
-{
- struct list_head *first = list->next;
- struct list_head *last = list->prev;
- struct list_head *at = head->next;
-
- first->prev = head;
- head->next = first;
-
- last->next = at;
- at->prev = last;
-}
-
-/**
- * list_splice - join two lists
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-static inline void list_splice(struct list_head *list, struct list_head *head)
-{
- if (!list_empty(list))
- __list_splice(list, head);
-}
-
-/**
- * list_splice_init - join two lists and reinitialise the emptied list.
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- *
- * The list at @list is reinitialised
- */
-static inline void list_splice_init(struct list_head *list,
- struct list_head *head)
-{
- if (!list_empty(list)) {
- __list_splice(list, head);
- INIT_LIST_HEAD(list);
- }
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
- container_of(ptr, type, member)
-
-/**
- * list_for_each - iterate over a list
- * @pos: the &struct list_head to use as a loop counter.
- * @head: the head for your list.
- */
-#define list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * __list_for_each - iterate over a list
- * @pos: the &struct list_head to use as a loop counter.
- * @head: the head for your list.
- *
- * This variant differs from list_for_each() in that it's the
- * simplest possible list iteration code, no prefetching is done.
- * Use this for code that knows the list to be very short (empty
- * or 1 entry) most of the time.
- */
-#define __list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * list_for_each_prev - iterate over a list backwards
- * @pos: the &struct list_head to use as a loop counter.
- * @head: the head for your list.
- */
-#define list_for_each_prev(pos, head) \
- for (pos = (head)->prev; pos != (head); pos = pos->prev)
-
-/**
- * list_for_each_safe - iterate over a list safe against removal of list entry
- * @pos: the &struct list_head to use as a loop counter.
- * @n: another &struct list_head to use as temporary storage
- * @head: the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
- for (pos = (head)->next, n = pos->next; pos != (head); \
- pos = n, n = pos->next)
-
-/**
- * list_for_each_entry - iterate over list of given type
- * @pos: the type * to use as a loop counter.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_reverse - iterate backwards over list of given type.
- * @pos: the type * to use as a loop counter.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry_reverse(pos, head, member) \
- for (pos = list_entry((head)->prev, typeof(*pos), member); \
- &pos->member != (head); \
- pos = list_entry(pos->member.prev, typeof(*pos), member))
-
-/**
- * list_prepare_entry - prepare a pos entry for use as a start point in
- * list_for_each_entry_continue
- * @pos: the type * to use as a start point
- * @head: the head of the list
- * @member: the name of the list_struct within the struct.
- */
-#define list_prepare_entry(pos, head, member) \
- ((pos) ? : list_entry(head, typeof(*pos), member))
-
-/**
- * list_for_each_entry_continue - iterate over list of given type
- * continuing after existing point
- * @pos: the type * to use as a loop counter.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry_continue(pos, head, member) \
- for (pos = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos: the type * to use as a loop counter.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-
-#endif
diff --git a/gfs/include/osi_list.h b/gfs/include/osi_list.h
deleted file mode 100644
index 3b1483b..0000000
--- a/gfs/include/osi_list.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef __OSI_LIST_DOT_H__
-#define __OSI_LIST_DOT_H__
-
-
-
-struct osi_list
-{
- struct osi_list *next, *prev;
-};
-typedef struct osi_list osi_list_t;
-
-
-
-#define osi_list_decl(var) osi_list_t var = { &var, &var }
-
-#define osi_list_empty(var) ((var)->next == (var))
-#define osi_list_entry(var, type, mem) ((type *)((unsigned long)(var) - (unsigned long)(&((type *)NULL)->mem)))
-
-
-
-#define osi_list_init(head) \
-do \
-{ \
- osi_list_t *osi_list_var = (head); \
- osi_list_var->next = osi_list_var->prev = osi_list_var; \
-} \
-while (0)
-
-#define osi_list_add(new, head) \
-do \
-{ \
- osi_list_t *osi_list_var_new = (new); \
- osi_list_t *osi_list_var_head = (head); \
- osi_list_var_new->next = osi_list_var_head->next; \
- osi_list_var_new->prev = osi_list_var_head; \
- osi_list_var_head->next->prev = osi_list_var_new; \
- osi_list_var_head->next = osi_list_var_new; \
-} \
-while (0)
-
-#define osi_list_add_next osi_list_add
-
-#define osi_list_add_prev(new, head) \
-do \
-{ \
- osi_list_t *osi_list_var_new = (new); \
- osi_list_t *osi_list_var_head = (head); \
- osi_list_var_new->prev = osi_list_var_head->prev; \
- osi_list_var_new->next = osi_list_var_head; \
- osi_list_var_head->prev->next = osi_list_var_new; \
- osi_list_var_head->prev = osi_list_var_new; \
-} \
-while (0)
-
-#define osi_list_del(var) \
-do \
-{ \
- osi_list_t *osi_list_var = (var); \
- osi_list_var->next->prev = osi_list_var->prev; \
- osi_list_var->prev->next = osi_list_var->next; \
-} \
-while (0)
-
-#define osi_list_del_init(var) \
-do \
-{ \
- osi_list_t *osi_list_var = (var); \
- osi_list_var->next->prev = osi_list_var->prev; \
- osi_list_var->prev->next = osi_list_var->next; \
- osi_list_var->next = osi_list_var->prev = osi_list_var; \
-} \
-while (0)
-
-#define osi_list_foreach(tmp, head) \
- for ((tmp) = (head)->next; (tmp) != (head); (tmp) = (tmp)->next)
-
-#define osi_list_foreach_safe(tmp, head, x) \
- for ((tmp) = (head)->next, (x) = (tmp)->next; \
- (tmp) != (head); \
- (tmp) = (x), (x) = (x)->next)
-
-
-
-#endif /* __OSI_LIST_DOT_H__ */
diff --git a/gfs/include/osi_user.h b/gfs/include/osi_user.h
deleted file mode 100644
index 34964ed..0000000
--- a/gfs/include/osi_user.h
+++ /dev/null
@@ -1,421 +0,0 @@
-#ifndef __OSI_USER_DOT_H__
-#define __OSI_USER_DOT_H__
-
-/* Include Files
- These should only be the ones necessary to compile the common code. */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <time.h>
-#include <sys/ioctl.h>
-
-#include "global.h"
-#include "osi_list.h"
-
-
-
-/* Memory allocation abstraction */
-
-static __inline__ void *osi_malloc(unsigned int size)
-{
- return malloc(size);
-}
-
-static __inline__ void osi_free(void *data, unsigned int size)
-{
- free(data);
-}
-
-
-
-/* Memory copy abstraction */
-
-#define osi_copy_to_user(uaddr, kaddr, len) (memcpy((uaddr), (kaddr), (len)) ? 0 : -EFAULT)
-#define osi_clear_user(uaddr, len) ((memset((uaddr), 0, (len))) ? 0 : -EFAULT)
-#define osi_copy_from_user(kaddr, uaddr, len) ((memcpy((kaddr), (uaddr), (len))) ? 0 : -EFAULT)
-#define osi_strncpy_from_user(kaddr, uaddr, len) ((strncpy((kaddr), (uaddr), (len))) ? 0 : -EFAULT)
-
-#define osi_read_access_ok(uaddr, len) (TRUE)
-#define osi_write_access_ok(uaddr, len) (TRUE)
-
-#define osi_memset memset
-#define osi_memcpy memcpy
-#define osi_memcmp memcmp
-
-#define osi_strlen strlen
-#define osi_strstr strstr
-#define osi_strcmp strcmp
-#define osi_strncmp strncmp
-#define osi_strtok strtok
-#define osi_strchr strchr
-#define osi_strcpy strcpy
-#define osi_strncpy strncpy
-#define osi_strcasecmp strcasecmp
-#define osi_strtod strtod
-#define osi_strtol strtol
-
-
-
-/* printf() abstraction */
-
-#define osi_printf printf
-#define osi_sprintf sprintf
-#define osi_snprintf snprintf
-#define osi_vsnprintf vsnprintf
-
-#define osi_sscanf sscanf
-
-#define osi_fprintf fprintf
-
-#define osi_tty_printf printf
-
-
-
-/* panic abstractions */
-
-#define panic(fmt, args...) \
-{ \
- fprintf(stderr, "%s: ", prog_name); \
- fprintf(stderr, fmt, ## args); \
- exit(-1); \
-}
-
-#define osi_panic panic
-#define osi_bug(x) \
-{ \
- fprintf(stderr, "%s: BUG: %s\n", prog_name, (x)); \
- exit(-1); \
-}
-
-
-
-/* GFS to VFS abstraction */
-
-typedef int osi_vfs_t;
-typedef int osi_vnode_t;
-typedef int osi_vfile_t;
-
-#define vf2vn(vfile) ((osi_vnode_t *)(vfile))
-#define vn2vfs(vnode) ((osi_vfs_t *)(vnode))
-
-
-
-/* I/O abstraction */
-
-struct buffer_head
-{
- unsigned long b_blocknr;
- unsigned long b_size;
- unsigned long b_state;
- char *b_data;
- char *b_pdata;
- osi_list_t b_list;
-};
-typedef struct buffer_head osi_buf_t;
-
-
-
-/* Device type abstraction */
-
-typedef unsigned short osi_dev_t;
-
-#define osi_make_dev MKDEV
-#define osi_u2k_dev
-#define osi_k2u_dev
-
-
-
-/* Atomic Bit Manipulation interface */
-
-struct osi_bitfield
-{
- unsigned long bitfield;
-};
-typedef struct osi_bitfield osi_bitfield_t;
-
-#define osi_test_bit(nr, addr) ((addr)->bitfield & (1 << nr))
-#define osi_set_bit(nr, addr) ((addr)->bitfield |= (1 << nr))
-#define osi_clear_bit(nr, addr) ((addr)->bitfield &= ~(1 << nr))
-#define osi_test_and_set_bit(nr, addr) ((addr)->bitfield |= (1 << nr))
-#define osi_test_and_clear_bit(nr, addr) ((addr)->bitfield &= ~(1 << nr))
-
-
-
-/* Atomic Counter Interface */
-
-struct osi_atomic
-{
- int atomic;
-};
-typedef struct osi_atomic osi_atomic_t;
-
-#define osi_atomic_inc(x) ((x)->atomic += 1)
-#define osi_atomic_dec(x) ((x)->atomic -= 1)
-#define osi_atomic_read(x) ((x)->atomic)
-#define osi_atomic_dec_and_test(x) ((x)->atomic -= 1)
-#define osi_atomic_set(x, y) ((x)->atomic = (y))
-
-
-
-/* Endianness conversion abstraction */
-
-#include "linux_endian.h"
-
-
-
-/* Filename structure */
-
-struct osi_filename
-{
- unsigned char *name;
- unsigned int len;
-};
-typedef struct osi_filename osi_filename_t;
-
-
-
-/* Sleeping mutual exclusion primitive abstraction
-
- All macros take a pointer to a osi_mutex_t structure.
- osi_mutex_down_try() returns TRUE if the down() succeeds
- */
-
-typedef int osi_mutex_t;
-
-#define osi_mutex_init(x)
-#define osi_mutex_init_lkd(x)
-
-#define osi_mutex_lock(x)
-#define osi_mutex_lock_intr(x)
-#define osi_mutex_trylock(x) (TRUE)
-#define osi_mutex_unlock(x)
-
-
-
-/* Reader/writer Sleeping mutual exclusion primitive abstraction */
-
-typedef int osi_mutex_rw_t;
-
-#define osi_mutex_rw_init(x)
-
-#define osi_mutex_read_lock(x)
-#define osi_mutex_write_lock(x)
-#define osi_mutex_read_trylock(x) (0)
-#define osi_mutex_write_trylock(x) (0)
-#define osi_mutex_read_unlock(x)
-#define osi_mutex_write_unlock(x)
-
-
-
-/* Spinlock abstraction */
-
-typedef int osi_spin_t;
-
-#define osi_spin_init(lock)
-
-#define osi_spin_lock(lock)
-#define osi_spin_unlock(lock)
-#define osi_spin_trylock(lock) (TRUE)
-
-
-
-/* RW-Spinlock abstraction */
-
-typedef int osi_spin_rw_t;
-
-#define osi_spin_rw_init(lock)
-
-#define osi_spin_read_lock(lock)
-#define osi_spin_write_lock(lock)
-#define osi_spin_read_unlock(lock)
-#define osi_spin_write_unlock(lock)
-#define osi_spin_write_trylock(lock) (TRUE)
-
-
-
-/* Process abstraction */
-
-#define osi_pid() 1
-#define osi_pname() ("main")
-
-typedef int osi_task_t;
-
-#define osi_task_is_set(taskp) (*(taskp))
-#define osi_task_is_me(taskp) (TRUE)
-#define osi_task_is_equal(task1p, task2p) (TRUE)
-#define osi_task_to_pid(taskp) (1)
-#define osi_task_to_pname(taskp) ("main")
-
-#define osi_task_clear(taskp) do { *(taskp) = 0; } while (0)
-#define osi_task_remember_me(taskp) do { *(taskp) = 1; } while (0)
-#define osi_task_sleep(taskp, x) do { } while (0)
-#define osi_task_wakeup(taskp) do { } while (0)
-
-
-
-/* Kernel Thead code */
-
-#define osi_daemonize(thread_name)
-#define osi_undaemonize()
-
-
-
-/* Time abstraction */
-
-#define osi_current_time() time(NULL)
-
-static __inline__ uint64 osi_gettimeofday(void)
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (uint64)tv.tv_sec * 1000000 + tv.tv_usec;
-}
-
-struct osi_clock_ticks
-{
- unsigned long value;
-};
-typedef struct osi_clock_ticks osi_clock_ticks_t;
-
-static __inline__ void osi_time_stamp(osi_clock_ticks_t *stamp)
-{
-}
-
-static __inline__ int osi_check_timeout(osi_clock_ticks_t *stamp, int seconds)
-{
- return 0;
-}
-
-static __inline__ unsigned int osi_time_diff(osi_clock_ticks_t *stamp)
-{
- return FALSE;
-}
-
-static __inline__ int osi_time_valid(osi_clock_ticks_t *stamp)
-{
- return FALSE;
-}
-
-
-
-/* Timer abstraction */
-
-
-typedef int osi_timer_t;
-typedef void (osi_timer_func)(void *);
-typedef void (linux_timer_func)(unsigned long);
-
-static __inline__ void osi_init_timer(osi_timer_t *t, osi_timer_func *fp, void *data)
-{
-}
-
-static __inline__ void osi_del_timer(osi_timer_t *t)
-{
-}
-
-static __inline__ void osi_set_timer(osi_timer_t *t, unsigned long sec)
-{
-}
-
-static __inline__ void osi_set_deci_timer(osi_timer_t *t, unsigned long dsec)
-{
-}
-
-static __inline__ int osi_timer_pending(osi_timer_t *t)
-{
- return -ENOSYS;
-}
-
-
-
-/* Schedule abstraction - Macro that makes a process temporarily
- give up control of the processor and lets other processes have
- a change to run.
- Sleep abstraction - Sleep for x number of sections. */
-
-#define osi_schedule()
-#define osi_sleep(x)
-#define osi_sleep_intr(x)
-
-
-
-/* Wait queue abstraction */
-
-typedef int osi_wchan_t;
-
-#define osi_wchan_init(x) do { } while (0)
-#define osi_wchan_cond_sleep(chan, sleep_cond) do { } while (0)
-#define osi_wchan_cond_sleep_intr(chan, sleep_cond) do { } while (0)
-#define osi_wchan_wakeup(x) do { } while (0)
-
-
-
-/* Completion events */
-
-struct osi_completion
-{
-};
-typedef struct osi_completion osi_completion_t;
-
-#define osi_completion_init(x) do { } while (0)
-
-#define osi_wait_for_completion(x) do { } while (0)
-#define osi_complete(x) do { } while (0)
-
-
-
-/* Credentials structure */
-
-struct osi_cred
-{
- uint32 cr_uid;
- uint32 cr_gid;
-};
-typedef struct osi_cred osi_cred_t;
-
-#define osi_cred_to_uid(credp) ((credp) ? (credp)->cr_uid : 0)
-#define osi_cred_to_gid(credp) ((credp) ? (credp)->cr_gid : 0)
-#define osi_cred_in_group(credp, gid) ((credp) ? ((cred)->cr_gid == (gid)) : FALSE)
-
-
-
-/* Signals abstraction */
-
-#define osi_pending_signals() FALSE
-
-
-
-/* Weird errnos */
-
-#define ERESTARTSYS EINTR
-
-
-
-/* Module stuff */
-
-typedef int osi_module_t;
-
-#define osi_module_this (NULL)
-
-#define osi_module_init(mod) do { } while (0)
-#define osi_module_inc(mod) do { } while (0)
-#define osi_module_inc_cond(mod) (FALSE)
-#define osi_module_dec(mod) do { } while (0)
-#define osi_module_busy(mod) (TRUE)
-
-
-
-/* Other Stuff */
-
-extern char *prog_name;
-
-#define OSI_CACHE_ALIGNED
-
-
-
-#endif /* __OSI_USER_DOT_H__ */
-
diff --git a/gfs/init.d/Makefile b/gfs/init.d/Makefile
deleted file mode 100644
index 097d83c..0000000
--- a/gfs/init.d/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-TARGET= gfs
-
-INITDT=$(TARGET)
-
-all: $(TARGET)
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-$(TARGET): $(S)/$(TARGET).in
- cat $(S)/$(TARGET).in | sed \
- -e 's#@SBINDIR@#${sbindir}#g' \
- -e 's#@INITDDIR@#${initddir}#g' \
- > $(TARGET)
-
-clean: generalclean
diff --git a/gfs/init.d/gfs.in b/gfs/init.d/gfs.in
deleted file mode 100644
index 31104b4..0000000
--- a/gfs/init.d/gfs.in
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/bin/bash
-#
-# gfs mount/unmount helper
-#
-# chkconfig: - 26 74
-# description: mount/unmount gfs filesystems configured in /etc/fstab
-
-### BEGIN INIT INFO
-# Provides: gfs
-# Required-Start: $network cman
-# Required-Stop: $network cman
-# Default-Start:
-# Default-Stop:
-# Short-Description: mount/unmount gfs filesystems configured in /etc/fstab
-# Description: mount/unmount gfs filesystems configured in /etc/fstab
-### END INIT INFO
-
-# set secure PATH
-PATH="/bin:/usr/bin:/sbin:/usr/sbin:@SBINDIR@"
-
-success()
-{
- echo -ne "[ OK ]\r"
-}
-
-failure()
-{
- echo -ne "[FAILED]\r"
-}
-
-# rpm based distros
-if [ -d /etc/sysconfig ]; then
- [ -f @INITDDIR@/functions ] && . @INITDDIR@/functions
- [ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster
- [ -f /etc/sysconfig/gfs ] && . /etc/sysconfig/gfs
- [ -z "$LOCK_FILE" ] && LOCK_FILE="/var/lock/subsys/gfs"
-fi
-
-# deb based distros
-if [ -d /etc/default ]; then
- [ -f /etc/default/cluster ] && . /etc/default/cluster
- [ -f /etc/default/gfs ] && . /etc/default/gfs
- [ -z "$LOCK_FILE" ] && LOCK_FILE="/var/lock/gfs"
-fi
-
-#
-# This script's behavior is modeled closely after the netfs script.
-#
-GFSFSTAB=$(LC_ALL=C awk '!/^#/ && $3 == "gfs" && $4 !~ /noauto/ { print $2 }' /etc/fstab)
-GFSMTAB=$(LC_ALL=C awk '!/^#/ && $3 == "gfs" && $2 != "/" { print $2 }' /proc/mounts)
-
-# See how we were called.
-case "$1" in
- start)
- if [ -n "$GFSFSTAB" ]
- then
- echo -n "Mounting GFS filesystems: "
- mount -a -t gfs
- rtrn=$?
- if [ $rtrn = 0 ]; then
- touch $LOCK_FILE
- success
- echo
- else
- failure
- echo
- fi
- fi
- ;;
-
- stop)
- if [ -n "$GFSMTAB" ]
- then
- sig=
- retry=6
- remaining=`LC_ALL=C awk '!/^#/ && $3 == "gfs" && $2 != "/" {print $2}' /proc/mounts`
- while [ -n "$remaining" -a "$retry" -gt 0 ]
- do
- echo -n "Unmounting GFS filesystems: "
- umount -a -t gfs
- rtrn=$?
- if [ $rtrn = 0 ]; then
- success
- echo
- else
- failure
- echo
- fi
-
- if [ $retry -eq 0 ]
- then
- echo -n "Unmounting GFS filesystems (lazy): "
- umount -l -a -t gfs
- rtrn=$?
- if [ $rtrn = 0 ]; then
- success
- echo
- else
- failure
- echo
- fi
- break
- fi
-
- sleep 2
- remaining=`LC_ALL=C awk '!/^#/ && $3 == "gfs" && $2 != "/" {print $2}' /proc/mounts`
- [ -z "$remaining" ] && break
- fuser -k -m $sig $remaining > /dev/null 2>&1
- sleep 10
- retry=$(($retry - 1))
- sig=-9
- done
- fi
-
- modprobe -r gfs
- rm -f $LOCK_FILE
- ;;
-
- status)
- if [ -f /proc/mounts ]
- then
- [ -n "$GFSFSTAB" ] && {
- echo "Configured GFS mountpoints: "
- for fs in $GFSFSTAB; do echo $fs ; done
- }
- [ -n "$GFSMTAB" ] && {
- echo "Active GFS mountpoints: "
- for fs in $GFSMTAB; do echo $fs ; done
- }
- else
- echo "/proc filesystem unavailable"
- fi
- ;;
-
- restart)
- $0 stop
- $0 start
- ;;
-
- reload|force-reload)
- $0 start
- ;;
- *)
- echo $"Usage: $0 {start|stop|restart|reload|status}"
- exit 1
-esac
-
-exit 0
diff --git a/gfs/libgfs/Makefile b/gfs/libgfs/Makefile
deleted file mode 100644
index bae9954..0000000
--- a/gfs/libgfs/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-TARGET=libgfs
-
-MAKESTATICLIB = 1
-
-OBJS= bio.o \
- bitmap.o \
- block_list.o \
- file.o \
- fs_bits.o \
- fs_bmap.o \
- fs_dir.o \
- fs_inode.o \
- inode.o \
- log.o \
- ondisk.o \
- rgrp.o \
- size.o \
- super.o \
- util.o
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/libs.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
-CFLAGS += -D_GNU_SOURCE -DHELPER_PROGRAM
-CFLAGS += -c
-CFLAGS += -I${KERNEL_SRC}/fs/gfs2/ -I${KERNEL_SRC}/include/
-CFLAGS += -I${gfskincdir} -I$(S)/../include
-CFLAGS += -I${incdir}
diff --git a/gfs/libgfs/bio.c b/gfs/libgfs/bio.c
deleted file mode 100644
index 673fc1a..0000000
--- a/gfs/libgfs/bio.c
+++ /dev/null
@@ -1,167 +0,0 @@
-#include <stdint.h>
-#include "list.h"
-#include "gfs_ondisk.h"
-#include "libgfs.h"
-
-/*
- * get_buf - get a buffer
- * @sdp: the super block
- * @blkno: blk # that this buffer will be associated with
- * @bhp: the location where the buffer is returned
- *
- * This function allocates space for a buffer head structure
- * and the corresponding data. It does not fill in the
- * actual data - that is done by read_buf.
- *
- * Returns: 0 on success, -1 on error
- */
-int get_buf(uint32_t sb_bsize, uint64 blkno, osi_buf_t **bhp)
-{
- osi_buf_t *bh = NULL;
-
- *bhp = NULL;
- bh = (osi_buf_t *)malloc(sizeof(osi_buf_t));
- if(!bh){
- log_err("Unable to allocate memory for new buffer head.\n");
- return -1;
- }
- if(!memset(bh, 0, sizeof(osi_buf_t))) {
- log_err("Unable to zero buffer head\n");
- return -1;
- }
-
- /* FIXME: Not sure how this will work on all
- * architectures without the casts */
- bh->b_blocknr = blkno;
- bh->b_size = sb_bsize;
- bh->b_state = 0;
- if(!(bh->b_data = malloc(BH_SIZE(bh)))) {
- free(bh);
- log_err("Unable to allocate memory for new buffer "
- "blkno = %"PRIu64", size = %u\n", blkno, BH_SIZE(bh));
- return -1;
- }
- if(!memset(BH_DATA(bh), 0, BH_SIZE(bh))) {
- free(bh);
- log_err("Unable to zero memory for new buffer "
- "blkno = %"PRIu64", size = %u\n", blkno, BH_SIZE(bh));
- }
-
- *bhp = bh;
-
- return 0;
-}
-
-
-/*
- * relse_buf - release a buffer
- * @sdp: the super block
- * @bh: the buffer to release
- *
- * This function will release the memory of the buffer
- * and associated buffer head.
- *
- * Returns: nothing
- */
-void relse_buf(osi_buf_t *bh){
- if(bh){
- if(BH_DATA(bh)) {
- free(BH_DATA(bh));
- bh->b_data = NULL;
- }
- free(bh);
- bh = NULL;
- }
-}
-
-
-/*
- * read_buf - read a buffer
- * @sdp: the super block
- * @blkno: block number
- * @bhp: place where buffer is returned
- * @flags:
- *
- * Returns 0 on success, -1 on error
- */
-int read_buf(int disk_fd, osi_buf_t *bh, int flags){
-
- if(do_lseek(disk_fd, (uint64)(BH_BLKNO(bh)*BH_SIZE(bh)))){
- log_err("Unable to seek to position %"PRIu64" "
- "(%"PRIu64" * %u) on storage device.\n",
- (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)),
- BH_BLKNO(bh), BH_SIZE(bh));
- return -1;
- }
-
- if(do_read(disk_fd, BH_DATA(bh), BH_SIZE(bh))){
- log_err("Unable to read %u bytes from position %"PRIu64"\n",
- BH_SIZE(bh), (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)));
- return -1;
- }
-
- return 0;
-}
-
-
-/*
- * write_buf - write a buffer
- * @sdp: the super block
- * @bh: buffer head that describes buffer to write
- * @flags: flags that determine usage
- *
- * Returns: 0 on success, -1 on failure
- */
-int write_buf(int disk_fd, osi_buf_t *bh, int flags){
-
- if(do_lseek(disk_fd, (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)))) {
- log_err("Unable to seek to position %"PRIu64
- "(%"PRIu64" * %u) on storage device.\n",
- (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)),
- BH_BLKNO(bh), BH_SIZE(bh));
- return -1;
- }
-
- log_debug("Writing to %"PRIu64" - %"PRIu64" %u\n",
- (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)),
- BH_BLKNO(bh), BH_SIZE(bh));
- if(do_write(disk_fd, BH_DATA(bh), BH_SIZE(bh))) {
- log_err("Unable to write %u bytes to position %"PRIu64"\n",
- BH_SIZE(bh), (uint64)(BH_BLKNO(bh) * BH_SIZE(bh)));
- return -1;
- }
-
- if(flags & BW_WAIT){
- fsync(disk_fd);
- }
-
- return 0;
-}
-
-
-/*
- * get_and_read_buf - combines get_buf and read_buf functions
- * @sdp
- * @blkno
- * @bhp
- * @flags
- *
- * Returns: 0 on success, -1 on error
- */
-int get_and_read_buf(int disk_fd, uint32_t sb_bsize, uint64 blkno,
- osi_buf_t **bhp, int flags)
-{
- if(get_buf(sb_bsize, blkno, bhp)) {
- stack;
- return -1;
- }
-
- if(read_buf(disk_fd, *bhp, flags)){
- stack;
- relse_buf(*bhp);
- *bhp = NULL; /* guarantee that ptr is NULL in failure cases */
- return -1;
- }
-
- return 0;
-}
diff --git a/gfs/libgfs/bitmap.c b/gfs/libgfs/bitmap.c
deleted file mode 100644
index 4d983a3..0000000
--- a/gfs/libgfs/bitmap.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Basic bitmap manipulation */
-#include <stdint.h>
-#include <stdio.h>
-#include <errno.h>
-#include "osi_user.h"
-#include "libgfs.h"
-#include "incore.h"
-
-
-#define BITMAP_SIZE(size, cpb) (size / cpb)
-
-#define BITMAP_BYTE_OFFSET(x, map) ((x % map->chunks_per_byte) \
- * map->chunksize )
-
-#define BITMAP_MASK(chunksize) ((2 << (chunksize - 1)) - 1)
-
-uint64_t bitmap_size(struct bmap *bmap) {
- return bmap->size;
-}
-
-int bitmap_create(struct bmap *bmap, uint64_t size, uint8_t chunksize)
-{
- if((((chunksize >> 1) << 1) != chunksize) && chunksize != 1) {
- log_err("chunksize must be a power of 2\n");
- return -1;
- }
- if(chunksize > 8) {
- log_err("chunksize must be <= 8\n");
- return -1;
- }
- bmap->chunksize = chunksize;
- bmap->chunks_per_byte = 8 / chunksize;
-
- bmap->size = size;
-
- /* Have to add 1 to BITMAP_SIZE since it's 0-based and mallocs
- * must be 1-based */
- bmap->mapsize = BITMAP_SIZE(size, bmap->chunks_per_byte)+1;
-
- if(!(bmap->map = malloc(sizeof(char) * bmap->mapsize))) {
- log_err("Unable to allocate bitmap of size %"PRIu64"\n",
- bmap->mapsize);
- return ENOMEM;
- }
- if(!memset(bmap->map, 0, sizeof(char) * bmap->mapsize)) {
- log_err("Unable to zero bitmap of size %"PRIu64"\n",
- bmap->mapsize);
- free(bmap->map);
- bmap->map = NULL;
- return ENOMEM;
- }
- log_debug("Allocated bitmap of size %"PRIu64
- " with %d chunks per byte\n",
- bmap->mapsize, bmap->chunks_per_byte);
- return 0;
-}
-
-int bitmap_set(struct bmap *bmap, uint64_t offset, uint8_t val)
-{
- char *byte = NULL;
- uint64_t b = offset;
-
- if(offset < bmap->size) {
- byte = bmap->map + BITMAP_SIZE(offset, bmap->chunks_per_byte);
- b = BITMAP_BYTE_OFFSET(offset, bmap);
-
- *byte |= (val & BITMAP_MASK(bmap->chunksize)) << b;
- return 0;
- }
- log_debug("offset %d out of bounds\n", offset);
- return -1;
-}
-
-int bitmap_get(struct bmap *bmap, uint64_t bit, uint8_t *val)
-{
- char *byte = NULL;
- uint64_t b = bit;
-
- if(bit < bmap->size) {
- byte = bmap->map + BITMAP_SIZE(bit, bmap->chunks_per_byte);
- b = BITMAP_BYTE_OFFSET(bit, bmap);
-
- *val = (*byte & (BITMAP_MASK(bmap->chunksize) << b )) >> b;
- return 0;
- }
- log_debug("offset %d out of bounds\n", bit);
- return -1;
-}
-
-
-int bitmap_clear(struct bmap *bmap, uint64_t offset)
-{
- char *byte = NULL;
- uint64_t b = offset;
-
- if(offset < bmap->size) {
- byte = bmap->map + BITMAP_SIZE(offset, bmap->chunks_per_byte);
- b = BITMAP_BYTE_OFFSET(offset, bmap);
-
- *byte &= ~(BITMAP_MASK(bmap->chunksize) << b);
- return 0;
- }
- log_debug("offset %d out of bounds\n", offset);
- return -1;
-
-}
-
-void bitmap_destroy(struct bmap *bmap)
-{
- if(bmap->map)
- free(bmap->map);
- bmap->size = 0;
- bmap->mapsize = 0;
- bmap->chunksize = 0;
- bmap->chunks_per_byte = 0;
-}
diff --git a/gfs/libgfs/block_list.c b/gfs/libgfs/block_list.c
deleted file mode 100644
index 28047a6..0000000
--- a/gfs/libgfs/block_list.c
+++ /dev/null
@@ -1,267 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <inttypes.h>
-#include "libgfs.h"
-#include "gfs_ondisk.h"
-
-#define FREE (0x0) /* 0000 */
-#define BLOCK_IN_USE (0x1) /* 0001 */
-
-#define DIR_INDIR_BLK (0x2) /* 0010 */
-#define DIR_INODE (0x3) /* 0011 */
-#define FILE_INODE (0x4) /* 0100 */
-#define LNK_INODE (0x5)
-#define BLK_INODE (0x6)
-#define CHR_INODE (0x7)
-#define FIFO_INODE (0x8)
-#define SOCK_INODE (0x9)
-#define DIR_LEAF_INODE (0xA) /* 1010 */
-#define JOURNAL_BLK (0xB) /* 1011 */
-#define OTHER_META (0xC) /* 1100 */
-#define FREE_META (0xD) /* 1101 */
-#define EATTR_META (0xE) /* 1110 */
-
-#define INVALID_META (0xF) /* 1111 */
-
-
-/* Must be kept in sync with mark_block enum in block_list.h */
-/* FIXME: Fragile */
-static int mark_to_gbmap[16] = {
- FREE, BLOCK_IN_USE, DIR_INDIR_BLK, DIR_INODE, FILE_INODE,
- LNK_INODE, BLK_INODE, CHR_INODE, FIFO_INODE, SOCK_INODE,
- DIR_LEAF_INODE, JOURNAL_BLK, OTHER_META, FREE_META,
- EATTR_META, INVALID_META
-};
-
-struct block_list *block_list_create(uint64_t size, enum block_list_type type)
-{
- struct block_list *il;
- log_info("Creating a block list of size %"PRIu64"...\n", size);
-
- if ((il = malloc(sizeof(*il)))) {
- if(!memset(il, 0, sizeof(*il))) {
- log_err("Cannot set block list to zero\n");
- return NULL;
- }
- il->type = type;
-
- switch(type) {
- case gbmap:
- if(bitmap_create(&il->list.gbmap.group_map, size, 4)) {
- stack;
- free(il);
- il = NULL;
- }
- if(bitmap_create(&il->list.gbmap.bad_map, size, 1)) {
- stack;
- free(il);
- il = NULL;
- }
- if(bitmap_create(&il->list.gbmap.dup_map, size, 1)) {
- stack;
- free(il);
- il = NULL;
- }
- if(bitmap_create(&il->list.gbmap.eattr_map, size, 1)) {
- stack;
- free(il);
- il = NULL;
- }
- break;
- default:
- log_crit("Block list type %d not implemented\n",
- type);
- break;
- }
- }
-
- return il;
-}
-
-int block_mark(struct block_list *il, uint64_t block, enum mark_block mark)
-{
- int err = 0;
-
- switch(il->type) {
- case gbmap:
- if(mark == bad_block) {
- err = bitmap_set(&il->list.gbmap.bad_map, block, 1);
- }
- else if(mark == dup_block) {
- err = bitmap_set(&il->list.gbmap.dup_map, block, 1);
- }
- else if(mark == eattr_block) {
- err = bitmap_set(&il->list.gbmap.eattr_map, block, 1);
- }
- else {
- err = bitmap_set(&il->list.gbmap.group_map, block,
- mark_to_gbmap[mark]);
- }
-
- break;
- default:
- log_err("block list type %d not implemented\n",
- il->type);
- err = -1;
- break;
- }
- return err;
-}
-
-int block_set(struct block_list *il, uint64_t block, enum mark_block mark)
-{
- int err = 0;
- err = block_clear(il, block, mark);
- if(!err)
- err = block_mark(il, block, mark);
- return err;
-}
-
-int block_clear(struct block_list *il, uint64_t block, enum mark_block m)
-{
- int err = 0;
-
- switch(il->type) {
- case gbmap:
- switch (m) {
- case dup_block:
- err = bitmap_clear(&il->list.gbmap.dup_map, block);
- break;
- case bad_block:
- err = bitmap_clear(&il->list.gbmap.bad_map, block);
- break;
- case eattr_block:
- err = bitmap_clear(&il->list.gbmap.eattr_map, block);
- break;
- default:
- /* FIXME: check types */
- err = bitmap_clear(&il->list.gbmap.group_map, block);
- break;
- }
-
- break;
- default:
- log_err("block list type %d not implemented\n",
- il->type);
- err = -1;
- break;
- }
- return err;
-}
-
-int block_check(struct block_list *il, uint64_t block, struct block_query *val)
-{
- int err = 0;
- val->block_type = 0;
- val->bad_block = 0;
- val->dup_block = 0;
- switch(il->type) {
- case gbmap:
- if((err = bitmap_get(&il->list.gbmap.group_map, block,
- &val->block_type))) {
- log_err("Unable to get block type for block %"
- PRIu64"\n", block);
- break;
- }
- if((err = bitmap_get(&il->list.gbmap.bad_map, block,
- &val->bad_block))) {
- log_err("Unable to get bad block status for block %"
- PRIu64"\n", block);
- break;
- }
- if((err = bitmap_get(&il->list.gbmap.dup_map, block,
- &val->dup_block))) {
- log_err("Unable to get duplicate status for block %"
- PRIu64"\n", block);
- break;
- }
- if((err = bitmap_get(&il->list.gbmap.eattr_map, block,
- &val->eattr_block))) {
- log_err("Unable to get eattr status for block %"
- PRIu64"\n", block);
- break;
- }
- break;
- default:
- log_err("block list type %d not implemented\n",
- il->type);
- err = -1;
- break;
- }
-
- return err;
-}
-
-void *block_list_destroy(struct block_list *il)
-{
- if(il) {
- switch(il->type) {
- case gbmap:
- bitmap_destroy(&il->list.gbmap.group_map);
- bitmap_destroy(&il->list.gbmap.bad_map);
- bitmap_destroy(&il->list.gbmap.dup_map);
- bitmap_destroy(&il->list.gbmap.eattr_map);
- break;
- default:
- break;
- }
- free(il);
- il = NULL;
- }
- return il;
-}
-
-
-int find_next_block_type(struct block_list *il, enum mark_block m, uint64_t *b)
-{
- uint64_t i;
- uint8_t val;
- int found = 0;
- for(i = *b; ; i++) {
- switch(il->type) {
- case gbmap:
- if(i >= bitmap_size(&il->list.gbmap.dup_map))
- return -1;
-
- switch(m) {
- case dup_block:
- if(bitmap_get(&il->list.gbmap.dup_map, i,
- &val)) {
- stack;
- return -1;
- }
-
- if(val)
- found = 1;
- break;
- case eattr_block:
- if(bitmap_get(&il->list.gbmap.eattr_map, i,
- &val)) {
- stack;
- return -1;
- }
-
- if(val)
- found = 1;
- break;
- default:
- /* FIXME: add support for getting
- * other types */
- log_err("Unhandled block type\n");
- }
- break;
- default:
- log_err("Unhandled block list type\n");
- break;
- }
- if(found) {
- *b = i;
- return 0;
- }
- }
- return -1;
-}
diff --git a/gfs/libgfs/file.c b/gfs/libgfs/file.c
deleted file mode 100644
index 7707cdf..0000000
--- a/gfs/libgfs/file.c
+++ /dev/null
@@ -1,233 +0,0 @@
-#include <stdint.h>
-#include "gfs_ondisk.h"
-#include "libgfs.h"
-
-/**
- * readi - Read a file
- * @ip: The GFS Inode
- * @buf: The buffer to place result into
- * @offset: File offset to begin reading from
- * @size: Amount of data to transfer
- *
- * Returns: The amount of data actually copied or the error
- */
-int readi(int disk_fd, struct gfs_inode *ip, void *bufin, uint64 offset,
- unsigned int size)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- osi_buf_t *bh;
- uint64_t lblock, dblock=0;
- uint32_t extlen = 0;
- unsigned int amount;
- int not_new = 0;
- int journaled = fs_is_jdata(ip);
- int copied = 0;
- int error = 0;
- char *buf = bufin;
-
- if (offset >= ip->i_di.di_size){
- log_debug("readi: Offset (%"PRIu64") is >= "
- "the file size (%"PRIu64").\n",
- offset, ip->i_di.di_size);
- goto out;
- }
-
- if ((offset + size) > ip->i_di.di_size)
- size = ip->i_di.di_size - offset;
-
- if (!size){
- log_err("readi: Nothing to be read.\n");
- goto out;
- }
-
- if (journaled){
- lblock = offset / sdp->sd_jbsize;
- offset %= sdp->sd_jbsize;
- }
- else{
- lblock = offset >> sdp->sd_sb.sb_bsize_shift;
- offset &= sdp->sd_sb.sb_bsize - 1;
- }
-
- if (fs_is_stuffed(ip))
- offset += sizeof(struct gfs_dinode);
- else if (journaled)
- offset += sizeof(struct gfs_meta_header);
-
-
- while (copied < size){
- amount = size - copied;
- if (amount > sdp->sd_sb.sb_bsize - offset)
- amount = sdp->sd_sb.sb_bsize - offset;
-
- if (!extlen){
- error = fs_block_map(disk_fd, ip, lblock, ¬_new, &dblock, &extlen);
- if (error){
- log_err("readi: The call to fs_block_map() failed.\n");
- goto out;
- }
- }
-
- if (dblock){
- error = get_and_read_buf(disk_fd, ip->i_sbd->sd_sb.sb_bsize,
- dblock, &bh, 0);
- if (error){
- log_err("readi: Unable to perform get_and_read_buf()\n");
- goto out;
- }
-
- dblock++;
- extlen--;
- }
- else
- bh = NULL;
-
- if (bh){
- memcpy(buf+copied, BH_DATA(bh)+offset, amount);
- relse_buf(bh);
- } else {
- memset(buf+copied, 0, amount);
- }
- copied += amount;
- lblock++;
-
- offset = (journaled) ? sizeof(struct gfs_meta_header) : 0;
- }
-
- out:
-
- return (error < 0) ? error : copied;
-}
-
-
-
-/**
- * writei - Write bytes to a file
- * @ip: The GFS inode
- * @buf: The buffer containing information to be written
- * @offset: The file offset to start writing at
- * @size: The amount of data to write
- *
- * Returns: The number of bytes correctly written or error code
- */
-int writei(int disk_fd, struct gfs_inode *ip, void *bufin, uint64_t offset,
- unsigned int size)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- osi_buf_t *dibh, *bh;
- uint64_t lblock, dblock;
- uint32_t extlen = 0;
- unsigned int amount;
- int new;
- int journaled = fs_is_jdata(ip);
- const uint64_t start = offset;
- int copied = 0;
- int error = 0;
- char *buf = bufin;
-
- /* Bomb out on writing nothing.
- Posix says we can't change the time here. */
-
- if (!size)
- goto fail; /* Not really an error */
-
-
- if (fs_is_stuffed(ip) &&
- ((start + size) > (sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode)))){
- error = fs_unstuff_dinode(disk_fd, ip);
- if (error)
- goto fail;
- }
-
-
- if (journaled){
- lblock = offset / sdp->sd_jbsize;
- offset %= sdp->sd_jbsize;
- }
- else{
- lblock = offset >> sdp->sd_sb.sb_bsize_shift;
- offset &= sdp->sd_sb.sb_bsize - 1;
- }
-
- if (fs_is_stuffed(ip))
- offset += sizeof(struct gfs_dinode);
- else if (journaled)
- offset += sizeof(struct gfs_meta_header);
-
-
- while (copied < size){
- amount = size - copied;
- if (amount > sdp->sd_sb.sb_bsize - offset)
- amount = sdp->sd_sb.sb_bsize - offset;
-
- if (!extlen){
- new = TRUE;
- error = fs_block_map(disk_fd, ip, lblock, &new, &dblock, &extlen);
- if (error)
- goto fail;
- if(!dblock){
- log_crit("fs_writei: "
- "Unable to map logical block to real block.\n");
- log_crit("Uncircumventable error.\n");
- exit(EXIT_FAILURE);
- }
- }
-
- error = get_and_read_buf(disk_fd, ip->i_sbd->sd_sb.sb_bsize, dblock,
- &bh, 0);
- if (error)
- goto fail;
-
- if(journaled && dblock != ip->i_di.di_num.no_addr ) {
- set_meta(bh, GFS_METATYPE_JD, GFS_FORMAT_JD);
- }
-
- memcpy(BH_DATA(bh)+offset, buf+copied, amount);
- write_buf(disk_fd, bh, 0);
- relse_buf(bh);
-
- copied += amount;
- lblock++;
- dblock++;
- extlen--;
-
- offset = (journaled) ? sizeof(struct gfs_meta_header) : 0;
- }
-
-
- out:
- error = get_and_read_buf(disk_fd, ip->i_sbd->sd_sb.sb_bsize,
- ip->i_num.no_addr, &dibh, 0);
- if (error){
- log_err("fs_writei: "
- "Unable to get inode buffer.\n");
- return -1;
- }
-
- error = check_meta(dibh, GFS_METATYPE_DI);
- if(error){
- log_err("fs_writei: "
- "Buffer is not a valid inode.\n");
- relse_buf(dibh);
- return -1;
- }
-
- if (ip->i_di.di_size < start + copied)
- ip->i_di.di_size = start + copied;
- ip->i_di.di_mtime = ip->i_di.di_ctime = osi_current_time();
-
- gfs_dinode_out(&ip->i_di, (char *)BH_DATA(dibh));
- write_buf(disk_fd, dibh, 0);
- relse_buf(dibh);
-
- return copied;
-
-
-
- fail:
- if (copied)
- goto out;
-
- return error;
-}
-
diff --git a/gfs/libgfs/fs_bits.c b/gfs/libgfs/fs_bits.c
deleted file mode 100644
index db6f36d..0000000
--- a/gfs/libgfs/fs_bits.c
+++ /dev/null
@@ -1,348 +0,0 @@
-#include "incore.h"
-#include "libgfs.h"
-/**
- * fs_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
- *
- */
-static void fs_setbit(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 / GFS_NBBY);
- bit = (block % GFS_NBBY) * GFS_BIT_SIZE;
- end = buffer + buflen;
-
- if(byte >= end){
- log_err("fs_setbit: byte >= end\n");
- exit(1);
- }
- cur_state = (*byte >> bit) & GFS_BIT_MASK;
-
- *byte ^= cur_state << bit;
- *byte |= new_state << bit;
-}
-
-static uint32_t fs_bitfit_core(struct gfs_sbd *sbp, uint64_t goal, uint64_t start,
- uint64_t len, unsigned char old_state)
-{
- uint64_t block;
- struct block_query q;
-
- log_debug("Goal: %"PRIu64", Start: %"PRIu64" len: %"PRIu64"\n",
- goal, start, len);
- for(block = start+goal; block < start+len; block++) {
- block_check(sbp->bl, block, &q);
- switch(old_state) {
- case GFS_BLKST_FREE:
- switch(q.block_type) {
- case block_free:
- return block - start;
- }
- break;
- case GFS_BLKST_FREEMETA:
- switch(q.block_type) {
- case meta_free:
- return block - start;
- }
- break;
- case GFS_BLKST_USEDMETA:
- switch(q.block_type) {
- case inode_dir:
- case inode_file:
- case inode_lnk:
- case inode_blk:
- case inode_chr:
- case inode_fifo:
- case inode_sock:
- case indir_blk:
- case leaf_blk:
- case journal_blk:
- case meta_other:
- case meta_eattr:
- return block - start;
- }
- break;
- case GFS_BLKST_USED:
- switch(q.block_type) {
- case block_used:
- return block - start;
- }
- break;
- default:
- log_err("Invalid type");
- break;
- }
- }
- return BFITNOENT;
-}
-/**
- * fs_bitfit - Find a free block in the bitmaps
- * @buffer: the buffer that holds the bitmaps
- * @buflen: the length (in bytes) of the buffer
- * @goal: the block to try to allocate
- * @old_state: the state of the block we're looking for
- *
- * Return: the block number that was allocated
- */
-uint32_t fs_bitfit(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 / GFS_NBBY);
- bit = (goal % GFS_NBBY) * GFS_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) & GFS_BIT_MASK) == old_state){
- return blk;
- }
-
- bit += GFS_BIT_SIZE;
- if (bit >= 8){
- bit = 0;
- byte++;
- }
-
- blk++;
- }
- return BFITNOENT;
-}
-
-/**
- * fs_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 fs_bitcount(unsigned char *buffer, unsigned int buflen,
- unsigned char state)
-{
- unsigned char *byte, *end;
- unsigned int bit;
- uint32_t count = 0;
-
- byte = buffer;
- bit = 0;
- end = buffer + buflen;
-
- while (byte < end){
- if (((*byte >> bit) & GFS_BIT_MASK) == state)
- count++;
-
- bit += GFS_BIT_SIZE;
- if (bit >= 8){
- bit = 0;
- byte++;
- }
- }
- return count;
-}
-
-
-/**
- * fs_blkalloc_internal - allocate a single block
- * @rgd: the resource group descriptor
- * @goal: the goal block in the RG
- * @old_state: the type of block to find
- * @new_state: the resulting block type
- * @do_it: if FALSE, we just find the block we would allocate
- *
- *
- * Returns: returns the block allocated, or BFITNOENT on failure
- */
-uint32_t fs_blkalloc_internal(struct gfs_rgrpd *rgd, uint32_t goal,
- unsigned char old_state,
- unsigned char new_state, int do_it)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- uint32_t block = 0;
- log_debug("fs_blkalloc_internal got %u as goal\n", goal);
- goal = ((int)(goal - rgd->rd_ri.ri_data1) < 0)
- ? 0
- : goal - rgd->rd_ri.ri_data1;
-
-
- block = fs_bitfit_core(sdp, goal, rgd->rd_ri.ri_data1,
- rgd->rd_ri.ri_data, old_state);
-
-
- if(block == BFITNOENT) {
- log_debug("No bits left in old_state?\n"
- "\told_state = %u\n"
- "\tnew_state = %u\n"
- "\trg_free = %u\n"
- "\trg_freemeta = %u\n",
- old_state, new_state,
- rgd->rd_rg.rg_free,
- rgd->rd_rg.rg_freemeta);
- return BFITNOENT;
- }
-
- log_debug("fs_blkalloc_internal found block %u\n", block);
- switch(new_state) {
- case GFS_BLKST_FREE:
- block_set(sdp->bl, block + rgd->rd_ri.ri_data1, block_free);
- break;
- case GFS_BLKST_USED:
- block_set(sdp->bl, block + rgd->rd_ri.ri_data1, block_used);
- break;
- case GFS_BLKST_USEDMETA:
- block_set(sdp->bl, block + rgd->rd_ri.ri_data1, meta_other);
- break;
- case GFS_BLKST_FREEMETA:
- block_set(sdp->bl, block + rgd->rd_ri.ri_data1, meta_free);
- break;
- }
- return block;
-}
-
-
-/*
- * fs_get_bitmap - get value of FS bitmap
- * @sdp: super block
- * @blkno: block number relative to file system
- *
- * This function gets the value of a bit of the
- * file system bitmap.
- * Possible state values for a block in the bitmap are:
- * GFS_BLKST_FREE (0)
- * GFS_BLKST_USED (1)
- * GFS_BLKST_FREEMETA (2)
- * GFS_BLKST_USEDMETA (3)
- *
- * Returns: state on success, -1 on error
- */
-int fs_get_bitmap(int disk_fd, struct gfs_sbd *sdp, uint64 blkno, struct gfs_rgrpd *rgd){
- int buf, val;
- uint32_t rgrp_block;
-/* struct gfs_rgrpd *rgd;*/
- struct gfs_bitmap *bits = NULL;
- unsigned int bit;
- unsigned char *byte;
- int local_rgd = 0;
-
- if(check_range(sdp, blkno)){
- log_warn("Block #%"PRIu64" is out of range.\n", blkno);
- return -1;
- }
- if(rgd == NULL) {
- local_rgd = 1;
- rgd = fs_blk2rgrpd(sdp, blkno);
- }
- if(rgd == NULL){
- log_err( "Unable to get rgrp for block #%"PRIu64"\n", blkno);
- return -1;
- }
- if(fs_rgrp_read(disk_fd, rgd, FALSE)){ /* FALSE:don't try to fix (done elsewhere) */
- log_err( "Unable to read rgrp.\n");
- return -1;
- }
-
- rgrp_block = (uint32_t)(blkno - rgd->rd_ri.ri_data1);
-
- for(buf= 0; buf < rgd->rd_ri.ri_length; buf++){
- bits = &(rgd->rd_bits[buf]);
- if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS_NBBY)){
- break;
- }
- }
-
- if(buf >= rgd->rd_ri.ri_length){
- log_err( "Unable to locate bitmap entry for block #%"PRIu64"\n",
- blkno);
- fs_rgrp_relse(rgd);
- return -1;
- }
-
- byte = (unsigned char *)((BH_DATA(rgd->rd_bh[buf]) + bits->bi_offset) +
- (rgrp_block/GFS_NBBY - bits->bi_start));
- bit = (rgrp_block % GFS_NBBY) * GFS_BIT_SIZE;
-
- val = ((*byte >> bit) & GFS_BIT_MASK);
- if(local_rgd) {
- fs_rgrp_relse(rgd);
- }
-
- return val;
-}
-
-
-/*
- * fs_set_bitmap
- * @sdp: super block
- * @blkno: block number relative to file system
- * @state: one of 4 possible states
- *
- * This function sets the value of a bit of the
- * file system bitmap.
- *
- * Returns: 0 on success, -1 on error
- */
-int fs_set_bitmap(int disk_fd, struct gfs_sbd *sdp, uint64 blkno, int state)
-{
- int buf;
- uint32_t rgrp_block;
- struct gfs_bitmap *bits = NULL;
- struct gfs_rgrpd *rgd;
-
- if((state != GFS_BLKST_FREE) && (state != GFS_BLKST_USED) &&
- (state != GFS_BLKST_FREEMETA) && (state != GFS_BLKST_USEDMETA)){
- return -1;
- }
-
- rgd = fs_blk2rgrpd(sdp, blkno);
-
- if(!rgd) {
- log_err("Unable to get resource group for blkno %"PRIu64"\n",
- blkno);
- return -1;
- }
-
- if(fs_rgrp_read(disk_fd, rgd, FALSE)) {
- stack;
- return -1;
- }
- rgrp_block = (uint32_t)(blkno - rgd->rd_ri.ri_data1);
- for(buf= 0; buf < rgd->rd_ri.ri_length; buf++){
- bits = &(rgd->rd_bits[buf]);
- if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS_NBBY)){
- break;
- }
- }
-
- fs_setbit((unsigned char *)BH_DATA(rgd->rd_bh[buf]) + bits->bi_offset,
- bits->bi_len,
- (rgrp_block - (bits->bi_start*GFS_NBBY)),
- state);
-
-
- if(write_buf(disk_fd, rgd->rd_bh[buf], 0)){
- fs_rgrp_relse(rgd);
- return -1;
- }
-
- fs_rgrp_relse(rgd);
- return 0;
-}
diff --git a/gfs/libgfs/fs_bmap.c b/gfs/libgfs/fs_bmap.c
deleted file mode 100644
index a75f774..0000000
--- a/gfs/libgfs/fs_bmap.c
+++ /dev/null
@@ -1,522 +0,0 @@
-#include "libgfs.h"
-
-typedef struct metapath
-{
- uint64 mp_list[GFS_MAX_META_HEIGHT];
-}metapath_t;
-
-
-/**
- * fs_unstuff_dinode - Unstuff a dinode when the data has grown too big
- * @ip: The GFS inode to unstuff
- * * This routine unstuffs a dinode and returns it to a "normal" state such
- * that the height can be grown in the traditional way.
- *
- * Returns: 0 on success, -EXXXX on failure
- */
-int fs_unstuff_dinode(int disk_fd, struct gfs_inode *ip)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- osi_buf_t *bh = NULL;
- osi_buf_t *dibh = NULL;
- int journaled = fs_is_jdata(ip);
- uint64 block = 0;
- int error;
-
- log_debug("Unstuffing inode %"PRIu64" - %u\n", ip->i_di.di_num.no_addr,
- journaled);
-
- if(!fs_is_stuffed(ip)){
- log_err("Trying to unstuff a dinode that is already unstuffed.\n");
- return -1;
- }
- error = get_and_read_buf(disk_fd, sdp->sd_sb.sb_bsize, ip->i_num.no_addr,
- &dibh, 0);
- if (error) {
- stack;
- goto fail;
- }
-
- error = check_meta(dibh, GFS_METATYPE_DI);
- if(error) {
- stack;
- goto fail;
- }
-
- if (ip->i_di.di_size){
- log_err("Allocating new block for unstuffed dinode\n");
- if(journaled){
- error = fs_metaalloc(disk_fd, ip, &block);
- if (error) {
- stack;
- goto fail;
- }
- log_err("Got block %"PRIu64"\n", block);
- error = get_buf(sdp->sd_sb.sb_bsize, block, &bh);
- if (error) {
- stack;
- goto fail;
- }
-
- set_meta(bh, GFS_METATYPE_JD, GFS_FORMAT_JD);
-
- memcpy(BH_DATA(bh)+sizeof(struct gfs_meta_header),
- BH_DATA(dibh)+sizeof(struct gfs_dinode),
- BH_SIZE(dibh)-sizeof(struct gfs_dinode));
-
- error = write_buf(disk_fd, bh, 0);
- if(error) {
- stack;
- goto fail;
- }
- relse_buf(bh);
- block_set(sdp->bl, block, journal_blk);
- }
- else{
- error = fs_blkalloc(disk_fd, ip, &block);
-
- if(error) {
- stack;
- goto fail;
- }
-
- error = get_buf(sdp->sd_sb.sb_bsize, block, &bh);
- if (error) {
- stack;
- goto fail;
- }
-
- memcpy(BH_DATA(bh)+sizeof(struct gfs_meta_header),
- BH_DATA(dibh)+sizeof(struct gfs_dinode),
- BH_SIZE(dibh)-sizeof(struct gfs_dinode));
-
- error = write_buf(disk_fd, bh, 0);
- if(error) {
- stack;
- goto fail;
- }
- relse_buf(bh);
- block_set(sdp->bl, block, block_used);
- }
- }
-
- bh = NULL;
- /* Set up the pointer to the new block */
-
- memset(BH_DATA(dibh)+sizeof(struct gfs_dinode), 0,
- BH_SIZE(dibh)-sizeof(struct gfs_dinode));
-
- if (ip->i_di.di_size){
- ((uint64 *)(BH_DATA(dibh) + sizeof(struct gfs_dinode)))[0] = cpu_to_gfs64(block);
- ip->i_di.di_blocks++;
- }
-
- ip->i_di.di_height = 1;
-
- gfs_dinode_out(&ip->i_di, BH_DATA(dibh));
- if(write_buf(disk_fd, dibh, 0)){
- log_err("Dinode unstuffed, but unable to write back dinode.\n");
- goto fail;
- }
- relse_buf(dibh);
-
- return 0;
-
-
-
- fail:
- if(bh) relse_buf(bh);
- if(dibh) relse_buf(dibh);
-
- return error;
-}
-
-
-/**
- * calc_tree_height - Calculate the height of a metadata tree
- * @ip: The GFS inode
- * @size: The proposed size of the file
- *
- * Work out how tall a metadata tree needs to be in order to accommodate a
- * file of a particular size. If size is less than the current size of
- * the inode, then the current size of the inode is used instead of the
- * supplied one.
- *
- * Returns: the height the tree should be
- */
-
-static unsigned int calc_tree_height(struct gfs_inode *ip, uint64 size)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- uint64 *arr;
- unsigned int max, height;
-
- if (ip->i_di.di_size > size)
- size = ip->i_di.di_size;
-
- if (fs_is_jdata(ip)){
- arr = sdp->sd_jheightsize;
- max = sdp->sd_max_jheight;
- }
- else{
- arr = sdp->sd_heightsize;
- max = sdp->sd_max_height;
- }
- for (height = 0; height < max; height++)
- if (arr[height] >= size)
- break;
-
- return height;
-}
-
-
-/**
- * build_height - Build a metadata tree of the requested height
- * @ip: The GFS inode
- * @height: The height to build to
- *
- *
- * Returns: 0 on success, -EXXXX on failure
- */
-static int build_height(int disk_fd, struct gfs_inode *ip, int height)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- osi_buf_t *bh, *dibh;
- uint64 block, *bp;
- unsigned int x;
- int new_block;
- int error;
-
- while (ip->i_di.di_height < height){
- error = get_and_read_buf(disk_fd, ip->i_sbd->sd_sb.sb_bsize,
- ip->i_num.no_addr, &dibh, 0);
- if (error)
- goto fail;
-
- new_block = FALSE;
- bp = (uint64 *)(BH_DATA(dibh) + sizeof(struct gfs_dinode));
- for (x = 0; x < sdp->sd_diptrs; x++, bp++)
- if (*bp){
- new_block = TRUE;
- break;
- }
-
-
- if (new_block){
- /* Get a new block, fill it with the old direct pointers and write it out */
- error = fs_metaalloc(disk_fd, ip, &block);
- if (error)
- goto fail_drelse;
-
- error = get_and_read_buf(disk_fd, sdp->sd_sb.sb_bsize, block, &bh, 0);
- if (error)
- goto fail_drelse;
-
- set_meta(bh, GFS_METATYPE_IN, GFS_FORMAT_IN);
- /*
- gfs_buffer_copy_tail(bh, sizeof(struct gfs_indirect),
- dibh, sizeof(struct gfs_dinode));
- */
- log_err("ATTENTION -- Not doing copy_tail...\n");
- exit(1);
- error = -1;
- goto fail_drelse;
- if((error = write_buf(disk_fd, bh, 0))){
- log_err( "Unable to write new buffer #%"PRIu64".\n",
- BH_BLKNO(bh));
- goto fail_drelse;
- }
- relse_buf(bh);
- }
-
-
- /* Set up the new direct pointer and write it out to disk */
-
- memset(BH_DATA(dibh)+sizeof(struct gfs_dinode), 0,
- BH_SIZE(dibh)-sizeof(struct gfs_dinode));
-
- if (new_block){
- ((uint64 *)(BH_DATA(dibh) + sizeof(struct gfs_dinode)))[0] = cpu_to_gfs64(block);
- ip->i_di.di_blocks++;
- }
-
- ip->i_di.di_height++;
-
- gfs_dinode_out(&ip->i_di, BH_DATA(dibh));
- write_buf(disk_fd, dibh, 0);
- relse_buf(dibh);
- }
-
- return 0;
-
-
-
- fail_drelse:
- relse_buf(dibh);
-
- fail:
- return error;
-}
-
-
-static void find_metapath(struct gfs_inode *ip, metapath_t *mp, uint64 block)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- unsigned int i;
-
- for (i = ip->i_di.di_height; i--; ){
- mp->mp_list[i] = block % sdp->sd_inptrs;
- block /= sdp->sd_inptrs;
- }
-}
-
-
-/**
- * metapointer - Return pointer to start of metadata in a buffer
- * @bh: The buffer
- * @level: The metadata level (0 = dinode)
- * @mp: The metapath
- *
- * Return a pointer to the block number of the next level of the metadata
- * tree given a buffer containing the pointer to the current level of the
- * metadata tree.
- */
-
-static uint64 *metapointer(osi_buf_t *bh, unsigned int level, metapath_t *mp)
-{
- int head_size = (level > 0) ? sizeof(struct gfs_indirect) : sizeof(struct gfs_dinode);
- return ((uint64 *)(BH_DATA(bh) + head_size)) + mp->mp_list[level];
-}
-
-
-/**
- * get_metablock - Get the next metadata block in metadata tree
- * @ip: The GFS inode
- * @bh: Buffer containing the pointers to metadata blocks
- * @level: The level of the tree (0 = dinode)
- * @mp: The metapath
- * @create: Non-zero if we may create a new meatdata block
- * @new: Used to indicate if we did create a new metadata block
- * @block: the returned disk block number
- *
- * Given a metatree, complete to a particular level, checks to see if the next
- * level of the tree exists. If not the next level of the tree is created.
- * The block number of the next level of the metadata tree is returned.
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-static int get_metablock(int disk_fd, struct gfs_inode *ip,
- osi_buf_t *bh, unsigned int level, metapath_t *mp,
- int create, int *new, uint64 *block)
-{
- uint64 *ptr = metapointer(bh, level, mp);
- int error = 0;
-
- *new = 0;
- *block = 0;
-
- if (*ptr){
- *block = gfs64_to_cpu(*ptr);
- goto out;
- }
-
- if (!create)
- goto out;
-
- error = fs_metaalloc(disk_fd, ip, block);
- if (error)
- goto out;
-
- *ptr = cpu_to_gfs64(*block);
- ip->i_di.di_blocks++;
- write_buf(disk_fd, bh, 0);
-
- *new = 1;
-
- out:
- return error;
-}
-
-
-/**
- * get_datablock - Get datablock number from metadata block
- * @rgd: rgrp to allocate from if necessary
- * @ip: The GFS inode
- * @bh: The buffer containing pointers to datablocks
- * @mp: The metapath
- * @create: Non-zero if we may create a new data block
- * @new: Used to indicate if we created a new data block
- * @block: the returned disk block number
- *
- * Given a fully built metadata tree, checks to see if a particular data
- * block exists. It is created if it does not exist and the block number
- * on disk is returned.
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-static int get_datablock(int disk_fd, struct gfs_inode *ip,
- osi_buf_t *bh, metapath_t *mp,
- int create, int *new, uint64 *block)
-{
- uint64 *ptr = metapointer(bh, ip->i_di.di_height - 1, mp);
- int error = 0;
-
- *new = 0;
- *block = 0;
-
- if (*ptr){
- *block = gfs64_to_cpu(*ptr);
- goto out;
- }
-
- if (!create)
- goto out;
-
- if (fs_is_jdata(ip)){
- error = fs_metaalloc(disk_fd, ip, block);
- if (error)
- goto out;
- }
- else {
- error = fs_blkalloc(disk_fd, ip, block);
- if (error)
- goto out;
- }
-
- *ptr = cpu_to_gfs64(*block);
- ip->i_di.di_blocks++;
- write_buf(disk_fd, bh, 0);
-
- *new = 1;
-
- out:
- return error;
-}
-
-
-/**
- * fs_block_map - Map a block from an inode to a disk block
- * @ip: The GFS inode
- * @lblock: The logical block number
- * @new: Value/Result argument (1 = may create/did create new blocks)
- * @dblock: the disk block number of the start of an extent
- * @extlen: the size of the extent
- *
- * Find the block number on the current device which corresponds to an
- * inode's block. If the block had to be created, "new" will be set.
- *
- * Returns: 0 on success, -EXXX on failure
- */
-int fs_block_map(int disk_fd, struct gfs_inode *ip, uint64 lblock, int *new,
- uint64 *dblock, uint32 *extlen)
-{
- struct gfs_sbd *sdp = ip->i_sbd;
- osi_buf_t *bh = NULL;
- metapath_t mp;
- int create = *new;
- unsigned int bsize;
- unsigned int height;
- unsigned int x, end_of_metadata;
- unsigned int nptrs;
- uint64 tmp_dblock;
- int tmp_new;
- int error = 0;
-
- *new = 0;
- *dblock = 0;
- if (extlen)
- *extlen = 0;
-
- if (fs_is_stuffed(ip)){
- *dblock = ip->i_num.no_addr;
- if (extlen)
- *extlen = 1;
- goto out;
- }
- bsize = (fs_is_jdata(ip)) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize;
-
- height = calc_tree_height(ip, (lblock + 1) * bsize);
- if (ip->i_di.di_height < height){
- if (!create){
- error = 0;
- goto fail;
- }
-
- error = build_height(disk_fd, ip, height);
- if (error)
- goto fail;
- }
-
- error = get_and_read_buf(disk_fd, ip->i_sbd->sd_sb.sb_bsize,
- ip->i_num.no_addr, &bh, 0);
- if (error)
- goto fail;
-
- find_metapath(ip, &mp, lblock);
- end_of_metadata = ip->i_di.di_height - 1;
-
- for (x = 0; x < end_of_metadata; x++){
- error = get_metablock(disk_fd, ip, bh, x, &mp, create, new, dblock);
- relse_buf(bh); bh = NULL;
- if (error)
- goto fail;
- if (!*dblock)
- goto out;
-
- error = get_and_read_buf(disk_fd, ip->i_sbd->sd_sb.sb_bsize,
- *dblock, &bh, 0);
- if (error)
- goto fail;
- }
-
- error = get_datablock(disk_fd, ip, bh, &mp, create, new, dblock);
- if (error)
- goto fail_drelse;
-
- if (extlen && *dblock){
- *extlen = 1;
-
- if (!*new){
- nptrs = (end_of_metadata) ? sdp->sd_inptrs : sdp->sd_diptrs;
- while (++mp.mp_list[end_of_metadata] < nptrs){
- error = get_datablock(disk_fd, ip, bh, &mp, 0, &tmp_new,
- &tmp_dblock);
- if(error){
- log_err( "Unable to perform get_datablock.\n");
- goto fail;
- }
-
- if (*dblock + *extlen != tmp_dblock)
- break;
-
- (*extlen)++;
- }
- }
- }
-
- relse_buf(bh);
-
-
- out:
- if (*new){
- error = get_and_read_buf(disk_fd, sdp->sd_sb.sb_bsize, ip->i_num.no_addr,
- &bh, 0);
- if (error)
- goto fail;
- gfs_dinode_out(&ip->i_di, BH_DATA(bh));
- write_buf(disk_fd, bh, 0);
- relse_buf(bh);
- }
- return 0;
-
-
-
- fail_drelse:
- if(bh)
- relse_buf(bh);
-
- fail:
- return error;
-}
diff --git a/gfs/libgfs/fs_dir.c b/gfs/libgfs/fs_dir.c
deleted file mode 100644
index 63187a0..0000000
--- a/gfs/libgfs/fs_dir.c
+++ /dev/null
@@ -1,1683 +0,0 @@
-#include "incore.h"
-#include "link.h"
-#include "libgfs.h"
-
-#define dir_hash(qstr) (gfs_dir_hash((char *)(qstr)->name, (qstr)->len))
-
-/* Detect directory is a stuffed inode */
-int gfs_inode_is_stuffed(struct gfs_inode *ip)
-{
- return !ip->i_di.di_height;
-}
-
-/**
- * dirent_first - Return the first dirent
- * @bh: The buffer
- * @dent: Pointer to list of dirents
- *
- * return first dirent whether bh points to leaf or stuffed dinode
- *
- * Returns: IS_LEAF or IS_DINODE
- */
-int dirent_first(osi_buf_t *bh, struct gfs_dirent **dent)
-{
- struct gfs_leaf *leaf;
- struct gfs_dinode *dinode;
-
- leaf = (struct gfs_leaf *)BH_DATA(bh);
-
- if (gfs32_to_cpu(leaf->lf_header.mh_type) == GFS_METATYPE_LF)
- {
- *dent = (struct gfs_dirent *)(BH_DATA(bh) + sizeof(struct gfs_leaf));
-
- return IS_LEAF;
- }
- else
- {
- dinode = (struct gfs_dinode *)BH_DATA(bh);
- if(gfs32_to_cpu(dinode->di_header.mh_type) != GFS_METATYPE_DI){
- log_err("buffer is not GFS_METATYPE_[DI | LF]\n");
- return -1;
- }
-
- *dent = (struct gfs_dirent *)(BH_DATA(bh) + sizeof(struct gfs_dinode));
-
- return IS_DINODE;
- }
-}
-
-
-/**
- * dirent_next - Next dirent
- * @bh: The buffer
- * @dent: Pointer to list of dirents
- *
- * Returns: 0 on success, error code otherwise
- */
-int dirent_next(osi_buf_t *bh, struct gfs_dirent **dent)
-{
- struct gfs_dirent *tmp, *cur;
- char *bh_end;
- uint32 cur_rec_len;
-
- cur = *dent;
- bh_end = BH_DATA(bh) + BH_SIZE(bh);
-
- cur_rec_len = gfs16_to_cpu(cur->de_rec_len);
-
- if ((char *)cur + cur_rec_len >= bh_end){
- if((char *)cur + cur_rec_len != bh_end){
- log_err("Bad record length causing failure in dirent_next()\n");
- return -1;
- }
- return -ENOENT;
- }
-
- tmp = (struct gfs_dirent *)((char *)cur + cur_rec_len);
-
- if((char *)tmp + gfs16_to_cpu(tmp->de_rec_len) > bh_end){
- log_err("Bad record length causing failure in dirent_next\n");
- return -1;
- }
-
- /* only the first dent could ever have de_ino == 0 */
- if(!tmp->de_inum.no_formal_ino){
- char tmp_name[256];
-
- memcpy(tmp_name, cur+sizeof(struct gfs_dirent), gfs16_to_cpu(cur->de_name_len));
- tmp_name[gfs16_to_cpu(cur->de_name_len)] = '\0';
- log_err("dirent_next: "
- "A non-first dir entry has zero formal inode.\n");
- log_err("\tFaulty dirent after (%s) in block #%"PRIu64".\n",
- tmp_name, BH_BLKNO(bh));
-
- return -1;
- }
-
- *dent = tmp;
-
- return 0;
-}
-
-
-/**
- * dirent_del - Delete a dirent
- * @dip: The GFS inode
- * @bh: The buffer
- * @prev: The previous dirent
- * @cur: The current dirent
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int dirent_del(int disk_fd, struct gfs_inode *dip, osi_buf_t *bh,
- struct gfs_dirent *prev, struct gfs_dirent *cur){
- uint32 cur_rec_len, prev_rec_len;
-
- dip->i_di.di_entries--;
- if(!cur->de_inum.no_formal_ino){
- log_err("dirent_del: "
- "Can not delete dirent with !no_formal_ino.\n");
- return -1;
- }
-
- /* If there is no prev entry, this is the first entry in the block.
- The de_rec_len is already as big as it needs to be. Just zero
- out the inode number and return. */
-
- if (!prev){
- cur->de_inum.no_formal_ino = 0; /* No endianess worries */
- if (write_buf(disk_fd, bh, 0)){
- log_err("dirent_del: Bad write_buf.\n");
- return -EIO;
- }
- return 0;
- }
-
- /* Combine this dentry with the previous one. */
-
- prev_rec_len = gfs16_to_cpu(prev->de_rec_len);
- cur_rec_len = gfs16_to_cpu(cur->de_rec_len);
-
- if((char *)prev + prev_rec_len != (char *)cur){
- log_err("dirent_del: Bad bounds for directory entries.\n");
- return -1;
- }
-
- if((char *)(cur) + cur_rec_len > BH_DATA(bh) + BH_SIZE(bh)){
- log_err("dirent_del: Directory entry has record length"
- " longer than buffer.\n");
- return -1;
- }
-
- log_debug("Updating previous record from %u to %u\n",
- prev_rec_len, prev_rec_len+cur_rec_len);
- prev_rec_len += cur_rec_len;
- prev->de_rec_len = cpu_to_gfs16(prev_rec_len);
-
- if(write_buf(disk_fd, bh, 0)){
- log_err("dirent_del: Bad write_buf.\n");
- return -EIO;
- }
-
- return 0;
-}
-
-
-/**
- * get_leaf - Get leaf
- * @dip:
- * @leaf_no:
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int get_leaf(int disk_fd, struct gfs_inode *dip, uint64 leaf_no,
- osi_buf_t **bhp)
-{
- int error;
-
- error = get_and_read_buf(disk_fd, dip->i_sbd->sd_sb.sb_bsize, leaf_no,
- bhp, 0);
- if (error) {
- log_err("Unable to read leaf buffer #%"PRIu64"\n", leaf_no);
- return error;
- }
-
- error = check_meta(*bhp, GFS_METATYPE_LF);
-
- if(error) {
- log_err("Metatype for block #%"PRIu64" is not type 'leaf'\n",
- leaf_no);
- relse_buf(*bhp);
- }
- return error;
-}
-
-
-/**
- * get_first_leaf - Get first leaf
- * @dip: The GFS inode
- * @lindex:
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int get_first_leaf(int disk_fd, struct gfs_inode *dip, uint32 lindex,
- osi_buf_t **bh_out)
-{
- uint64 leaf_no;
- int error;
-
- error = get_leaf_nr(disk_fd, dip, lindex, &leaf_no);
- if (!error)
- error = get_leaf(disk_fd, dip, leaf_no, bh_out);
-
- return error;
-}
-
-
-/**
- * get_next_leaf - Get next leaf
- * @dip: The GFS inode
- * @bh_in: The buffer
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int get_next_leaf(int disk_fd, struct gfs_inode *dip,osi_buf_t *bh_in,osi_buf_t **bh_out)
-{
- struct gfs_leaf *leaf;
- int error;
-
- leaf = (struct gfs_leaf *)BH_DATA(bh_in);
-
- if (!leaf->lf_next)
- error = -ENOENT;
- else
- error = get_leaf(disk_fd, dip, gfs64_to_cpu(leaf->lf_next), bh_out);
- return error;
-}
-
-/**
- * leaf_search
- * @bh:
- * @id:
- * @dent_out:
- * @dent_prev:
- *
- * Returns:
- */
-static int leaf_search(osi_buf_t *bh, identifier_t *id,
- struct gfs_dirent **dent_out,
- struct gfs_dirent **dent_prev)
-{
- uint32 hash;
- struct gfs_dirent *dent, *prev = NULL;
- unsigned int entries = 0, x = 0;
- int type;
-
- type = dirent_first(bh, &dent);
-
- if (type == IS_LEAF){
- struct gfs_leaf *leaf = (struct gfs_leaf *)BH_DATA(bh);
- entries = gfs16_to_cpu(leaf->lf_entries);
- } else if (type == IS_DINODE) {
- struct gfs_dinode *dinode = (struct gfs_dinode *)(BH_DATA(bh));
- entries = gfs32_to_cpu(dinode->di_entries);
- } else {
- log_err("type != IS_LEAF && type != IS_DINODE\n");
- return -1;
- }
-
- if(id->type == ID_FILENAME){
- hash = dir_hash(id->filename);
-
- do{
- if (!dent->de_inum.no_formal_ino){
- prev = dent;
- continue;
- }
-
- if (gfs32_to_cpu(dent->de_hash) == hash &&
- fs_filecmp(id->filename, (char *)(dent + 1),
- gfs16_to_cpu(dent->de_name_len))){
- *dent_out = dent;
- if (dent_prev)
- *dent_prev = prev;
- return 0;
- }
-
- if(x >= entries){
- log_err("x >= entries (%u >= %u)\n", x, entries);
- return -1;
- }
- x++;
- prev = dent;
- } while (dirent_next(bh, &dent) == 0);
- } else if(id->type == ID_INUM){
- struct gfs_inum inum;
-
- do{
- if (!dent->de_inum.no_formal_ino){
- prev = dent;
- continue;
- }
-
- gfs_inum_in(&inum, (char *)&dent->de_inum);
-
- if(inum.no_addr == id->inum->no_addr){
- *dent_out = dent;
- if(dent_prev)
- *dent_prev = prev;
- return 0;
- }
-
- if(x >= entries){
- log_err("x >= entries (%u >= %u)\n", x, entries);
- return -1;
- }
- x++;
- prev = dent;
- } while (dirent_next(bh, &dent) == 0);
- } else {
- log_err("leaf_search: Invalid type for identifier.\n");
- exit(1);
- }
-
- return -ENOENT;
-}
-
-
-/**
- * linked_leaf_search - Linked leaf search
- * @dip: The GFS inode
- * @id:
- * @dent_out:
- * @dent_prev:
- * @bh_out:
- *
- * Returns: 0 on sucess, error code otherwise
- */
-
-static int linked_leaf_search(int disk_fd, struct gfs_inode *dip,
- identifier_t *id, struct gfs_dirent **dent_out,
- struct gfs_dirent **dent_prev, osi_buf_t **bh_out)
-{
- osi_buf_t *bh = NULL, *bh_next;
- uint32 hsize, lindex;
- uint32 hash;
- int error = 0;
-
- hsize = 1 << dip->i_di.di_depth;
- if(hsize * sizeof(uint64) != dip->i_di.di_size){
- log_err("hsize * sizeof(uint64) != dip->i_di.di_size\n");
- return -1;
- }
-
- /* Figure out the address of the leaf node. */
-
- if(id->type == ID_FILENAME){
- hash = dir_hash(id->filename);
- lindex = hash >> (32 - dip->i_di.di_depth);
-
- error = get_first_leaf(disk_fd, dip, lindex, &bh_next);
- if (error){
- return error;
- }
-
- /* Find the entry */
- do{
- if (bh)
- relse_buf(bh);
-
- bh = bh_next;
-
- error = leaf_search(bh, id, dent_out, dent_prev);
- switch (error){
- case 0:
- *bh_out = bh;
- return 0;
-
- case -ENOENT:
- break;
-
- default:
- relse_buf(bh);
- return error;
- }
-
- error = get_next_leaf(disk_fd, dip, bh, &bh_next);
- }while (!error);
-
- relse_buf(bh);
- } else if(id->type == ID_INUM){
- for(lindex=0; lindex < (1 << dip->i_di.di_depth); lindex++){
- error = get_first_leaf(disk_fd, dip, lindex, &bh_next);
- if (error){
- return error;
- }
-
- /* Find the entry */
- do{
- if (bh)
- relse_buf(bh);
-
- bh = bh_next;
-
- error = leaf_search(bh, id, dent_out, dent_prev);
- switch (error){
- case 0:
- *bh_out = bh;
- return 0;
-
- case -ENOENT:
- break;
-
- default:
- relse_buf(bh);
- return error;
- }
-
- error = get_next_leaf(disk_fd, dip, bh, &bh_next);
- }while (!error);
- }
- } else {
- log_err("linked_leaf_search: Invalid type for identifier.\n");
- exit(1);
- }
- return error;
-}
-
-
-/**
- * dir_e_search -
- * @dip: The GFS inode
- * @id:
- * @inode:
- *
- * Returns:
- */
-static int dir_e_search(int disk_fd, struct gfs_inode *dip,
- identifier_t *id, unsigned int *type)
-{
- osi_buf_t *bh = NULL;
- struct gfs_dirent *dent;
- int error;
-
- error = linked_leaf_search(disk_fd, dip, id, &dent, NULL, &bh);
- if (error){
- return error;
- }
-
- if(id->type == ID_FILENAME){
- if(id->inum){
- log_err("dir_e_search: Illegal parameter. inum must be NULL.\n");
- exit(1);
- }
- if(!(id->inum = (struct gfs_inum *)malloc(sizeof(struct gfs_inum)))) {
- log_err("Unable to allocate inum structure\n");
- return -1;
- }
- if(!memset(id->inum, 0, sizeof(struct gfs_inum))) {
- log_err("Unable to zero inum structure\n");
- return -1;
- }
-
- gfs_inum_in(id->inum, (char *)&dent->de_inum);
- } else {
- if(id->filename){
- log_err("dir_e_search: Illegal parameter. name must be NULL.\n");
- exit(1);
- }
- if(!(id->filename = (osi_filename_t *)malloc(sizeof(osi_filename_t)))) {
- log_err("Unable to allocate osi_filename structure\n");
- return -1;
- }
- if(!(memset(id->filename, 0, sizeof(osi_filename_t)))) {
- log_err("Unable to zero osi_filename structure\n");
- return -1;
- }
-
- id->filename->len = gfs16_to_cpu(dent->de_name_len);
- if(!(id->filename->name = malloc(id->filename->len))) {
- log_err("Unable to allocate name in osi_filename structure\n");
- free(id->filename);
- return -1;
- }
- if(!(memset(id->filename->name, 0, id->filename->len))) {
- log_err("Unable to zero name in osi_filename structure\n");
- free(id->inum);
- free(id->filename);
- return -1;
- }
-
- memcpy(id->filename->name, (char *)dent+sizeof(struct gfs_dirent),
- id->filename->len);
- }
- if (type)
- *type = gfs16_to_cpu(dent->de_type);
-
- relse_buf(bh);
-
- return 0;
-}
-
-
-/**
- * dir_l_search -
- * @dip: The GFS inode
- * @id:
- * @inode:
- *
- * Returns:
- */
-static int dir_l_search(int disk_fd, struct gfs_inode *dip, identifier_t *id,
- unsigned int *type)
-{
- osi_buf_t *dibh;
- struct gfs_dirent *dent;
- int error;
-
- if(!fs_is_stuffed(dip)){
- log_err("A linear search was attempted on a directory "
- "that is not stuffed.\n");
- return -1;
- }
-
- error = get_and_read_buf(disk_fd, dip->i_sbd->sd_sb.sb_bsize,
- dip->i_num.no_addr, &dibh, 0);
- if (error)
- goto out;
-
-
- error = leaf_search(dibh, id, &dent, NULL);
- if (error)
- goto out_drelse;
-
- if(id->type == ID_FILENAME){
- if(id->inum){
- log_err("dir_l_search: Illegal parameter. inum must be NULL.\n");
- exit(1);
- }
- id->inum = (struct gfs_inum *)malloc(sizeof(struct gfs_inum));
- // FIXME: handle failed malloc
- memset(id->inum, 0, sizeof(struct gfs_inum));
-
- gfs_inum_in(id->inum, (char *)&dent->de_inum);
- } else {
- if(id->filename){
- log_err("dir_l_search: Illegal parameter. name must be NULL.\n");
- exit(1);
- }
- id->filename = (osi_filename_t *)malloc(sizeof(osi_filename_t));
- // FIXME: handle failed malloc
- memset(id->filename, 0, sizeof(osi_filename_t));
-
- id->filename->len = gfs16_to_cpu(dent->de_name_len);
- id->filename->name = malloc(id->filename->len);
- // FIXME: handle failed malloc
- memset(id->filename->name, 0, id->filename->len);
-
- memcpy(id->filename->name, (char *)dent+sizeof(struct gfs_dirent),
- id->filename->len);
- }
- if(type)
- *type = gfs16_to_cpu(dent->de_type);
-
-
- out_drelse:
- relse_buf(dibh);
-
- out:
- return error;
-}
-
-
-/**
- * dir_make_exhash - Convet a stuffed directory into an ExHash directory
- * @dip: The GFS inode
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int dir_make_exhash(int disk_fd, struct gfs_inode *dip)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_dirent *dent;
- osi_buf_t *bh = NULL, *dibh = NULL;
- struct gfs_leaf *leaf;
- int y;
- uint32 x;
- uint64 *lp, bn;
- int error;
-
- /* Sanity checks */
-
- if(sizeof(struct gfs_leaf) > sizeof(struct gfs_dinode)){
- log_err(
- "dir_make_exhash: on-disk leaf is larger than on-disk dinode.\n"
- " Unable to expand directory.\n");
- return -1;
- }
-
- error = get_and_read_buf(disk_fd, dip->i_sbd->sd_sb.sb_bsize,
- dip->i_num.no_addr, &dibh, 0);
- if (error)
- goto fail;
-
-
- error = fs_metaalloc(disk_fd, dip, &bn);
-
- if (error)
- goto fail_drelse;
-
-
- /* Turn over a new leaf */
-
- error = get_and_read_buf(disk_fd, sdp->sd_sb.sb_bsize, bn, &bh, 0);
- if (error)
- goto fail_drelse;
-
- if(check_meta(bh, 0)){
- log_err("dir_make_exhash: Buffer has bad meta header.\n");
- goto fail_drelse;
- }
-
- set_meta(bh, GFS_METATYPE_LF, GFS_FORMAT_LF);
- memset(BH_DATA(bh) + sizeof(struct gfs_meta_header), 0,
- BH_SIZE(bh) - sizeof(struct gfs_meta_header));
-
- /* Fill in the leaf structure */
-
- leaf = (struct gfs_leaf *)BH_DATA(bh);
-
- if(dip->i_di.di_entries >= (1 << 16)){
- log_err(
- "dir_make_exhash: Too many directory entries.\n"
- " Unable to expand directory.\n");
- goto fail_drelse;
- }
- leaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE);
- leaf->lf_entries = cpu_to_gfs16(dip->i_di.di_entries);
-
-
- /* Copy dirents */
- memset(BH_DATA(bh)+sizeof(struct gfs_leaf), 0, BH_SIZE(bh)-sizeof(struct gfs_leaf));
- memcpy(BH_DATA(bh)+sizeof(struct gfs_leaf),
- BH_DATA(dibh)+sizeof(struct gfs_dinode),
- BH_SIZE(dibh)-sizeof(struct gfs_dinode));
-
- /* Find last entry */
-
- x = 0;
- dirent_first(bh, &dent);
-
- do
- {
- if (!dent->de_inum.no_formal_ino)
- continue;
-
- if (++x == dip->i_di.di_entries)
- break;
- }
- while (dirent_next(bh, &dent) == 0);
-
-
- /* Adjust the last dirent's record length
- (Remember that dent still points to the last entry.) */
-
- dent->de_rec_len = gfs16_to_cpu(dent->de_rec_len) +
- sizeof(struct gfs_dinode) - sizeof(struct gfs_leaf);
- dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len);
-
- if(write_buf(disk_fd, bh, 0)){
- log_err("dir_make_exhash: bad write_buf()\n");
- goto fail_drelse;
- }
- relse_buf(bh); bh=NULL;
-
- log_debug("Created a new leaf block at %"PRIu64"\n", bn);
-
- block_set(dip->i_sbd->bl, bn, leaf_blk);
- /* We're done with the new leaf block, now setup the new
- hash table. */
-
- memset(BH_DATA(dibh) + sizeof(struct gfs_dinode), 0,
- BH_SIZE(dibh) - sizeof(struct gfs_dinode));
-
- lp = (uint64 *)(BH_DATA(dibh) + sizeof(struct gfs_dinode));
-
- for (x = sdp->sd_hash_ptrs; x--; lp++)
- *lp = cpu_to_gfs64(bn);
-
- dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2;
- dip->i_di.di_blocks++;
- dip->i_di.di_flags |= GFS_DIF_EXHASH;
- dip->i_di.di_payload_format = 0;
-
- for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ;
- dip->i_di.di_depth = y;
-
- gfs_dinode_out(&dip->i_di, BH_DATA(dibh));
-
- if(write_buf(disk_fd, dibh, 0)){
- log_err("dir_make_exhash: bad write_buf()\n");
- goto fail_drelse;
- }
- relse_buf(dibh); dibh = NULL;
-
- return 0;
-
-
-
- fail_drelse:
- if(bh)
- relse_buf(bh);
- if(dibh)
- relse_buf(dibh);
-
- fail:
- return error;
-}
-
-
-/**
- * dir_split_leaf - Split a leaf block into two
- * @dip: The GFS inode
- * @lindex:
- * @leaf_no:
- *
- * Returns: 0 on success, error code on failure
- */
-static int dir_split_leaf(int disk_fd, struct gfs_inode *dip, uint32 lindex,
- uint64 leaf_no)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- osi_buf_t *nbh, *obh, *dibh;
- struct gfs_leaf *nleaf, *oleaf;
- struct gfs_dirent *dent, *prev = NULL, *next = NULL, *new;
- uint32 start, len, half_len, divider;
- uint64 bn, *lp;
- uint32 name_len;
- int x, moved = FALSE;
- int error;
-
- /* Allocate the new leaf block */
-
- error = fs_metaalloc(disk_fd, dip, &bn);
- if (error)
- goto fail;
-
-
- /* Get the new leaf block */
- error = get_and_read_buf(disk_fd, sdp->sd_sb.sb_bsize, bn, &nbh, 0);
- if (error)
- goto fail;
-
- if(check_meta(nbh, 0)){
- log_err("dir_split_leaf: Buffer is not a meta buffer.\n");
- relse_buf(nbh);
- return -1;
- }
-
- set_meta(nbh, GFS_METATYPE_LF, GFS_FORMAT_LF);
-
- memset(BH_DATA(nbh)+sizeof(struct gfs_meta_header), 0,
- BH_SIZE(nbh)-sizeof(struct gfs_meta_header));
-
- nleaf = (struct gfs_leaf *)BH_DATA(nbh);
-
- nleaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE);
-
-
- /* Get the old leaf block */
-
- error = get_leaf(disk_fd, dip, leaf_no, &obh);
- if (error)
- goto fail_nrelse;
-
- oleaf = (struct gfs_leaf *)BH_DATA(obh);
-
-
- /* Compute the start and len of leaf pointers in the hash table. */
-
- len = 1 << (dip->i_di.di_depth - gfs16_to_cpu(oleaf->lf_depth));
- if(len == 1){
- log_err("dir_split_leaf: Corrupted leaf block encountered.\n");
- goto fail_orelse;
- }
- half_len = len >> 1;
-
- start = (lindex & ~(len - 1));
-
- log_debug("Splitting leaf: len = %u, half_len = %u\n", len, half_len);
-
- /* Change the pointers.
- Don't bother distinguishing stuffed from non-stuffed.
- This code is complicated enough already. */
-
- lp = (uint64 *)malloc(half_len * sizeof(uint64));
- // FIXME: handle failed malloc
- memset(lp, 0, half_len * sizeof(uint64));
-
- error = readi(disk_fd, dip, (char *)lp, start * sizeof(uint64),
- half_len * sizeof(uint64));
- if (error != half_len * sizeof(uint64)){
- if (error >= 0)
- error = -EIO;
- goto fail_lpfree;
- }
-
- /* Change the pointers */
-
- for (x = 0; x < half_len; x++)
- lp[x] = cpu_to_gfs64(bn);
-
- error = writei(disk_fd, dip, (char *)lp, start * sizeof(uint64),
- half_len * sizeof(uint64));
-
- if (error != half_len * sizeof(uint64)){
- if (error >= 0)
- error = -EIO;
- goto fail_lpfree;
- }
-
- free(lp); lp = NULL; /* need to set lp for failure cases */
-
-
- /* Compute the divider */
-
- divider = (start + half_len) << (32 - dip->i_di.di_depth);
-
- /* Copy the entries */
-
- dirent_first(obh, &dent);
-
- do{
- next = dent;
- if (dirent_next(obh, &next))
- next = NULL;
-
- if (dent->de_inum.no_formal_ino &&
- (gfs32_to_cpu(dent->de_hash) < divider)){
- name_len = gfs16_to_cpu(dent->de_name_len);
-
- error = fs_dirent_alloc(disk_fd, dip, nbh, name_len, &new);
- if(error){
- log_err("dir_split_leaf: fs_dirent_alloc failed.\n");
- goto fail_orelse;
- }
-
- new->de_inum = dent->de_inum; /* No endianness worries */
- new->de_hash = dent->de_hash; /* No endianness worries */
- new->de_type = dent->de_type; /* No endianness worries */
- memcpy((char *)(new + 1), (char *)(dent + 1), name_len);
-
- nleaf->lf_entries = gfs16_to_cpu(nleaf->lf_entries) + 1;
- nleaf->lf_entries = cpu_to_gfs16(nleaf->lf_entries);
-
- dirent_del(disk_fd, dip, obh, prev, dent);
- /* Dirent del decrements entries, but we're
- * just shifting entries around, so increment
- * it again */
- dip->i_di.di_entries++;
-
- if(!gfs16_to_cpu(oleaf->lf_entries)){
- log_err("dir_split_leaf: old leaf contains no entries.\n");
- goto fail_orelse;
- }
- oleaf->lf_entries = gfs16_to_cpu(oleaf->lf_entries) - 1;
- oleaf->lf_entries = cpu_to_gfs16(oleaf->lf_entries);
-
- if (!prev)
- prev = dent;
-
- moved = TRUE;
- }
- else
- prev = dent;
-
- dent = next;
- }
- while (dent);
-
-
- /* If none of the entries got moved into the new leaf,
- artificially fill in the first entry. */
-
- if (!moved){
- error = fs_dirent_alloc(disk_fd, dip, nbh, 0, &new);
- if(error){
- log_err("dir_split_leaf: fs_dirent_alloc failed..\n");
- goto fail_orelse;
- }
- new->de_inum.no_formal_ino = 0;
- }
-
-
- oleaf->lf_depth = gfs16_to_cpu(oleaf->lf_depth) + 1;
- oleaf->lf_depth = cpu_to_gfs16(oleaf->lf_depth);
- nleaf->lf_depth = oleaf->lf_depth;
-
-
- error = get_and_read_buf(disk_fd, dip->i_sbd->sd_sb.sb_bsize,
- dip->i_num.no_addr, &dibh, 0);
- if(error){
- log_err("dir_split_leaf: Unable to get inode buffer.\n");
- goto fail_orelse;
- }
-
- error = check_meta(dibh, GFS_METATYPE_DI);
- if(error){
- log_err("dir_split_leaf: Buffer #%"PRIu64" is not a directory "
- "inode.\n", BH_BLKNO(dibh));
- goto fail_drelse;
- }
-
- dip->i_di.di_blocks++;
-
- gfs_dinode_out(&dip->i_di, BH_DATA(dibh));
- if(write_buf(disk_fd, dibh, 0)){
- log_err("dir_split_leaf: Failed to write new directory inode.\n");
- goto fail_drelse;
- }
- relse_buf(dibh);
-
-
- if(write_buf(disk_fd, obh, 0)){
- log_err("dir_split_leaf: Failed to write back old leaf block.\n");
- goto fail_orelse;
- }
- relse_buf(obh);
- if(write_buf(disk_fd, nbh, 0)){
- log_err("dir_split_leaf: Failed to write new leaf block.\n");
- goto fail_nrelse;
- }
-
- log_debug("Created a new leaf block at %"PRIu64"\n", BH_BLKNO(nbh));
-
- block_set(dip->i_sbd->bl, BH_BLKNO(nbh), leaf_blk);
-
- relse_buf(nbh);
-
- return 0;
-
-
-
- fail_drelse:
- relse_buf(dibh);
-
- fail_lpfree:
- if(lp) free(lp);
-
- fail_orelse:
- relse_buf(obh);
-
- fail_nrelse:
- relse_buf(nbh);
-
- fail:
- return -1;
-}
-
-
-/**
- * dir_double_exhash - Double size of ExHash table
- * @dip: The GFS dinode
- *
- * Returns: 0 on success, -1 on failure
- */
-static int dir_double_exhash(int disk_fd, struct gfs_inode *dip)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- osi_buf_t *dibh;
- uint32 hsize;
- uint64 *buf;
- uint64 *from, *to;
- uint64 block;
- int x;
- int error = 0;
-
- /* Sanity Checks */
-
- hsize = 1 << dip->i_di.di_depth;
- if(hsize * sizeof(uint64) != dip->i_di.di_size){
- log_err("dir_double_exhash: "
- "hash size does not correspond to di_size.\n");
- return -1;
- }
-
-
- /* Allocate both the "from" and "to" buffers in one big chunk */
-
- buf = (uint64 *)malloc(3 * sdp->sd_hash_bsize);
- if(!buf){
- log_err("dir_double_exhash: "
- "Unable to allocate memory for blk ptr list.\n");
- return -1;
- }
- memset(buf, 0, 3 * sdp->sd_hash_bsize);
-
- for (block = dip->i_di.di_size / sdp->sd_hash_bsize; block--;){
- error = readi(disk_fd, dip, (char *)buf, block * sdp->sd_hash_bsize,
- sdp->sd_hash_bsize);
- if (error != sdp->sd_hash_bsize){
- if (error >= 0)
- error = -EIO;
- goto out;
- }
-
- from = buf;
- to = (uint64 *)((char *)buf + sdp->sd_hash_bsize);
-
- for (x = sdp->sd_hash_ptrs; x--; from++){
- *to++ = *from; /* No endianess worries */
- *to++ = *from;
- }
-
- error = writei(disk_fd, dip, (char *)buf + sdp->sd_hash_bsize,
- block * sdp->sd_sb.sb_bsize, sdp->sd_sb.sb_bsize);
- if (error != sdp->sd_sb.sb_bsize){
- if (error >= 0)
- error = -EIO;
- goto out;
- }
- }
-
- free(buf); buf=NULL;
-
-
- error = get_and_read_buf(disk_fd, sdp->sd_sb.sb_bsize,
- dip->i_num.no_addr, &dibh, 0);
- if(error){
- log_err("dir_double_exhash: "
- "Unable to get inode buffer.\n");
- return -1;
- }
-
- error = check_meta(dibh, GFS_METATYPE_DI);
- if(error){
- log_err("dir_double_exhash: "
- "Buffer does not contain directory inode.\n");
- relse_buf(dibh);
- return -1;
- }
-
- dip->i_di.di_depth++;
-
- gfs_dinode_out(&dip->i_di, BH_DATA(dibh));
- if(write_buf(disk_fd, dibh, 0)){
- log_err("dir_double_exhash: "
- "Unable to write out directory inode.\n");
- relse_buf(dibh);
- return -1;
- }
-
- relse_buf(dibh);
-
- return 0;
-
-
- out:
- if(buf) free(buf);
-
- return error;
-}
-
-
-static int dir_e_del(int disk_fd, struct gfs_inode *dip, osi_filename_t *filename){
- int lindex;
- int error;
- int found = 0;
- uint64 leaf_no;
- osi_buf_t *bh;
- identifier_t id;
- struct gfs_dirent *cur, *prev;
-
- id.type = ID_FILENAME;
- id.filename = filename;
- id.inum = NULL;
-
- lindex = (1 << (dip->i_di.di_depth))-1;
-
- for(; (lindex >= 0) && !found; lindex--){
- error = get_leaf_nr(disk_fd, dip, lindex, &leaf_no);
- if (error){
- log_err("dir_e_del: Unable to get leaf number.\n");
- return error;
- }
-
- while(leaf_no && !found){
- if(get_leaf(disk_fd, dip, leaf_no, &bh)){
- stack;
- return -1;
- }
-
- error = leaf_search(bh, &id, &cur, &prev);
- if(id.inum) free(id.inum);
-
- if(error){
- if(error != -ENOENT){
- log_err("dir_e_del: leaf_search failed.\n");
- relse_buf(bh);
- return -1;
- }
- leaf_no = gfs64_to_cpu(((struct gfs_leaf *)BH_DATA(bh))->lf_next);
- relse_buf(bh);
- } else {
- found = 1;
- }
- }
- }
-
- if(!found)
- return 1;
-
- if(dirent_del(disk_fd, dip, bh, prev, cur)){
- log_err("dir_e_del: dirent_del failed.\n");
- relse_buf(bh);
- return -1;
- }
-
- relse_buf(bh);
- return 0;
-}
-
-
-static int dir_l_del(int disk_fd, struct gfs_inode *dip, osi_buf_t *dibh,
- osi_filename_t *filename){
- int error=0;
- int got_buf = 0;
- struct gfs_dirent *cur, *prev;
- identifier_t id;
-
- id.type = ID_FILENAME;
- id.filename = filename;
- id.inum = NULL;
-
- if(!fs_is_stuffed(dip)){
- log_crit("dir_l_del: Attempting linear delete on unstuffed"
- " dinode.\n");
- return -1;
- }
-
- if(!dibh) {
- error = get_and_read_buf(disk_fd, dip->i_sbd->sd_sb.sb_bsize,
- dip->i_num.no_addr, &dibh, 0);
- if (error){
- log_err("dir_l_del: Failed to read in dinode buffer.\n");
- return -1;
- }
- got_buf = 1;
- }
-
- error = leaf_search(dibh, &id, &cur, &prev);
- if(id.inum) free(id.inum);
-
- if(error){
- if(error == -ENOENT){
- log_debug("dir_l_del found no entry\n");
- if(got_buf)
- relse_buf(dibh);
- return 1;
- } else {
- log_err("dir_l_del: leaf_search failed.\n");
- if(got_buf)
- relse_buf(dibh);
- return -1;
- }
- }
-
- if(dirent_del(disk_fd, dip, dibh, prev, cur)){
- stack;
- if(got_buf)
- relse_buf(dibh);
- return -1;
- }
-
- if(got_buf)
- relse_buf(dibh);
- return 0;
-}
-
-
-/*
- * fs_dirent_del
- * @dip
- * filename
- *
- * Delete a directory entry from a directory. This _only_
- * removes the directory entry - leaving the dinode in
- * place. (Likely without a link.)
- *
- * Returns: 0 on success (or if it doesn't already exist), -1 on failure
- */
-int fs_dirent_del(int disk_fd, struct gfs_inode *dip, osi_buf_t *bh, osi_filename_t *filename){
- int error;
-
- if(dip->i_di.di_type != GFS_FILE_DIR){
- log_err("fs_dirent_del: parent inode is not a directory.\n");
- return -1;
- }
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH)
- error = dir_e_del(disk_fd, dip, filename);
- else
- error = dir_l_del(disk_fd, dip, bh, filename);
-
- return error;
-
-}
-
-
-/**
- * dir_e_add -
- * @dip: The GFS inode
- * @filename:
- * @inode:
- * @type:
- *
- */
-static int dir_e_add(int disk_fd, struct gfs_inode *dip,
- osi_filename_t *filename, struct gfs_inum *inum,
- unsigned int type)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- osi_buf_t *bh, *nbh, *dibh;
- struct gfs_leaf *leaf, *nleaf;
- struct gfs_dirent *dent;
- uint32 hsize, lindex;
- uint32 hash;
- uint64 leaf_no, bn;
- int error;
-
- restart:
-
- /* Sanity Checks */
-
- hsize = 1 << dip->i_di.di_depth;
- if(hsize * sizeof(uint64) != dip->i_di.di_size){
- log_err("dir_e_add: hash size and di_size do not correspond.\n");
- return -1;
- }
-
- /* Figure out the address of the leaf node. */
-
- hash = dir_hash(filename);
- lindex = hash >> (32 - dip->i_di.di_depth);
-
-
- error = get_leaf_nr(disk_fd, dip, lindex, &leaf_no);
- if (error){
- log_err("dir_e_add: Unable to get leaf number.\n");
- return error;
- }
-
-
- /* Add entry to the leaf */
-
- while (TRUE){
- error = get_leaf(disk_fd, dip, leaf_no, &bh);
- if (error){
- log_err("dir_e_add: Unable to get leaf #%"PRIu64"\n", leaf_no);
- return error;
- }
-
- leaf = (struct gfs_leaf *)BH_DATA(bh);
-
-
- if (fs_dirent_alloc(disk_fd, dip, bh, filename->len, &dent)){
- if (gfs16_to_cpu(leaf->lf_depth) < dip->i_di.di_depth){
- /* Can we split the leaf? */
- relse_buf(bh);
-
- error = dir_split_leaf(disk_fd, dip, lindex, leaf_no);
- if (error){
- log_err("dir_e_add: Unable to split leaf.\n");
- return error;
- }
-
- goto restart;
- }
- else if (dip->i_di.di_depth < GFS_DIR_MAX_DEPTH){
- /* Can we double the hash table? */
- relse_buf(bh);
-
- error = dir_double_exhash(disk_fd, dip);
- if (error){
- log_err("dir_e_add: Unable to double exhash.\n");
- return error;
- }
-
- goto restart;
- }
- else if (leaf->lf_next){
- /* Can we try the next leaf in the list? */
- leaf_no = gfs64_to_cpu(leaf->lf_next);
- relse_buf(bh);
- continue;
- }
- else {
- /* Create a new leaf and add it to the list. */
- error = fs_metaalloc(disk_fd, dip, &bn);
- if (error){
- relse_buf(bh);
- log_err("dir_e_add: "
- "Unable to allocate space for meta block.\n");
- return error;
- }
-
- error = get_and_read_buf(disk_fd, sdp->sd_sb.sb_bsize, bn,
- &nbh, 0);
- if (error){
- relse_buf(bh);
- return error;
- }
-
- /*gfs_trans_add_bh(sdp, dip->i_gl, nbh);*/
- if(check_meta(nbh, 0)){
- log_err("dir_e_add: Buffer is not a meta buffer.\n");
- relse_buf(bh);
- relse_buf(nbh);
- return -1;
- }
- set_meta(nbh, GFS_METATYPE_LF, GFS_FORMAT_LF);
- /* Make sure the bitmap is updated */
- log_debug("Setting leaf block at %"PRIu64"\n",
- bn);
- block_set(dip->i_sbd->bl, bn, leaf_blk);
- memset(BH_DATA(nbh)+sizeof(struct gfs_meta_header), 0,
- BH_SIZE(nbh)-sizeof(struct gfs_meta_header));
-
- /*gfs_trans_add_bh(sdp, dip->i_gl, bh);*/
- leaf->lf_next = cpu_to_gfs64(bn);
-
- nleaf = (struct gfs_leaf *)BH_DATA(nbh);
- nleaf->lf_depth = leaf->lf_depth;
- nleaf->lf_dirent_format = cpu_to_gfs32(GFS_FORMAT_DE);
-
- if (fs_dirent_alloc(disk_fd, dip, nbh, filename->len, &dent)){
- log_err("dir_e_add: Uncircumventible error!\n");
- exit(EXIT_FAILURE);
- }
-
- dip->i_di.di_blocks++;
-
- /* ATTENTION -- check for errors */
- write_buf(disk_fd, nbh, BW_WAIT);
- write_buf(disk_fd, bh, 0);
- relse_buf(bh);
-
- bh = nbh;
- leaf = nleaf;
- }
- }
-
-
- gfs_inum_out(inum, (char *)&dent->de_inum);
- dent->de_hash = cpu_to_gfs32(hash);
- dent->de_type = cpu_to_gfs16(type);
- memcpy((char *)(dent + 1), filename->name, filename->len);
-
- leaf->lf_entries = gfs16_to_cpu(leaf->lf_entries) + 1;
- leaf->lf_entries = cpu_to_gfs16(leaf->lf_entries);
-
- write_buf(disk_fd, bh, 0);
- relse_buf(bh);
-
- error = get_and_read_buf(disk_fd, dip->i_sbd->sd_sb.sb_bsize,
- dip->i_num.no_addr, &dibh, 0);
- if(error){
- log_err("dir_e_add: Unable to get inode buffer.\n");
- return error;
- }
-
- error = check_meta(dibh, GFS_METATYPE_DI);
- if(error){
- log_err("dir_e_add: Buffer #%"PRIu64" is not a directory "
- "inode.\n", BH_BLKNO(dibh));
- relse_buf(dibh);
- return error;
- }
-
- dip->i_di.di_entries++;
- dip->i_di.di_mtime = dip->i_di.di_ctime = osi_current_time();
- log_debug("Entries for %"PRIu64" is %u\n", dip->i_di.di_num.no_addr,
- dip->i_di.di_entries);
-
- gfs_dinode_out(&dip->i_di, BH_DATA(dibh));
- write_buf(disk_fd, dibh, 0);
- relse_buf(dibh);
-
- return 0;
- }
-
- return -ENOENT;
-}
-
-
-/**
- * dir_l_add -
- * @dip: The GFS inode
- * @filename:
- * @inode:
- * @type:
- *
- * Returns:
- */
-
-static int dir_l_add(int disk_fd, struct gfs_inode *dip, osi_filename_t *filename,
- struct gfs_inum *inum, unsigned int type)
-{
- osi_buf_t *dibh;
- struct gfs_dirent *dent;
- int error;
-
- /* Sanity checks */
-
- if(!fs_is_stuffed(dip)){
- log_err("dir_l_add: Attempting linear add on unstuffed dinode.\n");
- return -1;
- }
-
- error = get_and_read_buf(disk_fd, dip->i_sbd->sd_sb.sb_bsize,
- dip->i_num.no_addr, &dibh, 0);
- if (error)
- goto out;
-
-
- if (fs_dirent_alloc(disk_fd, dip, dibh, filename->len, &dent))
- {
- /* no need to write buffer, it hasn't changed. */
- relse_buf(dibh);
-
- error = dir_make_exhash(disk_fd, dip);
- /* DEBUG */
- log_debug("Changing Linear dir to Exhash dir - %s\n",
- (error)? "UNSUCCESSFUL": "SUCCESSFUL");
- if (!error)
- error = dir_e_add(disk_fd, dip, filename, inum, type);
-
- goto out;
- }
-
-
- gfs_inum_out(inum, (char *)&dent->de_inum);
- dent->de_hash = dir_hash(filename);
- dent->de_hash = cpu_to_gfs32(dent->de_hash);
- dent->de_type = cpu_to_gfs16(type);
- memcpy((char *)(dent + 1), filename->name, filename->len);
-
-
- dip->i_di.di_entries++;
- dip->i_di.di_mtime = dip->i_di.di_ctime = osi_current_time();
- log_debug("Entries for %"PRIu64" is %u\n", dip->i_di.di_num.no_addr,
- dip->i_di.di_entries);
- gfs_dinode_out(&dip->i_di, BH_DATA(dibh));
- if(write_buf(disk_fd, dibh, 0)){
- log_err("dir_l_add: bad write_buf()\n");
- error = -EIO;
- }
-
- relse_buf(dibh);
-
- out:
- if(error){
- char tmp_name[256];
- memset(tmp_name, 0, sizeof(tmp_name));
- memcpy(tmp_name, filename->name, filename->len);
- log_err("Unable to add \"%s\" to directory #%"PRIu64"\n",
- tmp_name, dip->i_num.no_addr);
- }
- return error;
-}
-
-
-
-/**
- * fs_dir_add - Add new filename into directory
- * @dip: The GFS inode
- * @filename: The new name
- * @inode: The inode number of the entry
- * @type: The type of the entry
- *
- * Returns: 0 on success, error code on failure
- */
-int fs_dir_add(int disk_fd, struct gfs_inode *dip, osi_filename_t *filename,
- struct gfs_inum *inum, unsigned int type)
-{
- int error;
-
- if(dip->i_di.di_type != GFS_FILE_DIR){
- log_err("fs_dir_add: parent inode is not a directory.\n");
- return -1;
- }
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH)
- error = dir_e_add(disk_fd, dip, filename, inum, type);
- else
- error = dir_l_add(disk_fd, dip, filename, inum, type);
-
- return error;
-}
-
-
-/**
- * fs_dirent_alloc - Allocate a directory entry
- * @dip: The GFS inode
- * @bh: The buffer
- * @name_len: The length of the name
- * @dent_out: Pointer to list of dirents
- *
- * Returns: 0 on success, error code otherwise
- */
-int fs_dirent_alloc(int disk_fd, struct gfs_inode *dip, osi_buf_t *bh,
- int name_len, struct gfs_dirent **dent_out)
-{
- struct gfs_dirent *dent, *new;
- struct gfs_leaf *leaf;
- struct gfs_dinode *dinode;
- unsigned int rec_len = GFS_DIRENT_SIZE(name_len);
- unsigned int entries = 0, offset = 0, x = 0;
- int type;
-
- type = dirent_first(bh, &dent);
-
- if (type == IS_LEAF){
- leaf = (struct gfs_leaf *)BH_DATA(bh);
- entries = gfs16_to_cpu(leaf->lf_entries);
- offset = sizeof(struct gfs_leaf);
- }
- else if (type == IS_DINODE) {
- dinode = (struct gfs_dinode *)BH_DATA(bh);
- entries = gfs32_to_cpu(dinode->di_entries);
- offset = sizeof(struct gfs_dinode);
- } else {
- log_err("fs_dirent_alloc: Buffer has bad metatype.\n");
- return -1;
- }
-
- if (!entries){
- dent->de_rec_len = BH_SIZE(bh) - offset;
- dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len);
- dent->de_name_len = cpu_to_gfs16(name_len);
-
- *dent_out = dent;
- write_buf(disk_fd, bh, 0);
- goto success;
- }
-
-
- do{
- uint32 cur_rec_len, cur_name_len;
-
- cur_rec_len = gfs16_to_cpu(dent->de_rec_len);
- cur_name_len = gfs16_to_cpu(dent->de_name_len);
-
- if ((!dent->de_inum.no_formal_ino && cur_rec_len >= rec_len) ||
- (cur_rec_len >= GFS_DIRENT_SIZE(cur_name_len) + rec_len)){
- if (dent->de_inum.no_formal_ino){
- new = (struct gfs_dirent *)((char *)dent + GFS_DIRENT_SIZE(cur_name_len));
- memset(new, 0, sizeof(struct gfs_dirent));
-
- new->de_rec_len = cpu_to_gfs16(cur_rec_len - GFS_DIRENT_SIZE(cur_name_len));
- new->de_name_len = cpu_to_gfs16(name_len);
-
- dent->de_rec_len = cur_rec_len - gfs16_to_cpu(new->de_rec_len);
- dent->de_rec_len = cpu_to_gfs16(dent->de_rec_len);
-
- *dent_out = new;
- write_buf(disk_fd, bh, 0);
- goto success;
- }
-
- dent->de_name_len = cpu_to_gfs16(name_len);
-
- *dent_out = dent;
- write_buf(disk_fd, bh, 0);
- goto success;
- }
-
- if(x >= entries){
- log_err("fs_dirent_alloc: dirents contain bad length information.\n");
- return -1;
- }
-
- if (dent->de_inum.no_formal_ino)
- x++;
- }
- while(dirent_next(bh, &dent) == 0);
-
- return -ENOSPC;
-
- success:
- return 0;
-}
-
-
-/**
- * get_leaf_nr - Get a leaf number associated with the lindex
- * @dip: The GFS inode
- * @lindex:
- * @leaf_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int get_leaf_nr(int disk_fd, struct gfs_inode *dip, uint32 lindex,
- uint64 *leaf_out)
-{
- uint64 leaf_no;
- int error = -1;
- error = readi(disk_fd, dip, (char *)&leaf_no,
- lindex * sizeof(uint64), sizeof(uint64));
- if (error != sizeof(uint64)){
- log_debug("get_leaf_nr: Bad internal read. (rtn = %d)\n",
- error);
- return (error < 0) ? error : -EIO;
- }
-
- *leaf_out = gfs64_to_cpu(leaf_no);
-
- return 0;
-}
-
-
-/**
- * fs_filecmp - Compare two filenames
- * @file1: The first filename
- * @file2: The second filename
- * @len_of_file2: The length of the second file
- *
- * This routine compares two filenames and returns TRUE if they are equal.
- *
- * Returns: TRUE (!=0) if the files are the same, otherwise FALSE (0).
- */
-int fs_filecmp(osi_filename_t *file1, char *file2, int len_of_file2)
-{
- if (file1->len != len_of_file2){
- return FALSE;
- }
-
- if (osi_memcmp(file1->name, file2, file1->len)){
- return FALSE;
- }
- return TRUE;
-}
-
-
-/**
- * fs_dir_search - Search a directory
- * @dip: The GFS inode
- * @id
- * @type:
- *
- * This routine searches a directory for a file or another directory
- * given its identifier. The component of the identifier that is
- * not being used to search will be filled in and must be freed by
- * the caller.
- *
- * Returns: 0 if found, -1 on failure, -ENOENT if not found.
- */
-int fs_dir_search(int disk_fd, struct gfs_inode *dip, identifier_t *id,
- unsigned int *type)
-{
- int error;
-
- if(dip->i_di.di_type != GFS_FILE_DIR){
- log_err("An attempt was made to search an inode "
- "that is not a directory.\n");
- return -1;
- }
-
- if (dip->i_di.di_flags & GFS_DIF_EXHASH)
- error = dir_e_search(disk_fd, dip, id, type);
- else
- error = dir_l_search(disk_fd, dip, id, type);
-
- return error;
-}
diff --git a/gfs/libgfs/fs_inode.c b/gfs/libgfs/fs_inode.c
deleted file mode 100644
index 2b8d2ca..0000000
--- a/gfs/libgfs/fs_inode.c
+++ /dev/null
@@ -1,470 +0,0 @@
-#include "libgfs.h"
-
-#define ST_CREATE 1
-
-/**
- * fs_get_istruct - Get an inode given its number
- * @sdp: The GFS superblock
- * @inum: The inode number
- * @create: Flag to say if we are allowed to create a new struct gfs_inode
- * @ipp: pointer to put the returned inode in
- *
- * Returns: 0 on success, -1 on error
- */
-static int fs_get_istruct(int disk_fd, struct gfs_sbd *sdp,
- struct gfs_inum *inum, int create,
- struct gfs_inode **ipp)
-{
- struct gfs_inode *ip = NULL;
- int error = 0;
-
- if (!create){
- /* we are not currently tracking which inodes we already have */
- error = -1;
- goto out;
- }
-
- if(!(ip = (struct gfs_inode *)malloc(sizeof(struct gfs_inode)))) {
- log_err("Unable to allocate gfs_inode structure\n");
- error = -1;
- goto out;
- }
- if(!memset(ip, 0, sizeof(struct gfs_inode))) {
- log_err("Unable to zero gfs_inode structure\n");
- error = -1;
- goto out;
- }
-
- ip->i_num = *inum;
-
- ip->i_sbd = sdp;
-
- error = fs_copyin_dinode(disk_fd, sdp->sd_sb.sb_bsize, ip, NULL);
- if (error){
- free(ip);
- ip = NULL;
- goto out;
- }
-
- out:
- *ipp = ip;
-
- return error;
-}
-
-
-/*
- * fs_copyin_dinode - read dinode from disk and store in inode
- * @ip: inode, sdp and inum must be set
- *
- * Returns: 0 on success, -1 on error
- */
-int fs_copyin_dinode(int disk_fd, uint32_t sb_bsize, struct gfs_inode *ip,
- osi_buf_t *dibh)
-{
-/* osi_buf_t *dibh;*/
- int do_relse = 0;
- int error = 0;
-
- if(!dibh) {
- error = get_and_read_buf(disk_fd, sb_bsize,
- ip->i_num.no_addr, &dibh, 0);
- if (error) {
- stack;
- goto out;
- }
-
- if(check_meta(dibh, GFS_METATYPE_DI)){
- log_err("Block #%"PRIu64" is not a dinode.\n",
- ip->i_num.no_addr);
- relse_buf(dibh);
- return -1;
- }
- do_relse = 1;
- }
- gfs_dinode_in(&ip->i_di, BH_DATA(dibh));
-
- if(do_relse)
- relse_buf(dibh);
-
-
-
- out:
- return error;
-}
-
-
-/*
- * fs_copyout_dinode - given an inode, copy its dinode data to disk
- * @ip: the inode
- *
- * Returns: 0 on success, -1 on error
- */
-int fs_copyout_dinode(int disk_fd, uint32_t sb_bsize, struct gfs_inode *ip)
-{
- osi_buf_t *dibh;
- int error;
-
- error = get_and_read_buf(disk_fd, sb_bsize, ip->i_num.no_addr, &dibh, 0);
- if(error){
- log_err( "Unable to get a buffer to write dinode to disk.\n");
- return -1;
- }
-
- gfs_dinode_out(&ip->i_di, BH_DATA(dibh));
-
- if(write_buf(disk_fd, dibh, 0)){
- log_err( "Unable to commit dinode buffer to disk.\n");
- relse_buf(dibh);
- return -1;
- }
-
- relse_buf(dibh);
- return 0;
-}
-
-/**
- * fs_lookupi - Look up a filename in a directory and return its inode
- * @dip: The directory to search
- * @name: The name of the inode to look for
- * @cred: The caller's credentials
- * @ipp: Used to return the found inode if any
- *
- * Returns: 0 on success, -EXXXX on failure
- */
-static int fs_lookupi(int disk_fd, struct gfs_inode *dip,
- osi_filename_t *name, osi_cred_t *cred,
- struct gfs_inode **ipp)
-{
- struct gfs_sbd *sdp = dip->i_sbd;
- int error = 0;
- identifier_t id;
-
- memset(&id, 0, sizeof(identifier_t));
- id.filename = name;
- id.type = ID_FILENAME;
-
- *ipp = NULL;
-
- if (!name->len || name->len > GFS_FNAMESIZE)
- {
- error = -ENAMETOOLONG;
- goto out;
- }
-
- if (fs_filecmp(name, (char *)".", 1))
- {
- *ipp = dip;
- goto out;
- }
-
- error = fs_dir_search(disk_fd, dip, &id, NULL);
- if (error){
- if (error == -ENOENT)
- error = 0;
- goto out;
- }
-
- error = fs_get_istruct(disk_fd, sdp, id.inum, ST_CREATE, ipp);
-
- out:
-
- if(id.inum) free(id.inum);
- return error;
-}
-
-static int fs_createi(int disk_fd, struct gfs_inode *dip, osi_filename_t *name,
- unsigned int type, unsigned int mode, osi_cred_t *cred,
- int *new, struct gfs_inode **ipp)
-{
- osi_list_t *tmp=NULL;
- struct gfs_sbd *sdp = dip->i_sbd;
- struct gfs_inum inum;
- int error;
- int allocate=0;
- identifier_t id;
-
- memset(&id, 0, sizeof(identifier_t));
-
- if (!name->len || name->len > GFS_FNAMESIZE){
- error = -ENAMETOOLONG;
- goto fail;
- }
-
- restart:
-
- /* Don't create entries in an unlinked directory */
- if (!dip->i_di.di_nlink){
- error = -EPERM;
- goto fail;
- }
-
- id.filename = name;
- id.type = ID_FILENAME;
-
- error = fs_dir_search(disk_fd, dip, &id, NULL);
- if(id.inum) free(id.inum);
- switch (error)
- {
- case -ENOENT:
- break;
-
- case 0:
- if (!new){
- error = -EEXIST;
- goto fail;
- } else {
- error = fs_lookupi(disk_fd, dip, name, cred, ipp);
- if (error)
- goto fail;
-
- if (*ipp){
- *new = FALSE;
- return 0;
- } else
- goto restart;
- }
- break;
-
- default:
- goto fail;
- }
-
- if (dip->i_di.di_entries == (uint32)-1){
- error = -EFBIG;
- goto fail;
- }
- if (type == GFS_FILE_DIR && dip->i_di.di_nlink == (uint32)-1){
- error = -EMLINK;
- goto fail;
- }
-
- retry:
- inum.no_addr = inum.no_formal_ino = 0;
- for (tmp = (osi_list_t *)sdp->sd_rglist.next;
- tmp != (osi_list_t *)&sdp->sd_rglist; tmp = tmp->next){
- uint64 block;
- struct gfs_rgrpd *rgd;
-
- rgd = osi_list_entry(tmp, struct gfs_rgrpd, rd_list);
- if(fs_rgrp_read(disk_fd, rgd, FALSE))
- return -1;
- if(rgd->rd_rg.rg_freemeta){
- block = fs_blkalloc_internal(rgd, dip->i_num.no_addr,
- GFS_BLKST_FREEMETA,
- GFS_BLKST_USEDMETA, 1);
- log_debug("Got block %"PRIu64"\n", block);
- if(block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- block += rgd->rd_ri.ri_data1;
- log_debug("Got block #%"PRIu64"\n", block);
- inum.no_addr = inum.no_formal_ino = block;
- rgd->rd_rg.rg_freemeta--;
- rgd->rd_rg.rg_useddi++;
-
- if(fs_rgrp_recount(disk_fd, rgd)){
- log_err( "fs_createi: Unable to recount rgrp blocks.\n");
- fs_rgrp_relse(rgd);
- error = -EIO;
- goto fail;
- }
-
- /* write out the rgrp */
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- write_buf(disk_fd, rgd->rd_bh[0], 0);
- fs_rgrp_relse(rgd);
- break;
- } else {
- if(allocate){
- if(!clump_alloc(disk_fd, rgd, 0)){
- block = fs_blkalloc_internal(rgd, dip->i_num.no_addr,
- GFS_BLKST_FREEMETA,
- GFS_BLKST_USEDMETA, 1);
- log_debug("Got block %"PRIu64"\n",
- block);
- if(block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- block += rgd->rd_ri.ri_data1;
-
- inum.no_addr = inum.no_formal_ino = block;
- rgd->rd_rg.rg_freemeta--;
- rgd->rd_rg.rg_useddi++;
-
- if(fs_rgrp_recount(disk_fd, rgd)){
- log_err( "fs_createi: Unable to recount rgrp blocks.\n");
- fs_rgrp_relse(rgd);
- error = -EIO;
- goto fail;
- }
-
- /* write out the rgrp */
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- write_buf(disk_fd, rgd->rd_bh[0], 0);
- fs_rgrp_relse(rgd);
- break;
- }
- }
- fs_rgrp_relse(rgd);
- }
- }
-
- if(!inum.no_addr){
- if(allocate){
- log_err( "No space available for new file or directory.\n");
- return -1;
- } else {
- allocate = 1;
- goto retry;
- }
- }
-
- error = fs_dir_add(disk_fd, dip, name, &inum, type);
- if (error)
- goto fail;
-
- error = make_dinode(disk_fd, dip, sdp, &inum, type, mode, cred);
- if (error)
- goto fail;
-
-
- error = fs_get_istruct(disk_fd, sdp, &inum, ST_CREATE, ipp);
- if (error)
- goto fail;
-
- if (new)
- *new = TRUE;
-
- return 0;
-
- fail:
- return error;
-}
-
-
-/*
- * fs_mkdir - make a directory
- * @dip - dir inode that is the parent of the new dir
- * @new_dir - name of the new dir
- * @mode - mode of new dir
- * @nip - returned inode ptr to the new directory
- *
- * This function has one main difference from the way a normal mkdir
- * works. It will not return an error if the directory already
- * exists. Instead it will return success and nip will point to the
- * inode that exists with the same name as new_dir.
- *
- * Returns: 0 on success, -1 on failure.
- */
-int fs_mkdir(int disk_fd, struct gfs_inode *dip, char *new_dir,
- int mode, struct gfs_inode **nip){
- int error;
- osi_cred_t creds;
- osi_buf_t *dibh;
- struct gfs_dinode *di;
- struct gfs_dirent *dent;
- struct gfs_inode *ip= NULL;
- struct gfs_sbd *sdp = dip->i_sbd;
- osi_filename_t name;
- int new = 0;
-
- name.name = (unsigned char *)new_dir;
- name.len = strlen(new_dir);
- creds.cr_uid = getuid();
- creds.cr_gid = getgid();
-
- error = fs_createi(disk_fd, dip, &name, GFS_FILE_DIR, mode, &creds,
- &new, &ip);
-
- if (error)
- goto fail;
-
- if(!new){
- goto out;
- }
-
- if(!ip){
- log_err( "fs_mkdir: fs_createi() failed.\n");
- error = -1;
- goto fail;
- }
-
- ip->i_di.di_nlink = 2;
- ip->i_di.di_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode);
- ip->i_di.di_flags |= GFS_DIF_JDATA;
- ip->i_di.di_payload_format = GFS_FORMAT_DE;
- ip->i_di.di_entries = 2;
-
- error = get_and_read_buf(disk_fd, ip->i_sbd->sd_sb.sb_bsize,
- ip->i_num.no_addr, &dibh, 0);
- if(error){
- log_err( "fs_mkdir: Unable to aquire directory buffer.\n");
- goto fail;
- }
-
- di = (struct gfs_dinode *)BH_DATA(dibh);
-
- error = fs_dirent_alloc(disk_fd, ip, dibh, 1, &dent);
- if(error){ /* This should never fail */
- log_err( "fs_mkdir: fs_dirent_alloc() failed for \".\" entry.\n");
- goto fail;
- }
-
- dent->de_inum = di->di_num; /* already GFS endian */
- dent->de_hash = gfs_dir_hash(".", 1);
- dent->de_hash = cpu_to_gfs32(dent->de_hash);
- dent->de_type = cpu_to_gfs16(GFS_FILE_DIR);
- memcpy((char *)(dent + 1), ".", 1);
- di->di_entries = cpu_to_gfs32(1);
-
- error = fs_dirent_alloc(disk_fd, ip, dibh, 2, &dent);
- if(error){ /* This should never fail */
- log_err( "fs_mkdir: fs_dirent_alloc() failed for \"..\" entry.\n");
- goto fail;
- }
- gfs_inum_out(&dip->i_num, (char *)&dent->de_inum);
- dent->de_hash = gfs_dir_hash("..", 2);
- dent->de_hash = cpu_to_gfs32(dent->de_hash);
- dent->de_type = cpu_to_gfs16(GFS_FILE_DIR);
- memcpy((char *)(dent + 1), "..", 2);
-
- gfs_dinode_out(&ip->i_di, (char *)di);
- if(write_buf(disk_fd, dibh, 0)){
- log_err( "fs_mkdir: Bad write_buf()\n");
- error = -EIO;
- goto fail;
- }
-
- relse_buf(dibh);
-
-
- /* FIXME: this may break stuff elsewhere, but since I'm
- * keeping track of the linkcount in-core, we shouldn't need
- * to do this...
-
- error = fs_change_nlink(dip, +1);
- if(error){
- log_err( "fs_mkdir: fs_change_nlink() failed.\n");
- goto fail;
- } */
-
- out:
- error=0;
- if(nip) {
- *nip = ip;
- }
- else if(ip) {
- free(ip);
- ip = NULL;
- }
- return 0;
- fail:
- if(ip)
- free(ip);
- return error;
-}
-
-
diff --git a/gfs/libgfs/incore.h b/gfs/libgfs/incore.h
deleted file mode 100644
index 5a25076..0000000
--- a/gfs/libgfs/incore.h
+++ /dev/null
@@ -1,1271 +0,0 @@
-/*
- * In-core (memory/RAM) structures.
- * These do not appear on-disk. See gfs_ondisk.h for on-disk structures.
- */
-
-#ifndef __INCORE_DOT_H__
-#define __INCORE_DOT_H__
-
-#ifndef __KERNEL__ /* if called from userland */
-#include <stdint.h>
-#include "list.h"
-#include "gfs_ondisk.h"
-#include "osi_user.h"
-
-#define FSCK_HASH_SHIFT (13)
-#define FSCK_HASH_SIZE (1 << FSCK_HASH_SHIFT)
-#define FSCK_HASH_MASK (FSCK_HASH_SIZE - 1)
-
-struct semaphore {
- void *nothing;
-};
-struct completion {
- void *nothing;
-};
-struct lm_lockname {
- void *nothing;
-};
-struct rw_semaphore {
- void *nothing;
-};
-struct gfs_quota_lvb {
- void *nothing;
-};
-struct lm_lockstruct {
- void *nothing;
-};
-typedef int atomic_t;
-typedef int spinlock_t;
-typedef int lm_lock_t;
-typedef int rwlock_t;
-typedef int wait_queue_head_t;
-#endif
-
-/* flags used in function call parameters */
-
-#define DIO_NEW (0x00000001) /* Newly allocated metadata */
-#define DIO_FORCE (0x00000002) /* Force read of block from disk */
-#define DIO_CLEAN (0x00000004) /* Don't write to disk */
-#define DIO_DIRTY (0x00000008) /* Data changed, must write to disk */
-#define DIO_START (0x00000010) /* Start disk read or write */
-#define DIO_WAIT (0x00000020) /* Wait for disk r/w to complete */
-
-#define DIO_METADATA (0x00000040) /* Process glock's protected metadata */
-#define DIO_DATA (0x00000080) /* Process glock's protected filedata */
-#define DIO_INVISIBLE (0x00000100) /* Don't monkey with glock's dirty bit */
-#define DIO_CHECK (0x00000200) /* Make sure all metadata has been synced */
-#define DIO_ALL (0x00000400) /* Flush all AIL transactions to disk */
-
-/* Structure prototypes */
-
-struct gfs_log_operations;
-struct gfs_log_element;
-struct gfs_meta_header_cache;
-struct gfs_depend;
-struct gfs_bitmap;
-struct gfs_rgrpd;
-struct gfs_bufdata;
-struct gfs_glock_operations;
-struct gfs_holder;
-struct gfs_glock;
-struct gfs_alloc;
-struct gfs_inode;
-struct gfs_file;
-struct gfs_unlinked;
-struct gfs_quota_le;
-struct gfs_quota_data;
-struct gfs_log_buf;
-struct gfs_trans;
-struct gfs_gl_hash_bucket;
-struct gfs_sbd;
-
-typedef void (*gfs_glop_bh_t) (struct gfs_glock * gl, unsigned int ret);
-
-/*
- * Structure of operations that are associated with each
- * type of element in the log.
- */
-struct gfs_log_operations {
- /*
- * Operations specific to a given log element (LE).
- * These are typically executed individually via macros such as LO_ADD.
- */
-
- /* Add new LE to transaction */
- void (*lo_add) (struct gfs_sbd * sdp, struct gfs_log_element * le);
-
- /* Do any cleanup, etc., needed just before commit to incore log */
- void (*lo_trans_end) (struct gfs_sbd * sdp,
- struct gfs_log_element * le);
-
- /* Print LE-specific info via printk() */
- void (*lo_print) (struct gfs_sbd * sdp, struct gfs_log_element * le,
- unsigned int where);
-
- /* Find any incore transactions that overlap through this LE (e.g.
- * share glocks), to determine if any transactions can be combined. */
- struct gfs_trans *(*lo_overlap_trans) (struct gfs_sbd * sdp,
- struct gfs_log_element * le);
-
- /* Change LE from "new" to "incore" status, before write to log */
- void (*lo_incore_commit) (struct gfs_sbd * sdp, struct gfs_trans * tr,
- struct gfs_log_element * le);
-
- /* Allow writes to in-place locations, after log is on-disk */
- void (*lo_add_to_ail) (struct gfs_sbd * sdp,
- struct gfs_log_element * le);
-
- /* Clean up LE after log dump */
- void (*lo_clean_dump) (struct gfs_sbd * sdp,
- struct gfs_log_element * le);
-
- /*
- * Operations specific to a class of log elements.
- * These are typically executed over a whole transaction by
- * macros such as LO_TRANS_SIZE. Each LE-type-specific operation
- * for each LE contributes its part to the overall result.
- */
-
- /* Determine LE-type-specific quantities of blocks of various types
- * required for writing the log */
- void (*lo_trans_size) (struct gfs_sbd * sdp, struct gfs_trans * tr,
- unsigned int *mblks, unsigned int *eblks,
- unsigned int *blocks, unsigned int *bmem);
-
- /* Combine LE-type-specific values in new_tr and tr, result is in tr */
- void (*lo_trans_combine) (struct gfs_sbd * sdp, struct gfs_trans * tr,
- struct gfs_trans * new_tr);
-
- /* Create control and metadata buffers that will make up the log */
- void (*lo_build_bhlist) (struct gfs_sbd * sdp, struct gfs_trans * tr);
-
- /* Calculate log space needed for this LE in a log dump */
- void (*lo_dump_size) (struct gfs_sbd * sdp, unsigned int *elements,
- unsigned int *blocks, unsigned int *bmem);
-
- /* Add LE to log dump */
- void (*lo_build_dump) (struct gfs_sbd * sdp, struct gfs_trans * tr);
-
- /*
- * Operations that happen at recovery time
- */
-
- /* Reset/init whatever before doing recovery */
- void (*lo_before_scan) (struct gfs_sbd * sdp, unsigned int jid,
- struct gfs_log_header * head,
- unsigned int pass);
-
- /* LE-specific recovery procedure */
- int (*lo_scan_elements) (struct gfs_sbd * sdp,
- struct gfs_jindex * jdesc,
- struct gfs_glock * gl, uint64_t start,
- struct gfs_log_descriptor * desc,
- unsigned int pass);
-
- /* Verify and report recovery results/statistics */
- void (*lo_after_scan) (struct gfs_sbd * sdp, unsigned int jid,
- unsigned int pass);
-
-
- /*
- * Type of element (glock/buf/unlinked/quota)
- */
- char *lo_name;
-};
-
-/*
- * Structure that gets added to struct gfs_trans->tr_elements. They
- * make up the "stuff" in each transaction.
- */
-struct gfs_log_element {
- struct gfs_log_operations *le_ops; /* Vector of functions */
-
- struct gfs_trans *le_trans; /* We're part of this transaction */
- osi_list_t le_list; /* Link to transaction's element list */
-};
-
-/*
- * Meta-header cache structure.
- * One for each metadata block that we've de-allocated.
- * Used to temporarily store gfs_meta_header structs for meta blocks that
- * have been freshly turned into FREEMETA (alloc'd or de-alloc'd). Storing
- * these (small) structures in-core allows us to release the (large) buffers,
- * and not need to re-read the header from disk if/when we re-allocate the
- * blocks to USEDMETA, as long as this node holds the EXCLUSIVE lock for the
- * resource group containing the blocks. If we release the EX lock, we must
- * throw away the rgrp's cached meta headers, since another node could change
- * the blocks' contents.
- * In-core superblock structure hosts the hashed cache, as well as a
- * linear list of all cached, in most-recently-added order.
- * Also, each resource group keeps a list of cached blocks within its scope.
- */
-struct gfs_meta_header_cache {
- /* Links to various lists */
- osi_list_t mc_list_hash; /* Superblock's hashed list */
- osi_list_t mc_list_single; /* Superblock's list, MRU order */
- osi_list_t mc_list_rgd; /* Resource group's list */
-
- uint64_t mc_block; /* Block # (in-place address) */
- struct gfs_meta_header mc_mh; /* Payload: the block's meta-header */
-};
-
-/*
- * Dependency cache structure.
- * In-core superblock structure hosts the actual cache.
- * Also, each resource group keeps a list of dependency blocks within its scope.
- */
-struct gfs_depend {
- /* Links to various lists */
- osi_list_t gd_list_hash; /* Superblock's hashed list */
- osi_list_t gd_list_rgd; /* Resource group's list */
-
- struct gfs_rgrpd *gd_rgd; /* Resource group descriptor */
- uint64_t gd_formal_ino; /* Inode ID */
- unsigned long gd_time; /* Time (jiffies) when put on list */
-};
-
-/*
- * Block allocation bitmap descriptor structure.
- * One of these for each FS block that contains bitmap data
- * (i.e. the resource group header blocks and their following bitmap blocks).
- * Each allocatable FS data block is represented by 2 bits (4 alloc states).
- */
-struct gfs_bitmap {
- uint32_t bi_offset; /* Byte offset of bitmap within this bit block
- (non-zero only for an rgrp header block) */
- uint32_t bi_start; /* Data block (rgrp scope, 32-bit) represented
- by the first bit-pair in this bit block */
- uint32_t bi_len; /* The number of bitmap bytes in this bit block */
-};
-
-/*
- * Resource Group (Rgrp) descriptor structure.
- * There is one of these for each resource (block) group in the FS.
- * The filesystem is divided into a number of resource groups to allow
- * simultaneous block alloc operations by a number of nodes.
- */
-struct gfs_rgrpd {
- /* Links to superblock lists */
- osi_list_t rd_list; /* On-disk-order list of all rgrps */
- osi_list_t rd_list_mru; /* Most Recently Used list of all rgs */
- osi_list_t rd_recent; /* recently used rgrps */
- uint32_t rd_try_counter; /* # of times we fail a try lock */
-
- struct gfs_glock *rd_gl; /* Glock for this rgrp */
-
- struct gfs_rindex rd_ri; /* Resource Index (on-disk) structure */
- struct gfs_rgrp rd_rg; /* Resource Group (on-disk) structure */
- uint64_t rd_rg_vn; /* Version #: if != glock's gl_vn,
- we need to read rgrp fm disk */
-
- /* Block alloc bitmap cache */
- struct gfs_bitmap *rd_bits; /* Array of block bitmap descriptors */
- struct buffer_head **rd_bh; /* Array of ptrs to block bitmap bh's */
-
- /* Block allocation strategy, rgrp scope. Start at these blocks when
- searching for next data/meta block to alloc */
- uint32_t rd_last_alloc_data; /* Most recent data block allocated */
- uint32_t rd_last_alloc_meta; /* Most recent meta block allocated */
-
- osi_list_t rd_mhc; /* Cached meta-headers for this rgrp */
- osi_list_t rd_depend; /* Dependent inodes (MRU order) */
-
- struct gfs_sbd *rd_sbd; /* FS incore superblock (fs instance) */
-#ifndef __KERNEL__
- int32_t rd_open_count; /* # of open references on this rgrpd */
-#endif
-};
-
-/*
- * Per-buffer data
- * One of these is attached as GFS private data to each FS block's buffer_head.
- * These keep track of a buffer's progress through the transaction pipeline,
- * using the "new" embedded log element to attach it to a being-built
- * transaction, and moving the attachment point to the "incore" LE once
- * the transaction completes (at which time the buffer becomes a candidate
- * to be written to the on-disk log).
- * A buffer may be attached simultaneously to a new and an incore transaction,
- * but no more than one of each: Only one new trans may be built at a time
- * for a given buffer, obviously, since the buffer's contents are protected
- * by an EXclusive glock when writing. And, when a transaction is completely
- * built, GFS combines incore transactions that share glocks (see
- * incore_commit()), i.e. the glock that protects the buffer, so a buffer
- * never needs to be attached to more than one (combined) incore trans.
- * Note that multiple transactions can modify the buffer since its most
- * recent writes to disk. This principle applies to both in-place and
- * journal block locations on-disk, allowing this node to keep modifying the
- * cached data without writing it to disk, unless/until another node needs
- * to access the data, or the Linux OS tells us to sync to disk.
- * If a transaction follows another transaction before the first transaction's
- * log completes (indicated by the in-place buffer head still being pinned
- * in RAM), GFS copies the first transaction's results to a "frozen"
- * image of the buffer, so the first transaction results (an atomic
- * snapshot) can be logged properly, while the second transaction is
- * modifying the "real" buffer. This frozen copy lives only until the new
- * transaction is complete, at which point one of two things has occurred:
- * 1). Buffer was logged successfully; frozen copy's job is done.
- * 2). Buffer was not yet logged; frozen copy no longer needed, newer
- * buffer becomes the log candidate.
- *
- * gfs_bufdata structs also link into the Active Items Lists (AIL) (buffers
- * flushed to on-disk log, but not yet flushed to on-disk in-place locations)
- * attached to:
- * 1). The latest transaction to modify and log (on-disk) the buffer, and
- * 2). The glock that protects the buffer's contents.
- * The buffer is attached to only the most recent transaction's AIL
- * list for a couple of reasons. One is that only the most up-to-date
- * buffer content needs to be written to the in-place block on-disk. The
- * other is that since there is a more recent copy of the block in
- * the log, we don't need to keep the older copies in the log. We can
- * remove them from the AIL and let the log space be reused for new
- * transactions (GFS advances the log tail when removing buffers from AIL).
- */
-struct gfs_bufdata {
- struct buffer_head *bd_bh; /* We belong to this Linux buffer_head */
- struct gfs_glock *bd_gl; /* This glock protects buffer's payload */
-
- /* Log elements map us to a particular set of log operations functions,
- and to a particular transaction */
- struct gfs_log_element bd_new_le; /* New, incomplete transaction */
- struct gfs_log_element bd_incore_le; /* Complete (committed) trans */
-
- char *bd_frozen; /* "Frozen" copy of buffer's data */
- struct semaphore bd_lock; /* Protects access to this structure */
-
- /* "Pin" means keep buffer in RAM, don't write to disk (yet) */
- unsigned int bd_pinned; /* Recursive pin count */
-
- /* Links to Active Items Lists */
- osi_list_t bd_ail_tr_list; /* This buf's most recent trans' AIL */
- osi_list_t bd_ail_gl_list; /* This buf's glock's AIL */
-};
-
-/*
- * Glock operations
- * One set of operations for each glock, the set selected by type of glock.
- * These functions get called at various points in a glock's lifetime.
- * "xmote" = promote or demote (change lock state) a glock at inter-node scope.
- * "th" = top half, "bh" = bottom half
- * Some operations/fields are required (GFS assumes they are there):
- * go_xmote_th
- * go_drop_th
- * go_type
- * Other operations are optional (GFS checks for presence before calling).
- */
-struct gfs_glock_operations {
-
- /* Acquire lock or change lock state at inter-node scope:
- Does type-specific preparation (if any)
- Uses gfs_glock_xmote_th to call lock module. */
- void (*go_xmote_th) (struct gfs_glock * gl, unsigned int state,
- int flags);
-
- /* After acquiring or changing a lock at inter-node scope */
- void (*go_xmote_bh) (struct gfs_glock * gl);
-
- /* Release (unlock) a lock at inter-node scope:
- Does type-specific preparation (if any)
- Uses gfs_glock_drop_th to call lock module. */
- void (*go_drop_th) (struct gfs_glock * gl);
-
- /* After releasing a lock at inter-node scope */
- void (*go_drop_bh) (struct gfs_glock * gl);
-
- /* Sync dirty data to disk (e.g. before demoting an EX inter-node lock)
- (another node needs to read the updated data from disk) */
- void (*go_sync) (struct gfs_glock * gl, int flags);
-
- /* Invalidate local cached data just after releasing an inter-node lock
- (another node may change the on-disk data, so it's no good to us) */
- void (*go_inval) (struct gfs_glock * gl, int flags);
-
- /* Lock-type-specific check to see if it's okay to unlock a glock
- at inter-node scope (and remove it from our glock cache) */
- int (*go_demote_ok) (struct gfs_glock * gl);
-
- /* After getting lock for first holder (within this node) */
- int (*go_lock) (struct gfs_glock * gl, int flags);
-
- /* After last holder (within this node) gives up lock (glock may
- remain in glock cache, though) */
- void (*go_unlock) (struct gfs_glock * gl, int flags);
-
- /* After receiving a callback: another node needs the lock */
- void (*go_callback) (struct gfs_glock * gl, unsigned int state);
-
- /* Called when the glock layer marks a lock as being not greedy
- anymore */
- void (*go_greedy) (struct gfs_glock * gl);
-
- /* Lock type: locks with same lock # (often an FS block #),
- but different types, are different locks */
- int go_type;
-};
-
-/*
- * Glock holder structure
- * One for each holder of a glock.
- * These coordinate the use, within this node, of an acquired inter-node glock.
- * Once a node has acquired a glock, it may be shared within that node by
- * several processes, or even by several recursive requests from the same
- * process. Each is a separate "holder". Different holders may co-exist
- * having requested different lock states, as long as the node holds the
- * glock in a state that is compatible. A hold requestor may select, via
- * flags, the rules by which sharing within the node is granted:
- * LM_FLAG_ANY: Grant if glock state is any other than UNLOCKED.
- * GL_EXACT: Grant only if glock state is exactly the requested state.
- * GL_LOCAL_EXCL: Grant only one holder at a time within this node.
- * With no flags, a hold will be granted to a SHARED request even if the
- * node holds the glock in EXCLUSIVE mode. See relaxed_state_ok().
- * When a process needs to manipulate a lock, it requests it via one of
- * these holder structures. If the request cannot be satisfied immediately,
- * the holder structure gets queued on one of these lists in gfs_glock:
- * 1) waiters1, for gaining exclusive access to the (local) glock structure.
- * 2) waiters2, for demoting a lock (unlocking a glock, or changing its state
- * to be less restrictive) or relenquishing "greedy" status.
- * 3) waiters3, for promoting (locking a new glock, or changing a glock state
- * to be more restrictive).
- * When holding a lock, gfs_holder struct stays on glock's holder list.
- * See gfs-kernel/src/harness/lm_interface.h for gh_state (LM_ST_...)
- * and gh_flags (LM_FLAG...) fields.
- * Also see glock.h for gh_flags field (GL_...) flags.
- */
-
-/* Action requests */
-#define HIF_MUTEX (0) /* Exclusive (local) access to glock struct */
-#define HIF_PROMOTE (1) /* Change lock to more restrictive state */
-#define HIF_DEMOTE (2) /* Change lock to less restrictive state */
-#define HIF_GREEDY (3) /* Wait for the glock to be unlocked */
-
-/* States */
-#define HIF_ALLOCED (4) /* Holder structure is or was in use */
-#define HIF_DEALLOC (5) /* Toss holder struct as soon as queued request
- * is satisfied */
-#define HIF_HOLDER (6) /* We have been granted a hold on the lock */
-#define HIF_FIRST (7) /* We are first holder to get the lock */
-#define HIF_RECURSE (8) /* >1 hold requests on same glock by same process*/
-#define HIF_ABORTED (9) /* Aborted before being submitted */
-
-struct gfs_holder {
- osi_list_t gh_list; /* Link to one of glock's holder lists */
-
- struct gfs_glock *gh_gl; /* Glock that we're holding */
- struct task_struct *gh_owner; /* Linux process that is the holder */
-
- /* request to change lock state */
- unsigned int gh_state; /* LM_ST_... requested lock state */
- int gh_flags; /* GL_... or LM_FLAG_... req modifiers */
-
- int gh_error; /* GLR_... CANCELLED/TRYFAILED/-errno */
- unsigned long gh_iflags; /* HIF_... holder state, see above */
- struct completion gh_wait; /* Wait for completion of ... */
-};
-
-/*
- * Glock Structure
- * One for each inter-node lock held by this node.
- * A glock is a local representation/abstraction of an inter-node lock.
- * Inter-node locks are managed by a "lock module" (LM) which plugs in to
- * the lock harness / glock interface (see gfs-kernel/harness). Different
- * lock modules support different lock protocols (e.g. GULM, GDLM, no_lock).
- * A glock may have one or more holders within a node. See gfs_holder above.
- * Glocks are managed within a hash table hosted by the in-core superblock.
- * After all holders have released a glock, it will stay in the hash table
- * cache for a time (depending on lock type), during which the inter-node
- * lock will not be released unless another node needs the lock (lock
- * manager requests this via callback to GFS through LM on this node). This
- * provides better performance in case this node needs the glock again soon.
- * See comments for meta_go_demote_ok(), glops.c.
- * Each glock has an associated vector of lock-type-specific "glops" functions
- * which are called at important times during the life of a glock, and
- * which define the type of lock (e.g. dinode, rgrp, non-disk, etc).
- * See gfs_glock_operations above.
- * A glock, at inter-node scope, is identified by the following dimensions:
- * 1) lock number (usually a block # for on-disk protected entities,
- * or a fixed assigned number for non-disk locks, e.g. MOUNT).
- * 2) lock type (actually, the type of entity protected by the lock).
- * 3) lock namespace, to support multiple GFS filesystems simultaneously.
- * Namespace (usually cluster:filesystem) is specified when mounting.
- * See man page for gfs_mount.
- * Glocks require support of Lock Value Blocks (LVBs) by the inter-node lock
- * manager. LVBs are small (32-byte) chunks of data associated with a given
- * lock, that can be quickly shared between cluster nodes. Used for certain
- * purposes such as sharing an rgroup's block usage statistics without
- * requiring the overhead of:
- * -- sync-to-disk by one node, then a
- * -- read from disk by another node.
- *
- */
-
-#define GLF_PLUG (0) /* Dummy */
-#define GLF_LOCK (1) /* Exclusive (local) access to glock
- * structure */
-#define GLF_STICKY (2) /* Don't release this inter-node lock
- * unless another node explicitly asks */
-#define GLF_PREFETCH (3) /* This lock has been (speculatively)
- * prefetched, demote if not used soon */
-#define GLF_SYNC (4) /* Sync lock's protected data as soon as
- * there are no more holders */
-#define GLF_DIRTY (5) /* There is dirty data for this lock,
- * sync before releasing inter-node */
-#define GLF_SKIP_WAITERS2 (6) /* Make run_queue() ignore gl_waiters2
- * (demote/greedy) holders */
-#define GLF_GREEDY (7) /* This lock is ignoring callbacks
- * (requests from other nodes) for now */
-
-struct gfs_glock {
- osi_list_t gl_list; /* Link to hb_list in one of superblock's
- * sd_gl_hash glock hash table buckets */
- unsigned long gl_flags; /* GLF_... see above */
- struct lm_lockname gl_name; /* Lock number and lock type */
- atomic_t gl_count; /* Usage count */
-
- spinlock_t gl_spin; /* Protects some members of this struct */
-
- /* Lock state reflects inter-node manager's lock state */
- unsigned int gl_state; /* LM_ST_... see harness/lm_interface.h */
-
- /* Lists of gfs_holders */
- osi_list_t gl_holders; /* all current holders of the glock */
- osi_list_t gl_waiters1; /* HIF_MUTEX */
- osi_list_t gl_waiters2; /* HIF_DEMOTE, HIF_GREEDY */
- osi_list_t gl_waiters3; /* HIF_PROMOTE */
-
- struct gfs_glock_operations *gl_ops; /* function vector, defines type */
-
- /* State to remember for async lock requests */
- struct gfs_holder *gl_req_gh; /* Holder for request being serviced */
- gfs_glop_bh_t gl_req_bh; /* The bottom half to execute */
-
- lm_lock_t *gl_lock; /* Lock module's private lock data */
- char *gl_lvb; /* Lock Value Block */
- atomic_t gl_lvb_count; /* LVB recursive usage (hold/unhold) count */
-
- uint64_t gl_vn; /* Incremented when protected data changes */
- unsigned long gl_stamp; /* Glock cache retention timer */
- void *gl_object; /* The protected entity (e.g. a dinode) */
-
- /* Incore transaction stuff */
- /* Log elements map us to a particular set of log operations functions,
- and to a particular transaction */
- struct gfs_log_element gl_new_le; /* New, incomplete transaction */
- struct gfs_log_element gl_incore_le; /* Complete (committed) trans */
-
- struct gfs_gl_hash_bucket *gl_bucket; /* Our bucket in sd_gl_hash */
- osi_list_t gl_reclaim; /* Link to sd_reclaim_list */
-
- struct gfs_sbd *gl_sbd; /* Superblock (FS instance) */
-
- struct inode *gl_aspace; /* The buffers protected by this lock */
- osi_list_t gl_ail_bufs; /* AIL buffers protected by us */
-};
-
-/*
- * In-Place Reservation structure
- * Coordinates allocation of "in-place" (as opposed to journal) FS blocks,
- * which contain persistent inode/file/directory data and metadata.
- * These blocks are the allocatable blocks within resource groups (i.e.
- * not including rgrp header and block alloc bitmap blocks).
- * gfs_inplace_reserve() calculates a fulfillment plan for allocating blocks,
- * based on block statistics in the resource group headers.
- * Then, gfs_blkalloc() or gfs_metaalloc() walks the block alloc bitmaps
- * to do the actual allocation.
- */
-struct gfs_alloc {
- /* Up to 4 quotas (including an inode's user and group quotas)
- can track changes in block allocation */
-
- unsigned int al_qd_num; /* # of quotas tracking changes */
- struct gfs_quota_data *al_qd[4]; /* Ptrs to quota structures */
- struct gfs_holder al_qd_ghs[4]; /* Holders for quota glocks */
-
- /* Request, filled in by the caller to gfs_inplace_reserve() */
-
- uint32_t al_requested_di; /* Number of dinodes to reserve */
- uint32_t al_requested_meta; /* Number of metadata blocks to reserve */
- uint32_t al_requested_data; /* Number of data blocks to reserve */
-
- /* Fulfillment plan, filled in by gfs_inplace_reserve() */
-
- char *al_file; /* Debug info, .c file making request */
- unsigned int al_line; /* Debug info, line of code making req */
- struct gfs_holder al_ri_gh; /* Glock holder for resource grp index */
- struct gfs_holder al_rgd_gh; /* Glock holder for al_rgd rgrp */
- struct gfs_rgrpd *al_rgd; /* Resource group from which to alloc */
- uint32_t al_reserved_meta; /* Alloc up to this # meta blocks from al_rgd */
- uint32_t al_reserved_data; /* Alloc up to this # data blocks from al_rgd */
-
- /* Actual alloc, filled in by gfs_blkalloc()/gfs_metaalloc(), etc. */
-
- uint32_t al_alloced_di; /* # dinode blocks allocated */
- uint32_t al_alloced_meta; /* # meta blocks allocated */
- uint32_t al_alloced_data; /* # data blocks allocated */
-
- /* Dinode allocation crap */
-
- struct gfs_unlinked *al_ul; /* Unlinked dinode log entry */
-};
-
-/*
- * Incore inode structure
- */
-
-#define GIF_QD_LOCKED (0)
-#define GIF_PAGED (1)
-#define GIF_SW_PAGED (2)
-
-struct gfs_inode {
- struct gfs_inum i_num; /* Formal inode # and block address */
-
- atomic_t i_count; /* Usage count */
- unsigned long i_flags; /* GIF_... see above */
-
- uint64_t i_vn; /* Version #: if different from glock's vn,
- we need to read inode from disk */
- struct gfs_dinode i_di; /* Dinode (on-disk) structure */
-
- struct gfs_glock *i_gl; /* This glock protects this inode */
- struct gfs_sbd *i_sbd; /* Superblock (fs instance structure) */
- struct inode *i_vnode; /* Linux VFS inode structure */
-
- struct gfs_holder i_iopen_gh; /* Glock holder for Inode Open lock */
-
- /* Block allocation strategy, inode scope */
- struct gfs_alloc *i_alloc; /* In-place block reservation structure */
- uint64_t i_last_rg_alloc; /* Most recent blk alloc was fm this rgrp */
-
- spinlock_t i_spin;
- struct rw_semaphore i_rw_mutex;
-
- /* Cache of most-recently used buffers in indirect addressing chain */
- struct buffer_head *i_cache[GFS_MAX_META_HEIGHT];
-
- unsigned int i_greedy; /* The amount of time to be greedy */
- unsigned long i_last_pfault; /* The time of the last page fault */
-};
-
-struct inode_info
-{
- osi_list_t list;
- uint64_t inode;
- uint32_t link_count; /* the number of links the inode
- * thinks it has */
- uint32_t counted_links; /* the number of links we've found */
-};
-
-struct dir_info
-{
- osi_list_t list;
- uint64_t dinode;
- uint64_t treewalk_parent;
- uint64_t dotdot_parent;
- uint8_t checked:1;
-
-};
-
-/*
- * GFS per-fd structure
- */
-
-#define GFF_DID_DIRECT_ALLOC (0)
-
-struct gfs_file {
- unsigned long f_flags; /* GFF_... see above */
-
- struct semaphore f_fl_lock; /* Lock to protect flock operations */
- struct gfs_holder f_fl_gh; /* Holder for this f_vfile's flock */
-
- struct gfs_inode *f_inode; /* Incore GFS inode */
- struct file *f_vfile; /* Linux file struct */
-};
-
-/*
- * Unlinked inode log entry incore structure
- */
-
-#define ULF_NEW_UL (0) /* Part of new (being built) trans */
-#define ULF_INCORE_UL (1) /* Part of incore-committed trans */
-#define ULF_IC_LIST (2)
-#define ULF_OD_LIST (3)
-#define ULF_LOCK (4) /* Protects access to this structure */
-
-struct gfs_unlinked {
- osi_list_t ul_list; /* Link to superblock's sd_unlinked_list */
- unsigned int ul_count; /* Usage count */
-
- struct gfs_inum ul_inum; /* Formal inode #, block addr */
- unsigned long ul_flags; /* ULF_... */
-
- /* Log elements map us to a particular set of log operations functions,
- and to a particular transaction */
- struct gfs_log_element ul_new_le; /* New, not yet committed */
- struct gfs_log_element ul_incore_le; /* Committed to incore log */
- struct gfs_log_element ul_ondisk_le; /* Committed to ondisk log */
-};
-
-/*
- * Quota log element
- * One for each logged change in a block alloc value affecting a given quota.
- * Only one of these for a given quota within a given transaction;
- * multiple changes, within one transaction, for a given quota will be
- * combined into one log element.
- */
-struct gfs_quota_le {
- /* Log element maps us to a particular set of log operations functions,
- and to a particular transaction */
- struct gfs_log_element ql_le; /* Generic log element structure */
-
- struct gfs_quota_data *ql_data; /* The quota we're changing */
- osi_list_t ql_data_list; /* Link to quota's log element list */
-
- int64_t ql_change; /* # of blocks alloc'd (+) or freed (-) */
-};
-
-/*
- * Quota structure
- * One for each user or group quota.
- * Summarizes all block allocation activity for a given quota, and supports
- * recording updates of current block alloc values in GFS' special quota
- * file, including the journaling of these updates, encompassing
- * multiple transactions and log dumps.
- */
-
-#define QDF_USER (0) /* User (1) vs. group (0) quota */
-#define QDF_OD_LIST (1) /* Waiting for sync to quota file */
-#define QDF_LOCK (2) /* Protects access to this structure */
-
-struct gfs_quota_data {
- osi_list_t qd_list; /* Link to superblock's sd_quota_list */
- unsigned int qd_count; /* Usage count */
-
- uint32_t qd_id; /* User or group ID number */
- unsigned long qd_flags; /* QDF_... */
-
- /* This list is for non-log-dump transactions */
- osi_list_t qd_le_list; /* List of gfs_quota_le log elements */
-
- /* Summary of block alloc changes affecting this quota, in various
- stages of logging & syncing changes to the special quota file */
- int64_t qd_change_new; /* New, not yet committed to in-core log*/
- int64_t qd_change_ic; /* Committed to in-core log */
- int64_t qd_change_od; /* Committed to on-disk log */
- int64_t qd_change_sync; /* Being synced to the in-place quota file */
-
- struct gfs_quota_le qd_ondisk_ql; /* Log element for log dump */
- uint64_t qd_sync_gen; /* Sync-to-quota-file generation # */
-
- /* Glock provides protection for quota, *and* provides
- lock value block (LVB) communication, between nodes, of current
- quota values. Shared lock -> LVB read. EX lock -> LVB write. */
- struct gfs_glock *qd_gl; /* glock for this quota */
- struct gfs_quota_lvb qd_qb; /* LVB (limit/warn/value) */
-
- unsigned long qd_last_warn; /* Jiffies of last warning to user */
-};
-
-/*
- * Log Buffer descriptor structure.
- * One for each block buffer recorded in the log.
- * When beginning a new transaction, GFS pre-allocates a number of these,
- * and puts them on transaction's tr_free_bufs list.
- * Logged buffers are of two types:
- * 1). Exact copies of buffers to be written to in-place location in FS.
- * 2). Log-only buffers such as log headers and control blocks (e.g. tags).
- * A gfs_log_buf is required for both types; the ones for log-only buffers
- * contain NULL in lb_unlock, and get cleaned up after the log write.
- * lb_bh is a "fake" buffer head that directs Linux block I/O to write the buf
- * to the on-disk log location, rather than the on-disk in-place location.
- * Used for both types.
- * lb_unlock points to the "real" buffer head that directs Linux to write the
- * buf to its regular on-disk in-place filesystem location. Once the commit
- * to the on-disk log is finished, GFS unlocks the "real" buffer so it can be
- * written to in-place block, or modified by another transaction.
- * Used only for type 1).
- */
-struct gfs_log_buf {
- /* Link to one of the transaction structure's lists */
- osi_list_t lb_list; /* Link to tr_free_bufs or tr_list */
-
- struct buffer_head lb_bh; /* "Fake" bh; for the log block */
- struct buffer_head *lb_unlock; /* "Real" bh; for the in-place block */
-};
-
-/*
- * Transaction structure
- * One for each transaction
- * This coordinates the logging and flushing of written metadata.
- */
-
-#define TRF_LOG_DUMP (0x00000001)
-#define TRF_DUMMY (0x00000002)
-
-struct gfs_trans {
-
- /* Link to various lists */
- osi_list_t tr_list; /* Superblk's incore trans or AIL list*/
-
- /* Initial creation stuff */
-
- char *tr_file; /* Debug info: .c file creating trans */
- unsigned int tr_line; /* Debug info: codeline creating trans */
-
- /* Reservations for on-disk space in journal.
- Meta blocks are copies of in-place filesystem blocks.
- Extra blocks are log-only (log header and control blocks) */
- unsigned int tr_mblks_asked; /* # of meta log blocks requested */
- unsigned int tr_eblks_asked; /* # of extra log blocks requested */
- unsigned int tr_seg_reserved; /* # of segments actually reserved */
-
- struct gfs_holder *tr_t_gh; /* Glock holder for this transaction */
-
- /* Stuff filled in during creation */
-
- unsigned int tr_flags; /* TRF_... */
- osi_list_t tr_elements; /* List of this trans' log elements */
-
- /* Stuff modified during the commit */
-
- /* When creating a new transaction, GFS pre-allocates as many of
- these buffers and descriptor structures as it might need for
- all loggable filesystem (meta)data, and log-control (log-only, not
- going to filesystem in-place location) data going to on-disk log.
- It keeps them on these "free" lists until they get used (and linked
- into tr_bufs list, below) or "refunded" if not needed. */
- unsigned int tr_num_free_bufs; /* List of free gfs_log_buf structs */
- osi_list_t tr_free_bufs; /* .. 1 for each log block */
- unsigned int tr_num_free_bmem; /* List of free fs-block-size buffers */
- osi_list_t tr_free_bmem; /* .. for log-only (e.g. tag) blocks */
-
- /* Logged transaction starts with a (first) log header at a segment
- boundary, and fills contiguous blocks after that. Each segment
- boundary block gets another log header. */
- uint64_t tr_log_head; /* The next log block # to fill */
- uint64_t tr_first_head; /* Trans' first log header's block # */
-
- /* gfs_log_buf structs move from tr_free_bufs to here when being used */
- osi_list_t tr_bufs; /* List of buffers going to the log */
-
- /* Stuff that's part of the Active Items List (AIL) */
-
- osi_list_t tr_ail_bufs; /* List of buffers on AIL list */
-
- /* # log elements of various types on tr_elements list */
-
- unsigned int tr_num_gl; /* Glocks */
- unsigned int tr_num_buf; /* Buffers */
- unsigned int tr_num_iul; /* Unlinked inodes */
- unsigned int tr_num_ida; /* De-allocated inodes */
- unsigned int tr_num_q; /* Quotas */
-};
-
-#define GFS_GLOCKD_DEFAULT (1)
-#define GFS_GLOCKD_MAX (32)
-
-struct gfs_args {
- char ar_lockproto[GFS_LOCKNAME_LEN]; /* The name of the Lock Protocol */
- char ar_locktable[GFS_LOCKNAME_LEN]; /* The name of the Lock Table */
- char ar_hostdata[GFS_LOCKNAME_LEN]; /* The host specific data */
-
- /*
- * GFS can invoke some flock and disk caching optimizations if it is
- * not in a cluster, i.e. is a local filesystem. The chosen lock
- * module tells GFS, at mount time, if it supports clustering.
- * The nolock module is the only one that does not support clustering;
- * it sets to TRUE the local_fs field in the struct lm_lockops.
- * GFS can either optimize, or ignore the opportunity.
- * The user controls behavior via the following mount options.
- */
- int ar_ignore_local_fs; /* Don't optimize even if local_fs is TRUE */
- int ar_localflocks; /* Let the VFS do flock|fcntl locks for us */
- int ar_localcaching; /* Local-style caching (dangerous on multihost) */
- int ar_oopses_ok; /* Allow oopses */
-
- int ar_debug; /* Oops on errors instead of trying to be graceful */
- int ar_upgrade; /* Upgrade ondisk/multihost format */
-
- unsigned int ar_num_glockd; /* # of glock cleanup daemons to run
- (more daemons => faster cleanup) */
- int ar_posix_acls; /* Enable posix acls */
- int ar_suiddir; /* suiddir support */
-};
-
-struct gfs_tune {
- spinlock_t gt_spin;
-
- unsigned int gt_ilimit1;
- unsigned int gt_ilimit1_tries;
- unsigned int gt_ilimit1_min;
- unsigned int gt_ilimit2;
- unsigned int gt_ilimit2_tries;
- unsigned int gt_ilimit2_min;
- unsigned int gt_demote_secs; /* Cache retention for unheld glock */
- unsigned int gt_incore_log_blocks;
- unsigned int gt_jindex_refresh_secs; /* Check for new journal index */
- unsigned int gt_depend_secs;
-
- /* How often various daemons run (seconds) */
- unsigned int gt_scand_secs; /* Find unused glocks and inodes */
- unsigned int gt_recoverd_secs; /* Recover journal of crashed node */
- unsigned int gt_logd_secs; /* Update log tail as AIL flushes */
- unsigned int gt_quotad_secs; /* Sync changes to quota file, clean*/
- unsigned int gt_inoded_secs; /* Toss unused inodes */
-
- unsigned int gt_quota_simul_sync; /* Max # quotavals to sync at once */
- unsigned int gt_quota_warn_period; /* Secs between quota warn msgs */
- unsigned int gt_atime_quantum; /* Min secs between atime updates */
- unsigned int gt_quota_quantum; /* Secs between syncs to quota file */
- unsigned int gt_quota_scale_num; /* Numerator */
- unsigned int gt_quota_scale_den; /* Denominator */
- unsigned int gt_quota_enforce;
- unsigned int gt_quota_account;
- unsigned int gt_new_files_jdata;
- unsigned int gt_new_files_directio;
- unsigned int gt_max_atomic_write; /* Split large writes into this size*/
- unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */
- unsigned int gt_lockdump_size;
- unsigned int gt_stall_secs; /* Detects trouble! */
- unsigned int gt_complain_secs;
- unsigned int gt_reclaim_limit; /* Max # glocks in reclaim list */
- unsigned int gt_entries_per_readdir;
- unsigned int gt_prefetch_secs; /* Usage window for prefetched glocks */
- unsigned int gt_statfs_slots;
- unsigned int gt_max_mhc; /* Max # of meta headers in mhc cache */
- unsigned int gt_greedy_default;
- unsigned int gt_greedy_quantum;
- unsigned int gt_greedy_max;
- unsigned int gt_rgrp_try_threshold;
-};
-
-/*
- * One bucket of the filesystem's sd_gl_hash glock hash table.
- *
- * A gfs_glock links into a bucket's list via glock's gl_list member.
- *
- */
-struct gfs_gl_hash_bucket {
- rwlock_t hb_lock; /* Protects list */
- osi_list_t hb_list; /* List of glocks in this bucket */
-};
-
-struct options {
- char *device;
- int yes:1;
- int no:1;
-};
-
-/*
- * "Super Block" Data Structure
- * One per mounted filesystem.
- * This is the big instance structure that ties everything together for
- * a given mounted filesystem. Each GFS mount has its own, supporting
- * mounts of multiple GFS filesystems on each node.
- * Pointer to this is usually seen as "sdp" throughout code.
- * This is a very large structure, as structures go, in part because it
- * contains arrays of hash buckets for various in-core caches.
- */
-
-#define SDF_JOURNAL_LIVE (0) /* Journaling is active (journal is writeable)*/
-#define SDF_SHUTDOWN (1) /* FS abnormaly shutdown */
-
-/* Run (1) / stop (0) flags for various daemons */
-#define SDF_SCAND_RUN (2) /* Put unused glocks on reclaim queue */
-#define SDF_GLOCKD_RUN (3) /* Reclaim (dealloc) unused glocks */
-#define SDF_RECOVERD_RUN (4) /* Recover journal of a crashed node */
-#define SDF_LOGD_RUN (5) /* Update log tail after AIL flushed */
-#define SDF_QUOTAD_RUN (6) /* Sync quota changes to file, cleanup */
-#define SDF_INODED_RUN (7) /* Deallocate unlinked inodes */
-
-/* (Re)mount options from Linux VFS */
-#define SDF_NOATIME (8) /* Don't change access time */
-#define SDF_ROFS (9) /* Read-only mode */
-
-/* Journal log dump support */
-#define SDF_NEED_LOG_DUMP (10) /* Need to rewrite unlink and quota tags */
-#define SDF_FOUND_UL_DUMP (11) /* Recovery found unlinked tags */
-#define SDF_FOUND_Q_DUMP (12) /* Recovery found qutoa tags */
-#define SDF_IN_LOG_DUMP (13) /* Serializes log dumps */
-
-/* Glock cache */
-#define GFS_GL_HASH_SHIFT (13) /* # hash buckets = 8K */
-#define GFS_GL_HASH_SIZE (1 << GFS_GL_HASH_SHIFT)
-#define GFS_GL_HASH_MASK (GFS_GL_HASH_SIZE - 1)
-
-/* Meta header cache */
-#define GFS_MHC_HASH_SHIFT (10) /* # hash buckets = 1K */
-#define GFS_MHC_HASH_SIZE (1 << GFS_MHC_HASH_SHIFT)
-#define GFS_MHC_HASH_MASK (GFS_MHC_HASH_SIZE - 1)
-
-/* Dependency cache */
-#define GFS_DEPEND_HASH_SHIFT (10) /* # hash buckets = 1K */
-#define GFS_DEPEND_HASH_SIZE (1 << GFS_DEPEND_HASH_SHIFT)
-#define GFS_DEPEND_HASH_MASK (GFS_DEPEND_HASH_SIZE - 1)
-
-struct gfs_sbd {
- struct gfs_sb sd_sb; /* GFS on-disk Super Block image */
-
- struct super_block *sd_vfs; /* Linux VFS device independent sb */
-
- struct gfs_args sd_args; /* Mount arguments */
- unsigned long sd_flags; /* SDF_... see above */
-
- struct gfs_tune sd_tune; /* Filesystem tuning structure */
-
- /* Resource group stuff */
-
- struct gfs_inode *sd_riinode; /* Resource Index (rindex) inode */
- uint64_t sd_riinode_vn; /* Resource Index version # (detects
- whether new rgrps have been added) */
-
- osi_list_t sd_rglist; /* List of all resource groups,
- on-disk order */
- struct semaphore sd_rindex_lock;/* Serializes RIndex rereads */
- osi_list_t sd_rg_mru_list;/* List of all resource groups,
- most-recently-used (MRU) order */
- spinlock_t sd_rg_mru_lock; /* Protect mru list */
- osi_list_t sd_rg_recent; /* List of rgrps from which blocks
- were recently allocated */
- spinlock_t sd_rg_recent_lock; /* Protect recent list */
- struct gfs_rgrpd *sd_rg_forward;/* Next rgrp from which to attempt
- a block alloc */
- spinlock_t sd_rg_forward_lock; /* Protect forward pointer */
-
- unsigned int sd_rgcount; /* Total # of resource groups */
-
- /* Constants computed on mount */
-
- /* "bb" == "basic block" == 512Byte sector */
- uint32_t sd_fsb2bb; /* # 512B basic blocks in a FS block */
- uint32_t sd_fsb2bb_shift; /* Shift sector # to the right by
- this to get FileSystem block addr */
- uint32_t sd_diptrs; /* Max # of block pointers in a dinode */
- uint32_t sd_inptrs; /* Max # of block pointers in an indirect blk */
- uint32_t sd_jbsize; /* Payload size (bytes) of a journaled metadata
- block (GFS journals all meta blocks) */
- uint32_t sd_hash_bsize; /* sizeof(exhash hash block) */
- uint32_t sd_hash_bsize_shift;
- uint32_t sd_hash_ptrs; /* Number of points in a hash block */
- uint32_t sd_max_dirres; /* Max blocks needed to add a directory entry */
- uint32_t sd_max_height; /* Max height of a file's tree */
- uint64_t sd_heightsize[GFS_MAX_META_HEIGHT];
- uint32_t sd_max_jheight; /* Max height, journaled file's tree */
- uint64_t sd_jheightsize[GFS_MAX_META_HEIGHT];
-
- /* Lock Stuff */
-
- /* Glock cache (all glocks currently held by this node for this FS) */
- struct gfs_gl_hash_bucket sd_gl_hash[GFS_GL_HASH_SIZE];
-
- /* Glock reclaim support for scand and glockd */
- osi_list_t sd_reclaim_list; /* List of glocks to reclaim */
- spinlock_t sd_reclaim_lock;
- wait_queue_head_t sd_reclaim_wchan;
- atomic_t sd_reclaim_count; /* # glocks on reclaim list */
-
- /* Lock module tells us if we're first-to-mount,
- which journal to use, etc. */
- struct lm_lockstruct sd_lockstruct; /* Info provided by lock module */
-
- /* Other caches */
-
- /* Meta-header cache (incore copies of on-disk meta headers) */
- osi_list_t sd_mhc[GFS_MHC_HASH_SIZE]; /* hash buckets */
- osi_list_t sd_mhc_single; /* Non-hashed list of all MHCs */
- spinlock_t sd_mhc_lock;
- atomic_t sd_mhc_count; /* # MHCs in cache */
-
- /* Dependency cache */
- osi_list_t sd_depend[GFS_DEPEND_HASH_SIZE]; /* Hash buckets */
- spinlock_t sd_depend_lock;
- atomic_t sd_depend_count; /* # dependencies in cache */
-
- /* LIVE inter-node lock indicates that FS is mounted on at least
- one node */
- struct gfs_holder sd_live_gh; /* Glock holder for LIVE lock */
-
- /* For quiescing the filesystem */
- struct gfs_holder sd_freeze_gh;
- struct semaphore sd_freeze_lock;
- unsigned int sd_freeze_count;
-
- /* Inode Stuff */
-
- struct gfs_inode *sd_rooti; /* FS's root inode */
-
- /* Only 1 node at a time may rename (e.g. mv) directory from
- one directory to another. */
- struct gfs_glock *sd_rename_gl; /* Rename glock */
-
- /* Daemon stuff */
-
- /* Scan for glocks and inodes to toss from memory */
- struct task_struct *sd_scand_process; /* Scand places on reclaim list*/
- unsigned int sd_glockd_num; /* # of glockd procs to do reclaiming*/
-
- /* Recover journal of a crashed node */
- struct task_struct *sd_recoverd_process;
-
- /* Update log tail as AIL gets flushed to in-place on-disk blocks */
- struct task_struct *sd_logd_process;
-
- /* Sync quota updates to disk, and clean up unused quota structs */
- struct task_struct *sd_quotad_process;
-
- /* Clean up unused inode structures */
- struct task_struct *sd_inoded_process;
-
- /* Support for starting/stopping daemons */
- struct semaphore sd_thread_lock;
- struct completion sd_thread_completion;
-
- /* Log stuff */
-
- /* Transaction lock protects the following from one another:
- normal write transaction, journal replay (recovery), fs upgrade,
- fs read-only => read/write and read/write => read-only conversions.
- Also, acquiring the transaction lock in a state other than shared
- causes all other machines in the cluster to sync out their dirty
- data, mark their journal as being clean, and prevent any new FS
- modifications from occuring (i.e. quiesces the FS). */
- struct gfs_glock *sd_trans_gl; /* Transaction glock structure */
-
- struct gfs_inode *sd_jiinode; /* Journal index inode */
- uint64_t sd_jiinode_vn; /* Journal index version # (detects
- if new journals have been added) */
-
- unsigned int sd_journals; /* Number of journals in the FS */
- struct gfs_jindex *sd_jindex; /* Array of journal descriptors */
- struct semaphore sd_jindex_lock;
- unsigned long sd_jindex_refresh_time; /* Poll for new journals (secs) */
-
- struct gfs_jindex sd_jdesc; /* This machine's journal descriptor */
- struct gfs_holder sd_journal_gh; /* This machine's jrnl glock holder */
-
- uint64_t sd_sequence; /* Assigned to xactions in order they commit */
- uint64_t sd_log_head; /* Block number of next journal write */
- uint64_t sd_log_wrap;
-
- spinlock_t sd_log_seg_lock;
- unsigned int sd_log_seg_free; /* # of free segments in the log */
- unsigned int sd_log_seg_ail2; /* # of freeable segments in the log */
- osi_list_t sd_log_seg_list;
- wait_queue_head_t sd_log_seg_wait;
-
- /* "Active Items List" of transactions that have been flushed to
- on-disk log, and are waiting for flush to in-place on-disk blocks */
- osi_list_t sd_log_ail; /* "next" is head, "prev" is tail */
-
- /* Transactions committed incore, but not yet flushed to on-disk log */
- osi_list_t sd_log_incore; /* "Next" is newest, "prev" is oldest */
- unsigned int sd_log_buffers; /* # of buffers in the incore log */
-
- struct rw_semaphore sd_log_lock; /* Lock for access to log values */
-
- uint64_t sd_log_dump_last;
- uint64_t sd_log_dump_last_wrap;
-
- /*
- * Unlinked inode crap.
- * List includes newly created, not-yet-linked inodes,
- * as well as inodes that have been unlinked and are waiting
- * to be de-allocated.
- */
- osi_list_t sd_unlinked_list; /* List of unlinked inodes */
- spinlock_t sd_unlinked_lock; /* Protects list and members */
-
- atomic_t sd_unlinked_ic_count;
- atomic_t sd_unlinked_od_count;
-
- /* Quota crap */
-
- osi_list_t sd_quota_list; /* List of all gfs_quota_data structs */
- spinlock_t sd_quota_lock;
-
- atomic_t sd_quota_count; /* # quotas on sd_quota_list */
- atomic_t sd_quota_od_count; /* # quotas waiting for sync to
- special on-disk quota file */
-
- struct gfs_inode *sd_qinode; /* Special on-disk quota file */
-
- uint64_t sd_quota_sync_gen; /* Generation, incr when sync to file */
- unsigned long sd_quota_sync_time; /* Jiffies, last sync to quota file */
-
- /* License crap */
-
- struct gfs_inode *sd_linode; /* Special on-disk license file */
-
- /* Recovery stuff */
-
- /* Lock module tells GFS, via callback, when a journal needs recovery.
- It stays on this list until recovery daemon performs recovery. */
- osi_list_t sd_dirty_j; /* List of dirty journals */
- spinlock_t sd_dirty_j_lock; /* Protects list */
-
- /* Statistics for 3 possible recovery actions for each buffer in log,
- determined by comparing generation #s of logged block and
- in-place block. Scope of stats is for one journal. */
- unsigned int sd_recovery_replays; /* newer than in-place; copy it */
- unsigned int sd_recovery_skips; /* older than in-place; ignore it */
- unsigned int sd_recovery_sames; /* same as in-place; ignore it */
-
- /* Counters */
-
- /* current quantities of various things */
- atomic_t sd_glock_count; /* # of gfs_glock structs alloc'd */
- atomic_t sd_glock_held_count; /* # of glocks locked by this node */
- atomic_t sd_inode_count; /* # of gfs_inode structs alloc'd */
- atomic_t sd_bufdata_count; /* # of gfs_bufdata structs alloc'd */
-
- atomic_t sd_fh2dentry_misses; /* total # get_dentry misses */
- atomic_t sd_reclaimed; /* total # glocks reclaimed since mount */
-
- /* total lock-related calls handled since mount */
- atomic_t sd_glock_nq_calls;
- atomic_t sd_glock_dq_calls;
- atomic_t sd_glock_prefetch_calls;
- atomic_t sd_lm_lock_calls;
- atomic_t sd_lm_unlock_calls;
- atomic_t sd_lm_callbacks;
-
- atomic_t sd_lm_outstanding;
- atomic_t sd_bio_reads;
- atomic_t sd_bio_writes;
- atomic_t sd_bio_outstanding;
-
- /* total calls from Linux VFS handled since mount */
- atomic_t sd_ops_address;
- atomic_t sd_ops_dentry;
- atomic_t sd_ops_export;
- atomic_t sd_ops_file;
- atomic_t sd_ops_inode;
- atomic_t sd_ops_super;
- atomic_t sd_ops_vm;
-
- char sd_fsname[256];
-
- /* Debugging crud */
-
- unsigned long sd_last_warning;
-
- spinlock_t sd_ail_lock;
- osi_list_t sd_recovery_bufs;
-
- osi_list_t sd_list;
-#ifndef __KERNEL__ /* if called from userland */
- uint64_t last_fs_block;
- uint64_t last_data_block;
- uint64_t first_data_block;
- /* contains list of data and metadata blocks and various info about each */
- struct block_list *bl;
- struct gfs_inode *lf_dip; /* lost-n-found dir inode */
- /* dir_list is used to keep track of directory inodes and
- * their parents */
- osi_list_t dir_hash[FSCK_HASH_SIZE];
-
- /* inode_list is used to keep track of the link count of
- * inodes */
- osi_list_t inode_hash[FSCK_HASH_SIZE];
- osi_list_t dup_list;
-#endif
-};
-
-#endif /* __INCORE_DOT_H__ */
diff --git a/gfs/libgfs/inode.c b/gfs/libgfs/inode.c
deleted file mode 100644
index b288ef6..0000000
--- a/gfs/libgfs/inode.c
+++ /dev/null
@@ -1,322 +0,0 @@
-#include <stdint.h>
-#include "gfs_ondisk.h"
-#include "incore.h"
-#include "osi_user.h"
-#include "libgfs.h"
-
-/* FIXME: Not crazy about this name vs. load_inode, but I'm not very
- * creative ATM */
-/* replaces fs_copyin_dinode */
-int copyin_inode(struct gfs_sbd *sbp, osi_buf_t *bh, struct gfs_inode **inode)
-{
- struct gfs_inode *ip;
-
- if(!(ip = (struct gfs_inode *)malloc(sizeof(struct gfs_inode)))) {
- log_err("Unable to allocate memory for inode\n");
- return -1;
- }
- if(!memset(ip, 0, sizeof(struct gfs_inode))) {
- log_err("Unable to zero inode memory\n");
- return -1;
- }
- ip->i_sbd = sbp;
-
- ip->i_num.no_addr = ip->i_num.no_formal_ino = BH_BLKNO(bh);
- memset(&ip->i_di, 0, sizeof(struct gfs_dinode));
-
- gfs_dinode_in(&ip->i_di, BH_DATA(bh));
-
- *inode = ip;
-
- return 0;
-}
-
-int load_inode(int disk_fd, struct gfs_sbd *sbp, uint64_t block,
- struct gfs_inode **inode)
-{
- osi_buf_t *bh;
-
- if(get_and_read_buf(disk_fd, sbp->sd_sb.sb_bsize, block, &bh, 0)){
- log_err("Unable to retrieve block %"PRIu64"\n",
- block);
- return -1;
- }
-
- if(copyin_inode(sbp, bh, inode)) {
- relse_buf(bh);
- return -1;
- }
-
- relse_buf(bh);
- return 0;
-}
-
-
-void free_inode(struct gfs_inode **inode)
-{
- free(*inode);
- inode = NULL;
-}
-
-
-int check_inode(struct gfs_inode *ip)
-{
- int error = 0;
- if(ip->i_di.di_header.mh_type != GFS_METATYPE_DI) {
- return -1;
- }
-
- if(ip->i_num.no_formal_ino != ip->i_di.di_num.no_formal_ino){
- log_err(
- "In-core and on-disk formal inode"
- "numbers do not match. %"PRIu64" %"PRIu64"\n",
- ip->i_num.no_formal_ino,
- ip->i_di.di_num.no_formal_ino);
- error = -1;
- }
-
- /* Handle a moved inode */
-
- if (ip->i_num.no_addr != ip->i_di.di_num.no_addr){
- log_err("\tBlock # used to read disk inode: %"PRIu64"\n"
- "\tBlock # recorded in disk inode : %"PRIu64"\n",
- ip->i_num.no_addr, ip->i_di.di_num.no_addr);
- error = -1;
- }
-
- return error;
-
-}
-
-
-
-/*int remove_inode(struct gfs_sbd *sbp, uint64_t block)
-{
- struct gfs_inode *ip;
- load_inode(sbp, block, &ip);
- check_metatree(ip, &fxns);
- free_inode(&ip);
- return 0;
-}*/
-
-/**
- * fs_get_istruct - Get an inode given its number
- * @sdp: The GFS superblock
- * @inum: The inode number
- * @create: Flag to say if we are allowed to create a new struct gfs_inode
- * @ipp: pointer to put the returned inode in
- *
- * Returns: 0 on success, -1 on error
- */
-static int fs_get_istruct(int disk_fd, struct gfs_sbd *sdp,
- struct gfs_inum *inum,
- int create, struct gfs_inode **ipp)
-{
- struct gfs_inode *ip = NULL;
- int error = 0;
-
- if (!create){
- /* we are not currently tracking which inodes we already have */
- error = -1;
- goto out;
- }
-
- ip = (struct gfs_inode *)malloc(sizeof(struct gfs_inode));
- // FIXME: handle failed malloc
- ip->i_num = *inum;
-
- ip->i_sbd = sdp;
-
- error = fs_copyin_dinode(disk_fd, sdp->sd_sb.sb_bsize, ip, NULL);
- if (error){
- free(ip);
- ip = NULL;
- goto out;
- }
-
- out:
- *ipp = ip;
-
- return error;
-}
-
-
-
-/**
- * make_dinode - Fill in a new dinode structure
- * @dip: the directory this inode is being created in
- * @inum: the inode number
- * @type: the file type
- * @mode: the file permissions
- * @cred: a credentials structure
- *
- */
-
-int make_dinode(int disk_fd, struct gfs_inode *dip,
- struct gfs_sbd *sdp, struct gfs_inum *inum,
- unsigned int type, unsigned int mode, osi_cred_t *cred)
-{
- struct gfs_dinode di;
- osi_buf_t *dibh;
- struct gfs_rgrpd *rgd;
- int error;
-
- error = get_and_read_buf(disk_fd, sdp->sd_sb.sb_bsize, inum->no_addr,
- &dibh, 0);
- if (error)
- goto out;
-
- if(check_meta(dibh, 0)){
- struct gfs_meta_header mh;
- log_debug("Buffer #%"PRIu64" has no meta header.\n",
- BH_BLKNO(dibh));
- memset(&mh, 0, sizeof(struct gfs_meta_header));
- mh.mh_magic = GFS_MAGIC;
- mh.mh_type = GFS_METATYPE_NONE;
- gfs_meta_header_out(&mh, BH_DATA(dibh));
- log_debug("meta header added.\n");
- }
-
- ((struct gfs_meta_header *)BH_DATA(dibh))->mh_type =
- cpu_to_gfs32(GFS_METATYPE_DI);
- ((struct gfs_meta_header *)BH_DATA(dibh))->mh_format =
- cpu_to_gfs32(GFS_FORMAT_DI);
-
- memset(BH_DATA(dibh) + sizeof(struct gfs_dinode), 0,
- BH_SIZE(dibh) - sizeof(struct gfs_dinode));
-
- memset(&di, 0, sizeof(struct gfs_dinode));
-
- gfs_meta_header_in(&di.di_header, BH_DATA(dibh));
-
- di.di_num = *inum;
-
- if (dip && (dip->i_di.di_mode & 02000))
- {
- di.di_mode = mode | ((type == GFS_FILE_DIR) ? 02000 : 0);
- di.di_gid = dip->i_di.di_gid;
- }
- else
- {
- di.di_mode = mode;
- di.di_gid = osi_cred_to_gid(cred);
- }
-
- di.di_uid = osi_cred_to_uid(cred);
- di.di_nlink = 1;
- di.di_blocks = 1;
- di.di_atime = di.di_mtime = di.di_ctime = osi_current_time();
-
- rgd = fs_blk2rgrpd(sdp, inum->no_addr);
- if(!rgd){
- log_crit("Unable to map block #%"PRIu64" to rgrp\n", inum->no_addr);
- exit(1);
- }
-
- di.di_rgrp = rgd->rd_ri.ri_addr;
- di.di_goal_rgrp = di.di_rgrp;
- di.di_goal_dblk = di.di_goal_mblk = inum->no_addr - rgd->rd_ri.ri_data1;
-
- di.di_type = type;
-
- gfs_dinode_out(&di, BH_DATA(dibh));
- if (write_buf(disk_fd, dibh, 0)){
- log_err("make_dinode: bad write_buf()\n");
- error = -EIO;
- }
-
- relse_buf(dibh);
-
-
- out:
-
- return error;
-}
-
-int create_inode(int disk_fd, struct gfs_sbd *sbp, unsigned int type,
- struct gfs_inode **ip)
-{
- uint64_t block;
- struct gfs_rgrpd *rgd;
- osi_list_t *tmp;
- struct gfs_inum inum;
- int allocate=0;
- unsigned int mode = 0755;
- osi_cred_t cred;
- cred.cr_uid = getuid();
- cred.cr_gid = getgid();
- retry:
- inum.no_addr = inum.no_formal_ino = 0;
- /* Search for a resource group that has free space */
- osi_list_foreach(tmp, (osi_list_t *)&sbp->sd_rglist) {
- /* Create a new inode in that rgd */
- rgd = osi_list_entry(tmp, struct gfs_rgrpd, rd_list);
- if(fs_rgrp_read(disk_fd, rgd, FALSE)) {
- return -1;
- }
- if(rgd->rd_rg.rg_freemeta){
- block = fs_blkalloc_internal(rgd, 0,
- GFS_BLKST_FREEMETA, GFS_BLKST_USEDMETA, 1);
- log_debug("Got block %"PRIu64"\n", block);
- if(block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- block += rgd->rd_ri.ri_data1;
-
- inum.no_addr = inum.no_formal_ino = block;
- /* FIXME: type isn't right */
- block_set(sbp->bl, block, type);
- /* write out the rgrp */
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- write_buf(disk_fd, rgd->rd_bh[0], 0);
- fs_rgrp_relse(rgd);
- break;
- }
- else {
- if(allocate && !clump_alloc(disk_fd, rgd, 0)){
- block = fs_blkalloc_internal(rgd, 0,
- GFS_BLKST_FREEMETA,
- GFS_BLKST_USEDMETA, 1);
- log_debug("Got block %"PRIu64"\n", block);
-
- if(block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- block += rgd->rd_ri.ri_data1;
-
- inum.no_addr = inum.no_formal_ino = block;
-
- /* FIXME: type isn't right */
- block_set(sbp->bl, block, type);
-
- /* write out the rgrp */
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- write_buf(disk_fd, rgd->rd_bh[0], 0);
- fs_rgrp_relse(rgd);
- break;
- }
- fs_rgrp_relse(rgd);
- }
- }
-
- if(!inum.no_addr){
- if(allocate){
- log_err("No space available for new file or directory.\n");
- return -1;
- } else {
- allocate = 1;
- goto retry;
- }
- }
-
- /* We need to setup the inode without attaching it to a directory */
- if (make_dinode(disk_fd, NULL, sbp, &inum, type, mode, &cred)) {
- return -1;
- }
- if (fs_get_istruct(disk_fd, sbp, &inum, 1, ip)) {
- return -1;
- }
- return 0;
-}
diff --git a/gfs/libgfs/libgfs.h b/gfs/libgfs/libgfs.h
deleted file mode 100644
index d4e6237..0000000
--- a/gfs/libgfs/libgfs.h
+++ /dev/null
@@ -1,398 +0,0 @@
-/* These make the library more palatable to userland */
-
-#ifndef LIBGFS_H
-#define LIBGFS_H
-
-#include <stdint.h>
-#include "osi_user.h"
-#include "incore.h"
-
-struct qstr {
- unsigned int hash;
- unsigned int len;
- const unsigned char *name;
-};
-#define up(x) ;
-#define up_write(x) ;
-#define down(x) ;
-#define down_write(x) ;
-#define printk printf
-
-/* ------------------------------------------------------------------------- */
-/* formerly bitmap.h: */
-/* ------------------------------------------------------------------------- */
-struct bmap {
- uint64_t size;
- uint64_t mapsize;
- int chunksize;
- int chunks_per_byte;
- char *map;
-};
-
-int bitmap_create(struct bmap *bmap, uint64_t size, uint8_t bitsize);
-int bitmap_set(struct bmap *bmap, uint64_t offset, uint8_t val);
-int bitmap_get(struct bmap *bmap, uint64_t bit, uint8_t *val);
-int bitmap_clear(struct bmap *bmap, uint64_t offset);
-void bitmap_destroy(struct bmap *bmap);
-uint64_t bitmap_size(struct bmap *bmap);
-
-/* ------------------------------------------------------------------------- */
-/* formerly block_list.h: */
-/* ------------------------------------------------------------------------- */
-#define BMAP_COUNT 13
-
-enum block_list_type {
- gbmap = 0, /* Grouped bitmap */
- dbmap, /* Ondisk bitmap - like grouped bitmap, but mmaps
- * the bitmaps onto file(s) ondisk - not implemented */
-};
-
-/* Must be kept in sync with mark_to_bitmap array in block_list.c */
-enum mark_block {
- block_free = 0,
- block_used,
- indir_blk,
- inode_dir,
- inode_file,
- inode_lnk,
- inode_blk,
- inode_chr,
- inode_fifo,
- inode_sock,
- leaf_blk,
- journal_blk,
- meta_other,
- meta_free,
- meta_eattr,
- meta_inval = 15,
- bad_block, /* Contains at least one bad block */
- dup_block, /* Contains at least one duplicate block */
- eattr_block, /* Contains an eattr */
-};
-
-struct block_query {
- uint8_t block_type;
- uint8_t bad_block;
- uint8_t dup_block;
- uint8_t eattr_block;
-};
-
-struct gbmap {
- struct bmap group_map;
- struct bmap bad_map;
- struct bmap dup_map;
- struct bmap eattr_map;
-};
-
-struct dbmap {
- struct bmap group_map;
- char *group_file;
- struct bmap bad_map;
- char *bad_file;
- struct bmap dup_map;
- char *dup_file;
- struct bmap eattr_map;
- char *eattr_file;
-};
-
-union block_lists {
- struct gbmap gbmap;
- struct dbmap dbmap;
-};
-
-
-/* bitmap implementation */
-struct block_list {
- enum block_list_type type;
- /* Union of bitmap, rle */
- union block_lists list;
-};
-
-
-struct block_list *block_list_create(uint64_t size, enum block_list_type type);
-int block_mark(struct block_list *il, uint64_t block, enum mark_block mark);
-int block_set(struct block_list *il, uint64_t block, enum mark_block mark);
-int block_clear(struct block_list *il, uint64_t block, enum mark_block m);
-int block_check(struct block_list *il, uint64_t block,
- struct block_query *val);
-int block_check_for_mark(struct block_list *il, uint64_t block,
- enum mark_block mark);
-void *block_list_destroy(struct block_list *il);
-int find_next_block_type(struct block_list *il, enum mark_block m, uint64_t *b);
-
-/* ------------------------------------------------------------------------- */
-/* formerly log.h: */
-/* ------------------------------------------------------------------------- */
-#define MSG_DEBUG 7
-#define MSG_INFO 6
-#define MSG_NOTICE 5
-#define MSG_WARN 4
-#define MSG_ERROR 3
-#define MSG_CRITICAL 2
-#define MSG_NULL 1
-
-struct options;
-
-#define print_log(iif, priority, format...) \
-do { \
- print_log_level(iif, priority, __FILE__, __LINE__, ## format); \
-} while(0)
-
-#define log_debug(format...) \
-do { \
- print_log(0, MSG_DEBUG, format); \
-} while(0)
-
-#define log_info(format...) \
-do { \
- print_log(0, MSG_INFO, format); \
-} while(0)
-
-#define log_notice(format...) \
-do { \
- print_log(0, MSG_NOTICE, format); \
-} while(0)
-
-#define log_warn(format...) \
-do { \
- print_log(0, MSG_WARN, format); \
-} while(0)
-
-#define log_err(format...) \
-do { \
- print_log(0, MSG_ERROR, format); \
-} while(0)
-
-#define log_crit(format...) \
-do { \
- print_log(0, MSG_CRITICAL, format); \
-} while(0)
-
-#define stack log_debug("<backtrace> - %s()\n", __func__)
-
-#define log_at_debug(format...) \
-do { \
- print_log(1, MSG_DEBUG, format); \
-} while(0)
-
-#define log_at_info(format...) \
-do { \
- print_log(1, MSG_INFO, format); \
-} while(0)
-
-#define log_at_notice(format...) \
-do { \
- print_log(1, MSG_NOTICE, format); \
-} while(0)
-
-#define log_at_warn(format...) \
-do { \
- print_log(1, MSG_WARN, format); \
-} while(0)
-
-#define log_at_err(format...) \
-do { \
- print_log(1, MSG_ERROR, format); \
-} while(0)
-
-#define log_at_crit(format...) \
-do { \
- print_log(1, MSG_CRITICAL, format); \
-} while(0)
-
-void increase_verbosity(void);
-void decrease_verbosity(void);
-void print_log_level(int iif, int priority, const char *file, int line, const char *format, ...);
-int query(struct options *opts, const char *format, ...);
-
-/* ------------------------------------------------------------------------- */
-/* formerly bio.h: */
-/* ------------------------------------------------------------------------- */
-/* buf_write flags */
-#define BW_WAIT 1
-
-
-#define BH_DATA(bh) ((char *)(bh)->b_data)
-#define BH_BLKNO(bh) ((uint64)(bh)->b_blocknr)
-#define BH_SIZE(bh) ((uint32)(bh)->b_size)
-#define BH_STATE(bh) ((uint32)(bh)->b_state)
-
-int get_buf(uint32_t sb_bsize, uint64 blkno, osi_buf_t **bhp);
-void relse_buf(osi_buf_t *bh);
-int read_buf(int disk_fd, osi_buf_t *bh, int flags);
-int write_buf(int disk_fd, osi_buf_t *bh, int flags);
-int get_and_read_buf(int disk_fd, uint32_t sb_bsize, uint64 blkno,
- osi_buf_t **bhp, int flags);
-
-/* ------------------------------------------------------------------------- */
-/* formerly fs_bits.h: */
-/* ------------------------------------------------------------------------- */
-#define BFITNOENT (0xFFFFFFFF)
-
-struct fs_bitmap
-{
- uint32 bi_offset; /* The offset in the buffer of the first byte */
- uint32 bi_start; /* The position of the first byte in this block */
- uint32 bi_len; /* The number of bytes in this block */
-};
-typedef struct fs_bitmap fs_bitmap_t;
-
-/* functions with blk #'s that are buffer relative */
-uint32_t fs_bitcount(unsigned char *buffer, unsigned int buflen,
- unsigned char state);
-uint32_t fs_bitfit(unsigned char *buffer, unsigned int buflen,
- uint32_t goal, unsigned char old_state);
-
-/* functions with blk #'s that are rgrp relative */
-uint32_t fs_blkalloc_internal(struct gfs_rgrpd *rgd, uint32_t goal,
- unsigned char old_state,
- unsigned char new_state, int do_it);
-
-/* functions with blk #'s that are file system relative */
-int fs_get_bitmap(int disk_fd, struct gfs_sbd *sdp, uint64_t blkno, struct gfs_rgrpd *rgd);
-int fs_set_bitmap(int disk_fd, struct gfs_sbd *sdp, uint64_t blkno, int state);
-
-/* ------------------------------------------------------------------------- */
-/* formerly fs_bmap.h */
-/* ------------------------------------------------------------------------- */
-int fs_unstuff_dinode(int disk_fd, struct gfs_inode *ip);
-int fs_block_map(int disk_fd, struct gfs_inode *ip, uint64 lblock, int *new,
- uint64 *dblock, uint32 *extlen);
-
-/* ------------------------------------------------------------------------- */
-/* formerly iddev.h */
-/* ------------------------------------------------------------------------- */
-int device_size(int fd, uint64_t *bytes);
-
-/* ------------------------------------------------------------------------- */
-/* formerly util.h: */
-/* ------------------------------------------------------------------------- */
-#define do_lseek(fd, off) \
- ((lseek((fd), (off), SEEK_SET) == (off)) ? 0 : -1)
-
-#define do_read(fd, buff, len) \
- ((read((fd), (buff), (len)) == (len)) ? 0 : -1)
-
-#define do_write(fd, buff, len) \
- ((write((fd), (buff), (len)) == (len)) ? 0 : -1)
-
-int compute_height(struct gfs_sbd *sdp, uint64 sz);
-int check_range(struct gfs_sbd *sdp, uint64 blkno);
-int set_meta(osi_buf_t *bh, int type, int format);
-int check_type(osi_buf_t *bh, int type);
-int check_meta(osi_buf_t *bh, int type);
-int next_rg_meta(struct gfs_rgrpd *rgd, uint64 *block, int first);
-int next_rg_meta_free(struct gfs_rgrpd *rgd, uint64 *block, int first, int *free);
-int next_rg_metatype(int disk_fd, struct gfs_rgrpd *rgd, uint64 *block, uint32 type, int first);
-struct di_info *search_list(osi_list_t *list, uint64 addr);
-
-/* ------------------------------------------------------------------------- */
-/* formerly rgrp.h: */
-/* ------------------------------------------------------------------------- */
-struct gfs_sbd;
-struct gfs_rgrpd;
-struct gfs_inode;
-
-int fs_compute_bitstructs(struct gfs_rgrpd *rgd);
-struct gfs_rgrpd *fs_blk2rgrpd(struct gfs_sbd *sdp, uint64_t blk);
-
-int fs_rgrp_read(int disk_fd, struct gfs_rgrpd *rgd, int repair_if_corrupted);
-void fs_rgrp_relse(struct gfs_rgrpd *rgd);
-int fs_rgrp_verify(struct gfs_rgrpd *rgd);
-int fs_rgrp_recount(int disk_fd, struct gfs_rgrpd *rgd);
-
-int clump_alloc(int disk_fd, struct gfs_rgrpd *rgd, uint32_t goal);
-int fs_blkalloc(int disk_fd, struct gfs_inode *ip, uint64_t *block);
-int fs_metaalloc(int disk_fd, struct gfs_inode *ip, uint64_t *block);
-
-/* ------------------------------------------------------------------------- */
-/* formerly file.h: */
-/* ------------------------------------------------------------------------- */
-int readi(int disk_fd, struct gfs_inode *ip, void *buf, uint64_t offset,
- unsigned int size);
-int writei(int disk_fd, struct gfs_inode *ip, void *buf, uint64_t offset,
- unsigned int size);
-
-/* ------------------------------------------------------------------------- */
-/* formerly inode.h: */
-/* ------------------------------------------------------------------------- */
-int copyin_inode(struct gfs_sbd *sbp, osi_buf_t *bh, struct gfs_inode **ip);
-int load_inode(int disk_fd, struct gfs_sbd *sbp, uint64_t block,
- struct gfs_inode **ip);
-void free_inode(struct gfs_inode **inode);
-int check_inode(struct gfs_inode *ip);
-int create_inode(int disk_fd, struct gfs_sbd *sbp, unsigned int type,
- struct gfs_inode **ip);
-int make_dinode(int disk_fd, struct gfs_inode *dip,
- struct gfs_sbd *sdp, struct gfs_inum *inum,
- unsigned int type, unsigned int mode, osi_cred_t *cred);
-
-/* ------------------------------------------------------------------------- */
-/* formerly fs_inode.h: */
-/* ------------------------------------------------------------------------- */
-int fs_copyin_dinode(int disk_fd, uint32_t sb_bsize, struct gfs_inode *ip, osi_buf_t *bh);
-int fs_copyout_dinode(int disk_fd, uint32_t sb_bsize, struct gfs_inode *ip);
-int fs_mkdir(int disk_fd, struct gfs_inode *dip, char *new_dir, int mode, struct gfs_inode **nip);
-
-static __inline__ int fs_is_stuffed(struct gfs_inode *ip)
-{
- return !ip->i_di.di_height;
-}
-
-static __inline__ int fs_is_jdata(struct gfs_inode *ip)
-{
- return ip->i_di.di_flags & GFS_DIF_JDATA;
-}
-
-/* ------------------------------------------------------------------------- */
-/* formerly fs_dir.h: */
-/* ------------------------------------------------------------------------- */
-#define ID_FILENAME 0
-#define ID_INUM 1
-typedef struct identifier_s {
- int type;
-
- osi_filename_t *filename;
- struct gfs_inum *inum;
-} identifier_t;
-
-int dirent_del(int disk_fd, struct gfs_inode *dip, osi_buf_t *bh,
- struct gfs_dirent *prev, struct gfs_dirent *cur);
-int gfs_inode_is_stuffed(struct gfs_inode *ip);
-int dirent_first(osi_buf_t *bh, struct gfs_dirent **dent);
-int dirent_next(osi_buf_t *bh, struct gfs_dirent **dent);
-int get_leaf_nr(int file_fd, struct gfs_inode *dip, uint32 index,
- uint64 *leaf_out);
-int fs_filecmp(osi_filename_t *file1, char *file2, int len_of_file2);
-int fs_dirent_del(int disk_fd, struct gfs_inode *dip, osi_buf_t *bh, osi_filename_t *filename);
-int fs_dir_add(int disk_fd, struct gfs_inode *dip, osi_filename_t *filename,
- struct gfs_inum *inum, unsigned int type);
-int fs_dirent_alloc(int disk_fd, struct gfs_inode *dip, osi_buf_t *bh,
- int name_len, struct gfs_dirent **dent_out);
-
-int fs_dir_search(int disk_fd, struct gfs_inode *dip, identifier_t *id, unsigned int *type);
-int get_first_leaf(int disk_fd, struct gfs_inode *dip, uint32 index,
- osi_buf_t **bh_out);
-int get_next_leaf(int disk_fd, struct gfs_inode *dip,osi_buf_t *bh_in,osi_buf_t **bh_out);
-int get_leaf(int disk_fd, struct gfs_inode *dip, uint64 leaf_no,
- osi_buf_t **bhp);
-
-/* ------------------------------------------------------------------------- */
-/* formerly super.h: */
-/* ------------------------------------------------------------------------- */
-int hexdump(uint64 startaddr, const unsigned char *lpBuffer, int len);
-int read_sb(int disk_fd, struct gfs_sbd *sdp);
-int ji_update(int disk_fd, struct gfs_sbd *sdp);
-int ri_update(int disk_fd, struct gfs_sbd *sdp);
-void ri_cleanup(osi_list_t *rglist);
-int write_sb(int disk_fd, struct gfs_sbd *sdp);
-int set_block_ranges(int disk_fd, struct gfs_sbd *sdp);
-int read_super_block(int disk_fd, struct gfs_sbd *sdp);
-int compute_constants(struct gfs_sbd *sdp);
-uint32 rgrplength2bitblocks(struct gfs_sbd *sdp, uint32 length);
-
-/* ------------------------------------------------------------------------- */
-/* formerly rgrp.h: */
-/* ------------------------------------------------------------------------- */
-
-#endif
diff --git a/gfs/libgfs/log.c b/gfs/libgfs/log.c
deleted file mode 100644
index c80e85e..0000000
--- a/gfs/libgfs/log.c
+++ /dev/null
@@ -1,139 +0,0 @@
-#include <stdio.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <libintl.h>
-
-#include <sys/select.h>
-#include <unistd.h>
-
-#include "incore.h"
-#include "libgfs.h"
-
-#define _(String) gettext(String)
-
-struct log_state {
- int print_level;
-};
-static struct log_state _state = {MSG_NOTICE};
-
-void increase_verbosity(void)
-{
- _state.print_level++;
-}
-
-void decrease_verbosity(void)
-{
- _state.print_level--;
-}
-
-static void __attribute__((format(printf, 4, 0)))
-print_msg(int priority, const char *file, int line, const char *format, va_list args) {
-
- switch (priority) {
-
- case MSG_DEBUG:
- printf("(%s:%d)\t", file, line);
- vprintf(format, args);
- break;
- case MSG_INFO:
- case MSG_NOTICE:
- case MSG_WARN:
- vprintf(format, args);
- break;
- case MSG_ERROR:
- case MSG_CRITICAL:
- default:
- vfprintf(stderr, format, args);
- break;
- }
- return;
-}
-
-void __attribute__((format(printf, 5, 6)))
-print_log_level(int iif, int priority, const char *file, int line, const char *format, ...)
-{
-
- va_list args;
- const char *transform;
-
- va_start(args, format);
-
- transform = _(format);
-
- if((_state.print_level == priority) ||
- (!iif && (_state.print_level >= priority)))
- print_msg(priority, file, line, transform, args);
-
- va_end(args);
-}
-
-int __attribute__((format(printf, 2, 3)))
-query(struct options *opts, const char *format, ...)
-{
-
- va_list args;
- const char *transform;
- char response;
- fd_set rfds;
- struct timeval tv;
- int err = 0;
- int ret = 0;
-
- va_start(args, format);
-
- transform = _(format);
-
- if(opts->yes)
- return 1;
- if(opts->no)
- return 0;
-
- /* Watch stdin (fd 0) to see when it has input. */
- FD_ZERO(&rfds);
- FD_SET(STDIN_FILENO, &rfds);
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- /* Make sure there isn't extraneous input before asking the
- * user the question */
- while((err = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv))) {
- if(err < 0) {
- log_debug("Error in select() on stdin\n");
- break;
- }
- err = read(STDIN_FILENO, &response, sizeof(char));
-
- }
- query:
- vprintf(transform, args);
-
- /* Make sure query is printed out */
- fflush(NULL);
-
- rescan:
- err = read(STDIN_FILENO, &response, sizeof(char));
-
- if(tolower(response) == 'y') {
- ret = 1;
- } else if (tolower(response) == 'n') {
- ret = 0;
- } else if ((response == ' ') || (response == '\t')) {
- goto rescan;
- } else {
- while(response != '\n')
- err = read(STDIN_FILENO, &response, sizeof(char));
- printf("Bad response, please type 'y' or 'n'.\n");
- goto query;
- }
-
- /* Clip the input */
- while((err = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv))) {
- if(err < 0) {
- log_debug("Error in select() on stdin\n");
- break;
- }
- err = read(STDIN_FILENO, &response, sizeof(char));
- }
-
- return ret;
-}
diff --git a/gfs/libgfs/ondisk.c b/gfs/libgfs/ondisk.c
deleted file mode 100644
index 15ce0b5..0000000
--- a/gfs/libgfs/ondisk.c
+++ /dev/null
@@ -1,1282 +0,0 @@
-#ifndef HELPER_PROGRAM
-
-#include "libgfs.h"
-
-#define pv(struct, member, fmt) printk(" "#member" = "fmt"\n", struct->member);
-
-#else
-
-#include <stdio.h>
-#include <string.h>
-
-#include "global.h"
-#include "linux_endian.h"
-#include "gfs_ondisk.h" /* pull in kernel structures / routines */
-
-#define printk printf
-#define pv(struct, member, fmt) printf(" "#member" = "fmt"\n", struct->member);
-
-#endif /* !HELPER_PROGRAM */
-
-#define CPIN_08(s1, s2, member, count) {memcpy((s1->member), (s2->member), (count));}
-#define CPOUT_08(s1, s2, member, count) {memcpy((s2->member), (s1->member), (count));}
-#define CPIN_16(s1, s2, member) {(s1->member) = gfs16_to_cpu((s2->member));}
-#define CPOUT_16(s1, s2, member) {(s2->member) = cpu_to_gfs16((s1->member));}
-#define CPIN_32(s1, s2, member) {(s1->member) = gfs32_to_cpu((s2->member));}
-#define CPOUT_32(s1, s2, member) {(s2->member) = cpu_to_gfs32((s1->member));}
-#define CPIN_64(s1, s2, member) {(s1->member) = gfs64_to_cpu((s2->member));}
-#define CPOUT_64(s1, s2, member) {(s2->member) = cpu_to_gfs64((s1->member));}
-
-#define pa(struct, member, count) print_array(#member, struct->member, count);
-
-/**
- * print_array - Print out an array of bytes
- * @title: what to print before the array
- * @buf: the array
- * @count: the number of bytes
- */
-
-static void
-print_array(const char *title, char *buf, int count)
-{
- int x;
-
- printk(" %s =\n", title);
- for (x = 0; x < count; x++) {
- printk("%.2X ", (unsigned char) buf[x]);
- if (x % 16 == 15)
- printk("\n");
- }
- if (x % 16)
- printk("\n");
-
-}
-
-/**
- * gfs_inum_in - Read in an inode number
- * @no: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_inum_in(struct gfs_inum *no, char *buf)
-{
- struct gfs_inum *str = (struct gfs_inum *) buf;
-
- CPIN_64(no, str, no_formal_ino);
- CPIN_64(no, str, no_addr);
-
-}
-
-/**
- * gfs_inum_out - Write out an inode number
- * @no: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_inum_out(struct gfs_inum *no, char *buf)
-{
- struct gfs_inum *str = (struct gfs_inum *) buf;
-
- CPOUT_64(no, str, no_formal_ino);
- CPOUT_64(no, str, no_addr);
-
-}
-
-/**
- * gfs_inum_print - Print out a inode number
- * @no: the cpu-order buffer
- *
- */
-
-void
-gfs_inum_print(struct gfs_inum *no)
-{
-
- pv(no, no_formal_ino, "%" PRIu64);
- pv(no, no_addr, "%" PRIu64);
-
-}
-
-/**
- * gfs_meta_header_in - Read in a metadata header
- * @mh: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_meta_header_in(struct gfs_meta_header *mh, char *buf)
-{
- struct gfs_meta_header *str = (struct gfs_meta_header *) buf;
-
- CPIN_32(mh, str, mh_magic);
- CPIN_32(mh, str, mh_type);
- CPIN_64(mh, str, mh_generation);
- CPIN_32(mh, str, mh_format);
- CPIN_32(mh, str, mh_incarn);
-
-}
-
-/**
- * gfs_meta_header_in - Write out a metadata header
- * @mh: the cpu-order structure
- * @buf: the disk-order buffer
- *
- * Don't ever change the generation number in this routine.
- * It's done manually in increment_generation().
- */
-
-void
-gfs_meta_header_out(struct gfs_meta_header *mh, char *buf)
-{
- struct gfs_meta_header *str = (struct gfs_meta_header *) buf;
-
- CPOUT_32(mh, str, mh_magic);
- CPOUT_32(mh, str, mh_type);
- /*CPOUT_64(mh, str, mh_generation); */
- CPOUT_32(mh, str, mh_format);
- CPOUT_32(mh, str, mh_incarn);
-
-}
-
-/**
- * gfs_meta_header_print - Print out a metadata header
- * @mh: the cpu-order buffer
- *
- */
-
-void
-gfs_meta_header_print(struct gfs_meta_header *mh)
-{
-
- pv(mh, mh_magic, "0x%.8X");
- pv(mh, mh_type, "%u");
- pv(mh, mh_generation, "%" PRIu64);
- pv(mh, mh_format, "%u");
- pv(mh, mh_incarn, "%u");
-
-}
-
-/**
- * gfs_sb_in - Read in a superblock
- * @sb: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_sb_in(struct gfs_sb *sb, char *buf)
-{
- struct gfs_sb *str = (struct gfs_sb *) buf;
-
- gfs_meta_header_in(&sb->sb_header, buf);
-
- CPIN_32(sb, str, sb_fs_format);
- CPIN_32(sb, str, sb_multihost_format);
- CPIN_32(sb, str, sb_flags);
-
- CPIN_32(sb, str, sb_bsize);
- CPIN_32(sb, str, sb_bsize_shift);
- CPIN_32(sb, str, sb_seg_size);
-
- gfs_inum_in(&sb->sb_jindex_di, (char *) &str->sb_jindex_di);
- gfs_inum_in(&sb->sb_rindex_di, (char *) &str->sb_rindex_di);
- gfs_inum_in(&sb->sb_root_di, (char *) &str->sb_root_di);
-
- CPIN_08(sb, str, sb_lockproto, GFS_LOCKNAME_LEN);
- CPIN_08(sb, str, sb_locktable, GFS_LOCKNAME_LEN);
-
- gfs_inum_in(&sb->sb_quota_di, (char *) &str->sb_quota_di);
- gfs_inum_in(&sb->sb_license_di, (char *) &str->sb_license_di);
-
- CPIN_08(sb, str, sb_reserved, 96);
-
-}
-
-/**
- * gfs_sb_out - Write out a superblock
- * @sb: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_sb_out(struct gfs_sb *sb, char *buf)
-{
- struct gfs_sb *str = (struct gfs_sb *) buf;
-
- gfs_meta_header_out(&sb->sb_header, buf);
-
- CPOUT_32(sb, str, sb_fs_format);
- CPOUT_32(sb, str, sb_multihost_format);
- CPOUT_32(sb, str, sb_flags);
-
- CPOUT_32(sb, str, sb_bsize);
- CPOUT_32(sb, str, sb_bsize_shift);
- CPOUT_32(sb, str, sb_seg_size);
-
- gfs_inum_out(&sb->sb_jindex_di, (char *) &str->sb_jindex_di);
- gfs_inum_out(&sb->sb_rindex_di, (char *) &str->sb_rindex_di);
- gfs_inum_out(&sb->sb_root_di, (char *) &str->sb_root_di);
-
- CPOUT_08(sb, str, sb_lockproto, GFS_LOCKNAME_LEN);
- CPOUT_08(sb, str, sb_locktable, GFS_LOCKNAME_LEN);
-
- gfs_inum_out(&sb->sb_quota_di, (char *) &str->sb_quota_di);
- gfs_inum_out(&sb->sb_license_di, (char *) &str->sb_license_di);
-
- CPOUT_08(sb, str, sb_reserved, 96);
-
-}
-
-/**
- * gfs_sb_print - Print out a superblock
- * @sb: the cpu-order buffer
- *
- */
-
-void
-gfs_sb_print(struct gfs_sb *sb)
-{
- gfs_meta_header_print(&sb->sb_header);
-
- pv(sb, sb_fs_format, "%u");
- pv(sb, sb_multihost_format, "%u");
- pv(sb, sb_flags, "%u");
-
- pv(sb, sb_bsize, "%u");
- pv(sb, sb_bsize_shift, "%u");
- pv(sb, sb_seg_size, "%u");
-
- gfs_inum_print(&sb->sb_jindex_di);
- gfs_inum_print(&sb->sb_rindex_di);
- gfs_inum_print(&sb->sb_root_di);
-
- pv(sb, sb_lockproto, "%s");
- pv(sb, sb_locktable, "%s");
-
- gfs_inum_print(&sb->sb_quota_di);
- gfs_inum_print(&sb->sb_license_di);
-
- pa(sb, sb_reserved, 96);
-
-}
-
-/**
- * gfs_jindex_in - Read in a journal index structure
- * @jindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_jindex_in(struct gfs_jindex *jindex, char *buf)
-{
- struct gfs_jindex *str = (struct gfs_jindex *) buf;
-
- CPIN_64(jindex, str, ji_addr);
- CPIN_32(jindex, str, ji_nsegment);
- CPIN_32(jindex, str, ji_pad);
-
- CPIN_08(jindex, str, ji_reserved, 64);
-
-}
-
-/**
- * gfs_jindex_out - Write out a journal index structure
- * @jindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_jindex_out(struct gfs_jindex *jindex, char *buf)
-{
- struct gfs_jindex *str = (struct gfs_jindex *) buf;
-
- CPOUT_64(jindex, str, ji_addr);
- CPOUT_32(jindex, str, ji_nsegment);
- CPOUT_32(jindex, str, ji_pad);
-
- CPOUT_08(jindex, str, ji_reserved, 64);
-
-}
-
-/**
- * gfs_jindex_print - Print out a journal index structure
- * @ji: the cpu-order buffer
- *
- */
-
-void
-gfs_jindex_print(struct gfs_jindex *ji)
-{
-
- pv(ji, ji_addr, "%" PRIu64);
- pv(ji, ji_nsegment, "%u");
- pv(ji, ji_pad, "%u");
-
- pa(ji, ji_reserved, 64);
-
-}
-
-/**
- * gfs_rindex_in - Read in a resource index structure
- * @rindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rindex_in(struct gfs_rindex *grindex, char *buf)
-{
- struct gfs_rindex *str = (struct gfs_rindex *) buf;
-
- CPIN_64(grindex, str, ri_addr);
- CPIN_32(grindex, str, ri_length);
- CPIN_32(grindex, str, ri_pad);
-
- CPIN_64(grindex, str, ri_data1);
- CPIN_32(grindex, str, ri_data);
-
- CPIN_32(grindex, str, ri_bitbytes);
-
- CPIN_08(grindex, str, ri_reserved, 64);
-
-}
-
-/**
- * gfs_rindex_out - Write out a resource index structure
- * @rindex: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rindex_out(struct gfs_rindex *grindex, char *buf)
-{
- struct gfs_rindex *str = (struct gfs_rindex *) buf;
-
- CPOUT_64(grindex, str, ri_addr);
- CPOUT_32(grindex, str, ri_length);
- CPOUT_32(grindex, str, ri_pad);
-
- CPOUT_64(grindex, str, ri_data1);
- CPOUT_32(grindex, str, ri_data);
-
- CPOUT_32(grindex, str, ri_bitbytes);
-
- CPOUT_08(grindex, str, ri_reserved, 64);
-
-}
-
-/**
- * gfs_rindex_print - Print out a resource index structure
- * @ri: the cpu-order buffer
- *
- */
-
-void
-gfs_rindex_print(struct gfs_rindex *ri)
-{
-
- pv(ri, ri_addr, "%" PRIu64);
- pv(ri, ri_length, "%u");
- pv(ri, ri_pad, "%u");
-
- pv(ri, ri_data1, "%" PRIu64);
- pv(ri, ri_data, "%u");
-
- pv(ri, ri_bitbytes, "%u");
-
- pa(ri, ri_reserved, 64);
-
-}
-
-/**
- * gfs_rgrp_in - Read in a resource group header
- * @rgrp: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rgrp_in(struct gfs_rgrp *rgrp, char *buf)
-{
- struct gfs_rgrp *str = (struct gfs_rgrp *) buf;
-
- gfs_meta_header_in(&rgrp->rg_header, buf);
-
- CPIN_32(rgrp, str, rg_flags);
-
- CPIN_32(rgrp, str, rg_free);
-
- CPIN_32(rgrp, str, rg_useddi);
- CPIN_32(rgrp, str, rg_freedi);
- gfs_inum_in(&rgrp->rg_freedi_list, (char *) &str->rg_freedi_list);
-
- CPIN_32(rgrp, str, rg_usedmeta);
- CPIN_32(rgrp, str, rg_freemeta);
-
- CPIN_08(rgrp, str, rg_reserved, 64);
-
-}
-
-/**
- * gfs_rgrp_out - Write out a resource group header
- * @rgrp: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_rgrp_out(struct gfs_rgrp *rgrp, char *buf)
-{
- struct gfs_rgrp *str = (struct gfs_rgrp *) buf;
-
- gfs_meta_header_out(&rgrp->rg_header, buf);
-
- CPOUT_32(rgrp, str, rg_flags);
-
- CPOUT_32(rgrp, str, rg_free);
-
- CPOUT_32(rgrp, str, rg_useddi);
- CPOUT_32(rgrp, str, rg_freedi);
- gfs_inum_out(&rgrp->rg_freedi_list, (char *) &str->rg_freedi_list);
-
- CPOUT_32(rgrp, str, rg_usedmeta);
- CPOUT_32(rgrp, str, rg_freemeta);
-
- CPOUT_08(rgrp, str, rg_reserved, 64);
-
-}
-
-/**
- * gfs_rgrp_print - Print out a resource group header
- * @rg: the cpu-order buffer
- */
-
-void
-gfs_rgrp_print(struct gfs_rgrp *rg)
-{
-
- gfs_meta_header_print(&rg->rg_header);
-
- pv(rg, rg_flags, "%u");
-
- pv(rg, rg_free, "%u");
-
- pv(rg, rg_useddi, "%u");
- pv(rg, rg_freedi, "%u");
- gfs_inum_print(&rg->rg_freedi_list);
-
- pv(rg, rg_usedmeta, "%u");
- pv(rg, rg_freemeta, "%u");
-
- pa(rg, rg_reserved, 64);
-
-}
-
-/**
- * gfs_quota_in - Read in a quota structures
- * @quota: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_in(struct gfs_quota *quota, char *buf)
-{
- struct gfs_quota *str = (struct gfs_quota *) buf;
-
- CPIN_64(quota, str, qu_limit);
- CPIN_64(quota, str, qu_warn);
- CPIN_64(quota, str, qu_value);
-
- CPIN_08(quota, str, qu_reserved, 64);
-
-}
-
-/**
- * gfs_quota_out - Write out a quota structure
- * @quota: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_out(struct gfs_quota *quota, char *buf)
-{
- struct gfs_quota *str = (struct gfs_quota *) buf;
-
- CPOUT_64(quota, str, qu_limit);
- CPOUT_64(quota, str, qu_warn);
- CPOUT_64(quota, str, qu_value);
-
- CPOUT_08(quota, str, qu_reserved, 64);
-
-}
-
-/**
- * gfs_quota_print - Print out a quota structure
- * @quota: the cpu-order buffer
- */
-
-void
-gfs_quota_print(struct gfs_quota *quota)
-{
-
- pv(quota, qu_limit, "%" PRIu64);
- pv(quota, qu_warn, "%" PRIu64);
- pv(quota, qu_value, "%" PRId64);
-
- pa(quota, qu_reserved, 64);
-
-}
-
-/**
- * gfs_dinode_in - Read in a dinode
- * @dinode: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dinode_in(struct gfs_dinode *dinode, char *buf)
-{
- struct gfs_dinode *str = (struct gfs_dinode *) buf;
-
- gfs_meta_header_in(&dinode->di_header, buf);
-
- gfs_inum_in(&dinode->di_num, (char *) &str->di_num);
-
- CPIN_32(dinode, str, di_mode);
- CPIN_32(dinode, str, di_uid);
- CPIN_32(dinode, str, di_gid);
- CPIN_32(dinode, str, di_nlink);
- CPIN_64(dinode, str, di_size);
- CPIN_64(dinode, str, di_blocks);
- CPIN_64(dinode, str, di_atime);
- CPIN_64(dinode, str, di_mtime);
- CPIN_64(dinode, str, di_ctime);
- CPIN_32(dinode, str, di_major);
- CPIN_32(dinode, str, di_minor);
-
- CPIN_64(dinode, str, di_rgrp);
- CPIN_64(dinode, str, di_goal_rgrp);
- CPIN_32(dinode, str, di_goal_dblk);
- CPIN_32(dinode, str, di_goal_mblk);
- CPIN_32(dinode, str, di_flags);
- CPIN_32(dinode, str, di_payload_format);
- CPIN_16(dinode, str, di_type);
- CPIN_16(dinode, str, di_height);
- CPIN_32(dinode, str, di_incarn);
- CPIN_16(dinode, str, di_pad);
-
- CPIN_16(dinode, str, di_depth);
- CPIN_32(dinode, str, di_entries);
-
- gfs_inum_in(&dinode->di_next_unused, (char *) &str->di_next_unused);
-
- CPIN_64(dinode, str, di_eattr);
-
- CPIN_08(dinode, str, di_reserved, 56);
-
-}
-
-/**
- * gfs_dinode_out - Write out a dinode
- * @dinode: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dinode_out(struct gfs_dinode *dinode, char *buf)
-{
- struct gfs_dinode *str = (struct gfs_dinode *) buf;
-
- gfs_meta_header_out(&dinode->di_header, buf);
-
- gfs_inum_out(&dinode->di_num, (char *) &str->di_num);
-
- CPOUT_32(dinode, str, di_mode);
- CPOUT_32(dinode, str, di_uid);
- CPOUT_32(dinode, str, di_gid);
- CPOUT_32(dinode, str, di_nlink);
- CPOUT_64(dinode, str, di_size);
- CPOUT_64(dinode, str, di_blocks);
- CPOUT_64(dinode, str, di_atime);
- CPOUT_64(dinode, str, di_mtime);
- CPOUT_64(dinode, str, di_ctime);
- CPOUT_32(dinode, str, di_major);
- CPOUT_32(dinode, str, di_minor);
-
- CPOUT_64(dinode, str, di_rgrp);
- CPOUT_64(dinode, str, di_goal_rgrp);
- CPOUT_32(dinode, str, di_goal_dblk);
- CPOUT_32(dinode, str, di_goal_mblk);
- CPOUT_32(dinode, str, di_flags);
- CPOUT_32(dinode, str, di_payload_format);
- CPOUT_16(dinode, str, di_type);
- CPOUT_16(dinode, str, di_height);
- CPOUT_32(dinode, str, di_incarn);
- CPOUT_16(dinode, str, di_pad);
-
- CPOUT_16(dinode, str, di_depth);
- CPOUT_32(dinode, str, di_entries);
-
- gfs_inum_out(&dinode->di_next_unused, (char *) &str->di_next_unused);
-
- CPOUT_64(dinode, str, di_eattr);
-
- CPOUT_08(dinode, str, di_reserved, 56);
-
-}
-
-/**
- * gfs_dinode_print - Print out a dinode
- * @di: the cpu-order buffer
- */
-
-void
-gfs_dinode_print(struct gfs_dinode *di)
-{
-
- gfs_meta_header_print(&di->di_header);
-
- gfs_inum_print(&di->di_num);
-
- pv(di, di_mode, "0%o");
- pv(di, di_uid, "%u");
- pv(di, di_gid, "%u");
- pv(di, di_nlink, "%u");
- pv(di, di_size, "%" PRIu64);
- pv(di, di_blocks, "%" PRIu64);
- pv(di, di_atime, "%" PRId64);
- pv(di, di_mtime, "%" PRId64);
- pv(di, di_ctime, "%" PRId64);
- pv(di, di_major, "%u");
- pv(di, di_minor, "%u");
-
- pv(di, di_rgrp, "%" PRIu64);
- pv(di, di_goal_rgrp, "%" PRIu64);
- pv(di, di_goal_dblk, "%u");
- pv(di, di_goal_mblk, "%u");
- pv(di, di_flags, "0x%.8X");
- pv(di, di_payload_format, "%u");
- pv(di, di_type, "%u");
- pv(di, di_height, "%u");
- pv(di, di_incarn, "%u");
- pv(di, di_pad, "%u");
-
- pv(di, di_depth, "%u");
- pv(di, di_entries, "%u");
-
- gfs_inum_print(&di->di_next_unused);
-
- pv(di, di_eattr, "%" PRIu64);
-
- pa(di, di_reserved, 56);
-
-}
-
-/**
- * gfs_indirect_in - copy in the header of an indirect block
- * @indirect: the in memory copy
- * @buf: the buffer copy
- *
- */
-
-void
-gfs_indirect_in(struct gfs_indirect *indirect, char *buf)
-{
- struct gfs_indirect *str = (struct gfs_indirect *) buf;
-
- gfs_meta_header_in(&indirect->in_header, buf);
-
- CPIN_08(indirect, str, in_reserved, 64);
-
-}
-
-/**
- * gfs_indirect_out - copy out the header of an indirect block
- * @indirect: the in memory copy
- * @buf: the buffer copy
- *
- */
-
-void
-gfs_indirect_out(struct gfs_indirect *indirect, char *buf)
-{
- struct gfs_indirect *str = (struct gfs_indirect *) buf;
-
- gfs_meta_header_out(&indirect->in_header, buf);
-
- CPOUT_08(indirect, str, in_reserved, 64);
-
-}
-
-/**
- * gfs_indirect_print - Print out a indirect block header
- * @indirect: the cpu-order buffer
- */
-
-void
-gfs_indirect_print(struct gfs_indirect *indirect)
-{
-
- gfs_meta_header_print(&indirect->in_header);
-
- pa(indirect, in_reserved, 64);
-
-}
-
-/**
- * gfs_dirent_in - Read in a directory entry
- * @dirent: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dirent_in(struct gfs_dirent *dirent, char *buf)
-{
- struct gfs_dirent *str = (struct gfs_dirent *) buf;
-
- gfs_inum_in(&dirent->de_inum, (char *) &str->de_inum);
- CPIN_32(dirent, str, de_hash);
- CPIN_16(dirent, str, de_rec_len);
- CPIN_16(dirent, str, de_name_len);
- CPIN_16(dirent, str, de_type);
-
- CPIN_08(dirent, str, de_reserved, 14);
-
-}
-
-/**
- * gfs_dirent_out - Write out a directory entry
- * @dirent: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_dirent_out(struct gfs_dirent *dirent, char *buf)
-{
- struct gfs_dirent *str = (struct gfs_dirent *) buf;
-
- gfs_inum_out(&dirent->de_inum, (char *) &str->de_inum);
- CPOUT_32(dirent, str, de_hash);
- CPOUT_16(dirent, str, de_rec_len);
- CPOUT_16(dirent, str, de_name_len);
- CPOUT_16(dirent, str, de_type);
-
- CPOUT_08(dirent, str, de_reserved, 14);
-
-}
-
-/**
- * gfs_dirent_print - Print out a directory entry
- * @de: the cpu-order buffer
- * @name: the filename
- */
-
-void
-gfs_dirent_print(struct gfs_dirent *de, const char *name)
-{
- char buf[GFS_FNAMESIZE + 1];
-
- gfs_inum_print(&de->de_inum);
- pv(de, de_hash, "0x%.8X");
- pv(de, de_rec_len, "%u");
- pv(de, de_name_len, "%u");
- pv(de, de_type, "%u");
-
- pa(de, de_reserved, 14);
-
- memset(buf, 0, GFS_FNAMESIZE + 1);
- memcpy(buf, name, de->de_name_len);
- printk(" name = %s\n", buf);
-
-}
-
-/**
- * gfs_leaf_in - Read in a directory leaf header
- * @leaf: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_leaf_in(struct gfs_leaf *leaf, char *buf)
-{
- struct gfs_leaf *str = (struct gfs_leaf *) buf;
-
- gfs_meta_header_in(&leaf->lf_header, buf);
-
- CPIN_16(leaf, str, lf_depth);
- CPIN_16(leaf, str, lf_entries);
- CPIN_32(leaf, str, lf_dirent_format);
- CPIN_64(leaf, str, lf_next);
-
- CPIN_08(leaf, str, lf_reserved, 64);
-
-}
-
-/**
- * gfs_leaf_out - Write out a directory leaf header
- * @leaf: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_leaf_out(struct gfs_leaf *leaf, char *buf)
-{
- struct gfs_leaf *str = (struct gfs_leaf *) buf;
-
- gfs_meta_header_out(&leaf->lf_header, buf);
-
- CPOUT_16(leaf, str, lf_depth);
- CPOUT_16(leaf, str, lf_entries);
- CPOUT_32(leaf, str, lf_dirent_format);
- CPOUT_64(leaf, str, lf_next);
-
- CPOUT_08(leaf, str, lf_reserved, 64);
-
-}
-
-/**
- * gfs_leaf_print - Print out a directory leaf header
- * @lf: the cpu-order buffer
- */
-
-void
-gfs_leaf_print(struct gfs_leaf *lf)
-{
-
- gfs_meta_header_print(&lf->lf_header);
-
- pv(lf, lf_depth, "%u");
- pv(lf, lf_entries, "%u");
- pv(lf, lf_dirent_format, "%u");
- pv(lf, lf_next, "%" PRIu64);
-
- pa(lf, lf_reserved, 64);
-
-}
-
-/**
- * gfs_log_header_in - Read in a log header
- * @head: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_log_header_in(struct gfs_log_header *head, char *buf)
-{
- struct gfs_log_header *str = (struct gfs_log_header *) buf;
-
- gfs_meta_header_in(&head->lh_header, buf);
-
- CPIN_32(head, str, lh_flags);
- CPIN_32(head, str, lh_pad);
-
- CPIN_64(head, str, lh_first);
- CPIN_64(head, str, lh_sequence);
-
- CPIN_64(head, str, lh_tail);
- CPIN_64(head, str, lh_last_dump);
-
- CPIN_08(head, str, lh_reserved, 64);
-
-}
-
-/**
- * gfs_log_header_out - Write out a log header
- * @head: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_log_header_out(struct gfs_log_header *head, char *buf)
-{
- struct gfs_log_header *str = (struct gfs_log_header *) buf;
-
- gfs_meta_header_out(&head->lh_header, buf);
-
- CPOUT_32(head, str, lh_flags);
- CPOUT_32(head, str, lh_pad);
-
- CPOUT_64(head, str, lh_first);
- CPOUT_64(head, str, lh_sequence);
-
- CPOUT_64(head, str, lh_tail);
- CPOUT_64(head, str, lh_last_dump);
-
- CPOUT_08(head, str, lh_reserved, 64);
-
-}
-
-/**
- * gfs_log_header_print - Print out a log header
- * @head: the cpu-order buffer
- */
-
-void
-gfs_log_header_print(struct gfs_log_header *lh)
-{
-
- gfs_meta_header_print(&lh->lh_header);
-
- pv(lh, lh_flags, "0x%.8X");
- pv(lh, lh_pad, "%u");
-
- pv(lh, lh_first, "%" PRIu64);
- pv(lh, lh_sequence, "%" PRIu64);
-
- pv(lh, lh_tail, "%" PRIu64);
- pv(lh, lh_last_dump, "%" PRIu64);
-
- pa(lh, lh_reserved, 64);
-
-}
-
-/**
- * gfs_desc_in - Read in a log descriptor
- * @desc: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_desc_in(struct gfs_log_descriptor *desc, char *buf)
-{
- struct gfs_log_descriptor *str = (struct gfs_log_descriptor *) buf;
-
- gfs_meta_header_in(&desc->ld_header, buf);
-
- CPIN_32(desc, str, ld_type);
- CPIN_32(desc, str, ld_length);
- CPIN_32(desc, str, ld_data1);
- CPIN_32(desc, str, ld_data2);
-
- CPIN_08(desc, str, ld_reserved, 64);
-
-}
-
-/**
- * gfs_desc_out - Write out a log descriptor
- * @desc: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_desc_out(struct gfs_log_descriptor *desc, char *buf)
-{
- struct gfs_log_descriptor *str = (struct gfs_log_descriptor *) buf;
-
- gfs_meta_header_out(&desc->ld_header, buf);
-
- CPOUT_32(desc, str, ld_type);
- CPOUT_32(desc, str, ld_length);
- CPOUT_32(desc, str, ld_data1);
- CPOUT_32(desc, str, ld_data2);
-
- CPOUT_08(desc, str, ld_reserved, 64);
-
-}
-
-/**
- * gfs_desc_print - Print out a log descriptor
- * @ld: the cpu-order buffer
- */
-
-void
-gfs_desc_print(struct gfs_log_descriptor *ld)
-{
-
- gfs_meta_header_print(&ld->ld_header);
-
- pv(ld, ld_type, "%u");
- pv(ld, ld_length, "%u");
- pv(ld, ld_data1, "%u");
- pv(ld, ld_data2, "%u");
-
- pa(ld, ld_reserved, 64);
-
-}
-
-/**
- * gfs_block_tag_in - Read in a block tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_block_tag_in(struct gfs_block_tag *tag, char *buf)
-{
- struct gfs_block_tag *str = (struct gfs_block_tag *) buf;
-
- CPIN_64(tag, str, bt_blkno);
- CPIN_32(tag, str, bt_flags);
- CPIN_32(tag, str, bt_pad);
-
-}
-
-/**
- * gfs_block_tag_out - Write out a block tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_block_tag_out(struct gfs_block_tag *tag, char *buf)
-{
- struct gfs_block_tag *str = (struct gfs_block_tag *) buf;
-
- CPOUT_64(tag, str, bt_blkno);
- CPOUT_32(tag, str, bt_flags);
- CPOUT_32(tag, str, bt_pad);
-
-}
-
-/**
- * gfs_block_tag_print - Print out a block tag
- * @tag: the cpu-order buffer
- */
-
-void
-gfs_block_tag_print(struct gfs_block_tag *tag)
-{
-
- pv(tag, bt_blkno, "%" PRIu64);
- pv(tag, bt_flags, "%u");
- pv(tag, bt_pad, "%u");
-
-}
-
-/**
- * gfs_quota_tag_in - Read in a quota tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_tag_in(struct gfs_quota_tag *tag, char *buf)
-{
- struct gfs_quota_tag *str = (struct gfs_quota_tag *) buf;
-
- CPIN_64(tag, str, qt_change);
- CPIN_32(tag, str, qt_flags);
- CPIN_32(tag, str, qt_id);
-
-}
-
-/**
- * gfs_quota_tag_out - Write out a quota tag
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_quota_tag_out(struct gfs_quota_tag *tag, char *buf)
-{
- struct gfs_quota_tag *str = (struct gfs_quota_tag *) buf;
-
- CPOUT_64(tag, str, qt_change);
- CPOUT_32(tag, str, qt_flags);
- CPOUT_32(tag, str, qt_id);
-
-}
-
-/**
- * gfs_quota_tag_print - Print out a quota tag
- * @tag: the cpu-order buffer
- */
-
-void
-gfs_quota_tag_print(struct gfs_quota_tag *tag)
-{
-
- pv(tag, qt_change, "%" PRId64);
- pv(tag, qt_flags, "0x%.8X");
- pv(tag, qt_id, "%u");
-
-}
-
-/**
- * gfs_ea_header_in - Read in a Extended Attribute header
- * @tag: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_ea_header_in(struct gfs_ea_header *ea, char *buf)
-{
- struct gfs_ea_header *str = (struct gfs_ea_header *) buf;
-
- CPIN_32(ea, str, ea_rec_len);
- CPIN_32(ea, str, ea_data_len);
- ea->ea_name_len = str->ea_name_len;
- ea->ea_type = str->ea_type;
- ea->ea_flags = str->ea_flags;
- ea->ea_num_ptrs = str->ea_num_ptrs;
- CPIN_32(ea, str, ea_pad);
-
-}
-
-/**
- * gfs_ea_header_out - Write out a Extended Attribute header
- * @ea: the cpu-order structure
- * @buf: the disk-order buffer
- *
- */
-
-void
-gfs_ea_header_out(struct gfs_ea_header *ea, char *buf)
-{
- struct gfs_ea_header *str = (struct gfs_ea_header *) buf;
-
- CPOUT_32(ea, str, ea_rec_len);
- CPOUT_32(ea, str, ea_data_len);
- str->ea_name_len = ea->ea_name_len;
- str->ea_type = ea->ea_type;
- str->ea_flags = ea->ea_flags;
- str->ea_num_ptrs = ea->ea_num_ptrs;
- CPOUT_32(ea, str, ea_pad);
-
-}
-
-/**
- * gfs_ea_header_printt - Print out a Extended Attribute header
- * @ea: the cpu-order buffer
- */
-
-void
-gfs_ea_header_print(struct gfs_ea_header *ea, char *name)
-{
- char buf[GFS_EA_MAX_NAME_LEN + 1];
-
- pv(ea, ea_rec_len, "%u");
- pv(ea, ea_data_len, "%u");
- pv(ea, ea_name_len, "%u");
- pv(ea, ea_type, "%u");
- pv(ea, ea_flags, "%u");
- pv(ea, ea_num_ptrs, "%u");
- pv(ea, ea_pad, "%u");
-
- memset(buf, 0, GFS_EA_MAX_NAME_LEN + 1);
- memcpy(buf, name, ea->ea_name_len);
- printf(" name = %s\n", buf);
-}
-
-static const uint32_t crc_32_tab[] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,
- 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb,
- 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447,
- 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75,
- 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11,
- 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
- 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b,
- 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49,
- 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
- 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3,
- 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af,
- 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d,
- 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9,
- 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767,
- 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703,
- 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
- 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d,
- 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b,
- 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
- 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5,
- 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1,
- 0x5a05df1b, 0x2d02ef8d
-};
-
-/**
- * gfs_dir_hash - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * The hash function is a 32-bit CRC of the data. The algorithm uses
- * the crc_32_tab table above.
- *
- * This may not be the fastest hash function, but it does a fair bit better
- * at providing uniform results than the others I've looked at. That's
- * really important for efficient directories.
- *
- * Returns: the hash
- */
-
-uint32_t
-gfs_dir_hash(const char *data, int len)
-{
- uint32_t hash = 0xFFFFFFFF;
-
- for (; len--; data++)
- hash = crc_32_tab[(hash ^ *data) & 0xFF] ^ (hash >> 8);
-
- hash = ~hash;
-
- return hash;
-}
diff --git a/gfs/libgfs/rgrp.c b/gfs/libgfs/rgrp.c
deleted file mode 100644
index 6407b80..0000000
--- a/gfs/libgfs/rgrp.c
+++ /dev/null
@@ -1,593 +0,0 @@
-#include <stdint.h>
-#include "gfs_ondisk.h"
-#include "incore.h"
-#include "libgfs.h"
-
-/**
- * fs_compute_bitstructs - Compute the bitmap sizes
- * @rgd: The resource group descriptor
- *
- * Returns: 0 on success, -1 on error
- */
-int fs_compute_bitstructs(struct gfs_rgrpd *rgd)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- struct gfs_bitmap *bits;
- uint32 length = rgd->rd_ri.ri_length;
- uint32 bytes_left, bytes;
- int x;
-
- if(!(rgd->rd_bits = (struct gfs_bitmap *)malloc(length * sizeof(struct gfs_bitmap)))) {
- log_err("Unable to allocate bitmap structure\n");
- stack;
- return -1;
- }
- if(!memset(rgd->rd_bits, 0, length * sizeof(struct gfs_bitmap))) {
- log_err("Unable to zero bitmap structure\n");
- stack;
- return -1;
- }
-
- bytes_left = rgd->rd_ri.ri_bitbytes;
-
- for (x = 0; x < length; x++){
- bits = &rgd->rd_bits[x];
-
- if (length == 1){
- bytes = bytes_left;
- bits->bi_offset = sizeof(struct gfs_rgrp);
- bits->bi_start = 0;
- bits->bi_len = bytes;
- }
- else if (x == 0){
- bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs_rgrp);
- bits->bi_offset = sizeof(struct gfs_rgrp);
- bits->bi_start = 0;
- bits->bi_len = bytes;
- }
- else if (x + 1 == length){
- bytes = bytes_left;
- bits->bi_offset = sizeof(struct gfs_meta_header);
- bits->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
- bits->bi_len = bytes;
- }
- else{
- bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs_meta_header);
- bits->bi_offset = sizeof(struct gfs_meta_header);
- bits->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
- bits->bi_len = bytes;
- }
-
- bytes_left -= bytes;
- }
-
- if(bytes_left){
- log_err( "fs_compute_bitstructs: Too many blocks in rgrp to "
- "fit into available bitmap.\n");
- return -1;
- }
-
- if((rgd->rd_bits[length - 1].bi_start +
- rgd->rd_bits[length - 1].bi_len) * GFS_NBBY != rgd->rd_ri.ri_data){
- log_err( "fs_compute_bitstructs: # of blks in rgrp do not equal "
- "# of blks represented in bitmap.\n"
- "\tbi_start = %u\n"
- "\tbi_len = %u\n"
- "\tGFS_NBBY = %u\n"
- "\tri_data = %u\n",
- rgd->rd_bits[length - 1].bi_start,
- rgd->rd_bits[length - 1].bi_len,
- GFS_NBBY,
- rgd->rd_ri.ri_data);
- return -1;
- }
-
-
- if(!(rgd->rd_bh = (osi_buf_t **)malloc(length * sizeof(osi_buf_t *)))) {
- log_err("Unable to allocate osi_buf structure\n");
- stack;
- return -1;
- }
- if(!memset(rgd->rd_bh, 0, length * sizeof(osi_buf_t *))) {
- log_err("Unable to zero osi_buf structure\n");
- stack;
- return -1;
- }
-
- return 0;
-}
-
-
-/**
- * blk2rgrpd - Find resource group for a given data block number
- * @sdp: The GFS superblock
- * @n: The data block number
- *
- * Returns: Ths resource group, or NULL if not found
- */
-struct gfs_rgrpd *fs_blk2rgrpd(struct gfs_sbd *sdp, uint64 blk)
-{
- osi_list_t *tmp;
- struct gfs_rgrpd *rgd = NULL;
- struct gfs_rindex *ri;
-
- for(tmp = (osi_list_t *)sdp->sd_rglist.next;
- tmp != (osi_list_t *)&sdp->sd_rglist; tmp = tmp->next){
- rgd = osi_list_entry(tmp, struct gfs_rgrpd, rd_list);
- ri = &rgd->rd_ri;
-
- if (ri->ri_data1 <= blk && blk < ri->ri_data1 + ri->ri_data){
- break;
- } else
- rgd = NULL;
- }
- return rgd;
-}
-
-/**
- * fs_rgrp_read - read in the resource group information from disk.
- * @rgd - resource group structure
- * @repair_if_corrupted - If TRUE, rgrps found to be corrupt should be repaired
- * according to the index. If FALSE, no corruption is fixed.
- */
-int fs_rgrp_read(int disk_fd, struct gfs_rgrpd *rgd, int repair_if_corrupted)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- unsigned int x, length = rgd->rd_ri.ri_length;
- int error;
-
- if(rgd->rd_open_count){
- log_debug("rgrp already read...\n");
- rgd->rd_open_count++;
- return 0;
- }
-
- for (x = 0; x < length; x++){
- if(rgd->rd_bh[x]){
- log_err("Programmer error! Bitmaps are already present in rgrp.\n");
- exit(1);
- }
- error = get_and_read_buf(disk_fd, sdp->sd_sb.sb_bsize,
- rgd->rd_ri.ri_addr + x, &(rgd->rd_bh[x]), 0);
- if (error) {
- log_err("Unable to read rgrp from disk.\n");
- goto fail;
- }
-
- if(check_meta(rgd->rd_bh[x], (x) ? GFS_METATYPE_RB : GFS_METATYPE_RG)){
- log_err("Buffer #%"PRIu64" (%d of %d) is neither"
- " GFS_METATYPE_RB nor GFS_METATYPE_RG.\n",
- BH_BLKNO(rgd->rd_bh[x]),
- (int)x+1,
- (int)length);
- if (repair_if_corrupted) {
- log_err("Attempting to repair.\n");
- memset(&rgd->rd_rg, 0, sizeof(struct gfs_rgrp));
- rgd->rd_rg.rg_header.mh_magic = GFS_MAGIC;
- rgd->rd_rg.rg_header.mh_type = GFS_METATYPE_RG;
- rgd->rd_rg.rg_header.mh_format = GFS_FORMAT_RG;
- rgd->rd_rg.rg_free = rgd->rd_ri.ri_data;
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[x]));
- write_buf(disk_fd, rgd->rd_bh[x], BW_WAIT);
- }
- else {
- error = -1;
- goto fail;
- }
- }
- }
-
- gfs_rgrp_in(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- rgd->rd_open_count = 1;
-
- return 0;
-
- fail:
- for (x = 0; x < length; x++){
- relse_buf(rgd->rd_bh[x]);
- rgd->rd_bh[x] = NULL;
- }
-
- log_err("Resource group is corrupted.\n");
- return error;
-}
-
-void fs_rgrp_relse(struct gfs_rgrpd *rgd)
-{
- int x, length = rgd->rd_ri.ri_length;
-
- rgd->rd_open_count--;
- if(rgd->rd_open_count){
- log_debug("rgrp still held...\n");
- } else {
- for (x = 0; x < length; x++){
- relse_buf(rgd->rd_bh[x]);
- rgd->rd_bh[x] = NULL;
- }
- }
-}
-
-
-/**
- * rgrp_verify - Verify that a resource group is consistent
- * @sdp: the filesystem
- * @rgd: the rgrp
- *
- * Returns: 0 if ok, -1 on error
- */
-int fs_rgrp_verify(struct gfs_rgrpd *rgd)
-{
- struct gfs_bitmap *bits = NULL;
- uint32 length = rgd->rd_ri.ri_length;
- uint32 count[4], tmp;
- int buf, x;
-
- for (x = 0; x < 4; x++){
- count[x] = 0;
-
- for (buf = 0; buf < length; buf++){
- bits = &rgd->rd_bits[buf];
- count[x] += fs_bitcount((unsigned char *)
- BH_DATA(rgd->rd_bh[buf]) +
- bits->bi_offset,
- bits->bi_len, x);
- }
- }
-
- if(count[0] != rgd->rd_rg.rg_free){
- log_err("free data mismatch: %u != %u\n",
- count[0], rgd->rd_rg.rg_free);
- return -1;
- }
-
- tmp = rgd->rd_ri.ri_data -
- (rgd->rd_rg.rg_usedmeta + rgd->rd_rg.rg_freemeta) -
- (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi) -
- rgd->rd_rg.rg_free;
-
- if(count[1] != tmp){
- log_err("used data mismatch: %u != %u\n",
- count[1], tmp);
- return -1;
- }
- if(count[2] != rgd->rd_rg.rg_freemeta){
- log_err("free metadata mismatch: %u != %u\n",
- count[2], rgd->rd_rg.rg_freemeta);
- return -1;
- }
-
- tmp = rgd->rd_rg.rg_usedmeta +
- (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi);
-
- if(count[3] != tmp){
- log_err("used metadata mismatch: %u != %u\n",
- count[3], tmp);
- return -1;
- }
- return 0;
-}
-
-/**
- * fs_rgrp_recount - adjust block tracking numbers
- * rgd: resource group
- *
- * The resource groups keep track of how many free blocks, used blocks,
- * etc there are. This function readjusts those numbers based on the
- * current state of the bitmap.
- *
- * Returns: 0 on success, -1 on failure
- */
-int fs_rgrp_recount(int disk_fd, struct gfs_rgrpd *rgd){
- int i,j;
- fs_bitmap_t *bits = NULL;
- uint32 length = rgd->rd_ri.ri_length;
- uint32 count[4], tmp;
-
- for(i=0; i < 4; i++){
- count[i] = 0;
- for(j = 0; j < length; j++){
- bits = (fs_bitmap_t *)&rgd->rd_bits[j];
- count[i] += fs_bitcount((unsigned char *)
- BH_DATA(rgd->rd_bh[j]) +
- bits->bi_offset,
- bits->bi_len, i);
- }
- }
- if(count[0] != rgd->rd_rg.rg_free){
- log_warn("\tAdjusting free block count (%u -> %u).\n",
- rgd->rd_rg.rg_free, count[0]);
- rgd->rd_rg.rg_free = count[0];
- }
- if(count[2] != rgd->rd_rg.rg_freemeta){
- log_warn("\tAdjusting freemeta block count (%u -> %u).\n",
- rgd->rd_rg.rg_freemeta, count[2]);
- rgd->rd_rg.rg_freemeta = count[2];
- }
- tmp = rgd->rd_rg.rg_usedmeta +
- (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi);
-
- if(count[3] != tmp){
- int first = 1;
- struct gfs_sbd *sdp = rgd->rd_sbd;
- uint32 useddi = 0;
- uint32 freedi = 0;
- uint64 block;
- struct gfs_inode *ip;
-
- while (1){ /* count the used dinodes */
- if(next_rg_metatype(disk_fd, rgd, &block,
- GFS_METATYPE_DI, first)){
- break;
- }
- first = 0;
- if(load_inode(disk_fd, sdp, block, &ip)) {
- stack;
- continue;
- }
-
- if (ip->i_di.di_flags & GFS_DIF_UNUSED){
- freedi++;
- continue;
- }
- free_inode(&ip);
- useddi++;
- }
-
- if(useddi != rgd->rd_rg.rg_useddi){
- log_warn("\tAdjusting used dinode block count (%u -> %u).\n",
- rgd->rd_rg.rg_useddi, useddi);
- rgd->rd_rg.rg_useddi = useddi;
- }
- if(freedi != rgd->rd_rg.rg_freedi){
- log_warn("\tAdjusting free dinode block count (%u -> %u).\n",
- rgd->rd_rg.rg_freedi, freedi);
- rgd->rd_rg.rg_freedi = freedi;
- }
- if(rgd->rd_rg.rg_usedmeta != count[3] - (freedi + useddi)){
- log_warn("\tAdjusting used meta block count (%u -> %u).\n",
- rgd->rd_rg.rg_usedmeta,
- (count[3] - (freedi + useddi)));
- rgd->rd_rg.rg_usedmeta = count[3] - (freedi + useddi);
- }
- }
-
- tmp = rgd->rd_ri.ri_data -
- (rgd->rd_rg.rg_usedmeta + rgd->rd_rg.rg_freemeta) -
- (rgd->rd_rg.rg_useddi + rgd->rd_rg.rg_freedi) -
- rgd->rd_rg.rg_free;
-
- if(count[1] != tmp){
- log_err("Could not reconcile rgrp block counts.\n");
- return -1;
- }
- return 0;
-}
-
-/**
- * clump_alloc - Allocate a clump of metadata
- * @rgd: the resource group descriptor
- * @goal: the goal block in the RG
- *
- * Returns: 0 on success, -1 on failure
- */
-int clump_alloc(int disk_fd, struct gfs_rgrpd *rgd, uint32 goal)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- struct gfs_meta_header mh;
- osi_buf_t *bh[GFS_META_CLUMP] = {0};
- uint32 block;
- int i,j;
- int error = 0;
-
- memset(&mh, 0, sizeof(struct gfs_meta_header));
- mh.mh_magic = GFS_MAGIC;
- mh.mh_type = GFS_METATYPE_NONE;
-
- if(rgd->rd_rg.rg_free < GFS_META_CLUMP){
- log_debug(" Not enough free blocks in rgrp.\n");
- return -1;
- }
-
- for (i = 0; i < GFS_META_CLUMP; i++){
- block = fs_blkalloc_internal(rgd, goal,
- GFS_BLKST_FREE,
- GFS_BLKST_FREEMETA, TRUE);
- log_debug("Got block %u\n", block);
-
- if(block == BFITNOENT) {
- log_err("Unable to get enough blocks\n");
- goto fail;
- }
- block += rgd->rd_ri.ri_data1;
- block_set(rgd->rd_sbd->bl, block, meta_free);
- if (get_buf(sdp->sd_sb.sb_bsize, block, &(bh[i]))){
- log_err("Unable to allocate new buffer.\n");
- goto fail;
- }
- gfs_meta_header_out(&mh, BH_DATA(bh[i]));
-
- goal = block;
- }
-
- log_debug("64 Meta blocks (%"PRIu64" - %"PRIu64"), allocated in rgrp 0x%lx\n",
- (rgd->rd_ri.ri_data1 + block)-63,
- (rgd->rd_ri.ri_data1 + block),
- (unsigned long)rgd);
- for (j = 0; j < GFS_META_CLUMP; j++){
-
- error = write_buf(disk_fd, bh[j], BW_WAIT);
- if (error){
- log_err("Unable to write allocated metablock to disk.\n");
- goto fail;
- }
- }
-
- if(rgd->rd_rg.rg_free < GFS_META_CLUMP){
- log_err("More blocks were allocated from rgrp "
- "than are available.\n");
- goto fail;
- }
- rgd->rd_rg.rg_free -= GFS_META_CLUMP;
- rgd->rd_rg.rg_freemeta += GFS_META_CLUMP;
-
- for (i = 0; i < GFS_META_CLUMP; i++)
- relse_buf(bh[i]);
-
- return 0;
-
- fail:
- log_debug("clump_alloc failing...\n");
- for(--i; i >=0; i--){
- fs_set_bitmap(disk_fd, sdp, BH_BLKNO(bh[i]), GFS_BLKST_FREE);
- relse_buf(bh[i]);
- }
- return -1;
-}
-
-
-/**
- * fs_blkalloc - Allocate a data block
- * @ip: the inode to allocate the data block for
- * @block: the block allocated
- *
- * Returns: 0 on success, -1 on failure
- */
-int fs_blkalloc(int disk_fd, struct gfs_inode *ip, uint64 *block)
-{
- osi_list_t *tmp;
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_rgrpd *rgd;
- uint32 goal;
- int same;
-
- for(tmp = (osi_list_t *)sdp->sd_rglist.next;
- tmp != (osi_list_t *)&sdp->sd_rglist; tmp = tmp->next){
- rgd = osi_list_entry(tmp, struct gfs_rgrpd, rd_list);
-
- if(!rgd){
- log_err( "fs_blkalloc: Bad rgrp list!\n");
- return -1;
- }
-
- if(fs_rgrp_read(disk_fd, rgd, FALSE)){
- log_err( "fs_blkalloc: Unable to read rgrp.\n");
- return -1;
- }
-
- if(!rgd->rd_rg.rg_free){
- fs_rgrp_relse(rgd);
- continue;
- }
-
- same = (rgd->rd_ri.ri_addr == ip->i_di.di_goal_rgrp);
- goal = (same) ? ip->i_di.di_goal_dblk : 0;
-
- *block = fs_blkalloc_internal(rgd, goal,
- GFS_BLKST_FREE,
- GFS_BLKST_USED, TRUE);
-
- log_debug("Got block %"PRIu64"\n", *block);
- if(*block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- if (!same){
- ip->i_di.di_goal_rgrp = rgd->rd_ri.ri_addr;
- ip->i_di.di_goal_mblk = 0;
- }
-
- *block += rgd->rd_ri.ri_data1;
- ip->i_di.di_goal_dblk = *block;
-
- rgd->rd_rg.rg_free--;
-
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- if(write_buf(disk_fd, rgd->rd_bh[0], 0)){
- log_err( "Unable to write out rgrp block #%"
- PRIu64".\n",
- BH_BLKNO(rgd->rd_bh[0]));
- fs_rgrp_relse(rgd);
- return -1;
- }
- fs_rgrp_relse(rgd);
- return 0;
- }
-
- return 1;
-}
-
-
-/**
- * fs_metaalloc - Allocate a metadata block to a file
- * @ip: the file
- * @block: the block allocated
- *
- * Returns: 0 on success, -1 on failure
- */
-int fs_metaalloc(int disk_fd, struct gfs_inode *ip, uint64 *block)
-{
- osi_list_t *tmp;
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_rgrpd *rgd;
- uint32 goal;
- int same;
- int error = 0;
-
- /* ATTENTION -- maybe we should try to allocate from goal rgrp first */
- for(tmp = (osi_list_t *)sdp->sd_rglist.next;
- tmp != (osi_list_t *)&sdp->sd_rglist; tmp = tmp->next){
- rgd = osi_list_entry(tmp, struct gfs_rgrpd, rd_list);
-
- if(!rgd){
- log_err( "fs_metaalloc: Bad rgrp list!\n");
- return -1;
- }
-
- if(fs_rgrp_read(disk_fd, rgd, FALSE)){
- log_err( "fs_metaalloc: Unable to read rgrp.\n");
- return -1;
- }
-
- same = (rgd->rd_ri.ri_addr == ip->i_di.di_goal_rgrp);
- goal = (same) ? ip->i_di.di_goal_mblk : 0;
-
- if (!rgd->rd_rg.rg_freemeta){
- error = clump_alloc(disk_fd, rgd, goal);
- if (error){
- fs_rgrp_relse(rgd);
- continue;
- }
- }
-
-
- if(!rgd->rd_rg.rg_freemeta){
- fs_rgrp_relse(rgd);
- continue;
- }
- *block = fs_blkalloc_internal(rgd, goal,
- GFS_BLKST_FREEMETA,
- GFS_BLKST_USEDMETA, TRUE);
- log_debug("Got block %"PRIu64"\n", *block);
- if(*block == BFITNOENT) {
- fs_rgrp_relse(rgd);
- continue;
- }
- if (!same){
- ip->i_di.di_goal_rgrp = rgd->rd_ri.ri_addr;
- ip->i_di.di_goal_dblk = 0;
- }
- *block += rgd->rd_ri.ri_data1;
- ip->i_di.di_goal_mblk = *block;
-
- rgd->rd_rg.rg_freemeta--;
- rgd->rd_rg.rg_usedmeta++;
-
- gfs_rgrp_out(&rgd->rd_rg, BH_DATA(rgd->rd_bh[0]));
- write_buf(disk_fd, rgd->rd_bh[0], 0);
- fs_rgrp_relse(rgd);
- /* if we made it this far, then we are ok */
- return 0;
- }
-
- return -1;
-}
diff --git a/gfs/libgfs/size.c b/gfs/libgfs/size.c
deleted file mode 100644
index 289c04d..0000000
--- a/gfs/libgfs/size.c
+++ /dev/null
@@ -1,81 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/mount.h>
-
-#include "libgfs.h"
-
-#ifndef BLKGETSIZE64
-#define BLKGETSIZE64 _IOR(0x12, 114, size_t)
-#endif
-
-/**
- * do_device_size - determine the size of a Linux block device
- * @device: the path to the device node
- *
- * Returns: -1 on error (with errno set), 0 on success (with @bytes set)
- */
-
-static int
-do_device_size(int fd, uint64_t *bytes)
-{
- unsigned long size;
- off_t off;
- int error;
-
- error = ioctl(fd, BLKGETSIZE64, bytes); /* Size in bytes */
- if (!error)
- return 0;
-
- error = ioctl(fd, BLKGETSIZE, &size); /* Size in 512-byte blocks */
- if (!error) {
- *bytes = ((uint64_t) size) << 9;
- return 0;
- }
-
- off = lseek(fd, 0, SEEK_END);
- if (off >= 0) {
- *bytes = off;
- return 0;
- }
-
- return -1;
-}
-
-/**
- * device_size - figure out a device's size
- * @fd: the file descriptor of a device
- * @bytes: the number of bytes the device holds
- *
- * Returns: -1 on error (with errno set), 0 on success (with @bytes set)
- */
-
-int
-device_size(int fd, uint64_t *bytes)
-{
- struct stat st;
- int error;
-
- error = fstat(fd, &st);
- if (error)
- return error;
-
- if (S_ISREG(st.st_mode)) {
- *bytes = st.st_size;
- return 0;
- } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))
- return do_device_size(fd, bytes);
- else if (S_ISDIR(st.st_mode))
- errno = EISDIR;
- else
- errno = EINVAL;
-
- return -1;
-}
diff --git a/gfs/libgfs/super.c b/gfs/libgfs/super.c
deleted file mode 100644
index cf45e94..0000000
--- a/gfs/libgfs/super.c
+++ /dev/null
@@ -1,530 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <errno.h>
-
-#include "osi_list.h"
-#include "osi_user.h"
-#include "gfs_ondisk.h"
-#include "incore.h"
-#include "libgfs.h"
-
-#ifndef BLKGETSIZE64
-#define BLKGETSIZE64 _IOR(0x12, 114, size_t)
-#endif
-
-#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
-#define ri_compare(rg, ondisk, expected, field, fmt) \
- if (ondisk.field != expected.field) { \
- log_warn("rgindex[%d] " #field " discrepancy: index 0x%" fmt \
- " != expected: 0x%" fmt "\n", \
- rg, ondisk.field, expected.field); \
- ondisk.field = expected.field; \
- rgindex_modified = TRUE; \
- }
-
-static uint64 total_journal_space;
-
-/**
- * check_sb - Check superblock
- * @sdp: the filesystem
- * @sb: The superblock
- *
- * Checks the version code of the FS is one that we understand how to
- * read and that the sizes of the various on-disk structures have not
- * changed.
- *
- * Returns: 0 on success, -1 on failure
- */
-static int check_sb(struct gfs_sbd *sdp, struct gfs_sb *sb)
-{
- int error = 0;
- if (sb->sb_header.mh_magic != GFS_MAGIC ||
- sb->sb_header.mh_type != GFS_METATYPE_SB){
- log_crit("Either the super block is corrupted, or this "
- "is not a GFS filesystem\n");
- log_debug("Header magic: %X Header Type: %X\n",
- sb->sb_header.mh_magic,
- sb->sb_header.mh_type);
- error = -EINVAL;
- goto out;
- }
-
- /* If format numbers match exactly, we're done. */
- if (sb->sb_fs_format != GFS_FORMAT_FS ||
- sb->sb_multihost_format != GFS_FORMAT_MULTI){
- log_warn("Old file system detected.\n");
- }
-
- out:
- return error;
-}
-
-/*
- * compute_constants: compute constants for the superblock
- *
- * assumes:
- * sb_bsize_shift is set either from the ondisk superblock or otherwise.
- * sb_bsize is set either from the ondisk superblock or otherwise.
- */
-int compute_constants(struct gfs_sbd *sdp)
-{
- unsigned int x;
- uint64 space = 0;
- int error = 0;
-
- sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - 9;
- sdp->sd_diptrs =
- (sdp->sd_sb.sb_bsize-sizeof(struct gfs_dinode)) /
- sizeof(uint64);
- sdp->sd_inptrs =
- (sdp->sd_sb.sb_bsize-sizeof(struct gfs_indirect)) /
- sizeof(uint64);
- sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs_meta_header);
- sdp->sd_hash_bsize = sdp->sd_sb.sb_bsize / 2;
- sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64);
- sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize -
- sizeof(struct gfs_dinode);
- sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs;
- for (x = 2; ; x++){
- space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs;
- /* FIXME: Do we really need this first check?? */
- if (space / sdp->sd_inptrs != sdp->sd_heightsize[x - 1] ||
- space % sdp->sd_inptrs != 0)
- break;
- sdp->sd_heightsize[x] = space;
- }
- sdp->sd_max_height = x;
- if(sdp->sd_max_height > GFS_MAX_META_HEIGHT){
- log_err("Bad max metadata height.\n");
- error = -1;
- return error;
- }
-
- sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize -
- sizeof(struct gfs_dinode);
- sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs;
- for (x = 2; ; x++){
- space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs;
- if (space / sdp->sd_inptrs != sdp->sd_jheightsize[x - 1] ||
- space % sdp->sd_inptrs != 0)
- break;
- sdp->sd_jheightsize[x] = space;
- }
- sdp->sd_max_jheight = x;
- if(sdp->sd_max_jheight > GFS_MAX_META_HEIGHT){
- log_err("Bad max jheight.\n");
- error = -1;
- }
- return error;
-}
-
-/*
- * read_sb: read the super block from disk
- * sdp: in-core super block
- *
- * This function reads in the super block from disk and
- * initializes various constants maintained in the super
- * block
- *
- * Returns: 0 on success, -1 on failure.
- */
-int read_sb(int disk_fd, struct gfs_sbd *sdp)
-{
- osi_buf_t *bh;
- int error;
- error = get_and_read_buf(disk_fd, 512, /* assume 512 block size at first */
- GFS_SB_ADDR >> sdp->sd_fsb2bb_shift, &bh, 0);
- if (error){
- log_crit("Unable to read superblock\n");
- goto out;
- }
-
- gfs_sb_in(&sdp->sd_sb, BH_DATA(bh));
-
- relse_buf(bh);
-
- error = check_sb(sdp, &sdp->sd_sb);
- if (error)
- goto out;
-
- compute_constants(sdp);
-
- out:
-
- return error;
-}
-
-
-/*
- * ji_update - fill in journal info
- * ip: the journal index inode
- *
- * Given the inode for the journal index, read in all
- * the journal indexes.
- *
- * Returns: 0 on success, -1 on failure
- */
-int ji_update(int disk_fd, struct gfs_sbd *sdp)
-{
- struct gfs_inode *ip = sdp->sd_jiinode;
- char buf[sizeof(struct gfs_jindex)];
- unsigned int j;
- int error=0;
-
-
- if(ip->i_di.di_size % sizeof(struct gfs_jindex) != 0){
- log_err("The size reported in the journal index"
- " inode is not a\n"
- "\tmultiple of the size of a journal index.\n");
- return -1;
- }
-
- if(!(sdp->sd_jindex = (struct gfs_jindex *)malloc(ip->i_di.di_size))) {
- log_err("Unable to allocate journal index\n");
- return -1;
- }
- if(!memset(sdp->sd_jindex, 0, ip->i_di.di_size)) {
- log_err("Unable to zero journal index\n");
- return -1;
- }
- total_journal_space = 0;
-
- for (j = 0; ; j++) {
- struct gfs_jindex *journ;
- error = readi(disk_fd, ip, buf, j * sizeof(struct gfs_jindex),
- sizeof(struct gfs_jindex));
- if(!error)
- break;
- if (error != sizeof(struct gfs_jindex)){
- log_err("An error occurred while reading the"
- " journal index file.\n");
- goto fail;
- }
-
- journ = sdp->sd_jindex + j;
- gfs_jindex_in(journ, buf);
- total_journal_space += journ->ji_nsegment * sdp->sd_sb.sb_seg_size;
- }
-
-
- if(j * sizeof(struct gfs_jindex) != ip->i_di.di_size){
- log_err("journal inode size invalid\n");
- log_debug("j * sizeof(struct gfs_jindex) !="
- " ip->i_di.di_size\n");
- log_debug("%d != %d\n",
- j * sizeof(struct gfs_jindex), ip->i_di.di_size);
- goto fail;
- }
- sdp->sd_journals = j;
- log_debug("%d journals found.\n", j);
-
- return 0;
-
- fail:
- free(sdp->sd_jindex);
- return -1;
-}
-
-/* Print out debugging information in same format as gfs_edit. */
-int hexdump(uint64 startaddr, const unsigned char *lpBuffer, int len)
-{
- const unsigned char *pointer,*ptr2;
- int i;
- uint64 l;
-
- pointer = (unsigned char *)lpBuffer;
- ptr2 = (unsigned char *)lpBuffer;
- l = 0;
- while (l < len) {
- log_info("%.8"PRIX64,startaddr + l);
- for (i=0; i<16; i++) { /* first print it in hex */
- if (i%4 == 0)
- log_info(" ");
- log_info("%02X",*pointer);
- pointer++;
- }
- log_info(" [");
- for (i=0; i<16; i++) { /* now print it in character format */
- if ((*ptr2 >=' ') && (*ptr2 <= '~'))
- log_info("%c",*ptr2);
- else
- log_info(".");
- ptr2++;
- }
- log_info("] \n");
- l+=16;
- }
- return (len);
-}
-
-/**
- * rgrplength2bitblocks - blerg - Stolen by Bob from gfs_mkfs. Good
- * candidate for gfslib.
- *
- * @sdp: the superblock
- * @length: the number of blocks in a RG
- *
- * Give a number of blocks in a RG, figure out the number of blocks
- * needed for bitmaps.
- *
- * Returns: the number of bitmap blocks
- */
-
-uint32 rgrplength2bitblocks(struct gfs_sbd *sdp, uint32 length)
-{
- uint32 bitbytes;
- uint32 old_blocks = 0, blocks;
- int tries = 0;
-
- for (;;) {
- bitbytes = (length - old_blocks) / GFS_NBBY;
- blocks = 1;
-
- if (bitbytes > sdp->sd_sb.sb_bsize - sizeof(struct gfs_rgrp)) {
- bitbytes -= sdp->sd_sb.sb_bsize - sizeof(struct gfs_rgrp);
- blocks += DIV_RU(bitbytes, (sdp->sd_sb.sb_bsize -
- sizeof(struct gfs_meta_header)));
- }
- if (blocks == old_blocks)
- break;
- old_blocks = blocks;
- if (tries++ > 10) {
- blocks = 0;
- break;
- }
- }
- return blocks;
-}
-
-/*
- * ri_cleanup - free up the memory we previously allocated.
- */
-void ri_cleanup(osi_list_t *rglist)
-{
- struct gfs_rgrpd *rgd;
-
- while(!osi_list_empty(rglist)){
- rgd = osi_list_entry(rglist->next, struct gfs_rgrpd, rd_list);
- if(rgd->rd_bits)
- free(rgd->rd_bits);
- if(rgd->rd_bh)
- free(rgd->rd_bh);
- osi_list_del((osi_list_t *)&rgd->rd_list);
- free(rgd);
- }
-}
-
-/**
- * ri_update - attach rgrps to the super block
- * @sdp:
- *
- * Given the rgrp index inode, link in all rgrps into the super block
- * and be sure that they can be read.
- *
- * Returns: 0 on success, -1 on failure.
- */
-int ri_update(int disk_fd, struct gfs_sbd *sdp)
-{
- struct gfs_rgrpd *rgd;
- osi_list_t *tmp;
- struct gfs_rindex buf;
- unsigned int rg;
- int error, count1 = 0, count2 = 0;
-
- for (rg = 0; ; rg++) {
- error = readi(disk_fd, sdp->sd_riinode, (char *)&buf,
- rg * sizeof(struct gfs_rindex),
- sizeof(struct gfs_rindex));
- if (!error)
- break;
- if (error != sizeof(struct gfs_rindex)){
- log_err("Unable to read resource group index #%u.\n", rg);
- goto fail;
- }
- rgd = (struct gfs_rgrpd *)malloc(sizeof(struct gfs_rgrpd));
- // FIXME: handle failed malloc
- rgd->rd_sbd = sdp;
- osi_list_add_prev((osi_list_t *)&rgd->rd_list,
- (osi_list_t *)&sdp->sd_rglist);
- gfs_rindex_in(&rgd->rd_ri, (char *)&buf);
- if(fs_compute_bitstructs(rgd)){
- goto fail;
- }
- rgd->rd_open_count = 0;
- count1++;
- }
- log_debug("%u resource groups found.\n", rg);
- for (tmp = (osi_list_t *)sdp->sd_rglist.next;
- tmp != (osi_list_t *)&sdp->sd_rglist; tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct gfs_rgrpd, rd_list);
- error = fs_rgrp_read(disk_fd, rgd, FALSE);
- if (error) {
- log_err("Unable to read in rgrp descriptor.\n");
- goto fail;
- }
- fs_rgrp_relse(rgd);
- count2++;
- }
- if (count1 != count2) {
- log_err("Rgrps allocated (%d) does not equal"
- " rgrps read (%d).\n", count1, count2);
- goto fail;
- }
- sdp->sd_rgcount = count1;
- return 0;
-
- fail:
- while(!osi_list_empty((osi_list_t *)&sdp->sd_rglist)){
- rgd = osi_list_entry((osi_list_t *)sdp->sd_rglist.next,
- struct gfs_rgrpd, rd_list);
- if(rgd->rd_bits)
- free(rgd->rd_bits);
- if(rgd->rd_bh)
- free(rgd->rd_bh);
- osi_list_del((osi_list_t *)&rgd->rd_list);
- free(rgd);
- }
- return -1;
-}
-
-/**
- * set_block_ranges
- * @sdp: superblock
- *
- * Uses info in rgrps and jindex to determine boundaries of the
- * file system.
- *
- * Returns: 0 on success, -1 on failure
- */
-int set_block_ranges(int disk_fd, struct gfs_sbd *sdp)
-{
- struct gfs_jindex *jdesc;
- struct gfs_rgrpd *rgd;
- struct gfs_rindex *ri;
- osi_list_t *tmp;
- char buf[sdp->sd_sb.sb_bsize];
- uint64 rmax = 0;
- uint64 jmax = 0;
- uint64 rmin = 0;
- uint64 i;
- int error;
-
- log_info("Setting block ranges...\n");
-
- for (tmp = (osi_list_t *)sdp->sd_rglist.next;
- tmp != (osi_list_t *)&sdp->sd_rglist; tmp = tmp->next)
- {
- rgd = osi_list_entry(tmp, struct gfs_rgrpd, rd_list);
- ri = &rgd->rd_ri;
- if (ri->ri_data1 + ri->ri_data - 1 > rmax)
- rmax = ri->ri_data1 + ri->ri_data - 1;
- if (!rmin || ri->ri_data1 < rmin)
- rmin = ri->ri_data1;
- }
-
-
- for (i = 0; i < sdp->sd_journals; i++)
- {
- jdesc = &sdp->sd_jindex[i];
-
- if ((jdesc->ji_addr+jdesc->ji_nsegment*sdp->sd_sb.sb_seg_size-1)
- > jmax)
- jmax = jdesc->ji_addr + jdesc->ji_nsegment
- * sdp->sd_sb.sb_seg_size - 1;
- }
-
- sdp->last_fs_block = (jmax > rmax) ? jmax : rmax;
-
- sdp->last_data_block = rmax;
- sdp->first_data_block = rmin;
-
- if(do_lseek(disk_fd, (sdp->last_fs_block * sdp->sd_sb.sb_bsize))){
- log_crit("Can't seek to last block in file system: %"
- PRIu64"\n", sdp->last_fs_block);
- goto fail;
- }
-
- memset(buf, 0, sdp->sd_sb.sb_bsize);
- error = read(disk_fd, buf, sdp->sd_sb.sb_bsize);
- if (error != sdp->sd_sb.sb_bsize){
- log_crit("Can't read last block in file system (%u), "
- "last_fs_block: %"PRIu64"\n",
- error, sdp->last_fs_block);
- goto fail;
- }
-
- return 0;
-
- fail:
- return -1;
-}
-
-int write_sb(int disk_fd, struct gfs_sbd *sbp)
-{
- int error = 0;
- osi_buf_t *bh;
-
- error = get_and_read_buf(disk_fd, sbp->sd_sb.sb_bsize,
- GFS_SB_ADDR >> sbp->sd_fsb2bb_shift, &bh, 0);
- if (error){
- log_crit("Unable to read superblock\n");
- goto out;
- }
-
- memset(BH_DATA(bh), 0, sbp->sd_sb.sb_bsize);
- gfs_sb_out(&sbp->sd_sb, BH_DATA(bh));
-
- /* FIXME: Should this set the BW_WAIT flag? */
- if((error = write_buf(disk_fd, bh, 0))) {
- stack;
- goto out;
- }
-
- relse_buf(bh);
-out:
- return error;
-
-}
-
-/**
- * read_super_block
- * @sdp:
- *
- * Returns: 0 on success, -1 on failure
- */
-int read_super_block(int disk_fd, struct gfs_sbd *sdp)
-{
- uint32_t i;
-
- sync();
-
- /********************************************************************
- ***************** First, initialize all lists **********************
- ********************************************************************/
- log_info("Initializing lists...\n");
- osi_list_init((osi_list_t *)&sdp->sd_rglist);
- for(i = 0; i < FSCK_HASH_SIZE; i++) {
- osi_list_init(&sdp->dir_hash[i]);
- osi_list_init(&sdp->inode_hash[i]);
- }
-
- /********************************************************************
- ************ next, read in on-disk SB and set constants **********
- ********************************************************************/
- sdp->sd_sb.sb_bsize = 512;
- if (sdp->sd_sb.sb_bsize < GFS_BASIC_BLOCK)
- sdp->sd_sb.sb_bsize = GFS_BASIC_BLOCK;
-
- if(sizeof(struct gfs_sb) > sdp->sd_sb.sb_bsize){
- log_crit("GFS superblock is larger than the blocksize!\n");
- log_debug("sizeof(struct gfs_sb) > sdp->sb.sb_bsize\n");
- return -1;
- }
-
- if(read_sb(disk_fd, sdp) < 0){
- return -1;
- }
-
- return 0;
-}
diff --git a/gfs/libgfs/util.c b/gfs/libgfs/util.c
deleted file mode 100644
index 998396b..0000000
--- a/gfs/libgfs/util.c
+++ /dev/null
@@ -1,271 +0,0 @@
-#include "libgfs.h"
-
-/**
- * compute_height
- * @sdp:
- * @sz:
- *
- */
-int compute_height(struct gfs_sbd *sdp, uint64 sz)
-{
- unsigned int height;
- uint64 space, old_space;
- unsigned int bsize = sdp->sd_sb.sb_bsize;
-
- if (sz <= (bsize - sizeof(struct gfs_dinode)))
- return 0;
-
- height = 1;
- space = sdp->sd_diptrs * bsize;
-
- while (sz > space)
- {
- old_space = space;
-
- height++;
- space *= sdp->sd_inptrs;
-
- if (space / sdp->sd_inptrs != old_space ||
- space % sdp->sd_inptrs != 0)
- break;
- }
-
- return height;
-}
-
-
-/*
- * check_range - check if blkno is within FS limits
- * @sdp: super block
- * @blkno: block number
- *
- * Returns: 0 if ok, -1 if out of bounds
- */
-int check_range(struct gfs_sbd *sdp, uint64 blkno){
- if((blkno > sdp->last_fs_block) ||
- (blkno < sdp->first_data_block))
- return -1;
- return 0;
-}
-
-
-/*
- * set_meta - set the meta header of a buffer
- * @bh
- * @type
- *
- * Returns: 0 if ok, -1 on error
- */
-int set_meta(osi_buf_t *bh, int type, int format){
- struct gfs_meta_header header;
-
- if(!check_meta(bh, 0)){
- log_debug("Setting metadata\n");
- ((struct gfs_meta_header *)BH_DATA(bh))->mh_type = cpu_to_gfs32(type);
- ((struct gfs_meta_header *)BH_DATA(bh))->mh_format = cpu_to_gfs32(format);
- } else {
- memset(&header, 0, sizeof(struct gfs_meta_header));
- header.mh_magic = GFS_MAGIC;
- header.mh_type = type;
- header.mh_format = format;
-
- gfs_meta_header_out(&header, BH_DATA(bh));
- }
- return 0;
-}
-
-
-
-
-/*
- * check_meta - check the meta header of a buffer
- * @bh: buffer to check
- * @type: meta type (or 0 if don't care)
- *
- * Returns: 0 if ok, -1 on error
- */
-int check_meta(osi_buf_t *bh, int type){
- uint32 check_magic = ((struct gfs_meta_header *)BH_DATA((bh)))->mh_magic;
- uint32 check_metatype = ((struct gfs_meta_header *)BH_DATA((bh)))->mh_type;
-
- check_magic = gfs32_to_cpu(check_magic);
- check_metatype = gfs32_to_cpu(check_metatype);
- if((check_magic != GFS_MAGIC) || (type && (check_metatype != type))){
- log_debug("For %"PRIu64" Expected %X:%X - got %X:%X\n", BH_BLKNO(bh), GFS_MAGIC, type,
- check_magic, check_metatype);
- return -1;
- }
- return 0;
-}
-
-/*
- * check_type - check the meta type of a buffer
- * @bh: buffer to check
- * @type: meta type
- *
- * Returns: 0 if ok, -1 on error
- */
-int check_type(osi_buf_t *bh, int type){
- uint32 check_magic = ((struct gfs_meta_header *)BH_DATA((bh)))->mh_magic;
- uint32 check_metatype = ((struct gfs_meta_header *)BH_DATA((bh)))->mh_type;
-
- check_magic = gfs32_to_cpu(check_magic);
- check_metatype = gfs32_to_cpu(check_metatype);
- if((check_magic != GFS_MAGIC) || (check_metatype != type)){
- return -1;
- }
- return 0;
-}
-
-/**
- * next_rg_meta
- * @rgd:
- * @block:
- * @first: if set, start at zero and ignore block
- *
- * The position to start looking from is *block. When a block
- * is found, it is returned in block.
- *
- * Returns: 0 on success, -1 when finished
- */
-int next_rg_meta(struct gfs_rgrpd *rgd, uint64 *block, int first)
-{
- struct gfs_bitmap *bits = NULL;
- uint32 length = rgd->rd_ri.ri_length;
- uint32 blk = (first)? 0: (uint32)((*block+1)-rgd->rd_ri.ri_data1);
- int i;
-
- if(!first && (*block < rgd->rd_ri.ri_data1)){
- log_err("next_rg_meta: Start block is outside rgrp bounds.\n");
- exit(1);
- }
-
- for(i=0; i < length; i++){
- bits = &rgd->rd_bits[i];
- if(blk < bits->bi_len*GFS_NBBY){
- break;
- }
- blk -= bits->bi_len*GFS_NBBY;
- }
-
-
- for(; i < length; i++){
- bits = &rgd->rd_bits[i];
-
- blk = fs_bitfit((unsigned char *)BH_DATA(rgd->rd_bh[i]) + bits->bi_offset,
- bits->bi_len, blk, GFS_BLKST_USEDMETA);
-
- if(blk != BFITNOENT){
- *block = blk + (bits->bi_start * GFS_NBBY) + rgd->rd_ri.ri_data1;
- break;
- }
-
- blk=0;
- }
-
- if(i == length){
- return -1;
- }
- return 0;
-}
-
-/**
- * next_rg_meta_free - finds free or used metadata
- * @rgd:
- * @block:
- * @first: if set, start at zero and ignore block
- *
- * The position to start looking from is *block. When a block
- * is found, it is returned in block.
- *
- * Returns: 0 on success, -1 when finished
- */
-int next_rg_meta_free(struct gfs_rgrpd *rgd, uint64 *block, int first, int *mfree)
-{
- struct gfs_bitmap *bits = NULL;
- uint32 length = rgd->rd_ri.ri_length;
- uint32 blk = (first)? 0: (uint32)((*block+1)-rgd->rd_ri.ri_data1);
- uint32 ublk, fblk;
- int i;
-
- if(!first && (*block < rgd->rd_ri.ri_data1)){
- log_err("next_rg_meta: Start block is outside rgrp bounds.\n");
- exit(1);
- }
-
- for(i=0; i < length; i++){
- bits = &rgd->rd_bits[i];
- if(blk < bits->bi_len*GFS_NBBY){
- break;
- }
- blk -= bits->bi_len*GFS_NBBY;
- }
-
-
- for(; i < length; i++){
- bits = &rgd->rd_bits[i];
-
- ublk = fs_bitfit((unsigned char *)BH_DATA(rgd->rd_bh[i]) + bits->bi_offset,
- bits->bi_len, blk, GFS_BLKST_USEDMETA);
-
- fblk = fs_bitfit((unsigned char *)BH_DATA(rgd->rd_bh[i]) + bits->bi_offset,
- bits->bi_len, blk, GFS_BLKST_FREEMETA);
- if(ublk < fblk) {
- blk = ublk;
- *mfree = 0;
- } else {
- blk = fblk;
- *mfree = 1;
- }
- if(blk != BFITNOENT){
- *block = blk + (bits->bi_start * GFS_NBBY) + rgd->rd_ri.ri_data1;
- break;
- }
-
- blk=0;
- }
-
- if(i == length){
- return -1;
- }
- return 0;
-}
-
-/**
- * next_rg_metatype
- * @rgd:
- * @block:
- * @type: the type of metadata we're looking for
- * @first: if set we should start at block zero and block is ignored
- *
- * Returns: 0 on success, -1 on error or finished
- */
-int next_rg_metatype(int disk_fd, struct gfs_rgrpd *rgd, uint64 *block,
- uint32 type, int first)
-{
- struct gfs_sbd *sdp = rgd->rd_sbd;
- osi_buf_t *bh=NULL;
-
- do{
- relse_buf(bh);
- if(next_rg_meta(rgd, block, first))
- return -1;
-
- if (get_and_read_buf(disk_fd, sdp->sd_sb.sb_bsize, *block, &bh, 0)){
- log_err("next_rg_metatype: Unable to read meta block "
- "#%"PRIu64" from disk\n", *block);
- exit(1);
- }
-
- if(check_meta(bh,0)){
- log_err("next_rg_metatype: next_rg_meta returned block #%"PRIu64",\n"
- " which is not a valid meta block.\n", *block);
- exit(1);
- }
-
- first = 0;
- } while(check_meta(bh, type));
- relse_buf(bh);
-
- return 0;
-}
diff --git a/gfs/man/Makefile b/gfs/man/Makefile
deleted file mode 100644
index 9047b36..0000000
--- a/gfs/man/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-MANTARGET= \
- gfs.8 \
- mount.gfs.8 \
- gfs_edit.8 \
- fsck.gfs.8 \
- gfs_grow.8 \
- gfs_jadd.8 \
- mkfs.gfs.8 \
- gfs_quota.8 \
- gfs_tool.8
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-all:
-
-clean:
diff --git a/gfs/man/fsck.gfs.8 b/gfs/man/fsck.gfs.8
deleted file mode 100644
index 3dd8b85..0000000
--- a/gfs/man/fsck.gfs.8
+++ /dev/null
@@ -1,59 +0,0 @@
-.TH fsck.gfs 8
-
-.SH NAME
-fsck.gfs - Offline GFS file system checker
-
-.SH SYNOPSIS
-.B fsck.gfs
-[\fIOPTION\fR]... \fIDEVICE\fR
-
-.SH WARNING
-All GFS nodes \fImust\fP have the GFS filesystem unmounted before running
-fsck.gfs. Failure to unmount all nodes may result in filesystem corruption.
-
-.SH DESCRIPTION
-fsck.gfs will check that the GFS file system on a device is structurally valid.
-It should not be run on a mounted file system. If file system corruption is
-detected, it will attempt to repair the file system. There is a limit to what
-fsck.gfs can do. If important file system structures are destroyed, such that
-the checker can not determine what the repairs should be, reparations could
-fail.
-
-GFS is a journaled file system, and as such should be able to repair damages to
-the file system on its own. However, faulty hardware has the ability to write
-incomplete blocks to a file system thereby causing corruption that GFS can not
-fix. The first step to ensuring a healthy file system is the selection of
-reliable hardware (i.e. storage systems that will write complete blocks - even
-in the event of power failure).
-
-.SH OPTIONS
-.TP
-\fB-h\fP
-Help.
-
-This prints out the proper command line usage syntax.
-.TP
-\fB-q\fP
-Quiet.
-.TP
-\fB-n\fP
-No to all questions.
-
-By specifying this option, fsck.gfs will only show the changes that
-would be made, not make any changes to the filesystem.
-.TP
-\fB-V\fP
-Version.
-
-Print out the current version name.
-.TP
-\fB-v\fP
-Verbose operation.
-
-Print more information while running.
-.TP
-\fB-y\fP
-Yes to all questions.
-
-By specifying this option, fsck.gfs will not prompt before making
-changes.
diff --git a/gfs/man/gfs.8 b/gfs/man/gfs.8
deleted file mode 100644
index f3a579e..0000000
--- a/gfs/man/gfs.8
+++ /dev/null
@@ -1,37 +0,0 @@
-.TH gfs 8
-
-.SH NAME
-gfs \- GFS reference guide
-
-.SH SYNOPSIS
-Overview of manpages and their locations
-
-.SH DESCRIPTION
-The GFS documentation has been split into a number of sections. Please
-refer to the table below to determine which man page coincides with the
-command/feature you are looking for.
-.TP 16
-gfs
-GFS overview (this man page)
-.TP
-mount.gfs
-Mounting a GFS file system
-.TP
-fsck.gfs
-The GFS file system checker
-.TP
-gfs_grow
-Growing a GFS file system
-.TP
-gfs_jadd
-Adding a journal to a GFS file system
-.TP
-mkfs.gfs
-Make a GFS file system
-.TP
-gfs_quota
-Manipulate GFS disk quotas
-.TP
-gfs_tool
-Tool to manipulate a GFS file system
-
diff --git a/gfs/man/gfs_edit.8 b/gfs/man/gfs_edit.8
deleted file mode 100644
index 0a53b8b..0000000
--- a/gfs/man/gfs_edit.8
+++ /dev/null
@@ -1 +0,0 @@
-.so man8/gfs2_edit.8
diff --git a/gfs/man/gfs_grow.8 b/gfs/man/gfs_grow.8
deleted file mode 100644
index 5133ec4..0000000
--- a/gfs/man/gfs_grow.8
+++ /dev/null
@@ -1,63 +0,0 @@
-.TH gfs_grow 8
-
-.SH NAME
-gfs_grow - Expand a GFS filesystem
-
-.SH SYNOPSIS
-.B gfs_grow
-[\fIOPTION\fR]... <\fIDEVICE\fR|\fIMOINTPOINT\fR>...
-
-.SH DESCRIPTION
-gfs_grow is used to expand a GFS filesystem after the device
-upon which the filesystem resides has also been expanded. By
-running gfs_grow on a GFS filesystem, you are requesting that
-any spare space between the current end of the filesystem and
-the end of the device is filled with a newly initialized GFS
-filesystem extension. When this operation is complete, the resource
-index for the filesystem is updated so that all nodes in the
-cluster can use the extra storage space which has been added.
-
-You may only run gfs_grow on a mounted filesystem; expansion of
-unmounted filesystems is not supported. You only need to
-run gfs_grow on one node in the cluster. All the other nodes will
-see the expansion has occurred and automatically start to use the
-newly available space.
-
-You must be superuser to execute \fBgfs_grow\fP. The gfs_grow
-tool tries to prevent you from corrupting your filesystem by checking as
-many of the likely problems as it can. When expanding a filesystem,
-only the last step of updating the resource index affects the currently
-mounted filesystem and so failure part way through the expansion process
-should leave your filesystem in its original unexpanded state.
-
-You can run gfs_grow with the \fB-Tv\fP flags to get a display
-of the current state of a mounted GFS filesystem. This can be useful
-to do after the expansion process to see if the changes have been
-successful.
-
-\fBgfs_grow\fP will consume all the remaining space in a device and add
-it to the filesystem. If you want to add journals too, you need to add
-the journals first using \fBgfs_jadd\fP.
-
-.SH OPTIONS
-.TP
-\fB-h\fP
-Prints out a short usage message and exits.
-.TP
-\fB-q\fP
-Quiet. Turns down the verbosity level.
-.TP
-\fB-T\fP
-Test. Do all calculations, but do not write any data to the disk and do
-not expand the filesystem. This is used to discover what the tool would
-have done were it run without this flag. You probably want to turn the
-verbosity level up in order to gain most information from this option.
-.TP
-\fB-V\fP
-Version. Print out version information, then exit.
-.TP
-\fB-v\fP
-Verbose. Turn up verbosity of messages.
-
-.SH SEE ALSO
-mkfs.gfs(8) gfs_jadd(8)
diff --git a/gfs/man/gfs_jadd.8 b/gfs/man/gfs_jadd.8
deleted file mode 100644
index 24804e0..0000000
--- a/gfs/man/gfs_jadd.8
+++ /dev/null
@@ -1,75 +0,0 @@
-.TH gfs_jadd 8
-
-.SH NAME
-gfs_jadd \- Add journals to a GFS filesystem
-
-.SH SYNOPSIS
-.B gfs_jadd
-[\fIOPTION\fR]... <\fIDEVICE\fR|\fIMOINTPOINT\fR>...
-
-.SH DESCRIPTION
-\fIgfs_jadd\fR is used to add journals to a GFS filesystem after
-the device upon which the filesystem resides has been grown.
-By running \fIgfs_jadd\fR
-on a GFS filesystem, you are filling in space between the current end
-of the filesystem and the end of the device upon which the filesystem
-resides. When this operation
-is complete, the journal index is updated so that machines mounting the
-filesystem at a later date will see the newly created journals in
-addition to the journals already there. Machines which are already running
-in the cluster are unaffected.
-
-\fIgfs_jadd\fR will not use space that has been formatted for filesystem data even if that space has never been populated with files.
-
-You may only run \fIgfs_jadd\fR on a mounted filesystem, addition of journals to
-unmounted filesystems is not supported.
-You only need to run \fIgfs_jadd\fR
-on one node in the cluster. All the other nodes will see the expansion
-has occurred when required.
-
-You must be superuser to execute \fIgfs_jadd\fR. The
-\fIgfs_jadd\fR
-tool tries to prevent you from corrupting your filesystem by checking as
-many of the likely problems as it can. When growing a filesystem,
-only the last step of updating the journal index affects the currently
-mounted filesystem and so failure part way through the expansion process
-should leave your filesystem in its original state.
-
-You can run \fIgfs_jadd\fR with the \fI-Tv\fR
-flags to get a display of the current state of a mounted GFS filesystem.
-This can be useful to do after the journal addition process to see if the
-changes have been successful.
-
-.SH OPTIONS
-.TP
-\fB-j num\fP
-The number of new journals to add. This defaults to 1.
-.TP
-\fB-J size\fP
-The size of the new journals in megabytes. The defaults to 128MB (the
-minimum size allowed is 32MB). If you want to add journals of different
-sizes to the filesystem, you'll need to run gfs_jadd once for each
-different size of journal. The size you specify here will be rounded
-down so that it is a multiple of the journal segment size which was
-specified at filesystem creation time.
-.TP
-\fB-h\fP
-Help. Prints out a short usage message and exits.
-.TP
-\fB-q\fP
-Quiet. Turns down the verbosity level.
-.TP
-\fB-T\fP
-Test. Do all calculations, but do not write any data to the disk and do
-not add journals. This is used to discover what the tool would
-have done were it run without this flag. You probably want to turn the
-verbosity level up in order to gain most information from this option.
-.TP
-\fB-V\fP
-Version. Print version information, then exit.
-.TP
-\fB-v\fP
-Verbose. Turn up verbosity of messages.
-
-.SH SEE ALSO
-mkfs.gfs(8) gfs_grow(8)
diff --git a/gfs/man/gfs_quota.8 b/gfs/man/gfs_quota.8
deleted file mode 100644
index bc905ac..0000000
--- a/gfs/man/gfs_quota.8
+++ /dev/null
@@ -1,101 +0,0 @@
-.TH gfs_quota 8
-
-.SH NAME
-gfs_quota - Manipulate GFS disk quotas
-
-.SH SYNOPSIS
-.B gfs_quota
-<list|sync|get|limit|warn|check|init> [\fIOPTION\fR]...
-
-.SH DESCRIPTION
-gfs_quota is used to examine and change quota values in a GFS filesystem.
-This command has a number of different actions.
-
-.SH ACTIONS
-.TP
-\fBlist\fP
-List the contents of the quota file. Only IDs that have a non-zero hard limit,
-warn limit, or value are printed.
-.TP
-\fBsync\fP
-Sync any local quota changes to the quota file.
-.TP
-\fBget\fP
-Get the current data for the ID specified by the -u or -g argument.
-.TP
-\fBlimit\fP
-Set the current hard limit for the ID specified by the -u or -g argument to
-the value specified by the -l argument on the specified filesystem.
-The filesystem won't let the user or group use more than this much space.
-A value of zero here means that no limit is enforced.
-.TP
-\fBwarn\fP
-Set the current warn limit for the ID specified by the -u or -g argument to
-the value specified by the -l argument on the specified filesystem.
-The filesystem will start complaining to the user or group when more
-than this much space is used. A value of zero here means that the
-user won't ever be warned.
-.TP
-\fBcheck\fP
-Scan a filesystem and make sure that what's out there on the disk matches
-what's in the quota file. This is only accurate if the filesystem is
-idle when this is running. If there is a mismatch, it is printed to
-stdout. Note: GFS quotas are transactional and a quota check is \fBnot\fP
-needed every time there is a system crash.
-.TP
-\fBinit\fP
-Scan a filesystem and initialize the quota file with the values obtained
-from the scan. The filesystem should be idle when this is run. You should
-only need to do this if you upgrade a pre-quota GFS filesystem (pre-GFS 5.1).
-
-.SH OPTIONS
-\fB-b\fP
-The units for disk space are filesystem blocks.
-.TP
-\fB-d\fP
-Don't include the space allocated to GFS' hidden files in
-what's reported for the root UID and GID values. This is useful
-if you're trying to get the numbers reported by gfs_quota to match
-up with the numbers reported by du.
-.TP
-\fB-f\fP \fIDirectory\fR
-Specifies which filesystem to perform the action on.
-.TP
-\fB-g\fP \fIGID\fR
-Specifies the group ID for get, limit, or warn. It can be either
-the group name from the group file, or the GID number.
-.TP
-\fB-h\fP
-Print out a help message describing available
-options, then exit.
-.TP
-\fB-k\fP
-The units for disk space are kilobytes.
-.TP
-\fB-l\fP \fISize\fR
-Specifies the new value for the limit or warn actions.
-The value is assumed to be in the units specified by the
--m, -k, -s, -b arguments. The default is megabytes.
-.TP
-\fB-m\fP
-The units for disk space are megabytes. This is the default.
-.TP
-\fB-n\fP
-Don't try to resolve UIDs and GIDs into user and group names.
-.TP
-\fB-s\fP
-The units for disk space are sectors (512-byte blocks).
-.TP
-\fB-u\fP \fIUID\fR
-Specifies the user ID for get, limit, or warn. It can be either
-the username from the password file, or the UID number.
-.TP
-\fB-V\fP
-Print program version information, then exit.
-
-.SH EXAMPLE
-To set the hard limit for user "nobody" to
-1048576 kilobytes on filesystem /gfs0
-
-gfs_quota limit -l 1048576 -k -u nobody -f /gfs0
-
diff --git a/gfs/man/gfs_tool.8 b/gfs/man/gfs_tool.8
deleted file mode 100644
index 7cefdc2..0000000
--- a/gfs/man/gfs_tool.8
+++ /dev/null
@@ -1,145 +0,0 @@
-.TH gfs_tool 8
-
-.SH NAME
-gfs_tool - interface to gfs ioctl calls
-
-.SH SYNOPSIS
-.B gfs_tool
-\fICOMMAND\fR [\fIOPTION\fR] [\fIPARAMETERS ...\fR]
-
-.SH DESCRIPTION
-gfs_tool is an interface to a variety of the GFS ioctl calls.
-.TP
-Specifying gfs_tool -h prints gfs_tool command line usage (help).
-.TP
-Specifying gfs_tool -V prints the gfs_tool version information.
-.SH COMMANDS
-.TP
-\fBclearflag\fP \fIFlag\fR \fIFile1\fR \fIFile2\fR \fI...\fR
-Clear an attribute flag on a file.
-.TP
-\fBcounters\fP \fIMountPoint\fR [-c] [-i \fIinterval\fR]
-Print out statistics about a filesystem. If -c is specified, gfs_tool
-keeps running printing out the statistics once per second or, if
-specified, the interval given with the -i option, in seconds.
-.TP
-\fBdf\fP \fIMountPoint\fR [-k]|[-H]
-Print out a space usage summary of a given filesystem. The information
-printed is more detailed than a standard "df". If -k is specified, the
-output is given in kilobytes (KB). If -H is specified, the output is
-given in human readable format (similar to df -h). If neither -k nor -H
-are specified, the output is given in file system blocks.
-
-.TP
-\fBfreeze\fP \fIMountPoint\fR
-Freeze (quiesce) a GFS cluster.
-.TP
-\fBgetsb\fP \fIMountPoint\fR
-Print out the superblock of a mounted filesystem.
-.TP
-\fBgettune\fP \fIMountPoint\fR
-Print out the current values of the tuning parameters in a running
-filesystem.
-.TP
-\fBjindex\fP \fIMountPoint\fR
-Print out the journal index of a mounted filesystem.
-.TP
-\fBlayout\fP \fIFile\fR \fI[buffersize]\fR
-Print out on-disk layout information about a file or directory.
-Buffersize is the size of the buffer (in bytes) that gfs_tool allocates
-to store the file's metadata during processing. It defaults to 4194304
-bytes. If you are printing a very big directory you may need to specify
-a bigger size.
-.TP
-\fBlist\fP
-List the currently mounted GFS filesystems. Each line represents
-a filesystem. The columns represent (in order): 1) A number that
-is a cookie that represents the mounted filesystem. 2) The name of the
-device that holds the filesystem (well, the name as the Linux
-kernel knows it). 3) The lock table field that the filesystem was
-mounted with.
-.TP
-\fBlockdump\fP \fIMountPoint\fR \fI[buffersize]\fR
-Print out information about the locks this machine holds for a given
-filesystem. Buffersize is the size of the buffer (in bytes) that gfs_tool
-allocates to store the lock data during processing. It defaults to 4194304
-bytes.
-.TP
-\fBmargs\fP \fIarguments\fR
-This loads arguments into the module what will override the mount
-options passed with the -o field on the next mount. See mount.gfs(8).
-.TP
-\fBreclaim\fP \fIFile\fR
-Returns unused on-disk metadata blocks to free blocks.
-.TP
-\fBrindex\fP \fIMountPoint\fR
-Print out the resource group index of a mounted filesystem.
-.TP
-\fBquota\fP \fIMountPoint\fR
-Print out the quota file of a mounted filesystem. Also see
-the "gfs_quota list" command.
-.TP
-\fBsb\fP \fIdevice\fR \fBproto\fP \fI[newvalue]\fR
-View (and possibly replace) the name of the locking protocol in the
-file system superblock. The file system shouldn't be mounted by any
-client when you do this.
-.TP
-\fBsb\fP \fIdevice\fR \fBtable\fP \fI[newvalue]\fR
-View (and possibly replace) the name of the locking table in the
-file system superblock. The file system shouldn't be mounted by any
-client when you do this.
-.TP
-\fBsb\fP \fIdevice\fR \fBondisk\fP \fI[newvalue]\fR
-View (and possibly replace) the ondisk format number in the
-file system superblock. The file system shouldn't be mounted by any
-client when you do this. No one should have to use this.
-.TP
-\fBsb\fP \fIdevice\fR \fBmultihost\fP \fI[newvalue]\fR
-View (and possibly replace) the multihost format number in the
-file system superblock. The file system shouldn't be mounted by any
-client when you do this. No one should have to use this.
-.TP
-\fBsb\fP \fIdevice\fR \fBall\fP
-Print out the superblock.
-.TP
-\fBsetflag\fP \fIFlag\fR \fIFile1\fR \fIFile2\fR \fI...\fR
-Set an attribute flag on a file. There are four currently
-supported flags. They are jdata, directio, inherit_jdata, and
-inherit_directio.
-
-The \fIjdata\fR flag causes all the data written to a regular file
-to be journaled. The jdata flag can only be set (or cleared) if the file
-is zero length.
-
-The \fIdirectio\fR flag causes all I/O to a regular file to be Direct
-I/O, even if the O_DIRECT flag isn't used on the open() command.
-
-The \fIinherit_jdata\fR flag is set on a directory. It causes all new
-regular files created in that directory automatically inherit the
-\fIjdata\fR flag. The \fIinherit_jdata\fR is also inherited by any new
-subdirectories created in that directory.
-
-The \fIinherit_directio\fR flag is set on a directory. It causes all new
-regular files created in that directory automatically inherit the
-\fIdirectio\fR flag. The \fIinherit_directio\fR is also inherited by
-any new subdirectories created in that directory.
-.TP
-\fBsettune\fP \fIMountPoint\fR \fIparameter\fR \fInewvalue\fR
-Set the value of tuning parameter. Use \fBgettune\fP for a listing of
-tunable parameters.
-.TP
-\fBshrink\fP \fIMountPoint\fR
-Causes any unused inodes to be thrown out of memory.
-.TP
-\fBstat\fP \fIFile\fR
-Print out extended stat information about a file.
-.TP
-\fBunfreeze\fP \fIMountPoint\fR
-Unfreeze a GFS cluster.
-.TP
-\fBversion\fP
-Print out the version of GFS that this program goes with.
-.TP
-\fBwithdraw\fP \fIMountPoint\fR
-Cause GFS to abnormally shutdown a given filesystem on this node.
-
diff --git a/gfs/man/mkfs.gfs.8 b/gfs/man/mkfs.gfs.8
deleted file mode 100644
index 9176ea7..0000000
--- a/gfs/man/mkfs.gfs.8
+++ /dev/null
@@ -1,82 +0,0 @@
-.TH mkfs.gfs 8
-
-.SH NAME
-mkfs.gfs - Make a GFS filesystem
-
-.SH SYNOPSIS
-.B mkfs.gfs
-[\fIOPTION\fR]... \fIDEVICE\fR
-
-.SH DESCRIPTION
-mkfs.gfs is used to create a Global File System.
-
-.SH OPTIONS
-.TP
-\fB-b\fP \fIBlockSize\fR
-Set the filesystem block size to \fIBlockSize\fR (must be a power of
-two). The minimum block size is 512. The FS block size cannot exceed
-the machine's memory page size. On the most architectures (i386,
-x86_64, s390, s390x), the memory page size is 4096 bytes. On other
-architectures it may be bigger. The default block size is 4096 bytes.
-In general, GFS filesystems should not deviate from the default value.
-.TP
-\fB-D\fP
-Enable debugging output.
-.TP
-\fB-h\fP
-Print out a help message describing available
-options, then exit.
-.TP
-\fB-J\fP \fIMegaBytes\fR
-The size of the journals in Megabytes. The default journal size is
-128 megabytes. The minimum size is 32 megabytes.
-.TP
-\fB-j\fP \fINumber\fR
-The number of journals for mkfs.gfs to create. You need at least one
-journal per machine that will mount the filesystem.
-.TP
-\fB-O\fP
-This option prevents mkfs.gfs from asking for confirmation before writing
-the filesystem.
-.TP
-\fB-p\fP \fILockProtoName\fR
-LockProtoName is the name of the locking protocol to use. The locking
-protocol should be \fIlock_dlm\fR for a clustered file system or if you
-are using GFS as a local filesystem (\fB1 node only\fP), you can specify the
-\fIlock_nolock\fR protocol.
-.TP
-\fB-q\fP
-Be quiet. Don't print anything.
-.TP
-\fB-r\fP \fIMegaBytes\fR
-mkfs.gfs will try to make Resource Groups (RGs) about this big.
-Minimum RG size is 32 MB. Maximum RG size is 2048 MB.
-A large RG size may increase performance on very large file systems.
-If not specified, mkfs.gfs will choose the RG size based on the size
-of the file system: average size file systems will have 256 MB RGs, and
-bigger file systems will have bigger RGs for better performance.
-.TP
-\fB-s\fP \fIBlocks\fR
-Journal segment size in filesystem blocks. This value must be at
-least two and not large enough to produce a segment size greater than
-4MB.
-.TP
-\fB-t\fP \fILockTableName\fR
-The lock table field appropriate to the lock module you're using.
-It is \fIclustername:fsname\fR.
-Clustername must match that in cluster.conf; only members of this
-cluster are permitted to use this file system.
-Fsname is a unique file system name used to distinguish this GFS file
-system from others created (1 to 16 characters). Lock_nolock doesn't
-use this field.
-.TP
-\fB-V\fP
-Print program version information, then exit.
-
-.SH EXAMPLE
-.TP
-mkfs.gfs -t mycluster:mygfs -p lock_dlm -j 2 /dev/vg0/mygfs
-This will make a Global File System on the block device
-"/dev/vg0/mygfs". It will belong to "mycluster" and register itself
-as wanting locking for "mygfs". It will use DLM for locking and make
-two journals.
diff --git a/gfs/man/mount.gfs.8 b/gfs/man/mount.gfs.8
deleted file mode 100644
index 5975c13..0000000
--- a/gfs/man/mount.gfs.8
+++ /dev/null
@@ -1,193 +0,0 @@
-.TH mount.gfs 8
-
-.SH NAME
-mount.gfs - GFS mount options
-
-.SH SYNOPSIS
-.B mount
-[\fIStandardMountOptions\fR] \fB-t\fP gfs \fIDEVICE\fR \fIMOUNTPOINT\fR \fB-o\fP [GFSOption1,GFSOption2,GFSOptionX...]
-
-.SH DESCRIPTION
-GFS may be used as a local (single computer) filesystem, but its real purpose
-is in clusters, where multiple computers (nodes) share a common storage device.
-
-Above is the format typically used to mount a GFS filesystem, using the
-\fBmount\fP(8) command. The \fIdevice\fR may be any block device on which you
-have created a GFS filesystem. Examples include a
-single disk partition (e.g. /dev/sdb3), a loopback device, a device exported
-from another node (e.g. an iSCSI device or a \fBgnbd\fP(8) device), or a
-logical volume (typically comprised of a number of individual disks).
-
-\fIdevice\fR does not necessarily need to match the device name as seen on
-another node in the cluster, nor does it need to be a logical volume. However,
-the use of a cluster-aware volume manager such as CLVM2 (see \fBlvm\fP(8))
-will guarantee that the managed devices are named identically on each node in a
-cluster (for much easier management), and will allow you to configure a very
-large volume from multiple storage units (e.g. disk drives).
-
-\fIdevice\fR must make the entire filesystem storage area visible to the
-computer. That is, you cannot mount different parts of a single filesystem on
-different computers. Each computer must see an entire filesystem. You
-may, however, mount several GFS filesystems if you want to distribute your
-data storage in a controllable way.
-
-\fImountpoint\fR is the same as \fIdir\fR in the \fBmount\fP(8) man page.
-
-This man page describes GFS-specific options that can be passed to the GFS
-file system at mount time, using the \fB-o\fP flag. There are many other
-\fB-o\fP options handled by the generic mount command \fBmount\fP(8).
-However, the options described below are specifically for GFS, and are not
-interpreted by the mount command nor by the kernel's Virtual File System. GFS
-and non-GFS options may be intermingled after the \fB-o\fP, separated by
-commas (but no spaces).
-
-As an alternative to mount command line options, you may send mount
-options to gfs using "gfs_tool margs" (after loading the gfs kernel
-module, but before mounting GFS). For example, you may need to do
-this when working from an initial ramdisk \fBinitrd\fP(4). The
-options are restricted to the ones described on this man page (no
-general \fBmount\fP(8) options will be recognized), must not be
-preceded by -o, and must be separated by commas (no spaces). Example:
-
-# gfs_tool margs "lockproto=lock_nolock,ignore_local_fs"
-
-Options loaded via "gfs_tool margs" have a lifetime of only one GFS
-mount. If you wish to mount another GFS filesystem, you must set
-another group of options with "gfs_tool margs".
-
-If you have trouble mounting GFS, check the syslog (e.g. /var/log/messages)
-for specific error messages.
-
-.SH OPTIONS
-.TP
-\fBlockproto=\fP\fILockModuleName\fR
-This specifies which inter-node lock protocol is used by the GFS filesystem
-for this mount, overriding the default lock protocol name stored in the
-filesystem's on-disk superblock.
-
-The \fILockModuleName\fR must be an exact match of the protocol name presented
-by the lock module when it registers with the lock harness. Traditionally,
-this matches the .o filename of the lock module, e.g. \fIlock_dlm\fR,
-or \fIlock_nolock\fR.
-
-The default lock protocol name is written to disk initially when creating the
-filesystem with \fBmkfs.gfs\fP(8), -p option. It can be changed on-disk by
-using the \fBgfs_tool\fP(8) utility's \fBsb proto\fP command.
-
-The \fBlockproto\fP mount option should be used only under special
-circumstances in which you want to temporarily use a different lock protocol
-without changing the on-disk default.
-.TP
-\fBlocktable=\fP\fILockTableName\fR
-This specifies the identity of the cluster and of the filesystem for this
-mount, overriding the default cluster/filesystem identify stored in the
-filesystem's on-disk superblock. The cluster/filesystem name is recognized
-globally throughout the cluster, and establishes a unique namespace for
-the inter-node locking system, enabling the mounting of multiple GFS
-filesystems.
-
-The format of \fILockTableName\fR is lock-module-specific. For
-lock_dlm, the format is \fIclustername:fsname\fR. For
-lock_nolock, the field is ignored.
-
-The default cluster/filesystem name is written to disk initially when creating
-the filesystem with \fBmkfs.gfs\fP(8), -t option. It can be changed on-disk
-by using the \fBgfs_tool\fP(8) utility's \fBsb table\fP command.
-
-The \fBlocktable\fP mount option should be used only under special
-circumstances in which you want to mount the filesystem in a different cluster,
-or mount it as a different filesystem name, without changing the on-disk
-default.
-.TP
-\fBlocalcaching\fP
-This flag tells GFS that it is running as a local (not clustered) filesystem,
-so it can turn on some block caching optimizations that can't be used when
-running in cluster mode.
-
-This is turned on automatically by the lock_nolock module,
-but can be overridden by using the \fBignore_local_fs\fP option.
-.TP
-\fBlocalflocks\fP
-This flag tells GFS that it is running as a local (not clustered) filesystem,
-so it can allow the kernel VFS layer to do all flock and fcntl file locking.
-When running in cluster mode, these file locks require inter-node locks,
-and require the support of GFS. When running locally, better performance
-is achieved by letting VFS handle the whole job.
-
-This is turned on automatically by the lock_nolock module,
-but can be overridden by using the \fBignore_local_fs\fP option.
-.TP
-\fBoopses_ok\fP
-Normally, GFS automatically turns on the "kernel.panic_on_oops"
-sysctl to cause the machine to panic if an oops (an in-kernel
-segfault or GFS assertion failure) happens. An oops on one machine of
-a cluster filesystem can cause the filesystem to stall on all machines
-in the cluster. (Panics don't have this "feature".) By turning on
-"panic_on_oops", GFS tries to make sure the cluster remains in
-operation even if one machine has a problem. There are cases,
-however, where this behavior is not desirable -- debugging being
-the main one. The \fBoopses_ok\fP option causes GFS to leave the
-"panic_on_oops" variable alone so oopses can happen. Use this option
-with care.
-
-This is turned on automatically by the lock_nolock module,
-but can be overridden by using the \fBignore_local_fs\fP option.
-.TP
-\fBignore_local_fs\fP
-By default, using the nolock lock module automatically turns on the
-\fBlocalcaching\fP and \fBlocalflocks\fP optimizations. \fBignore_local_fs\fP
-forces GFS to treat the filesystem as if it were a multihost (clustered)
-filesystem, with \fBlocalcaching\fP and \fBlocalflocks\fP optimizations
-turned off.
-.TP
-\fBupgrade\fP
-This flag tells GFS to upgrade the filesystem's on-disk format to the version
-supported by the current GFS software installation on this computer.
-If you try to mount an old-version disk image, GFS will notify you via a syslog
-message that you need to upgrade. Try mounting again, using the
-\fB-o upgrade\fP option. When upgrading, only one node may mount the GFS
-filesystem.
-.TP
-\fBnum_glockd\fP
-Tunes GFS to alleviate memory pressure when rapidly acquiring many locks (e.g.
-several processes scanning through huge directory trees). GFS' glockd kernel
-daemon cleans up memory for no-longer-needed glocks. Multiple instances
-of the daemon clean up faster than a single instance. The default value is
-one daemon, with a maximum of 32. Since this option was introduced, other
-methods of rapid cleanup have been developed within GFS, so this option may go
-away in the future.
-.TP
-\fBacl\fP
-Enables POSIX Access Control List \fBacl\fP(5) support within GFS.
-.TP
-\fBspectator\fP
-Mount this filesystem using a special form of read-only mount. The mount
-does not use one of the filesystem's journals.
-.TP
-\fBsuiddir\fP
-Sets owner of any newly created file or directory to be that of parent
-directory, if parent directory has S_ISUID permission attribute bit set.
-Sets S_ISUID in any new directory, if its parent directory's S_ISUID is set.
-Strips all execution bits on a new file, if parent directory owner is different
-from owner of process creating the file. Set this option only if you know
-why you are setting it.
-
-.SH LINKS
-.TP 30
-http://sources.redhat.com/cluster
--- home site of GFS
-.TP
-http://www.suse.de/~agruen/acl/linux-acls/
--- good writeup on ACL support in Linux
-
-.SH SEE ALSO
-
-\fBgfs\fP(8),
-\fBmount\fP(8) for general mount options,
-\fBchmod\fP(1) and \fBchmod\fP(2) for access permission flags,
-\fBacl\fP(5) for access control lists,
-\fBlvm\fP(8) for volume management,
-\fBccs\fP(7) for cluster management,
-\fBumount\fP(8),
-\fBinitrd\fP(4).
-
diff --git a/gfs/tests/Makefile b/gfs/tests/Makefile
deleted file mode 100644
index 5b2e7c0..0000000
--- a/gfs/tests/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-include ../make/defines.mk
-include $(OBJDIR)/make/passthrough.mk
-
-SUBDIRS=filecon2 mmdd
diff --git a/gfs/tests/filecon2/Makefile b/gfs/tests/filecon2/Makefile
deleted file mode 100644
index d443a70..0000000
--- a/gfs/tests/filecon2/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-TARGETS= filecon2_server filecon2_client
-
-all: $(TARGETS)
-
-include ../../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-
-CFLAGS += -O3
-CFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
-CFLAGS += -I../../include
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L${libdir}
-
-%: %.o
- $(CC) -o $@ $^ $(LDFLAGS)
-
-clean: generalclean
diff --git a/gfs/tests/filecon2/filecon2.h b/gfs/tests/filecon2/filecon2.h
deleted file mode 100644
index 96e03b7..0000000
--- a/gfs/tests/filecon2/filecon2.h
+++ /dev/null
@@ -1,146 +0,0 @@
-#ifndef __FILECON2_DOT_H__
-#define __FILECON2_DOT_H__
-
-
-
-/* Extern Macro */
-
-#ifndef EXTERN
-#define EXTERN extern
-#define INIT(X)
-#else
-#undef EXTERN
-#define EXTERN
-#define INIT(X) =X
-#endif
-
-
-
-#define die(fmt, args...) \
-do \
-{ \
- fprintf(stderr, "%s: ", prog_name); \
- fprintf(stderr, fmt, ##args); \
- exit(EXIT_FAILURE); \
-} \
-while (0)
-
-#define type_zalloc(ptr, type, count) \
-do \
-{ \
- (ptr) = (type *)malloc(sizeof(type) * (count)); \
- if ((ptr)) \
- memset((char *)(ptr), 0, sizeof(type) * (count)); \
- else \
- die("unable to allocate memory on line %d of file %s\n", \
- __LINE__, __FILE__); \
-} \
-while (0)
-
-#define type_alloc(ptr, type, count) \
-do \
-{ \
- (ptr) = (type *)malloc(sizeof(type) * (count)); \
- if (!(ptr)) \
- die("unable to allocate memory on line %d of file %s\n", \
- __LINE__, __FILE__); \
-} \
-while (0)
-
-#define do_lseek(fd, off) \
-do \
-{ \
- if (lseek((fd), (off), SEEK_SET) != (off)) \
- die("bad seek: %s on line %d of file %s\n", \
- strerror(errno),__LINE__, __FILE__); \
-} \
-while (0)
-
-#define do_read(fd, buf, len) \
-do \
-{ \
- int do_read_out; \
- do_read_out = read((fd), (buf), (len)); \
- if (do_read_out != (len)) \
- die("bad read: result = %d (%s) on line %d of file %s\n", \
- do_read_out, strerror(errno), __LINE__, __FILE__); \
-} \
-while (0)
-
-#define do_write(fd, buf, len) \
-do \
-{ \
- int do_write_out; \
- do_write_out = write((fd), (buf), (len)); \
- if (do_write_out != (len)) \
- die("bad write: result = %d (%s) on line %d of file %s\n", \
- do_write_out, strerror(errno), __LINE__, __FILE__); \
-} \
-while (0)
-
-#define do_ftruncate(fd, off) \
-do \
-{ \
- if (ftruncate((fd), (off)) < 0) \
- die("bad truncate: %s on line %d of file %s\n", \
- strerror(errno), __LINE__, __FILE__); \
-} \
-while (0)
-
-#define RAND(x) ((x) * (random() / (RAND_MAX + 1.0)))
-
-#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
-
-
-
-#define FILECON2_PORT (12046)
-#define FILECON2_MAGIC (0x76543210)
-
-#define FCR_READ_BUFFERED (16241)
-#define FCR_READ_DIRECT (16242)
-#define FCR_READ_MMAPPED (16243)
-#define FCR_WRITE_BUFFERED (16244)
-#define FCR_WRITE_DIRECT (16245)
-#define FCR_WRITE_MMAPPED (16246)
-#define FCR_TRUNC (16247)
-#define FCR_NOP (16248)
-#define FCR_SEED (16249)
-#define FCR_STOP (16250)
-
-struct filecon2_request
-{
- uint32 magic;
- uint32 type;
- uint32 length;
- uint32 data;
- uint64 offset;
-};
-typedef struct filecon2_request filecon2_request_t;
-
-static __inline__ void request_in(filecon2_request_t *req, char *buf)
-{
- filecon2_request_t *str = (filecon2_request_t *)buf;
- req->magic = be32_to_cpu(str->magic);
- req->type = be32_to_cpu(str->type);
- req->length = be32_to_cpu(str->length);
- req->data = be32_to_cpu(str->data);
- req->offset = be64_to_cpu(str->offset);
-}
-
-static __inline__ void request_out(filecon2_request_t *req, char *buf)
-{
- filecon2_request_t *str = (filecon2_request_t *)buf;
- str->magic = cpu_to_be32(req->magic);
- str->type = cpu_to_be32(req->type);
- str->length = cpu_to_be32(req->length);
- str->data = cpu_to_be32(req->data);
- str->offset = cpu_to_be64(req->offset);
-}
-
-
-EXTERN char *prog_name;
-EXTERN pid_t pid;
-
-
-#endif /* __FILECON2_DOT_H__ */
-
diff --git a/gfs/tests/filecon2/filecon2_client.c b/gfs/tests/filecon2/filecon2_client.c
deleted file mode 100644
index a2196c6..0000000
--- a/gfs/tests/filecon2/filecon2_client.c
+++ /dev/null
@@ -1,841 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
-#include "global.h"
-#include "linux_endian.h"
-#define EXTERN
-#include "filecon2.h"
-
-
-
-#ifndef O_DIRECT
-#define O_DIRECT (0)
-#warning O_DIRECT is broken
-#endif
-#ifndef PAGE_SIZE
-#define PAGE_SIZE (65536)
-#endif
-
-#define CHANCES (8)
-
-#define PATTERN_RAND (12341)
-#define PATTERN_OPNUM (12342)
-
-
-
-struct operation
-{
- char *name;
- void (*func)();
-};
-typedef struct operation operation_t;
-
-
-
-unsigned int port = FILECON2_PORT;
-unsigned int seed = 0;
-uint64 offset = 0;
-uint64 length = 1048576;
-uint32 chunk = 1024;
-unsigned int pattern = PATTERN_RAND;
-int buffered = FALSE;
-int direct = FALSE;
-int mmapped = FALSE;
-int trunc = FALSE;
-int nop = FALSE;
-unsigned int align = 1;
-int reread = FALSE;
-int respect_eof = FALSE;
-int check_file_size = FALSE;
-int verbose = FALSE;
-char *servername = NULL;
-char *filename = NULL;
-
-int user_seed = FALSE;
-int fd_b = -1, fd_d = -1;
-int sock;
-
-int first = FALSE;
-unsigned char *mmap_data = NULL;
-
-uint64 file_size;
-unsigned int opnum;
-
-float chances[CHANCES];
-
-
-
-
-
-void rand_extent(uint64 *o, uint32 *l)
-{
- uint64 off;
- uint32 len;
-
- if (align > 1)
- {
- do
- {
- off = RAND(length / align);
- len = RAND(chunk / align) + 1;
- off *= align;
- len *= align;
- }
- while (off + len > length);
- }
- else
- {
- do
- {
- off = RAND(length);
- len = RAND(chunk) + 1;
- }
- while (off + len > length);
- }
-
- *o = off;
- *l = len;
-}
-
-
-void fill_pattern(unsigned char *data, unsigned int len)
-{
- unsigned int x;
-
- switch (pattern)
- {
- case PATTERN_RAND:
- while (len--)
- *data++ = RAND(256);
- break;
-
- case PATTERN_OPNUM:
- x = cpu_to_be32(opnum);
- while (len)
- {
- if (len > sizeof(unsigned int))
- {
- memcpy(data, &x, sizeof(unsigned int));
- data += sizeof(unsigned int);
- len -= sizeof(unsigned int);
- }
- else
- {
- memcpy(data, &x, len);
- break;
- }
- }
- break;
-
- default:
- die("unknown pattern\n");
- }
-}
-
-
-void do_first()
-{
- filecon2_request_t req;
- unsigned char data[sizeof(filecon2_request_t) + 1];
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.type = FCR_WRITE_BUFFERED;
- req.length = 1;
- req.data = 1;
- req.offset = offset + length - 1;
-
- fill_pattern(data + sizeof(filecon2_request_t), 1);
-
- do_lseek(fd_b, offset + length - 1);
- do_write(fd_b, data + sizeof(filecon2_request_t), 1);
-
- request_out(&req, data);
- do_write(sock, data, sizeof(filecon2_request_t) + 1);
-
- mmap_data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd_b, offset);
- if (mmap_data == MAP_FAILED)
- die("can't mmap file: %s\n", strerror(errno));
-
- first = FALSE;
-}
-
-
-void do_check_file_size()
-{
- struct stat st;
- int error;
-
- error = fstat(fd_b, &st);
- if (error)
- die("can't stat file: %s\n", strerror(errno));
-
- if (file_size != st.st_size)
- die("file size mismatch (server = %"PRIu64", me = %"PRIu64")\n",
- file_size, st.st_size);
-}
-
-
-void op_buffered_read()
-{
- filecon2_request_t req;
- uint64 off;
- uint32 len;
- unsigned char *data;
- int error;
-
- rand_extent(&off, &len);
- off += offset;
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.type = FCR_READ_BUFFERED;
- req.length = len;
- req.data = len;
- req.offset = off;
-
- type_alloc(data, char, sizeof(filecon2_request_t) + len);
-
- do_lseek(fd_b, off);
- error = read(fd_b, data + sizeof(filecon2_request_t), len);
- if (error < 0)
- die("error reading from file: %s\n", strerror(errno));
- req.data = error;
-
- request_out(&req, data);
- do_write(sock, data, sizeof(filecon2_request_t) + req.data);
-
- free(data);
-}
-
-
-void op_buffered_write()
-{
- filecon2_request_t req;
- uint64 off;
- uint32 len;
- unsigned char *data;
-
- rand_extent(&off, &len);
- off += offset;
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.type = FCR_WRITE_BUFFERED;
- req.length = len;
- req.data = len;
- req.offset = off;
-
- type_alloc(data, char, sizeof(filecon2_request_t) + len);
-
- fill_pattern(data + sizeof(filecon2_request_t), len);
-
- do_lseek(fd_b, off);
- do_write(fd_b, data + sizeof(filecon2_request_t), len);
-
- if (reread)
- {
- unsigned char *data_reread;
-
- type_alloc(data_reread, char, len);
-
- do_lseek(fd_b, off);
- do_read(fd_b, data_reread, len);
-
- if (memcmp(data + sizeof(filecon2_request_t), data_reread, len) != 0)
- die("buffered write: bad reread\n");
-
- free(data_reread);
- }
-
- request_out(&req, data);
- do_write(sock, data, sizeof(filecon2_request_t) + req.data);
-
- free(data);
-}
-
-
-void op_direct_read()
-{
- filecon2_request_t req;
- uint64 off;
- uint32 len;
- unsigned char *data, *data_orig;
- unsigned int remainder;
- int error;
-
- if (respect_eof)
- {
- if (file_size < offset + align)
- {
- off = offset;
- len = 0;
- }
- else
- for (;;)
- {
- rand_extent(&off, &len);
- off += offset;
- if (off + len <= file_size)
- break;
- }
- }
- else
- {
- rand_extent(&off, &len);
- off += offset;
- }
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.type = FCR_READ_DIRECT;
- req.length = len;
- req.data = len;
- req.offset = off;
-
- data = data_orig = malloc(sizeof(filecon2_request_t) + len + PAGE_SIZE);
- if (!data)
- die("out of memory\n");
- remainder = ((unsigned long)(data + sizeof(filecon2_request_t))) & (PAGE_SIZE - 1);
- if (remainder)
- data += PAGE_SIZE - remainder;
-
- do_lseek(fd_d, off);
- error = read(fd_d, data + sizeof(filecon2_request_t), len);
- if (error < 0)
- die("error reading from file: %s\n", strerror(errno));
- req.data = error;
-
- request_out(&req, data);
- do_write(sock, data, sizeof(filecon2_request_t) + req.data);
-
- free(data_orig);
-}
-
-
-void op_direct_write()
-{
- filecon2_request_t req;
- uint64 off;
- uint32 len;
- unsigned char *data, *data_orig;
- unsigned int remainder;
-
- rand_extent(&off, &len);
- off += offset;
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.type = FCR_WRITE_DIRECT;
- req.length = len;
- req.data = len;
- req.offset = off;
-
- data = data_orig = malloc(sizeof(filecon2_request_t) + len + PAGE_SIZE);
- if (!data)
- die("out of memory\n");
- remainder = ((unsigned long)(data + sizeof(filecon2_request_t))) & (PAGE_SIZE - 1);
- if (remainder)
- data += PAGE_SIZE - remainder;
-
- fill_pattern(data + sizeof(filecon2_request_t), len);
-
- do_lseek(fd_d, off);
- do_write(fd_d, data + sizeof(filecon2_request_t), len);
-
- if (reread)
- {
- unsigned char *data_reread, *data_reread_orig;
-
- data_reread = data_reread_orig = malloc(len + PAGE_SIZE);
- if (!data_reread)
- die("out of memory\n");
- remainder = ((unsigned long)data_reread) & (PAGE_SIZE - 1);
- if (remainder)
- data_reread += PAGE_SIZE - remainder;
-
- do_lseek(fd_d, off);
- do_read(fd_d, data_reread, len);
-
- if (memcmp(data + sizeof(filecon2_request_t), data_reread, len) != 0)
- die("direct write: bad reread\n");
-
- free(data_reread_orig);
- }
-
- request_out(&req, data);
- do_write(sock, data, sizeof(filecon2_request_t) + req.data);
-
- free(data_orig);
-}
-
-
-void op_mmapped_read()
-{
- filecon2_request_t req;
- uint64 off;
- uint32 len;
- unsigned char *data;
-
- rand_extent(&off, &len);
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.type = FCR_READ_MMAPPED;
- req.length = len;
- req.data = len;
- req.offset = offset + off;
-
- type_alloc(data, char, sizeof(filecon2_request_t) + len);
-
- memcpy(data + sizeof(filecon2_request_t), mmap_data + off, len);
-
- request_out(&req, data);
- do_write(sock, data, sizeof(filecon2_request_t) + req.data);
-
- free(data);
-}
-
-
-void op_mmapped_write()
-{
- filecon2_request_t req;
- uint64 off;
- uint32 len;
- unsigned char *data;
-
- rand_extent(&off, &len);
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.type = FCR_WRITE_MMAPPED;
- req.length = len;
- req.data = len;
- req.offset = offset + off;
-
- type_alloc(data, char, sizeof(filecon2_request_t) + len);
-
- fill_pattern(data + sizeof(filecon2_request_t), len);
-
- memcpy(mmap_data + off, data + sizeof(filecon2_request_t), len);
-
- if (reread)
- {
- if (memcmp(mmap_data + off, data + sizeof(filecon2_request_t), len) != 0)
- die("mmapped write: bad reread\n");
- }
-
- request_out(&req, data);
- do_write(sock, data, sizeof(filecon2_request_t) + req.data);
-
- free(data);
-}
-
-
-void op_trunc()
-{
- filecon2_request_t req;
- uint64 off;
- unsigned char data[sizeof(filecon2_request_t)];
-
- if (align > 1)
- {
- off = RAND((length / align) + 1);
- off *= align;
- }
- else
- off = RAND(length + 1);
-
- off += offset;
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.type = FCR_TRUNC;
- req.offset = off;
-
- do_ftruncate(fd_b, off);
-
- request_out(&req, data);
- do_write(sock, data, sizeof(filecon2_request_t));
-}
-
-
-void op_nop()
-{
- filecon2_request_t req;
- unsigned char data[sizeof(filecon2_request_t)];
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.type = FCR_NOP;
-
- request_out(&req, data);
- do_write(sock, data, sizeof(filecon2_request_t));
-}
-
-
-const static operation_t ops[] =
-{
- { "buffered read", op_buffered_read },
- { "buffered write", op_buffered_write },
- { "direct read", op_direct_read },
- { "direct write", op_direct_write },
- { "mmapped read", op_mmapped_read },
- { "mmapped write", op_mmapped_write },
- { "truncate", op_trunc },
- { "nop", op_nop },
-};
-
-
-int do_op()
-{
- filecon2_request_t req;
- unsigned char buf[sizeof(filecon2_request_t)];
- float c, x = 0.0;
- unsigned int op;
-
-
- do_read(sock, buf, sizeof(filecon2_request_t));
- request_in(&req, buf);
-
- if (req.magic != FILECON2_MAGIC)
- die("magic number mismatch\n");
- if (req.type == FCR_STOP)
- return FALSE;
- if (req.type)
- die("strange message from server\n");
-
- file_size = req.offset;
- opnum = req.length;
-
-
- if (first)
- {
- do_first();
- return TRUE;
- }
- else if (check_file_size)
- do_check_file_size();
-
-
- for (;;)
- {
- op = 0;
- c = RAND(1);
-
- for (;;)
- {
- if (chances[op])
- {
- x += chances[op];
- if (x > c)
- {
- ops[op].func();
- return TRUE;
- }
- }
-
- op++;
- if (op == CHANCES)
- break;
- }
- }
-
-
- die("D'oh!\n");
-}
-
-
-void compute_chances()
-{
- unsigned int x;
- float sum = 0.0;
-
- for (x = 0; x < CHANCES; x++)
- chances[x] = 0.0;
-
- if (buffered)
- {
- chances[0] = 1.0;
- chances[1] = 1.0;
- }
- if (direct)
- {
- chances[2] = 1.0;
- chances[3] = 1.0;
- }
- if (mmapped)
- {
- chances[4] = 1.0;
- chances[5] = 1.0;
- }
- if (trunc)
- chances[6] = 0.1;
- if (nop)
- chances[7] = 0.1;
-
- for (x = 0; x < CHANCES; x++)
- sum += chances[x];
-
- for (x = 0; x < CHANCES; x++)
- chances[x] /= sum;
-}
-
-
-void do_seed()
-{
- filecon2_request_t req;
- unsigned char buf[sizeof(filecon2_request_t)];
-
- do_read(sock, buf, sizeof(filecon2_request_t));
- request_in(&req, buf);
-
- if (req.magic != FILECON2_MAGIC)
- die("magic number mismatch\n");
- if (req.type != FCR_SEED)
- die("strange message from server\n");
-
- if (!user_seed)
- seed = req.length;
-
- if (verbose)
- printf("\nseed = %u\n", seed);
-
- srandom(seed);
-}
-
-
-int main(int argc, char *argv[])
-{
- int optchar, cont = TRUE;
- struct hostent *hname;
- struct sockaddr_in sin;
- unsigned int x;
- int error;
-
-
- prog_name = argv[0];
- pid = getpid();
-
-
- if (argc < 3)
- {
- fprintf(stderr, "%s usage:\n\n", prog_name);
- fprintf(stderr, "%s -p <port> -s <seed> -o <offset> -l <length> -c <chunksize> -f <pattern> -b -d -m -t -n -a <align> -r -e -x -v server file\n\n", prog_name);
- fprintf(stderr, " -p <port> Port to connect to\n");
- fprintf(stderr, " -s <seed> Seed for the random number generator\n");
- fprintf(stderr, " -o <offset> The start of the active region in bytes\n");
- fprintf(stderr, " -l <length> The length of the active region in bytes\n");
- fprintf(stderr, " -c <chunksize> Read/Write up to this amount in one I/O\n");
- fprintf(stderr, " -f <pattern> Do writes with this pattern (rand, opnum)\n");
- fprintf(stderr, " -b Do buffered I/O\n");
- fprintf(stderr, " -d Do direct I/O\n");
- fprintf(stderr, " -m Do memory mapped I/O\n");
- fprintf(stderr, " -t Do truncates\n");
- fprintf(stderr, " -n Do nops\n");
- fprintf(stderr, " -a <align> I/O should be aligned to multiples of this value\n");
- fprintf(stderr, " -r Reread writes\n");
- fprintf(stderr, " -e Don't try to read past the EOF when doing Direct I/O\n");
- fprintf(stderr, " -x Always check to make sure the file's size is correct\n");
- fprintf(stderr, " -v Be verbose\n");
- exit(EXIT_FAILURE);
- }
-
- while (cont)
- {
- optchar = getopt(argc, argv, "p:s:o:l:c:f:bdmtna:rexv");
- switch (optchar)
- {
- case 'p':
- sscanf(optarg, "%u", &port);
- break;
- case 's':
- sscanf(optarg, "%u", &seed);
- user_seed = TRUE;
- break;
- case 'o':
- sscanf(optarg, "%"SCNu64"", &offset);
- break;
- case 'l':
- sscanf(optarg, "%"SCNu64"", &length);
- break;
- case 'c':
- sscanf(optarg, "%u", &chunk);
- break;
- case 'f':
- if (strcmp(optarg, "rand") == 0)
- pattern = PATTERN_RAND;
- else if (strcmp(optarg, "opnum") == 0)
- pattern = PATTERN_OPNUM;
- else
- die("unknown pattern %s\n", optarg);
- break;
- case 'b':
- buffered = TRUE;
- break;
- case 'd':
- direct = TRUE;
- break;
- case 'm':
- mmapped = TRUE;
- break;
- case 't':
- trunc = TRUE;
- break;
- case 'n':
- nop = TRUE;
- break;
- case 'a':
- sscanf(optarg, "%u", &align);
- break;
- case 'r':
- reread = TRUE;
- break;
- case 'e':
- respect_eof = TRUE;
- break;
- case 'x':
- check_file_size = TRUE;
- break;
- case 'v':
- verbose = TRUE;
- break;
- case EOF:
- cont = FALSE;
- break;
- default:
- die("bad argument\n");
- }
- }
-
- if (optind < argc)
- servername = argv[optind++];
- else
- die("no servername\n");
-
- if (optind < argc)
- filename = argv[optind++];
- else
- die("no filename\n");
-
- if (port >= 65536)
- die("invalid port number: %u\n", port);
-
- if (align > chunk || chunk > length)
- die("bad sizes, should be: -a <= -c < = -l\n");
-
- if (offset % align)
- die("offset not aligned\n");
-
- if (mmapped)
- {
- if (trunc)
- die("can't do both -m and -t\n");
- first = TRUE;
- }
-
-
- compute_chances();
-
-
- if (verbose)
- {
- printf("port = %u\n", port);
- if (user_seed)
- printf("seed = %u\n", seed);
- else
- printf("seed = <ProvidedByServer>\n");
- printf("offset = %"PRIu64"\n", offset);
- printf("length = %"PRIu64"\n", length);
- printf("chunk = %u\n", chunk);
- switch (pattern)
- {
- case PATTERN_RAND:
- printf("pattern = rand\n");
- break;
- case PATTERN_OPNUM:
- printf("pattern = opnum\n");
- break;
- default:
- printf("pattern = unknown\n");
- break;
- }
- printf("buffered = %d\n", buffered);
- printf("direct = %d\n", direct);
- printf("mmapped = %d\n", mmapped);
- printf("trunc = %d\n", trunc);
- printf("nop = %d\n", nop);
- printf("align = %u\n", align);
- printf("reread = %d\n", reread);
- printf("respect_eof = %d\n", respect_eof);
- printf("check_file_size = %d\n", check_file_size);
- printf("verbose = %d\n", verbose);
- printf("servername = %s\n", servername);
- printf("filename = %s\n", filename);
-
- printf("\n");
- for (x = 0; x < CHANCES; x++)
- printf("%s %f\n", ops[x].name, chances[x]);
- }
-
-
- fd_b = open(filename, O_RDWR);
- if (fd_b < 0)
- die("can't open file %s: %s\n", filename, strerror(errno));
-
- if (direct)
- {
- fd_d = open(filename, O_RDWR | O_DIRECT);
- if (fd_d < 0)
- die("can't open file %s: %s\n", filename, strerror(errno));
- }
-
-
- hname = gethostbyname(servername);
- if (!hname)
- die("can't resolve host %s: %s\n", servername, strerror(errno));
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock < 0)
- die("can't open socket: %s\n", strerror(errno));
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = *((uint32 *)*(hname->h_addr_list));
- sin.sin_port = cpu_to_be16(port);
-
- error = connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
- if (error < 0)
- die("can't connect to host %s (%u): %s\n", servername, port, strerror(errno));
-
-
- do_seed();
-
-
- while (do_op()) /* Do nothing */;
-
-
- close(sock);
- if (direct)
- close(fd_d);
- if (mmap_data)
- munmap(mmap_data, length);
- close(fd_b);
-
-
- exit(EXIT_SUCCESS);
-}
-
-
-
diff --git a/gfs/tests/filecon2/filecon2_server.c b/gfs/tests/filecon2/filecon2_server.c
deleted file mode 100644
index bc59124..0000000
--- a/gfs/tests/filecon2/filecon2_server.c
+++ /dev/null
@@ -1,597 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
-#include "global.h"
-#include "osi_list.h"
-#include "linux_endian.h"
-#define EXTERN
-#include "filecon2.h"
-
-
-
-struct log
-{
- osi_list_t list;
- unsigned int cli;
- filecon2_request_t req;
-};
-typedef struct log log_t;
-
-
-
-int fd = -1;
-unsigned int clients = 0;
-struct sockaddr_in *ssin = NULL;
-int *sock = NULL;
-unsigned int t = 0;
-
-int log = FALSE;
-osi_list_decl(log_list);
-
-
-
-
-
-char *type2string(unsigned int type)
-{
- char *type_string;
-
- switch (type)
- {
- case FCR_READ_BUFFERED:
- type_string = "read(b)";
- break;
- case FCR_READ_DIRECT:
- type_string = "read(d)";
- break;
- case FCR_READ_MMAPPED:
- type_string = "read(m)";
- break;
- case FCR_WRITE_BUFFERED:
- type_string = "write(b)";
- break;
- case FCR_WRITE_DIRECT:
- type_string = "write(d)";
- break;
- case FCR_WRITE_MMAPPED:
- type_string = "write(m)";
- break;
- case FCR_TRUNC:
- type_string = "trunc";
- break;
- case FCR_NOP:
- type_string = "nop";
- break;
- case FCR_SEED:
- type_string = "seed";
- break;
- case FCR_STOP:
- type_string = "stop";
- break;
- default:
- type_string = "unknown";
- break;
- }
-
- return type_string;
-}
-
-
-void request_print(unsigned int cli, filecon2_request_t *req)
-{
- printf("Request from %u/%.8X/%.4X:\n",
- cli, be32_to_cpu(ssin[cli].sin_addr.s_addr), be16_to_cpu(ssin[cli].sin_port));
- printf(" magic = 0x%X\n", req->magic);
- printf(" type = %s (%u)\n", type2string(req->type), req->type);
- printf(" length = %u\n", req->length);
- printf(" data = %u\n", req->data);
- printf(" offset = %"PRIu64"\n", req->offset);
-}
-
-
-void dump_data(filecon2_request_t *req, unsigned char *client, unsigned char *server)
-{
- FILE *outfile;
- unsigned int x;
- unsigned int first = (unsigned int)-1, last = (unsigned int)-1;
- uint64 f1, l1, f2, l2;
-
- for (x = 0; x < req->data; x++)
- if (client[x] != server[x])
- {
- first = x;
- break;
- }
-
- if (first == (unsigned int)-1)
- die("blerg1\n");
-
- for (x = req->data; x--; )
- if (client[x] != server[x])
- {
- last = x;
- break;
- }
-
- if (last == (unsigned int)-1)
- die("blerg2\n");
-
- f1 = req->offset + first;
- l1 = req->offset + last;
-
- printf("Error range (%"PRIu64" - %"PRIu64"), (%u - %u) \n",
- f1, l1, first, last);
-
- if (log)
- {
- osi_list_t *tmp, *head;
- log_t *l;
- unsigned int t = 0;
-
- for (head = &log_list, tmp = head->next;
- tmp != head;
- tmp = tmp->next, t++)
- {
- l = osi_list_entry(tmp, log_t, list);
-
- if (l->req.type == FCR_NOP)
- continue;
- else if (l->req.type == FCR_TRUNC)
- {
- f2 = l->req.offset;
- l2 = l->req.offset;
- }
- else
- {
- f2 = l->req.offset;
- l2 = l->req.offset + l->req.data - 1;
- }
-
- if ((f1 <= f2 && f2 <= l1) ||
- (f1 <= l2 && l2 <= l1) ||
- (f2 <= f1 && f1 <= l2) ||
- (f2 <= l1 && l1 <= l2))
- {
- printf("%.7u: %u/%.8X/%.4X: %s (%"PRIu64" - %"PRIu64")\n",
- t,
- l->cli, be32_to_cpu(ssin[l->cli].sin_addr.s_addr), be16_to_cpu(ssin[l->cli].sin_port),
- type2string(l->req.type),
- f2, l2);
- }
- }
- }
-
- outfile = fopen("out.client", "w");
- if (!outfile)
- die("can't open file %s: %s\n", "out.client", strerror(errno));
- for (x = 0; x < req->data; x++)
- {
- fprintf(outfile, "%.2X", client[x]);
- if (x % 32 == 31)
- fprintf(outfile, "\n");
- }
- if (x % 32)
- fprintf(outfile, "\n");
- fclose(outfile);
-
- outfile = fopen("out.server", "w");
- if (!outfile)
- die("can't open file %s: %s\n", "out.server", strerror(errno));
- for (x = 0; x < req->data; x++)
- {
- fprintf(outfile, "%.2X", server[x]);
- if (x % 32 == 31)
- fprintf(outfile, "\n");
- }
- if (x % 32)
- fprintf(outfile, "\n");
- fclose(outfile);
-}
-
-
-void do_op(unsigned int cli)
-{
- struct stat st;
- filecon2_request_t req;
- unsigned char buf[sizeof(filecon2_request_t)];
- uint64 first, last;
- unsigned char *data1 = NULL;
- unsigned char *data2;
- unsigned int x = 0;
- int error;
-
- error = fstat(fd, &st);
- if (error)
- die("can't stat file: %s\n", strerror(errno));
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.length = t;
- req.offset = st.st_size;
- request_out(&req, buf);
- do_write(sock[cli], buf, sizeof(filecon2_request_t));
-
- do_read(sock[cli], buf, sizeof(filecon2_request_t));
- request_in(&req, buf);
-
- if (req.magic != FILECON2_MAGIC)
- {
- request_print(cli, &req);
- die("magic number mismatch\n");
- }
-
- if (req.type == FCR_NOP)
- first = last = 0;
- else if (req.type == FCR_TRUNC)
- first = last = req.offset;
- else
- {
- first = req.offset;
- last = req.offset + req.data - 1;
- }
-
- printf("%.7u: %d/%u/%.8X/%.4X: %s (%"PRIu64" - %"PRIu64")\n",
- t, pid,
- cli, be32_to_cpu(ssin[cli].sin_addr.s_addr), be16_to_cpu(ssin[cli].sin_port),
- type2string(req.type),
- first, last);
-
- if (log)
- {
- log_t *l;
- l = malloc(sizeof(log_t));
- if (!l)
- die("out of memory\n");
- memset(l, 0, sizeof(log_t));
- l->cli = cli;
- l->req = req;
- osi_list_add_prev(&l->list, &log_list);
- }
-
- if (req.data)
- {
- data1 = malloc(req.data);
- if (!data1)
- {
- request_print(cli, &req);
- die("out of memory\n");
- }
-
- for (;;)
- {
- error = read(sock[cli], data1 + x, req.data - x);
- if (error < 0)
- {
- request_print(cli, &req);
- die("can't read from socket: %s\n", strerror(errno));
- }
-
- x += error;
-
- if (x == req.data)
- break;
- if (x > req.data)
- {
- request_print(cli, &req);
- die("data overflow from client: %u\n", x);
- }
- }
- }
-
- if (req.type == FCR_READ_BUFFERED ||
- req.type == FCR_READ_MMAPPED)
- {
- data2 = malloc(req.data + 1); /* req.data might be zero */;
- if (!data2)
- {
- request_print(cli, &req);
- die("out of memory\n");
- }
-
- do_lseek(fd, req.offset);
- error = read(fd, data2, req.length);
- if (error < 0)
- {
- request_print(cli, &req);
- die("bad read from file: %s\n", strerror(errno));
- }
-
- if (error != req.data)
- {
- request_print(cli, &req);
- die("length mismatch from read: %u\n", error);
- }
- if (req.data && memcmp(data1, data2, req.data) != 0)
- {
- request_print(cli, &req);
- dump_data(&req, data1, data2);
- die("value mismatch\n");
- }
-
- free(data2);
- }
- else if (req.type == FCR_READ_DIRECT)
- {
- data2 = malloc(req.length + 1);
- if (!data2)
- {
- request_print(cli, &req);
- die("out of memory\n");
- }
-
- do_lseek(fd, req.offset);
- error = read(fd, data2, req.length);
- if (error < 0)
- {
- request_print(cli, &req);
- die("bad read from file: %s\n", strerror(errno));
- }
-
- /* FixMe!!! */
- if (error < req.data || error - req.data > 4096)
- {
- request_print(cli, &req);
- die("length mismatch from read: %u\n", error);
- }
- if (req.data && memcmp(data1, data2, req.data) != 0)
- {
- request_print(cli, &req);
- dump_data(&req, data1, data2);
- die("value mismatch\n");
- }
-
- free(data2);
- }
- else if (req.type == FCR_WRITE_BUFFERED ||
- req.type == FCR_WRITE_DIRECT ||
- req.type == FCR_WRITE_MMAPPED)
- {
- if (!req.data)
- {
- request_print(cli, &req);
- die("no data to write\n");
- }
- if (req.length != req.data)
- {
- request_print(cli, &req);
- die("length != data on write\n");
- }
-
- do_lseek(fd, req.offset);
- error = write(fd, data1, req.length);
- if (error < 0)
- {
- request_print(cli, &req);
- die("bad write to file: %s\n", strerror(errno));
- }
- if (error != req.length)
- {
- request_print(cli, &req);
- die("short write: %u\n", error);
- }
- }
- else if (req.type == FCR_TRUNC)
- {
- error = ftruncate(fd, req.offset);
- if (error)
- {
- request_print(cli, &req);
- die("bad truncate: %s\n", strerror(errno));
- }
- }
- else if (req.type == FCR_NOP)
- {
- /* Do nothing */
- }
- else
- {
- request_print(cli, &req);
- die("strange message from client\n");
- }
-
- if (req.data)
- free(data1);
-}
-
-
-void do_seed(int sock)
-{
- filecon2_request_t req;
- unsigned char buf[sizeof(filecon2_request_t)];
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.type = FCR_SEED;
- req.length = random();
- request_out(&req, buf);
- do_write(sock, buf, sizeof(filecon2_request_t));
-}
-
-
-void do_stop(int sock)
-{
- filecon2_request_t req;
- unsigned char buf[sizeof(filecon2_request_t)];
-
- memset(&req, 0, sizeof(filecon2_request_t));
- req.magic = FILECON2_MAGIC;
- req.type = FCR_STOP;
- request_out(&req, buf);
- do_write(sock, buf, sizeof(filecon2_request_t));
-}
-
-
-int main(int argc, char *argv[])
-{
- unsigned int port = FILECON2_PORT;
- unsigned int seed = time(NULL) ^ getpid();
- unsigned int wait_clients = 1;
- unsigned int to = 0;
- char *filename;
-
- int optchar, cont = TRUE;
- int asking_sock;
- int trueint = TRUE;
- struct sockaddr_in sin;
- fd_set fds;
- struct timeval tv;
- unsigned int size;
- unsigned int cli;
- int error;
-
-
- prog_name = argv[0];
- pid = getpid();
-
-
- if (argc < 2)
- {
- fprintf(stderr, "%s usage:\n\n", prog_name);
- fprintf(stderr, "%s -p <port> -s <seed> -w <clients> -t <to> filename\n\n", prog_name);
- fprintf(stderr, " -p <port> The port to listen on (%u by default)\n", FILECON2_PORT);
- fprintf(stderr, " -s <seed> Seed for the random number generator\n");
- fprintf(stderr, " -w <clients> Wait for a number of clients to join\n");
- fprintf(stderr, " -t <to> Only do a given number of operations\n");
- fprintf(stderr, " -l Log operations for error reporting\n");
- exit(EXIT_FAILURE);
- }
-
- while (cont)
- {
- optchar = getopt(argc, argv, "p:s:w:t:l");
- switch (optchar)
- {
- case 'p':
- sscanf(optarg, "%u", &port);
- break;
- case 's':
- sscanf(optarg, "%u", &seed);
- break;
- case 'w':
- sscanf(optarg, "%u", &wait_clients);
- break;
- case 't':
- sscanf(optarg, "%u", &to);
- break;
- case 'l':
- log = TRUE;
- break;
- case EOF:
- cont = FALSE;
- break;
- default:
- die("bad argument\n");
- }
- }
-
- if (optind < argc)
- filename = argv[optind];
- else
- die("no filename\n");
-
- if (port >= 65536)
- die("invalid port number: %u\n", port);
-
-
- srandom(seed);
-
-
- fd = open(filename, O_RDWR, 0644);
- if (fd < 0)
- die("can't open file %s: %s\n", filename, strerror(errno));
-
-
- asking_sock = socket(AF_INET, SOCK_STREAM, 0);
- if (asking_sock < 0)
- die("can't open socket: %s\n", strerror(errno));
-
- error = setsockopt(asking_sock, SOL_SOCKET, SO_REUSEADDR, &trueint, sizeof(int));
- if (error < 0)
- die("can't set SO_REUSEADDR: %s\n", strerror(errno));
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
- sin.sin_port = cpu_to_be16(port);
-
- error = bind(asking_sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
- if (error < 0)
- die("can't bind to port %u: %s\n", port, strerror(errno));
-
- error = listen(asking_sock, 5);
- if (error < 0)
- die("can't bind to socket: %s\n", strerror(errno));
-
-
- for (;;)
- {
- FD_ZERO(&fds);
- FD_SET(asking_sock, &fds);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- error = select(asking_sock + 1, &fds, NULL, NULL,
- (clients < wait_clients) ? NULL : &tv);
- if (error < 0)
- die("can't select: %s\n", strerror(errno));
-
- if (error) /* Add a new client */
- {
- cli = clients;
- clients++;
-
- sock = realloc(sock, clients * sizeof(int));
- if (!sock)
- die("can't alloc memory: %s\n", strerror(errno));
- ssin = realloc(ssin, clients * sizeof(struct sockaddr_in));
- if (!ssin)
- die("can't alloc memory: %s\n", strerror(errno));
-
- size = sizeof(struct sockaddr_in);
- sock[cli] = accept(asking_sock, &ssin[cli], &size);
- if (sock[cli] < 0)
- die("can't accept: %s\n", strerror(errno));
-
- do_seed(sock[cli]);
-
- printf("connect %u/%.8X/%.4X\n",
- cli, be32_to_cpu(ssin[cli].sin_addr.s_addr), be16_to_cpu(ssin[cli].sin_port));
- }
-
- if (clients < wait_clients)
- continue;
-
-
- cli = RAND(clients);
- do_op(cli);
- t++;
-
- if (to && t == to)
- break;
- }
-
-
- for (cli = 0; cli < clients; cli++)
- {
- do_stop(sock[cli]);
- close(sock[cli]);
- }
- close(fd);
-
-
- exit(EXIT_SUCCESS);
-}
-
-
-
diff --git a/gfs/tests/mmdd/Makefile b/gfs/tests/mmdd/Makefile
deleted file mode 100644
index eb9cc9e..0000000
--- a/gfs/tests/mmdd/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-TARGETS= mmdd sfdd
-
-all: $(TARGETS)
-
-include ../../../make/defines.mk
-include $(OBJDIR)/make/clean.mk
-
-CFLAGS += -D_GNU_SOURCE
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L${libdir}
-
-mmdd.o: mmdd.c
- $(CC) $(CFLAGS) -D_FILE_OFFSET_BITS=64 -c -o $@ $<
-
-sfdd.o: mmdd.c
- $(CC) $(CFLAGS) -DUSE_SENDFILE -c -o $@ $<
-
-%: %.o
- $(CC) -o $@ $^ $(LDFLAGS)
-
-clean: generalclean
-
--include mmdd.d
--include sfdd.d
diff --git a/gfs/tests/mmdd/mmdd.c b/gfs/tests/mmdd/mmdd.c
deleted file mode 100644
index 3864f71..0000000
--- a/gfs/tests/mmdd/mmdd.c
+++ /dev/null
@@ -1,703 +0,0 @@
-#ifdef __linux__
-#else
-#undef USE_SENDFILE
-#endif
-
-#ifdef __FreeBSD__
-#define O_SYNC O_FSYNC
-#else
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#ifdef USE_SENDFILE
-#include <sys/sendfile.h>
-#endif
-
-
-
-#define die(fmt, args...) \
-do \
-{ \
- fprintf(stderr, "%s: ", prog_name); \
- fprintf(stderr, fmt, ##args); \
- exit(EXIT_FAILURE); \
-} \
-while (0)
-
-#define TRUE (1)
-#define FALSE (0)
-
-
-
-#ifndef O_DIRECT
-#define O_DIRECT (0)
-#warning O_DIRECT is broken
-#endif
-#ifndef PAGE_SIZE
-#define PAGE_SIZE (65536)
-#endif
-
-
-
-char *prog_name;
-off_t read_offset = 0;
-off_t write_offset = 0;
-int private = FALSE;
-
-
-
-
-
-#ifdef USE_SENDFILE
-void send_sendfile(int ifd, int ofd, unsigned bs)
-{
- int count;
-
- count = sendfile(ofd, ifd, &read_offset, bs);
- if (count != bs)
- die("Bad sendfile return %d: %s\n", count, strerror(errno));
-
- write_offset += bs;
-}
-#endif
-
-
-void do_bothmapped(int ifd, int ofd, unsigned bs)
-{
- char *data_in;
- char *data_out;
-
- data_in = mmap(NULL, bs, PROT_READ, (private) ? MAP_PRIVATE : MAP_SHARED, ifd, read_offset);
- if (data_in == MAP_FAILED)
- die("can't mmap file: %s\n", strerror(errno));
-
- data_out = mmap(NULL, bs, PROT_READ | PROT_WRITE, (private) ? MAP_PRIVATE : MAP_SHARED, ofd, write_offset);
- if (data_out == MAP_FAILED)
- die("can't mmap file: %s\n", strerror(errno));
-
- memcpy(data_out, data_in, bs);
-
- munmap(data_in, bs);
- munmap(data_out, bs);
-
- read_offset += bs;
- write_offset += bs;
-}
-
-
-void do_imapped(int ifd, int ofd, unsigned bs)
-{
- char *data;
- int count;
-
- data = mmap(NULL, bs, PROT_READ, (private) ? MAP_PRIVATE : MAP_SHARED, ifd, read_offset);
- if (data == MAP_FAILED)
- die("can't mmap file: %s\n", strerror(errno));
-
- count = write(ofd, data, bs);
- if (count != bs)
- die("bad write return %d: %s\n", count, strerror(errno));
-
- munmap(data, bs);
-
- read_offset += bs;
- write_offset += bs;
-}
-
-
-void do_omapped(int ifd, int ofd, unsigned bs)
-{
- char *data;
- int count;
-
- data = mmap(NULL, bs, PROT_READ | PROT_WRITE, (private) ? MAP_PRIVATE : MAP_SHARED, ofd, write_offset);
- if (data == MAP_FAILED)
- die("can't mmap file: %s\n", strerror(errno));
-
- count = read(ifd, data, bs);
- if (count != bs)
- die("bad read return %d: %s\n", count, strerror(errno));
-
- munmap(data, bs);
-
- read_offset += bs;
- write_offset += bs;
-}
-
-
-void do_mapped_read(int fd, char *buf, unsigned int bs)
-{
- char *data;
-
- data = mmap(NULL, bs, PROT_READ, (private) ? MAP_PRIVATE : MAP_SHARED, fd, read_offset);
- if (data == MAP_FAILED)
- die("can't mmap file: %s\n", strerror(errno));
-
- memcpy(buf, data, bs);
-
- munmap(data, bs);
-
- read_offset += bs;
-}
-
-
-void do_raw_read(int fd, char *buf, unsigned int bs)
-{
- int count;
-
- count = read(fd, buf, bs);
- if (count != bs)
- die("bad read return %d: %s\n", count, strerror(errno));
-}
-
-
-void do_mapped_write(int fd, char *buf, unsigned int bs)
-{
- char *data;
-
- data = mmap(NULL, bs, PROT_READ | PROT_WRITE, (private) ? MAP_PRIVATE : MAP_SHARED, fd, write_offset);
- if (data == MAP_FAILED)
- die("can't mmap file: %s\n", strerror(errno));
-
- memcpy(data, buf, bs);
-
- munmap(data, bs);
-
- write_offset += bs;
-}
-
-
-void do_raw_write(int fd, char *buf, unsigned int bs)
-{
- int count;
-
- count = write(fd, buf, bs);
- if (count != bs)
- die("bad write return %d: %s\n", count, strerror(errno));
-}
-
-
-int main(int argc, char *argv[])
-{
- int arg;
-
- char *ifname = NULL;
- char *ofname = NULL;
- int imapped = FALSE, omapped = FALSE;
- unsigned int bs = 4096;
- unsigned long long move = 0;
- unsigned long long count = 0;
- unsigned long long skip = 0;
- unsigned long long seek = 0;
- int do_fsync = FALSE;
- int do_osync = FALSE;
- int verbose = FALSE;
- int notrunc = FALSE;
- int nobounce = FALSE;
- int append = FALSE;
- int direct = FALSE;
- int fgt = FALSE;
- int do_excl = FALSE;
-
- int done_bs = FALSE;
- int done_amount = FALSE;
- int done_skip = FALSE;
- int done_seek = FALSE;
- int done_fsync = FALSE;
- int done_osync = FALSE;
- int done_notrunc = FALSE;
- int done_nobounce = FALSE;
- int done_append = FALSE;
- int done_direct = FALSE;
- int done_private = FALSE;
- int done_fgt = FALSE;
- int done_excl = FALSE;
-
-#ifdef USE_SENDFILE
- int do_sendfile = FALSE;
- int done_sendfile = FALSE;
-#endif
-
- int ifd = -1, ofd = -1;
-
- char c;
- char *data;
- unsigned long long x;
- unsigned int remainder;
-
- unsigned int timeslots, index = 0;
- struct timeval *tv;
- unsigned long long t1, t2;
- double seconds, mbps;
-
- struct stat st;
- char *fgt_name = NULL;
- FILE *fgt_file;
-
- int error;
-
-
-
- prog_name = argv[0];
-
-
-
- if (argc == 1)
- die("options: Help me! Help me!\n");
-
-
-
- for (arg = 1; arg < argc; arg++)
- {
- if (strncmp(argv[arg], "if=", 3) == 0)
- {
- if (ifname)
- die("you're only allowed one \"i?f=\"\n");
-
- ifname = argv[arg] + 3;
- imapped = FALSE;
- }
- else if (strncmp(argv[arg], "imf=", 4) == 0)
- {
- if (ifname)
- die("you're only allowed one \"i?f=\"\n");
-
- ifname = argv[arg] + 4;
- imapped = TRUE;
- }
- else if (strncmp(argv[arg], "of=", 3) == 0)
- {
- if (ofname)
- die("you're only allowed one \"o?f=\"\n");
-
- ofname = argv[arg] + 3;
- omapped = FALSE;
- }
- else if (strncmp(argv[arg], "omf=", 4) == 0)
- {
- if (ofname)
- die("you're only allowed one \"o?f=\"\n");
-
- ofname = argv[arg] + 4;
- omapped = TRUE;
- }
- else if (strncmp(argv[arg], "bs=", 3) == 0)
- {
- if (done_bs)
- die("you're only allowed one \"bs=\"\n");
- done_bs = TRUE;
-
- bs = atoi(argv[arg] + 3);
- c = argv[arg][strlen(argv[arg]) - 1];
- if (c == 'k')
- bs <<= 10;
- else if (c == 'm')
- bs <<= 20;
- else if (c == 'g')
- bs <<= 30;
-
- if (!bs)
- die("invalid blocksize: %u\n", bs);
- }
- else if (strncmp(argv[arg], "move=", 5) == 0)
- {
- if (done_amount)
- die("you're only allowed one amount\n");
- done_amount = TRUE;
-
- sscanf(argv[arg] + 5, "%qu", &move);
- c = argv[arg][strlen(argv[arg]) - 1];
- if (c == 'k')
- move <<= 10;
- else if (c == 'm')
- move <<= 20;
- else if (c == 'g')
- move <<= 30;
-
- if (!move)
- die("zero move\n");
- }
- else if (strncmp(argv[arg], "count=", 6) == 0)
- {
- if (done_amount)
- die("you're only allowed one amount\n");
- done_amount = TRUE;
-
- sscanf(argv[arg] + 6, "%qu", &count);
-
- if (!count)
- die("zero count\n");
- }
- else if (strncmp(argv[arg], "skip=", 5) == 0)
- {
- if (done_skip)
- die("you're only allowed one skip\n");
- done_skip = TRUE;
-
- sscanf(argv[arg] + 5, "%qu", &skip);
- }
- else if (strncmp(argv[arg], "seek=", 5) == 0)
- {
- if (done_seek)
- die("you're only allowed one seek\n");
- done_seek = TRUE;
-
- sscanf(argv[arg] + 5, "%qu", &seek);
- }
- else if (strncmp(argv[arg], "fsync=", 6) == 0)
- {
- if (done_fsync)
- die("you're only allowed one \"fsync=\"\n");
- done_fsync = TRUE;
-
- do_fsync = atoi(argv[arg] + 6);
- }
- else if (strncmp(argv[arg], "osync=", 6) == 0)
- {
- if (done_osync)
- die("you're only allowed one \"osync=\"\n");
- done_osync = TRUE;
-
- do_osync = atoi(argv[arg] + 6);
- }
- else if (strncmp(argv[arg], "notrunc=", 8) == 0)
- {
- if (done_notrunc)
- die("you're only allowed one \"notrunc=\"\n");
- done_notrunc = TRUE;
-
- notrunc = atoi(argv[arg] + 8);
- }
- else if (strncmp(argv[arg], "nobounce=", 9) == 0)
- {
- if (done_nobounce)
- die("you're only allowed one \"nobounce=\"\n");
- done_nobounce = TRUE;
-
- nobounce = atoi(argv[arg] + 9);
- }
- else if (strncmp(argv[arg], "append=", 7) == 0)
- {
- if (done_append)
- die("you're only allowed one \"append=\"\n");
- done_append = TRUE;
-
- append = atoi(argv[arg] + 7);
- }
- else if (strncmp(argv[arg], "direct=", 7) == 0)
- {
- if (done_direct)
- die("you're only allowed one \"direct=\"\n");
- done_direct = TRUE;
-
- direct = atoi(argv[arg] + 7);
- }
-#ifdef USE_SENDFILE
- else if (strncmp(argv[arg], "sendfile=", 9) == 0)
- {
- if (done_sendfile)
- die("you're only allowed one \"sendfile=\"\n");
- done_sendfile = TRUE;
-
- do_sendfile = atoi(argv[arg] + 9);
- }
-#endif
- else if (strncmp(argv[arg], "private=", 8) == 0)
- {
- if (done_private)
- die("you're only allowed one \"private=\"\n");
- done_private = TRUE;
-
- private = atoi(argv[arg] + 8);
- }
- else if (strncmp(argv[arg], "fgt=", 4) == 0)
- {
- if (done_fgt)
- die("you're only allowed one \"fgt=\"\n");
- done_fgt = TRUE;
-
- if (isdigit(*(argv[arg] + 4)))
- fgt = atoi(argv[arg] + 4);
- else
- {
- fgt = TRUE;
- fgt_name = argv[arg] + 4;
- }
- }
- else if (strncmp(argv[arg], "excl=", 5) == 0)
- {
- if (done_excl)
- die("you're only allowed one \"excl=\"\n");
- done_excl = TRUE;
-
- do_excl = atoi(argv[arg] + 5);
- }
- else if (strcmp(argv[arg], "-v") == 0)
- {
- verbose = TRUE;
- }
- else
- {
- die("unknown/unimplemented option: %s\n", argv[arg]);
- }
- }
-
-
-
- if (!done_amount)
- die("need an amount to move\n");
-
- if (verbose)
- {
- fprintf(stderr, "ifname = %s (%s)\n", ifname, (imapped) ? "mapped" : "raw");
- fprintf(stderr, "ofname = %s (%s)\n", ofname, (omapped) ? "mapped" : "raw");
- fprintf(stderr, "bs = %u\n", bs);
- fprintf(stderr, "move = %qu\n", move);
- fprintf(stderr, "count = %qu\n", count);
- fprintf(stderr, "skip = %qu\n", skip);
- fprintf(stderr, "seek = %qu\n", seek);
- fprintf(stderr, "fsync = %d\n", do_fsync);
- fprintf(stderr, "notrunc = %d\n", notrunc);
- fprintf(stderr, "nobounce = %d\n", nobounce);
- fprintf(stderr, "append = %d\n", append);
- fprintf(stderr, "direct = %d\n", direct);
-#ifdef USE_SENDFILE
- fprintf(stderr, "sendfile = %d\n", do_sendfile);
-#endif
- fprintf(stderr, "private = %d\n", private);
- fprintf(stderr, "fine grain timing = %d\n", fgt);
- fprintf(stderr, "fine grain timing file = %s\n", (fgt_name) ? fgt_name : "NULL");
- fprintf(stderr, "excl = %d\n", do_excl);
- }
-
- if (!count)
- {
- if (move % bs != 0)
- die("move size (%qu) not divisible by block size (%u)\n", move, bs);
- count = move / bs;
- }
-
-
-
- data = (char *)malloc(bs + PAGE_SIZE);
- if (!data)
- die("out of memory\n");
-
- remainder = ((unsigned long)data) & (PAGE_SIZE - 1);
- if (remainder)
- data += PAGE_SIZE - remainder;
-
- memset(data, 0, bs);
-
-
-
- if (fgt)
- {
- if (count & 0xFFFFFFFFF0000000)
- die("count is too high -- can't do fine grain timing\n");
- timeslots = count + 3;
- }
- else
- timeslots = 2;
-
- tv = malloc(timeslots * sizeof(struct timeval));
- if (!tv)
- die("out of memory\n");
-
-
-
- gettimeofday(&tv[index++], NULL);
-
-
-
- if (ifname)
- {
- if (strcmp(ifname, "-") == 0)
- ifd = STDIN_FILENO;
- else
- {
- ifd = open(ifname, O_RDONLY | ((direct) ? O_DIRECT : 0));
- if (ifd < 0)
- die("can't open file %s: %s\n", ifname, strerror(errno));
- if (verbose)
- {
- error = fstat(ifd, &st);
- if (error)
- die("can't stat file %s: %s\n", ifname, strerror(errno));
- fprintf(stderr, "input inode = %qu\n", (unsigned long long)st.st_ino);
- }
-
- if (skip && lseek(ifd, skip * bs, SEEK_SET) != skip * bs)
- die("can't skip: %s\n", strerror(errno));
- }
- }
-
- if (ofname)
- {
- if (strcmp(ofname, "-") == 0)
- ofd = STDOUT_FILENO;
- else
- {
- ofd = open(ofname,
- O_RDWR |
- O_CREAT |
- ((notrunc) ? 0 : O_TRUNC) |
- ((direct) ? O_DIRECT : 0) |
- ((append) ? O_APPEND : 0) |
- ((do_osync) ? O_SYNC : 0) |
- ((do_excl) ? O_EXCL : 0),
- 0644);
- if (ofd < 0)
- die("can't open file %s: %s\n", ofname, strerror(errno));
- if (verbose)
- {
- error = fstat(ofd, &st);
- if (error)
- die("can't stat file %s: %s\n", ofname, strerror(errno));
- fprintf(stderr, "output inode = %qu\n", (unsigned long long)st.st_ino);
- }
-
- if (seek && lseek(ofd, seek * bs, SEEK_SET) != seek * bs)
- die("can't seek: %s\n", strerror(errno));
- }
- }
-
- if (ofd >= 0 && omapped)
- {
- if (ftruncate(ofd, bs * count) < 0)
- die("can't truncate bigger: %s\n", strerror(errno));
- }
-
-
-
- if (fgt)
- gettimeofday(&tv[index++], NULL);
-
-
-
- for (x = 0; x < count; x++)
- {
-#ifdef USE_SENDFILE
- if (do_sendfile && ifd >= 0 && ofd >= 0)
- send_sendfile(ifd, ofd, bs);
- else
-#endif
- if (nobounce && ifd >= 0 && ofd >= 0 && (imapped || omapped))
- {
- if (imapped && omapped)
- do_bothmapped(ifd, ofd, bs);
- else if (imapped)
- do_imapped(ifd, ofd, bs);
- else
- do_omapped(ifd, ofd, bs);
- }
- else
- {
- if (ifd >= 0)
- {
- if (imapped)
- do_mapped_read(ifd, data, bs);
- else
- do_raw_read(ifd, data, bs);
- }
-
- if (ofd >= 0)
- {
- if (omapped)
- do_mapped_write(ofd, data, bs);
- else
- do_raw_write(ofd, data, bs);
- }
- }
-
- if (verbose)
- fprintf(stderr, "%qu\n", x);
-
- if (fgt)
- gettimeofday(&tv[index++], NULL);
- }
-
-
-
- if (ifd >= 0)
- close(ifd);
-
- if (ofd >= 0)
- {
- if (do_fsync)
- fsync(ofd);
- close(ofd);
- }
-
-
-
- gettimeofday(&tv[index++], NULL);
-
- if (index != timeslots)
- die("index != timeslots\n");
-
-
-
- if (fgt)
- {
- if (fgt_name)
- {
- fgt_file = fopen(fgt_name, "w");
- if (!fgt_file)
- die("can't open file %s: %s\n", fgt_name, strerror(errno));
- }
- else
- fgt_file = stderr;
-
- t1 = (unsigned long long)tv[0].tv_sec * 1000000 + tv[0].tv_usec;
- fprintf(fgt_file, "start = %qu\n", t1);
-
- for (index = 1; index < timeslots; index++)
- {
- t1 = (unsigned long long)tv[index - 1].tv_sec * 1000000 + tv[index - 1].tv_usec;
- t2 = (unsigned long long)tv[index].tv_sec * 1000000 + tv[index].tv_usec;
-
- if (index == 1)
- fprintf(fgt_file, "setup = %qu\n", t2 - t1);
- else if (index == timeslots - 1)
- fprintf(fgt_file, "cleanup = %qu\n", t2 - t1);
- else
- fprintf(fgt_file, "loop %u = %qu\n", index - 2, t2 - t1);
- }
-
- t1 = (unsigned long long)tv[0].tv_sec * 1000000 + tv[0].tv_usec;
- t2 = (unsigned long long)tv[timeslots - 1].tv_sec * 1000000 + tv[timeslots - 1].tv_usec;
-
- fprintf(fgt_file, "total = %qu\n", t2 - t1);
-
- if (fgt_name)
- fclose(fgt_file);
- }
-
-
-
- t1 = (unsigned long long)tv[0].tv_sec * 1000000 + tv[0].tv_usec;
- t2 = (unsigned long long)tv[timeslots - 1].tv_sec * 1000000 + tv[timeslots - 1].tv_usec;
-
- seconds = (t2 - t1) / 1000000.0;
- mbps = bs * count / 1048576.0 / seconds;
-
- fprintf(stderr, "seconds = %.4f, MB/s = %.4f\n", seconds, mbps);
-
-
-
- exit(EXIT_SUCCESS);
-}
-
-
-
diff --git a/gfs2/Makefile b/gfs2/Makefile
deleted file mode 100644
index 7daf231..0000000
--- a/gfs2/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-include ../make/defines.mk
-include $(OBJDIR)/make/passthrough.mk
-
-SUBDIRS=libgfs2 convert edit fsck mkfs mount quota tool man init.d
diff --git a/gfs2/convert/Makefile b/gfs2/convert/Makefile
deleted file mode 100644
index eddb79a..0000000
--- a/gfs2/convert/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-TARGET= gfs2_convert
-
-SBINDIRT=$(TARGET)
-
-all: depends ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= gfs2_convert.o
-
-CFLAGS += -D_FILE_OFFSET_BITS=64 -DHELPER_PROGRAM
-CFLAGS += -I${KERNEL_SRC}/fs/gfs2/ -I${KERNEL_SRC}/include/
-CFLAGS += -I$(S)/../include -I$(S)/../libgfs2
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L../libgfs2 -lgfs2
-LDFLAGS += -L${libdir}
-
-LDDEPS += ../libgfs2/libgfs2.a
-
-${TARGET}: ${OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-depends:
- $(MAKE) -C ../libgfs2 all
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
deleted file mode 100644
index f84de84..0000000
--- a/gfs2/convert/gfs2_convert.c
+++ /dev/null
@@ -1,2318 +0,0 @@
-/*****************************************************************************
-******************************************************************************
-**
-** gfs2_convert - convert a gfs1 filesystem into a gfs2 filesystem.
-**
-******************************************************************************
-*****************************************************************************/
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <libgen.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <dirent.h>
-#include <string.h>
-#include <time.h>
-#include <sys/time.h>
-#include <errno.h>
-
-#include <linux/types.h>
-#include <linux/gfs2_ondisk.h>
-#include "osi_list.h"
-#include "copyright.cf"
-#include "libgfs2.h"
-
-/* The following declares are needed because gfs2 can't have */
-/* dependencies on gfs1: */
-#define RGRP_STUFFED_BLKS(sb) (((sb)->sb_bsize - sizeof(struct gfs2_rgrp)) * GFS2_NBBY)
-#define RGRP_BITMAP_BLKS(sb) (((sb)->sb_bsize - sizeof(struct gfs2_meta_header)) * GFS2_NBBY)
-
-/* Define some gfs1 constants from gfs1's gfs_ondisk.h */
-#define GFS_METATYPE_NONE (0)
-#define GFS_METATYPE_SB (1) /* Super-Block */
-#define GFS_METATYPE_RG (2) /* Resource Group Header */
-#define GFS_METATYPE_RB (3) /* Resource Group Block Alloc BitBlock */
-#define GFS_METATYPE_DI (4) /* "Disk" inode (dinode) */
-#define GFS_METATYPE_IN (5) /* Indirect dinode block list */
-#define GFS_METATYPE_LF (6) /* Leaf dinode block list */
-#define GFS_METATYPE_JD (7) /* Journal Data */
-#define GFS_METATYPE_LH (8) /* Log Header (gfs_log_header) */
-#define GFS_METATYPE_LD (9) /* Log Descriptor (gfs_log_descriptor) */
-#define GFS_METATYPE_EA (10) /* Extended Attribute */
-#define GFS_METATYPE_ED (11) /* Extended Attribute data */
-
-/* GFS1 Dinode types */
-#define GFS_FILE_NON (0)
-#define GFS_FILE_REG (1) /* regular file */
-#define GFS_FILE_DIR (2) /* directory */
-#define GFS_FILE_LNK (5) /* link */
-#define GFS_FILE_BLK (7) /* block device node */
-#define GFS_FILE_CHR (8) /* character device node */
-#define GFS_FILE_FIFO (101) /* fifo/pipe */
-#define GFS_FILE_SOCK (102) /* socket */
-
-#define GFS_FORMAT_SB (100) /* Super-Block */
-#define GFS_FORMAT_FS (1309) /* Filesystem (all-encompassing) */
-#define GFS_FORMAT_MULTI (1401) /* Multi-Host */
-
-#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
-
-struct gfs1_rgrp {
- struct gfs2_meta_header rg_header; /* hasn't changed from gfs1 to 2 */
- uint32_t rg_flags;
- uint32_t rg_free; /* Number (qty) of free data blocks */
- /* Dinodes are USEDMETA, but are handled separately from other METAs */
- uint32_t rg_useddi; /* Number (qty) of dinodes (used or free) */
- uint32_t rg_freedi; /* Number (qty) of unused (free) dinodes */
- struct gfs2_inum rg_freedi_list; /* hasn't changed from gfs1 to 2 */
- /* These META statistics do not include dinodes (used or free) */
- uint32_t rg_usedmeta; /* Number (qty) of used metadata blocks */
- uint32_t rg_freemeta; /* Number (qty) of unused metadata blocks */
- char rg_reserved[64];
-};
-
-struct gfs1_jindex {
- uint64_t ji_addr; /* starting block of the journal */
- uint32_t ji_nsegment; /* number (quantity) of segments in journal */
- uint32_t ji_pad;
-
- char ji_reserved[64];
-};
-
-struct gfs1_sb {
- /* Order is important; need to be able to read old superblocks
- in order to support on-disk version upgrades */
- struct gfs2_meta_header sb_header;
-
- uint32_t sb_fs_format; /* GFS_FORMAT_FS (on-disk version) */
- uint32_t sb_multihost_format; /* GFS_FORMAT_MULTI */
- uint32_t sb_flags; /* ?? */
-
- uint32_t sb_bsize; /* fundamental FS block size in bytes */
- uint32_t sb_bsize_shift; /* log2(sb_bsize) */
- uint32_t sb_seg_size; /* Journal segment size in FS blocks */
-
- /* These special inodes do not appear in any on-disk directory. */
- struct gfs2_inum sb_jindex_di; /* journal index inode */
- struct gfs2_inum sb_rindex_di; /* resource group index inode */
- struct gfs2_inum sb_root_di; /* root directory inode */
-
- /* Default inter-node locking protocol (lock module) and namespace */
- char sb_lockproto[GFS2_LOCKNAME_LEN]; /* lock protocol name */
- char sb_locktable[GFS2_LOCKNAME_LEN]; /* unique name for this FS */
-
- /* More special inodes */
- struct gfs2_inum sb_quota_di; /* quota inode */
- struct gfs2_inum sb_license_di; /* license inode */
-
- char sb_reserved[96];
-};
-
-struct inode_dir_block {
- osi_list_t list;
- uint64_t di_addr;
- uint64_t di_paddr; /* Parent dir inode addr */
-};
-
-struct inode_block {
- osi_list_t list;
- uint64_t di_addr;
-};
-
-struct blocklist {
- osi_list_t list;
- uint64_t block;
- struct metapath mp;
- int height;
- char *ptrbuf;
-};
-
-struct gfs1_sb raw_gfs1_ondisk_sb;
-struct gfs2_sbd sb2;
-char device[256];
-struct inode_block dirs_to_fix; /* linked list of directories to fix */
-struct inode_dir_block cdpns_to_fix; /* linked list of cdpn symlinks */
-int seconds;
-struct timeval tv;
-uint64_t dirs_fixed;
-uint64_t cdpns_fixed;
-uint64_t dirents_fixed;
-struct gfs1_jindex *sd_jindex = NULL; /* gfs1 journal index in memory */
-int gfs2_inptrs;
-uint64_t gfs2_heightsize[GFS2_MAX_META_HEIGHT];
-uint64_t gfs2_jheightsize[GFS2_MAX_META_HEIGHT];
-uint32_t gfs2_max_height;
-uint32_t gfs2_max_jheight;
-uint64_t jindex_addr = 0, rindex_addr = 0;
-
-/* ------------------------------------------------------------------------- */
-/* This function is for libgfs's sake. */
-/* ------------------------------------------------------------------------- */
-void print_it(const char *label, const char *fmt, const char *fmt2, ...)
-{
- va_list args;
-
- va_start(args, fmt2);
- printf("%s: ", label);
- vprintf(fmt, args);
- va_end(args);
-}
-
-/* ------------------------------------------------------------------------- */
-/* convert_bitmaps - Convert gfs1 bitmaps to gfs2 bitmaps. */
-/* Fixes all unallocated metadata bitmap states (which are */
-/* valid in gfs1 but invalid in gfs2). */
-/* ------------------------------------------------------------------------- */
-static void convert_bitmaps(struct gfs2_sbd *sdp, struct rgrp_list *rg)
-{
- uint32_t blk;
- int x, y;
- struct gfs2_rindex *ri;
- unsigned char state;
-
- ri = &rg->ri;
- for (blk = 0; blk < ri->ri_length; blk++) {
- x = (blk) ? sizeof(struct gfs2_meta_header) :
- sizeof(struct gfs2_rgrp);
-
- for (; x < sdp->bsize; x++)
- for (y = 0; y < GFS2_NBBY; y++) {
- state = (rg->bh[blk]->b_data[x] >>
- (GFS2_BIT_SIZE * y)) & 0x03;
- if (state == 0x02) /* unallocated metadata state invalid */
- rg->bh[blk]->b_data[x] &= ~(0x02 << (GFS2_BIT_SIZE * y));
- }
- }
-}/* convert_bitmaps */
-
-/* ------------------------------------------------------------------------- */
-/* convert_rgs - Convert gfs1 resource groups to gfs2. */
-/* Returns: 0 on success, -1 on failure */
-/* ------------------------------------------------------------------------- */
-static int convert_rgs(struct gfs2_sbd *sbp)
-{
- struct rgrp_list *rgd;
- osi_list_t *tmp;
- struct gfs1_rgrp *rgd1;
- int rgs = 0;
-
- /* --------------------------------- */
- /* Now convert its rgs into gfs2 rgs */
- /* --------------------------------- */
- osi_list_foreach(tmp, &sbp->rglist) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- rgd1 = (struct gfs1_rgrp *)&rgd->rg; /* recast as gfs1 structure */
- /* rg_freemeta is a gfs1 structure, so libgfs2 doesn't know to */
- /* convert from be to cpu. We must do it now. */
- rgd->rg.rg_free = rgd1->rg_free + be32_to_cpu(rgd1->rg_freemeta);
- /* Zero it out so we don't add it again in case something breaks */
- /* later on in the process and we have to re-run convert */
- rgd1->rg_freemeta = 0;
-
- sbp->blks_total += rgd->ri.ri_data;
- sbp->blks_alloced += (rgd->ri.ri_data - rgd->rg.rg_free);
- sbp->dinodes_alloced += rgd1->rg_useddi;
- convert_bitmaps(sbp, rgd);
- /* Write the updated rgrp to the gfs2 buffer */
- gfs2_rgrp_out(&rgd->rg, rgd->bh[0]);
- rgs++;
- if (rgs % 100 == 0) {
- printf(".");
- fflush(stdout);
- }
- }
- return 0;
-}/* superblock_cvt */
-
-/* ------------------------------------------------------------------------- */
-/* calc_gfs2_tree_height - calculate new dinode height as if this is gfs2 */
-/* */
-/* This is similar to calc_tree_height in libgfs2 but at the point this */
-/* function is called, I have the wrong (gfs1 not gfs2) constants in place. */
-/* ------------------------------------------------------------------------- */
-static unsigned int calc_gfs2_tree_height(struct gfs2_inode *ip, uint64_t size)
-{
- uint64_t *arr;
- unsigned int max, height;
-
- if (ip->i_di.di_size > size)
- size = ip->i_di.di_size;
-
- if (S_ISDIR(ip->i_di.di_mode)) {
- arr = gfs2_jheightsize;
- max = gfs2_max_jheight;
- } else {
- arr = gfs2_heightsize;
- max = gfs2_max_height;
- }
-
- for (height = 0; height < max; height++)
- if (arr[height] >= size)
- break;
-
- return height;
-}
-
-/* ------------------------------------------------------------------------- */
-/* mp_gfs1_to_gfs2 - convert a gfs1 metapath to a gfs2 metapath. */
-/* ------------------------------------------------------------------------- */
-static void mp_gfs1_to_gfs2(struct gfs2_sbd *sbp, int gfs1_h, int gfs2_h,
- struct metapath *gfs1mp, struct metapath *gfs2mp)
-{
- uint64_t lblock;
- int h;
- uint64_t gfs1factor[GFS2_MAX_META_HEIGHT];
- uint64_t gfs2factor[GFS2_MAX_META_HEIGHT];
-
- /* figure out multiplication factors for each height - gfs1 */
- memset(&gfs1factor, 0, sizeof(gfs1factor));
- gfs1factor[gfs1_h - 1] = 1ull;
- for (h = gfs1_h - 1; h > 0; h--)
- gfs1factor[h - 1] = gfs1factor[h] * sbp->sd_inptrs;
-
- /* figure out multiplication factors for each height - gfs2 */
- memset(&gfs2factor, 0, sizeof(gfs2factor));
- gfs2factor[gfs2_h - 1] = 1ull;
- for (h = gfs2_h - 1; h > 0; h--)
- gfs2factor[h - 1] = gfs2factor[h] * gfs2_inptrs;
-
- /* Convert from gfs1 to a logical block */
- lblock = 0;
- for (h = 0; h < gfs1_h; h++)
- lblock += (gfs1mp->mp_list[h] * gfs1factor[h]);
-
- /* Convert from a logical block back to gfs2 */
- memset(gfs2mp, 0, sizeof(*gfs2mp));
- for (h = 0; h < gfs2_h; h++) {
- /* Can't use do_div here because the factors are too large. */
- gfs2mp->mp_list[h] = lblock / gfs2factor[h];
- lblock %= gfs2factor[h];
- }
-}
-
-/* ------------------------------------------------------------------------- */
-/* fix_metatree - Fix up the metatree to match the gfs2 metapath info */
-/* Similar to gfs2_writei in libgfs2 but we're only */
-/* interested in rearranging the metadata while leaving the */
-/* actual data blocks intact. */
-/* ------------------------------------------------------------------------- */
-static void fix_metatree(struct gfs2_sbd *sbp, struct gfs2_inode *ip,
- struct blocklist *blk, uint64_t *first_nonzero_ptr,
- unsigned int size)
-{
- uint64_t block;
- struct gfs2_buffer_head *bh;
- unsigned int amount, ptramt;
- int hdrsize, h, copied = 0, new;
- struct gfs2_meta_header mh;
- char *srcptr = (char *)first_nonzero_ptr;
-
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_IN;
- mh.mh_format = GFS2_FORMAT_IN;
- if (!ip->i_di.di_height)
- unstuff_dinode(ip);
-
- ptramt = blk->mp.mp_list[blk->height] * sizeof(uint64_t);
- amount = size;
-
- while (copied < size) {
- bh = ip->i_bh;
- /* First, build up the metatree */
- for (h = 0; h < blk->height; h++) {
- new = 0;
- lookup_block(ip, bh, h, &blk->mp, 1, &new, &block);
- if (bh != ip->i_bh)
- brelse(bh);
- if (!block)
- break;
-
- bh = bread(sbp, block);
- if (new)
- memset(bh->b_data, 0, sbp->bsize);
- gfs2_meta_header_out(&mh, bh);
- }
-
- hdrsize = sizeof(struct gfs2_meta_header);
-
- if (amount > sbp->bsize - hdrsize - ptramt)
- amount = sbp->bsize - hdrsize - ptramt;
-
- memcpy(bh->b_data + hdrsize + ptramt, (char *)srcptr, amount);
- srcptr += amount;
- bmodified(bh);
- if (bh != ip->i_bh)
- brelse(bh);
-
- copied += amount;
-
- if (hdrsize + ptramt + amount >= sbp->bsize) {
- /* advance to the next metablock */
- blk->mp.mp_list[blk->height] +=
- (amount / sizeof(uint64_t));
- for (h = blk->height; h > 0; h--) {
- if (blk->mp.mp_list[h] >= gfs2_inptrs) {
- blk->mp.mp_list[h] = 0;
- blk->mp.mp_list[h - 1]++;
- continue;
- }
- break;
- }
- }
- amount = size - copied;
- ptramt = 0;
- }
-}
-
-/* ------------------------------------------------------------------------- */
-/* adjust_indirect_blocks - convert all gfs_indirect blocks to gfs2. */
-/* */
-/* This function converts all gfs_indirect blocks to GFS2. The difference */
-/* is that gfs1 indirect block has a 64-byte chunk of reserved space that */
-/* gfs2 does not. Since GFS block locations (relative to the start of the */
-/* file have their locations defined by the offset from the end of the */
-/* structure, all block pointers must be shifted. */
-/* */
-/* Stuffed inodes don't need to be shifted at since there are no indirect */
-/* blocks. Inodes with height 1 don't need to be shifted either, because */
-/* the dinode size is the same between gfs and gfs2 (232 bytes), and */
-/* therefore you can fit the same number of block pointers after the dinode */
-/* structure. For the normal 4K block size, that's 483 pointers. For 1K */
-/* blocks, it's 99 pointers. */
-/* */
-/* At height 2 things get complex. GFS1 reserves an area of 64 (0x40) bytes */
-/* at the start of the indirect block, so for 4K blocks, you can fit 501 */
-/* pointers. GFS2 doesn't reserve that space, so you can fit 509 pointers. */
-/* For 1K blocks, it's 117 pointers in GFS1 and 125 in GFS2. */
-/* */
-/* That means, for example, that if you have 4K blocks, a 946MB file will */
-/* require a height of 3 for GFS, but only a height of 2 for GFS2. */
-/* There isn't a good way to shift the pointers around from one height to */
-/* another, so the only way to do it is to rebuild all those indirect blocks */
-/* from empty ones. */
-/* */
-/* For example, with a 1K block size, if you do: */
-/* */
-/* dd if=/mnt/gfs/big of=/tmp/tocompare skip=496572346368 bs=1024 count=1 */
-/* */
-/* the resulting metadata paths will look vastly different for the data: */
-/* */
-/* height 0 1 2 3 4 5 */
-/* GFS1: 0x16 0x4b 0x70 0x11 0x5e 0x48 */
-/* GFS2: 0x10 0x21 0x78 0x05 0x14 0x76 */
-/* */
-/* To complicate matters, we can't really require free space. A user might */
-/* be trying to migrate a "full" gfs1 file system to GFS2. After we */
-/* convert the journals to GFS2, we might have more free space, so we can */
-/* allocate blocks at that time. */
-/* */
-/* Assumes: GFS1 values are in place for diptrs and inptrs. */
-/* */
-/* Returns: 0 on success, -1 on failure */
-/* */
-/* Adapted from gfs2_fsck metawalk.c's build_and_check_metalist */
-/* ------------------------------------------------------------------------- */
-static int adjust_indirect_blocks(struct gfs2_sbd *sbp, struct gfs2_inode *ip)
-{
- uint32_t gfs2_hgt;
- struct gfs2_buffer_head *bh;
- osi_list_t *tmp, *x;
- int h, header_size, bufsize, ptrnum;
- uint64_t *ptr1, block;
- uint64_t dinode_size;
- int error = 0, di_height;
- struct blocklist blocks, *blk, *newblk;
- struct metapath gfs2mp;
- struct gfs2_buffer_head *dibh = ip->i_bh;
-
- /* if there are no indirect blocks to check */
- if (ip->i_di.di_height <= 1)
- return 0;
-
- osi_list_init(&blocks.list);
-
- /* Add the dinode block to the blocks list */
- blk = malloc(sizeof(struct blocklist));
- if (!blk) {
- log_crit("Error: Can't allocate memory"
- " for indirect block fix.\n");
- return -1;
- }
- memset(blk, 0, sizeof(*blk));
- /* allocate a buffer to hold the pointers */
- bufsize = sbp->sd_inptrs * sizeof(uint64_t);
- blk->block = dibh->b_blocknr;
- blk->ptrbuf = malloc(bufsize);
- if (!blk->ptrbuf) {
- log_crit("Error: Can't allocate memory"
- " for file conversion.\n");
- free(blk);
- return -1;
- }
- memset(blk->ptrbuf, 0, bufsize);
- /* Fill in the pointers from the dinode buffer */
- memcpy(blk->ptrbuf, dibh->b_data + sizeof(struct gfs_dinode),
- sbp->bsize - sizeof(struct gfs_dinode));
- /* Zero out the pointers so we can fill them in later. */
- memset(dibh->b_data + sizeof(struct gfs_dinode), 0,
- sbp->bsize - sizeof(struct gfs_dinode));
- osi_list_add_prev(&blk->list, &blocks.list);
-
- /* Now run the metadata chain and build lists of all metadata blocks */
- osi_list_foreach(tmp, &blocks.list) {
- blk = osi_list_entry(tmp, struct blocklist, list);
-
- if (blk->height >= ip->i_di.di_height - 1)
- continue;
- header_size = (blk->height > 0 ? sizeof(struct gfs_indirect) :
- sizeof(struct gfs_dinode));
- for (ptr1 = (uint64_t *)blk->ptrbuf, ptrnum = 0;
- ptrnum < sbp->sd_inptrs; ptr1++, ptrnum++) {
- if (!*ptr1)
- continue;
-
- block = be64_to_cpu(*ptr1);
-
- newblk = malloc(sizeof(struct blocklist));
- if (!newblk) {
- log_crit("Error: Can't allocate memory"
- " for indirect block fix.\n");
- error = -1;
- goto out;
- }
- memset(newblk, 0, sizeof(*newblk));
- newblk->ptrbuf = malloc(bufsize);
- if (!newblk->ptrbuf) {
- log_crit("Error: Can't allocate memory"
- " for file conversion.\n");
- free(newblk);
- goto out;
- }
- memset(newblk->ptrbuf, 0, bufsize);
- newblk->block = block;
- newblk->height = blk->height + 1;
- /* Build the metapointer list from our predecessors */
- for (h = 0; h < blk->height; h++)
- newblk->mp.mp_list[h] = blk->mp.mp_list[h];
- newblk->mp.mp_list[h] = ptrnum;
- /* Queue it to be processed later on in the loop. */
- osi_list_add_prev(&newblk->list, &blocks.list);
-
- /* read the new metadata block's pointers */
- bh = bread(sbp, block);
- memcpy(newblk->ptrbuf, bh->b_data +
- sizeof(struct gfs_indirect), bufsize);
- /* Zero the buffer so we can fill it in later */
- memset(bh->b_data + sizeof(struct gfs_indirect), 0,
- bufsize);
- bmodified(bh);
- brelse(bh);
- /* Free the metadata block so we can reuse it.
- This allows us to convert a "full" file system. */
- ip->i_di.di_blocks--;
- gfs2_free_block(sbp, block);
- }
- }
-
- /* The gfs2 height may be different. We need to rebuild the
- metadata tree to the gfs2 height. */
- gfs2_hgt = calc_gfs2_tree_height(ip, ip->i_di.di_size);
- /* Save off the size because we're going to empty the contents
- and add the data blocks back in later. */
- dinode_size = ip->i_di.di_size;
- ip->i_di.di_size = 0ULL;
- di_height = ip->i_di.di_height;
- ip->i_di.di_height = 0;
-
- /* Now run through the block list a second time. If the block
- is the highest for metadata, rewrite the data to the gfs2
- offset. */
- osi_list_foreach_safe(tmp, &blocks.list, x) {
- unsigned int len;
- uint64_t *ptr2;
-
- blk = osi_list_entry(tmp, struct blocklist, list);
- /* If it's not metadata that holds data block pointers
- (i.e. metadata pointing to other metadata) */
- if (blk->height != di_height - 1) {
- osi_list_del(tmp);
- free(blk->ptrbuf);
- free(blk);
- continue;
- }
- /* Skip zero pointers at the start of the buffer. This may
- seem pointless, but the gfs1 blocks won't align with the
- gfs2 blocks. That means that a single block write of
- gfs1's pointers is likely to span two blocks on gfs2.
- That's a problem if the file system is full.
- So I'm trying to truncate the data at the start and end
- of the buffers (i.e. write only what we need to). */
- len = bufsize;
- for (ptr1 = (uint64_t *)blk->ptrbuf, ptrnum = 0;
- ptrnum < sbp->sd_inptrs; ptr1++, ptrnum++) {
- if (*ptr1 != 0x00)
- break;
- len -= sizeof(uint64_t);
- }
- /* Skip zero bytes at the end of the buffer */
- ptr2 = (uint64_t *)(blk->ptrbuf + bufsize) - 1;
- while (len > 0 && *ptr2 == 0) {
- ptr2--;
- len -= sizeof(uint64_t);
- }
- blk->mp.mp_list[di_height - 1] = ptrnum;
- mp_gfs1_to_gfs2(sbp, di_height, gfs2_hgt, &blk->mp, &gfs2mp);
- memcpy(&blk->mp, &gfs2mp, sizeof(struct metapath));
- blk->height -= di_height - gfs2_hgt;
- if (len)
- fix_metatree(sbp, ip, blk, ptr1, len);
- osi_list_del(tmp);
- free(blk->ptrbuf);
- free(blk);
- }
- ip->i_di.di_size = dinode_size;
-
- /* Set the new dinode height, which may or may not have changed. */
- /* The caller will take it from the ip and write it to the buffer */
- ip->i_di.di_height = gfs2_hgt;
- return 0;
-
-out:
- while (!osi_list_empty(&blocks.list)) {
- blk = osi_list_entry(tmp, struct blocklist, list);
- osi_list_del(&blocks.list);
- free(blk->ptrbuf);
- free(blk);
- }
- return error;
-}
-
-static void jdata_mp_gfs1_to_gfs2(struct gfs2_sbd *sbp, int gfs1_h, int gfs2_h,
- struct metapath *gfs1mp, struct metapath *gfs2mp,
- unsigned int *len, uint64_t dinode_size)
-{
- uint64_t offset;
- int h;
- uint64_t gfs1factor[GFS2_MAX_META_HEIGHT];
- uint64_t gfs2factor[GFS2_MAX_META_HEIGHT];
-
- /* figure out multiplication factors for each height - gfs1 */
- memset(&gfs1factor, 0, sizeof(gfs1factor));
- gfs1factor[gfs1_h - 1] = sbp->bsize - sizeof(struct gfs2_meta_header);
- for (h = gfs1_h - 1; h > 0; h--)
- gfs1factor[h - 1] = gfs1factor[h] * sbp->sd_inptrs;
-
- /* figure out multiplication factors for each height - gfs2 */
- memset(&gfs2factor, 0, sizeof(gfs2factor));
- gfs2factor[gfs2_h] = 1ull;
- gfs2factor[gfs2_h - 1] = sbp->bsize;
- for (h = gfs2_h - 1; h > 0; h--)
- gfs2factor[h - 1] = gfs2factor[h] * gfs2_inptrs;
-
- /* Convert from gfs1 to an offset */
- offset = 0;
- for (h = 0; h < gfs1_h; h++)
- offset += (gfs1mp->mp_list[h] * gfs1factor[h]);
-
- if (dinode_size - offset < *len)
- *len = dinode_size - offset;
-
- /* Convert from an offset back to gfs2 */
- memset(gfs2mp, 0, sizeof(*gfs2mp));
- for (h = 0; h <= gfs2_h; h++) {
- /* Can't use do_div here because the factors are too large. */
- gfs2mp->mp_list[h] = offset / gfs2factor[h];
- offset %= gfs2factor[h];
- }
-}
-
-static void fix_jdatatree(struct gfs2_sbd *sbp, struct gfs2_inode *ip,
- struct blocklist *blk, char *srcptr,
- unsigned int size)
-{
- uint64_t block;
- struct gfs2_buffer_head *bh;
- unsigned int amount, ptramt;
- int h, copied = 0, new = 0;
- struct gfs2_meta_header mh;
-
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_IN;
- mh.mh_format = GFS2_FORMAT_IN;
-
- if (!ip->i_di.di_height)
- unstuff_dinode(ip);
-
- ptramt = blk->mp.mp_list[blk->height];
- amount = size;
-
- while (copied < size) {
- bh = ip->i_bh;
- /* First, build up the metatree */
- for (h = 0; h < blk->height; h++) {
- new = 0;
- lookup_block(ip, bh, h, &blk->mp, 1, &new, &block);
- if (bh != ip->i_bh)
- brelse(bh);
- if (!block)
- break;
-
- bh = bread(sbp, block);
- if (new)
- memset(bh->b_data, 0, sbp->bsize);
- if (h < (blk->height - 1))
- gfs2_meta_header_out(&mh, bh);
- }
-
- if (amount > sbp->bsize - ptramt)
- amount = sbp->bsize - ptramt;
-
- memcpy(bh->b_data + ptramt, (char *)srcptr, amount);
- srcptr += amount;
- bmodified(bh);
- if (bh != ip->i_bh)
- brelse(bh);
-
- copied += amount;
-
- if (ptramt + amount >= sbp->bsize) {
- /* advance to the next metablock */
- blk->mp.mp_list[blk->height] += amount;
- for (h = blk->height; h > 0; h--) {
- if (blk->mp.mp_list[h] >= gfs2_inptrs) {
- blk->mp.mp_list[h] = 0;
- blk->mp.mp_list[h - 1]++;
- continue;
- }
- break;
- }
- }
- amount = size - copied;
- ptramt = 0;
- }
-}
-
-static int adjust_jdata_inode(struct gfs2_sbd *sbp, struct gfs2_inode *ip)
-{
- uint32_t gfs2_hgt;
- struct gfs2_buffer_head *bh;
- osi_list_t *tmp, *x;
- int h, header_size, bufsize, ptrnum;
- uint64_t *ptr1, block;
- uint64_t dinode_size;
- int error = 0, di_height;
- struct blocklist blocks, *blk, *newblk;
- struct metapath gfs2mp;
- struct gfs2_buffer_head *dibh = ip->i_bh;
-
- /* Don't have to worry about things with stuffed inodes */
- if (ip->i_di.di_height == 0)
- return 0;
-
- osi_list_init(&blocks.list);
-
- /* Add the dinode block to the blocks list */
- blk = malloc(sizeof(struct blocklist));
- if (!blk) {
- log_crit("Error: Can't allocate memory"
- " for indirect block fix.\n");
- return -1;
- }
- memset(blk, 0, sizeof(*blk));
- /* allocate a buffer to hold the pointers or data */
- bufsize = sbp->bsize - sizeof(struct gfs2_meta_header);
- blk->block = dibh->b_blocknr;
- /*
- * blk->ptrbuf either contains
- * a) diptrs (for height=0)
- * b) inptrs (for height=1 to di_height - 1)
- * c) data for height = di_height
- */
- blk->ptrbuf = malloc(bufsize);
- if (!blk->ptrbuf) {
- log_crit("Error: Can't allocate memory"
- " for file conversion.\n");
- free(blk);
- return -1;
- }
- memset(blk->ptrbuf, 0, bufsize);
- /* Fill in the pointers from the dinode buffer */
- memcpy(blk->ptrbuf, dibh->b_data + sizeof(struct gfs_dinode),
- sbp->bsize - sizeof(struct gfs_dinode));
- /* Zero out the pointers so we can fill them in later. */
- memset(dibh->b_data + sizeof(struct gfs_dinode), 0,
- sbp->bsize - sizeof(struct gfs_dinode));
- osi_list_add_prev(&blk->list, &blocks.list);
-
- /* Now run the metadata chain and build lists of all metadata blocks */
- osi_list_foreach(tmp, &blocks.list) {
- blk = osi_list_entry(tmp, struct blocklist, list);
-
- if (blk->height >= ip->i_di.di_height - 1)
- continue;
- header_size = (blk->height > 0 ? sizeof(struct gfs_indirect) :
- sizeof(struct gfs_dinode));
- for (ptr1 = (uint64_t *)blk->ptrbuf, ptrnum = 0;
- ptrnum < sbp->sd_inptrs; ptr1++, ptrnum++) {
- if (!*ptr1)
- continue;
-
- block = be64_to_cpu(*ptr1);
-
- newblk = malloc(sizeof(struct blocklist));
- if (!newblk) {
- log_crit("Error: Can't allocate memory"
- " for indirect block fix.\n");
- error = -1;
- goto out;
- }
- memset(newblk, 0, sizeof(*newblk));
- newblk->ptrbuf = malloc(bufsize);
- if (!newblk->ptrbuf) {
- log_crit("Error: Can't allocate memory"
- " for file conversion.\n");
- free(newblk);
- goto out;
- }
- memset(newblk->ptrbuf, 0, bufsize);
- newblk->block = block;
- newblk->height = blk->height + 1;
- /* Build the metapointer list from our predecessors */
- for (h = 0; h < blk->height; h++)
- newblk->mp.mp_list[h] = blk->mp.mp_list[h];
- newblk->mp.mp_list[h] = ptrnum;
- /* Queue it to be processed later on in the loop. */
- osi_list_add_prev(&newblk->list, &blocks.list);
-
- /* read the new metadata block's pointers */
- bh = bread(sbp, block);
- memcpy(newblk->ptrbuf, bh->b_data + sizeof(struct gfs_indirect),
- sbp->bsize - sizeof(struct gfs_indirect));
- /* Zero the buffer so we can fill it in later */
- memset(bh->b_data + sizeof(struct gfs_indirect), 0,
- sbp->bsize - sizeof(struct gfs_indirect));
- bmodified(bh);
- brelse(bh);
- /* Free the block so we can reuse it. This allows us to
- convert a "full" file system. */
- ip->i_di.di_blocks--;
- gfs2_free_block(sbp, block);
- }
- }
- /* The gfs2 height may be different. We need to rebuild the
- metadata tree to the gfs2 height. */
- gfs2_hgt = calc_gfs2_tree_height(ip, ip->i_di.di_size);
- /* Save off the size because we're going to empty the contents
- and add the data blocks back in later. */
- dinode_size = ip->i_di.di_size;
- ip->i_di.di_size = 0ULL;
- di_height = ip->i_di.di_height;
- ip->i_di.di_height = 0;
-
- /* Now run through the block list a second time. If the block
- is a data block, rewrite the data to the gfs2 offset. */
- osi_list_foreach_safe(tmp, &blocks.list, x) {
- unsigned int len;
-
- blk = osi_list_entry(tmp, struct blocklist, list);
- /* If it's not a highest level indirect block */
- if (blk->height != di_height - 1) {
- osi_list_del(tmp);
- free(blk->ptrbuf);
- free(blk);
- continue;
- }
- /*
- * For each metadata block that holds jdata block pointers,
- * get the blk pointers and copy them block by block
- */
- for (ptr1 = (uint64_t *) blk->ptrbuf, ptrnum = 0;
- ptrnum < sbp->sd_inptrs; ptr1++, ptrnum++) {
- if (!*ptr1)
- continue;
- block = be64_to_cpu(*ptr1);
-
- newblk = malloc(sizeof(struct blocklist));
- if (!newblk) {
- log_crit("Error: Can't allocate memory"
- " for indirect block fix.\n");
- error = -1;
- goto out;
- }
- memset(newblk, 0, sizeof(*newblk));
- newblk->ptrbuf = malloc(bufsize);
- if (!newblk->ptrbuf) {
- log_crit("Error: Can't allocate memory"
- " for file conversion.\n");
- free(newblk);
- goto out;
- }
- memset(newblk->ptrbuf, 0, bufsize);
- newblk->block = block;
- newblk->height = blk->height + 1;
- /* Build the metapointer list from our predecessors */
- for (h=0; h < blk->height; h++)
- newblk->mp.mp_list[h] = blk->mp.mp_list[h];
- newblk->mp.mp_list[h] = ptrnum;
- bh = bread(sbp, block);
- /* This is a data block. i.e newblk->height == ip->i_di.di_height */
- /* read in the jdata block */
- memcpy(newblk->ptrbuf, bh->b_data +
- sizeof(struct gfs2_meta_header), bufsize);
- memset(bh->b_data + sizeof(struct gfs2_meta_header), 0,
- bufsize);
- bmodified(bh);
- brelse(bh);
- /* Free the block so we can reuse it. This allows us to
- convert a "full" file system */
- ip->i_di.di_blocks--;
- gfs2_free_block(sbp, block);
-
- len = bufsize;
- jdata_mp_gfs1_to_gfs2(sbp, di_height, gfs2_hgt, &newblk->mp, &gfs2mp,
- &len, dinode_size);
- memcpy(&newblk->mp, &gfs2mp, sizeof(struct metapath));
- newblk->height -= di_height - gfs2_hgt;
- if (len)
- fix_jdatatree(sbp, ip, newblk, newblk->ptrbuf, len);
- free(newblk->ptrbuf);
- free(newblk);
- }
- osi_list_del(tmp);
- free(blk->ptrbuf);
- free(blk);
- }
- ip->i_di.di_size = dinode_size;
-
- /* Set the new dinode height, which may or may not have changed. */
- /* The caller will take it from the ip and write it to the buffer */
- ip->i_di.di_height = gfs2_hgt;
- return 0;
-
-out:
- while (!osi_list_empty(&blocks.list)) {
- blk = osi_list_entry(tmp, struct blocklist, list);
- osi_list_del(&blocks.list);
- free(blk->ptrbuf);
- free(blk);
- }
- return error;
-}
-
-const char *cdpn[14] = {"{hostname}", "{mach}", "{os}", "{uid}", "{gid}", "{sys}", "{jid}",
- "@hostname", "@mach", "@os", "@uid", "@gid", "@sys", "@jid"};
-static int has_cdpn(const char *str)
-{
- int i;
- for (i=0; i<14; i++)
- if (strstr(str, cdpn[i]) != NULL)
- return 1;
- return 0;
-}
-
-static int fix_cdpn_symlink(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh, struct gfs2_inode *ip)
-{
- int ret = 0;
- char *linkptr = NULL;
-
- if (ip->i_di.di_height != 0)
- return 0;
-
- linkptr = bh->b_data + sizeof(struct gfs_dinode);
- if (has_cdpn(linkptr)) {
- struct inode_dir_block *fix;
- /* Save the symlink di_addr. We'll find the parent di_addr later */
- fix = malloc(sizeof(struct inode_dir_block));
- if (!fix) {
- log_crit("Error: out of memory.\n");
- return -1;
- }
- memset(fix, 0, sizeof(struct inode_dir_block));
- fix->di_addr = ip->i_di.di_num.no_addr;
- osi_list_add_prev((osi_list_t *)&fix->list,
- (osi_list_t *)&cdpns_to_fix);
- }
-
- return ret;
-}
-
-/*
- * fix_xattr -
- * Extended attributes can be either direct (in the ip->i_di.di_eattr block) or
- * then can be at a maximum of 1 indirect level. Multiple levels of indirection
- * are not supported. If the di_eattr block contains extended attribute data,
- * i.e block type = GFS_METATYPE_EA, we ignore it.
- * If the di_eattr block contains block pointers to extended attributes we need
- * to fix the header. gfs1 uses gfs_indirect as the header which is 64 bytes
- * bigger than gfs2_meta_header that gfs2 uses.
- */
-static int fix_xattr(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh, struct gfs2_inode *ip)
-{
- int ret = 0, len, old_hdr_sz, new_hdr_sz;
- struct gfs2_buffer_head *eabh;
- char *buf;
-
- /* Read in the i_di.di_eattr block */
- eabh = bread(sbp, ip->i_di.di_eattr);
- if (!gfs2_check_meta(eabh, GFS_METATYPE_IN)) {/* if it is an indirect block */
- len = sbp->bsize - sizeof(struct gfs_indirect);
- buf = malloc(len);
- if (!buf) {
- log_crit("Error: out of memory.\n");
- return -1;
- }
- old_hdr_sz = sizeof(struct gfs_indirect);
- new_hdr_sz = sizeof(struct gfs2_meta_header);
- memcpy(buf, eabh->b_data + old_hdr_sz, sbp->bsize - old_hdr_sz);
- memset(eabh->b_data + new_hdr_sz, 0, sbp->bsize - new_hdr_sz);
- memcpy(eabh->b_data + new_hdr_sz, buf, len);
- free(buf);
- bmodified(eabh);
- }
- brelse(eabh);
-
- return ret;
-}
-
-/* ------------------------------------------------------------------------- */
-/* adjust_inode - change an inode from gfs1 to gfs2 */
-/* */
-/* Returns: 0 on success, -1 on failure */
-/* ------------------------------------------------------------------------- */
-static int adjust_inode(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh)
-{
- struct gfs2_inode *inode;
- struct inode_block *fixdir;
- int inode_was_gfs1;
-
- inode = gfs_inode_get(sbp, bh);
-
- inode_was_gfs1 = (inode->i_di.di_num.no_formal_ino ==
- inode->i_di.di_num.no_addr);
- /* Fix the inode number: */
- inode->i_di.di_num.no_formal_ino = sbp->md.next_inum; ;
-
- /* Fix the inode type: gfs1 uses di_type, gfs2 uses di_mode. */
- switch (inode->i_di.__pad1) { /* formerly di_type */
- case GFS_FILE_DIR: /* directory */
- inode->i_di.di_mode |= S_IFDIR;
- /* Add this directory to the list of dirs to fix later. */
- fixdir = malloc(sizeof(struct inode_block));
- if (!fixdir) {
- log_crit("Error: out of memory.\n");
- return -1;
- }
- memset(fixdir, 0, sizeof(struct inode_block));
- fixdir->di_addr = inode->i_di.di_num.no_addr;
- osi_list_add_prev((osi_list_t *)&fixdir->list,
- (osi_list_t *)&dirs_to_fix);
- break;
- case GFS_FILE_REG: /* regular file */
- inode->i_di.di_mode |= S_IFREG;
- break;
- case GFS_FILE_LNK: /* symlink */
- inode->i_di.di_mode |= S_IFLNK;
- break;
- case GFS_FILE_BLK: /* block device */
- inode->i_di.di_mode |= S_IFBLK;
- break;
- case GFS_FILE_CHR: /* character device */
- inode->i_di.di_mode |= S_IFCHR;
- break;
- case GFS_FILE_FIFO: /* fifo / pipe */
- inode->i_di.di_mode |= S_IFIFO;
- break;
- case GFS_FILE_SOCK: /* socket */
- inode->i_di.di_mode |= S_IFSOCK;
- break;
- }
-
- /* ----------------------------------------------------------- */
- /* gfs2 inodes are slightly different from gfs1 inodes in that */
- /* di_goal_meta has shifted locations and di_goal_data has */
- /* changed from 32-bits to 64-bits. The following code */
- /* adjusts for the shift. */
- /* */
- /* Note: It may sound absurd, but we need to check if this */
- /* inode has already been converted to gfs2 or if it's */
- /* still a gfs1 inode. That's just in case there was a */
- /* prior attempt to run gfs2_convert that never finished */
- /* (due to power out, ctrl-c, kill, segfault, whatever.) */
- /* If it is unconverted gfs1 we want to do a full */
- /* conversion. If it's a gfs2 inode from a prior run, */
- /* we still need to renumber the inode, but here we */
- /* don't want to shift the data around. */
- /* ----------------------------------------------------------- */
- if (inode_was_gfs1) {
- struct gfs_dinode *gfs1_dinode_struct;
- int ret = 0;
-
- gfs1_dinode_struct = (struct gfs_dinode *)&inode->i_di;
- inode->i_di.di_goal_meta = inode->i_di.di_goal_data;
- inode->i_di.di_goal_data = 0; /* make sure the upper 32b are 0 */
- inode->i_di.di_goal_data = gfs1_dinode_struct->di_goal_dblk;
- inode->i_di.di_generation = 0;
- if (!(inode->i_di.di_mode & S_IFDIR) &&
- inode->i_di.di_flags & GFS2_DIF_JDATA)
- ret = adjust_jdata_inode(sbp, inode);
- else
- ret = adjust_indirect_blocks(sbp, inode);
- if (ret)
- return -1;
- /* Check for cdpns */
- if (inode->i_di.di_mode & S_IFLNK) {
- ret = fix_cdpn_symlink(sbp, bh, inode);
- if (ret)
- return -1;
- }
- /* Check for extended attributes */
- if (inode->i_di.di_eattr) {
- ret = fix_xattr(sbp, bh, inode);
- if (ret)
- return -1;
- }
- }
-
- bmodified(inode->i_bh);
- inode_put(&inode); /* does gfs2_dinode_out if modified */
- sbp->md.next_inum++; /* update inode count */
- return 0;
-} /* adjust_inode */
-
-/* ------------------------------------------------------------------------- */
-/* inode_renumber - renumber the inodes */
-/* */
-/* In gfs1, the inode number WAS the inode address. In gfs2, the inodes are */
-/* numbered sequentially. */
-/* */
-/* Returns: 0 on success, -1 on failure */
-/* ------------------------------------------------------------------------- */
-static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr, osi_list_t *cdpn_to_fix)
-{
- struct rgrp_list *rgd;
- osi_list_t *tmp;
- uint64_t block;
- struct gfs2_buffer_head *bh;
- int first;
- int error = 0;
- int rgs_processed = 0;
-
- log_notice("Converting inodes.\n");
- sbp->md.next_inum = 1; /* starting inode numbering */
- gettimeofday(&tv, NULL);
- seconds = tv.tv_sec;
-
- /* ---------------------------------------------------------------- */
- /* Traverse the resource groups to figure out where the inodes are. */
- /* ---------------------------------------------------------------- */
- osi_list_foreach(tmp, &sbp->rglist) {
- rgs_processed++;
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- first = 1;
- while (1) { /* for all inodes in the resource group */
- gettimeofday(&tv, NULL);
- /* Put out a warm, fuzzy message every second so the customer */
- /* doesn't think we hung. (This may take a long time). */
- if (tv.tv_sec - seconds) {
- seconds = tv.tv_sec;
- log_notice("\r%" PRIu64" inodes from %d rgs "
- "converted.", sbp->md.next_inum,
- rgs_processed);
- fflush(stdout);
- }
- /* Get the next metadata block. Break out if we reach the end. */
- /* We have to check all metadata blocks because the bitmap may */
- /* be "11" (used meta) for both inodes and indirect blocks. */
- /* We need to process the inodes and change the indirect blocks */
- /* to have a bitmap type of "01" (data). */
- if (gfs2_next_rg_metatype(sbp, rgd, &block, 0, first))
- break;
- /* If this is the root inode block, remember it for later: */
- if (block == root_inode_addr) {
- sbp->sd_sb.sb_root_dir.no_addr = block;
- sbp->sd_sb.sb_root_dir.no_formal_ino = sbp->md.next_inum;
- }
- bh = bread(sbp, block);
- if (!gfs2_check_meta(bh, GFS_METATYPE_DI)) {/* if it is an dinode */
- /* Skip the rindex and jindex inodes for now. */
- if (block != rindex_addr && block != jindex_addr)
- error = adjust_inode(sbp, bh);
- } else { /* It's metadata, but not an inode, so fix the bitmap. */
- int blk, buf_offset;
- int bitmap_byte; /* byte within the bitmap to fix */
- int byte_bit; /* bit within the byte */
-
- /* Figure out the absolute bitmap byte we need to fix. */
- /* ignoring structure offsets and bitmap blocks for now. */
- bitmap_byte = (block - rgd->ri.ri_data0) / GFS2_NBBY;
- byte_bit = (block - rgd->ri.ri_data0) % GFS2_NBBY;
- /* Now figure out which bitmap block the byte is on */
- for (blk = 0; blk < rgd->ri.ri_length; blk++) {
- /* figure out offset of first bitmap byte for this map: */
- buf_offset = (blk) ? sizeof(struct gfs2_meta_header) :
- sizeof(struct gfs2_rgrp);
- /* if it's on this page */
- if (buf_offset + bitmap_byte < sbp->bsize) {
- rgd->bh[blk]->b_data[buf_offset + bitmap_byte] &=
- ~(0x03 << (GFS2_BIT_SIZE * byte_bit));
- rgd->bh[blk]->b_data[buf_offset + bitmap_byte] |=
- (0x01 << (GFS2_BIT_SIZE * byte_bit));
- break;
- }
- bitmap_byte -= (sbp->bsize - buf_offset);
- bmodified(rgd->bh[blk]);
- }
- }
- brelse(bh);
- first = 0;
- } /* while 1 */
- } /* for all rgs */
- log_notice("\r%" PRIu64" inodes from %d rgs converted.",
- sbp->md.next_inum, rgs_processed);
- fflush(stdout);
- return 0;
-}/* inode_renumber */
-
-/* ------------------------------------------------------------------------- */
-/* fetch_inum - fetch an inum entry from disk, given its block */
-/* ------------------------------------------------------------------------- */
-static int fetch_inum(struct gfs2_sbd *sbp, uint64_t iblock,
- struct gfs2_inum *inum, uint64_t *eablk)
-{
- struct gfs2_inode *fix_inode;
-
- fix_inode = inode_read(sbp, iblock);
- inum->no_formal_ino = fix_inode->i_di.di_num.no_formal_ino;
- inum->no_addr = fix_inode->i_di.di_num.no_addr;
- if (eablk)
- *eablk = fix_inode->i_di.di_eattr;
-
- inode_put(&fix_inode);
- return 0;
-}/* fetch_inum */
-
-/* ------------------------------------------------------------------------- */
-/* process_dirent_info - fix one dirent (directory entry) buffer */
-/* */
-/* We changed inode numbers, so we must update that number into the */
-/* directory entries themselves. */
-/* */
-/* Returns: 0 on success, -1 on failure, -EISDIR when dentmod marked DT_DIR */
-/* ------------------------------------------------------------------------- */
-static int process_dirent_info(struct gfs2_inode *dip, struct gfs2_sbd *sbp,
- struct gfs2_buffer_head *bh, int dir_entries, uint64_t dentmod)
-{
- int error = 0;
- struct gfs2_dirent *dent;
- int de; /* directory entry index */
-
- error = gfs2_dirent_first(dip, bh, &dent);
- if (error != IS_LEAF && error != IS_DINODE) {
- log_crit("Error retrieving directory.\n");
- return -1;
- }
- error = 0;
- /* Go through every dirent in the buffer and process it. */
- /* Turns out you can't trust dir_entries is correct. */
- for (de = 0; ; de++) {
- struct gfs2_inum inum;
- int dent_was_gfs1;
-
- if (dentmod) {
- if (dent->de_type == cpu_to_be16(DT_LNK)
- && cpu_to_be64(dent->de_inum.no_addr) == dentmod) {
- dent->de_type = cpu_to_be16(DT_DIR);
- error = -EISDIR;
- break;
- }
- goto skip_next;
- }
-
- gettimeofday(&tv, NULL);
- /* Do more warm fuzzy stuff for the customer. */
- dirents_fixed++;
- if (tv.tv_sec - seconds) {
- seconds = tv.tv_sec;
- log_notice("\r%" PRIu64 " directories, %" PRIu64 " dirents fixed.",
- dirs_fixed, dirents_fixed);
- fflush(stdout);
- }
- /* fix the dirent's inode number based on the inode */
- gfs2_inum_in(&inum, (char *)&dent->de_inum);
- dent_was_gfs1 = (dent->de_inum.no_addr == dent->de_inum.no_formal_ino);
- if (inum.no_formal_ino) { /* if not a sentinel (placeholder) */
- error = fetch_inum(sbp, inum.no_addr, &inum, NULL);
- if (error) {
- log_crit("Error retrieving inode 0x%llx\n",
- (unsigned long long)inum.no_addr);
- break;
- }
- /* fix the dirent's inode number from the fetched inum. */
- dent->de_inum.no_formal_ino = cpu_to_be64(inum.no_formal_ino);
- }
- /* Fix the dirent's filename hash: They are the same as gfs1 */
- /* dent->de_hash = cpu_to_be32(gfs2_disk_hash((char *)(dent + 1), */
- /* be16_to_cpu(dent->de_name_len))); */
- /* Fix the dirent's file type. Gfs1 used home-grown values. */
- /* Gfs2 uses standard values from include/linux/fs.h */
- /* Only do this if the dent was a true gfs1 dent, and not a */
- /* gfs2 dent converted from a previously aborted run. */
- if (dent_was_gfs1) {
- switch be16_to_cpu(dent->de_type) {
- case GFS_FILE_NON:
- dent->de_type = cpu_to_be16(DT_UNKNOWN);
- break;
- case GFS_FILE_REG: /* regular file */
- dent->de_type = cpu_to_be16(DT_REG);
- break;
- case GFS_FILE_DIR: /* directory */
- dent->de_type = cpu_to_be16(DT_DIR);
- break;
- case GFS_FILE_LNK: /* link */
- dent->de_type = cpu_to_be16(DT_LNK);
- break;
- case GFS_FILE_BLK: /* block device node */
- dent->de_type = cpu_to_be16(DT_BLK);
- break;
- case GFS_FILE_CHR: /* character device node */
- dent->de_type = cpu_to_be16(DT_CHR);
- break;
- case GFS_FILE_FIFO: /* fifo/pipe */
- dent->de_type = cpu_to_be16(DT_FIFO);
- break;
- case GFS_FILE_SOCK: /* socket */
- dent->de_type = cpu_to_be16(DT_SOCK);
- break;
- }
- }
- /*
- * Compare this dirent address with every one in the
- * cdpns_to_fix list to find if this directory (dip) is
- * a cdpn symlink's parent. If so add it to the list element
- */
- if (dent->de_type == cpu_to_be16(DT_LNK)) {
- osi_list_t *tmp;
- struct inode_dir_block *fix;
- osi_list_foreach(tmp, &cdpns_to_fix.list) {
- fix = osi_list_entry(tmp, struct inode_dir_block, list);
- if (fix->di_addr == inum.no_addr)
- fix->di_paddr = dip->i_di.di_num.no_addr;
- }
- }
-
- skip_next:
- error = gfs2_dirent_next(dip, bh, &dent);
- if (error) {
- if (error == -ENOENT) /* beyond the end of this bh */
- error = 0;
- break;
- }
- } /* for every directory entry */
- return error;
-}/* process_dirent_info */
-
-/* ------------------------------------------------------------------------- */
-/* fix_one_directory_exhash - fix one directory's inode numbers. */
-/* */
-/* This is for exhash directories, where the inode has a list of "leaf" */
-/* blocks, each of which is a buffer full of dirents that must be processed. */
-/* */
-/* Returns: 0 on success, -1 on failure */
-/* ------------------------------------------------------------------------- */
-static int fix_one_directory_exhash(struct gfs2_sbd *sbp, struct gfs2_inode *dip, uint64_t dentmod)
-{
- struct gfs2_buffer_head *bh_leaf;
- int error;
- uint64_t leaf_block, prev_leaf_block;
- uint32_t leaf_num;
-
- prev_leaf_block = 0;
- /* for all the leafs, get the leaf block and process the dirents inside */
- for (leaf_num = 0; ; leaf_num++) {
- uint64_t buf;
- struct gfs2_leaf leaf;
-
- error = gfs2_readi(dip, (char *)&buf, leaf_num * sizeof(uint64_t),
- sizeof(uint64_t));
- if (!error) /* end of file */
- return 0; /* success */
- else if (error != sizeof(uint64_t)) {
- log_crit("fix_one_directory_exhash: error reading directory.\n");
- return -1;
- }
- else {
- leaf_block = be64_to_cpu(buf);
- error = 0;
- }
- /* leaf blocks may be repeated, so skip the duplicates: */
- if (leaf_block == prev_leaf_block) /* same block? */
- continue; /* already converted */
- prev_leaf_block = leaf_block;
- /* read the leaf buffer in */
- error = gfs2_get_leaf(dip, leaf_block, &bh_leaf);
- if (error) {
- log_crit("Error reading leaf %" PRIx64 "\n", leaf_block);
- break;
- }
- gfs2_leaf_in(&leaf, bh_leaf); /* buffer to structure */
- error = process_dirent_info(dip, sbp, bh_leaf, leaf.lf_entries, dentmod);
- bmodified(bh_leaf);
- brelse(bh_leaf);
- if (dentmod && error == -EISDIR) /* dentmod was marked DT_DIR, break out */
- break;
- } /* for leaf_num */
- return 0;
-}/* fix_one_directory_exhash */
-
-static int process_directory(struct gfs2_sbd *sbp, uint64_t dirblock, uint64_t dentmod)
-{
- struct gfs2_inode *dip;
- int error = 0;
- /* read in the directory inode */
- dip = inode_read(sbp, dirblock);
- /* fix the directory: either exhash (leaves) or linear (stuffed) */
- if (dip->i_di.di_flags & GFS2_DIF_EXHASH) {
- if (fix_one_directory_exhash(sbp, dip, dentmod)) {
- log_crit("Error fixing exhash directory.\n");
- inode_put(&dip);
- return -1;
- }
- } else {
- error = process_dirent_info(dip, sbp, dip->i_bh, dip->i_di.di_entries, dentmod);
- if (error && error != -EISDIR) {
- log_crit("Error fixing linear directory.\n");
- inode_put(&dip);
- return -1;
- }
- }
- bmodified(dip->i_bh);
- inode_put(&dip);
- return 0;
-}
-/* ------------------------------------------------------------------------- */
-/* fix_directory_info - sync new inode numbers with directory info */
-/* Returns: 0 on success, -1 on failure */
-/* ------------------------------------------------------------------------- */
-static int fix_directory_info(struct gfs2_sbd *sbp, osi_list_t *dir_to_fix)
-{
- osi_list_t *tmp, *fix;
- struct inode_block *dir_iblk;
- uint64_t offset, dirblock;
-
- dirs_fixed = 0;
- dirents_fixed = 0;
- gettimeofday(&tv, NULL);
- seconds = tv.tv_sec;
- log_notice("\nFixing file and directory information.\n");
- fflush(stdout);
- offset = 0;
- tmp = NULL;
- /* for every directory in the list */
- for (fix = dir_to_fix->next; fix != dir_to_fix; fix = fix->next) {
- if (tmp) {
- osi_list_del(tmp);
- free(tmp);
- }
- tmp = fix; /* remember the addr to free next time */
- dirs_fixed++;
- /* figure out the directory inode block and read it in */
- dir_iblk = (struct inode_block *)fix;
- dirblock = dir_iblk->di_addr; /* addr of dir inode */
- if (process_directory(sbp, dirblock, 0)) {
- log_crit("Error processing directory\n");
- return -1;
- }
- }
- /* Free the last entry in memory: */
- if (tmp) {
- osi_list_del(tmp);
- free(tmp);
- }
- return 0;
-}/* fix_directory_info */
-
-/* ------------------------------------------------------------------------- */
-/* fix_cdpn_symlinks - convert cdpn symlinks to empty directories */
-/* Returns: 0 on success, -1 on failure */
-/* ------------------------------------------------------------------------- */
-static int fix_cdpn_symlinks(struct gfs2_sbd *sbp, osi_list_t *cdpn_to_fix)
-{
- osi_list_t *tmp, *x;
- int error = 0;
-
- cdpns_fixed = 0;
- osi_list_foreach_safe(tmp, cdpn_to_fix, x) {
- struct gfs2_inum fix, dir;
- struct inode_dir_block *l_fix;
- struct gfs2_buffer_head *bh;
- struct gfs2_inode *fix_inode;
- uint64_t eablk;
-
- l_fix = osi_list_entry(tmp, struct inode_dir_block, list);
- osi_list_del(tmp);
-
- /* convert symlink to empty dir */
- error = fetch_inum(sbp, l_fix->di_addr, &fix, &eablk);
- if (error) {
- log_crit("Error retrieving inode at block %llx\n",
- (unsigned long long)l_fix->di_addr);
- break;
- }
- error = fetch_inum(sbp, l_fix->di_paddr, &dir, NULL);
- if (error) {
- log_crit("Error retrieving inode at block %llx\n",
- (unsigned long long)l_fix->di_paddr);
- break;
- }
-
- /* initialize the symlink inode to be a directory */
- bh = init_dinode(sbp, &fix, S_IFDIR | 0755, 0, &dir);
- fix_inode = inode_get(sbp, bh);
- fix_inode->i_di.di_eattr = eablk; /*fix extended attribute */
- inode_put(&fix_inode);
- bmodified(bh);
- brelse(bh);
-
- /* fix the parent directory dirent entry for this inode */
- error = process_directory(sbp, l_fix->di_paddr, l_fix->di_addr);
- if (error) {
- log_crit("Error trying to fix cdpn dentry\n");
- break;
- }
- free(l_fix);
- cdpns_fixed++;
- }
- return error;
-} /* fix_cdpn_symlinks */
-
-/* ------------------------------------------------------------------------- */
-/* Fetch gfs1 jindex structure from buffer */
-/* ------------------------------------------------------------------------- */
-static void gfs1_jindex_in(struct gfs1_jindex *jindex, char *buf)
-{
- struct gfs1_jindex *str = (struct gfs1_jindex *)buf;
-
- jindex->ji_addr = be64_to_cpu(str->ji_addr);
- jindex->ji_nsegment = be32_to_cpu(str->ji_nsegment);
- memset(jindex->ji_reserved, 0, 64);
-}
-
-/* ------------------------------------------------------------------------- */
-/* read_gfs1_jiindex - read the gfs1 jindex file. */
-/* Returns: 0 on success, -1 on failure */
-/* ------------------------------------------------------------------------- */
-static int read_gfs1_jiindex(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *ip = sdp->md.jiinode;
- char buf[sizeof(struct gfs1_jindex)];
- unsigned int j;
- int error=0;
- unsigned int tmp_mode = 0;
-
- if(ip->i_di.di_size % sizeof(struct gfs1_jindex) != 0){
- log_crit("The size reported in the journal index"
- " inode is not a\n"
- "\tmultiple of the size of a journal index.\n");
- return -1;
- }
- if(!(sd_jindex = (struct gfs1_jindex *)malloc(ip->i_di.di_size))) {
- log_crit("Unable to allocate journal index\n");
- return -1;
- }
- if(!memset(sd_jindex, 0, ip->i_di.di_size)) {
- log_crit("Unable to zero journal index\n");
- return -1;
- }
- /* ugly hack
- * Faking the gfs1_jindex inode as a directory to gfs2_readi
- * so it skips the metaheader struct in the data blocks
- * in the inode. gfs2_jindex inode doesn't have metaheaders
- * in the data blocks */
- tmp_mode = ip->i_di.di_mode;
- ip->i_di.di_mode &= ~S_IFMT;
- ip->i_di.di_mode |= S_IFDIR;
- for (j = 0; ; j++) {
- struct gfs1_jindex *journ;
-
- error = gfs2_readi(ip, buf, j * sizeof(struct gfs1_jindex),
- sizeof(struct gfs1_jindex));
- if(!error)
- break;
- if (error != sizeof(struct gfs1_jindex)){
- log_crit("An error occurred while reading the"
- " journal index file.\n");
- goto fail;
- }
- journ = sd_jindex + j;
- gfs1_jindex_in(journ, buf);
- sdp->jsize = (journ->ji_nsegment * 16 * sdp->bsize) >> 20;
- }
- ip->i_di.di_mode = tmp_mode;
- if(j * sizeof(struct gfs1_jindex) != ip->i_di.di_size){
- log_crit("journal inode size invalid\n");
- goto fail;
- }
- sdp->md.journals = sdp->orig_journals = j;
- return 0;
-
- fail:
- free(sd_jindex);
- return -1;
-}
-
-/* ------------------------------------------------------------------------- */
-/* init - initialization code */
-/* Returns: 0 on success, -1 on failure */
-/* ------------------------------------------------------------------------- */
-static int init(struct gfs2_sbd *sbp)
-{
- struct gfs2_buffer_head *bh;
- int rgcount;
- struct gfs2_inum inum;
-
- memset(sbp, 0, sizeof(struct gfs2_sbd));
- if ((sbp->device_fd = open(device, O_RDWR)) < 0) {
- perror(device);
- exit(-1);
- }
- /* --------------------------------- */
- /* initialize the incore superblock */
- /* --------------------------------- */
- sbp->sd_sb.sb_header.mh_magic = GFS2_MAGIC;
- sbp->sd_sb.sb_header.mh_type = GFS2_METATYPE_SB;
- sbp->sd_sb.sb_header.mh_format = GFS2_FORMAT_SB;
-
- osi_list_init((osi_list_t *)&dirs_to_fix);
- osi_list_init((osi_list_t *)&cdpns_to_fix);
- /* ---------------------------------------------- */
- /* Initialize lists and read in the superblock. */
- /* ---------------------------------------------- */
- sbp->jsize = GFS2_DEFAULT_JSIZE;
- sbp->rgsize = GFS2_DEFAULT_RGSIZE;
- sbp->utsize = GFS2_DEFAULT_UTSIZE;
- sbp->qcsize = GFS2_DEFAULT_QCSIZE;
- sbp->time = time(NULL);
- sbp->blks_total = 0; /* total blocks - total them up later */
- sbp->blks_alloced = 0; /* blocks allocated - total them up later */
- sbp->dinodes_alloced = 0; /* dinodes allocated - total them up later */
- sbp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
- sbp->bsize = sbp->sd_sb.sb_bsize;
- osi_list_init(&sbp->rglist);
- if (compute_constants(sbp)) {
- log_crit("Error: Bad constants (1)\n");
- exit(-1);
- }
-
- bh = bread(sbp, GFS2_SB_ADDR >> sbp->sd_fsb2bb_shift);
- memcpy(&raw_gfs1_ondisk_sb, (struct gfs1_sb *)bh->b_data,
- sizeof(struct gfs1_sb));
- gfs2_sb_in(&sbp->sd_sb, bh);
-
- jindex_addr = be64_to_cpu(raw_gfs1_ondisk_sb.sb_jindex_di.no_addr);
- rindex_addr = be64_to_cpu(raw_gfs1_ondisk_sb.sb_rindex_di.no_addr);
-
- sbp->bsize = sbp->sd_sb.sb_bsize;
- sbp->sd_inptrs = (sbp->bsize - sizeof(struct gfs_indirect)) /
- sizeof(uint64_t);
- sbp->sd_diptrs = (sbp->bsize - sizeof(struct gfs_dinode)) /
- sizeof(uint64_t);
- sbp->sd_jbsize = sbp->bsize - sizeof(struct gfs2_meta_header);
- brelse(bh);
- if (compute_heightsize(sbp, sbp->sd_heightsize, &sbp->sd_max_height,
- sbp->bsize, sbp->sd_diptrs, sbp->sd_inptrs)) {
- log_crit("Error: Bad constants (1)\n");
- exit(-1);
- }
-
- if (compute_heightsize(sbp, sbp->sd_jheightsize, &sbp->sd_max_jheight,
- sbp->sd_jbsize, sbp->sd_diptrs, sbp->sd_inptrs)) {
- log_crit("Error: Bad constants (1)\n");
- exit(-1);
- }
- /* -------------------------------------------------------- */
- /* Our constants are for gfs1. Need some for gfs2 as well. */
- /* -------------------------------------------------------- */
- gfs2_inptrs = (sbp->bsize - sizeof(struct gfs2_meta_header)) /
- sizeof(uint64_t); /* How many ptrs can we fit on a block? */
- memset(gfs2_heightsize, 0, sizeof(gfs2_heightsize));
- if (compute_heightsize(sbp, gfs2_heightsize, &gfs2_max_height,
- sbp->bsize, sbp->sd_diptrs, gfs2_inptrs)) {
- log_crit("Error: Bad constants (1)\n");
- exit(-1);
- }
- memset(gfs2_jheightsize, 0, sizeof(gfs2_jheightsize));
- if (compute_heightsize(sbp, gfs2_jheightsize, &gfs2_max_jheight,
- sbp->sd_jbsize, sbp->sd_diptrs, gfs2_inptrs)) {
- log_crit("Error: Bad constants (1)\n");
- exit(-1);
- }
-
- /* ---------------------------------------------- */
- /* Make sure we're really gfs1 */
- /* ---------------------------------------------- */
- if (sbp->sd_sb.sb_fs_format != GFS_FORMAT_FS ||
- sbp->sd_sb.sb_header.mh_type != GFS_METATYPE_SB ||
- sbp->sd_sb.sb_header.mh_format != GFS_FORMAT_SB ||
- sbp->sd_sb.sb_multihost_format != GFS_FORMAT_MULTI) {
- log_crit("Error: %s does not look like a gfs1 filesystem.\n",
- device);
- close(sbp->device_fd);
- exit(-1);
- }
- /* get gfs1 rindex inode - gfs1's rindex inode ptr became __pad2 */
- gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_rindex_di);
- sbp->md.riinode = gfs_inode_read(sbp, inum.no_addr);
- /* get gfs1 jindex inode - gfs1's journal index inode ptr became master */
- gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_jindex_di);
- sbp->md.jiinode = inode_read(sbp, inum.no_addr);
- /* read in the journal index data */
- read_gfs1_jiindex(sbp);
- /* read in the resource group index data: */
-
- /* We've got a slight dilemma here. In gfs1, we used to have a meta */
- /* header in front of the rgindex pages. In gfs2, we don't. That's */
- /* apparently only for directories. So we need to fake out libgfs2 */
- /* so that it adjusts for the metaheader by faking out the inode to */
- /* look like a directory, temporarily. */
- sbp->md.riinode->i_di.di_mode &= ~S_IFMT;
- sbp->md.riinode->i_di.di_mode |= S_IFDIR;
- printf("Examining file system");
- if (gfs1_ri_update(sbp, 0, &rgcount, 0)){
- log_crit("Unable to fill in resource group information.\n");
- return -1;
- }
- printf("\n");
- fflush(stdout);
- inode_put(&sbp->md.riinode);
- inode_put(&sbp->md.jiinode);
- log_debug("%d rgs found.\n", rgcount);
- return 0;
-}/* fill_super_block */
-
-/* ------------------------------------------------------------------------- */
-/* give_warning - give the all-important warning message. */
-/* ------------------------------------------------------------------------- */
-static void give_warning(void)
-{
- printf("This program will convert a gfs1 filesystem to a " \
- "gfs2 filesystem.\n");
- printf("WARNING: This can't be undone. It is strongly advised " \
- "that you:\n\n");
- printf(" 1. Back up your entire filesystem first.\n");
- printf(" 2. Run gfs_fsck first to ensure filesystem integrity.\n");
- printf(" 3. Make sure the filesystem is NOT mounted from any node.\n");
- printf(" 4. Make sure you have the latest software versions.\n");
-}/* give_warning */
-
-/* ------------------------------------------------------------------------- */
-/* version - print version information */
-/* ------------------------------------------------------------------------- */
-static void version(void)
-{
- log_notice("gfs2_convert version %s (built %s %s)\n", RELEASE_VERSION,
- __DATE__, __TIME__);
- log_notice("%s\n\n", REDHAT_COPYRIGHT);
-}
-
-/* ------------------------------------------------------------------------- */
-/* usage - print usage information */
-/* ------------------------------------------------------------------------- */
-static void usage(const char *name)
-{
- give_warning();
- printf("\nUsage:\n");
- printf("%s [-hnqvVy] <device>\n\n", name);
- printf("Flags:\n");
- printf("\th - print this help message\n");
- printf("\tn - assume 'no' to all questions\n");
- printf("\tq - quieter output\n");
- printf("\tv - more verbose output\n");
- printf("\tV - print version information\n");
- printf("\ty - assume 'yes' to all questions\n");
-}/* usage */
-
-/* ------------------------------------------------------------------------- */
-/* process_parameters */
-/* ------------------------------------------------------------------------- */
-static void process_parameters(int argc, char **argv, struct gfs2_options *opts)
-
-{
- int c;
-
- opts->yes = 0;
- opts->no = 0;
- if (argc == 1) {
- usage(argv[0]);
- exit(0);
- }
- memset(device, 0, sizeof(device));
- while((c = getopt(argc, argv, "hnqvyV")) != -1) {
- switch(c) {
-
- case 'h':
- usage(argv[0]);
- exit(0);
- break;
- case 'n':
- opts->no = 1;
- break;
- case 'q':
- decrease_verbosity();
- break;
- case 'v':
- increase_verbosity();
- break;
- case 'V':
- exit(0);
- case 'y':
- opts->yes = 1;
- break;
- default:
- fprintf(stderr,"Parameter not understood: %c\n", c);
- usage(argv[0]);
- exit(0);
- }
- }
- if(argc > optind) {
- strcpy(device, argv[optind]);
- opts->device = device;
- if(!opts->device) {
- fprintf(stderr, "Please use '-h' for usage.\n");
- exit(1);
- }
- } else {
- fprintf(stderr, "No device specified. Use '-h' for usage.\n");
- exit(1);
- }
-} /* process_parameters */
-
-/* ------------------------------------------------------------------------- */
-/* rgrp_length - Calculate the length of a resource group */
-/* @size: The total size of the resource group */
-/* ------------------------------------------------------------------------- */
-static uint64_t rgrp_length(uint64_t size, struct gfs2_sbd *sdp)
-{
- uint64_t bitbytes = RGRP_BITMAP_BLKS(&sdp->sd_sb) + 1;
- uint64_t stuff = RGRP_STUFFED_BLKS(&sdp->sd_sb) + 1;
- uint64_t blocks = 1;
-
- if (size >= stuff) {
- size -= stuff;
- while (size > bitbytes) {
- blocks++;
- size -= bitbytes;
- }
- if (size)
- blocks++;
- }
- return blocks;
-}/* rgrp_length */
-
-/* ------------------------------------------------------------------------- */
-/* journ_space_to_rg - convert gfs1 journal space to gfs2 rg space. */
-/* */
-/* In gfs1, the journals were kept separate from the files and directories. */
-/* They had a dedicated section of the fs carved out for them. */
-/* In gfs2, the journals are just files like any other, (but still hidden). */
-/* Therefore, the old journal space has to be converted to normal resource */
-/* group space. */
-/* */
-/* Returns: 0 on success, -1 on failure */
-/* ------------------------------------------------------------------------- */
-static int journ_space_to_rg(struct gfs2_sbd *sdp)
-{
- int error = 0;
- int j, x;
- struct gfs1_jindex *jndx;
- struct rgrp_list *rgd, *rgdhigh;
- osi_list_t *tmp;
- struct gfs2_meta_header mh;
-
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_RB;
- mh.mh_format = GFS2_FORMAT_RB;
- log_notice("Converting journal space to rg space.\n");
- /* Go through each journal, converting them one by one */
- for (j = 0; j < sdp->orig_journals; j++) { /* for each journal */
- uint64_t size;
-
- jndx = &sd_jindex[j];
- /* go through all rg index entries, keeping track of the
- highest that's still in the first subdevice.
- Note: we really should go through all of the rgindex because
- we might have had rg's added by gfs_grow, and journals added
- by jadd. gfs_grow adds rgs out of order, so we can't count
- on them being in ascending order. */
- rgdhigh = NULL;
- osi_list_foreach(tmp, &sdp->rglist) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- if (rgd->ri.ri_addr < jndx->ji_addr &&
- ((rgdhigh == NULL) ||
- (rgd->ri.ri_addr > rgdhigh->ri.ri_addr)))
- rgdhigh = rgd;
- } /* for each rg */
- log_info("Addr 0x%llx comes after rg at addr 0x%llx\n",
- (unsigned long long)jndx->ji_addr,
- (unsigned long long)rgdhigh->ri.ri_addr);
- if (!rgdhigh) { /* if we somehow didn't find one. */
- log_crit("Error: No suitable rg found for journal.\n");
- return -1;
- }
- /* Allocate a new rgd entry which includes rg and ri. */
- /* convert the gfs1 rgrp into a new gfs2 rgrp */
- rgd = malloc(sizeof(struct rgrp_list));
- if (!rgd) {
- log_crit("Error: unable to allocate memory for rg conversion.\n");
- return -1;
- }
- memset(rgd, 0, sizeof(struct rgrp_list));
- size = jndx->ji_nsegment * be32_to_cpu(raw_gfs1_ondisk_sb.sb_seg_size);
- rgd->rg.rg_header.mh_magic = GFS2_MAGIC;
- rgd->rg.rg_header.mh_type = GFS2_METATYPE_RG;
- rgd->rg.rg_header.mh_format = GFS2_FORMAT_RG;
- rgd->rg.rg_flags = 0;
- rgd->rg.rg_dinodes = 0;
-
- rgd->ri.ri_addr = jndx->ji_addr; /* new rg addr becomes ji addr */
- rgd->ri.ri_length = rgrp_length(size, sdp); /* aka bitblocks */
-
- rgd->ri.ri_data0 = jndx->ji_addr + rgd->ri.ri_length;
- rgd->ri.ri_data = size - rgd->ri.ri_length;
- /* Round down to nearest multiple of GFS2_NBBY */
- while (rgd->ri.ri_data & 0x03)
- rgd->ri.ri_data--;
- sdp->blks_total += rgd->ri.ri_data; /* For statfs file update */
- rgd->rg.rg_free = rgd->ri.ri_data;
- rgd->ri.ri_bitbytes = rgd->ri.ri_data / GFS2_NBBY;
-
- if(!(rgd->bh = (struct gfs2_buffer_head **)
- malloc(rgd->ri.ri_length *
- sizeof(struct gfs2_buffer_head *))))
- return -1;
- if(!memset(rgd->bh, 0, rgd->ri.ri_length *
- sizeof(struct gfs2_buffer_head *))) {
- free(rgd->bh);
- return -1;
- }
- for (x = 0; x < rgd->ri.ri_length; x++) {
- rgd->bh[x] = bget(sdp, rgd->ri.ri_addr + x);
- memset(rgd->bh[x]->b_data, 0, sdp->bsize);
- }
- if (gfs2_compute_bitstructs(sdp, rgd)) {
- log_crit("gfs2_convert: Error converting bitmaps.\n");
- exit(-1);
- }
- convert_bitmaps(sdp, rgd);
- for (x = 0; x < rgd->ri.ri_length; x++) {
- if (x)
- gfs2_meta_header_out(&mh, rgd->bh[x]);
- else
- gfs2_rgrp_out(&rgd->rg, rgd->bh[x]);
- }
- /* Add the new gfs2 rg to our list: We'll output the rg index later. */
- osi_list_add_prev((osi_list_t *)&rgd->list,
- (osi_list_t *)&sdp->rglist);
- } /* for each journal */
- return error;
-}/* journ_space_to_rg */
-
-/* ------------------------------------------------------------------------- */
-/* update_inode_file - update the inode file with the new next_inum */
-/* ------------------------------------------------------------------------- */
-static void update_inode_file(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *ip = sdp->md.inum;
- uint64_t buf;
- int count;
-
- buf = cpu_to_be64(sdp->md.next_inum);
- count = gfs2_writei(ip, &buf, 0, sizeof(uint64_t));
- if (count != sizeof(uint64_t))
- die("update_inode_file\n");
-
- log_debug("\nNext Inum: %"PRIu64"\n", sdp->md.next_inum);
-}/* update_inode_file */
-
-/* ------------------------------------------------------------------------- */
-/* write_statfs_file - write the statfs file */
-/* ------------------------------------------------------------------------- */
-static void write_statfs_file(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *ip = sdp->md.statfs;
- struct gfs2_statfs_change sc;
- char buf[sizeof(struct gfs2_statfs_change)];
- int count;
-
- sc.sc_total = sdp->blks_total;
- sc.sc_free = sdp->blks_total - sdp->blks_alloced;
- sc.sc_dinodes = sdp->dinodes_alloced;
-
- gfs2_statfs_change_out(&sc, buf);
- count = gfs2_writei(ip, buf, 0, sizeof(struct gfs2_statfs_change));
- if (count != sizeof(struct gfs2_statfs_change))
- die("do_init (2)\n");
-}/* write_statfs_file */
-
-/* ------------------------------------------------------------------------- */
-/* remove_obsolete_gfs1 - remove obsolete gfs1 inodes. */
-/* ------------------------------------------------------------------------- */
-static void remove_obsolete_gfs1(struct gfs2_sbd *sbp)
-{
- struct gfs2_inum inum;
-
- log_notice("Removing obsolete GFS1 file system structures.\n");
- fflush(stdout);
- /* Delete the old gfs1 Journal index: */
- gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_jindex_di);
- gfs2_freedi(sbp, inum.no_addr);
-
- /* Delete the old gfs1 rgindex: */
- gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_rindex_di);
- gfs2_freedi(sbp, inum.no_addr);
-
- /* Delete the old gfs1 Quota file: */
- gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_quota_di);
- gfs2_freedi(sbp, inum.no_addr);
-
- /* Delete the old gfs1 License file: */
- gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_license_di);
- gfs2_freedi(sbp, inum.no_addr);
-}
-
-/* ------------------------------------------------------------------------- */
-/* lifted from libgfs2/structures.c */
-/* ------------------------------------------------------------------------- */
-static void conv_build_jindex(struct gfs2_sbd *sdp)
-{
- unsigned int j;
-
- sdp->md.jiinode = createi(sdp->master_dir, "jindex", S_IFDIR | 0700,
- GFS2_DIF_SYSTEM);
-
- sdp->md.journal = malloc(sdp->md.journals *
- sizeof(struct gfs2_inode *));
- for (j = 0; j < sdp->md.journals; j++) {
- char name[256];
-
- printf("Writing journal #%d...", j + 1);
- fflush(stdout);
- sprintf(name, "journal%u", j);
- sdp->md.journal[j] = createi(sdp->md.jiinode, name, S_IFREG |
- 0600, GFS2_DIF_SYSTEM);
- write_journal(sdp, j,
- sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
- inode_put(&sdp->md.journal[j]);
- printf("done.\n");
- fflush(stdout);
- }
-
- free(sdp->md.journal);
- if (sdp->debug) {
- printf("\nJindex:\n");
- gfs2_dinode_print(&sdp->md.jiinode->i_di);
- }
-
- inode_put(&sdp->md.jiinode);
-}
-
-static unsigned int total_file_blocks(struct gfs2_sbd *sdp,
- uint64_t filesize, int journaled)
-{
- unsigned int data_blks = 0, meta_blks = 0, total_blks;
- unsigned int max, height, bsize;
- uint64_t *arr;
-
- /* Now find the total meta blocks required for data_blks */
- if (filesize <= sdp->bsize - sizeof(struct gfs2_dinode)) {
- total_blks = 1; /* stuffed inode */
- goto out;
- }
-
- if (journaled) {
- arr = sdp->sd_jheightsize;
- max = sdp->sd_max_jheight;
- bsize = sdp->sd_jbsize;
- } else {
- arr = sdp->sd_heightsize;
- max = sdp->sd_max_height;
- bsize = sdp->bsize;
- }
- data_blks = DIV_RU(filesize, bsize); /* total data blocks reqd */
-
- for (height = 0; height < max; height++)
- if (arr[height] >= filesize)
- break;
- if (height == 1) {
- total_blks = data_blks + 1; /* dinode has direct ptrs to data blocks */
- goto out;
- }
-
- meta_blks = DIV_RU(data_blks, sdp->sd_inptrs);
- total_blks = data_blks + meta_blks;
-out:
- return data_blks + meta_blks;
-}
-
-/* We check if the GFS2 filesystem files/structures created after the call to
- * check_fit() in main() will fit in the currently available free blocks
- */
-static int check_fit(struct gfs2_sbd *sdp)
-{
- unsigned int blks_need = 0, blks_avail = sdp->blks_total - sdp->blks_alloced;
-
- /* build_master() */
- blks_need++; /*creation of master dir inode - 1 block */
-
- /* conv_build_jindex() */
- {
- blks_need++; /* creation of 'jindex' disk inode */
- /* creation of journals */
- blks_need += sdp->md.journals *
- total_file_blocks(sdp, sdp->jsize << 20, 1);
- }
- /* build_per_node() */
- {
- blks_need++; /* creation of 'per_node' dir inode */
- /* njourn x (inum_range + statfs_change + quota_change inodes) */
- blks_need += sdp->md.journals * 3;
- /* quota change inodes are prealloced */
- blks_need += sdp->md.journals *
- total_file_blocks(sdp, sdp->qcsize << 20, 1);
- }
- /* build_inum() */
- blks_need++; /* creation of 'inum' disk inode */
-
- /* build_statfs() */
- blks_need++; /* creation of 'statfs' disk inode */
-
- /* build_rindex() */
- {
- osi_list_t *tmp, *head;
- unsigned int rg_count = 0;
-
- blks_need++; /* creationg of 'rindex' disk inode */
- /* find the total # of rindex entries, gives size of rindex inode */
- for (head = &sdp->rglist, tmp = head->next; tmp != head;
- tmp = tmp->next)
- rg_count++;
- blks_need +=
- total_file_blocks(sdp, rg_count * sizeof(struct gfs2_rindex), 1);
- }
- /* build_quota() */
- blks_need++; /* quota inode block and uid=gid=0 quota - total 1 block */
-
- /* Up until this point we require blks_need blocks. We don't
- * include the blocks freed by the next step (remove_obsolete_gfs1)
- * because it's possible for us to exceed the available blocks
- * before this step */
-
- return blks_avail > blks_need;
-}
-
-/* We fetch the old quota inode block and copy the contents of the block
- * (minus the struct gfs2_dinode) into the new quota block. We update the
- * inode height/size of the new quota file to that of the old one and set the
- * old quota inode height/size to zero, so only the inode block gets freed.
- */
-static void copy_quotas(struct gfs2_sbd *sdp)
-{
- struct gfs2_inum inum;
- struct gfs2_inode *oq_ip, *nq_ip;
- int err;
-
- err = gfs2_lookupi(sdp->master_dir, "quota", 5, &nq_ip);
- if (err)
- die("Couldn't lookup new quota file: %d\n", err);
-
- gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_quota_di);
- oq_ip = inode_read(sdp, inum.no_addr);
-
- nq_ip->i_di.di_height = oq_ip->i_di.di_height;
- nq_ip->i_di.di_size = oq_ip->i_di.di_size;
- memcpy(nq_ip->i_bh->b_data + sizeof(struct gfs2_dinode),
- oq_ip->i_bh->b_data + sizeof(struct gfs2_dinode),
- sdp->bsize - sizeof(struct gfs2_dinode));
-
- oq_ip->i_di.di_height = 0;
- oq_ip->i_di.di_size = 0;
-
- bmodified(nq_ip->i_bh);
- inode_put(&nq_ip);
-
- bmodified(oq_ip->i_bh);
- inode_put(&oq_ip);
-}
-
-/* ------------------------------------------------------------------------- */
-/* main - mainline code */
-/* ------------------------------------------------------------------------- */
-int main(int argc, char **argv)
-{
- int error;
- struct gfs2_buffer_head *bh;
- struct gfs2_options opts;
-
- version();
- process_parameters(argc, argv, &opts);
- error = init(&sb2);
-
- /* ---------------------------------------------- */
- /* Make them seal their fate. */
- /* ---------------------------------------------- */
- if (!error) {
- int do_abort;
-
- give_warning();
- if (!gfs2_query(&do_abort, &opts,
- "Convert %s from GFS1 to GFS2? (y/n)",
- device)) {
- log_crit("%s not converted.\n", device);
- close(sb2.device_fd);
- exit(0);
- }
- }
- /* ---------------------------------------------- */
- /* Convert incore gfs1 sb to gfs2 sb */
- /* ---------------------------------------------- */
- if (!error) {
- log_notice("Converting resource groups.");
- fflush(stdout);
- error = convert_rgs(&sb2);
- log_notice("\n");
- if (error)
- log_crit("%s: Unable to convert resource groups.\n",
- device);
- fsync(sb2.device_fd); /* write the buffers to disk */
- }
- /* ---------------------------------------------- */
- /* Renumber the inodes consecutively. */
- /* ---------------------------------------------- */
- if (!error) {
- error = inode_renumber(&sb2, sb2.sd_sb.sb_root_dir.no_addr,
- (osi_list_t *)&cdpns_to_fix);
- if (error)
- log_crit("\n%s: Error renumbering inodes.\n", device);
- fsync(sb2.device_fd); /* write the buffers to disk */
- }
- /* ---------------------------------------------- */
- /* Fix the directories to match the new numbers. */
- /* ---------------------------------------------- */
- if (!error) {
- error = fix_directory_info(&sb2, (osi_list_t *)&dirs_to_fix);
- log_notice("\r%" PRIu64 " directories, %" PRIu64 " dirents fixed.",
- dirs_fixed, dirents_fixed);
- fflush(stdout);
- if (error)
- log_crit("\n%s: Error fixing directories.\n", device);
- }
- /* ---------------------------------------------- */
- /* Convert cdpn symlinks to empty dirs */
- /* ---------------------------------------------- */
- if (!error) {
- error = fix_cdpn_symlinks(&sb2, (osi_list_t *)&cdpns_to_fix);
- log_notice("\r%" PRIu64 " cdpn symlinks moved to empty directories.",
- cdpns_fixed);
- fflush(stdout);
- if (error)
- log_crit("\n%s: Error fixing cdpn symlinks.\n", device);
- }
- /* ---------------------------------------------- */
- /* Convert journal space to rg space */
- /* ---------------------------------------------- */
- if (!error) {
- log_notice("\nConverting journals.\n");
- error = journ_space_to_rg(&sb2);
- if (error)
- log_crit("%s: Error converting journal space.\n", device);
- fsync(sb2.device_fd); /* write the buffers to disk */
- }
- /* ---------------------------------------------- */
- /* Create our system files and directories. */
- /* ---------------------------------------------- */
- if (!error) {
- int jreduce = 0;
- /* Now we've got to treat it as a gfs2 file system */
- if (compute_constants(&sb2)) {
- log_crit("Error: Bad constants (1)\n");
- exit(-1);
- }
-
- /* Check if all the files we're about to create will
- * fit into the space remaining on the device */
- while (!check_fit(&sb2)) {
- sb2.jsize--; /* reduce jsize by 1MB each time */
- jreduce = 1;
- }
- if (jreduce)
- log_notice("Reduced journal size to %u MB to accommodate "
- "GFS2 file system structures.\n", sb2.jsize);
- /* Build the master subdirectory. */
- build_master(&sb2); /* Does not do inode_put */
- sb2.sd_sb.sb_master_dir = sb2.master_dir->i_di.di_num;
- /* Build empty journal index file. */
- conv_build_jindex(&sb2);
- log_notice("Building GFS2 file system structures.\n");
- /* Build the per-node directories */
- build_per_node(&sb2);
- /* Create the empty inode number file */
- build_inum(&sb2); /* Does not do inode_put */
- /* Create the statfs file */
- build_statfs(&sb2); /* Does not do inode_put */
-
- /* Create the resource group index file */
- build_rindex(&sb2);
- /* Create the quota file */
- build_quota(&sb2);
-
- /* Copy out the master dinode */
- {
- struct gfs2_inode *ip = sb2.master_dir;
- if (ip->i_bh->b_modified)
- gfs2_dinode_out(&ip->i_di, ip->i_bh);
- }
- /* Copy old quotas */
- copy_quotas(&sb2);
-
- update_inode_file(&sb2);
- /* Now delete the now-obsolete gfs1 files: */
- remove_obsolete_gfs1(&sb2);
-
- write_statfs_file(&sb2);
-
- inode_put(&sb2.master_dir);
- inode_put(&sb2.md.inum);
- inode_put(&sb2.md.statfs);
-
- fsync(sb2.device_fd); /* write the buffers to disk */
-
- /* Now free all the in memory */
- gfs2_rgrp_free(&sb2.rglist);
- log_notice("Committing changes to disk.\n");
- fflush(stdout);
- /* Set filesystem type in superblock to gfs2. We do this at the */
- /* end because if the tool is interrupted in the middle, we want */
- /* it to not reject the partially converted fs as already done */
- /* when it's run a second time. */
- bh = bread(&sb2, sb2.sb_addr);
- sb2.sd_sb.sb_fs_format = GFS2_FORMAT_FS;
- sb2.sd_sb.sb_multihost_format = GFS2_FORMAT_MULTI;
- gfs2_sb_out(&sb2.sd_sb, bh);
- brelse(bh);
-
- error = fsync(sb2.device_fd);
- if (error)
- perror(device);
- else
- log_notice("%s: filesystem converted successfully to gfs2.\n",
- device);
- }
- close(sb2.device_fd);
- if (sd_jindex)
- free(sd_jindex);
- exit(0);
-}
diff --git a/gfs2/edit/Makefile b/gfs2/edit/Makefile
deleted file mode 100644
index b8a53cc..0000000
--- a/gfs2/edit/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-TARGET= gfs2_edit
-
-SBINDIRT=$(TARGET)
-
-all: depends ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= gfs2hex.o \
- savemeta.o \
- hexedit.o
-
-CFLAGS += -DHELPER_PROGRAM -D_FILE_OFFSET_BITS=64
-CFLAGS += -I${ncursesincdir}
-CFLAGS += -I${KERNEL_SRC}/fs/gfs2/ -I${KERNEL_SRC}/include/
-CFLAGS += -I$(S)/../include -I$(S)/../libgfs2
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L${ncurseslibdir} -lncurses
-LDFLAGS += -L../libgfs2/ -lgfs2
-LDFLAGS += -L${libdir}
-
-LDDEPS += ../libgfs2/libgfs2.a
-
-${TARGET}: ${OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-depends:
- $(MAKE) -C ../libgfs2 all
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs2/edit/gfs2hex.c b/gfs2/edit/gfs2hex.c
deleted file mode 100644
index 00c4481..0000000
--- a/gfs2/edit/gfs2hex.c
+++ /dev/null
@@ -1,692 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <linux/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <curses.h>
-
-#include "hexedit.h"
-
-#define WANT_GFS_CONVERSION_FUNCTIONS
-#include <linux/gfs2_ondisk.h>
-
-#include "gfs2hex.h"
-/* from libgfs2: */
-#include "libgfs2.h"
-
-#define pv(struct, member, fmt, fmt2) do { \
- print_it(" "#member, fmt, fmt2, struct->member); \
- } while (FALSE);
-#define pv2(struct, member, fmt, fmt2) do { \
- print_it(" ", fmt, fmt2, struct->member); \
- } while (FALSE);
-
-
-struct gfs2_sb sb;
-struct gfs2_buffer_head *bh;
-struct gfs2_dinode di;
-int line, termlines;
-char edit_fmt[80];
-char estring[1024];
-char efield[64];
-int edit_mode = 0;
-int edit_row[DMODES], edit_col[DMODES];
-int edit_size[DMODES], last_entry_onscreen[DMODES];
-char edit_fmt[80];
-enum dsp_mode dmode = HEX_MODE; /* display mode */
-uint64_t block = 0;
-int blockhist = 0;
-struct iinfo *indirect;
-int indirect_blocks;
-int gfs1 = 0;
-uint64_t block_in_mem = -1;
-struct gfs2_sbd sbd;
-uint64_t starting_blk;
-struct blkstack_info blockstack[BLOCK_STACK_SIZE];
-int identify = FALSE;
-char device[NAME_MAX];
-uint64_t max_block = 0;
-int start_row[DMODES], end_row[DMODES], lines_per_row[DMODES];
-struct gfs_sb *sbd1;
-int gfs2_struct_type;
-unsigned int offset;
-int termcols = 80;
-struct indirect_info masterdir;
-struct gfs2_inum gfs1_quota_di;
-int print_entry_ndx;
-struct gfs2_inum gfs1_license_di;
-int screen_chunk_size = 512;
-uint64_t temp_blk;
-int color_scheme = 0;
-int struct_len;
-uint64_t dev_offset = 0;
-int editing = 0;
-int insert = 0;
-const char *termtype;
-WINDOW *wind;
-int dsplines = 0;
-
-const char *block_type_str[15] = {
- "Clump",
- "Superblock",
- "Resource Group Header",
- "Resource Group Bitmap",
- "Dinode",
- "Indirect Block",
- "Leaf",
- "Journaled Data",
- "Log Header",
- "Log descriptor",
- "Ext. attrib",
- "Eattr Data",
- "Log Buffer",
- "Metatype 13",
- "Quota Change",
-};
-
-struct gfs1_rgrp {
- struct gfs2_meta_header rg_header;
-
- uint32_t rg_flags; /* ?? */
-
- uint32_t rg_free; /* Number (qty) of free data blocks */
-
- /* Dinodes are USEDMETA, but are handled separately from other METAs */
- uint32_t rg_useddi; /* Number (qty) of dinodes (used or free) */
- uint32_t rg_freedi; /* Number (qty) of unused (free) dinodes */
- struct gfs2_inum rg_freedi_list; /* 1st block in chain of free dinodes */
-
- /* These META statistics do not include dinodes (used or free) */
- uint32_t rg_usedmeta; /* Number (qty) of used metadata blocks */
- uint32_t rg_freemeta; /* Number (qty) of unused metadata blocks */
-
- char rg_reserved[64];
-};
-
-void eol(int col) /* end of line */
-{
- if (termlines) {
- line++;
- move(line, col);
- }
- else {
- printf("\n");
- for (; col > 0; col--)
- printf(" ");
- }
-}
-
-void __attribute__((format (printf, 1, 2))) print_gfs2(const char *fmt, ...)
-{
- va_list args;
- char string[NAME_MAX];
-
- memset(string, 0, sizeof(string));
- va_start(args, fmt);
- vsprintf(string, fmt, args);
- if (termlines)
- printw("%s", string);
- else
- printf("%s", string);
- va_end(args);
-}
-
-static void check_highlight(int highlight)
-{
- if (!termlines || line >= termlines) /* If printing or out of bounds */
- return;
- if (dmode == HEX_MODE) {
- if (line == (edit_row[dmode] * lines_per_row[dmode]) + 4) {
- if (highlight) {
- COLORS_HIGHLIGHT;
- last_entry_onscreen[dmode] = print_entry_ndx;
- }
- else
- COLORS_NORMAL;
- }
- }
- else {
- if ((line * lines_per_row[dmode]) - 4 ==
- (edit_row[dmode] - start_row[dmode]) * lines_per_row[dmode]) {
- if (highlight) {
- COLORS_HIGHLIGHT;
- last_entry_onscreen[dmode] = print_entry_ndx;
- }
- else
- COLORS_NORMAL;
- }
- }
-}
-
-void print_it(const char *label, const char *fmt, const char *fmt2, ...)
-{
- va_list args;
- char tmp_string[NAME_MAX];
- const char *fmtstring;
- int decimalsize;
-
- if (!termlines || line < termlines) {
- va_start(args, fmt2);
- check_highlight(TRUE);
- if (termlines) {
- move(line,0);
- printw("%s", label);
- move(line,24);
- }
- else {
- if (!strcmp(label, " "))
- printf("%-11s", label);
- else
- printf("%-24s", label);
- }
- vsprintf(tmp_string, fmt, args);
-
- if (termlines)
- printw("%s", tmp_string);
- else
- printf("%s", tmp_string);
- check_highlight(FALSE);
-
- if (fmt2) {
- decimalsize = strlen(tmp_string);
- va_end(args);
- va_start(args, fmt2);
- vsprintf(tmp_string, fmt2, args);
- check_highlight(TRUE);
- if (termlines) {
- move(line, 50);
- printw("%s", tmp_string);
- }
- else {
- int i;
- for (i=20 - decimalsize; i > 0; i--)
- printf(" ");
- printf("%s", tmp_string);
- }
- check_highlight(FALSE);
- }
- else {
- if (strstr(fmt,"X") || strstr(fmt,"x"))
- fmtstring="(hex)";
- else if (strstr(fmt,"s"))
- fmtstring="";
- else
- fmtstring="(decimal)";
- if (termlines) {
- move(line, 50);
- printw("%s", fmtstring);
- }
- else
- printf("%s", fmtstring);
- }
- if (termlines) {
- refresh();
- if (line == (edit_row[dmode] * lines_per_row[dmode]) + 4) {
- strcpy(efield, label + 2); /* it's indented */
- strcpy(estring, tmp_string);
- strcpy(edit_fmt, fmt);
- edit_size[dmode] = strlen(estring);
- COLORS_NORMAL;
- }
- last_entry_onscreen[dmode] = (line / lines_per_row[dmode]) - 4;
- }
- eol(0);
- va_end(args);
- }
-}
-
-static int indirect_dirent(struct indirect_info *indir, char *ptr, int d)
-{
- struct gfs2_dirent de;
-
- gfs2_dirent_in(&de, ptr);
- if (de.de_rec_len < sizeof(struct gfs2_dirent) ||
- de.de_rec_len > 4096 - sizeof(struct gfs2_dirent))
- return -1;
- if (de.de_inum.no_addr) {
- indir->block = de.de_inum.no_addr;
- memcpy(&indir->dirent[d].dirent, &de, sizeof(struct gfs2_dirent));
- memcpy(&indir->dirent[d].filename,
- ptr + sizeof(struct gfs2_dirent), de.de_name_len);
- indir->dirent[d].filename[de.de_name_len] = '\0';
- indir->dirent[d].block = de.de_inum.no_addr;
- indir->is_dir = TRUE;
- indir->dirents++;
- }
- return de.de_rec_len;
-}
-
-/******************************************************************************
-*******************************************************************************
-**
-** do_dinode_extended()
-**
-** Description:
-**
-** Input(s):
-**
-** Output(s):
-**
-** Returns:
-**
-*******************************************************************************
-******************************************************************************/
-void do_dinode_extended(struct gfs2_dinode *dine, struct gfs2_buffer_head *lbh)
-{
- unsigned int x, y, ptroff = 0;
- uint64_t p, last;
- int isdir = !!(S_ISDIR(dine->di_mode)) ||
- (gfs1 && dine->__pad1 == GFS_FILE_DIR);
-
- indirect_blocks = 0;
- memset(indirect, 0, sizeof(indirect));
- if (dine->di_height > 0) {
- /* Indirect pointers */
- for (x = sizeof(struct gfs2_dinode); x < sbd.bsize;
- x += sizeof(uint64_t)) {
- p = be64_to_cpu(*(uint64_t *)(lbh->b_data + x));
- if (p) {
- indirect->ii[indirect_blocks].block = p;
- indirect->ii[indirect_blocks].mp.mp_list[0] =
- ptroff;
- indirect->ii[indirect_blocks].is_dir = FALSE;
- indirect_blocks++;
- }
- ptroff++;
- }
- }
- else if (isdir && !(dine->di_flags & GFS2_DIF_EXHASH)) {
- int skip = 0;
-
- /* Directory Entries: */
- indirect->ii[0].dirents = 0;
- indirect->ii[0].block = block;
- indirect->ii[0].is_dir = TRUE;
- for (x = sizeof(struct gfs2_dinode); x < sbd.bsize; x += skip) {
- skip = indirect_dirent(indirect->ii, lbh->b_data + x,
- indirect->ii[0].dirents);
- if (skip <= 0)
- break;
- }
- }
- else if (isdir &&
- (dine->di_flags & GFS2_DIF_EXHASH) &&
- dine->di_height == 0) {
- /* Leaf Pointers: */
-
- last = be64_to_cpu(*(uint64_t *)(lbh->b_data +
- sizeof(struct gfs2_dinode)));
-
- for (x = sizeof(struct gfs2_dinode), y = 0;
- y < (1 << dine->di_depth);
- x += sizeof(uint64_t), y++) {
- p = be64_to_cpu(*(uint64_t *)(lbh->b_data + x));
-
- if (p != last || ((y + 1) * sizeof(uint64_t) == dine->di_size)) {
- struct gfs2_buffer_head *tmp_bh;
- int skip = 0, direntcount = 0;
- struct gfs2_leaf leaf;
- unsigned int bufoffset;
-
- if (last >= max_block)
- break;
- tmp_bh = bread(&sbd, last);
- gfs2_leaf_in(&leaf, tmp_bh);
- indirect->ii[indirect_blocks].dirents = 0;
- for (direntcount = 0, bufoffset = sizeof(struct gfs2_leaf);
- bufoffset < sbd.bsize;
- direntcount++, bufoffset += skip) {
- skip = indirect_dirent(&indirect->ii[indirect_blocks],
- tmp_bh->b_data + bufoffset,
- direntcount);
- if (skip <= 0)
- break;
- }
- brelse(tmp_bh);
- indirect->ii[indirect_blocks].block = last;
- indirect_blocks++;
- last = p;
- } /* if not duplicate pointer */
- } /* for indirect pointers found */
- } /* if exhash */
-}/* do_dinode_extended */
-
-/******************************************************************************
-*******************************************************************************
-**
-** do_indirect_extended()
-**
-** Description:
-**
-** Input(s):
-**
-** Output(s):
-**
-** Returns:
-**
-*******************************************************************************
-******************************************************************************/
-int do_indirect_extended(char *diebuf, struct iinfo *iinf, int hgt)
-{
- unsigned int x, y;
- uint64_t p;
- int i_blocks;
-
- i_blocks = 0;
- for (x = 0; x < 512; x++) {
- iinf->ii[x].is_dir = 0;
- iinf->ii[x].height = 0;
- iinf->ii[x].block = 0;
- iinf->ii[x].dirents = 0;
- memset(&iinf->ii[x].dirent, 0, sizeof(struct gfs2_dirents));
- }
- for (x = (gfs1 ? sizeof(struct gfs_indirect):
- sizeof(struct gfs2_meta_header)), y = 0;
- x < sbd.bsize;
- x += sizeof(uint64_t), y++) {
- p = be64_to_cpu(*(uint64_t *)(diebuf + x));
- if (p) {
- iinf->ii[i_blocks].block = p;
- iinf->ii[i_blocks].mp.mp_list[hgt] = i_blocks;
- iinf->ii[i_blocks].is_dir = FALSE;
- i_blocks++;
- }
- }
- return i_blocks;
-}
-
-/******************************************************************************
-*******************************************************************************
-**
-** do_leaf_extended()
-**
-** Description:
-**
-** Input(s):
-**
-** Output(s):
-**
-** Returns:
-**
-*******************************************************************************
-******************************************************************************/
-void do_leaf_extended(char *dlebuf, struct iinfo *indir)
-{
- int x, i;
- struct gfs2_dirent de;
-
- x = 0;
- memset(indir, 0, sizeof(*indir));
- /* Directory Entries: */
- for (i = sizeof(struct gfs2_leaf); i < sbd.bsize;
- i += de.de_rec_len) {
- gfs2_dirent_in(&de, dlebuf + i);
- if (de.de_inum.no_addr) {
- indir->ii[0].block = de.de_inum.no_addr;
- indir->ii[0].dirent[x].block = de.de_inum.no_addr;
- memcpy(&indir->ii[0].dirent[x].dirent,
- &de, sizeof(struct gfs2_dirent));
- memcpy(&indir->ii[0].dirent[x].filename,
- dlebuf + i + sizeof(struct gfs2_dirent),
- de.de_name_len);
- indir->ii[0].dirent[x].filename[de.de_name_len] = '\0';
- indir->ii[0].is_dir = TRUE;
- indir->ii[0].dirents++;
- x++;
- }
- if (de.de_rec_len <= sizeof(struct gfs2_dirent))
- break;
- }
-}
-
-
-/******************************************************************************
-*******************************************************************************
-**
-** do_eattr_extended()
-**
-** Description:
-**
-** Input(s):
-**
-** Output(s):
-**
-** Returns:
-**
-*******************************************************************************
-******************************************************************************/
-
-static void do_eattr_extended(struct gfs2_buffer_head *ebh)
-{
- struct gfs2_ea_header ea;
- unsigned int x;
-
- eol(0);
- print_gfs2("Eattr Entries:");
- eol(0);
-
- for (x = sizeof(struct gfs2_meta_header); x < sbd.bsize;
- x += ea.ea_rec_len)
- {
- eol(0);
- gfs2_ea_header_in(&ea, ebh->b_data + x);
- gfs2_ea_header_print(&ea, ebh->b_data + x +
- sizeof(struct gfs2_ea_header));
- }
-}
-
-static void gfs2_inum_print2(const char *title,struct gfs2_inum *no)
-{
- if (termlines) {
- check_highlight(TRUE);
- move(line,2);
- printw(title);
- check_highlight(FALSE);
- }
- else
- printf(" %s:",title);
- pv2(no, no_formal_ino, "%lld", "0x%"PRIx64);
- if (!termlines)
- printf(" addr:");
- pv2(no, no_addr, "%lld", "0x%"PRIx64);
-}
-
-/**
- * gfs2_sb_print2 - Print out a superblock
- * @sb: the cpu-order buffer
- */
-static void gfs2_sb_print2(struct gfs2_sb *sbp2)
-{
- gfs2_meta_header_print(&sbp2->sb_header);
-
- pv(sbp2, sb_fs_format, "%u", "0x%x");
- pv(sbp2, sb_multihost_format, "%u", "0x%x");
-
- if (gfs1)
- pv(sbd1, sb_flags, "%u", "0x%x");
- pv(sbp2, sb_bsize, "%u", "0x%x");
- pv(sbp2, sb_bsize_shift, "%u", "0x%x");
- if (gfs1) {
- pv(sbd1, sb_seg_size, "%u", "0x%x");
- gfs2_inum_print2("jindex ino", &sbd1->sb_jindex_di);
- gfs2_inum_print2("rindex ino", &sbd1->sb_rindex_di);
- }
- else
- gfs2_inum_print2("master dir", &sbp2->sb_master_dir);
- gfs2_inum_print2("root dir ", &sbp2->sb_root_dir);
-
- pv(sbp2, sb_lockproto, "%s", NULL);
- pv(sbp2, sb_locktable, "%s", NULL);
- if (gfs1) {
- gfs2_inum_print2("quota ino ", &gfs1_quota_di);
- gfs2_inum_print2("license ", &gfs1_license_di);
- }
-#ifdef GFS2_HAS_UUID
- print_it(" sb_uuid", "%s", NULL, str_uuid(sbp2->sb_uuid));
-#endif
-}
-
-/**
- * gfs1_rgrp_in - read in a gfs1 rgrp
- */
-static void gfs1_rgrp_in(struct gfs1_rgrp *rgrp, struct gfs2_buffer_head *rbh)
-{
- struct gfs1_rgrp *str = (struct gfs1_rgrp *)rbh->b_data;
-
- gfs2_meta_header_in(&rgrp->rg_header, rbh);
- rgrp->rg_flags = be32_to_cpu(str->rg_flags);
- rgrp->rg_free = be32_to_cpu(str->rg_free);
- rgrp->rg_useddi = be32_to_cpu(str->rg_useddi);
- rgrp->rg_freedi = be32_to_cpu(str->rg_freedi);
- gfs2_inum_in(&rgrp->rg_freedi_list, (char *)&str->rg_freedi_list);
- rgrp->rg_usedmeta = be32_to_cpu(str->rg_usedmeta);
- rgrp->rg_freemeta = be32_to_cpu(str->rg_freemeta);
- memcpy(rgrp->rg_reserved, str->rg_reserved, 64);
-}
-
-/**
- * gfs_rgrp_print - Print out a resource group header
- */
-static void gfs1_rgrp_print(struct gfs1_rgrp *rg)
-{
- gfs2_meta_header_print(&rg->rg_header);
- pv(rg, rg_flags, "%u", "0x%x");
- pv(rg, rg_free, "%u", "0x%x");
- pv(rg, rg_useddi, "%u", "0x%x");
- pv(rg, rg_freedi, "%u", "0x%x");
- gfs2_inum_print(&rg->rg_freedi_list);
-
- pv(rg, rg_usedmeta, "%u", "0x%x");
- pv(rg, rg_freemeta, "%u", "0x%x");
-}
-
-/******************************************************************************
-*******************************************************************************
-**
-** int display_gfs2()
-**
-** Description:
-** This routine...
-**
-** Input(s):
-** *buffer -
-** extended -
-**
-** Returns:
-** 0 if OK, 1 on error.
-**
-*******************************************************************************
-******************************************************************************/
-int display_gfs2(void)
-{
- struct gfs2_meta_header mh;
- struct gfs2_rgrp rg;
- struct gfs2_leaf lf;
- struct gfs_log_header lh1;
- struct gfs2_log_header lh;
- struct gfs2_log_descriptor ld;
- struct gfs2_quota_change qc;
-
- uint32_t magic;
-
- magic = be32_to_cpu(*(uint32_t *)bh->b_data);
-
- switch (magic)
- {
- case GFS2_MAGIC:
- gfs2_meta_header_in(&mh, bh);
- if (mh.mh_type > GFS2_METATYPE_QC)
- print_gfs2("Unknown metadata type");
- else
- print_gfs2("%s:", block_type_str[mh.mh_type]);
- eol(0);
-
- switch (mh.mh_type)
- {
- case GFS2_METATYPE_SB:
- gfs2_sb_in(&sbd.sd_sb, bh);
- gfs2_sb_print2(&sbd.sd_sb);
- break;
-
- case GFS2_METATYPE_RG:
- if (gfs1) {
- struct gfs1_rgrp rg1;
-
- gfs1_rgrp_in(&rg1, bh);
- gfs1_rgrp_print(&rg1);
- } else {
- gfs2_rgrp_in(&rg, bh);
- gfs2_rgrp_print(&rg);
- }
- break;
-
- case GFS2_METATYPE_RB:
- gfs2_meta_header_print(&mh);
- break;
-
- case GFS2_METATYPE_DI:
- gfs2_dinode_print(&di);
- break;
-
- case GFS2_METATYPE_IN:
- gfs2_meta_header_print(&mh);
- break;
-
- case GFS2_METATYPE_LF:
- gfs2_leaf_in(&lf, bh);
- gfs2_leaf_print(&lf);
- break;
-
- case GFS2_METATYPE_JD:
- gfs2_meta_header_print(&mh);
- break;
-
- case GFS2_METATYPE_LH:
- if (gfs1) {
- gfs_log_header_in(&lh1, bh);
- gfs_log_header_print(&lh1);
- } else {
- gfs2_log_header_in(&lh, bh);
- gfs2_log_header_print(&lh);
- }
- break;
-
- case GFS2_METATYPE_LD:
- gfs2_log_descriptor_in(&ld, bh);
- gfs2_log_descriptor_print(&ld);
- break;
-
- case GFS2_METATYPE_EA:
- do_eattr_extended(bh);
- break;
-
- case GFS2_METATYPE_ED:
- gfs2_meta_header_print(&mh);
- break;
-
- case GFS2_METATYPE_LB:
- gfs2_meta_header_print(&mh);
- break;
-
- case GFS2_METATYPE_QC:
- gfs2_quota_change_in(&qc, bh);
- gfs2_quota_change_print(&qc);
- break;
-
- default:
- break;
- }
- break;
-
- default:
- print_gfs2("Unknown block type");
- eol(0);
- break;
- };
- return(0);
-}
diff --git a/gfs2/edit/gfs2hex.h b/gfs2/edit/gfs2hex.h
deleted file mode 100644
index d18dd59..0000000
--- a/gfs2/edit/gfs2hex.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __GFS2HEX_DOT_H__
-#define __GFS2HEX_DOT_H__
-
-#include "hexedit.h"
-
-int display_gfs2(void);
-int edit_gfs2(void);
-void do_dinode_extended(struct gfs2_dinode *di, struct gfs2_buffer_head *lbh);
-void print_gfs2(const char *fmt, ...);
-int do_indirect_extended(char *diebuf, struct iinfo *iinf, int hgt);
-void do_leaf_extended(char *dlebuf, struct iinfo *indir);
-void eol(int col);
-
-#endif /* __GFS2HEX_DOT_H__ */
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
deleted file mode 100644
index cfc3634..0000000
--- a/gfs2/edit/hexedit.c
+++ /dev/null
@@ -1,3581 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <linux/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <curses.h>
-#include <term.h>
-#include <time.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <sys/mount.h>
-#include <dirent.h>
-
-#include <linux/gfs2_ondisk.h>
-#include "copyright.cf"
-
-#include "hexedit.h"
-#include "libgfs2.h"
-#include "gfs2hex.h"
-
-#define pv(struct, member, fmt, fmt2) do { \
- print_it(" "#member, fmt, fmt2, struct->member); \
- } while (FALSE);
-
-const char *mtypes[] = {"none", "sb", "rg", "rb", "di", "in", "lf", "jd",
- "lh", "ld", "ea", "ed", "lb", "13", "qc"};
-const char *allocdesc[2][5] = {
- {"Free ", "Data ", "Unlnk", "Meta ", "Resrv"},
- {"Free ", "Data ", "FreeM", "Meta ", "Resrv"},};
-
-#define RGLIST_DUMMY_BLOCK -2
-
-int display(int identify_only);
-
-/* for assigning numeric fields: */
-#define checkassign(strfield, struct, member, value) do { \
- if (strcmp(#member, strfield) == 0) { \
- struct->member = (typeof(struct->member)) value; \
- return 0; \
- } \
- } while(0)
-
-/* for assigning string fields: */
-#define checkassigns(strfield, struct, member, val) do { \
- if (strcmp(#member, strfield) == 0) { \
- memcpy(struct->member, val, sizeof(struct->member)); \
- return 0; \
- } \
- } while(0)
-
-/* for printing numeric fields: */
-#define checkprint(strfield, struct, member) do { \
- if (strcmp(#member, strfield) == 0) { \
- if (dmode == HEX_MODE) \
- printf("0x%llx\n", \
- (unsigned long long)struct->member); \
- else \
- printf("%llu\n", \
- (unsigned long long)struct->member); \
- return 0; \
- } \
- } while(0)
-
-/* for printing string fields: */
-#define checkprints(strfield, struct, member) do { \
- if (strcmp(#member, strfield) == 0) { \
- printf("%s\n", struct->member); \
- return 0; \
- } \
- } while(0)
-
-static int gfs2_dinode_printval(struct gfs2_dinode *dip, const char *strfield)
-{
- checkprint(strfield, dip, di_mode);
- checkprint(strfield, dip, di_uid);
- checkprint(strfield, dip, di_gid);
- checkprint(strfield, dip, di_nlink);
- checkprint(strfield, dip, di_size);
- checkprint(strfield, dip, di_blocks);
- checkprint(strfield, dip, di_atime);
- checkprint(strfield, dip, di_mtime);
- checkprint(strfield, dip, di_ctime);
- checkprint(strfield, dip, di_major);
- checkprint(strfield, dip, di_minor);
- checkprint(strfield, dip, di_goal_meta);
- checkprint(strfield, dip, di_goal_data);
- checkprint(strfield, dip, di_flags);
- checkprint(strfield, dip, di_payload_format);
- checkprint(strfield, dip, di_height);
- checkprint(strfield, dip, di_depth);
- checkprint(strfield, dip, di_entries);
- checkprint(strfield, dip, di_eattr);
-
- return -1;
-}
-
-static int gfs2_dinode_assignval(struct gfs2_dinode *dia, const char *strfield,
- uint64_t value)
-{
- checkassign(strfield, dia, di_mode, value);
- checkassign(strfield, dia, di_uid, value);
- checkassign(strfield, dia, di_gid, value);
- checkassign(strfield, dia, di_nlink, value);
- checkassign(strfield, dia, di_size, value);
- checkassign(strfield, dia, di_blocks, value);
- checkassign(strfield, dia, di_atime, value);
- checkassign(strfield, dia, di_mtime, value);
- checkassign(strfield, dia, di_ctime, value);
- checkassign(strfield, dia, di_major, value);
- checkassign(strfield, dia, di_minor, value);
- checkassign(strfield, dia, di_goal_meta, value);
- checkassign(strfield, dia, di_goal_data, value);
- checkassign(strfield, dia, di_flags, value);
- checkassign(strfield, dia, di_payload_format, value);
- checkassign(strfield, dia, di_height, value);
- checkassign(strfield, dia, di_depth, value);
- checkassign(strfield, dia, di_entries, value);
- checkassign(strfield, dia, di_eattr, value);
-
- return -1;
-}
-
-static int gfs2_rgrp_printval(struct gfs2_rgrp *rg, const char *strfield)
-{
- checkprint(strfield, rg, rg_flags);
- checkprint(strfield, rg, rg_free);
- checkprint(strfield, rg, rg_dinodes);
-
- return -1;
-}
-
-static int gfs2_rgrp_assignval(struct gfs2_rgrp *rg, const char *strfield,
- uint64_t value)
-{
- checkassign(strfield, rg, rg_flags, value);
- checkassign(strfield, rg, rg_free, value);
- checkassign(strfield, rg, rg_dinodes, value);
-
- return -1;
-}
-
-/* ------------------------------------------------------------------------ */
-/* UpdateSize - screen size changed, so update it */
-/* ------------------------------------------------------------------------ */
-static void UpdateSize(int sig)
-{
- static char term_buffer[2048];
- int rc;
-
- termlines = 30;
- termtype = getenv("TERM");
- if (termtype == NULL)
- return;
- rc=tgetent(term_buffer,termtype);
- if (rc>=0) {
- termlines = tgetnum((char *)"li");
- if (termlines < 10)
- termlines = 30;
- termcols = tgetnum((char *)"co");
- if (termcols < 80)
- termcols = 80;
- }
- else
- perror("Error: tgetent failed.");
- termlines--; /* last line is number of lines -1 */
- display(FALSE);
- signal(SIGWINCH, UpdateSize);
-}
-
-/* ------------------------------------------------------------------------- */
-/* erase - clear the screen */
-/* ------------------------------------------------------------------------- */
-static void Erase(void)
-{
- int i;
- char spaces[256];
-
- memset(spaces, ' ', sizeof(spaces));
- spaces[termcols] = '\0';
- for (i = 0; i < termlines; i++) {
- move(i, 0);
- printw(spaces);
- }
- /*clear(); doesn't set background correctly */
- /*erase();*/
- /*bkgd(bg);*/
-}
-
-/* ------------------------------------------------------------------------- */
-/* display_title_lines */
-/* ------------------------------------------------------------------------- */
-static void display_title_lines(void)
-{
- Erase();
- COLORS_TITLE;
- move(0, 0);
- printw("%-80s",TITLE1);
- move(termlines, 0);
- printw("%-79s",TITLE2);
- COLORS_NORMAL;
-}
-
-/* ------------------------------------------------------------------------- */
-/* bobgets - get a string */
-/* returns: 1 if user exited by hitting enter */
-/* 0 if user exited by hitting escape */
-/* ------------------------------------------------------------------------- */
-static int bobgets(char string[],int x,int y,int sz,int *ch)
-{
- int done,runningy,rc;
-
- move(x,y);
- done=FALSE;
- COLORS_INVERSE;
- move(x,y);
- addstr(string);
- move(x,y);
- curs_set(2);
- refresh();
- runningy=y;
- rc=0;
- while (!done) {
- *ch = getch();
-
- if(*ch < 0x0100 && isprint(*ch)) {
- char *p=string+strlen(string); // end of the string
-
- *(p+1)='\0';
- while (insert && p > &string[runningy-y]) {
- *p=*(p-1);
- p--;
- }
- string[runningy-y]=*ch;
- runningy++;
- move(x,y);
- addstr(string);
- if (runningy-y >= sz) {
- rc=1;
- *ch = KEY_RIGHT;
- done = TRUE;
- }
- }
- else {
- // special character, is it one we recognize?
- switch(*ch)
- {
- case(KEY_ENTER):
- case('\n'):
- case('\r'):
- rc=1;
- done=TRUE;
- string[runningy-y] = '\0';
- break;
- case(KEY_CANCEL):
- case(0x01B):
- rc=0;
- done=TRUE;
- break;
- case(KEY_LEFT):
- if (dmode == HEX_MODE) {
- done = TRUE;
- rc = 1;
- }
- else
- runningy--;
- break;
- case(KEY_RIGHT):
- if (dmode == HEX_MODE) {
- done = TRUE;
- rc = 1;
- }
- else
- runningy++;
- break;
- case(KEY_DC):
- case(0x07F):
- if (runningy>=y) {
- char *p;
- p = &string[runningy - y];
- while (*p) {
- *p = *(p + 1);
- p++;
- }
- *p = '\0';
- runningy--;
- // remove the character from the string
- move(x,y);
- addstr(string);
- COLORS_NORMAL;
- addstr(" ");
- COLORS_INVERSE;
- runningy++;
- }
- break;
- case(KEY_BACKSPACE):
- if (runningy>y) {
- char *p;
-
- p = &string[runningy - y - 1];
- while (*p) {
- *p = *(p + 1);
- p++;
- }
- *p='\0';
- runningy--;
- // remove the character from the string
- move(x,y);
- addstr(string);
- COLORS_NORMAL;
- addstr(" ");
- COLORS_INVERSE;
- }
- break;
- case KEY_DOWN: // Down
- rc=0x5000U;
- done=TRUE;
- break;
- case KEY_UP: // Up
- rc=0x4800U;
- done=TRUE;
- break;
- case 0x014b:
- insert=!insert;
- move(0,68);
- if (insert)
- printw("insert ");
- else
- printw("replace");
- break;
- default:
- move(0,70);
- printw("%08X",*ch);
- // ignore all other characters
- break;
- } // end switch on non-printable character
- } // end non-printable character
- move(x,runningy);
- refresh();
- } // while !done
- if (sz>0)
- string[sz]='\0';
- COLORS_NORMAL;
- return rc;
-}/* bobgets */
-
-/******************************************************************************
-** instr - instructions
-******************************************************************************/
-static void gfs2instr(const char *s1, const char *s2)
-{
- COLORS_HIGHLIGHT;
- move(line,0);
- printw(s1);
- COLORS_NORMAL;
- move(line,17);
- printw(s2);
- line++;
-}
-
-/******************************************************************************
-*******************************************************************************
-**
-** void print_usage()
-**
-** Description:
-** This routine prints out the appropriate commands for this application.
-**
-*******************************************************************************
-******************************************************************************/
-
-static void print_usage(void)
-{
- int ch;
-
- line = 2;
- Erase();
- display_title_lines();
- move(line++,0);
- printw("Supported commands: (roughly conforming to the rules of 'less')");
- line++;
- move(line++,0);
- printw("Navigation:");
- gfs2instr("<pg up>/<down>","Move up or down one screen full");
- gfs2instr("<up>/<down>","Move up or down one line");
- gfs2instr("<left>/<right>","Move left or right one byte");
- gfs2instr("<home>","Return to the superblock.");
- gfs2instr(" f","Forward one 4K block");
- gfs2instr(" b","Backward one 4K block");
- gfs2instr(" g","Goto a given block (number, master, root, rindex, jindex, etc)");
- gfs2instr(" j","Jump to the highlighted 64-bit block number.");
- gfs2instr(" ","(You may also arrow up to the block number and hit enter)");
- gfs2instr("<backspace>","Return to a previous block (a block stack is kept)");
- gfs2instr("<space>","Jump forward to block before backspace (opposite of backspace)");
- line++;
- move(line++, 0);
- printw("Other commands:");
- gfs2instr(" h","This Help display");
- gfs2instr(" c","Toggle the color scheme");
- gfs2instr(" m","Switch display mode: hex -> GFS2 structure -> Extended");
- gfs2instr(" q","Quit (same as hitting <escape> key)");
- gfs2instr("<enter>","Edit a value (enter to save, esc to discard)");
- gfs2instr(" ","(Currently only works on the hex display)");
- gfs2instr("<escape>","Quit the program");
- line++;
- move(line++, 0);
- printw("Notes: Areas shown in red are outside the bounds of the struct/file.");
- move(line++, 0);
- printw(" Areas shown in blue are file contents.");
- move(line++, 0);
- printw(" Characters shown in green are selected for edit on <enter>.");
- move(line++, 0);
- move(line++, 0);
- printw("Press any key to return.");
- refresh();
- while ((ch=getch()) == 0); // wait for input
- Erase();
-}
-
-/* ------------------------------------------------------------------------ */
-/* get_block_type */
-/* returns: metatype if block is a GFS2 structure block type */
-/* 0 if block is not a GFS2 structure */
-/* ------------------------------------------------------------------------ */
-static int get_block_type(struct gfs2_buffer_head *lbh)
-{
- int ret_type = 0;
- char *lpBuffer = lbh->b_data;
-
- if (*(lpBuffer+0)==0x01 && *(lpBuffer+1)==0x16 &&
- *(lpBuffer+2)==0x19 && *(lpBuffer+3)==0x70 &&
- *(lpBuffer+4)==0x00 && *(lpBuffer+5)==0x00 &&
- *(lpBuffer+6)==0x00) /* If magic number appears at the start */
- ret_type = *(lpBuffer+7);
- return ret_type;
-}
-
-/* ------------------------------------------------------------------------ */
-/* display_block_type */
-/* returns: metatype if block is a GFS2 structure block type */
-/* 0 if block is not a GFS2 structure */
-/* ------------------------------------------------------------------------ */
-int display_block_type(int from_restore)
-{
- int ret_type = 0; /* return type */
-
- /* first, print out the kind of GFS2 block this is */
- if (termlines) {
- line = 1;
- move(line, 0);
- }
- print_gfs2("Block #");
- if (termlines) {
- if (edit_row[dmode] == -1)
- COLORS_HIGHLIGHT;
- }
- if (block == RGLIST_DUMMY_BLOCK)
- print_gfs2("RG List ");
- else
- print_gfs2("%lld (0x%"PRIx64")", block, block);
- if (termlines) {
- if (edit_row[dmode] == -1)
- COLORS_NORMAL;
- move(line,30);
- }
- else
- print_gfs2(" ");
- if (!from_restore) {
- print_gfs2("of %" PRIu64 " (0x%" PRIX64 ")", max_block,
- max_block);
- if (termlines)
- move(line, 55);
- else
- printf(" ");
- }
- if (block == RGLIST_DUMMY_BLOCK) {
- ret_type = GFS2_METATYPE_RG;
- struct_len = gfs1 ? sizeof(struct gfs_rgrp) : sizeof(struct gfs2_rgrp);
- }
- else if ((ret_type = get_block_type(bh))) {
- switch (*(bh->b_data + 7)) {
- case GFS2_METATYPE_SB: /* 1 */
- print_gfs2("(superblock)");
- if (gfs1)
- struct_len = sizeof(struct gfs_sb);
- else
- struct_len = sizeof(struct gfs2_sb);
- break;
- case GFS2_METATYPE_RG: /* 2 */
- print_gfs2("(rsrc grp hdr)");
- struct_len = sizeof(struct gfs2_rgrp);
- break;
- case GFS2_METATYPE_RB: /* 3 */
- print_gfs2("(rsrc grp bitblk)");
- struct_len = sizeof(struct gfs2_meta_header);
- break;
- case GFS2_METATYPE_DI: /* 4 */
- print_gfs2("(disk inode)");
- struct_len = sizeof(struct gfs2_dinode);
- break;
- case GFS2_METATYPE_IN: /* 5 */
- print_gfs2("(indir blklist)");
- if (gfs1)
- struct_len = sizeof(struct gfs_indirect);
- else
- struct_len = sizeof(struct gfs2_meta_header);
- break;
- case GFS2_METATYPE_LF: /* 6 */
- print_gfs2("(directory leaf)");
- struct_len = sizeof(struct gfs2_leaf);
- break;
- case GFS2_METATYPE_JD:
- print_gfs2("(journal data)");
- struct_len = sizeof(struct gfs2_meta_header);
- break;
- case GFS2_METATYPE_LH:
- print_gfs2("(log header)");
- struct_len = sizeof(struct gfs2_log_header);
- break;
- case GFS2_METATYPE_LD:
- print_gfs2("(log descriptor)");
- if (gfs1)
- struct_len = sizeof(struct gfs_log_descriptor);
- else
- struct_len =
- sizeof(struct gfs2_log_descriptor);
- break;
- case GFS2_METATYPE_EA:
- print_gfs2("(extended attr hdr)");
- struct_len = sizeof(struct gfs2_meta_header) +
- sizeof(struct gfs2_ea_header);
- break;
- case GFS2_METATYPE_ED:
- print_gfs2("(extended attr data)");
- struct_len = sizeof(struct gfs2_meta_header) +
- sizeof(struct gfs2_ea_header);
- break;
- case GFS2_METATYPE_LB:
- print_gfs2("(log buffer)");
- struct_len = sizeof(struct gfs2_meta_header);
- break;
- case GFS2_METATYPE_QC:
- print_gfs2("(quota change)");
- struct_len = sizeof(struct gfs2_quota_change);
- break;
- default:
- print_gfs2("(wtf?)");
- struct_len = sbd.bsize;
- break;
- }
- }
- else
- struct_len = sbd.bsize;
- eol(0);
- if (from_restore)
- return ret_type;
- if (termlines && dmode == HEX_MODE) {
- int type, pgnum;
- struct rgrp_list *rgd;
-
- rgd = gfs2_blk2rgrpd(&sbd, block);
- if (rgd) {
- gfs2_rgrp_read(&sbd, rgd);
- if ((*(bh->b_data + 7) == GFS2_METATYPE_RG) ||
- (*(bh->b_data + 7) == GFS2_METATYPE_RB))
- type = 4;
- else
- type = gfs2_get_bitmap(&sbd, block, rgd);
- } else
- type = 4;
- screen_chunk_size = ((termlines - 4) * 16) >> 8 << 8;
- if (!screen_chunk_size)
- screen_chunk_size = 256;
- pgnum = (offset / screen_chunk_size);
- print_gfs2("(p.%d of %d--%s)", pgnum + 1,
- (sbd.bsize % screen_chunk_size) > 0 ?
- sbd.bsize / screen_chunk_size + 1 : sbd.bsize /
- screen_chunk_size, allocdesc[gfs1][type]);
- /*eol(9);*/
- if ((*(bh->b_data + 7) == GFS2_METATYPE_IN) ||
- (*(bh->b_data + 7) == GFS2_METATYPE_DI &&
- (*(bh->b_data + 0x8b) || *(bh->b_data + 0x8a)))) {
- int ptroffset = edit_row[dmode] * 16 + edit_col[dmode];
-
- if (ptroffset >= struct_len || pgnum) {
- int pnum;
-
- pnum = pgnum * screen_chunk_size;
- pnum += (ptroffset - struct_len);
- pnum /= sizeof(uint64_t);
-
- print_gfs2(" pointer 0x%x", pnum);
- }
- }
- else if ((*(bh->b_data + 7) == GFS2_METATYPE_RG)) {
- int ptroffset = edit_row[dmode] * 16 + edit_col[dmode];
-
- if (ptroffset >= struct_len || pgnum) {
- int blknum, b, btype;
-
- blknum = pgnum * screen_chunk_size;
- blknum += (ptroffset - struct_len);
- blknum *= 4;
- blknum += rgd->ri.ri_data0;
-
- print_gfs2(" blk ");
- for (b = blknum; b < blknum + 4; b++) {
- btype = gfs2_get_bitmap(&sbd, b, rgd);
- print_gfs2("0x%x-%s ", b,
- allocdesc[gfs1][btype]);
- }
- }
- }
- else if ((*(bh->b_data + 7) == GFS2_METATYPE_RB)) {
- int ptroffset = edit_row[dmode] * 16 + edit_col[dmode];
-
- if (ptroffset >= struct_len || pgnum) {
- int blknum, b, btype, rb_number;
-
- rb_number = block - rgd->ri.ri_addr;
- blknum = 0;
- /* count the number of bytes representing
- blocks prior to the displayed screen. */
- for (b = 0; b < rb_number; b++) {
- struct_len = (b ?
- sizeof(struct gfs2_meta_header) :
- sizeof(struct gfs2_rgrp));
- blknum += (sbd.bsize - struct_len);
- }
- struct_len = sizeof(struct gfs2_meta_header);
- /* add the number of bytes on this screen */
- blknum += (ptroffset - struct_len);
- /* factor in the page number */
- blknum += pgnum * screen_chunk_size;
- /* convert bytes to blocks */
- blknum *= GFS2_NBBY;
- /* add the starting offset for this rgrp */
- blknum += rgd->ri.ri_data0;
- print_gfs2(" blk ");
- for (b = blknum; b < blknum + 4; b++) {
- btype = gfs2_get_bitmap(&sbd, b, rgd);
- print_gfs2("0x%x-%s ", b,
- allocdesc[gfs1][btype]);
- }
- }
- }
- if (rgd)
- gfs2_rgrp_relse(rgd);
- }
- if (block == sbd.sd_sb.sb_root_dir.no_addr)
- print_gfs2("--------------- Root directory ------------------");
- else if (!gfs1 && block == sbd.sd_sb.sb_master_dir.no_addr)
- print_gfs2("-------------- Master directory -----------------");
- else if (!gfs1 && block == RGLIST_DUMMY_BLOCK)
- print_gfs2("------------------ RG List ----------------------");
- else {
- if (gfs1) {
- if (block == sbd1->sb_rindex_di.no_addr)
- print_gfs2("---------------- rindex file -------------------");
- else if (block == gfs1_quota_di.no_addr)
- print_gfs2("---------------- Quota file --------------------");
- else if (block == sbd1->sb_jindex_di.no_addr)
- print_gfs2("--------------- Journal Index ------------------");
- else if (block == gfs1_license_di.no_addr)
- print_gfs2("--------------- License file -------------------");
- }
- else {
- int d;
-
- for (d = 2; d < 8; d++) {
- if (block == masterdir.dirent[d].block) {
- if (!strncmp(masterdir.dirent[d].filename, "jindex", 6))
- print_gfs2("--------------- Journal Index ------------------");
- else if (!strncmp(masterdir.dirent[d].filename, "per_node", 8))
- print_gfs2("--------------- Per-node Dir -------------------");
- else if (!strncmp(masterdir.dirent[d].filename, "inum", 4))
- print_gfs2("---------------- Inum file ---------------------");
- else if (!strncmp(masterdir.dirent[d].filename, "statfs", 6))
- print_gfs2("---------------- statfs file -------------------");
- else if (!strncmp(masterdir.dirent[d].filename, "rindex", 6))
- print_gfs2("---------------- rindex file -------------------");
- else if (!strncmp(masterdir.dirent[d].filename, "quota", 5))
- print_gfs2("---------------- Quota file --------------------");
- }
- }
- }
- }
- eol(0);
- return ret_type;
-}
-
-/* ------------------------------------------------------------------------ */
-/* hexdump - hex dump the filesystem block to the screen */
-/* ------------------------------------------------------------------------ */
-static int hexdump(uint64_t startaddr, int len)
-{
- const unsigned char *pointer,*ptr2;
- int i;
- uint64_t l;
- const char *lpBuffer = bh->b_data;
-
- strcpy(edit_fmt,"%02X");
- pointer = (unsigned char *)lpBuffer + offset;
- ptr2 = (unsigned char *)lpBuffer + offset;
- l = offset;
- print_entry_ndx = 0;
- while (((termlines &&
- line < termlines &&
- line <= ((screen_chunk_size / 16) + 2)) ||
- (!termlines && l < len)) &&
- l < sbd.bsize) {
- int ptr_not_null = 0;
-
- if (termlines) {
- move(line, 0);
- COLORS_OFFSETS; /* cyan for offsets */
- }
- if (startaddr < 0xffffffff)
- print_gfs2("%.8"PRIX64, startaddr + l);
- else
- print_gfs2("%.16"PRIX64, startaddr + l);
- if (termlines) {
- if (l < struct_len)
- COLORS_NORMAL; /* normal part of structure */
- else if (gfs2_struct_type == GFS2_METATYPE_DI &&
- l < struct_len + di.di_size)
- COLORS_CONTENTS; /* after struct but not eof */
- else
- COLORS_SPECIAL; /* beyond end of the struct */
- }
- for (i = 0; i < 16; i++) { /* first print it in hex */
- /* Figure out if we have a null pointer--for colors */
- if (((gfs2_struct_type == GFS2_METATYPE_IN) ||
- (gfs2_struct_type == GFS2_METATYPE_DI &&
- l < struct_len + di.di_size &&
- (di.di_height > 0 || !S_ISREG(di.di_mode)))) &&
- (i==0 || i==8)) {
- int j;
-
- ptr_not_null = 0;
- for (j = 0; j < 8; j++) {
- if (*(pointer + j)) {
- ptr_not_null = 1;
- break;
- }
- }
- }
- if (termlines) {
- if (l + i < struct_len)
- COLORS_NORMAL; /* in the structure */
- else if (gfs2_struct_type == GFS2_METATYPE_DI
- && l + i < struct_len + di.di_size) {
- if ((!di.di_height &&
- S_ISREG(di.di_mode)) ||
- !ptr_not_null)
- COLORS_CONTENTS;/*stuff data */
- else
- COLORS_SPECIAL;/* non-null */
- }
- else if (gfs2_struct_type == GFS2_METATYPE_IN){
- if (ptr_not_null)
- COLORS_SPECIAL;/* non-null */
- else
- COLORS_CONTENTS;/* null */
- } else
- COLORS_SPECIAL; /* past the struct */
- }
- if (i%4 == 0)
- print_gfs2(" ");
- if (termlines && line == edit_row[dmode] + 3 &&
- i == edit_col[dmode]) {
- COLORS_HIGHLIGHT; /* in the structure */
- memset(estring,0,3);
- sprintf(estring,"%02X",*pointer);
- }
- print_gfs2("%02X",*pointer);
- if (termlines && line == edit_row[dmode] + 3 &&
- i == edit_col[dmode]) {
- if (l < struct_len + offset)
- COLORS_NORMAL; /* in the structure */
- else
- COLORS_SPECIAL; /* beyond structure */
- }
- pointer++;
- }
- print_gfs2(" [");
- for (i=0; i<16; i++) { /* now print it in character format */
- if ((*ptr2 >=' ') && (*ptr2 <= '~'))
- print_gfs2("%c",*ptr2);
- else
- print_gfs2(".");
- ptr2++;
- }
- print_gfs2("] ");
- if (line - 3 > last_entry_onscreen[dmode])
- last_entry_onscreen[dmode] = line - 3;
- eol(0);
- l+=16;
- print_entry_ndx++;
- } /* while */
- if (gfs1) {
- COLORS_NORMAL;
- print_gfs2(" *** This seems to be a GFS-1 file system ***");
- eol(0);
- }
- return (offset+len);
-}/* hexdump */
-
-/* ------------------------------------------------------------------------ */
-/* masterblock - find a file (by name) in the master directory and return */
-/* its block number. */
-/* ------------------------------------------------------------------------ */
-uint64_t masterblock(const char *fn)
-{
- int d;
-
- for (d = 2; d < 8; d++)
- if (!strncmp(masterdir.dirent[d].filename, fn, strlen(fn)))
- return (masterdir.dirent[d].block);
- return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-/* risize - size of one rindex entry, whether gfs1 or gfs2 */
-/* ------------------------------------------------------------------------ */
-static int risize(void)
-{
- if (gfs1)
- return sizeof(struct gfs_rindex);
- else
- return sizeof(struct gfs2_rindex);
-}
-
-/* ------------------------------------------------------------------------ */
-/* rgcount - return how many rgrps there are. */
-/* ------------------------------------------------------------------------ */
-static void rgcount(void)
-{
- printf("%lld RGs in this file system.\n",
- (unsigned long long)sbd.md.riinode->i_di.di_size / risize());
- inode_put(&sbd.md.riinode);
- gfs2_rgrp_free(&sbd.rglist);
- exit(EXIT_SUCCESS);
-}
-
-/* ------------------------------------------------------------------------ */
-/* find_rgrp_block - locate the block for a given rgrp number */
-/* ------------------------------------------------------------------------ */
-static uint64_t find_rgrp_block(struct gfs2_inode *dif, int rg)
-{
- int amt;
- struct gfs2_rindex fbuf, ri;
- uint64_t foffset, gfs1_adj = 0;
-
- foffset = rg * risize();
- if (gfs1) {
- uint64_t sd_jbsize =
- (sbd.bsize - sizeof(struct gfs2_meta_header));
-
- gfs1_adj = (foffset / sd_jbsize) *
- sizeof(struct gfs2_meta_header);
- gfs1_adj += sizeof(struct gfs2_meta_header);
- }
- amt = gfs2_readi(dif, (void *)&fbuf, foffset + gfs1_adj, risize());
- if (!amt) /* end of file */
- return 0;
- gfs2_rindex_in(&ri, (void *)&fbuf);
- return ri.ri_addr;
-}
-
-/* ------------------------------------------------------------------------ */
-/* gfs_rgrp_in - Read in a resource group header */
-/* ------------------------------------------------------------------------ */
-static void gfs_rgrp_in(struct gfs_rgrp *rgrp, struct gfs2_buffer_head *rbh)
-{
- struct gfs_rgrp *str = (struct gfs_rgrp *)rbh->b_data;
-
- gfs2_meta_header_in(&rgrp->rg_header, rbh);
- rgrp->rg_flags = be32_to_cpu(str->rg_flags);
- rgrp->rg_free = be32_to_cpu(str->rg_free);
- rgrp->rg_useddi = be32_to_cpu(str->rg_useddi);
- rgrp->rg_freedi = be32_to_cpu(str->rg_freedi);
- gfs2_inum_in(&rgrp->rg_freedi_list, (char *)&str->rg_freedi_list);
- rgrp->rg_usedmeta = be32_to_cpu(str->rg_usedmeta);
- rgrp->rg_freemeta = be32_to_cpu(str->rg_freemeta);
-}
-
-/* ------------------------------------------------------------------------ */
-/* gfs_rgrp_out */
-/* ------------------------------------------------------------------------ */
-static void gfs_rgrp_out(struct gfs_rgrp *rgrp, struct gfs2_buffer_head *rbh)
-{
- struct gfs_rgrp *str = (struct gfs_rgrp *)rbh->b_data;
-
- gfs2_meta_header_out(&rgrp->rg_header, rbh);
- str->rg_flags = cpu_to_be32(rgrp->rg_flags);
- str->rg_free = cpu_to_be32(rgrp->rg_free);
- str->rg_useddi = cpu_to_be32(rgrp->rg_useddi);
- str->rg_freedi = cpu_to_be32(rgrp->rg_freedi);
- gfs2_inum_out(&rgrp->rg_freedi_list, (char *)&str->rg_freedi_list);
- str->rg_usedmeta = cpu_to_be32(rgrp->rg_usedmeta);
- str->rg_freemeta = cpu_to_be32(rgrp->rg_freemeta);
-}
-
-/* ------------------------------------------------------------------------ */
-/* gfs_rgrp_print - print a gfs1 resource group */
-/* ------------------------------------------------------------------------ */
-static void gfs_rgrp_print(struct gfs_rgrp *rg)
-{
- gfs2_meta_header_print(&rg->rg_header);
- pv(rg, rg_flags, "%u", "0x%x");
- pv(rg, rg_free, "%u", "0x%x");
- pv(rg, rg_useddi, "%u", "0x%x");
- pv(rg, rg_freedi, "%u", "0x%x");
- gfs2_inum_print(&rg->rg_freedi_list);
- pv(rg, rg_usedmeta, "%u", "0x%x");
- pv(rg, rg_freemeta, "%u", "0x%x");
-}
-
-/* ------------------------------------------------------------------------ */
-/* get_rg_addr */
-/* ------------------------------------------------------------------------ */
-static uint64_t get_rg_addr(int rgnum)
-{
- uint64_t rgblk = 0, gblock;
- struct gfs2_inode *riinode;
-
- if (gfs1)
- gblock = sbd1->sb_rindex_di.no_addr;
- else
- gblock = masterblock("rindex");
- riinode = inode_read(&sbd, gblock);
- if (rgnum < riinode->i_di.di_size / risize())
- rgblk = find_rgrp_block(riinode, rgnum);
- else
- fprintf(stderr, "Error: File system only has %lld RGs.\n",
- (unsigned long long)riinode->i_di.di_size / risize());
- inode_put(&riinode);
- return rgblk;
-}
-
-/* ------------------------------------------------------------------------ */
-/* set_rgrp_flags - Set an rgrp's flags to a given value */
-/* rgnum: which rg to print or modify flags for (0 - X) */
-/* new_flags: value to set new rg_flags to (if modify == TRUE) */
-/* modify: TRUE if the value is to be modified, FALSE if it's to be printed */
-/* full: TRUE if the full RG should be printed. */
-/* ------------------------------------------------------------------------ */
-static void set_rgrp_flags(int rgnum, uint32_t new_flags, int modify, int full)
-{
- union {
- struct gfs2_rgrp rg2;
- struct gfs_rgrp rg1;
- } rg;
- struct gfs2_buffer_head *rbh;
- uint64_t rgblk;
-
- rgblk = get_rg_addr(rgnum);
- rbh = bread(&sbd, rgblk);
- if (gfs1)
- gfs_rgrp_in(&rg.rg1, rbh);
- else
- gfs2_rgrp_in(&rg.rg2, rbh);
- if (modify) {
- printf("RG #%d (block %llu / 0x%llx) rg_flags changed from 0x%08x to 0x%08x\n",
- rgnum, (unsigned long long)rgblk,
- (unsigned long long)rgblk, rg.rg2.rg_flags, new_flags);
- rg.rg2.rg_flags = new_flags;
- if (gfs1)
- gfs_rgrp_out(&rg.rg1, rbh);
- else
- gfs2_rgrp_out(&rg.rg2, rbh);
- brelse(rbh);
- } else {
- if (full) {
- print_gfs2("RG #%d", rgnum);
- print_gfs2(" located at: %llu (0x%llx)", rgblk, rgblk);
- eol(0);
- if (gfs1)
- gfs_rgrp_print(&rg.rg1);
- else
- gfs2_rgrp_print(&rg.rg2);
- }
- else
- printf("RG #%d (block %llu / 0x%llx) rg_flags = 0x%08x\n",
- rgnum, (unsigned long long)rgblk,
- (unsigned long long)rgblk, rg.rg2.rg_flags);
- brelse(rbh);
- }
- if (modify)
- fsync(sbd.device_fd);
-}
-
-/* ------------------------------------------------------------------------ */
-/* parse_rindex - print the rgindex file. */
-/* ------------------------------------------------------------------------ */
-static int parse_rindex(struct gfs2_inode *dip, int print_rindex)
-{
- int error, start_line;
- struct gfs2_rindex ri;
- char rbuf[sizeof(struct gfs_rindex)];
- char highlighted_addr[32];
-
- start_line = line;
- error = 0;
- print_gfs2("RG index entries found: %d.", dip->i_di.di_size / risize());
- eol(0);
- lines_per_row[dmode] = 6;
- memset(highlighted_addr, 0, sizeof(highlighted_addr));
-
- for (print_entry_ndx=0; ; print_entry_ndx++) {
- uint64_t roff;
-
- roff = print_entry_ndx * risize();
-
- if (gfs1)
- error = gfs1_readi(dip, (void *)&rbuf, roff, risize());
- else
- error = gfs2_readi(dip, (void *)&rbuf, roff, risize());
- if (!error) /* end of file */
- break;
- gfs2_rindex_in(&ri, rbuf);
- if (!termlines ||
- (print_entry_ndx >= start_row[dmode] &&
- ((print_entry_ndx - start_row[dmode])+1) * lines_per_row[dmode] <=
- termlines - start_line - 2)) {
- if (edit_row[dmode] == print_entry_ndx) {
- COLORS_HIGHLIGHT;
- sprintf(highlighted_addr, "%llx", (unsigned long long)ri.ri_addr);
- }
- print_gfs2("RG #%d", print_entry_ndx);
- if (!print_rindex)
- print_gfs2(" located at: %llu (0x%llx)",
- ri.ri_addr, ri.ri_addr);
- eol(0);
- if (edit_row[dmode] == print_entry_ndx)
- COLORS_NORMAL;
- if(print_rindex)
- gfs2_rindex_print(&ri);
- else {
- struct gfs2_buffer_head *tmp_bh;
-
- tmp_bh = bread(&sbd, ri.ri_addr);
- if (gfs1) {
- struct gfs_rgrp rg1;
- gfs_rgrp_in(&rg1, tmp_bh);
- gfs_rgrp_print(&rg1);
- } else {
- struct gfs2_rgrp rg;
- gfs2_rgrp_in(&rg, tmp_bh);
- gfs2_rgrp_print(&rg);
- }
- brelse(tmp_bh);
- }
- last_entry_onscreen[dmode] = print_entry_ndx;
- }
- }
- strcpy(estring, highlighted_addr);
- end_row[dmode] = print_entry_ndx;
- return error;
-}
-
-/* ------------------------------------------------------------------------ */
-/* gfs_jindex_in - read in a gfs1 jindex structure. */
-/* ------------------------------------------------------------------------ */
-void gfs_jindex_in(struct gfs_jindex *jindex, char *jbuf)
-{
- struct gfs_jindex *str = (struct gfs_jindex *) jbuf;
-
- jindex->ji_addr = be64_to_cpu(str->ji_addr);
- jindex->ji_nsegment = be32_to_cpu(str->ji_nsegment);
- jindex->ji_pad = be32_to_cpu(str->ji_pad);
- memcpy(jindex->ji_reserved, str->ji_reserved, 64);
-}
-
-/* ------------------------------------------------------------------------ */
-/* gfs_jindex_print - print an jindex entry. */
-/* ------------------------------------------------------------------------ */
-static void gfs_jindex_print(struct gfs_jindex *ji)
-{
- pv((unsigned long long)ji, ji_addr, "%llu", "0x%llx");
- pv(ji, ji_nsegment, "%u", "0x%x");
- pv(ji, ji_pad, "%u", "0x%x");
-}
-
-/* ------------------------------------------------------------------------ */
-/* print_jindex - print the jindex file. */
-/* ------------------------------------------------------------------------ */
-static int print_jindex(struct gfs2_inode *dij)
-{
- int error, start_line;
- struct gfs_jindex ji;
- char jbuf[sizeof(struct gfs_jindex)];
-
- start_line = line;
- error = 0;
- print_gfs2("Journal index entries found: %d.",
- dij->i_di.di_size / sizeof(struct gfs_jindex));
- eol(0);
- lines_per_row[dmode] = 4;
- for (print_entry_ndx=0; ; print_entry_ndx++) {
- error = gfs2_readi(dij, (void *)&jbuf,
- print_entry_ndx*sizeof(struct gfs_jindex),
- sizeof(struct gfs_jindex));
- gfs_jindex_in(&ji, jbuf);
- if (!error) /* end of file */
- break;
- if (!termlines ||
- (print_entry_ndx >= start_row[dmode] &&
- ((print_entry_ndx - start_row[dmode])+1) *
- lines_per_row[dmode] <= termlines - start_line - 2)) {
- if (edit_row[dmode] == print_entry_ndx) {
- COLORS_HIGHLIGHT;
- strcpy(efield, "ji_addr");
- sprintf(estring, "%" PRIx64, ji.ji_addr);
- }
- print_gfs2("Journal #%d", print_entry_ndx);
- eol(0);
- if (edit_row[dmode] == print_entry_ndx)
- COLORS_NORMAL;
- gfs_jindex_print(&ji);
- last_entry_onscreen[dmode] = print_entry_ndx;
- }
- }
- end_row[dmode] = print_entry_ndx;
- return error;
-}
-
-/* ------------------------------------------------------------------------ */
-/* print_inum - print the inum file. */
-/* ------------------------------------------------------------------------ */
-static int print_inum(struct gfs2_inode *dii)
-{
- uint64_t inum, inodenum;
- int rc;
-
- rc = gfs2_readi(dii, (void *)&inum, 0, sizeof(inum));
- if (!rc) {
- print_gfs2("The inum file is empty.");
- eol(0);
- return 0;
- }
- if (rc != sizeof(inum)) {
- print_gfs2("Error reading inum file.");
- eol(0);
- return -1;
- }
- inodenum = be64_to_cpu(inum);
- print_gfs2("Next inode num = %lld (0x%llx)", inodenum, inodenum);
- eol(0);
- return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-/* print_statfs - print the statfs file. */
-/* ------------------------------------------------------------------------ */
-static int print_statfs(struct gfs2_inode *dis)
-{
- struct gfs2_statfs_change sfb, sfc;
- int rc;
-
- rc = gfs2_readi(dis, (void *)&sfb, 0, sizeof(sfb));
- if (!rc) {
- print_gfs2("The statfs file is empty.");
- eol(0);
- return 0;
- }
- if (rc != sizeof(sfb)) {
- print_gfs2("Error reading statfs file.");
- eol(0);
- return -1;
- }
- gfs2_statfs_change_in(&sfc, (char *)&sfb);
- print_gfs2("statfs file contents:");
- eol(0);
- gfs2_statfs_change_print(&sfc);
- return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-/* print_quota - print the quota file. */
-/* ------------------------------------------------------------------------ */
-static int print_quota(struct gfs2_inode *diq)
-{
- struct gfs2_quota qbuf, q;
- int i, error;
-
- print_gfs2("quota file contents:");
- eol(0);
- print_gfs2("quota entries found: %d.", diq->i_di.di_size / sizeof(q));
- eol(0);
- for (i=0; ; i++) {
- error = gfs2_readi(diq, (void *)&qbuf, i * sizeof(q), sizeof(qbuf));
- if (!error)
- break;
- if (error != sizeof(qbuf)) {
- print_gfs2("Error reading quota file.");
- eol(0);
- return -1;
- }
- gfs2_quota_in(&q, (char *)&qbuf);
- print_gfs2("Entry #%d", i + 1);
- eol(0);
- gfs2_quota_print(&q);
- }
- return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-/* has_indirect_blocks */
-/* ------------------------------------------------------------------------ */
-static int has_indirect_blocks(void)
-{
- if (indirect_blocks || gfs2_struct_type == GFS2_METATYPE_SB ||
- gfs2_struct_type == GFS2_METATYPE_LF ||
- (gfs2_struct_type == GFS2_METATYPE_DI &&
- (S_ISDIR(di.di_mode) || (gfs1 && di.__pad1 == GFS_FILE_DIR))))
- return TRUE;
- return FALSE;
-}
-
-/* ------------------------------------------------------------------------ */
-/* print_inode_type */
-/* ------------------------------------------------------------------------ */
-static void print_inode_type(__be16 de_type)
-{
- if (gfs1) {
- switch(de_type) {
- case GFS_FILE_NON:
- print_gfs2("Unknown");
- break;
- case GFS_FILE_REG:
- print_gfs2("File ");
- break;
- case GFS_FILE_DIR:
- print_gfs2("Dir ");
- break;
- case GFS_FILE_LNK:
- print_gfs2("Symlink");
- break;
- case GFS_FILE_BLK:
- print_gfs2("BlkDev ");
- break;
- case GFS_FILE_CHR:
- print_gfs2("ChrDev ");
- break;
- case GFS_FILE_FIFO:
- print_gfs2("Fifo ");
- break;
- case GFS_FILE_SOCK:
- print_gfs2("Socket ");
- break;
- default:
- print_gfs2("%04x ", de_type);
- break;
- }
- return;
- }
- switch(de_type) {
- case DT_UNKNOWN:
- print_gfs2("Unknown");
- break;
- case DT_REG:
- print_gfs2("File ");
- break;
- case DT_DIR:
- print_gfs2("Dir ");
- break;
- case DT_LNK:
- print_gfs2("Symlink");
- break;
- case DT_BLK:
- print_gfs2("BlkDev ");
- break;
- case DT_CHR:
- print_gfs2("ChrDev ");
- break;
- case DT_FIFO:
- print_gfs2("Fifo ");
- break;
- case DT_SOCK:
- print_gfs2("Socket ");
- break;
- default:
- print_gfs2("%04x ", de_type);
- break;
- }
-}
-
-/* ------------------------------------------------------------------------ */
-/* display_leaf - display directory leaf */
-/* ------------------------------------------------------------------------ */
-static int display_leaf(struct iinfo *ind)
-{
- int start_line, total_dirents = start_row[dmode];
- int d;
-
- eol(0);
- if (gfs2_struct_type == GFS2_METATYPE_SB)
- print_gfs2("The superblock has 2 directories");
- else
- print_gfs2("This directory block contains %d directory entries.",
- ind->ii[0].dirents);
-
- start_line = line;
- for (d = start_row[dmode]; d < ind->ii[0].dirents; d++) {
- if (termlines && d >= termlines - start_line - 2
- + start_row[dmode])
- break;
- total_dirents++;
- if (ind->ii[0].dirents > 1) {
- eol(5);
- if (termlines) {
- if (edit_row[dmode] >=0 &&
- line - start_line - 1 ==
- edit_row[dmode] - start_row[dmode]) {
- COLORS_HIGHLIGHT;
- sprintf(estring, "%"PRIx64,
- ind->ii[0].dirent[d].block);
- strcpy(edit_fmt, "%"PRIx64);
- }
- }
- print_gfs2("%d. (%d). %lld (0x%llx): ",
- total_dirents, d + 1,
- ind->ii[0].dirent[d].block,
- ind->ii[0].dirent[d].block);
- }
- print_inode_type(ind->ii[0].dirent[d].dirent.de_type);
- print_gfs2(" %s", ind->ii[0].dirent[d].filename);
- if (termlines) {
- if (edit_row[dmode] >= 0 &&
- line - start_line - 1 == edit_row[dmode] -
- start_row[dmode])
- COLORS_NORMAL;
- }
- }
- if (line >= 4)
- last_entry_onscreen[dmode] = line - 4;
- eol(0);
- end_row[dmode] = ind->ii[0].dirents;
- if (end_row[dmode] < last_entry_onscreen[dmode])
- end_row[dmode] = last_entry_onscreen[dmode];
- return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-/* metapath_to_lblock - convert from metapath, height to logical block */
-/* ------------------------------------------------------------------------ */
-static uint64_t metapath_to_lblock(struct metapath *mp, int hgt)
-{
- int h;
- uint64_t lblock = 0;
- uint64_t factor[GFS2_MAX_META_HEIGHT];
-
- if (di.di_height < 2)
- return mp->mp_list[0];
- /* figure out multiplication factors for each height */
- memset(&factor, 0, sizeof(factor));
- factor[di.di_height - 1] = 1ull;
- for (h = di.di_height - 2; h >= 0; h--)
- factor[h] = factor[h + 1] * sbd.sd_inptrs;
- for (h = 0; h <= hgt; h++)
- lblock += (mp->mp_list[h] * factor[h]);
- return lblock;
-}
-
-/* ------------------------------------------------------------------------ */
-/* dinode_valid - check if we have a dinode in recent history */
-/* ------------------------------------------------------------------------ */
-static int dinode_valid(void)
-{
- int i;
-
- if (gfs2_struct_type == GFS2_METATYPE_DI)
- return 1;
- for (i = 0; i <= blockhist && i < 5; i++) {
- if (blockstack[(blockhist - i) %
- BLOCK_STACK_SIZE].gfs2_struct_type ==
- GFS2_METATYPE_DI)
- return 1;
- }
- return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-/* get_height */
-/* ------------------------------------------------------------------------ */
-static int get_height(void)
-{
- int cur_height = 0, i;
-
- if (gfs2_struct_type != GFS2_METATYPE_DI) {
- for (i = 0; i <= blockhist && i < 5; i++) {
- if (blockstack[(blockhist - i) %
- BLOCK_STACK_SIZE].gfs2_struct_type ==
- GFS2_METATYPE_DI)
- break;
- cur_height++;
- }
- }
- return cur_height;
-}
-
-/* ------------------------------------------------------------------------ */
-/* display_indirect */
-/* ------------------------------------------------------------------------ */
-static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t startoff)
-{
- int start_line, total_dirents;
- int cur_height = -1, pndx;
-
- last_entry_onscreen[dmode] = 0;
- if (!has_indirect_blocks())
- return -1;
- if (!level) {
- if (gfs2_struct_type == GFS2_METATYPE_DI) {
- if (S_ISDIR(di.di_mode))
- print_gfs2("This directory contains %d indirect blocks",
- indblocks);
- else
- print_gfs2("This inode contains %d indirect blocks",
- indblocks);
- }
- else
- print_gfs2("This indirect block contains %d indirect blocks",
- indblocks);
- }
- total_dirents = 0;
- if (dinode_valid() && !S_ISDIR(di.di_mode)) {
- /* See if we are on an inode or have one in history. */
- if (level)
- cur_height = level;
- else {
- cur_height = get_height();
- print_gfs2(" (at height %d of %d)",
- cur_height, di.di_height);
- }
- }
- eol(0);
- if (!level && indblocks) {
- print_gfs2("Indirect blocks:");
- eol(0);
- }
- start_line = line;
- dsplines = termlines - line - 1;
- for (pndx = start_row[dmode];
- (!termlines || pndx < termlines - start_line - 1
- + start_row[dmode]) && pndx < indblocks;
- pndx++) {
- uint64_t file_offset;
-
- print_entry_ndx = pndx;
- if (termlines) {
- if (edit_row[dmode] >= 0 &&
- line - start_line ==
- edit_row[dmode] - start_row[dmode])
- COLORS_HIGHLIGHT;
- move(line, 1);
- }
- if (!termlines) {
- int h;
-
- for (h = 0; h < level; h++)
- print_gfs2(" ");
- }
- print_gfs2("%d => ", pndx);
- if (termlines)
- move(line,9);
- print_gfs2("0x%llx / %lld", ind->ii[pndx].block,
- ind->ii[pndx].block);
- if (termlines) {
- if (edit_row[dmode] >= 0 &&
- line - start_line ==
- edit_row[dmode] - start_row[dmode]) {
- sprintf(estring, "%"PRIx64,
- ind->ii[print_entry_ndx].block);
- strcpy(edit_fmt, "%"PRIx64);
- edit_size[dmode] = strlen(estring);
- COLORS_NORMAL;
- }
- }
- if (dinode_valid() && !S_ISDIR(di.di_mode)) {
- float human_off;
- char h;
-
- file_offset = metapath_to_lblock(&ind->ii[pndx].mp,
- cur_height) *
- sbd.bsize;
- print_gfs2(" ");
- h = 'K';
- human_off = (file_offset / 1024.0);
- if (human_off > 1024.0) { h = 'M'; human_off /= 1024.0; }
- if (human_off > 1024.0) { h = 'G'; human_off /= 1024.0; }
- if (human_off > 1024.0) { h = 'T'; human_off /= 1024.0; }
- if (human_off > 1024.0) { h = 'P'; human_off /= 1024.0; }
- if (human_off > 1024.0) { h = 'E'; human_off /= 1024.0; }
- print_gfs2("(data offset 0x%llx / %lld / %6.2f%c)",
- file_offset, file_offset, human_off, h);
- print_gfs2(" ");
- }
- else
- file_offset = 0;
- if (dinode_valid() && !termlines &&
- ((level + 1 < di.di_height) ||
- (S_ISDIR(di.di_mode) && !level))) {
- struct iinfo *more_indir;
- int more_ind;
- char *tmpbuf;
-
- more_indir = malloc(sizeof(struct iinfo));
- tmpbuf = malloc(sbd.bsize);
- if (tmpbuf) {
- lseek(sbd.device_fd,
- ind->ii[pndx].block * sbd.bsize,
- SEEK_SET);
- /* read in the desired block */
- if (read(sbd.device_fd, tmpbuf, sbd.bsize) !=
- sbd.bsize) {
- fprintf(stderr, "bad read: %s from %s:"
- "%d: block %lld (0x%llx)\n",
- strerror(errno),
- __FUNCTION__, __LINE__,
- (unsigned long long)ind->ii[pndx].block,
- (unsigned long long)ind->ii[pndx].block);
- exit(-1);
- }
- memset(more_indir, 0, sizeof(struct iinfo));
- if (S_ISDIR(di.di_mode)) {
- do_leaf_extended(tmpbuf, more_indir);
- display_leaf(more_indir);
- } else {
- int x;
-
- for (x = 0; x < 512; x++) {
- memcpy(&more_indir->ii[x].mp,
- &ind->ii[pndx].mp,
- sizeof(struct metapath));
- more_indir->ii[x].
- mp.mp_list[cur_height+1] =
- x;
- }
- more_ind = do_indirect_extended(tmpbuf,
- more_indir,
- cur_height + 1);
- display_indirect(more_indir,
- more_ind, level + 1,
- file_offset);
- }
- free(tmpbuf);
- }
- free(more_indir);
- }
- print_entry_ndx = pndx; /* restore after recursion */
- eol(0);
- } /* for each display row */
- if (line >= 7) /* 7 because it was bumped at the end */
- last_entry_onscreen[dmode] = line - 7;
- eol(0);
- end_row[dmode] = indblocks;
- if (end_row[dmode] < last_entry_onscreen[dmode])
- end_row[dmode] = last_entry_onscreen[dmode];
- lines_per_row[dmode] = 1;
- return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-/* block_is_rindex */
-/* ------------------------------------------------------------------------ */
-int block_is_rindex(void)
-{
- if ((gfs1 && block == sbd1->sb_rindex_di.no_addr) ||
- (block == masterblock("rindex")))
- return TRUE;
- return FALSE;
-}
-
-/* ------------------------------------------------------------------------ */
-/* block_is_rglist - there's no such block as the rglist. This is a */
-/* special case meant to parse the rindex and follow the */
-/* blocks to the real rgs. */
-/* ------------------------------------------------------------------------ */
-static int block_is_rglist(void)
-{
- if (block == RGLIST_DUMMY_BLOCK)
- return TRUE;
- return FALSE;
-}
-
-/* ------------------------------------------------------------------------ */
-/* block_is_jindex */
-/* ------------------------------------------------------------------------ */
-int block_is_jindex(void)
-{
- if ((gfs1 && block == sbd1->sb_jindex_di.no_addr))
- return TRUE;
- return FALSE;
-}
-
-/* ------------------------------------------------------------------------ */
-/* block_is_inum_file */
-/* ------------------------------------------------------------------------ */
-int block_is_inum_file(void)
-{
- if (!gfs1 && block == masterblock("inum"))
- return TRUE;
- return FALSE;
-}
-
-/* ------------------------------------------------------------------------ */
-/* block_is_statfs_file */
-/* ------------------------------------------------------------------------ */
-int block_is_statfs_file(void)
-{
- if (gfs1 && block == gfs1_license_di.no_addr)
- return TRUE;
- if (!gfs1 && block == masterblock("statfs"))
- return TRUE;
- return FALSE;
-}
-
-/* ------------------------------------------------------------------------ */
-/* block_is_quota_file */
-/* ------------------------------------------------------------------------ */
-int block_is_quota_file(void)
-{
- if (gfs1 && block == gfs1_quota_di.no_addr)
- return TRUE;
- if (!gfs1 && block == masterblock("quota"))
- return TRUE;
- return FALSE;
-}
-
-/* ------------------------------------------------------------------------ */
-/* block_is_per_node */
-/* ------------------------------------------------------------------------ */
-int block_is_per_node(void)
-{
- if (!gfs1 && block == masterblock("per_node"))
- return TRUE;
- return FALSE;
-}
-
-/* ------------------------------------------------------------------------ */
-/* block_is_in_per_node */
-/* ------------------------------------------------------------------------ */
-int block_is_in_per_node(void)
-{
- int d;
- struct gfs2_inode *per_node_di;
-
- if (gfs1)
- return FALSE;
-
- per_node_di = inode_read(&sbd, masterblock("per_node"));
-
- do_dinode_extended(&per_node_di->i_di, per_node_di->i_bh);
- inode_put(&per_node_di);
-
- for (d = 0; d < indirect->ii[0].dirents; d++) {
- if (block == indirect->ii[0].dirent[d].block)
- return TRUE;
- }
- return FALSE;
-}
-
-/* ------------------------------------------------------------------------ */
-/* block_has_extended_info */
-/* ------------------------------------------------------------------------ */
-static int block_has_extended_info(void)
-{
- if (has_indirect_blocks() ||
- block_is_rindex() ||
- block_is_rglist() ||
- block_is_jindex() ||
- block_is_inum_file() ||
- block_is_statfs_file() ||
- block_is_quota_file())
- return TRUE;
- return FALSE;
-}
-
-/* ------------------------------------------------------------------------ */
-/* display_extended */
-/* ------------------------------------------------------------------------ */
-static int display_extended(void)
-{
- struct gfs2_inode *tmp_inode;
- struct gfs2_buffer_head *tmp_bh;
-
- /* Display any indirect pointers that we have. */
- if (block_is_rindex()) {
- tmp_bh = bread(&sbd, block);
- tmp_inode = inode_get(&sbd, tmp_bh);
- parse_rindex(tmp_inode, TRUE);
- brelse(tmp_bh);
- }
- else if (has_indirect_blocks() && !indirect_blocks &&
- !display_leaf(indirect))
- return -1;
- else if (display_indirect(indirect, indirect_blocks, 0, 0) == 0)
- return -1;
- else if (block_is_rglist()) {
- if (gfs1)
- tmp_bh = bread(&sbd,
- sbd1->sb_rindex_di.no_addr);
- else
- tmp_bh = bread(&sbd, masterblock("rindex"));
- tmp_inode = inode_get(&sbd, tmp_bh);
- parse_rindex(tmp_inode, FALSE);
- brelse(tmp_bh);
- }
- else if (block_is_jindex()) {
- tmp_bh = bread(&sbd, block);
- tmp_inode = inode_get(&sbd, tmp_bh);
- print_jindex(tmp_inode);
- brelse(tmp_bh);
- }
- else if (block_is_inum_file()) {
- tmp_bh = bread(&sbd, block);
- tmp_inode = inode_get(&sbd, tmp_bh);
- print_inum(tmp_inode);
- brelse(tmp_bh);
- }
- else if (block_is_statfs_file()) {
- tmp_bh = bread(&sbd, block);
- tmp_inode = inode_get(&sbd, tmp_bh);
- print_statfs(tmp_inode);
- brelse(tmp_bh);
- }
- else if (block_is_quota_file()) {
- tmp_bh = bread(&sbd, block);
- tmp_inode = inode_get(&sbd, tmp_bh);
- print_quota(tmp_inode);
- brelse(tmp_bh);
- }
- return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-/* read_superblock - read the superblock */
-/* ------------------------------------------------------------------------ */
-static void read_superblock(int fd)
-{
- int count;
-
- sbd1 = (struct gfs_sb *)&sbd.sd_sb;
- ioctl(fd, BLKFLSBUF, 0);
- memset(&sbd, 0, sizeof(struct gfs2_sbd));
- sbd.bsize = GFS2_DEFAULT_BSIZE;
- sbd.device_fd = fd;
- bh = bread(&sbd, 0x10);
- sbd.jsize = GFS2_DEFAULT_JSIZE;
- sbd.rgsize = GFS2_DEFAULT_RGSIZE;
- sbd.utsize = GFS2_DEFAULT_UTSIZE;
- sbd.qcsize = GFS2_DEFAULT_QCSIZE;
- sbd.time = time(NULL);
- osi_list_init(&sbd.rglist);
- gfs2_sb_in(&sbd.sd_sb, bh); /* parse it out into the sb structure */
- /* Check to see if this is really gfs1 */
- if (sbd1->sb_fs_format == GFS_FORMAT_FS &&
- sbd1->sb_header.mh_type == GFS_METATYPE_SB &&
- sbd1->sb_header.mh_format == GFS_FORMAT_SB &&
- sbd1->sb_multihost_format == GFS_FORMAT_MULTI) {
- struct gfs_sb *sbbuf = (struct gfs_sb *)bh->b_data;
-
- gfs1 = TRUE;
- sbd1->sb_flags = be32_to_cpu(sbbuf->sb_flags);
- sbd1->sb_seg_size = be32_to_cpu(sbbuf->sb_seg_size);
- gfs2_inum_in(&sbd1->sb_rindex_di, (void *)&sbbuf->sb_rindex_di);
- gfs2_inum_in(&gfs1_quota_di, (void *)&sbbuf->sb_quota_di);
- gfs2_inum_in(&gfs1_license_di, (void *)&sbbuf->sb_license_di);
- }
- else
- gfs1 = FALSE;
- sbd.bsize = sbd.sd_sb.sb_bsize;
- if (!sbd.bsize)
- sbd.bsize = GFS2_DEFAULT_BSIZE;
- if (compute_constants(&sbd)) {
- fprintf(stderr, "Bad constants (1)\n");
- exit(-1);
- }
- block = 0x10 * (GFS2_DEFAULT_BSIZE / sbd.bsize);
- device_geometry(&sbd);
- if (fix_device_geometry(&sbd)) {
- fprintf(stderr, "Device is too small (%"PRIu64" bytes)\n",
- sbd.device.length << GFS2_BASIC_BLOCK_SHIFT);
- exit(-1);
- }
- if(gfs1) {
- sbd.sd_inptrs = (sbd.bsize - sizeof(struct gfs_indirect)) /
- sizeof(uint64_t);
- sbd.sd_diptrs = (sbd.bsize - sizeof(struct gfs_dinode)) /
- sizeof(uint64_t);
- sbd.md.riinode = inode_read(&sbd, sbd1->sb_rindex_di.no_addr);
- sbd.fssize = sbd.device.length;
- gfs1_rindex_read(&sbd, 0, &count);
- } else {
- int sane;
-
- sbd.sd_inptrs = (sbd.bsize - sizeof(struct gfs2_meta_header)) /
- sizeof(uint64_t);
- sbd.sd_diptrs = (sbd.bsize - sizeof(struct gfs2_dinode)) /
- sizeof(uint64_t);
- sbd.master_dir = inode_read(&sbd,
- sbd.sd_sb.sb_master_dir.no_addr);
- gfs2_lookupi(sbd.master_dir, "rindex", 6, &sbd.md.riinode);
- sbd.fssize = sbd.device.length;
- rindex_read(&sbd, 0, &count, &sane);
- }
-
-}
-
-/* ------------------------------------------------------------------------ */
-/* read_master_dir - read the master directory */
-/* ------------------------------------------------------------------------ */
-static void read_master_dir(void)
-{
- ioctl(sbd.device_fd, BLKFLSBUF, 0);
- lseek(sbd.device_fd, sbd.sd_sb.sb_master_dir.no_addr * sbd.bsize,
- SEEK_SET);
- if (read(sbd.device_fd, bh->b_data, sbd.bsize) != sbd.bsize) {
- fprintf(stderr, "read error: %s from %s:%d: "
- "master dir block %lld (0x%llx)\n",
- strerror(errno), __FUNCTION__,
- __LINE__,
- (unsigned long long)sbd.sd_sb.sb_master_dir.no_addr,
- (unsigned long long)sbd.sd_sb.sb_master_dir.no_addr);
- exit(-1);
- }
- gfs2_dinode_in(&di, bh); /* parse disk inode into structure */
- do_dinode_extended(&di, bh); /* get extended data, if any */
- memcpy(&masterdir, &indirect[0], sizeof(struct indirect_info));
-}
-
-/* ------------------------------------------------------------------------ */
-/* display */
-/* ------------------------------------------------------------------------ */
-int display(int identify_only)
-{
- uint64_t blk;
-
- if (block == RGLIST_DUMMY_BLOCK) {
- if (gfs1)
- blk = sbd1->sb_rindex_di.no_addr;
- else
- blk = masterblock("rindex");
- } else
- blk = block;
- if (termlines) {
- display_title_lines();
- move(2,0);
- }
- if (block_in_mem != blk) { /* If we changed blocks from the last read */
- dev_offset = blk * sbd.bsize;
- ioctl(sbd.device_fd, BLKFLSBUF, 0);
- if (!(bh = bread(&sbd, blk))) {
- fprintf(stderr, "read error: %s from %s:%d: "
- "offset %lld (0x%llx)\n",
- strerror(errno), __FUNCTION__, __LINE__,
- (unsigned long long)dev_offset,
- (unsigned long long)dev_offset);
- exit(-1);
- }
- block_in_mem = blk; /* remember which block is in memory */
- }
- line = 1;
- gfs2_struct_type = display_block_type(FALSE);
- if (identify_only)
- return 0;
- indirect_blocks = 0;
- lines_per_row[dmode] = 1;
- if (gfs2_struct_type == GFS2_METATYPE_SB || blk == 0x10 * (4096 / sbd.bsize)) {
- gfs2_sb_in(&sbd.sd_sb, bh); /* parse it out into the sb structure */
- memset(indirect, 0, sizeof(indirect));
- indirect->ii[0].block = sbd.sd_sb.sb_master_dir.no_addr;
- indirect->ii[0].is_dir = TRUE;
- indirect->ii[0].dirents = 2;
-
- memcpy(&indirect->ii[0].dirent[0].filename, "root", 4);
- indirect->ii[0].dirent[0].dirent.de_inum.no_formal_ino =
- sbd.sd_sb.sb_root_dir.no_formal_ino;
- indirect->ii[0].dirent[0].dirent.de_inum.no_addr =
- sbd.sd_sb.sb_root_dir.no_addr;
- indirect->ii[0].dirent[0].block = sbd.sd_sb.sb_root_dir.no_addr;
- indirect->ii[0].dirent[0].dirent.de_type = DT_DIR;
-
- memcpy(&indirect->ii[0].dirent[1].filename, "master", 7);
- indirect->ii[0].dirent[1].dirent.de_inum.no_formal_ino =
- sbd.sd_sb.sb_master_dir.no_formal_ino;
- indirect->ii[0].dirent[1].dirent.de_inum.no_addr =
- sbd.sd_sb.sb_master_dir.no_addr;
- indirect->ii[0].dirent[1].block = sbd.sd_sb.sb_master_dir.no_addr;
- indirect->ii[0].dirent[1].dirent.de_type = DT_DIR;
- }
- else if (gfs2_struct_type == GFS2_METATYPE_DI) {
- gfs2_dinode_in(&di, bh); /* parse disk inode into structure */
- do_dinode_extended(&di, bh); /* get extended data, if any */
- }
- else if (gfs2_struct_type == GFS2_METATYPE_IN) { /* indirect block list */
- int i, hgt = get_height();
-
- if (blockhist) {
- for (i = 0; i < 512; i++)
- memcpy(&indirect->ii[i].mp,
- &blockstack[blockhist - 1].mp,
- sizeof(struct metapath));
- }
- indirect_blocks = do_indirect_extended(bh->b_data, indirect,
- hgt);
- }
- else if (gfs2_struct_type == GFS2_METATYPE_LF) { /* directory leaf */
- do_leaf_extended(bh->b_data, indirect);
- }
- last_entry_onscreen[dmode] = 0;
- if (dmode == EXTENDED_MODE && !block_has_extended_info())
- dmode = HEX_MODE;
- if (termlines) {
- move(termlines, 63);
- if (dmode==HEX_MODE)
- printw("Mode: Hex %s", (editing?"edit ":"view "));
- else
- printw("Mode: %s", (dmode==GFS2_MODE?"Structure":
- "Pointers "));
- move(line, 0);
- }
- if (dmode == HEX_MODE) /* if hex display mode */
- hexdump(dev_offset, (gfs2_struct_type == GFS2_METATYPE_DI)?
- struct_len + di.di_size:sbd.bsize);
- else if (dmode == GFS2_MODE) /* if structure display */
- display_gfs2(); /* display the gfs2 structure */
- else
- display_extended(); /* display extended blocks */
- /* No else here because display_extended can switch back to hex mode */
- if (termlines)
- refresh();
- return(0);
-}
-
-/* ------------------------------------------------------------------------ */
-/* push_block - push a block onto the block stack */
-/* ------------------------------------------------------------------------ */
-static void push_block(uint64_t blk)
-{
- int i, bhst;
-
- bhst = blockhist % BLOCK_STACK_SIZE;
- if (blk) {
- blockstack[bhst].dmode = dmode;
- for (i = 0; i < DMODES; i++) {
- blockstack[bhst].start_row[i] = start_row[i];
- blockstack[bhst].end_row[i] = end_row[i];
- blockstack[bhst].edit_row[i] = edit_row[i];
- blockstack[bhst].edit_col[i] = edit_col[i];
- blockstack[bhst].lines_per_row[i] = lines_per_row[i];
- }
- blockstack[bhst].gfs2_struct_type = gfs2_struct_type;
- if (edit_row[dmode] >= 0)
- memcpy(&blockstack[bhst].mp,
- &indirect->ii[edit_row[dmode]].mp,
- sizeof(struct metapath));
- blockhist++;
- blockstack[blockhist % BLOCK_STACK_SIZE].block = blk;
- }
-}
-
-/* ------------------------------------------------------------------------ */
-/* pop_block - pop a block off the block stack */
-/* ------------------------------------------------------------------------ */
-static uint64_t pop_block(void)
-{
- int i, bhst;
-
- if (!blockhist)
- return block;
- blockhist--;
- bhst = blockhist % BLOCK_STACK_SIZE;
- dmode = blockstack[bhst].dmode;
- for (i = 0; i < DMODES; i++) {
- start_row[i] = blockstack[bhst].start_row[i];
- end_row[i] = blockstack[bhst].end_row[i];
- edit_row[i] = blockstack[bhst].edit_row[i];
- edit_col[i] = blockstack[bhst].edit_col[i];
- lines_per_row[i] = blockstack[bhst].lines_per_row[i];
- }
- gfs2_struct_type = blockstack[bhst].gfs2_struct_type;
- return blockstack[bhst].block;
-}
-
-/* ------------------------------------------------------------------------ */
-/* find_journal_block - figure out where a journal starts, given the name */
-/* Returns: journal block number, changes j_size to the journal size */
-/* ------------------------------------------------------------------------ */
-static uint64_t find_journal_block(const char *journal, uint64_t *j_size)
-{
- int journal_num;
- uint64_t jindex_block, jblock = 0;
- int amtread;
- struct gfs2_buffer_head *jindex_bh, *j_bh;
- char jbuf[sbd.bsize];
- struct gfs2_inode *j_inode = NULL;
-
- journal_num = atoi(journal + 7);
- /* Figure out the block of the jindex file */
- if (gfs1)
- jindex_block = sbd1->sb_jindex_di.no_addr;
- else
- jindex_block = masterblock("jindex");
- /* read in the block */
- jindex_bh = bread(&sbd, jindex_block);
- /* get the dinode data from it. */
- gfs2_dinode_in(&di, jindex_bh); /* parse disk inode to struct*/
-
- if (!gfs1)
- do_dinode_extended(&di, jindex_bh); /* parse dir. */
- brelse(jindex_bh);
-
- if (gfs1) {
- struct gfs2_inode *jiinode;
- struct gfs_jindex ji;
-
- jiinode = inode_get(&sbd, jindex_bh);
- amtread = gfs2_readi(jiinode, (void *)&jbuf,
- journal_num * sizeof(struct gfs_jindex),
- sizeof(struct gfs_jindex));
- if (amtread) {
- gfs_jindex_in(&ji, jbuf);
- jblock = ji.ji_addr;
- *j_size = ji.ji_nsegment * 0x10;
- }
- } else {
- struct gfs2_dinode jdi;
-
- jblock = indirect->ii[0].dirent[journal_num + 2].block;
- j_bh = bread(&sbd, jblock);
- j_inode = inode_get(&sbd, j_bh);
- gfs2_dinode_in(&jdi, j_bh);/* parse dinode to struct */
- *j_size = jdi.di_size;
- brelse(j_bh);
- }
- return jblock;
-}
-
-/* ------------------------------------------------------------------------ */
-/* Find next metadata block of a given type AFTER a given point in the fs */
-/* */
-/* This is used to find blocks that aren't represented in the bitmaps, such */
-/* as the RGs and bitmaps or the superblock. */
-/* ------------------------------------------------------------------------ */
-static uint64_t find_metablockoftype_slow(uint64_t startblk, int metatype, int print)
-{
- uint64_t blk, last_fs_block;
- int found = 0;
- struct gfs2_buffer_head *lbh;
-
- last_fs_block = lseek(sbd.device_fd, 0, SEEK_END) / sbd.bsize;
- for (blk = startblk + 1; blk < last_fs_block; blk++) {
- lbh = bread(&sbd, blk);
- /* Can't use get_block_type here (returns false "none") */
- if (lbh->b_data[0] == 0x01 && lbh->b_data[1] == 0x16 &&
- lbh->b_data[2] == 0x19 && lbh->b_data[3] == 0x70 &&
- lbh->b_data[4] == 0x00 && lbh->b_data[5] == 0x00 &&
- lbh->b_data[6] == 0x00 && lbh->b_data[7] == metatype) {
- found = 1;
- brelse(lbh);
- break;
- }
- brelse(lbh);
- }
- if (!found)
- blk = 0;
- if (print) {
- if (dmode == HEX_MODE)
- printf("0x%llx\n", (unsigned long long)blk);
- else
- printf("%llu\n", (unsigned long long)blk);
- }
- gfs2_rgrp_free(&sbd.rglist);
- if (print)
- exit(0);
- return blk;
-}
-
-/* ------------------------------------------------------------------------ */
-/* Find next "metadata in use" block AFTER a given point in the fs */
-/* */
-/* This version does its magic by searching the bitmaps of the RG. After */
-/* all, if we're searching for a dinode, we want a real allocated inode, */
-/* not just some block that used to be an inode in a previous incarnation. */
-/* ------------------------------------------------------------------------ */
-static uint64_t find_metablockoftype_rg(uint64_t startblk, int metatype, int print)
-{
- uint64_t blk;
- int first = 1, found = 0;
- struct rgrp_list *rgd;
- struct gfs2_rindex *ri;
- osi_list_t *tmp;
-
- blk = 0;
- /* Skip the rgs prior to the block we've been given */
- for(tmp = sbd.rglist.next; tmp != &sbd.rglist; tmp = tmp->next){
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- ri = &rgd->ri;
- if (first && startblk <= ri->ri_data0) {
- startblk = ri->ri_data0;
- break;
- } else if (ri->ri_addr <= startblk &&
- startblk < ri->ri_data0 + ri->ri_data)
- break;
- else
- rgd = NULL;
- first = 0;
- }
- if (!rgd) {
- if (print)
- printf("0\n");
- gfs2_rgrp_free(&sbd.rglist);
- if (print)
- exit(-1);
- }
- for(; !found && tmp != &sbd.rglist; tmp = tmp->next){
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- first = 1;
- do {
- if (gfs2_next_rg_metatype(&sbd, rgd, &blk, metatype,
- first))
- break;
- if (blk > startblk) {
- found = 1;
- break;
- }
- first = 0;
- } while (blk <= startblk);
- }
- if (!found)
- blk = 0;
- if (print) {
- if (dmode == HEX_MODE)
- printf("0x%llx\n", (unsigned long long)blk);
- else
- printf("%llu\n", (unsigned long long)blk);
- }
- gfs2_rgrp_free(&sbd.rglist);
- if (print)
- exit(0);
- return blk;
-}
-
-/* ------------------------------------------------------------------------ */
-/* Find next metadata block AFTER a given point in the fs */
-/* ------------------------------------------------------------------------ */
-static uint64_t find_metablockoftype(const char *strtype, int print)
-{
- int mtype = 0;
- uint64_t startblk, blk = 0;
-
- if (print)
- startblk = blockstack[blockhist % BLOCK_STACK_SIZE].block;
- else
- startblk = block;
-
- for (mtype = GFS2_METATYPE_NONE;
- mtype <= GFS2_METATYPE_QC; mtype++)
- if (!strcasecmp(strtype, mtypes[mtype]))
- break;
- if (!strcmp(strtype, "dinode"))
- mtype = GFS2_METATYPE_DI;
- if (mtype >= GFS2_METATYPE_NONE && mtype <= GFS2_METATYPE_RB)
- blk = find_metablockoftype_slow(startblk, mtype, print);
- else if (mtype >= GFS2_METATYPE_DI && mtype <= GFS2_METATYPE_QC)
- blk = find_metablockoftype_rg(startblk, mtype, print);
- else if (print) {
- fprintf(stderr, "Error: metadata type not "
- "specified: must be one of:\n");
- fprintf(stderr, "sb rg rb di in lf jd lh ld"
- " ea ed lb 13 qc\n");
- gfs2_rgrp_free(&sbd.rglist);
- exit(-1);
- }
- return blk;
-}
-
-/* ------------------------------------------------------------------------ */
-/* Check if the word is a keyword such as "sb" or "rindex" */
-/* Returns: block number if it is, else 0 */
-/* ------------------------------------------------------------------------ */
-uint64_t check_keywords(const char *kword)
-{
- uint64_t blk = 0;
-
- if (!strcmp(kword, "sb") ||!strcmp(kword, "superblock"))
- blk = 0x10 * (4096 / sbd.bsize); /* superblock */
- else if (!strcmp(kword, "root") || !strcmp(kword, "rootdir"))
- blk = sbd.sd_sb.sb_root_dir.no_addr;
- else if (!strcmp(kword, "master")) {
- if (!gfs1)
- blk = sbd.sd_sb.sb_master_dir.no_addr;
- else
- fprintf(stderr, "This is GFS1; there's no master directory.\n");
- }
- else if (!strcmp(kword, "jindex")) {
- if (gfs1)
- blk = sbd1->sb_jindex_di.no_addr;
- else
- blk = masterblock("jindex"); /* journal index */
- }
- else if (!gfs1 && !strcmp(kword, "per_node"))
- blk = masterblock("per_node");
- else if (!gfs1 && !strcmp(kword, "inum"))
- blk = masterblock("inum");
- else if (!strcmp(kword, "statfs")) {
- if (gfs1)
- blk = gfs1_license_di.no_addr;
- else
- blk = masterblock("statfs");
- }
- else if (!strcmp(kword, "rindex") || !strcmp(kword, "rgindex")) {
- if (gfs1)
- blk = sbd1->sb_rindex_di.no_addr;
- else
- blk = masterblock("rindex");
- } else if (!strcmp(kword, "rgs")) {
- blk = RGLIST_DUMMY_BLOCK;
- } else if (!strcmp(kword, "quota")) {
- if (gfs1)
- blk = gfs1_quota_di.no_addr;
- else
- blk = masterblock("quota");
- } else if (!strncmp(kword, "rg ", 3)) {
- int rgnum = 0;
-
- rgnum = atoi(kword + 3);
- blk = get_rg_addr(rgnum);
- } else if (!strncmp(kword, "journal", 7) && isdigit(kword[7])) {
- uint64_t j_size;
-
- blk = find_journal_block(kword, &j_size);
- } else if (kword[0]=='/') /* search */
- blk = find_metablockoftype(&kword[1], 0);
- else if (kword[0]=='0' && kword[1]=='x') /* hex addr */
- sscanf(kword, "%"SCNx64, &blk);/* retrieve in hex */
- else
- sscanf(kword, "%" PRIu64, &blk); /* retrieve decimal */
-
- return blk;
-}
-
-/* ------------------------------------------------------------------------ */
-/* goto_block - go to a desired block entered by the user */
-/* ------------------------------------------------------------------------ */
-static uint64_t goto_block(void)
-{
- char string[256];
- int ch;
-
- memset(string, 0, sizeof(string));
- sprintf(string,"%"PRId64, block);
- if (bobgets(string, 1, 7, 16, &ch)) {
- if (isalnum(string[0]) || string[0] == '/')
- temp_blk = check_keywords(string);
- else if (string[0] == '+') {
- if (string[1] == '0' && string[2] == 'x')
- sscanf(string, "%"SCNx64, &temp_blk);
- else
- sscanf(string, "%" PRIu64, &temp_blk);
- temp_blk += block;
- }
- else if (string[0] == '-') {
- if (string[1] == '0' && string[2] == 'x')
- sscanf(string, "%"SCNx64, &temp_blk);
- else
- sscanf(string, "%" PRIu64, &temp_blk);
- temp_blk -= block;
- }
-
- if (temp_blk == RGLIST_DUMMY_BLOCK || temp_blk < max_block) {
- offset = 0;
- block = temp_blk;
- push_block(block);
- }
- }
- return block;
-}
-
-/* ------------------------------------------------------------------------ */
-/* init_colors */
-/* ------------------------------------------------------------------------ */
-static void init_colors(void)
-{
-
- if (color_scheme) {
- init_pair(COLOR_TITLE, COLOR_BLACK, COLOR_CYAN);
- init_pair(COLOR_NORMAL, COLOR_WHITE, COLOR_BLACK);
- init_pair(COLOR_INVERSE, COLOR_BLACK, COLOR_WHITE);
- init_pair(COLOR_SPECIAL, COLOR_RED, COLOR_BLACK);
- init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_BLACK);
- init_pair(COLOR_OFFSETS, COLOR_CYAN, COLOR_BLACK);
- init_pair(COLOR_CONTENTS, COLOR_YELLOW, COLOR_BLACK);
- }
- else {
- init_pair(COLOR_TITLE, COLOR_BLACK, COLOR_CYAN);
- init_pair(COLOR_NORMAL, COLOR_BLACK, COLOR_WHITE);
- init_pair(COLOR_INVERSE, COLOR_WHITE, COLOR_BLACK);
- init_pair(COLOR_SPECIAL, COLOR_MAGENTA, COLOR_WHITE);
- init_pair(COLOR_HIGHLIGHT, COLOR_RED, COLOR_WHITE); /*cursor*/
- init_pair(COLOR_OFFSETS, COLOR_CYAN, COLOR_WHITE);
- init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE);
- }
-}
-
-/* ------------------------------------------------------------------------ */
-/* hex_edit - Allow the user to edit the page by entering hex digits */
-/* ------------------------------------------------------------------------ */
-static void hex_edit(int *exitch)
-{
- int left_off;
- int ch;
-
- left_off = ((block * sbd.bsize) < 0xffffffff) ? 9 : 17;
- /* 8 and 16 char addresses on screen */
-
- if (bobgets(estring, edit_row[dmode] + 3,
- (edit_col[dmode] * 2) + (edit_col[dmode] / 4) + left_off,
- 2, exitch)) {
- if (strstr(edit_fmt,"X") || strstr(edit_fmt,"x")) {
- int hexoffset;
- int i, sl = strlen(estring);
-
- for (i = 0; i < sl; i+=2) {
- hexoffset = (edit_row[dmode] * 16) +
- edit_col[dmode] + (i / 2);
- ch = 0x00;
- if (isdigit(estring[i]))
- ch = (estring[i] - '0') * 0x10;
- else if (estring[i] >= 'a' &&
- estring[i] <= 'f')
- ch = (estring[i]-'a' + 0x0a)*0x10;
- else if (estring[i] >= 'A' &&
- estring[i] <= 'F')
- ch = (estring[i] - 'A' + 0x0a) * 0x10;
- if (isdigit(estring[i+1]))
- ch += (estring[i+1] - '0');
- else if (estring[i+1] >= 'a' &&
- estring[i+1] <= 'f')
- ch += (estring[i+1] - 'a' + 0x0a);
- else if (estring[i+1] >= 'A' &&
- estring[i+1] <= 'F')
- ch += (estring[i+1] - 'A' + 0x0a);
- bh->b_data[offset + hexoffset] = ch;
- }
- lseek(sbd.device_fd, dev_offset, SEEK_SET);
- if (write(sbd.device_fd, bh->b_data, sbd.bsize) !=
- sbd.bsize) {
- fprintf(stderr, "write error: %s from %s:%d: "
- "offset %lld (0x%llx)\n",
- strerror(errno),
- __FUNCTION__, __LINE__,
- (unsigned long long)dev_offset,
- (unsigned long long)dev_offset);
- exit(-1);
- }
- fsync(sbd.device_fd);
- }
- }
-}
-
-/* ------------------------------------------------------------------------ */
-/* page up */
-/* ------------------------------------------------------------------------ */
-static void pageup(void)
-{
- if (dmode == EXTENDED_MODE) {
- if (edit_row[dmode] - (dsplines / lines_per_row[dmode]) > 0)
- edit_row[dmode] -= (dsplines / lines_per_row[dmode]);
- else
- edit_row[dmode] = 0;
- if (start_row[dmode] - (dsplines / lines_per_row[dmode]) > 0)
- start_row[dmode] -= (dsplines / lines_per_row[dmode]);
- else
- start_row[dmode] = 0;
- }
- else {
- start_row[dmode] = edit_row[dmode] = 0;
- if (dmode == GFS2_MODE || offset==0) {
- block--;
- if (dmode == HEX_MODE)
- offset = (sbd.bsize % screen_chunk_size) > 0 ?
- screen_chunk_size *
- (sbd.bsize / screen_chunk_size) :
- sbd.bsize - screen_chunk_size;
- else
- offset = 0;
- }
- else
- offset -= screen_chunk_size;
- }
-}
-
-/* ------------------------------------------------------------------------ */
-/* page down */
-/* ------------------------------------------------------------------------ */
-static void pagedn(void)
-{
- if (dmode == EXTENDED_MODE) {
- if ((edit_row[dmode] + dsplines) / lines_per_row[dmode] + 1 <=
- end_row[dmode]) {
- start_row[dmode] += dsplines / lines_per_row[dmode];
- edit_row[dmode] += dsplines / lines_per_row[dmode];
- } else {
- edit_row[dmode] = end_row[dmode] - 1;
- while (edit_row[dmode] - start_row[dmode]
- + 1 > last_entry_onscreen[dmode])
- start_row[dmode]++;
- }
- }
- else {
- start_row[dmode] = edit_row[dmode] = 0;
- if (dmode == GFS2_MODE ||
- offset + screen_chunk_size >= sbd.bsize) {
- block++;
- offset = 0;
- }
- else
- offset += screen_chunk_size;
- }
-}
-
-/* ------------------------------------------------------------------------ */
-/* jump - jump to the address the cursor is on */
-/* ------------------------------------------------------------------------ */
-static void jump(void)
-{
- if (dmode == HEX_MODE) {
- unsigned int col2;
- uint64_t *b;
-
- if (edit_row[dmode] >= 0) {
- col2 = edit_col[dmode] & 0x08;/* thus 0-7->0, 8-15->8 */
- b = (uint64_t *)&bh->b_data[edit_row[dmode]*16 +
- offset + col2];
- temp_blk=be64_to_cpu(*b);
- }
- }
- else
- sscanf(estring, "%"SCNx64, &temp_blk);/* retrieve in hex */
- if (temp_blk < max_block) { /* if the block number is valid */
- int i;
-
- offset = 0;
- block = temp_blk;
- push_block(block);
- for (i = 0; i < DMODES; i++) {
- start_row[i] = end_row[i] = edit_row[i] = 0;
- edit_col[i] = 0;
- }
- }
-}
-
-/* ------------------------------------------------------------------------ */
-/* print block type */
-/* ------------------------------------------------------------------------ */
-static void print_block_type(uint64_t tblock, int type, const char *additional)
-{
- if (type <= GFS2_METATYPE_QC)
- printf("%d (Block %lld is type %d: %s%s)\n", type,
- (unsigned long long)tblock, type, block_type_str[type],
- additional);
- else
- printf("%d (Block %lld is type %d: unknown%s)\n", type,
- (unsigned long long)tblock, type, additional);
-}
-
-/* ------------------------------------------------------------------------ */
-/* find_print block type */
-/* ------------------------------------------------------------------------ */
-static void find_print_block_type(void)
-{
- uint64_t tblock;
- struct gfs2_buffer_head *lbh;
- int type;
-
- tblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
- lbh = bread(&sbd, tblock);
- type = get_block_type(lbh);
- print_block_type(tblock, type, "");
- brelse(lbh);
- gfs2_rgrp_free(&sbd.rglist);
- exit(0);
-}
-
-/* ------------------------------------------------------------------------ */
-/* Find and print the resource group associated with a given block */
-/* ------------------------------------------------------------------------ */
-static void find_print_block_rg(int bitmap)
-{
- uint64_t rblock, rgblock;
- int i;
- struct rgrp_list *rgd;
-
- rblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
- if (rblock == sbd.sb_addr)
- printf("0 (the superblock is not in the bitmap)\n");
- else {
- rgd = gfs2_blk2rgrpd(&sbd, rblock);
- if (rgd) {
- rgblock = rgd->ri.ri_addr;
- if (bitmap) {
- struct gfs2_bitmap *bits = NULL;
-
- for (i = 0; i < rgd->ri.ri_length; i++) {
- bits = &(rgd->bits[i]);
- if (rblock - rgd->ri.ri_data0 <
- ((bits->bi_start + bits->bi_len) *
- GFS2_NBBY)) {
- break;
- }
- }
- if (i < rgd->ri.ri_length)
- rgblock += i;
-
- }
- if (dmode == HEX_MODE)
- printf("0x%llx\n",(unsigned long long)rgblock);
- else
- printf("%llu\n", (unsigned long long)rgblock);
- } else {
- printf("-1 (block invalid or part of an rgrp).\n");
- }
- }
- gfs2_rgrp_free(&sbd.rglist);
- exit(0);
-}
-
-/* ------------------------------------------------------------------------ */
-/* find/change/print block allocation (what the bitmap says about block) */
-/* ------------------------------------------------------------------------ */
-static void find_change_block_alloc(int *newval)
-{
- uint64_t ablock;
- int type;
- struct rgrp_list *rgd;
-
- if (newval &&
- (*newval < GFS2_BLKST_FREE || *newval > GFS2_BLKST_DINODE)) {
- int i;
-
- printf("Error: value %d is not valid.\nValid values are:\n",
- *newval);
- for (i = GFS2_BLKST_FREE; i <= GFS2_BLKST_DINODE; i++)
- printf("%d - %s\n", i, allocdesc[gfs1][i]);
- gfs2_rgrp_free(&sbd.rglist);
- exit(-1);
- }
- ablock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
- if (ablock == sbd.sb_addr)
- printf("3 (the superblock is not in the bitmap)\n");
- else {
- if (newval) {
- if (gfs2_set_bitmap(&sbd, ablock, *newval))
- printf("-1 (block invalid or part of an rgrp).\n");
- else
- printf("%d\n", *newval);
- } else {
- rgd = gfs2_blk2rgrpd(&sbd, ablock);
- if (rgd) {
- gfs2_rgrp_read(&sbd, rgd);
- type = gfs2_get_bitmap(&sbd, ablock, rgd);
- gfs2_rgrp_relse(rgd);
- printf("%d (%s)\n", type, allocdesc[gfs1][type]);
- } else {
- gfs2_rgrp_free(&sbd.rglist);
- printf("-1 (block invalid or part of an rgrp).\n");
- exit(-1);
- }
- }
- }
- gfs2_rgrp_free(&sbd.rglist);
- if (newval)
- fsync(sbd.device_fd);
- exit(0);
-}
-
-/* ------------------------------------------------------------------------ */
-/* process request to print a certain field from a previously pushed block */
-/* ------------------------------------------------------------------------ */
-static void process_field(const char *field, uint64_t *newval, int print_field)
-{
- uint64_t fblock;
- struct gfs2_buffer_head *rbh;
- int type;
- struct gfs2_rgrp rg;
-
- fblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
- rbh = bread(&sbd, fblock);
- type = get_block_type(rbh);
- switch (type) {
- case GFS2_METATYPE_SB:
- if (print_field)
- print_block_type(fblock, type,
- " which is not implemented");
- break;
- case GFS2_METATYPE_RG:
- gfs2_rgrp_in(&rg, rbh);
- if (newval) {
- gfs2_rgrp_assignval(&rg, field, *newval);
- gfs2_rgrp_out(&rg, rbh);
- if (print_field)
- gfs2_rgrp_printval(&rg, field);
- } else {
- if (print_field && gfs2_rgrp_printval(&rg, field))
- printf("Field '%s' not found.\n", field);
- }
- break;
- case GFS2_METATYPE_RB:
- if (print_field)
- print_block_type(fblock, type,
- " which is not implemented");
- break;
- case GFS2_METATYPE_DI:
- gfs2_dinode_in(&di, rbh);
- if (newval) {
- gfs2_dinode_assignval(&di, field, *newval);
- gfs2_dinode_out(&di, rbh);
- if (print_field)
- gfs2_dinode_printval(&di, field);
- } else {
- if (print_field && gfs2_dinode_printval(&di, field))
- printf("Field '%s' not found.\n", field);
- }
- break;
- case GFS2_METATYPE_IN:
- case GFS2_METATYPE_LF:
- case GFS2_METATYPE_JD:
- case GFS2_METATYPE_LH:
- case GFS2_METATYPE_LD:
- case GFS2_METATYPE_EA:
- case GFS2_METATYPE_ED:
- case GFS2_METATYPE_LB:
- case GFS2_METATYPE_QC:
- default:
- if (print_field)
- print_block_type(fblock, type,
- " which is not implemented");
- break;
- }
- brelse(rbh);
- fsync(sbd.device_fd);
-}
-
-/* ------------------------------------------------------------------------ */
-/* interactive_mode - accept keystrokes from user and display structures */
-/* ------------------------------------------------------------------------ */
-static void interactive_mode(void)
-{
- int ch, Quit;
-
- if ((wind = initscr()) == NULL) {
- fprintf(stderr, "Error: unable to initialize screen.");
- eol(0);
- exit(-1);
- }
-
- /* Do our initial screen stuff: */
- signal(SIGWINCH, UpdateSize); /* handle the terminal resize signal */
- UpdateSize(0); /* update screen size based on terminal settings */
- clear(); /* don't use Erase */
- start_color();
- noecho();
- keypad(stdscr, TRUE);
- raw();
- curs_set(0);
- init_colors();
- /* Accept keystrokes and act on them accordingly */
- Quit = FALSE;
- editing = FALSE;
- while (!Quit) {
- display(FALSE);
- if (editing) {
- if (edit_row[dmode] == -1)
- block = goto_block();
- else {
- if (dmode == HEX_MODE)
- hex_edit(&ch);
- else if (dmode == GFS2_MODE) {
- uint64_t val;
-
- bobgets(estring, edit_row[dmode]+4, 24,
- 10, &ch);
- if (estring[0] == '0' &&
- estring[1] == 'x')
- sscanf(estring, "%"SCNx64,
- &val);
- else
- val = (uint64_t)atoll(estring);
- process_field(efield, &val, 0);
- block_in_mem = -1;
- } else
- bobgets(estring, edit_row[dmode]+6, 14,
- edit_size[dmode], &ch);
- }
- }
- else
- while ((ch=getch()) == 0); // wait for input
-
- switch (ch)
- {
- /* --------------------------------------------------------- */
- /* escape or 'q' */
- /* --------------------------------------------------------- */
- case 0x1b:
- case 0x03:
- case 'q':
- if (editing)
- editing = FALSE;
- else
- Quit=TRUE;
- break;
- /* --------------------------------------------------------- */
- /* home - return to the superblock */
- /* --------------------------------------------------------- */
- case KEY_HOME:
- if (dmode == EXTENDED_MODE) {
- start_row[dmode] = end_row[dmode] = 0;
- edit_row[dmode] = 0;
- }
- else {
- block = 0x10 * (4096 / sbd.bsize);
- push_block(block);
- offset = 0;
- }
- break;
- /* --------------------------------------------------------- */
- /* backspace - return to the previous block on the stack */
- /* --------------------------------------------------------- */
- case KEY_BACKSPACE:
- case 0x7f:
- block = pop_block();
- offset = 0;
- break;
- /* --------------------------------------------------------- */
- /* space - go down the block stack (opposite of backspace) */
- /* --------------------------------------------------------- */
- case ' ':
- blockhist++;
- block = blockstack[blockhist % BLOCK_STACK_SIZE].block;
- offset = 0;
- break;
- /* --------------------------------------------------------- */
- /* arrow up */
- /* --------------------------------------------------------- */
- case KEY_UP:
- case '-':
- if (dmode == EXTENDED_MODE) {
- if (edit_row[dmode] > 0)
- edit_row[dmode]--;
- if (edit_row[dmode] < start_row[dmode])
- start_row[dmode] = edit_row[dmode];
- }
- else {
- if (edit_row[dmode] >= 0)
- edit_row[dmode]--;
- }
- break;
- /* --------------------------------------------------------- */
- /* arrow down */
- /* --------------------------------------------------------- */
- case KEY_DOWN:
- case '+':
- if (dmode == EXTENDED_MODE) {
- if (edit_row[dmode] + 1 < end_row[dmode]) {
- if (edit_row[dmode] - start_row[dmode]
- + 1 > last_entry_onscreen[dmode])
- start_row[dmode]++;
- edit_row[dmode]++;
- }
- }
- else {
- if (edit_row[dmode] < last_entry_onscreen[dmode])
- edit_row[dmode]++;
- }
- break;
- /* --------------------------------------------------------- */
- /* arrow left */
- /* --------------------------------------------------------- */
- case KEY_LEFT:
- if (dmode == HEX_MODE) {
- if (edit_col[dmode] > 0)
- edit_col[dmode]--;
- else
- edit_col[dmode] = 15;
- }
- break;
- /* --------------------------------------------------------- */
- /* arrow right */
- /* --------------------------------------------------------- */
- case KEY_RIGHT:
- if (dmode == HEX_MODE) {
- if (edit_col[dmode] < 15)
- edit_col[dmode]++;
- else
- edit_col[dmode] = 0;
- }
- break;
- /* --------------------------------------------------------- */
- /* m - change display mode key */
- /* --------------------------------------------------------- */
- case 'm':
- dmode = ((dmode + 1) % DMODES);
- break;
- /* --------------------------------------------------------- */
- /* J - Jump to highlighted block number */
- /* --------------------------------------------------------- */
- case 'j':
- jump();
- break;
- /* --------------------------------------------------------- */
- /* g - goto block */
- /* --------------------------------------------------------- */
- case 'g':
- block = goto_block();
- break;
- /* --------------------------------------------------------- */
- /* h - help key */
- /* --------------------------------------------------------- */
- case 'h':
- print_usage();
- break;
- /* --------------------------------------------------------- */
- /* e - change to extended mode */
- /* --------------------------------------------------------- */
- case 'e':
- dmode = EXTENDED_MODE;
- break;
- /* --------------------------------------------------------- */
- /* b - Back one 4K block */
- /* --------------------------------------------------------- */
- case 'b':
- start_row[dmode] = end_row[dmode] = edit_row[dmode] = 0;
- if (block > 0)
- block--;
- offset = 0;
- break;
- /* --------------------------------------------------------- */
- /* c - Change color scheme */
- /* --------------------------------------------------------- */
- case 'c':
- color_scheme = !color_scheme;
- init_colors();
- break;
- /* --------------------------------------------------------- */
- /* page up key */
- /* --------------------------------------------------------- */
- case 0x19: // ctrl-y for vt100
- case KEY_PPAGE: // PgUp
- case 0x15: // ctrl-u for vi compat.
- case 0x02: // ctrl-b for less compat.
- pageup();
- break;
- /* --------------------------------------------------------- */
- /* end - Jump to the end of the list */
- /* --------------------------------------------------------- */
- case 0x168:
- if (dmode == EXTENDED_MODE) {
- int ents_per_screen = dsplines /
- lines_per_row[dmode];
-
- edit_row[dmode] = end_row[dmode] - 1;
- if ((edit_row[dmode] - ents_per_screen)+1 > 0)
- start_row[dmode] = edit_row[dmode] -
- ents_per_screen + 1;
- else
- start_row[dmode] = 0;
- }
- /* TODO: Make end key work for other display modes. */
- break;
- /* --------------------------------------------------------- */
- /* f - Forward one 4K block */
- /* --------------------------------------------------------- */
- case 'f':
- start_row[dmode]=end_row[dmode]=edit_row[dmode] = 0;
- lines_per_row[dmode] = 1;
- block++;
- offset = 0;
- break;
- /* --------------------------------------------------------- */
- /* page down key */
- /* --------------------------------------------------------- */
- case 0x16: // ctrl-v for vt100
- case KEY_NPAGE: // PgDown
- case 0x04: // ctrl-d for vi compat.
- pagedn();
- break;
- /* --------------------------------------------------------- */
- /* enter key - change a value */
- /* --------------------------------------------------------- */
- case(KEY_ENTER):
- case('\n'):
- case('\r'):
- editing = !editing;
- break;
- default:
- move(termlines - 1, 0);
- printw("Keystroke not understood: 0x%03X",ch);
- refresh();
- usleep(50000);
- break;
- } /* switch */
- } /* while !Quit */
-
- Erase();
- refresh();
- endwin();
-}/* interactive_mode */
-
-/* ------------------------------------------------------------------------ */
-/* gfs_log_header_in - read in a gfs1-style log header */
-/* ------------------------------------------------------------------------ */
-void gfs_log_header_in(struct gfs_log_header *head,
- struct gfs2_buffer_head *lbh)
-{
- struct gfs_log_header *str = (struct gfs_log_header *)lbh->b_data;
-
- gfs2_meta_header_in(&head->lh_header, lbh);
-
- head->lh_flags = be32_to_cpu(str->lh_flags);
- head->lh_pad = be32_to_cpu(str->lh_pad);
-
- head->lh_first = be64_to_cpu(str->lh_first);
- head->lh_sequence = be64_to_cpu(str->lh_sequence);
-
- head->lh_tail = be64_to_cpu(str->lh_tail);
- head->lh_last_dump = be64_to_cpu(str->lh_last_dump);
-
- memcpy(head->lh_reserved, str->lh_reserved, 64);
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* gfs_log_header_print - print a gfs1-style log header */
-/* ------------------------------------------------------------------------ */
-void gfs_log_header_print(struct gfs_log_header *lh)
-{
- gfs2_meta_header_print(&lh->lh_header);
- pv(lh, lh_flags, "%u", "0x%.8X");
- pv(lh, lh_pad, "%u", "%x");
- pv((unsigned long long)lh, lh_first, "%llu", "%llx");
- pv((unsigned long long)lh, lh_sequence, "%llu", "%llx");
- pv((unsigned long long)lh, lh_tail, "%llu", "%llx");
- pv((unsigned long long)lh, lh_last_dump, "%llu", "%llx");
-}
-
-/* ------------------------------------------------------------------------ */
-/* print_ld_blocks - print all blocks given in a log descriptor */
-/* returns: the number of block numbers it printed */
-/* ------------------------------------------------------------------------ */
-static int print_ld_blocks(const uint64_t *b, const char *end, int start_line)
-{
- int bcount = 0, i = 0;
- static char str[256];
-
- while (*b && (char *)b < end) {
- if (!termlines ||
- (print_entry_ndx >= start_row[dmode] &&
- ((print_entry_ndx - start_row[dmode])+1) *
- lines_per_row[dmode] <= termlines - start_line - 2)) {
- if (i && i % 4 == 0) {
- eol(0);
- print_gfs2(" ");
- }
- i++;
- sprintf(str, "0x%llx",
- (unsigned long long)be64_to_cpu(*b));
- print_gfs2("%-18.18s ", str);
- bcount++;
- }
- b++;
- if (gfs1)
- b++;
- }
- eol(0);
- return bcount;
-}
-
-/* ------------------------------------------------------------------------ */
-/* fsck_readi - same as libgfs2's gfs2_readi, but sets absolute block # */
-/* of the first bit of data read. */
-/* ------------------------------------------------------------------------ */
-static int fsck_readi(struct gfs2_inode *ip, void *rbuf, uint64_t roffset,
- unsigned int size, uint64_t *abs_block)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_buffer_head *lbh;
- uint64_t lblock, dblock;
- unsigned int o;
- uint32_t extlen = 0;
- unsigned int amount;
- int not_new = 0;
- int isdir = !!(S_ISDIR(ip->i_di.di_mode));
- int copied = 0;
-
- *abs_block = 0;
- if (roffset >= ip->i_di.di_size)
- return 0;
- if ((roffset + size) > ip->i_di.di_size)
- size = ip->i_di.di_size - roffset;
- if (!size)
- return 0;
- if (isdir) {
- o = roffset % sdp->sd_jbsize;
- lblock = roffset / sdp->sd_jbsize;
- } else {
- lblock = roffset >> sdp->sd_sb.sb_bsize_shift;
- o = roffset & (sdp->bsize - 1);
- }
-
- if (!ip->i_di.di_height) /* inode_is_stuffed */
- o += sizeof(struct gfs2_dinode);
- else if (isdir)
- o += sizeof(struct gfs2_meta_header);
-
- while (copied < size) {
- amount = size - copied;
- if (amount > sdp->bsize - o)
- amount = sdp->bsize - o;
- if (!extlen)
- block_map(ip, lblock, ¬_new, &dblock, &extlen,
- FALSE);
- if (dblock) {
- lbh = bread(sdp, dblock);
- if (*abs_block == 0)
- *abs_block = lbh->b_blocknr;
- dblock++;
- extlen--;
- } else
- lbh = NULL;
- if (lbh) {
- memcpy(rbuf, lbh->b_data + o, amount);
- brelse(lbh);
- } else {
- memset(rbuf, 0, amount);
- }
- copied += amount;
- lblock++;
- o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
- }
- return copied;
-}
-
-static void check_journal_wrap(uint64_t seq, uint64_t *highest_seq)
-{
- if (seq < *highest_seq) {
- print_gfs2("------------------------------------------------"
- "------------------------------------------------");
- eol(0);
- print_gfs2("Journal wrapped here.");
- eol(0);
- print_gfs2("------------------------------------------------"
- "------------------------------------------------");
- eol(0);
- }
- *highest_seq = seq;
-}
-
-/* ------------------------------------------------------------------------ */
-/* dump_journal - dump a journal file's contents. */
-/* ------------------------------------------------------------------------ */
-static void dump_journal(const char *journal)
-{
- struct gfs2_buffer_head *j_bh = NULL, dummy_bh;
- uint64_t jblock, j_size, jb, abs_block;
- int error, start_line, journal_num;
- struct gfs2_inode *j_inode = NULL;
- int ld_blocks = 0;
- uint64_t highest_seq = 0;
- char *jbuf = NULL;
-
- start_line = line;
- lines_per_row[dmode] = 1;
- error = 0;
- journal_num = atoi(journal + 7);
- print_gfs2("Dumping journal #%d.", journal_num);
- eol(0);
- jblock = find_journal_block(journal, &j_size);
- if (!jblock)
- return;
- if (!gfs1) {
- j_bh = bread(&sbd, jblock);
- j_inode = inode_get(&sbd, j_bh);
- jbuf = malloc(sbd.bsize);
- }
-
- for (jb = 0; jb < j_size; jb += (gfs1 ? 1:sbd.bsize)) {
- if (gfs1) {
- if (j_bh)
- brelse(j_bh);
- j_bh = bread(&sbd, jblock + jb);
- abs_block = jblock + jb;
- dummy_bh.b_data = j_bh->b_data;
- } else {
- error = fsck_readi(j_inode, (void *)jbuf, jb,
- sbd.bsize, &abs_block);
- if (!error) /* end of file */
- break;
- dummy_bh.b_data = jbuf;
- }
- if (get_block_type(&dummy_bh) == GFS2_METATYPE_LD) {
- uint64_t *b;
- struct gfs2_log_descriptor ld;
- int ltndx;
- uint32_t logtypes[2][6] = {
- {GFS2_LOG_DESC_METADATA,
- GFS2_LOG_DESC_REVOKE,
- GFS2_LOG_DESC_JDATA,
- 0, 0, 0},
- {GFS_LOG_DESC_METADATA,
- GFS_LOG_DESC_IUL,
- GFS_LOG_DESC_IDA,
- GFS_LOG_DESC_Q,
- GFS_LOG_DESC_LAST,
- 0}};
- const char *logtypestr[2][6] = {
- {"Metadata", "Revoke", "Jdata",
- "Unknown", "Unknown", "Unknown"},
- {"Metadata", "Unlinked inode", "Dealloc inode",
- "Quota", "Final Entry", "Unknown"}};
-
- print_gfs2("0x%llx (j+%4llx): Log descriptor, ",
- abs_block, jb / (gfs1 ? 1 : sbd.bsize));
- gfs2_log_descriptor_in(&ld, &dummy_bh);
- print_gfs2("type %d ", ld.ld_type);
-
- for (ltndx = 0;; ltndx++) {
- if (ld.ld_type == logtypes[gfs1][ltndx] ||
- logtypes[gfs1][ltndx] == 0)
- break;
- }
- print_gfs2("(%s) ", logtypestr[gfs1][ltndx]);
- print_gfs2("len:%u, data1: %u",
- ld.ld_length, ld.ld_data1);
- eol(0);
- print_gfs2(" ");
- if (gfs1)
- b = (uint64_t *)(dummy_bh.b_data +
- sizeof(struct gfs_log_descriptor));
- else
- b = (uint64_t *)(dummy_bh.b_data +
- sizeof(struct gfs2_log_descriptor));
- ld_blocks = ld.ld_data1;
- ld_blocks -= print_ld_blocks(b, (dummy_bh.b_data +
- sbd.bsize),
- start_line);
- } else if (get_block_type(&dummy_bh) == GFS2_METATYPE_LH) {
- struct gfs2_log_header lh;
- struct gfs_log_header lh1;
-
- if (gfs1) {
- gfs_log_header_in(&lh1, &dummy_bh);
- check_journal_wrap(lh1.lh_sequence,
- &highest_seq);
- print_gfs2("0x%llx (j+%4llx): Log header: "
- "Flags:%x, Seq: 0x%x, "
- "1st: 0x%x, tail: 0x%x, "
- "last: 0x%x", abs_block,
- jb, lh1.lh_flags, lh1.lh_sequence,
- lh1.lh_first, lh1.lh_tail,
- lh1.lh_last_dump);
- } else {
- gfs2_log_header_in(&lh, &dummy_bh);
- check_journal_wrap(lh.lh_sequence,
- &highest_seq);
- print_gfs2("0x%llx (j+%4llx): Log header: Seq"
- ": 0x%x, tail: 0x%x, blk: 0x%x",
- abs_block,
- jb / sbd.bsize, lh.lh_sequence,
- lh.lh_tail, lh.lh_blkno);
- }
- eol(0);
- } else if (gfs1 && ld_blocks > 0) {
- print_gfs2("0x%llx (j+%4llx): GFS log descriptor"
- " continuation block", abs_block, jb);
- eol(0);
- print_gfs2(" ");
- ld_blocks -= print_ld_blocks((uint64_t *)dummy_bh.b_data,
- (dummy_bh.b_data +
- sbd.bsize), start_line);
- }
- }
- brelse(j_bh);
- blockhist = -1; /* So we don't print anything else */
- free(jbuf);
-}
-
-/* ------------------------------------------------------------------------ */
-/* usage - print command line usage */
-/* ------------------------------------------------------------------------ */
-static void usage(void)
-{
- fprintf(stderr,"\nFormat is: gfs2_edit [-c 1] [-V] [-x] [-h] [identify] [-p structures|blocks][blocktype][blockalloc [val]][blockbits][blockrg][find sb|rg|rb|di|in|lf|jd|lh|ld|ea|ed|lb|13|qc][field <f>[val]] /dev/device\n\n");
- fprintf(stderr,"If only the device is specified, it enters into hexedit mode.\n");
- fprintf(stderr,"identify - prints out only the block type, not the details.\n");
- fprintf(stderr,"printsavedmeta - prints out the saved metadata blocks from a savemeta file.\n");
- fprintf(stderr,"savemeta <file_system> <file> - save off your metadata for analysis and debugging.\n");
- fprintf(stderr," (The intelligent way: assume bitmap is correct).\n");
- fprintf(stderr,"savemetaslow - save off your metadata for analysis and debugging. The SLOW way (block by block).\n");
- fprintf(stderr,"savergs - save off only the resource group information (rindex and rgs).\n");
- fprintf(stderr,"restoremeta - restore metadata for debugging (DANGEROUS).\n");
- fprintf(stderr,"rgcount - print how many RGs in the file system.\n");
- fprintf(stderr,"rgflags rgnum [new flags] - print or modify flags for rg #rgnum (0 - X)\n");
- fprintf(stderr,"-V prints version number.\n");
- fprintf(stderr,"-c 1 selects alternate color scheme 1\n");
- fprintf(stderr,"-p prints GFS2 structures or blocks to stdout.\n");
- fprintf(stderr," sb - prints the superblock.\n");
- fprintf(stderr," size - prints the filesystem size.\n");
- fprintf(stderr," master - prints the master directory.\n");
- fprintf(stderr," root - prints the root directory.\n");
- fprintf(stderr," jindex - prints the journal index directory.\n");
- fprintf(stderr," per_node - prints the per_node directory.\n");
- fprintf(stderr," inum - prints the inum file.\n");
- fprintf(stderr," statfs - prints the statfs file.\n");
- fprintf(stderr," rindex - prints the rindex file.\n");
- fprintf(stderr," rg X - print resource group X.\n");
- fprintf(stderr," rgs - prints all the resource groups (rgs).\n");
- fprintf(stderr," quota - prints the quota file.\n");
- fprintf(stderr," 0x1234 - prints the specified block\n");
- fprintf(stderr,"-p <block> blocktype - prints the type "
- "of the specified block\n");
- fprintf(stderr,"-p <block> blockrg - prints the resource group "
- "block corresponding to the specified block\n");
- fprintf(stderr,"-p <block> blockbits - prints the block with "
- "the bitmap corresponding to the specified block\n");
- fprintf(stderr,"-p <block> blockalloc [0|1|2|3] - print or change "
- "the allocation type of the specified block\n");
- fprintf(stderr,"-p <block> field [new_value] - prints or change the "
- "structure field\n");
- fprintf(stderr,"-p <b> find sb|rg|rb|di|in|lf|jd|lh|ld|ea|ed|lb|"
- "13|qc - find block of given type after block <b>\n");
- fprintf(stderr," <b> specifies the starting block for search\n");
- fprintf(stderr,"-s specifies a starting block such as root, rindex, quota, inum.\n");
- fprintf(stderr,"-x print in hexmode.\n");
- fprintf(stderr,"-h prints this help.\n\n");
- fprintf(stderr,"Examples:\n");
- fprintf(stderr," To run in interactive mode:\n");
- fprintf(stderr," gfs2_edit /dev/bobs_vg/lvol0\n");
- fprintf(stderr," To print out the superblock and master directory:\n");
- fprintf(stderr," gfs2_edit -p sb master /dev/bobs_vg/lvol0\n");
- fprintf(stderr," To print out the master directory in hex:\n");
- fprintf(stderr," gfs2_edit -x -p master /dev/bobs_vg/lvol0\n");
- fprintf(stderr," To print out the block-type for block 0x27381:\n");
- fprintf(stderr," gfs2_edit identify -p 0x27381 /dev/bobs_vg/lvol0\n");
- fprintf(stderr," To print out the fourth Resource Group. (the first R is #0)\n");
- fprintf(stderr," gfs2_edit -p rg 3 /dev/sdb1\n");
- fprintf(stderr," To print out the metadata type of block 1234\n");
- fprintf(stderr," gfs2_edit -p 1234 blocktype /dev/roth_vg/roth_lb\n");
- fprintf(stderr," To print out the allocation type of block 2345\n");
- fprintf(stderr," gfs2_edit -p 2345 blockalloc /dev/vg/lv\n");
- fprintf(stderr," To change the allocation type of block 2345 to a 'free block'\n");
- fprintf(stderr," gfs2_edit -p 2345 blockalloc 0 /dev/vg/lv\n");
- fprintf(stderr," To print out the file size of the dinode at block 0x118\n");
- fprintf(stderr," gfs2_edit -p 0x118 field di_size /dev/roth_vg/roth_lb\n");
- fprintf(stderr," To find any dinode higher than the quota file dinode:\n");
- fprintf(stderr," gfs2_edit -p quota find di /dev/x/y\n");
- fprintf(stderr," To set the Resource Group flags for rg #7 to 3.\n");
- fprintf(stderr," gfs2_edit rgflags 7 3 /dev/sdc2\n");
- fprintf(stderr," To save off all metadata for /dev/vg/lv:\n");
- fprintf(stderr," gfs2_edit savemeta /dev/vg/lv /tmp/metasave\n");
-}/* usage */
-
-/* ------------------------------------------------------------------------ */
-/* parameterpass1 - pre-processing for command-line parameters */
-/* ------------------------------------------------------------------------ */
-static void parameterpass1(int argc, char *argv[], int i)
-{
- if (!strcasecmp(argv[i], "-V")) {
- printf("%s version %s (built %s %s)\n",
- argv[0], RELEASE_VERSION, __DATE__, __TIME__);
- printf("%s\n", REDHAT_COPYRIGHT);
- exit(0);
- }
- else if (!strcasecmp(argv[i], "-h") ||
- !strcasecmp(argv[i], "-help") ||
- !strcasecmp(argv[i], "-usage")) {
- usage();
- exit(0);
- }
- else if (!strcasecmp(argv[i], "-c")) {
- i++;
- color_scheme = atoi(argv[i]);
- }
- else if (!strcasecmp(argv[i], "-p") ||
- !strcasecmp(argv[i], "-print")) {
- termlines = 0; /* initial value--we'll figure
- it out later */
- dmode = GFS2_MODE;
- }
- else if (!strcasecmp(argv[i], "savemeta"))
- termlines = 0;
- else if (!strcasecmp(argv[i], "savemetaslow"))
- termlines = 0;
- else if (!strcasecmp(argv[i], "savergs"))
- termlines = 0;
- else if (!strcasecmp(argv[i], "printsavedmeta")) {
- if (dmode == INIT_MODE)
- dmode = GFS2_MODE;
- restoremeta(argv[i+1], argv[i+2], TRUE);
- } else if (!strcasecmp(argv[i], "restoremeta")) {
- if (dmode == INIT_MODE)
- dmode = HEX_MODE; /* hopefully not used */
- restoremeta(argv[i+1], argv[i+2], FALSE);
- } else if (!strcmp(argv[i], "rgcount"))
- termlines = 0;
- else if (!strcmp(argv[i], "rgflags"))
- termlines = 0;
- else if (!strcmp(argv[i], "rg"))
- termlines = 0;
- else if (!strcasecmp(argv[i], "-x"))
- dmode = HEX_MODE;
- else if (!device[0] && strchr(argv[i],'/'))
- strcpy(device, argv[i]);
-}
-
-/* ------------------------------------------------------------------------ */
-/* process_parameters - process commandline parameters */
-/* pass - we make two passes through the parameters; the first pass gathers */
-/* normals parameters, device name, etc. The second pass is for */
-/* figuring out what structures to print out. */
-/* ------------------------------------------------------------------------ */
-static void process_parameters(int argc, char *argv[], int pass)
-{
- int i;
- uint64_t keyword_blk;
-
- if (argc < 2) {
- usage();
- die("no device specified\n");
- }
- for (i = 1; i < argc; i++) {
- if (!pass) { /* first pass */
- parameterpass1(argc, argv, i);
- continue;
- }
- /* second pass */
- if (!strcasecmp(argv[i], "-s")) {
- i++;
- if (i >= argc - 1) {
- printf("Error: starting block not specified "
- "with -s.\n");
- printf("%s -s [starting block | keyword] "
- "<device>\n", argv[0]);
- printf("For example: %s -s \"rg 3\" "
- "/dev/exxon_vg/exxon_lv\n", argv[0]);
- exit(EXIT_FAILURE);
- }
- starting_blk = check_keywords(argv[i]);
- continue;
- }
- if (termlines || strchr(argv[i],'/')) /* if print or slash */
- continue;
-
- if (!strncmp(argv[i], "journal", 7) &&
- isdigit(argv[i][7])) {
- dump_journal(argv[i]);
- continue;
- }
- keyword_blk = check_keywords(argv[i]);
- if (keyword_blk)
- push_block(keyword_blk);
- else if (!strcasecmp(argv[i], "-x"))
- dmode = HEX_MODE;
- else if (argv[i][0] == '-') /* if it starts with a dash */
- ; /* ignore it--meant for pass == 0 */
- else if (!strcmp(argv[i], "identify"))
- identify = TRUE;
- else if (!strcmp(argv[i], "size")) {
- printf("Device size: %" PRIu64 " (0x%" PRIx64 ")\n",
- max_block, max_block);
- exit(EXIT_SUCCESS);
- } else if (!strcmp(argv[i], "rgcount"))
- rgcount();
- else if (!strcmp(argv[i], "field")) {
- uint64_t newval;
-
- i++;
- if (i >= argc - 1) {
- printf("Error: field not specified.\n");
- printf("Format is: %s -p <block> field "
- "<field> [newvalue]\n", argv[0]);
- gfs2_rgrp_free(&sbd.rglist);
- exit(EXIT_FAILURE);
- }
- if (isdigit(argv[i + 1][0])) {
- if (argv[i + 1][0]=='0' && argv[i + 1][1]=='x')
- sscanf(argv[i + 1], "%"SCNx64,
- &newval);
- else
- newval = (uint64_t)atoll(argv[i + 1]);
- process_field(argv[i], &newval, 1);
- gfs2_rgrp_free(&sbd.rglist);
- exit(0);
- } else {
- process_field(argv[i], NULL, 1);
- gfs2_rgrp_free(&sbd.rglist);
- exit(0);
- }
- } else if (!strcmp(argv[i], "blocktype")) {
- find_print_block_type();
- } else if (!strcmp(argv[i], "blockrg")) {
- find_print_block_rg(0);
- } else if (!strcmp(argv[i], "blockbits")) {
- find_print_block_rg(1);
- } else if (!strcmp(argv[i], "blockalloc")) {
- if (isdigit(argv[i + 1][0])) {
- int newval;
-
- if (argv[i + 1][0]=='0' && argv[i + 1][1]=='x')
- sscanf(argv[i + 1], "%x", &newval);
- else
- newval = (uint64_t)atoi(argv[i + 1]);
- find_change_block_alloc(&newval);
- } else {
- find_change_block_alloc(NULL);
- }
- } else if (!strcmp(argv[i], "find")) {
- find_metablockoftype(argv[i + 1], 1);
- } else if (!strcmp(argv[i], "rgflags")) {
- int rg, set = FALSE;
- uint32_t new_flags = 0;
-
- i++;
- if (i >= argc - 1) {
- printf("Error: rg # not specified.\n");
- printf("Format is: %s rgflags rgnum"
- "[newvalue]\n", argv[0]);
- gfs2_rgrp_free(&sbd.rglist);
- exit(EXIT_FAILURE);
- }
- if (argv[i][0]=='0' && argv[i][1]=='x')
- sscanf(argv[i], "%"SCNx32, &rg);
- else
- rg = atoi(argv[i]);
- i++;
- if (i < argc - 1 &&
- isdigit(argv[i][0])) {
- set = TRUE;
- if (argv[i][0]=='0' && argv[i][1]=='x')
- sscanf(argv[i], "%"SCNx32, &new_flags);
- else
- new_flags = atoi(argv[i]);
- }
- set_rgrp_flags(rg, new_flags, set, FALSE);
- gfs2_rgrp_free(&sbd.rglist);
- exit(EXIT_SUCCESS);
- } else if (!strcmp(argv[i], "rg")) {
- int rg;
-
- i++;
- if (i >= argc - 1) {
- printf("Error: rg # not specified.\n");
- printf("Format is: %s rg rgnum\n", argv[0]);
- gfs2_rgrp_free(&sbd.rglist);
- exit(EXIT_FAILURE);
- }
- rg = atoi(argv[i]);
- if (!strcasecmp(argv[i + 1], "find")) {
- temp_blk = get_rg_addr(rg);
- push_block(temp_blk);
- } else {
- set_rgrp_flags(rg, 0, FALSE, TRUE);
- gfs2_rgrp_free(&sbd.rglist);
- exit(EXIT_SUCCESS);
- }
- }
- else if (!strcasecmp(argv[i], "savemeta"))
- savemeta(argv[i+2], 0);
- else if (!strcasecmp(argv[i], "savemetaslow"))
- savemeta(argv[i+2], 1);
- else if (!strcasecmp(argv[i], "savergs"))
- savemeta(argv[i+2], 2);
- else if (isdigit(argv[i][0])) { /* decimal addr */
- sscanf(argv[i], "%"SCNd64, &temp_blk);
- push_block(temp_blk);
- } else {
- fprintf(stderr,"I don't know what '%s' means.\n",
- argv[i]);
- usage();
- exit(EXIT_FAILURE);
- }
- } /* for */
-}/* process_parameters */
-
-/******************************************************************************
-*******************************************************************************
-**
-** main()
-**
-** Description:
-** Do everything
-**
-*******************************************************************************
-******************************************************************************/
-int main(int argc, char *argv[])
-{
- int i, j, fd;
-
- indirect = malloc(sizeof(struct iinfo));
- if (!indirect)
- die("Out of memory.");
- memset(indirect, 0, sizeof(struct iinfo));
- memset(start_row, 0, sizeof(start_row));
- memset(lines_per_row, 0, sizeof(lines_per_row));
- memset(end_row, 0, sizeof(end_row));
- memset(edit_row, 0, sizeof(edit_row));
- memset(edit_col, 0, sizeof(edit_col));
- memset(edit_size, 0, sizeof(edit_size));
- memset(last_entry_onscreen, 0, sizeof(last_entry_onscreen));
- dmode = INIT_MODE;
- sbd.bsize = 4096;
- block = starting_blk = 0x10;
- for (i = 0; i < BLOCK_STACK_SIZE; i++) {
- blockstack[i].dmode = HEX_MODE;
- blockstack[i].block = block;
- for (j = 0; j < DMODES; j++) {
- blockstack[i].start_row[j] = 0;
- blockstack[i].end_row[j] = 0;
- blockstack[i].edit_row[j] = 0;
- blockstack[i].edit_col[j] = 0;
- blockstack[i].lines_per_row[j] = 0;
- }
- }
-
- edit_row[GFS2_MODE] = 10; /* Start off at root inode
- pointer in superblock */
- memset(device, 0, sizeof(device));
- termlines = 30; /* assume interactive mode until we find -p */
- process_parameters(argc, argv, 0);
- if (dmode == INIT_MODE)
- dmode = HEX_MODE;
-
- fd = open(device, O_RDWR);
- if (fd < 0)
- die("can't open %s: %s\n", device, strerror(errno));
- max_block = lseek(fd, 0, SEEK_END) / sbd.bsize;
-
- read_superblock(fd);
- max_block = lseek(fd, 0, SEEK_END) / sbd.bsize;
- strcpy(sbd.device_name, device);
- if (gfs1)
- edit_row[GFS2_MODE]++;
- else
- read_master_dir();
- block_in_mem = -1;
- process_parameters(argc, argv, 1); /* get what to print from cmdline */
-
- block = blockstack[0].block = starting_blk * (4096 / sbd.bsize);
-
- if (termlines)
- interactive_mode();
- else { /* print all the structures requested */
- for (i = 0; i <= blockhist; i++) {
- block = blockstack[i + 1].block;
- if (!block)
- break;
- display(identify);
- if (!identify) {
- display_extended();
- printf("-------------------------------------" \
- "-----------------");
- eol(0);
- }
- block = pop_block();
- }
- }
- close(fd);
- if (indirect)
- free(indirect);
- gfs2_rgrp_free(&sbd.rglist);
- exit(EXIT_SUCCESS);
-}
diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h
deleted file mode 100644
index 549c3af..0000000
--- a/gfs2/edit/hexedit.h
+++ /dev/null
@@ -1,316 +0,0 @@
-#ifndef __HEXVIEW_DOT_H__
-#define __HEXVIEW_DOT_H__
-
-#include <sys/types.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <linux/gfs2_ondisk.h>
-#include <string.h>
-
-#include "libgfs2.h"
-#include "copyright.cf"
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#define DMODES 3
-enum dsp_mode { HEX_MODE = 0, GFS2_MODE = 1, EXTENDED_MODE = 2, INIT_MODE = 3 };
-#define BLOCK_STACK_SIZE 256
-
-#define GFS_FORMAT_SB (100) /* Super-Block */
-#define GFS_METATYPE_SB (1) /* Super-Block */
-#define GFS_FORMAT_FS (1309) /* Filesystem (all-encompassing) */
-#define GFS_FORMAT_MULTI (1401) /* Multi-Host */
-/* GFS1 Dinode types */
-#define GFS_FILE_NON (0)
-#define GFS_FILE_REG (1) /* regular file */
-#define GFS_FILE_DIR (2) /* directory */
-#define GFS_FILE_LNK (5) /* link */
-#define GFS_FILE_BLK (7) /* block device node */
-#define GFS_FILE_CHR (8) /* character device node */
-#define GFS_FILE_FIFO (101) /* fifo/pipe */
-#define GFS_FILE_SOCK (102) /* socket */
-
-/* GFS 1 journal block types: */
-#define GFS_LOG_DESC_METADATA (300) /* metadata */
-#define GFS_LOG_DESC_IUL (400) /* unlinked inode */
-#define GFS_LOG_DESC_IDA (401) /* de-allocated inode */
-#define GFS_LOG_DESC_Q (402) /* quota */
-#define GFS_LOG_DESC_LAST (500) /* final in a logged transaction */
-
-extern uint64_t block;
-extern int blockhist;
-extern int edit_mode;
-extern int line;
-extern char edit_fmt[80];
-extern char estring[1024]; /* edit string */
-extern char efield[64];
-extern uint64_t dev_offset;
-extern uint64_t max_block;
-extern struct gfs2_buffer_head *bh;
-extern int termlines;
-extern int termcols;
-extern int insert;
-extern const char *termtype;
-extern int line;
-extern int struct_len;
-extern unsigned int offset;
-extern int edit_row[DMODES], edit_col[DMODES], print_entry_ndx;
-extern int start_row[DMODES], end_row[DMODES], lines_per_row[DMODES];
-extern int edit_size[DMODES], last_entry_onscreen[DMODES];
-extern char edit_fmt[80];
-extern struct gfs2_sbd sbd;
-extern struct gfs_sb *sbd1;
-extern struct gfs2_inum gfs1_quota_di; /* kludge because gfs2 sb too small */
-extern struct gfs2_inum gfs1_license_di; /* kludge because gfs2 sb too small */
-extern struct gfs2_dinode di;
-extern int screen_chunk_size; /* how much of the 4K can fit on screen */
-extern int gfs2_struct_type;
-extern uint64_t block_in_mem;
-extern char device[NAME_MAX];
-extern int identify;
-extern int color_scheme;
-extern WINDOW *wind;
-extern int gfs1;
-extern int editing;
-extern uint64_t temp_blk;
-extern uint64_t starting_blk;
-extern const char *block_type_str[15];
-extern int dsplines;
-
-struct gfs_jindex {
- uint64_t ji_addr; /* starting block of the journal */
- uint32_t ji_nsegment; /* number (quantity) of segments in journal */
- uint32_t ji_pad;
-
- char ji_reserved[64];
-};
-
-struct gfs_log_descriptor {
- struct gfs2_meta_header ld_header;
-
- uint32_t ld_type; /* GFS_LOG_DESC_... Type of this log chunk */
- uint32_t ld_length; /* Number of buffers in this chunk */
- uint32_t ld_data1; /* descriptor-specific field */
- uint32_t ld_data2; /* descriptor-specific field */
- char ld_reserved[64];
-};
-
-struct gfs_log_header {
- struct gfs2_meta_header lh_header;
-
- uint32_t lh_flags; /* GFS_LOG_HEAD_... */
- uint32_t lh_pad;
-
- uint64_t lh_first; /* Block number of first header in this trans */
- uint64_t lh_sequence; /* Sequence number of this transaction */
-
- uint64_t lh_tail; /* Block number of log tail */
- uint64_t lh_last_dump; /* Block number of last dump */
-
- char lh_reserved[64];
-};
-
-struct gfs_rindex {
- uint64_t ri_addr; /* block # of 1st block (header) in rgrp */
- uint32_t ri_length; /* # fs blocks containing rgrp header & bitmap */
- uint32_t ri_pad;
-
- uint64_t ri_data1; /* block # of first data/meta block in rgrp */
- uint32_t ri_data; /* number (qty) of data/meta blocks in rgrp */
-
- uint32_t ri_bitbytes; /* total # bytes used by block alloc bitmap */
-
- char ri_reserved[64];
-};
-
-struct gfs_rgrp {
- struct gfs2_meta_header rg_header;
-
- uint32_t rg_flags; /* ?? */
-
- uint32_t rg_free; /* Number (qty) of free data blocks */
-
- /* Dinodes are USEDMETA, but are handled separately from other METAs */
- uint32_t rg_useddi; /* Number (qty) of dinodes (used or free) */
- uint32_t rg_freedi; /* Number (qty) of unused (free) dinodes */
- struct gfs2_inum rg_freedi_list; /* 1st block in chain of free dinodes */
-
- /* These META statistics do not include dinodes (used or free) */
- uint32_t rg_usedmeta; /* Number (qty) of used metadata blocks */
- uint32_t rg_freemeta; /* Number (qty) of unused metadata blocks */
-
- char rg_reserved[64];
-};
-
-extern int block_is_jindex(void);
-extern int block_is_rindex(void);
-extern int block_is_inum_file(void);
-extern int block_is_statfs_file(void);
-extern int block_is_quota_file(void);
-extern int block_is_per_node(void);
-extern int block_is_in_per_node(void);
-extern int display_block_type(int from_restore);
-extern void gfs_jindex_in(struct gfs_jindex *jindex, char *buf);
-extern void gfs_log_header_in(struct gfs_log_header *head,
- struct gfs2_buffer_head *bh);
-extern void gfs_log_header_print(struct gfs_log_header *lh);
-extern void gfs_dinode_in(struct gfs_dinode *di, struct gfs2_buffer_head *bh);
-extern void savemeta(char *out_fn, int saveoption);
-extern void restoremeta(const char *in_fn, const char *out_device,
- uint64_t printblocksonly);
-extern int display(int identify_only);
-extern uint64_t check_keywords(const char *kword);
-extern uint64_t masterblock(const char *fn);
-
-struct gfs2_dirents {
- uint64_t block;
- struct gfs2_dirent dirent;
- char filename[NAME_MAX];
-};
-
-struct indirect_info {
- int is_dir;
- int height;
- uint64_t block;
- uint32_t dirents;
- struct metapath mp;
- struct gfs2_dirents dirent[64];
-};
-
-struct iinfo {
- struct indirect_info ii[512];
-};
-
-struct blkstack_info {
- uint64_t block;
- int start_row[DMODES];
- int end_row[DMODES];
- int lines_per_row[DMODES];
- int edit_row[DMODES];
- int edit_col[DMODES];
- enum dsp_mode dmode;
- int gfs2_struct_type;
- struct metapath mp;
-};
-
-struct gfs_sb {
- /* Order is important; need to be able to read old superblocks
- in order to support on-disk version upgrades */
- struct gfs2_meta_header sb_header;
-
- uint32_t sb_fs_format; /* GFS_FORMAT_FS (on-disk version) */
- uint32_t sb_multihost_format; /* GFS_FORMAT_MULTI */
- uint32_t sb_flags; /* ?? */
-
- uint32_t sb_bsize; /* fundamental FS block size in bytes */
- uint32_t sb_bsize_shift; /* log2(sb_bsize) */
- uint32_t sb_seg_size; /* Journal segment size in FS blocks */
-
- /* These special inodes do not appear in any on-disk directory. */
- struct gfs2_inum sb_jindex_di; /* journal index inode */
- struct gfs2_inum sb_rindex_di; /* resource group index inode */
- struct gfs2_inum sb_root_di; /* root directory inode */
-
- /* Default inter-node locking protocol (lock module) and namespace */
- char sb_lockproto[GFS2_LOCKNAME_LEN]; /* lock protocol name */
- char sb_locktable[GFS2_LOCKNAME_LEN]; /* unique name for this FS */
-
- /* More special inodes */
- struct gfs2_inum sb_quota_di; /* quota inode */
- struct gfs2_inum sb_license_di; /* license inode */
-
- char sb_reserved[96];
-};
-
-extern struct blkstack_info blockstack[BLOCK_STACK_SIZE];
-extern struct iinfo *indirect; /* more than the most indirect
- pointers possible for any given 4K block */
-extern struct indirect_info masterdir; /* Master directory info */
-extern int indirect_blocks; /* count of indirect blocks */
-extern enum dsp_mode dmode;
-
-#define SCREEN_HEIGHT (16)
-#define SCREEN_WIDTH (16)
-
-/* Memory macros */
-
-#define type_alloc(ptr, type, count) \
-{ \
- (ptr) = (type *)malloc(sizeof(type) * (count)); \
- if (!(ptr)) \
- die("unable to allocate memory on line %d of file %s\n", \
- __LINE__, __FILE__); \
-}
-
-#define printk printw
-
-/* Divide x by y. Round up if there is a remainder. */
-#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
-
-#define TITLE1 "gfs2_edit - Global File System Editor (use with extreme caution)"
-#define TITLE2 REDHAT_COPYRIGHT " - Press H for help"
-
-#define COLOR_TITLE 1
-#define COLOR_NORMAL 2
-#define COLOR_INVERSE 3
-#define COLOR_SPECIAL 4
-#define COLOR_HIGHLIGHT 5
-#define COLOR_OFFSETS 6
-#define COLOR_CONTENTS 7
-
-#define COLORS_TITLE \
- do { \
- if (termlines) { \
- attrset(COLOR_PAIR(COLOR_TITLE)); \
- attron(A_BOLD); \
- } \
- } while (0)
-#define COLORS_NORMAL \
- do { \
- if (termlines) { \
- attrset(COLOR_PAIR(COLOR_NORMAL)); \
- attron(A_BOLD); \
- } \
- } while (0)
-#define COLORS_INVERSE \
- do { \
- if (termlines) { \
- attrset(COLOR_PAIR(COLOR_INVERSE)); \
- attron(A_BOLD); \
- } \
- } while (0)
-#define COLORS_SPECIAL \
- do { \
- if (termlines) { \
- attrset(COLOR_PAIR(COLOR_SPECIAL)); \
- attron(A_BOLD); \
- } \
- } while (0)
-#define COLORS_HIGHLIGHT \
- do { \
- if (termlines) { \
- attrset(COLOR_PAIR(COLOR_HIGHLIGHT)); \
- attron(A_BOLD); \
- } \
- } while (0)
-#define COLORS_OFFSETS \
- do { \
- if (termlines) { \
- attrset(COLOR_PAIR(COLOR_OFFSETS)); \
- attron(A_BOLD); \
- } \
- } while (0)
-#define COLORS_CONTENTS \
- do { \
- if (termlines) { \
- attrset(COLOR_PAIR(COLOR_CONTENTS)); \
- attron(A_BOLD); \
- } \
- } while (0)
-
-#endif /* __HEXVIEW_DOT_H__ */
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
deleted file mode 100644
index c052acf..0000000
--- a/gfs2/edit/savemeta.c
+++ /dev/null
@@ -1,913 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <linux/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <curses.h>
-#include <term.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <sys/time.h>
-#include <linux/gfs2_ondisk.h>
-
-#include "osi_list.h"
-#include "gfs2hex.h"
-#include "hexedit.h"
-#include "libgfs2.h"
-
-#define BUFSIZE (4096)
-#define DFT_SAVE_FILE "/tmp/gfsmeta.XXXXXX"
-#define MAX_JOURNALS_SAVED 256
-
-struct saved_metablock {
- uint64_t blk;
- uint16_t siglen; /* significant data length */
- char buf[BUFSIZE];
-};
-
-struct saved_metablock *savedata;
-struct gfs2_buffer_head *savebh;
-uint64_t last_fs_block, last_reported_block, blks_saved, total_out, pct;
-uint64_t journal_blocks[MAX_JOURNALS_SAVED];
-uint64_t gfs1_journal_size = 0; /* in blocks */
-int journals_found = 0;
-
-extern void read_superblock(void);
-
-/*
- * get_gfs_struct_info - get block type and structure length
- *
- * @block_type - pointer to integer to hold the block type
- * @struct_length - pointer to integet to hold the structure length
- *
- * returns: 0 if successful
- * -1 if this isn't gfs metadata.
- */
-static int get_gfs_struct_info(struct gfs2_buffer_head *lbh, int *block_type,
- int *gstruct_len)
-{
- struct gfs2_meta_header mh;
-
- *block_type = 0;
- *gstruct_len = sbd.bsize;
-
- gfs2_meta_header_in(&mh, lbh);
- if (mh.mh_magic != GFS2_MAGIC)
- return -1;
-
- *block_type = mh.mh_type;
-
- switch (mh.mh_type) {
- case GFS2_METATYPE_SB: /* 1 (superblock) */
- *gstruct_len = sizeof(struct gfs_sb);
- break;
- case GFS2_METATYPE_RG: /* 2 (rsrc grp hdr) */
- *gstruct_len = sbd.bsize; /*sizeof(struct gfs_rgrp);*/
- break;
- case GFS2_METATYPE_RB: /* 3 (rsrc grp bitblk) */
- *gstruct_len = sbd.bsize;
- break;
- case GFS2_METATYPE_DI: /* 4 (disk inode) */
- *gstruct_len = sbd.bsize; /*sizeof(struct gfs_dinode);*/
- break;
- case GFS2_METATYPE_IN: /* 5 (indir inode blklst) */
- *gstruct_len = sbd.bsize; /*sizeof(struct gfs_indirect);*/
- break;
- case GFS2_METATYPE_LF: /* 6 (leaf dinode blklst) */
- *gstruct_len = sbd.bsize; /*sizeof(struct gfs_leaf);*/
- break;
- case GFS2_METATYPE_JD: /* 7 (journal data) */
- *gstruct_len = sbd.bsize;
- break;
- case GFS2_METATYPE_LH: /* 8 (log header) */
- if (gfs1)
- *gstruct_len = 512; /* gfs copies the log header
- twice and compares the copy,
- so we need to save all 512
- bytes of it. */
- else
- *gstruct_len = sizeof(struct gfs2_log_header);
- break;
- case GFS2_METATYPE_LD: /* 9 (log descriptor) */
- *gstruct_len = sbd.bsize;
- break;
- case GFS2_METATYPE_EA: /* 10 (extended attr hdr) */
- *gstruct_len = sbd.bsize;
- break;
- case GFS2_METATYPE_ED: /* 11 (extended attr data) */
- *gstruct_len = sbd.bsize;
- break;
- default:
- *gstruct_len = sbd.bsize;
- break;
- }
- return 0;
-}
-
-/* Put out a warm, fuzzy message every second so the user */
-/* doesn't think we hung. (This may take a long time). */
-/* We only check whether to report every one percent because */
-/* checking every block kills performance. We only report */
-/* every second because we don't need 100 extra messages in */
-/* logs made from verbose mode. */
-static void warm_fuzzy_stuff(uint64_t wfsblock, int force, int save)
-{
- static struct timeval tv;
- static uint32_t seconds = 0;
-
- last_reported_block = wfsblock;
- gettimeofday(&tv, NULL);
- if (!seconds)
- seconds = tv.tv_sec;
- if (force || tv.tv_sec - seconds) {
- static uint64_t percent;
-
- seconds = tv.tv_sec;
- if (last_fs_block) {
- printf("\r");
- if (save) {
- percent = (wfsblock * 100) / last_fs_block;
- printf("%" PRIu64 " metadata blocks (%"
- PRIu64 "%%) processed, ", wfsblock,
- percent);
- }
- if (total_out < 1024 * 1024)
- printf("%" PRIu64 " metadata blocks (%"
- PRIu64 "KB) %s. ",
- blks_saved, total_out / 1024,
- save?"saved":"restored");
- else
- printf("%" PRIu64 " metadata blocks (%"
- PRIu64 "MB) %s. ",
- blks_saved, total_out / (1024*1024),
- save?"saved":"restored");
- if (force)
- printf("\n");
- fflush(stdout);
- }
- }
-}
-
-static int block_is_a_journal(void)
-{
- int j;
-
- for (j = 0; j < journals_found; j++)
- if (block == journal_blocks[j])
- return TRUE;
- return FALSE;
-}
-
-static int block_is_systemfile(void)
-{
- return block_is_jindex() || block_is_inum_file() ||
- block_is_statfs_file() || block_is_quota_file() ||
- block_is_rindex() || block_is_a_journal() ||
- block_is_per_node() || block_is_in_per_node();
-}
-
-static int save_block(int fd, int out_fd, uint64_t blk)
-{
- int blktype, blklen, outsz;
- uint16_t trailing0;
- char *p;
-
- if (blk > last_fs_block) {
- fprintf(stderr, "\nWarning: bad block pointer '0x%llx' "
- "ignored in block (block %llu (%llx))",
- (unsigned long long)blk,
- (unsigned long long)block, (unsigned long long)block);
- return 0;
- }
- memset(savedata, 0, sizeof(struct saved_metablock));
- savebh = bread(&sbd, blk);
- memcpy(&savedata->buf, savebh->b_data, sbd.bsize);
-
- /* If this isn't metadata and isn't a system file, we don't want it.
- Note that we're checking "block" here rather than blk. That's
- because we want to know if the source inode's "block" is a system
- inode, not the block within the inode "blk". They may or may not
- be the same thing. */
- if (get_gfs_struct_info(savebh, &blktype, &blklen) &&
- !block_is_systemfile())
- return 0; /* Not metadata, and not system file, so skip it */
- trailing0 = 0;
- p = &savedata->buf[blklen - 1];
- while (*p=='\0' && trailing0 < sbd.bsize) {
- trailing0++;
- p--;
- }
- savedata->blk = cpu_to_be64(blk);
- if (write(out_fd, &savedata->blk, sizeof(savedata->blk)) !=
- sizeof(savedata->blk)) {
- fprintf(stderr, "write error: %s from %s:%d: "
- "block %lld (0x%llx)\n", strerror(errno),
- __FUNCTION__, __LINE__,
- (unsigned long long)savedata->blk,
- (unsigned long long)savedata->blk);
- exit(-1);
- }
- outsz = blklen - trailing0;
- savedata->siglen = cpu_to_be16(outsz);
- if (write(out_fd, &savedata->siglen, sizeof(savedata->siglen)) !=
- sizeof(savedata->siglen)) {
- fprintf(stderr, "write error: %s from %s:%d: "
- "block %lld (0x%llx)\n", strerror(errno),
- __FUNCTION__, __LINE__,
- (unsigned long long)savedata->blk,
- (unsigned long long)savedata->blk);
- exit(-1);
- }
- if (write(out_fd, savedata->buf, outsz) != outsz) {
- fprintf(stderr, "write error: %s from %s:%d: "
- "block %lld (0x%llx)\n", strerror(errno),
- __FUNCTION__, __LINE__,
- (unsigned long long)savedata->blk,
- (unsigned long long)savedata->blk);
- exit(-1);
- }
- total_out += sizeof(savedata->blk) + sizeof(savedata->siglen) + outsz;
- blks_saved++;
- return blktype;
-}
-
-/*
- * save_ea_block - save off an extended attribute block
- */
-static void save_ea_block(int out_fd, struct gfs2_buffer_head *metabh)
-{
- int i, e, ea_len = sbd.bsize;
- struct gfs2_ea_header ea;
-
- for (e = sizeof(struct gfs2_meta_header); e < sbd.bsize; e += ea_len) {
- uint64_t blk, *b;
- int charoff;
-
- gfs2_ea_header_in(&ea, metabh->b_data + e);
- for (i = 0; i < ea.ea_num_ptrs; i++) {
- charoff = e + ea.ea_name_len +
- sizeof(struct gfs2_ea_header) +
- sizeof(uint64_t) - 1;
- charoff /= sizeof(uint64_t);
- b = (uint64_t *)(metabh->b_data);
- b += charoff + i;
- blk = be64_to_cpu(*b);
- save_block(sbd.device_fd, out_fd, blk);
- }
- if (!ea.ea_rec_len)
- break;
- ea_len = ea.ea_rec_len;
- }
-}
-
-/*
- * save_indirect_blocks - save all indirect blocks for the given buffer
- */
-static void save_indirect_blocks(int out_fd, osi_list_t *cur_list,
- struct gfs2_buffer_head *mybh, int height, int hgt)
-{
- uint64_t old_block = 0, indir_block;
- uint64_t *ptr;
- int head_size, blktype;
- struct gfs2_buffer_head *nbh;
-
- head_size = (hgt > 1 ?
- sizeof(struct gfs2_meta_header) :
- sizeof(struct gfs2_dinode));
-
- for (ptr = (uint64_t *)(mybh->b_data + head_size);
- (char *)ptr < (mybh->b_data + sbd.bsize); ptr++) {
- if (!*ptr)
- continue;
- indir_block = be64_to_cpu(*ptr);
- if (indir_block == old_block)
- continue;
- old_block = indir_block;
- blktype = save_block(sbd.device_fd, out_fd, indir_block);
- if (blktype == GFS2_METATYPE_EA) {
- nbh = bread(&sbd, indir_block);
- save_ea_block(out_fd, nbh);
- brelse(nbh);
- }
- if (height != hgt) { /* If not at max height */
- nbh = bread(&sbd, indir_block);
- osi_list_add_prev(&nbh->b_altlist, cur_list);
- brelse(nbh);
- }
- } /* for all data on the indirect block */
-}
-
-/*
- * save_inode_data - save off important data associated with an inode
- *
- * out_fd - destination file descriptor
- * block - block number of the inode to save the data for
- *
- * For user files, we don't want anything except all the indirect block
- * pointers that reside on blocks on all but the highest height.
- *
- * For system files like statfs and inum, we want everything because they
- * may contain important clues and no user data.
- *
- * For file system journals, the "data" is a mixture of metadata and
- * journaled data. We want all the metadata and none of the user data.
- */
-static void save_inode_data(int out_fd)
-{
- uint32_t height;
- struct gfs2_inode *inode;
- osi_list_t metalist[GFS2_MAX_META_HEIGHT];
- osi_list_t *prev_list, *cur_list, *tmp;
- struct gfs2_buffer_head *metabh, *mybh;
- int i;
-
- for (i = 0; i < GFS2_MAX_META_HEIGHT; i++)
- osi_list_init(&metalist[i]);
- metabh = bread(&sbd, block);
- if (gfs1)
- inode = inode_get(&sbd, metabh);
- else
- inode = gfs_inode_get(&sbd, metabh);
- height = inode->i_di.di_height;
- /* If this is a user inode, we don't follow to the file height.
- We stop one level less. That way we save off the indirect
- pointer blocks but not the actual file contents. The exception
- is directories, where the height represents the level at which
- the hash table exists, and we have to save the directory data. */
- if (inode->i_di.di_flags & GFS2_DIF_EXHASH &&
- (S_ISDIR(inode->i_di.di_mode) ||
- (gfs1 && inode->i_di.__pad1 == GFS_FILE_DIR)))
- height++;
- else if (height && !block_is_systemfile() &&
- !S_ISDIR(inode->i_di.di_mode))
- height--;
- osi_list_add(&metabh->b_altlist, &metalist[0]);
- for (i = 1; i <= height; i++){
- prev_list = &metalist[i - 1];
- cur_list = &metalist[i];
-
- for (tmp = prev_list->next; tmp != prev_list; tmp = tmp->next){
- mybh = osi_list_entry(tmp, struct gfs2_buffer_head,
- b_altlist);
- save_indirect_blocks(out_fd, cur_list, mybh,
- height, i);
- } /* for blocks at that height */
- } /* for height */
- /* free metalists */
- for (i = 0; i < GFS2_MAX_META_HEIGHT; i++) {
- cur_list = &metalist[i];
- while (!osi_list_empty(cur_list)) {
- mybh = osi_list_entry(cur_list->next,
- struct gfs2_buffer_head,
- b_altlist);
- osi_list_del(&mybh->b_altlist);
- }
- }
- /* Process directory exhash inodes */
- if (S_ISDIR(inode->i_di.di_mode)) {
- if (inode->i_di.di_flags & GFS2_DIF_EXHASH) {
- save_indirect_blocks(out_fd, cur_list, metabh,
- height, 0);
- }
- }
- if (inode->i_di.di_eattr) { /* if this inode has extended attributes */
- struct gfs2_meta_header mh;
- struct gfs2_buffer_head *lbh;
-
- lbh = bread(&sbd, inode->i_di.di_eattr);
- save_block(sbd.device_fd, out_fd, inode->i_di.di_eattr);
- gfs2_meta_header_in(&mh, lbh);
- if (mh.mh_magic == GFS2_MAGIC &&
- mh.mh_type == GFS2_METATYPE_EA)
- save_ea_block(out_fd, lbh);
- else if (mh.mh_magic == GFS2_MAGIC &&
- mh.mh_type == GFS2_METATYPE_IN)
- save_indirect_blocks(out_fd, cur_list, lbh, 2, 2);
- else {
- if (mh.mh_magic == GFS2_MAGIC) /* if it's metadata */
- save_block(sbd.device_fd, out_fd,
- inode->i_di.di_eattr);
- fprintf(stderr,
- "\nWarning: corrupt extended "
- "attribute at block %llu (0x%llx) "
- "detected in inode %lld (0x%llx).\n",
- (unsigned long long)inode->i_di.di_eattr,
- (unsigned long long)inode->i_di.di_eattr,
- (unsigned long long)block,
- (unsigned long long)block);
- }
- brelse(lbh);
- }
- inode_put(&inode);
- brelse(metabh);
-}
-
-static void get_journal_inode_blocks(void)
-{
- int journal;
-
- journals_found = 0;
- memset(journal_blocks, 0, sizeof(journal_blocks));
- /* Save off all the journals--but only the metadata.
- * This is confusing so I'll explain. The journals contain important
- * metadata. However, in gfs2 the journals are regular files within
- * the system directory. Since they're regular files, the blocks
- * within the journals are considered data, not metadata. Therefore,
- * they won't have been saved by the code above. We want to dump
- * these blocks, but we have to be careful. We only care about the
- * journal blocks that look like metadata, and we need to not save
- * journaled user data that may exist there as well. */
- for (journal = 0; ; journal++) { /* while journals exist */
- uint64_t jblock;
- int amt;
- struct gfs2_inode *j_inode = NULL;
-
- if (gfs1) {
- struct gfs_jindex ji;
- char jbuf[sizeof(struct gfs_jindex)];
-
- j_inode = gfs_inode_read(&sbd,
- sbd1->sb_jindex_di.no_addr);
- amt = gfs2_readi(j_inode, (void *)&jbuf,
- journal * sizeof(struct gfs_jindex),
- sizeof(struct gfs_jindex));
- inode_put(&j_inode);
- if (!amt)
- break;
- gfs_jindex_in(&ji, jbuf);
- jblock = ji.ji_addr;
- gfs1_journal_size = ji.ji_nsegment * 16;
- } else {
- if (journal > indirect->ii[0].dirents - 3)
- break;
- jblock = indirect->ii[0].dirent[journal + 2].block;
- }
- journal_blocks[journals_found++] = jblock;
- }
-}
-
-static int next_rg_freemeta(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
- uint64_t *nrfblock, int first)
-{
- struct gfs2_bitmap *bits = NULL;
- uint32_t length = rgd->ri.ri_length;
- uint32_t blk = (first)? 0: (uint32_t)((*nrfblock+1)-rgd->ri.ri_data0);
- int i;
- struct gfs2_buffer_head *lbh;
-
- if(!first && (*nrfblock < rgd->ri.ri_data0)) {
- log_err("next_rg_freemeta: Start block is outside rgrp "
- "bounds.\n");
- exit(1);
- }
- for(i=0; i < length; i++){
- bits = &rgd->bits[i];
- if(blk < bits->bi_len*GFS2_NBBY)
- break;
- blk -= bits->bi_len*GFS2_NBBY;
- }
- for(; i < length; i++){
- bits = &rgd->bits[i];
- lbh = bread(sdp, rgd->ri.ri_addr + i);
- blk = gfs2_bitfit((unsigned char *)lbh->b_data +
- bits->bi_offset, bits->bi_len, blk,
- GFS2_BLKST_UNLINKED);
- brelse(lbh);
- if(blk != BFITNOENT){
- *nrfblock = blk + (bits->bi_start * GFS2_NBBY) +
- rgd->ri.ri_data0;
- break;
- }
- blk=0;
- }
- if(i == length)
- return -1;
- return 0;
-}
-
-void savemeta(char *out_fn, int saveoption)
-{
- int out_fd;
- int slow;
- osi_list_t *tmp;
- int rgcount;
- uint64_t jindex_block;
- struct gfs2_buffer_head *lbh;
-
- slow = (saveoption == 1);
- sbd.md.journals = 1;
-
- if (!out_fn) {
- out_fn = strdup(DFT_SAVE_FILE);
- if (!out_fn)
- die("Can't allocate memory for the operation.\n");
- out_fd = mkstemp(out_fn);
- } else
- out_fd = open(out_fn, O_RDWR | O_CREAT, 0644);
-
- if (out_fd < 0)
- die("Can't open %s: %s\n", out_fn, strerror(errno));
-
- if (ftruncate(out_fd, 0))
- die("Can't truncate %s: %s\n", out_fn, strerror(errno));
- savedata = malloc(sizeof(struct saved_metablock));
- if (!savedata)
- die("Can't allocate memory for the operation.\n");
-
- lseek(sbd.device_fd, 0, SEEK_SET);
- blks_saved = total_out = last_reported_block = 0;
- if (!gfs1)
- sbd.bsize = BUFSIZE;
- if (!slow) {
- if (device_geometry(&sbd)) {
- fprintf(stderr, "Geometery error\n");
- exit(-1);
- }
- if (fix_device_geometry(&sbd)) {
- fprintf(stderr, "Device is too small (%"PRIu64" bytes)\n",
- sbd.device.length << GFS2_BASIC_BLOCK_SHIFT);
- exit(-1);
- }
- osi_list_init(&sbd.rglist);
- if (!gfs1)
- sbd.sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
- if (compute_constants(&sbd)) {
- fprintf(stderr, "Bad constants (1)\n");
- exit(-1);
- }
- if(gfs1) {
- sbd.bsize = sbd.sd_sb.sb_bsize;
- sbd.sd_inptrs = (sbd.bsize -
- sizeof(struct gfs_indirect)) /
- sizeof(uint64_t);
- sbd.sd_diptrs = (sbd.bsize -
- sizeof(struct gfs_dinode)) /
- sizeof(uint64_t);
- } else {
- if (read_sb(&sbd) < 0)
- slow = TRUE;
- else {
- sbd.sd_inptrs = (sbd.bsize -
- sizeof(struct gfs2_meta_header)) /
- sizeof(uint64_t);
- sbd.sd_diptrs = (sbd.bsize -
- sizeof(struct gfs2_dinode)) /
- sizeof(uint64_t);
- }
- }
- }
- last_fs_block = lseek(sbd.device_fd, 0, SEEK_END) / sbd.bsize;
- printf("There are %" PRIu64 " blocks of %u bytes.\n",
- last_fs_block, sbd.bsize);
- if (!slow) {
- if (gfs1) {
- sbd.md.riinode = inode_read(&sbd,
- sbd1->sb_rindex_di.no_addr);
- jindex_block = sbd1->sb_jindex_di.no_addr;
- } else {
- sbd.master_dir =
- inode_read(&sbd,
- sbd.sd_sb.sb_master_dir.no_addr);
-
- slow = gfs2_lookupi(sbd.master_dir, "rindex", 6,
- &sbd.md.riinode);
- jindex_block = masterblock("jindex");
- }
- lbh = bread(&sbd, jindex_block);
- gfs2_dinode_in(&di, lbh);
- if (!gfs1)
- do_dinode_extended(&di, lbh);
- brelse(lbh);
- }
- if (!slow) {
- int sane;
-
- printf("Reading resource groups...");
- fflush(stdout);
- if (gfs1)
- slow = gfs1_ri_update(&sbd, 0, &rgcount, 0);
- else
- slow = ri_update(&sbd, 0, &rgcount, &sane);
- printf("Done.\n\n");
- fflush(stdout);
- }
- get_journal_inode_blocks();
- if (!slow) {
- /* Save off the superblock */
- save_block(sbd.device_fd, out_fd, 0x10 * (4096 / sbd.bsize));
- /* If this is gfs1, save off the rindex because it's not
- part of the file system as it is in gfs2. */
- if (gfs1) {
- int j;
-
- block = sbd1->sb_rindex_di.no_addr;
- save_block(sbd.device_fd, out_fd, block);
- save_inode_data(out_fd);
- /* In GFS1, journals aren't part of the RG space */
- for (j = 0; j < journals_found; j++) {
- log_debug("Saving journal #%d\n", j + 1);
- for (block = journal_blocks[j];
- block < journal_blocks[j] +
- gfs1_journal_size;
- block++)
- save_block(sbd.device_fd, out_fd, block);
- }
- }
- /* Walk through the resource groups saving everything within */
- for (tmp = sbd.rglist.next; tmp != &sbd.rglist;
- tmp = tmp->next){
- struct rgrp_list *rgd;
- int first;
-
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- slow = gfs2_rgrp_read(&sbd, rgd);
- if (slow)
- continue;
- log_debug("RG at %lld (0x%llx) is %u long\n",
- (unsigned long long)rgd->ri.ri_addr,
- (unsigned long long)rgd->ri.ri_addr,
- rgd->ri.ri_length);
- first = 1;
- /* Save off the rg and bitmaps */
- for (block = rgd->ri.ri_addr;
- block < rgd->ri.ri_data0; block++) {
- warm_fuzzy_stuff(block, FALSE, TRUE);
- save_block(sbd.device_fd, out_fd, block);
- }
- /* Save off the other metadata: inodes, etc. */
- if (saveoption != 2) {
- int blktype;
-
- while (!gfs2_next_rg_meta(rgd, &block, first)){
- warm_fuzzy_stuff(block, FALSE, TRUE);
- blktype = save_block(sbd.device_fd,
- out_fd, block);
- if (blktype == GFS2_METATYPE_DI)
- save_inode_data(out_fd);
- first = 0;
- }
- /* Save off the free/unlinked meta blocks too.
- If we don't, we may run into metadata
- allocation issues. */
- while (!next_rg_freemeta(&sbd, rgd, &block,
- first)) {
- blktype = save_block(sbd.device_fd,
- out_fd, block);
- first = 0;
- }
- }
- gfs2_rgrp_relse(rgd);
- }
- }
- if (slow) {
- for (block = 0; block < last_fs_block; block++) {
- save_block(sbd.device_fd, out_fd, block);
- }
- }
- /* Clean up */
- /* There may be a gap between end of file system and end of device */
- /* so we tell the user that we've processed everything. */
- block = last_fs_block;
- warm_fuzzy_stuff(block, TRUE, TRUE);
- printf("\nMetadata saved to file %s.\n", out_fn);
- free(savedata);
- close(out_fd);
- close(sbd.device_fd);
- exit(0);
-}
-
-/**
- * anthropomorphize - make a uint64_t number more human
- */
-static const char *anthropomorphize(unsigned long long inhuman_value)
-{
- const char *symbols = " KMGTPE";
- int i;
- unsigned long long val = inhuman_value;
- static char out_val[32];
-
- memset(out_val, 0, sizeof(out_val));
- for (i = 0; i < 6 && val > 1024; i++)
- val /= 1024;
- sprintf(out_val, "%llu%c", val, symbols[i]);
- return out_val;
-}
-
-static int restore_data(int fd, int in_fd, int printblocksonly)
-{
- size_t rs;
- uint64_t buf64, writes = 0, highest_valid_block = 0;
- uint16_t buf16;
- int first = 1, pos;
- char rdbuf[256];
- char gfs_superblock_id[8] = {0x01, 0x16, 0x19, 0x70,
- 0x00, 0x00, 0x00, 0x01};
-
- if (!printblocksonly)
- lseek(fd, 0, SEEK_SET);
- lseek(in_fd, 0, SEEK_SET);
- rs = read(in_fd, rdbuf, sizeof(rdbuf));
- if (rs != sizeof(rdbuf)) {
- fprintf(stderr, "Error: File is too small.\n");
- return -1;
- }
- for (pos = 0; pos < sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t);
- pos++) {
- if (!memcmp(&rdbuf[pos + sizeof(uint64_t) + sizeof(uint16_t)],
- gfs_superblock_id, sizeof(gfs_superblock_id))) {
- break;
- }
- }
- if (pos == sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
- pos = 0;
- if (lseek(in_fd, pos, SEEK_SET) != pos) {
- fprintf(stderr, "bad seek: %s from %s:%d: "
- "offset %lld (0x%llx)\n", strerror(errno),
- __FUNCTION__, __LINE__, (unsigned long long)pos,
- (unsigned long long)pos);
- exit(-1);
- }
- blks_saved = total_out = 0;
- last_fs_block = 0;
- while (TRUE) {
- struct gfs2_buffer_head dummy_bh;
-
- memset(savedata, 0, sizeof(struct saved_metablock));
- rs = read(in_fd, &buf64, sizeof(uint64_t));
- if (!rs)
- break;
- if (rs != sizeof(uint64_t)) {
- fprintf(stderr, "Error reading from file.\n");
- return -1;
- }
- total_out += sbd.bsize;
- savedata->blk = be64_to_cpu(buf64);
- if (!printblocksonly &&
- last_fs_block && savedata->blk >= last_fs_block) {
- fprintf(stderr, "Error: File system is too small to "
- "restore this metadata.\n");
- fprintf(stderr, "File system is %" PRIu64 " blocks, ",
- last_fs_block);
- fprintf(stderr, "Restore block = %" PRIu64 "\n",
- savedata->blk);
- return -1;
- }
- rs = read(in_fd, &buf16, sizeof(uint16_t));
- savedata->siglen = be16_to_cpu(buf16);
- if (savedata->siglen > sizeof(savedata->buf)) {
- fprintf(stderr, "\nBad record length: %d for block #%"
- PRIu64 " (0x%" PRIx64").\n", savedata->siglen,
- savedata->blk, savedata->blk);
- return -1;
- }
- if (savedata->siglen &&
- read(in_fd, savedata->buf, savedata->siglen) !=
- savedata->siglen) {
- fprintf(stderr, "read error: %s from %s:%d: "
- "block %lld (0x%llx)\n",
- strerror(errno), __FUNCTION__, __LINE__,
- (unsigned long long)savedata->blk,
- (unsigned long long)savedata->blk);
- exit(-1);
- }
- if (first) {
- struct gfs2_sb bufsb;
-
- dummy_bh.b_data = (char *)&bufsb;
- memcpy(&bufsb, savedata->buf, sizeof(bufsb));
- gfs2_sb_in(&sbd.sd_sb, &dummy_bh);
- sbd1 = (struct gfs_sb *)&sbd.sd_sb;
- if (sbd1->sb_fs_format == GFS_FORMAT_FS &&
- sbd1->sb_header.mh_type ==
- GFS_METATYPE_SB &&
- sbd1->sb_header.mh_format ==
- GFS_FORMAT_SB &&
- sbd1->sb_multihost_format ==
- GFS_FORMAT_MULTI) {
- gfs1 = TRUE;
- } else if (check_sb(&sbd.sd_sb)) {
- fprintf(stderr,"Error: Invalid superblock data.\n");
- return -1;
- }
- sbd.bsize = sbd.sd_sb.sb_bsize;
- if (!printblocksonly) {
- last_fs_block =
- lseek(fd, 0, SEEK_END) / sbd.bsize;
- printf("There are %" PRIu64 " blocks of " \
- "%u bytes in the destination" \
- " file system.\n\n",
- last_fs_block, sbd.bsize);
- } else {
- printf("This is %s metadata\n", gfs1 ?
- "gfs (not gfs2)" : "gfs2");
- }
- first = 0;
- }
- bh = &dummy_bh;
- bh->b_data = savedata->buf;
- if (printblocksonly) {
- block = savedata->blk;
- if (block > highest_valid_block)
- highest_valid_block = block;
- if (printblocksonly > 1 && printblocksonly == block) {
- block_in_mem = block;
- display(0);
- return 0;
- } else if (printblocksonly == 1) {
- print_gfs2("%d (l=0x%x): ", blks_saved,
- savedata->siglen);
- display_block_type(TRUE);
- }
- } else {
- warm_fuzzy_stuff(savedata->blk, FALSE, FALSE);
- if (savedata->blk >= last_fs_block) {
- printf("\nOut of space on the destination "
- "device; quitting.\n");
- break;
- }
- if (lseek(fd, savedata->blk * sbd.bsize, SEEK_SET) !=
- savedata->blk * sbd.bsize) {
- fprintf(stderr, "bad seek: %s from %s:"
- "%d: block %lld (0x%llx)\n",
- strerror(errno), __FUNCTION__,
- __LINE__,
- (unsigned long long)savedata->blk,
- (unsigned long long)savedata->blk);
- exit(-1);
- }
- if (write(fd, savedata->buf, sbd.bsize) != sbd.bsize) {
- fprintf(stderr, "write error: %s from "
- "%s:%d: block %lld (0x%llx)\n",
- strerror(errno), __FUNCTION__,
- __LINE__,
- (unsigned long long)savedata->blk,
- (unsigned long long)savedata->blk);
- exit(-1);
- }
- writes++;
- }
- blks_saved++;
- }
- if (!printblocksonly)
- warm_fuzzy_stuff(savedata->blk, TRUE, FALSE);
- else
- printf("File system size: %lld (0x%llx) blocks, aka %sB\n",
- (unsigned long long)highest_valid_block,
- (unsigned long long)highest_valid_block,
- anthropomorphize(highest_valid_block * sbd.bsize));
- return 0;
-}
-
-static void complain(const char *complaint)
-{
- fprintf(stderr, "%s\n", complaint);
- die("Format is: \ngfs2_edit restoremeta <file to restore> "
- "<dest file system>\n");
-}
-
-void restoremeta(const char *in_fn, const char *out_device,
- uint64_t printblocksonly)
-{
- int in_fd, error;
-
- termlines = 0;
- if (!in_fn)
- complain("No source file specified.");
- if (!printblocksonly && !out_device)
- complain("No destination file system specified.");
- in_fd = open(in_fn, O_RDONLY);
- if (in_fd < 0)
- die("Can't open source file %s: %s\n",
- in_fn, strerror(errno));
-
- if (!printblocksonly) {
- sbd.device_fd = open(out_device, O_RDWR);
- if (sbd.device_fd < 0)
- die("Can't open destination file system %s: %s\n",
- out_device, strerror(errno));
- } else if (out_device) /* for printsavedmeta, the out_device is an
- optional block no */
- printblocksonly = check_keywords(out_device);
- savedata = malloc(sizeof(struct saved_metablock));
- if (!savedata)
- die("Can't allocate memory for the restore operation.\n");
-
- blks_saved = 0;
- error = restore_data(sbd.device_fd, in_fd, printblocksonly);
- printf("File %s %s %s.\n", in_fn,
- (printblocksonly ? "print" : "restore"),
- (error ? "error" : "successful"));
- free(savedata);
- close(in_fd);
- if (!printblocksonly)
- close(sbd.device_fd);
-
- exit(error);
-}
diff --git a/gfs2/fsck/FEATURES b/gfs2/fsck/FEATURES
deleted file mode 100644
index 8a63591..0000000
--- a/gfs2/fsck/FEATURES
+++ /dev/null
@@ -1,25 +0,0 @@
-This is a completely rewritten filesystem checker for GFS. Performance
-characteristics are significantly improved. The design follows the 5-pass
-fsck design found in "Fsck - The UNIX File System Check Program"
-by McKusick & Kowalkski (1994)
- - http://citeseer.ist.psu.edu/mckusick94fsck.html
-
-
-Line item list of supported features:
-
-1. Detects and replaces missing/bad root inode
-2. Detects and relinks unlinked inodes to l+f
- o If a file is zero length, it is not relinked to l+f - unless it
- has an extended attribute attached to it.
-3. Detects duplicate blocks and removes inodes containing them
-4. Detects bad blocks (block number out of range) and removes inodes
- containing them - Currently EAs that have blocks are removed but
- the inode containing them is left.
-5. Detects bad metadata headers and clears the structure
-6. Fixes bad resource group bitmaps
-7. Fixes incorrect resource group counts
-8. Creates l+f directory if missing
-9. Detects and removes duplicate '.' and '..' entries
-10. Creates '.' if missing
-11. Beginning of support for internationalization
-12. Checks extended attributes
diff --git a/gfs2/fsck/Makefile b/gfs2/fsck/Makefile
deleted file mode 100644
index 68ff24e..0000000
--- a/gfs2/fsck/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-TARGET= fsck.gfs2
-
-FORCESBINT=$(TARGET)
-
-all: depends ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= eattr.o \
- fs_recovery.o \
- hash.o \
- initialize.o \
- inode_hash.o \
- link.o \
- lost_n_found.o \
- main.o \
- metawalk.o \
- pass1.o \
- pass1b.o \
- pass1c.o \
- pass2.o \
- pass3.o \
- pass4.o \
- pass5.o \
- rgrepair.o \
- util.o
-
-CFLAGS += -D_FILE_OFFSET_BITS=64 -DHELPER_PROGRAM
-CFLAGS += -I${KERNEL_SRC}/fs/gfs2/ -I${KERNEL_SRC}/include/
-CFLAGS += -I$(S)/../include -I$(S)/../libgfs2
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L../libgfs2 -lgfs2
-LDFLAGS += -L${libdir}
-
-LDDEPS += ../libgfs2/libgfs2.a
-
-${TARGET}: $(OBJS) ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-depends:
- $(MAKE) -C ../libgfs2 all
-
-clean: generalclean
- rm -f test_block_list test_bitmap
-
-${TARGET}.pot: $(OBJS:.o=.c)
- xgettext -C -F --keyword=print_log --keyword=log_debug --keyword=log_info --keyword=_ \
- --keyword=log_notice --keyword=log_warn --keyword=log_err --keyword=log_crit \
- --keyword=log_debug --keyword=log_err --keyword=log_print -d - $(OBJS:.o=.c) > ${TARGET}.pot
-
--include $(OBJS:.o=.d)
diff --git a/gfs2/fsck/eattr.c b/gfs2/fsck/eattr.c
deleted file mode 100644
index 5d3e7cd..0000000
--- a/gfs2/fsck/eattr.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <stdint.h>
-#include <string.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "fsck.h"
-#include "metawalk.h"
-#include "eattr.h"
-
-int clear_eattr_entry (struct gfs2_inode *ip,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
-
- if(!ea_hdr->ea_name_len){
- /* Skip this entry for now */
- return 1;
- }
-
- if(!GFS2_EATYPE_VALID(ea_hdr->ea_type) &&
- ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
- /* Skip invalid entry */
- return 1;
- }
-
- if(ea_hdr->ea_num_ptrs){
- uint32_t avail_size;
- int max_ptrs;
-
- avail_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
- max_ptrs = (be32_to_cpu(ea_hdr->ea_data_len)+avail_size-1)/avail_size;
-
- if(max_ptrs > ea_hdr->ea_num_ptrs) {
- return 1;
- } else {
- log_debug( _(" Pointers Required: %d\n"
- " Pointers Reported: %d\n"),
- max_ptrs, ea_hdr->ea_num_ptrs);
- }
-
-
- }
- return 0;
-}
-
-int clear_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev, void *private)
-{
- uint64_t block = be64_to_cpu(*ea_data_ptr);
-
- return delete_eattr_leaf(ip, block, 0, &leaf_bh, private);
-}
-
-
-
diff --git a/gfs2/fsck/eattr.h b/gfs2/fsck/eattr.h
deleted file mode 100644
index f4264b0..0000000
--- a/gfs2/fsck/eattr.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _EATTR_H
-#define _EATTR_H
-
-int clear_eattr_indir(struct gfs2_inode *ip, uint64_t block, uint64_t parent,
- struct gfs2_buffer_head **bh, void *private);
-int clear_eattr_leaf(struct gfs2_inode *ip, uint64_t block, uint64_t parent,
- struct gfs2_buffer_head **bh, void *private);
-int clear_eattr_entry (struct gfs2_inode *ip,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private);
-int clear_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev, void *private);
-
-#endif /* _EATTR_H */
diff --git a/gfs2/fsck/fs_bits.h b/gfs2/fsck/fs_bits.h
deleted file mode 100644
index d4f262e..0000000
--- a/gfs2/fsck/fs_bits.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __FS_BITS_H__
-#define __FS_BITS_H__
-
-#include "libgfs2.h"
-#include "fsck.h"
-
-#define BFITNOENT (0xFFFFFFFF)
-
-struct fs_bitmap
-{
- uint32_t bi_offset; /* The offset in the buffer of the first byte */
- uint32_t bi_start; /* The position of the first byte in this block */
- uint32_t bi_len; /* The number of bytes in this block */
-};
-typedef struct fs_bitmap fs_bitmap_t;
-
-#endif /* __FS_BITS_H__ */
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
deleted file mode 100644
index 07c1552..0000000
--- a/gfs2/fsck/fs_recovery.c
+++ /dev/null
@@ -1,655 +0,0 @@
-#include <errno.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "fsck.h"
-#include "fs_recovery.h"
-#include "libgfs2.h"
-#include "util.h"
-
-#define JOURNAL_NAME_SIZE 16
-
-unsigned int sd_found_jblocks = 0, sd_replayed_jblocks = 0;
-unsigned int sd_found_metablocks = 0, sd_replayed_metablocks = 0;
-unsigned int sd_found_revokes = 0;
-osi_list_t sd_revoke_list;
-unsigned int sd_replay_tail;
-
-struct gfs2_revoke_replay {
- osi_list_t rr_list;
- uint64_t rr_blkno;
- unsigned int rr_where;
-};
-
-int gfs2_revoke_add(struct gfs2_sbd *sdp, uint64_t blkno, unsigned int where)
-{
- osi_list_t *tmp, *head = &sd_revoke_list;
- struct gfs2_revoke_replay *rr;
- int found = 0;
-
- osi_list_foreach(tmp, head) {
- rr = osi_list_entry(tmp, struct gfs2_revoke_replay, rr_list);
- if (rr->rr_blkno == blkno) {
- found = 1;
- break;
- }
- }
-
- if (found) {
- rr->rr_where = where;
- return 0;
- }
-
- rr = malloc(sizeof(struct gfs2_revoke_replay));
- if (!rr)
- return -ENOMEM;
-
- rr->rr_blkno = blkno;
- rr->rr_where = where;
- osi_list_add(&rr->rr_list, head);
- return 1;
-}
-
-int gfs2_revoke_check(struct gfs2_sbd *sdp, uint64_t blkno, unsigned int where)
-{
- osi_list_t *tmp;
- struct gfs2_revoke_replay *rr;
- int wrap, a, b;
- int found = 0;
-
- osi_list_foreach(tmp, &sd_revoke_list) {
- rr = osi_list_entry(tmp, struct gfs2_revoke_replay, rr_list);
- if (rr->rr_blkno == blkno) {
- found = 1;
- break;
- }
- }
-
- if (!found)
- return 0;
-
- wrap = (rr->rr_where < sd_replay_tail);
- a = (sd_replay_tail < where);
- b = (where < rr->rr_where);
- return (wrap) ? (a || b) : (a && b);
-}
-
-void gfs2_revoke_clean(struct gfs2_sbd *sdp)
-{
- osi_list_t *head = &sd_revoke_list;
- struct gfs2_revoke_replay *rr;
-
- while (!osi_list_empty(head)) {
- rr = osi_list_entry(head->next, struct gfs2_revoke_replay, rr_list);
- osi_list_del(&rr->rr_list);
- free(rr);
- }
-}
-
-static int buf_lo_scan_elements(struct gfs2_inode *ip, unsigned int start,
- struct gfs2_log_descriptor *ld, __be64 *ptr,
- int pass)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- unsigned int blks = be32_to_cpu(ld->ld_data1);
- struct gfs2_buffer_head *bh_log, *bh_ip;
- uint64_t blkno;
- int error = 0;
-
- if (pass != 1 || be32_to_cpu(ld->ld_type) != GFS2_LOG_DESC_METADATA)
- return 0;
-
- gfs2_replay_incr_blk(ip, &start);
-
- for (; blks; gfs2_replay_incr_blk(ip, &start), blks--) {
- uint32_t check_magic;
-
- sd_found_metablocks++;
-
- blkno = be64_to_cpu(*ptr);
- ptr++;
- if (gfs2_revoke_check(sdp, blkno, start))
- continue;
-
- error = gfs2_replay_read_block(ip, start, &bh_log);
- if (error)
- return error;
-
- log_info( _("Journal replay writing metadata block #"
- "%lld (0x%llx) for journal+0x%x\n"),
- (unsigned long long)blkno, (unsigned long long)blkno,
- start);
- bh_ip = bget(sdp, blkno);
- memcpy(bh_ip->b_data, bh_log->b_data, sdp->bsize);
-
- check_magic = ((struct gfs2_meta_header *)
- (bh_ip->b_data))->mh_magic;
- check_magic = be32_to_cpu(check_magic);
- if (check_magic != GFS2_MAGIC)
- error = -EIO;
- else
- bmodified(bh_ip);
-
- brelse(bh_log);
- brelse(bh_ip);
- if (error)
- break;
-
- sd_replayed_metablocks++;
- }
- return error;
-}
-
-static int revoke_lo_scan_elements(struct gfs2_inode *ip, unsigned int start,
- struct gfs2_log_descriptor *ld, __be64 *ptr,
- int pass)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- unsigned int blks = be32_to_cpu(ld->ld_length);
- unsigned int revokes = be32_to_cpu(ld->ld_data1);
- struct gfs2_buffer_head *bh;
- unsigned int offset;
- uint64_t blkno;
- int first = 1;
- int error;
-
- if (pass != 0 || be32_to_cpu(ld->ld_type) != GFS2_LOG_DESC_REVOKE)
- return 0;
-
- offset = sizeof(struct gfs2_log_descriptor);
-
- for (; blks; gfs2_replay_incr_blk(ip, &start), blks--) {
- error = gfs2_replay_read_block(ip, start, &bh);
- if (error)
- return error;
-
- if (!first) {
- if (gfs2_check_meta(bh, GFS2_METATYPE_LB))
- continue;
- }
- while (offset + sizeof(uint64_t) <= sdp->sd_sb.sb_bsize) {
- blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset));
- log_info( _("Journal replay processing revoke for "
- "block #%lld (0x%llx) for journal+0x%x\n"),
- (unsigned long long)blkno,
- (unsigned long long)blkno,
- start);
- error = gfs2_revoke_add(sdp, blkno, start);
- if (error < 0)
- return error;
- else if (error)
- sd_found_revokes++;
-
- if (!--revokes)
- break;
- offset += sizeof(uint64_t);
- }
-
- bmodified(bh);
- brelse(bh);
- offset = sizeof(struct gfs2_meta_header);
- first = 0;
- }
- return 0;
-}
-
-static int databuf_lo_scan_elements(struct gfs2_inode *ip, unsigned int start,
- struct gfs2_log_descriptor *ld,
- __be64 *ptr, int pass)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- unsigned int blks = be32_to_cpu(ld->ld_data1);
- struct gfs2_buffer_head *bh_log, *bh_ip;
- uint64_t blkno;
- uint64_t esc;
- int error = 0;
-
- if (pass != 1 || be32_to_cpu(ld->ld_type) != GFS2_LOG_DESC_JDATA)
- return 0;
-
- gfs2_replay_incr_blk(ip, &start);
- for (; blks; gfs2_replay_incr_blk(ip, &start), blks--) {
- blkno = be64_to_cpu(*ptr);
- ptr++;
- esc = be64_to_cpu(*ptr);
- ptr++;
-
- sd_found_jblocks++;
-
- if (gfs2_revoke_check(sdp, blkno, start))
- continue;
-
- error = gfs2_replay_read_block(ip, start, &bh_log);
- if (error)
- return error;
-
- log_info( _("Journal replay writing data block #%lld (0x%llx)"
- " for journal+0x%x\n"),
- (unsigned long long)blkno, (unsigned long long)blkno,
- start);
- bh_ip = bget(sdp, blkno);
- memcpy(bh_ip->b_data, bh_log->b_data, sdp->bsize);
-
- /* Unescape */
- if (esc) {
- __be32 *eptr = (__be32 *)bh_ip->b_data;
- *eptr = cpu_to_be32(GFS2_MAGIC);
- }
-
- brelse(bh_log);
- bmodified(bh_ip);
- brelse(bh_ip);
-
- sd_replayed_jblocks++;
- }
- return error;
-}
-
-/**
- * foreach_descriptor - go through the active part of the log
- * @ip: the journal incore inode
- * @start: the first log header in the active region
- * @end: the last log header (don't process the contents of this entry))
- *
- * Call a given function once for every log descriptor in the active
- * portion of the log.
- *
- * Returns: errno
- */
-
-static int foreach_descriptor(struct gfs2_inode *ip, unsigned int start,
- unsigned int end, int pass)
-{
- struct gfs2_buffer_head *bh;
- struct gfs2_log_descriptor *ld;
- int error = 0;
- uint32_t length;
- __be64 *ptr;
- unsigned int offset = sizeof(struct gfs2_log_descriptor);
- offset += sizeof(__be64) - 1;
- offset &= ~(sizeof(__be64) - 1);
-
- while (start != end) {
- uint32_t check_magic;
-
- error = gfs2_replay_read_block(ip, start, &bh);
- if (error)
- return error;
- check_magic = ((struct gfs2_meta_header *)
- (bh->b_data))->mh_magic;
- check_magic = be32_to_cpu(check_magic);
- if (check_magic != GFS2_MAGIC) {
- bmodified(bh);
- brelse(bh);
- return -EIO;
- }
- ld = (struct gfs2_log_descriptor *)bh->b_data;
- length = be32_to_cpu(ld->ld_length);
-
- if (be32_to_cpu(ld->ld_header.mh_type) == GFS2_METATYPE_LH) {
- struct gfs2_log_header lh;
-
- error = get_log_header(ip, start, &lh);
- if (!error) {
- gfs2_replay_incr_blk(ip, &start);
- bmodified(bh);
- brelse(bh);
- continue;
- }
- if (error == 1)
- error = -EIO;
- bmodified(bh);
- brelse(bh);
- return error;
- } else if (gfs2_check_meta(bh, GFS2_METATYPE_LD)) {
- bmodified(bh);
- brelse(bh);
- return -EIO;
- }
- ptr = (__be64 *)(bh->b_data + offset);
- error = databuf_lo_scan_elements(ip, start, ld, ptr, pass);
- if (error) {
- bmodified(bh);
- brelse(bh);
- return error;
- }
- error = buf_lo_scan_elements(ip, start, ld, ptr, pass);
- if (error) {
- bmodified(bh);
- brelse(bh);
- return error;
- }
- error = revoke_lo_scan_elements(ip, start, ld, ptr, pass);
- if (error) {
- bmodified(bh);
- brelse(bh);
- return error;
- }
-
- while (length--)
- gfs2_replay_incr_blk(ip, &start);
-
- bmodified(bh);
- brelse(bh);
- }
-
- return 0;
-}
-
-/**
- * fix_journal_seq_no - Fix log header sequencing problems
- * @ip: the journal incore inode
- */
-static int fix_journal_seq_no(struct gfs2_inode *ip)
-{
- int error = 0, wrapped = 0;
- uint32_t jd_blocks = ip->i_di.di_size / ip->i_sbd->sd_sb.sb_bsize;
- uint32_t blk;
- struct gfs2_log_header lh;
- uint64_t highest_seq = 0, lowest_seq = 0, prev_seq = 0;
- int new = 0;
- uint64_t dblock;
- uint32_t extlen;
- struct gfs2_buffer_head *bh;
-
- for (blk = 0; blk < jd_blocks; blk++) {
- error = get_log_header(ip, blk, &lh);
- if (error == 1) /* if not a log header */
- continue; /* just journal data--ignore it */
- if (!lowest_seq || lh.lh_sequence < lowest_seq)
- lowest_seq = lh.lh_sequence;
- if (!highest_seq || lh.lh_sequence > highest_seq)
- highest_seq = lh.lh_sequence;
- if (lh.lh_sequence > prev_seq) {
- prev_seq = lh.lh_sequence;
- continue;
- }
- /* The sequence number is not higher than the previous one,
- so it's either wrap-around or a sequencing problem. */
- if (!wrapped && lh.lh_sequence == lowest_seq) {
- wrapped = 1;
- prev_seq = lh.lh_sequence;
- continue;
- }
- log_err( _("Journal block %u (0x%x): sequence no. 0x%llx "
- "out of order.\n"), blk, blk, lh.lh_sequence);
- log_info( _("Low: 0x%llx, High: 0x%llx, Prev: 0x%llx\n"),
- (unsigned long long)lowest_seq,
- (unsigned long long)highest_seq,
- (unsigned long long)prev_seq);
- highest_seq++;
- lh.lh_sequence = highest_seq;
- prev_seq = lh.lh_sequence;
- log_warn( _("Renumbering it as 0x%llx\n"), lh.lh_sequence);
- block_map(ip, blk, &new, &dblock, &extlen, FALSE);
- bh = bread(ip->i_sbd, dblock);
- gfs2_log_header_out(&lh, bh);
- brelse(bh);
- }
- return 0;
-}
-
-/**
- * preen_is_safe - Can we safely preen the file system?
- *
- * If a preen option was specified (-a or -p) we're likely to have been
- * called from rc.sysinit. We need to determine whether this is shared
- * storage or not. If it's local storage (locking protocol==lock_nolock)
- * it's safe to preen the file system. If it's lock_dlm, it's likely
- * mounted by other nodes in the cluster, which is dangerous and therefore,
- * we should warn the user to run fsck.gfs2 manually when it's safe.
- */
-int preen_is_safe(struct gfs2_sbd *sdp, int preen, int force_check)
-{
- if (!preen) /* If preen was not specified */
- return 1; /* not called by rc.sysinit--we're okay to preen */
- if (force_check) /* If check was forced by the user? */
- return 1; /* user's responsibility--we're okay to preen */
- if(!memcmp(sdp->sd_sb.sb_lockproto + 5, "nolock", 6))
- return 1; /* local file system--preen is okay */
- return 0; /* might be mounted on another node--not guaranteed safe */
-}
-
-/**
- * gfs2_recover_journal - recovery a given journal
- * @ip: the journal incore inode
- * j: which journal to check
- * preen: Was preen (-a or -p) specified?
- * force_check: Was -f specified to force the check?
- * @was_clean: if the journal was originally clean, this is set to 1.
- * if the journal was dirty from the start, this is set to 0.
- *
- * Acquire the journal's lock, check to see if the journal is clean, and
- * do recovery if necessary.
- *
- * Returns: errno
- */
-
-static int gfs2_recover_journal(struct gfs2_inode *ip, int j, int preen,
- int force_check, int *was_clean)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_log_header head;
- unsigned int pass;
- int error;
-
- *was_clean = 0;
- log_info( _("jid=%u: Looking at journal...\n"), j);
-
- osi_list_init(&sd_revoke_list);
- error = gfs2_find_jhead(ip, &head);
- if (error) {
- if (opts.no) {
- log_err( _("Journal #%d (\"journal%d\") is corrupt.\n"
- "Not fixing it due to the -n option.\n"),
- j+1, j);
- goto out;
- }
- if (!preen_is_safe(sdp, preen, force_check)) {
- log_err(_("Journal #%d (\"journal%d\") is corrupt.\n"),
- j+1, j);
- log_err(_("I'm not fixing it because it may be unsafe:\n"
- "Locking protocol is not lock_nolock and "
- "the -a or -p option was specified.\n"));
- log_err(_("Please make sure no node has the file system "
- "mounted then rerun fsck.gfs2 manually "
- "without -a or -p.\n"));
- goto out;
- }
- if (!query( _("\nJournal #%d (\"journal%d\") is "
- "corrupt. Okay to repair it? (y/n)"),
- j+1, j)) {
- log_err( _("jid=%u: The journal was not repaired.\n"),
- j);
- goto out;
- }
- log_info( _("jid=%u: Repairing journal...\n"), j);
- error = fix_journal_seq_no(ip);
- if (error) {
- log_err( _("jid=%u: Unable to repair the bad "
- "journal.\n"), j);
- goto out;
- }
- error = gfs2_find_jhead(ip, &head);
- if (error) {
- log_err( _("jid=%u: Unable to fix the bad journal.\n"),
- j);
- goto out;
- }
- log_err( _("jid=%u: The journal was successfully fixed.\n"),
- j);
- }
- if (head.lh_flags & GFS2_LOG_HEAD_UNMOUNT) {
- log_info( _("jid=%u: Journal is clean.\n"), j);
- *was_clean = 1;
- return 0;
- }
- if (opts.no) {
- log_err(_("Journal #%d (\"journal%d\") is dirty; not replaying"
- " due to the -n option.\n"),
- j+1, j);
- goto out;
- }
- if (!preen_is_safe(sdp, preen, force_check)) {
- log_err( _("Journal #%d (\"journal%d\") is dirty.\n"), j+1, j);
- log_err( _("I'm not replaying it because it may be unsafe:\n"
- "Locking protocol is not lock_nolock and "
- "the -a or -p option was specified.\n"));
- log_err( _("Please make sure no node has the file system "
- "mounted then rerun fsck.gfs2 manually "
- "without -a or -p.\n"));
- error = FSCK_ERROR;
- goto out;
- }
- if (!query( _("\nJournal #%d (\"journal%d\") is dirty. Okay to "
- "replay it? (y/n)"), j+1, j))
- goto reinit;
-
- log_info( _("jid=%u: Replaying journal...\n"), j);
-
- sd_found_jblocks = sd_replayed_jblocks = 0;
- sd_found_metablocks = sd_replayed_metablocks = 0;
- sd_found_revokes = 0;
- sd_replay_tail = head.lh_tail;
- for (pass = 0; pass < 2; pass++) {
- error = foreach_descriptor(ip, head.lh_tail,
- head.lh_blkno, pass);
- if (error)
- goto out;
- }
- log_info( _("jid=%u: Found %u revoke tags\n"), j, sd_found_revokes);
- gfs2_revoke_clean(sdp);
- error = clean_journal(ip, &head);
- if (error)
- goto out;
- log_err( _("jid=%u: Replayed %u of %u journaled data blocks\n"),
- j, sd_replayed_jblocks, sd_found_jblocks);
- log_err( _("jid=%u: Replayed %u of %u metadata blocks\n"),
- j, sd_replayed_metablocks, sd_found_metablocks);
-
- /* Check for errors and give them the option to reinitialize the
- journal. */
-out:
- if (!error) {
- log_info( _("jid=%u: Done\n"), j);
- return 0;
- }
- log_info( _("jid=%u: Failed\n"), j);
-reinit:
- if (query( _("Do you want to clear the journal instead? (y/n)")))
- error = write_journal(sdp, j,
- sdp->md.journal[j]->i_di.di_size /
- sdp->sd_sb.sb_bsize);
- else
- log_err( _("jid=%u: journal not cleared.\n"), j);
- return error;
-}
-
-/*
- * replay_journals - replay the journals
- * sdp: the super block
- * preen: Was preen (-a or -p) specified?
- * force_check: Was -f specified to force the check?
- * @clean_journals - set to the number of clean journals we find
- *
- * There should be a flag to the fsck to enable/disable this
- * feature. The fsck falls back to clearing the journal if an
- * inconsistency is found, but only for the bad journal.
- *
- * Returns: 0 on success, -1 on failure
- */
-int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
- int *clean_journals)
-{
- int i;
- int clean = 0, dirty_journals = 0, error = 0, gave_msg = 0;
-
- *clean_journals = 0;
-
- sdp->jsize = GFS2_DEFAULT_JSIZE;
- /* Get master dinode */
- gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
-
- /* read in the journal index data */
- if (ji_update(sdp)){
- log_err( _("Unable to read in jindex inode.\n"));
- return -1;
- }
-
- for(i = 0; i < sdp->md.journals; i++) {
- if (!sdp->md.journal[i]) {
- log_err(_("File system journal \"journal%d\" is "
- "missing: pass1 will try to recreate it.\n"),
- i);
- continue;
- }
- if (!error) {
- uint64_t jsize = sdp->md.journal[i]->i_di.di_size /
- (1024 * 1024);
-
- if (sdp->jsize == GFS2_DEFAULT_JSIZE && jsize &&
- jsize != sdp->jsize)
- sdp->jsize = jsize;
- error = gfs2_recover_journal(sdp->md.journal[i], i,
- preen, force_check,
- &clean);
- if (!clean)
- dirty_journals++;
- if (!gave_msg && dirty_journals == 1 && !opts.no &&
- preen_is_safe(sdp, preen, force_check)) {
- gave_msg = 1;
- log_notice( _("Recovering journals (this may "
- "take a while)\n"));
- }
- *clean_journals += clean;
- }
- inode_put(&sdp->md.journal[i]);
- }
- inode_put(&sdp->md.jiinode);
- /* Sync the buffers to disk so we get a fresh start. */
- fsync(sdp->device_fd);
- return error;
-}
-
-/*
- * ji_update - fill in journal info
- * sdp: the incore superblock pointer
- *
- * Given the inode for the journal index, read in all
- * the journal inodes.
- *
- * Returns: 0 on success, -1 on failure
- */
-int ji_update(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *jip, *ip = sdp->md.jiinode;
- char journal_name[JOURNAL_NAME_SIZE];
- int i;
-
- if(!ip) {
- log_crit("Journal index inode not found.\n");
- return -1;
- }
-
- if(!(sdp->md.journal = calloc(ip->i_di.di_entries - 2, sizeof(struct gfs2_inode *)))) {
- log_err("Unable to allocate journal index\n");
- return -1;
- }
- sdp->md.journals = 0;
- memset(journal_name, 0, sizeof(*journal_name));
- for(i = 0; i < ip->i_di.di_entries - 2; i++) {
- /* FIXME check snprintf return code */
- snprintf(journal_name, JOURNAL_NAME_SIZE, "journal%u", i);
- gfs2_lookupi(sdp->md.jiinode, journal_name, strlen(journal_name),
- &jip);
- sdp->md.journal[i] = jip;
- }
- sdp->md.journals = ip->i_di.di_entries - 2;
- return 0;
-
-}
diff --git a/gfs2/fsck/fs_recovery.h b/gfs2/fsck/fs_recovery.h
deleted file mode 100644
index 1a7aae3..0000000
--- a/gfs2/fsck/fs_recovery.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __FS_RECOVERY_H__
-#define __FS_RECOVERY_H__
-
-#include "libgfs2.h"
-
-extern int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
- int *clean_journals);
-extern int preen_is_safe(struct gfs2_sbd *sdp, int preen, int force_check);
-
-extern int ji_update(struct gfs2_sbd *sdp);
-#endif /* __FS_RECOVERY_H__ */
-
diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
deleted file mode 100644
index b0e1efc..0000000
--- a/gfs2/fsck/fsck.h
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef _FSCK_H
-#define _FSCK_H
-
-#include "libgfs2.h"
-#include "osi_tree.h"
-
-#define FSCK_HASH_SHIFT (13)
-#define FSCK_HASH_SIZE (1 << FSCK_HASH_SHIFT)
-#define FSCK_HASH_MASK (FSCK_HASH_SIZE - 1)
-
-#define query(fmt, args...) fsck_query(fmt, ##args)
-
-/*
- * Exit codes used by fsck-type programs
- * Copied from e2fsck's e2fsck.h
- */
-#define FSCK_OK 0 /* No errors */
-#define FSCK_NONDESTRUCT 1 /* File system errors corrected */
-#define FSCK_REBOOT 2 /* System should be rebooted */
-#define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */
-#define FSCK_ERROR 8 /* Operational error */
-#define FSCK_USAGE 16 /* Usage or syntax error */
-#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
-#define FSCK_LIBRARY 128 /* Shared library error */
-
-#define BAD_POINTER_TOLERANCE 10 /* How many bad pointers is too many? */
-
-struct inode_info
-{
- struct osi_node node;
- uint64_t inode;
- uint16_t link_count; /* the number of links the inode
- * thinks it has */
- uint16_t counted_links; /* the number of links we've found */
-};
-
-struct dir_info
-{
- struct osi_node node;
- uint64_t dinode;
- uint64_t treewalk_parent;
- uint64_t dotdot_parent;
- uint8_t checked:1;
-
-};
-
-struct dir_status {
- uint8_t dotdir:1;
- uint8_t dotdotdir:1;
- uint8_t q;
- uint32_t entry_count;
-};
-
-struct duptree {
- struct osi_node node;
- int first_ref_found; /* Has the original reference been found? */
- int refs;
- uint64_t block;
- osi_list_t ref_inode_list; /* list of inodes referencing a dup block */
- osi_list_t ref_invinode_list; /* list of invalid inodes referencing */
-};
-
-enum dup_ref_type {
- ref_as_data = 0,
- ref_as_meta = 1,
- ref_as_ea = 2,
- ref_types = 3
-};
-
-struct inode_with_dups {
- osi_list_t list;
- uint64_t block_no;
- int dup_count;
- int reftypecount[ref_types];
- uint64_t parent;
- char *name;
-};
-
-enum rgindex_trust_level { /* how far can we trust our RG index? */
- blind_faith = 0, /* We'd like to trust the rgindex. We always used to
- before bz 179069. This should cover most cases. */
- ye_of_little_faith = 1, /* The rindex seems trustworthy but there's
- rg damage that need to be fixed. */
- open_minded = 2, /* At least 1 RG is corrupt. Try to calculate what it
- should be, in a perfect world where our RGs are all
- on even boundaries. Blue sky. Chirping birds. */
- distrust = 3 /* The world isn't perfect, our RGs are not on nice neat
- boundaries. The fs must have been messed with by
- gfs2_grow or something. Count the RGs by hand. */
-};
-
-extern struct gfs2_inode *fsck_load_inode(struct gfs2_sbd *sbp, uint64_t block);
-extern struct gfs2_inode *fsck_inode_get(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *bh);
-extern void fsck_inode_put(struct gfs2_inode **ip);
-
-extern int initialize(struct gfs2_sbd *sbp, int force_check, int preen,
- int *all_clean);
-extern void destroy(struct gfs2_sbd *sbp);
-extern int pass1(struct gfs2_sbd *sbp);
-extern int pass1b(struct gfs2_sbd *sbp);
-extern int pass1c(struct gfs2_sbd *sbp);
-extern int pass2(struct gfs2_sbd *sbp);
-extern int pass3(struct gfs2_sbd *sbp);
-extern int pass4(struct gfs2_sbd *sbp);
-extern int pass5(struct gfs2_sbd *sbp);
-extern int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count,
- int *sane);
-extern void gfs2_dup_free(void);
-extern int fsck_query(const char *format, ...)
- __attribute__((format(printf,1,2)));
-extern struct dir_info *dirtree_find(uint64_t block);
-extern void dup_delete(struct duptree *b);
-extern void dirtree_delete(struct dir_info *b);
-
-/* FIXME: Hack to get this going for pass2 - this should be pulled out
- * of pass1 and put somewhere else... */
-struct dir_info *dirtree_insert(uint64_t dblock);
-
-extern struct gfs2_options opts;
-extern struct gfs2_inode *lf_dip; /* Lost and found directory inode */
-extern struct gfs2_bmap *bl;
-extern uint64_t last_fs_block, last_reported_block;
-extern int64_t last_reported_fblock;
-extern int skip_this_pass, fsck_abort;
-extern int errors_found, errors_corrected;
-extern uint64_t last_data_block;
-extern uint64_t first_data_block;
-extern struct osi_root dup_blocks;
-extern struct osi_root dirtree;
-extern struct osi_root inodetree;
-extern int dups_found; /* How many duplicate references have we found? */
-extern int dups_found_first; /* How many duplicates have we found the original
- reference for? */
-#endif /* _FSCK_H */
diff --git a/gfs2/fsck/hash.c b/gfs2/fsck/hash.c
deleted file mode 100644
index 9f09111..0000000
--- a/gfs2/fsck/hash.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* This is the same hash algorithm used by the glocks in gfs */
-
-#include <stdint.h>
-#include <unistd.h>
-#include "libgfs2.h"
-#include "hash.h"
-#include "osi_list.h"
-
-/**
- * hash_more_internal - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- * @hash: the hash from a previous call
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * This is the 32-bit FNV-1a hash from:
- * http://www.isthe.com/chongo/tech/comp/fnv/
- *
- * Hash guts
- *
- * Returns: the hash
- */
-
-static __inline__ uint32_t
-hash_more_internal(const void *data, unsigned int len, uint32_t hash)
-{
- unsigned char *p = (unsigned char *) data;
- unsigned char *e = p + len;
- uint32_t h = hash;
-
- while (p < e) {
- h ^= (uint32_t) (*p++);
- h *= 0x01000193;
- }
-
- return h;
-}
-
-/**
- * fsck_hash - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * This is the 32-bit FNV-1a hash from:
- * http://www.isthe.com/chongo/tech/comp/fnv/
- *
- * Returns: the hash
- */
-
-uint32_t
-fsck_hash(const void *data, unsigned int len)
-{
- uint32_t h = 0x811C9DC5;
- h = hash_more_internal(data, len, h);
- return h;
-}
-
-/**
- * fsck_hash_more - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- * @hash: the hash from a previous call
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * This is the 32-bit FNV-1a hash from:
- * http://www.isthe.com/chongo/tech/comp/fnv/
- *
- * This version let's you hash together discontinuous regions.
- * For example, to compute the combined hash of the memory in
- * (data1, len1), (data2, len2), and (data3, len3) you:
- *
- * h = fsck_hash(data1, len1);
- * h = fsck_hash_more(data2, len2, h);
- * h = fsck_hash_more(data3, len3, h);
- *
- * Returns: the hash
- */
-
-uint32_t
-fsck_hash_more(const void *data, unsigned int len, uint32_t hash)
-{
- uint32_t h;
- h = hash_more_internal(data, len, hash);
- return h;
-}
-
-
diff --git a/gfs2/fsck/hash.h b/gfs2/fsck/hash.h
deleted file mode 100644
index d5fe8e9..0000000
--- a/gfs2/fsck/hash.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _HASH_H
-#define _HASH_H
-
-uint32_t fsck_hash(const void *data, unsigned int len);
-uint32_t fsck_hash_more(const void *data, unsigned int len, uint32_t hash);
-
-#endif /* _HASH_H */
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
deleted file mode 100644
index 14cc9f6..0000000
--- a/gfs2/fsck/initialize.c
+++ /dev/null
@@ -1,1163 +0,0 @@
-#include <stdio.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <libintl.h>
-#include <errno.h>
-
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "fsck.h"
-#include "util.h"
-#include "fs_recovery.h"
-#include "metawalk.h"
-#include "inode_hash.h"
-
-#define CLEAR_POINTER(x) \
- if(x) { \
- free(x); \
- x = NULL; \
- }
-#define HIGHEST_BLOCK 0xffffffffffffffff
-
-static int was_mounted_ro = 0;
-static uint64_t possible_root = HIGHEST_BLOCK;
-static struct master_dir fix_md;
-
-/**
- * block_mounters
- *
- * Change the lock protocol so nobody can mount the fs
- *
- */
-static int block_mounters(struct gfs2_sbd *sbp, int block_em)
-{
- if(block_em) {
- /* verify it starts with lock_ */
- if(!strncmp(sbp->sd_sb.sb_lockproto, "lock_", 5)) {
- /* Change lock_ to fsck_ */
- memcpy(sbp->sd_sb.sb_lockproto, "fsck_", 5);
- }
- /* FIXME: Need to do other verification in the else
- * case */
- } else {
- /* verify it starts with fsck_ */
- /* verify it starts with lock_ */
- if(!strncmp(sbp->sd_sb.sb_lockproto, "fsck_", 5)) {
- /* Change fsck_ to lock_ */
- memcpy(sbp->sd_sb.sb_lockproto, "lock_", 5);
- }
- }
-
- if(write_sb(sbp)) {
- stack;
- return -1;
- }
- return 0;
-}
-
-void gfs2_dup_free(void)
-{
- struct osi_node *n;
- struct duptree *dt;
-
- while ((n = osi_first(&dup_blocks))) {
- dt = (struct duptree *)n;
- dup_delete(dt);
- }
-}
-
-static void gfs2_dirtree_free(void)
-{
- struct osi_node *n;
- struct dir_info *dt;
-
- while ((n = osi_first(&dirtree))) {
- dt = (struct dir_info *)n;
- dirtree_delete(dt);
- }
-}
-
-static void gfs2_inodetree_free(void)
-{
- struct osi_node *n;
- struct inode_info *dt;
-
- while ((n = osi_first(&inodetree))) {
- dt = (struct inode_info *)n;
- inodetree_delete(dt);
- }
-}
-
-/*
- * empty_super_block - free all structures in the super block
- * sdp: the in-core super block
- *
- * This function frees all allocated structures within the
- * super block. It does not free the super block itself.
- *
- * Returns: Nothing
- */
-static void empty_super_block(struct gfs2_sbd *sdp)
-{
- log_info( _("Freeing buffers.\n"));
- gfs2_rgrp_free(&sdp->rglist);
-
- if (bl)
- gfs2_bmap_destroy(sdp, bl);
- gfs2_inodetree_free();
- gfs2_dirtree_free();
- gfs2_dup_free();
-}
-
-
-/**
- * set_block_ranges
- * @sdp: superblock
- *
- * Uses info in rgrps and jindex to determine boundaries of the
- * file system.
- *
- * Returns: 0 on success, -1 on failure
- */
-static int set_block_ranges(struct gfs2_sbd *sdp)
-{
-
- struct rgrp_list *rgd;
- struct gfs2_rindex *ri;
- osi_list_t *tmp;
- char buf[sdp->sd_sb.sb_bsize];
- uint64_t rmax = 0;
- uint64_t rmin = 0;
- int error;
-
- log_info( _("Setting block ranges...\n"));
-
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next)
- {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- ri = &rgd->ri;
- if (ri->ri_data0 + ri->ri_data - 1 > rmax)
- rmax = ri->ri_data0 + ri->ri_data - 1;
- if (!rmin || ri->ri_data0 < rmin)
- rmin = ri->ri_data0;
- }
-
- last_fs_block = rmax;
- if (last_fs_block > 0xffffffff && sizeof(unsigned long) <= 4) {
- log_crit( _("This file system is too big for this computer to handle.\n"));
- log_crit( _("Last fs block = 0x%llx, but sizeof(unsigned long) is %zu bytes.\n"),
- (unsigned long long)last_fs_block,
- sizeof(unsigned long));
- goto fail;
- }
-
- last_data_block = rmax;
- first_data_block = rmin;
-
- if(fsck_lseek(sdp->device_fd, (last_fs_block * sdp->sd_sb.sb_bsize))){
- log_crit( _("Can't seek to last block in file system: %"
- PRIu64" (0x%" PRIx64 ")\n"), last_fs_block, last_fs_block);
- goto fail;
- }
-
- memset(buf, 0, sdp->sd_sb.sb_bsize);
- error = read(sdp->device_fd, buf, sdp->sd_sb.sb_bsize);
- if (error != sdp->sd_sb.sb_bsize){
- log_crit( _("Can't read last block in file system (error %u), "
- "last_fs_block: %"PRIu64" (0x%" PRIx64 ")\n"), error,
- last_fs_block, last_fs_block);
- goto fail;
- }
-
- return 0;
-
- fail:
- return -1;
-}
-
-/**
- * check_rgrp_integrity - verify a rgrp free block count against the bitmap
- */
-static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
- int *fixit, int *this_rg_fixed,
- int *this_rg_bad)
-{
- uint32_t rg_free, rg_reclaimed;
- int rgb, x, y, off, bytes_to_check, total_bytes_to_check;
- unsigned int state;
-
- rg_free = rg_reclaimed = 0;
- total_bytes_to_check = rgd->ri.ri_bitbytes;
- *this_rg_fixed = *this_rg_bad = 0;
-
- for (rgb = 0; rgb < rgd->ri.ri_length; rgb++){
- /* Count up the free blocks in the bitmap */
- off = (rgb) ? sizeof(struct gfs2_meta_header) :
- sizeof(struct gfs2_rgrp);
- if (total_bytes_to_check <= sdp->bsize - off)
- bytes_to_check = total_bytes_to_check;
- else
- bytes_to_check = sdp->bsize - off;
- total_bytes_to_check -= bytes_to_check;
- for (x = 0; x < bytes_to_check; x++) {
- unsigned char *byte;
-
- byte = (unsigned char *)&rgd->bh[rgb]->b_data[off + x];
- if (*byte == 0x55)
- continue;
- if (*byte == 0x00) {
- rg_free += GFS2_NBBY;
- continue;
- }
- for (y = 0; y < GFS2_NBBY; y++) {
- state = (*byte >>
- (GFS2_BIT_SIZE * y)) & GFS2_BIT_MASK;
- if (state == GFS2_BLKST_USED)
- continue;
- if (state == GFS2_BLKST_DINODE)
- continue;
- if (state == GFS2_BLKST_FREE) {
- rg_free++;
- continue;
- }
- /* GFS2_BLKST_UNLINKED */
- *this_rg_bad = 1;
- if (!(*fixit)) {
- if (query(_("Okay to reclaim unlinked "
- "inodes? (y/n)")))
- *fixit = 1;
- }
- if (!(*fixit))
- continue;
- *byte &= ~(GFS2_BIT_MASK <<
- (GFS2_BIT_SIZE * y));
- bmodified(rgd->bh[rgb]);
- rg_reclaimed++;
- rg_free++;
- *this_rg_fixed = 1;
- }
- }
- }
- if (rgd->rg.rg_free != rg_free) {
- *this_rg_bad = 1;
- log_err( _("Error: resource group %lld (0x%llx): "
- "free space (%d) does not match bitmap (%d)\n"),
- (unsigned long long)rgd->ri.ri_addr,
- (unsigned long long)rgd->ri.ri_addr,
- rgd->rg.rg_free, rg_free);
- if (rg_reclaimed)
- log_err( _("(%d blocks were reclaimed)\n"),
- rg_reclaimed);
- if (query( _("Fix the rgrp free blocks count? (y/n)"))) {
- rgd->rg.rg_free = rg_free;
- gfs2_rgrp_out(&rgd->rg, rgd->bh[0]);
- *this_rg_fixed = 1;
- log_err( _("The rgrp was fixed.\n"));
- } else
- log_err( _("The rgrp was not fixed.\n"));
- }
- /*
- else {
- log_debug( _("Resource group %lld (0x%llx) free space "
- "is consistent: free: %d reclaimed: %d\n"),
- (unsigned long long)rgd->ri.ri_addr,
- (unsigned long long)rgd->ri.ri_addr,
- rg_free, rg_reclaimed);
- }*/
-}
-
-/**
- * check_rgrps_integrity - verify rgrp consistency
- *
- * Returns: 0 on success, 1 if errors were detected
- */
-static int check_rgrps_integrity(struct gfs2_sbd *sdp)
-{
- int rgs_good = 0, rgs_bad = 0, rgs_fixed = 0;
- int was_bad = 0, was_fixed = 0, error = 0;
- osi_list_t *tmp;
- struct rgrp_list *rgd;
- int reclaim_unlinked = 0;
-
- log_info( _("Checking the integrity of all resource groups.\n"));
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
- if (fsck_abort)
- return 0;
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- check_rgrp_integrity(sdp, rgd, &reclaim_unlinked,
- &was_fixed, &was_bad);
- if (was_fixed)
- rgs_fixed++;
- if (was_bad) {
- error = 1;
- rgs_bad++;
- } else
- rgs_good++;
- }
- if (rgs_bad)
- log_err( _("RGs: Consistent: %d Inconsistent: %d Fixed: %d"
- " Total: %d\n"),
- rgs_good, rgs_bad, rgs_fixed, rgs_good + rgs_bad);
- return error;
-}
-
-/**
- * rebuild_master - rebuild a destroyed master directory
- */
-static int rebuild_master(struct gfs2_sbd *sdp)
-{
- struct gfs2_inum inum;
- struct gfs2_buffer_head *bh;
-
- log_err(_("The system master directory seems to be destroyed.\n"));
- if (!query(_("Okay to rebuild it? (y/n)"))) {
- log_err(_("System master not rebuilt; aborting.\n"));
- return -1;
- }
- log_err(_("Trying to rebuild the master directory.\n"));
- inum.no_formal_ino = sdp->md.next_inum++;
- inum.no_addr = sdp->sd_sb.sb_master_dir.no_addr;
- bh = init_dinode(sdp, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, &inum);
- sdp->master_dir = inode_get(sdp, bh);
- sdp->master_dir->bh_owned = 1;
-
- if (fix_md.jiinode) {
- inum.no_formal_ino = sdp->md.next_inum++;
- inum.no_addr = fix_md.jiinode->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "jindex", 6, &inum,
- IF2DT(S_IFDIR | 0700));
- sdp->master_dir->i_di.di_nlink++;
- } else {
- build_jindex(sdp);
- }
-
- if (fix_md.pinode) {
- inum.no_formal_ino = sdp->md.next_inum++;
- inum.no_addr = fix_md.pinode->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "per_node", 8, &inum,
- IF2DT(S_IFDIR | 0700));
- sdp->master_dir->i_di.di_nlink++;
- } else {
- build_per_node(sdp);
- }
-
- if (fix_md.inum) {
- inum.no_formal_ino = sdp->md.next_inum++;
- inum.no_addr = fix_md.inum->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "inum", 4, &inum,
- IF2DT(S_IFREG | 0600));
- } else {
- build_inum(sdp);
- }
-
- if (fix_md.statfs) {
- inum.no_formal_ino = sdp->md.next_inum++;
- inum.no_addr = fix_md.statfs->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "statfs", 6, &inum,
- IF2DT(S_IFREG | 0600));
- } else {
- build_statfs(sdp);
- }
-
- if (fix_md.riinode) {
- inum.no_formal_ino = sdp->md.next_inum++;
- inum.no_addr = fix_md.riinode->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "rindex", 6, &inum,
- IF2DT(S_IFREG | 0600));
- } else {
- build_rindex(sdp);
- }
-
- if (fix_md.qinode) {
- inum.no_formal_ino = sdp->md.next_inum++;
- inum.no_addr = fix_md.qinode->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "quota", 5, &inum,
- IF2DT(S_IFREG | 0600));
- } else {
- build_quota(sdp);
- }
-
- log_err(_("Master directory rebuilt.\n"));
- inode_put(&sdp->master_dir);
- return 0;
-}
-
-/**
- * init_system_inodes
- *
- * Returns: 0 on success, -1 on failure
- */
-static int init_system_inodes(struct gfs2_sbd *sdp)
-{
- uint64_t inumbuf;
- char *buf;
- struct gfs2_statfs_change sc;
- int rgcount, sane = 1;
- enum rgindex_trust_level trust_lvl;
- uint64_t addl_mem_needed;
-
- /*******************************************************************
- ****************** Initialize important inodes ******************
- *******************************************************************/
-
- log_info( _("Initializing special inodes...\n"));
-
- /* Get root dinode */
- sdp->md.rooti = inode_read(sdp, sdp->sd_sb.sb_root_dir.no_addr);
-
- gfs2_lookupi(sdp->master_dir, "rindex", 6, &sdp->md.riinode);
- if (!sdp->md.riinode) {
- if (query( _("The gfs2 system rindex inode is missing. "
- "Okay to rebuild it? (y/n) ")))
- build_rindex(sdp);
- }
-
- /*******************************************************************
- ****************** Fill in journal information ******************
- *******************************************************************/
-
- /* rgrepair requires the journals be read in in order to distinguish
- "real" rgrps from rgrps that are just copies left in journals. */
- gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
- if (!sdp->md.jiinode) {
- if (query( _("The gfs2 system jindex inode is missing. "
- "Okay to rebuild it? (y/n) ")))
- build_jindex(sdp);
- }
-
- /* read in the ji data */
- if (ji_update(sdp)){
- log_err( _("Unable to read in jindex inode.\n"));
- return -1;
- }
-
- /*******************************************************************
- ******** Validate and read in resource group information ********
- *******************************************************************/
- log_warn( _("Validating Resource Group index.\n"));
- for (trust_lvl = blind_faith; trust_lvl <= distrust; trust_lvl++) {
- log_warn( _("Level %d RG check.\n"), trust_lvl + 1);
- if ((rg_repair(sdp, trust_lvl, &rgcount, &sane) == 0) &&
- (ri_update(sdp, 0, &rgcount, &sane) == 0)) {
- log_warn( _("(level %d passed)\n"), trust_lvl + 1);
- break;
- }
- else
- log_err( _("(level %d failed)\n"), trust_lvl + 1);
- }
- if (trust_lvl > distrust) {
- log_err( _("RG recovery impossible; I can't fix this file system.\n"));
- return -1;
- }
- log_info( _("%u resource groups found.\n"), rgcount);
-
- check_rgrps_integrity(sdp);
-
- /*******************************************************************
- ***************** Initialize more system inodes *****************
- *******************************************************************/
- /* Look for "inum" entry in master dinode */
- gfs2_lookupi(sdp->master_dir, "inum", 4, &sdp->md.inum);
- if (!sdp->md.inum) {
- if (query( _("The gfs2 system inum inode is missing. "
- "Okay to rebuild it? (y/n) ")))
- build_inum(sdp);
- }
- /* Read inum entry into buffer */
- gfs2_readi(sdp->md.inum, &inumbuf, 0, sdp->md.inum->i_di.di_size);
- /* call gfs2_inum_range_in() to retrieve range */
- sdp->md.next_inum = be64_to_cpu(inumbuf);
-
- gfs2_lookupi(sdp->master_dir, "statfs", 6, &sdp->md.statfs);
- if (!sdp->md.statfs) {
- if (query( _("The gfs2 system statfs inode is missing. "
- "Okay to rebuild it? (y/n) ")))
- build_statfs(sdp);
- else {
- log_err( _("fsck.gfs2 cannot continue without a "
- "valid statfs file; aborting.\n"));
- return FSCK_ERROR;
- }
- }
- buf = malloc(sdp->md.statfs->i_di.di_size);
- // FIXME: handle failed malloc
- gfs2_readi(sdp->md.statfs, buf, 0, sdp->md.statfs->i_di.di_size);
- /* call gfs2_inum_range_in() to retrieve range */
- gfs2_statfs_change_in(&sc, buf);
- free(buf);
-
- gfs2_lookupi(sdp->master_dir, "quota", 5, &sdp->md.qinode);
- if (!sdp->md.qinode) {
- if (query( _("The gfs2 system quota inode is missing. "
- "Okay to rebuild it? (y/n) ")))
- build_quota(sdp);
- }
-
- gfs2_lookupi(sdp->master_dir, "per_node", 8, &sdp->md.pinode);
- if (!sdp->md.pinode) {
- if (query( _("The gfs2 system per_node directory inode is "
- "missing. Okay to rebuild it? (y/n) ")))
- build_per_node(sdp);
- }
-
- /* FIXME fill in per_node structure */
- /*******************************************************************
- ******* Now, set boundary fields in the super block *************
- *******************************************************************/
- if(set_block_ranges(sdp)){
- log_err( _("Unable to determine the boundaries of the"
- " file system.\n"));
- goto fail;
- }
-
- bl = gfs2_bmap_create(sdp, last_fs_block+1, &addl_mem_needed);
- if (!bl) {
- log_crit( _("This system doesn't have enough memory + swap space to fsck this file system.\n"));
- log_crit( _("Additional memory needed is approximately: %lluMB\n"),
- (unsigned long long)(addl_mem_needed / 1048576ULL));
- log_crit( _("Please increase your swap space by that amount and run gfs2_fsck again.\n"));
- goto fail;
- }
- return 0;
- fail:
- empty_super_block(sdp);
-
- return -1;
-}
-
-static int get_lockproto_table(struct gfs2_sbd *sdp)
-{
- FILE *fp;
- char line[PATH_MAX], *p, *p2;
- char fsname[PATH_MAX];
-
- memset(sdp->lockproto, 0, sizeof(sdp->lockproto));
- memset(sdp->locktable, 0, sizeof(sdp->locktable));
- fp = fopen("/etc/cluster/cluster.conf", "rt");
- if (!fp) {
- /* no cluster.conf; must be a stand-alone file system */
- strcpy(sdp->lockproto, "lock_nolock");
- log_warn(_("Lock protocol determined to be: lock_nolock\n"));
- log_warn(_("Stand-alone file system: No need for a lock "
- "table.\n"));
- return 0;
- }
- /* We found a cluster.conf so assume it's a clustered file system */
- log_warn(_("Lock protocol assumed to be: " GFS2_DEFAULT_LOCKPROTO
- "\n"));
- strcpy(sdp->lockproto, GFS2_DEFAULT_LOCKPROTO);
- while (fgets(line, sizeof(line) - 1, fp)) {
- p = strstr(line,"<cluster name=");
- if (p) {
- p += 15;
- p2 = strchr(p,'"');
- strncpy(sdp->locktable, p, p2 - p);
- break;
- }
- }
- if (sdp->locktable[0] == '\0') {
- log_err(_("Error: Unable to determine cluster name from "
- "/etc/cluster.conf\n"));
- } else {
- memset(fsname, 0, sizeof(fsname));
- p = strrchr(opts.device, '/');
- if (p) {
- p++;
- strncpy(fsname, p, sizeof(fsname));
- } else
- strcpy(fsname, "repaired");
- strcat(sdp->locktable, ":");
- strcat(sdp->locktable, fsname);
- log_warn(_("Lock table determined to be: %s\n"),
- sdp->locktable);
- }
- fclose(fp);
- return 0;
-}
-
-/**
- * is_journal_copy - Is this a "real" dinode or a copy inside a journal?
- * A real dinode will be located at the block number in its no_addr.
- * A journal-copy will be at a different block (inside the journal).
- */
-static int is_journal_copy(struct gfs2_inode *ip, struct gfs2_buffer_head *bh)
-{
- if (ip->i_di.di_num.no_addr == bh->b_blocknr)
- return 0;
- return 1; /* journal copy */
-}
-
-/**
- * peruse_system_dinode - process a system dinode
- *
- * This function looks at a system dinode and tries to figure out which
- * dinode it is: statfs, inum, per_node, master, etc. Some of them we
- * can deduce from the contents. For example, di_size will be a multiple
- * of 96 for the rindex. di_size will be 8 for inum, 24 for statfs, etc.
- * the per_node directory will have a ".." entry that will lead us to
- * the master dinode if it's been destroyed.
- */
-static void peruse_system_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
- struct gfs2_buffer_head *bh)
-{
- struct gfs2_inode *ip, *child_ip;
- struct gfs2_inum inum;
- int error;
-
- if (di->di_num.no_formal_ino == 2) {
- if (sdp->sd_sb.sb_master_dir.no_addr)
- return;
- log_warn(_("Found system master directory at: 0x%llx.\n"),
- di->di_num.no_addr);
- sdp->sd_sb.sb_master_dir.no_addr = di->di_num.no_addr;
- return;
- }
- ip = inode_read(sdp, di->di_num.no_addr);
- if (di->di_num.no_formal_ino == 3) {
- if (fix_md.jiinode || is_journal_copy(ip, bh))
- return;
- log_warn(_("Found system jindex file at: 0x%llx\n"),
- di->di_num.no_addr);
- fix_md.jiinode = ip;
- } else if (S_ISDIR(di->di_mode)) {
- /* Check for a jindex dir entry. Only one system dir has a
- jindex: master */
- gfs2_lookupi(ip, "jindex", 6, &child_ip);
- if (child_ip) {
- if (fix_md.jiinode || is_journal_copy(ip, bh))
- return;
- fix_md.jiinode = child_ip;
- sdp->sd_sb.sb_master_dir.no_addr = di->di_num.no_addr;
- log_warn(_("Found system master directory at: "
- "0x%llx\n"), di->di_num.no_addr);
- return;
- }
-
- /* Check for a statfs_change0 dir entry. Only one system dir
- has a statfs_change: per_node, and its .. will be master. */
- gfs2_lookupi(ip, "statfs_change0", 14, &child_ip);
- if (child_ip) {
- if (fix_md.pinode || is_journal_copy(ip, bh))
- return;
- log_warn(_("Found system per_node directory at: "
- "0x%llx\n"), ip->i_di.di_num.no_addr);
- fix_md.pinode = ip;
- error = dir_search(ip, "..", 2, NULL, &inum);
- if (!error && inum.no_addr) {
- sdp->sd_sb.sb_master_dir.no_addr =
- inum.no_addr;
- log_warn(_("From per_node\'s \'..\' I "
- "backtracked the master directory "
- "to: 0x%llx\n"), inum.no_addr);
- }
- return;
- }
- log_debug(_("Unknown system directory at block 0x%llx\n"),
- di->di_num.no_addr);
- inode_put(&ip);
- } else if (di->di_size == 8) {
- if (fix_md.inum || is_journal_copy(ip, bh))
- return;
- fix_md.inum = ip;
- log_warn(_("Found system inum file at: 0x%llx\n"),
- di->di_num.no_addr);
- } else if (di->di_size == 24) {
- if (fix_md.statfs || is_journal_copy(ip, bh))
- return;
- fix_md.statfs = ip;
- log_warn(_("Found system statfs file at: 0x%llx\n"),
- di->di_num.no_addr);
- } else if ((di->di_size % 96) == 0) {
- if (fix_md.riinode || is_journal_copy(ip, bh))
- return;
- fix_md.riinode = ip;
- log_warn(_("Found system rindex file at: 0x%llx\n"),
- di->di_num.no_addr);
- } else if (!fix_md.qinode && di->di_size >= 176 &&
- di->di_num.no_formal_ino >= 12 &&
- di->di_num.no_formal_ino <= 100) {
- if (is_journal_copy(ip, bh))
- return;
- fix_md.qinode = ip;
- log_warn(_("Found system quota file at: 0x%llx\n"),
- di->di_num.no_addr);
- }
-}
-
-/**
- * peruse_user_dinode - process a user dinode trying to find the root directory
- *
- */
-static void peruse_user_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
- struct gfs2_buffer_head *bh)
-{
- struct gfs2_inode *ip, *parent_ip;
- struct gfs2_inum inum;
- int error;
-
- if (sdp->sd_sb.sb_root_dir.no_addr) /* if we know the root dinode */
- return; /* we don't need to find the root */
- if (!S_ISDIR(di->di_mode)) /* if this isn't a directory */
- return; /* it can't lead us to the root anyway */
-
- if (di->di_num.no_formal_ino == 1) {
- struct gfs2_buffer_head *root_bh;
-
- if (di->di_num.no_addr == bh->b_blocknr) {
- log_warn(_("Found the root directory at: 0x%llx.\n"),
- di->di_num.no_addr);
- sdp->sd_sb.sb_root_dir.no_addr = di->di_num.no_addr;
- return;
- }
- log_warn(_("The root dinode should be at block 0x%llx but it "
- "seems to be destroyed.\n"),
- (unsigned long long)di->di_num.no_addr);
- log_warn(_("Found a copy of the root directory in a journal "
- "at block: 0x%llx.\n"),
- (unsigned long long)bh->b_blocknr);
- if (!query(_("Do you want to replace the root dinode from the "
- "copy? (y/n)"))) {
- log_err(_("Damaged root dinode not fixed.\n"));
- return;
- }
- root_bh = bread(sdp, di->di_num.no_addr);
- memcpy(root_bh->b_data, bh->b_data, sdp->bsize);
- bmodified(root_bh);
- brelse(root_bh);
- log_warn(_("Root directory copied from the journal.\n"));
- return;
- }
- ip = inode_read(sdp, di->di_num.no_addr);
- while (ip) {
- gfs2_lookupi(ip, "..", 2, &parent_ip);
- if (parent_ip && parent_ip->i_di.di_num.no_addr ==
- ip->i_di.di_num.no_addr) {
- log_warn(_("fsck found the root inode at: 0x%llx\n"),
- ip->i_di.di_num.no_addr);
- sdp->sd_sb.sb_root_dir.no_addr =
- ip->i_di.di_num.no_addr;
- inode_put(&parent_ip);
- inode_put(&ip);
- return;
- }
- if (!parent_ip)
- break;
- inode_put(&ip);
- ip = parent_ip;
- }
- error = dir_search(ip, "..", 2, NULL, &inum);
- if (!error && inum.no_addr && inum.no_addr < possible_root) {
- possible_root = inum.no_addr;
- log_debug(_("Found a possible root at: 0x%llx\n"),
- (unsigned long long)possible_root);
- }
- inode_put(&ip);
-}
-
-/**
- * find_rgs_for_bsize - check a range of blocks for rgrps to determine bsize.
- * Assumes: device is open.
- */
-static int find_rgs_for_bsize(struct gfs2_sbd *sdp, uint64_t startblock,
- uint32_t *known_bsize)
-{
- uint64_t blk, max_rg_size, rb_addr;
- struct gfs2_buffer_head *bh, *rb_bh;
- uint32_t bsize, bsize2;
- uint32_t chk;
- char *p;
- int found_rg;
- struct gfs2_meta_header mh;
-
- sdp->bsize = GFS2_DEFAULT_BSIZE;
- max_rg_size = 524288;
- /* Max RG size is 2GB. Max block size is 4K. 2G / 4K blks = 524288,
- So this is traversing 2GB in 4K block increments. */
- for (blk = startblock; blk < startblock + max_rg_size; blk++) {
- bh = bread(sdp, blk);
- found_rg = 0;
- for (bsize = 0; bsize < GFS2_DEFAULT_BSIZE;
- bsize += GFS2_BASIC_BLOCK) {
- p = bh->b_data + bsize;
- chk = ((struct gfs2_meta_header *)p)->mh_magic;
- if (be32_to_cpu(chk) != GFS2_MAGIC)
- continue;
- chk = ((struct gfs2_meta_header *)p)->mh_type;
- if (be32_to_cpu(chk) == GFS2_METATYPE_RG) {
- found_rg = 1;
- break;
- }
- }
- if (!found_rg)
- continue;
- /* Try all the block sizes in 512 byte multiples */
- for (bsize2 = GFS2_BASIC_BLOCK; bsize2 <= GFS2_DEFAULT_BSIZE;
- bsize2 += GFS2_BASIC_BLOCK) {
- rb_addr = (bh->b_blocknr *
- (GFS2_DEFAULT_BSIZE / bsize2)) +
- (bsize / bsize2) + 1;
- sdp->bsize = bsize2; /* temporarily */
- rb_bh = bread(sdp, rb_addr);
- gfs2_meta_header_in(&mh, rb_bh);
- brelse(rb_bh);
- if (mh.mh_magic == GFS2_MAGIC &&
- mh.mh_type == GFS2_METATYPE_RB) {
- log_debug(_("boff:%d bsize2:%d rg:0x%llx, "
- "rb:0x%llx\n"), bsize, bsize2,
- (unsigned long long)blk,
- (unsigned long long)rb_addr);
- *known_bsize = bsize2;
- break;
- }
- }
- brelse(bh);
- if (!(*known_bsize)) {
- sdp->bsize = GFS2_DEFAULT_BSIZE;
- continue;
- }
-
- sdp->bsize = *known_bsize;
- log_warn(_("Block size determined to be: %d\n"), *known_bsize);
- return 0;
- }
- return 0;
-}
-
-/**
- * peruse_metadata - check a range of blocks for metadata
- * Assumes: device is open.
- */
-static int peruse_metadata(struct gfs2_sbd *sdp, uint64_t startblock)
-{
- uint64_t blk, max_rg_size;
- struct gfs2_buffer_head *bh;
- struct gfs2_dinode di;
- int found_gfs2_dinodes = 0, possible_gfs1_dinodes = 0;
-
- max_rg_size = 2147483648ull / sdp->bsize;
- /* Max RG size is 2GB. 2G / bsize. */
- for (blk = startblock; blk < startblock + max_rg_size; blk++) {
- bh = bread(sdp, blk);
- if (gfs2_check_meta(bh, GFS2_METATYPE_DI)) {
- brelse(bh);
- continue;
- }
- gfs2_dinode_in(&di, bh);
- if (!found_gfs2_dinodes &&
- di.di_num.no_addr == di.di_num.no_formal_ino) {
- possible_gfs1_dinodes++;
- if (possible_gfs1_dinodes > 5) {
- log_err(_("Found several gfs (version 1) "
- "dinodes; aborting.\n"));
- brelse(bh);
- return -1;
- }
- } else {
- found_gfs2_dinodes++;
- }
- if (di.di_flags & GFS2_DIF_SYSTEM)
- peruse_system_dinode(sdp, &di, bh);
- else
- peruse_user_dinode(sdp, &di, bh);
- brelse(bh);
- }
- return 0;
-}
-
-/**
- * sb_repair - repair a damaged superblock
- * Assumes: device is open.
- * The biggest RG size is 2GB
- */
-static int sb_repair(struct gfs2_sbd *sdp)
-{
- uint64_t real_device_size, half;
- uint32_t known_bsize = 0;
- unsigned char uuid[16];
- int error = 0;
-
- memset(&fix_md, 0, sizeof(fix_md));
- /* Step 1 - First we need to determine the correct block size. */
- sdp->bsize = GFS2_DEFAULT_BSIZE;
- log_warn(_("Gathering information to repair the gfs2 superblock. "
- "This may take some time.\n"));
- error = find_rgs_for_bsize(sdp, (GFS2_SB_ADDR * GFS2_BASIC_BLOCK) /
- GFS2_DEFAULT_BSIZE, &known_bsize);
- if (error)
- return error;
- if (!known_bsize) {
- log_warn(_("Block size not apparent; checking elsewhere.\n"));
- /* First, figure out the device size. We need that so we can
- find a suitable start point to determine what's what. */
- device_size(sdp->device_fd, &real_device_size);
- half = real_device_size / 2; /* in bytes */
- half /= sdp->bsize;
- /* Start looking halfway through the device for gfs2
- structures. If there aren't any at all, forget it. */
- error = find_rgs_for_bsize(sdp, half, &known_bsize);
- if (error)
- return error;
- }
- if (!known_bsize) {
- log_err(_("Unable to determine the block size; this "
- "does not look like a gfs2 file system.\n"));
- return -1;
- }
- /* Step 2 - look for the sytem dinodes */
- error = peruse_metadata(sdp, (GFS2_SB_ADDR * GFS2_BASIC_BLOCK) /
- GFS2_DEFAULT_BSIZE);
- if (error)
- return error;
- if (!sdp->sd_sb.sb_master_dir.no_addr) {
- log_err(_("Unable to locate the system master directory.\n"));
- return -1;
- }
- if (!sdp->sd_sb.sb_root_dir.no_addr) {
- struct gfs2_inum inum;
-
- log_err(_("Unable to locate the root directory.\n"));
- if (possible_root == HIGHEST_BLOCK) {
- /* Take advantage of the fact that mkfs.gfs2
- creates master immediately after root. */
- log_err(_("Can't find any dinodes that might "
- "be the root; using master - 1.\n"));
- possible_root = sdp->sd_sb.sb_master_dir.no_addr - 1;
- }
- log_err(_("Found a root directory candidate at 0x%llx\n"),
- (unsigned long long)possible_root);
- sdp->sd_sb.sb_root_dir.no_addr = possible_root;
- sdp->md.rooti = inode_read(sdp, possible_root);
- if (!sdp->md.rooti ||
- sdp->md.rooti->i_di.di_header.mh_magic != GFS2_MAGIC) {
- struct gfs2_buffer_head *bh;
-
- log_err(_("The root dinode block is destroyed.\n"));
- log_err(_("At this point I recommend "
- "reinitializing it.\n"
- "Hopefully everything will later "
- "be put into lost+found.\n"));
- if (!query(_("Okay to reinitialize the root "
- "dinode? (y/n)"))) {
- log_err(_("The root dinode was not "
- "reinitialized; aborting.\n"));
- return -1;
- }
- inum.no_formal_ino = 1;
- inum.no_addr = possible_root;
- bh = init_dinode(sdp, &inum, S_IFDIR | 0755, 0, &inum);
- brelse(bh);
- }
- }
- /* Step 3 - Rebuild the lock protocol and file system table name */
- get_lockproto_table(sdp);
- if (query(_("Okay to fix the GFS2 superblock? (y/n)"))) {
- log_info(_("Master system directory found at: 0x%llx\n"),
- sdp->sd_sb.sb_master_dir.no_addr);
- sdp->master_dir = inode_read(sdp,
- sdp->sd_sb.sb_master_dir.no_addr);
- sdp->master_dir->i_di.di_num.no_addr =
- sdp->sd_sb.sb_master_dir.no_addr;
- log_info(_("Root directory found at: 0x%llx\n"),
- sdp->sd_sb.sb_root_dir.no_addr);
- sdp->md.rooti = inode_read(sdp,
- sdp->sd_sb.sb_root_dir.no_addr);
- get_random_bytes(uuid, sizeof(uuid));
- build_sb(sdp, uuid);
- inode_put(&sdp->md.rooti);
- inode_put(&sdp->master_dir);
- } else {
- log_crit(_("GFS2 superblock not fixed; fsck cannot proceed "
- "without a valid superblock.\n"));
- return -1;
- }
- return 0;
-}
-
-/**
- * fill_super_block
- * @sdp:
- *
- * Returns: 0 on success, -1 on failure
- */
-static int fill_super_block(struct gfs2_sbd *sdp)
-{
- sync();
-
- /********************************************************************
- ***************** First, initialize all lists **********************
- ********************************************************************/
- log_info( _("Initializing lists...\n"));
- osi_list_init(&sdp->rglist);
-
- /********************************************************************
- ************ next, read in on-disk SB and set constants **********
- ********************************************************************/
- sdp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
- sdp->bsize = sdp->sd_sb.sb_bsize;
-
- if(sizeof(struct gfs2_sb) > sdp->sd_sb.sb_bsize){
- log_crit( _("GFS superblock is larger than the blocksize!\n"));
- log_debug( _("sizeof(struct gfs2_sb) > sdp->sd_sb.sb_bsize\n"));
- return -1;
- }
-
- if (compute_constants(sdp)) {
- log_crit(_("Bad constants (1)\n"));
- exit(-1);
- }
- if (read_sb(sdp) < 0) {
- /* First, check for a gfs1 (not gfs2) file system */
- if (sdp->sd_sb.sb_header.mh_magic == GFS2_MAGIC &&
- sdp->sd_sb.sb_header.mh_type == GFS2_METATYPE_SB)
- return -1; /* This is gfs1, don't try to repair */
- /* It's not a "sane" gfs1 fs so try to repair it */
- if (sb_repair(sdp) != 0)
- return -1; /* unrepairable, so exit */
- /* Now that we've tried to repair it, re-read it. */
- if (read_sb(sdp) < 0)
- return -1;
- }
-
- return 0;
-}
-
-/**
- * initialize - initialize superblock pointer
- *
- */
-int initialize(struct gfs2_sbd *sbp, int force_check, int preen,
- int *all_clean)
-{
- int clean_journals = 0, open_flag;
-
- *all_clean = 0;
-
- if(opts.no)
- open_flag = O_RDONLY;
- else
- open_flag = O_RDWR | O_EXCL;
-
- sbp->device_fd = open(opts.device, open_flag);
- if (sbp->device_fd < 0) {
- int is_mounted, ro;
-
- if (open_flag == O_RDONLY || errno != EBUSY) {
- log_crit( _("Unable to open device: %s\n"),
- opts.device);
- return FSCK_USAGE;
- }
- /* We can't open it EXCL. It may be already open rw (in which
- case we want to deny them access) or it may be mounted as
- the root file system at boot time (in which case we need to
- allow it.) We use is_pathname_mounted here even though
- we're specifying a device name, not a path name. The
- function checks for device as well. */
- strncpy(sbp->device_name, opts.device,
- sizeof(sbp->device_name));
- sbp->path_name = sbp->device_name; /* This gets overwritten */
- is_mounted = is_pathname_mounted(sbp, &ro);
- /* If the device is busy, but not because it's mounted, fail.
- This protects against cases where the file system is LVM
- and perhaps mounted on a different node. */
- if (!is_mounted)
- goto mount_fail;
- /* If the device is mounted, but not mounted RO, fail. This
- protects them against cases where the file system is
- mounted RW, but still allows us to check our own root
- file system. */
- if (!ro)
- goto mount_fail;
- /* The device is mounted RO, so it's likely our own root
- file system. We can only do so much to protect the users
- from themselves. Try opening without O_EXCL. */
- if ((sbp->device_fd = open(opts.device, O_RDWR)) < 0)
- goto mount_fail;
-
- was_mounted_ro = 1;
- }
-
- /* read in sb from disk */
- if (fill_super_block(sbp))
- return FSCK_ERROR;
-
- /* Change lock protocol to be fsck_* instead of lock_* */
- if(!opts.no && preen_is_safe(sbp, preen, force_check)) {
- if(block_mounters(sbp, 1)) {
- log_err( _("Unable to block other mounters\n"));
- return FSCK_USAGE;
- }
- }
-
- /* Get master dinode */
- sbp->master_dir = inode_read(sbp, sbp->sd_sb.sb_master_dir.no_addr);
- if (sbp->master_dir->i_di.di_header.mh_magic != GFS2_MAGIC ||
- sbp->master_dir->i_di.di_header.mh_type != GFS2_METATYPE_DI ||
- !sbp->master_dir->i_di.di_size) {
- inode_put(&sbp->master_dir);
- rebuild_master(sbp);
- sbp->master_dir = inode_read(sbp,
- sbp->sd_sb.sb_master_dir.no_addr);
- }
-
- /* verify various things */
-
- if(replay_journals(sbp, preen, force_check, &clean_journals)) {
- if(!opts.no && preen_is_safe(sbp, preen, force_check))
- block_mounters(sbp, 0);
- stack;
- return FSCK_ERROR;
- }
- if (sbp->md.journals == clean_journals)
- *all_clean = 1;
- else {
- if (force_check || !preen)
- log_notice( _("\nJournal recovery complete.\n"));
- }
-
- if (!force_check && *all_clean && preen)
- return FSCK_OK;
-
- if (init_system_inodes(sbp))
- return FSCK_ERROR;
-
- return FSCK_OK;
-
-mount_fail:
- log_crit( _("Device %s is busy.\n"), opts.device);
- return FSCK_USAGE;
-}
-
-static void destroy_sbp(struct gfs2_sbd *sbp)
-{
- if(!opts.no) {
- if(block_mounters(sbp, 0)) {
- log_warn( _("Unable to unblock other mounters - manual intervention required\n"));
- log_warn( _("Use 'gfs2_tool sb <device> proto' to fix\n"));
- }
- log_info( _("Syncing the device.\n"));
- fsync(sbp->device_fd);
- }
- empty_super_block(sbp);
- close(sbp->device_fd);
- if (was_mounted_ro && errors_corrected) {
- sbp->device_fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
- if (sbp->device_fd >= 0) {
- write(sbp->device_fd, "2", 1);
- close(sbp->device_fd);
- } else
- log_err( _("fsck.gfs2: Non-fatal error dropping "
- "caches.\n"));
- }
-}
-
-void destroy(struct gfs2_sbd *sbp)
-{
- destroy_sbp(sbp);
-}
diff --git a/gfs2/fsck/inode_hash.c b/gfs2/fsck/inode_hash.c
deleted file mode 100644
index 2ba1d05..0000000
--- a/gfs2/fsck/inode_hash.c
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <stdint.h>
-#include <unistd.h>
-#include <libintl.h>
-
-#include "libgfs2.h"
-#include "osi_list.h"
-#include "hash.h"
-#include "inode_hash.h"
-#include "fsck.h"
-#define _(String) gettext(String)
-
-struct inode_info *inodetree_find(uint64_t block)
-{
- struct osi_node *node = inodetree.osi_node;
-
- while (node) {
- struct inode_info *data = (struct inode_info *)node;
-
- if (block < data->inode)
- node = node->osi_left;
- else if (block > data->inode)
- node = node->osi_right;
- else
- return data;
- }
- return NULL;
-}
-
-struct inode_info *inodetree_insert(uint64_t dblock)
-{
- struct osi_node **newn = &inodetree.osi_node, *parent = NULL;
- struct inode_info *data;
-
- /* Figure out where to put new node */
- while (*newn) {
- struct inode_info *cur = (struct inode_info *)*newn;
-
- parent = *newn;
- if (dblock < cur->inode)
- newn = &((*newn)->osi_left);
- else if (dblock > cur->inode)
- newn = &((*newn)->osi_right);
- else
- return cur;
- }
-
- data = malloc(sizeof(struct inode_info));
- if (!data) {
- log_crit( _("Unable to allocate inode_info structure\n"));
- return NULL;
- }
- if (!memset(data, 0, sizeof(struct inode_info))) {
- log_crit( _("Error while zeroing inode_info structure\n"));
- return NULL;
- }
- /* Add new node and rebalance tree. */
- data->inode = dblock;
- osi_link_node(&data->node, parent, newn);
- osi_insert_color(&data->node, &inodetree);
-
- return data;
-}
-
-void inodetree_delete(struct inode_info *b)
-{
- osi_erase(&b->node, &inodetree);
- free(b);
-}
diff --git a/gfs2/fsck/inode_hash.h b/gfs2/fsck/inode_hash.h
deleted file mode 100644
index e18022d..0000000
--- a/gfs2/fsck/inode_hash.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _INODE_HASH_H
-#define _INODE_HASH_H
-
-struct inode_info;
-
-extern struct inode_info *inodetree_find(uint64_t block);
-extern struct inode_info *inodetree_insert(uint64_t dblock);
-extern void inodetree_delete(struct inode_info *b);
-
-#endif /* _INODE_HASH_H */
diff --git a/gfs2/fsck/link.c b/gfs2/fsck/link.c
deleted file mode 100644
index ce8eb52..0000000
--- a/gfs2/fsck/link.c
+++ /dev/null
@@ -1,94 +0,0 @@
-#include <inttypes.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "fsck.h"
-#include "inode_hash.h"
-#include "link.h"
-
-int set_link_count(uint64_t inode_no, uint32_t count)
-{
- struct inode_info *ii;
- /*log_debug( _("Setting link count to %u for %" PRIu64
- " (0x%" PRIx64 ")\n"), count, inode_no, inode_no);*/
- /* If the list has entries, look for one that matches inode_no */
- ii = inodetree_find(inode_no);
- if (!ii)
- ii = inodetree_insert(inode_no);
- if (ii)
- ii->link_count = count;
- else
- return -1;
- return 0;
-}
-
-int increment_link(uint64_t inode_no, uint64_t referenced_from,
- const char *why)
-{
- struct inode_info *ii = NULL;
-
- ii = inodetree_find(inode_no);
- /* If the list has entries, look for one that matches
- * inode_no */
- if (ii) {
- ii->counted_links++;
- log_debug( _("Directory %lld (0x%llx) incremented counted "
- "links to %u for %"PRIu64" (0x%" PRIx64 ") "
- "via %s\n"),
- (unsigned long long)referenced_from,
- (unsigned long long)referenced_from,
- ii->counted_links, inode_no, inode_no, why);
- return 0;
- }
- log_debug( _("Ref: %lld (0x%llx) No match found when incrementing "
- "link for %" PRIu64 " (0x%" PRIx64 ")!\n"),
- (unsigned long long)referenced_from,
- (unsigned long long)referenced_from, inode_no, inode_no);
- /* If no match was found, add a new entry and set its
- * counted links to 1 */
- ii = inodetree_insert(inode_no);
- if (ii)
- ii->counted_links = 1;
- else
- return -1;
- return 0;
-}
-
-int decrement_link(uint64_t inode_no, uint64_t referenced_from,
- const char *why)
-{
- struct inode_info *ii = NULL;
-
- ii = inodetree_find(inode_no);
- /* If the list has entries, look for one that matches
- * inode_no */
- if(ii) {
- if (!ii->counted_links) {
- log_debug( _("Directory %lld (0x%llx)'s link to "
- " %"PRIu64" (0x%" PRIx64 ") via %s is zero!\n"),
- (unsigned long long)referenced_from,
- (unsigned long long)referenced_from,
- inode_no, inode_no, why);
- return 0;
- }
- ii->counted_links--;
- log_debug( _("Directory %lld (0x%llx) decremented counted "
- "links to %u for %"PRIu64" (0x%" PRIx64 ") "
- "via %s\n"),
- (unsigned long long)referenced_from,
- (unsigned long long)referenced_from,
- ii->counted_links, inode_no, inode_no, why);
- return 0;
- }
- log_debug( _("No match found when decrementing link for %" PRIu64
- " (0x%" PRIx64 ")!\n"), inode_no, inode_no);
- return -1;
-
-}
-
-
diff --git a/gfs2/fsck/link.h b/gfs2/fsck/link.h
deleted file mode 100644
index f890575..0000000
--- a/gfs2/fsck/link.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _LINK_H
-#define _LINK_H
-
-int set_link_count(uint64_t inode_no, uint32_t count);
-int increment_link(uint64_t inode_no, uint64_t referenced_from,
- const char *why);
-int decrement_link(uint64_t inode_no, uint64_t referenced_from,
- const char *why);
-
-#endif /* _LINK_H */
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
deleted file mode 100644
index 3256bdc..0000000
--- a/gfs2/fsck/lost_n_found.c
+++ /dev/null
@@ -1,199 +0,0 @@
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "fsck.h"
-#include "libgfs2.h"
-#include "lost_n_found.h"
-#include "link.h"
-#include "metawalk.h"
-#include "util.h"
-
-/* add_inode_to_lf - Add dir entry to lost+found for the inode
- * @ip: inode to add to lost + found
- *
- * This function adds an entry into the lost and found dir
- * for the given inode. The name of the entry will be
- * "lost_<ip->i_num.no_addr>".
- *
- * Returns: 0 on success, -1 on failure.
- */
-int add_inode_to_lf(struct gfs2_inode *ip){
- char tmp_name[256];
- __be32 inode_type;
- uint64_t lf_blocks;
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct dir_info *di;
-
- if(!lf_dip) {
- uint8_t q;
-
- log_info( _("Locating/Creating lost+found directory\n"));
-
- lf_dip = createi(sdp->md.rooti, "lost+found",
- S_IFDIR | 0700, 0);
- /* createi will have incremented the di_nlink link count for
- the root directory. We must increment the nlink value
- in the hash table to keep them in sync so that pass4 can
- detect and fix any descrepancies. */
- set_link_count(sdp->sd_sb.sb_root_dir.no_addr,
- sdp->md.rooti->i_di.di_nlink);
-
- q = block_type(lf_dip->i_di.di_num.no_addr);
- if(q != gfs2_inode_dir) {
- /* This is a new lost+found directory, so set its
- * block type and increment link counts for
- * the directories */
- /* FIXME: i'd feel better about this if
- * fs_mkdir returned whether it created a new
- * directory or just found an old one, and we
- * used that instead of the block_type to run
- * this */
- fsck_blockmap_set(ip, lf_dip->i_di.di_num.no_addr,
- _("lost+found dinode"),
- gfs2_inode_dir);
- /* root inode links to lost+found */
- increment_link(sdp->md.rooti->i_di.di_num.no_addr,
- lf_dip->i_di.di_num.no_addr, _("root"));
- /* lost+found link for '.' from itself */
- increment_link(lf_dip->i_di.di_num.no_addr,
- lf_dip->i_di.di_num.no_addr, "\".\"");
- /* lost+found link for '..' back to root */
- increment_link(lf_dip->i_di.di_num.no_addr,
- sdp->md.rooti->i_di.di_num.no_addr,
- "\"..\"");
- }
- log_info( _("lost+found directory is dinode %lld (0x%llx)\n"),
- (unsigned long long)lf_dip->i_di.di_num.no_addr,
- (unsigned long long)lf_dip->i_di.di_num.no_addr);
- di = dirtree_find(lf_dip->i_di.di_num.no_addr);
- if (di) {
- log_info( _("Marking lost+found inode connected\n"));
- di->checked = 1;
- di = NULL;
- }
- }
- if(ip->i_di.di_num.no_addr == lf_dip->i_di.di_num.no_addr) {
- log_err( _("Trying to add lost+found to itself...skipping"));
- return 0;
- }
- lf_blocks = lf_dip->i_di.di_blocks;
-
- switch(ip->i_di.di_mode & S_IFMT){
- case S_IFDIR:
- log_info( _("Adding .. entry pointing to lost+found for "
- "directory %llu (0x%llx)\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
-
- /* If there's a pre-existing .. directory entry, we have to
- back out the links. */
- di = dirtree_find(ip->i_di.di_num.no_addr);
- if (di && gfs2_check_range(sdp, di->dotdot_parent) == 0) {
- struct gfs2_inode *dip;
-
- log_debug(_("Directory %lld (0x%llx) already had a "
- "\"..\" link to %lld (0x%llx).\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)di->dotdot_parent,
- (unsigned long long)di->dotdot_parent);
- decrement_link(di->dotdot_parent,
- ip->i_di.di_num.no_addr,
- _(".. unlinked, moving to lost+found"));
- dip = fsck_load_inode(sdp, di->dotdot_parent);
- if (dip->i_di.di_nlink > 0) {
- dip->i_di.di_nlink--;
- log_debug(_("Decrementing its links to %d\n"),
- dip->i_di.di_nlink);
- bmodified(dip->i_bh);
- } else if (!dip->i_di.di_nlink) {
- log_debug(_("Its link count is zero.\n"));
- } else {
- log_debug(_("Its link count is %d! "
- "Changing it to 0.\n"),
- dip->i_di.di_nlink);
- dip->i_di.di_nlink = 0;
- bmodified(dip->i_bh);
- }
- fsck_inode_put(&dip);
- di = NULL;
- } else
- log_debug(_("Couldn't find a valid \"..\" entry "
- "for orphan directory %lld (0x%llx)\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if(gfs2_dirent_del(ip, "..", 2))
- log_warn( _("add_inode_to_lf: Unable to remove "
- "\"..\" directory entry.\n"));
-
- dir_add(ip, "..", 2, &(lf_dip->i_di.di_num), DT_DIR);
- sprintf(tmp_name, "lost_dir_%llu",
- (unsigned long long)ip->i_di.di_num.no_addr);
- inode_type = DT_DIR;
- break;
- case S_IFREG:
- sprintf(tmp_name, "lost_file_%llu",
- (unsigned long long)ip->i_di.di_num.no_addr);
- inode_type = DT_REG;
- break;
- case S_IFLNK:
- sprintf(tmp_name, "lost_link_%llu",
- (unsigned long long)ip->i_di.di_num.no_addr);
- inode_type = DT_LNK;
- break;
- case S_IFBLK:
- sprintf(tmp_name, "lost_blkdev_%llu",
- (unsigned long long)ip->i_di.di_num.no_addr);
- inode_type = DT_BLK;
- break;
- case S_IFCHR:
- sprintf(tmp_name, "lost_chrdev_%llu",
- (unsigned long long)ip->i_di.di_num.no_addr);
- inode_type = DT_CHR;
- break;
- case S_IFIFO:
- sprintf(tmp_name, "lost_fifo_%llu",
- (unsigned long long)ip->i_di.di_num.no_addr);
- inode_type = DT_FIFO;
- break;
- case S_IFSOCK:
- sprintf(tmp_name, "lost_socket_%llu",
- (unsigned long long)ip->i_di.di_num.no_addr);
- inode_type = DT_SOCK;
- break;
- default:
- sprintf(tmp_name, "lost_%llu",
- (unsigned long long)ip->i_di.di_num.no_addr);
- inode_type = DT_REG;
- break;
- }
-
- dir_add(lf_dip, tmp_name, strlen(tmp_name), &(ip->i_di.di_num),
- inode_type);
- /* If the lf directory had new blocks added we have to mark them
- properly in the bitmap so they're not freed. */
- if (lf_dip->i_di.di_blocks != lf_blocks)
- reprocess_inode(lf_dip, "lost+found");
-
- /* This inode is linked from lost+found */
- increment_link(ip->i_di.di_num.no_addr, lf_dip->i_di.di_num.no_addr,
- _("from lost+found"));
- /* If it's a directory, lost+found is back-linked to it via .. */
- if(S_ISDIR(ip->i_di.di_mode))
- increment_link(lf_dip->i_di.di_num.no_addr,
- ip->i_di.di_mode, _("to lost+found"));
-
- log_notice( _("Added inode #%llu (0x%llx) to lost+found dir\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- gfs2_dinode_out(&lf_dip->i_di, lf_dip->i_bh);
- bwrite(lf_dip->i_bh);
- return 0;
-}
diff --git a/gfs2/fsck/lost_n_found.h b/gfs2/fsck/lost_n_found.h
deleted file mode 100644
index f28a1d9..0000000
--- a/gfs2/fsck/lost_n_found.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __LOST_N_FOUND_H__
-#define __LOST_N_FOUND_H__
-
-#include "libgfs2.h"
-
-int add_inode_to_lf(struct gfs2_inode *ip);
-
-#endif /* __LOST_N_FOUND_H__ */
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
deleted file mode 100644
index 222219f..0000000
--- a/gfs2/fsck/main.c
+++ /dev/null
@@ -1,368 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <libgen.h>
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <signal.h>
-#include <libintl.h>
-#include <locale.h>
-#define _(String) gettext(String)
-
-#include "copyright.cf"
-#include "libgfs2.h"
-#include "fsck.h"
-#include "osi_list.h"
-#include "metawalk.h"
-#include "util.h"
-
-struct gfs2_options opts = {0};
-struct gfs2_inode *lf_dip = NULL; /* Lost and found directory inode */
-struct gfs2_bmap *bl = NULL;
-uint64_t last_fs_block, last_reported_block = -1;
-int64_t last_reported_fblock = -1000000;
-int skip_this_pass = FALSE, fsck_abort = FALSE;
-int errors_found = 0, errors_corrected = 0;
-const char *pass = "";
-uint64_t last_data_block;
-uint64_t first_data_block;
-int preen = 0, force_check = 0;
-struct osi_root dup_blocks = (struct osi_root) { NULL, };
-struct osi_root dirtree = (struct osi_root) { NULL, };
-struct osi_root inodetree = (struct osi_root) { NULL, };
-int dups_found = 0, dups_found_first = 0;
-
-/* This function is for libgfs2's sake. */
-void print_it(const char *label, const char *fmt, const char *fmt2, ...)
-{
- va_list args;
-
- va_start(args, fmt2);
- printf("%s: ", label);
- vprintf(fmt, args);
- va_end(args);
-}
-
-static void usage(char *name)
-{
- printf("Usage: %s [-afhnpqvVy] <device> \n", basename(name));
-}
-
-static void version(void)
-{
- printf( _("GFS2 fsck %s (built %s %s)\n"),
- RELEASE_VERSION, __DATE__, __TIME__);
- printf( _(REDHAT_COPYRIGHT "\n"));
-}
-
-static int read_cmdline(int argc, char **argv, struct gfs2_options *gopts)
-{
- int c;
-
- while((c = getopt(argc, argv, "afhnpqvyV")) != -1) {
- switch(c) {
-
- case 'a':
- preen = 1;
- gopts->yes = 1;
- break;
- case 'f':
- force_check = 1;
- break;
- case 'h':
- usage(argv[0]);
- exit(FSCK_OK);
- break;
- case 'n':
- gopts->no = 1;
- break;
- case 'p':
- preen = 1;
- gopts->yes = 1;
- break;
- case 'q':
- decrease_verbosity();
- break;
- case 'v':
- increase_verbosity();
- break;
- case 'V':
- version();
- exit(FSCK_OK);
- break;
- case 'y':
- gopts->yes = 1;
- break;
- case ':':
- case '?':
- fprintf(stderr, _("Please use '-h' for usage.\n"));
- return FSCK_USAGE;
- default:
- fprintf(stderr, _("Bad programmer! You forgot to catch"
- " the %c flag\n"), c);
- return FSCK_USAGE;
-
- }
- }
- if(argc > optind) {
- gopts->device = (argv[optind]);
- if(!gopts->device) {
- fprintf(stderr, _("Please use '-h' for usage.\n"));
- return FSCK_USAGE;
- }
- } else {
- fprintf(stderr, _("No device specified. Use '-h' for usage.\n"));
- return FSCK_USAGE;
- }
- return 0;
-}
-
-static void interrupt(int sig)
-{
- char response;
- char progress[PATH_MAX];
-
- if (!last_reported_block || last_reported_block == last_fs_block)
- sprintf(progress, _("progress unknown.\n"));
- else
- sprintf(progress, _("processing block %" PRIu64 " out of %"
- PRIu64 "\n"), last_reported_block, last_fs_block);
-
- response = generic_interrupt("gfs2_fsck", pass, progress,
- _("Do you want to abort gfs2_fsck, skip " \
- "the rest of this pass or continue " \
- "(a/s/c)?"), "asc");
- if(tolower(response) == 's') {
- skip_this_pass = TRUE;
- return;
- }
- else if (tolower(response) == 'a') {
- fsck_abort = TRUE;
- return;
- }
-}
-
-static void check_statfs(struct gfs2_sbd *sdp)
-{
- osi_list_t *tmp;
- struct rgrp_list *rgd;
- struct gfs2_rindex *ri;
- struct gfs2_statfs_change sc;
- char buf[sizeof(struct gfs2_statfs_change)];
- int count;
-
- /* Read the current statfs values */
- count = gfs2_readi(sdp->md.statfs, buf, 0,
- sdp->md.statfs->i_di.di_size);
- if (count == sizeof(struct gfs2_statfs_change))
- gfs2_statfs_change_in(&sc, buf);
-
- /* Calculate the real values from the rgrp information */
- sdp->blks_total = 0;
- sdp->blks_alloced = 0;
- sdp->dinodes_alloced = 0;
-
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- ri = &rgd->ri;
- sdp->blks_total += ri->ri_data;
- sdp->blks_alloced += (ri->ri_data - rgd->rg.rg_free);
- sdp->dinodes_alloced += rgd->rg.rg_dinodes;
- }
-
- /* See if they match */
- if (sc.sc_total == sdp->blks_total &&
- sc.sc_free == (sdp->blks_total - sdp->blks_alloced) &&
- sc.sc_dinodes == sdp->dinodes_alloced) {
- log_info( _("The statfs file is accurate.\n"));
- return;
- }
- log_err( _("The statfs file is wrong:\n\n"));
- log_err( _("Current statfs values:\n"));
- log_err( _("blocks: %lld (0x%llx)\n"),
- (unsigned long long)sc.sc_total,
- (unsigned long long)sc.sc_total);
- log_err( _("free: %lld (0x%llx)\n"),
- (unsigned long long)sc.sc_free,
- (unsigned long long)sc.sc_free);
- log_err( _("dinodes: %lld (0x%llx)\n\n"),
- (unsigned long long)sc.sc_dinodes,
- (unsigned long long)sc.sc_dinodes);
-
- log_err( _("Calculated statfs values:\n"));
- log_err( _("blocks: %lld (0x%llx)\n"),
- (unsigned long long)sdp->blks_total,
- (unsigned long long)sdp->blks_total);
- log_err( _("free: %lld (0x%llx)\n"),
- (unsigned long long)(sdp->blks_total - sdp->blks_alloced),
- (unsigned long long)(sdp->blks_total - sdp->blks_alloced));
- log_err( _("dinodes: %lld (0x%llx)\n"),
- (unsigned long long)sdp->dinodes_alloced,
- (unsigned long long)sdp->dinodes_alloced);
-
- errors_found++;
- if (!query( _("Okay to fix the master statfs file? (y/n)"))) {
- log_err( _("The statfs file was not fixed.\n"));
- return;
- }
-
- do_init_statfs(sdp);
- log_err( _("The statfs file was fixed.\n"));
- errors_corrected++;
-}
-
-int main(int argc, char **argv)
-{
- struct gfs2_sbd sb;
- struct gfs2_sbd *sbp = &sb;
- int j;
- int error = 0;
- int all_clean = 0;
-
- setlocale(LC_ALL, "");
- textdomain("gfs2-utils");
-
- memset(sbp, 0, sizeof(*sbp));
-
- if((error = read_cmdline(argc, argv, &opts)))
- exit(error);
- setbuf(stdout, NULL);
- log_notice( _("Initializing fsck\n"));
- if ((error = initialize(sbp, force_check, preen, &all_clean)))
- exit(error);
-
- if (!force_check && all_clean && preen) {
- log_err( _("%s: clean.\n"), opts.device);
- destroy(sbp);
- exit(FSCK_OK);
- }
-
- signal(SIGINT, interrupt);
- log_notice( _("Starting pass1\n"));
- pass = "pass 1";
- last_reported_block = 0;
- if ((error = pass1(sbp)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice( _("Pass1 interrupted \n"));
- }
- else
- log_notice( _("Pass1 complete \n"));
-
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 1b";
- log_notice( _("Starting pass1b\n"));
- if((error = pass1b(sbp)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice( _("Pass1b interrupted \n"));
- }
- else
- log_notice( _("Pass1b complete\n"));
- }
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 1c";
- log_notice( _("Starting pass1c\n"));
- if((error = pass1c(sbp)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice( _("Pass1c interrupted \n"));
- }
- else
- log_notice( _("Pass1c complete\n"));
- }
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 2";
- log_notice( _("Starting pass2\n"));
- if ((error = pass2(sbp)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice( _("Pass2 interrupted \n"));
- }
- else
- log_notice( _("Pass2 complete \n"));
- }
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 3";
- log_notice( _("Starting pass3\n"));
- if ((error = pass3(sbp)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice( _("Pass3 interrupted \n"));
- }
- else
- log_notice( _("Pass3 complete \n"));
- }
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 4";
- log_notice( _("Starting pass4\n"));
- if ((error = pass4(sbp)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice( _("Pass4 interrupted \n"));
- }
- else
- log_notice( _("Pass4 complete \n"));
- }
- if (!fsck_abort) {
- last_reported_block = 0;
- pass = "pass 5";
- log_notice( _("Starting pass5\n"));
- if ((error = pass5(sbp)))
- exit(error);
- if (skip_this_pass || fsck_abort) {
- skip_this_pass = FALSE;
- log_notice( _("Pass5 interrupted \n"));
- error = FSCK_CANCELED;
- }
- else
- log_notice( _("Pass5 complete \n"));
- } else {
- error = FSCK_CANCELED;
- }
-
- check_statfs(sbp);
-
- /* Free up our system inodes */
- inode_put(&sbp->md.inum);
- inode_put(&sbp->md.statfs);
- for (j = 0; j < sbp->md.journals; j++)
- inode_put(&sbp->md.journal[j]);
- inode_put(&sbp->md.jiinode);
- inode_put(&sbp->md.riinode);
- inode_put(&sbp->md.qinode);
- inode_put(&sbp->md.pinode);
- inode_put(&sbp->md.rooti);
- inode_put(&sbp->master_dir);
- if (lf_dip)
- inode_put(&lf_dip);
-
- if (!opts.no && errors_corrected)
- log_notice( _("Writing changes to disk\n"));
- fsync(sbp->device_fd);
- destroy(sbp);
- log_notice( _("gfs2_fsck complete \n"));
-
- if (!error) {
- if (!errors_found)
- error = FSCK_OK;
- else if (errors_found == errors_corrected)
- error = FSCK_NONDESTRUCT;
- else
- error = FSCK_UNCORRECTED;
- }
- exit(error);
-}
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
deleted file mode 100644
index ff348e4..0000000
--- a/gfs2/fsck/metawalk.c
+++ /dev/null
@@ -1,1580 +0,0 @@
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <libintl.h>
-#include <ctype.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "osi_tree.h"
-#include "fsck.h"
-#include "util.h"
-#include "metawalk.h"
-#include "hash.h"
-#include "inode_hash.h"
-
-#define COMFORTABLE_BLKS 5242880 /* 20GB in 4K blocks */
-
-/* There are two bitmaps: (1) The "blockmap" that fsck uses to keep track of
- what block type has been discovered, and (2) The rgrp bitmap. Function
- gfs2_blockmap_set is used to set the former and gfs2_set_bitmap
- is used to set the latter. The two must be kept in sync, otherwise
- you'll get bitmap mismatches. This function checks the status of the
- bitmap whenever the blockmap changes, and fixes it accordingly. */
-int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk,
- enum gfs2_mark_block new_blockmap_state)
-{
- int old_bitmap_state, new_bitmap_state;
- struct rgrp_list *rgd;
-
- rgd = gfs2_blk2rgrpd(sdp, blk);
-
- old_bitmap_state = gfs2_get_bitmap(sdp, blk, rgd);
- if (old_bitmap_state < 0) {
- log_err( _("Block %lld (0x%llx) is not represented in the"
- "system bitmap; part of an rgrp or superblock.\n"),
- (unsigned long long)blk, (unsigned long long)blk);
- return -1;
- }
- new_bitmap_state = blockmap_to_bitmap(new_blockmap_state);
- if (old_bitmap_state != new_bitmap_state) {
- const char *allocdesc[] = {"free space", "data", "unlinked",
- "inode", "reserved"};
-
- log_err( _("Block %llu (0x%llx) seems to be %s, but is "
- "marked as %s in the bitmap.\n"),
- (unsigned long long)blk, (unsigned long long)blk,
- allocdesc[new_bitmap_state],
- allocdesc[old_bitmap_state]);
- if(query( _("Okay to fix the bitmap? (y/n)"))) {
- /* If the new bitmap state is free (and therefore the
- old state was not) we have to add to the free
- space in the rgrp. If the old bitmap state was
- free (and therefore it no longer is) we have to
- subtract to the free space. If the type changed
- from dinode to data or data to dinode, no change in
- free space. */
- gfs2_set_bitmap(sdp, blk, new_bitmap_state);
- if (new_bitmap_state == GFS2_BLKST_FREE) {
- /* If we're freeing a dinode, get rid of
- the hash table entries for it. */
- if (old_bitmap_state == GFS2_BLKST_DINODE) {
- struct dir_info *dt;
- struct inode_info *ii;
-
- dt = dirtree_find(blk);
- if (dt)
- dirtree_delete(dt);
- ii = inodetree_find(blk);
- if (ii)
- inodetree_delete(ii);
- }
- rgd->rg.rg_free++;
- gfs2_rgrp_out(&rgd->rg, rgd->bh[0]);
- } else if (old_bitmap_state == GFS2_BLKST_FREE) {
- rgd->rg.rg_free--;
- gfs2_rgrp_out(&rgd->rg, rgd->bh[0]);
- }
- log_err( _("The bitmap was fixed.\n"));
- } else {
- log_err( _("The bitmap inconsistency was ignored.\n"));
- }
- }
- return 0;
-}
-
-/*
- * _fsck_blockmap_set - Mark a block in the 4-bit blockmap and the 2-bit
- * bitmap, and adjust free space accordingly.
- */
-int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
- const char *btype, enum gfs2_mark_block mark,
- const char *caller, int fline)
-{
- int error;
-
- if (print_level >= MSG_DEBUG) {
- const char *p;
-
- p = strrchr(caller, '/');
- if (p)
- p++;
- else
- p = caller;
- /* I'm circumventing the log levels here on purpose to make the
- output easier to debug. */
- if (ip->i_di.di_num.no_addr == bblock) {
- print_fsck_log(MSG_DEBUG, p, fline,
- _("%s inode found at block %lld "
- "(0x%llx): marking as '%s'\n"),
- btype, (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- block_type_string(mark));
- } else if (mark == gfs2_bad_block || mark == gfs2_meta_inval) {
- print_fsck_log(MSG_DEBUG, p, fline,
- _("inode %lld (0x%llx) references "
- "%s block %lld (0x%llx): "
- "marking as '%s'\n"),
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- btype, (unsigned long long)bblock,
- (unsigned long long)bblock,
- block_type_string(mark));
- } else {
- print_fsck_log(MSG_DEBUG, p, fline,
- _("inode %lld (0x%llx) references "
- "%s block %lld (0x%llx): "
- "marking as '%s'\n"),
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)
- ip->i_di.di_num.no_addr, btype,
- (unsigned long long)bblock,
- (unsigned long long)bblock,
- block_type_string(mark));
- }
- }
-
- /* First, check the rgrp bitmap against what we think it should be.
- If that fails, it's an invalid block--part of an rgrp. */
- error = check_n_fix_bitmap(ip->i_sbd, bblock, mark);
- if (error) {
- log_err( _("This block is not represented in the bitmap.\n"));
- return error;
- }
-
- error = gfs2_blockmap_set(bl, bblock, mark);
- return error;
-}
-
-struct duptree *dupfind(uint64_t block)
-{
- struct osi_node *node = dup_blocks.osi_node;
-
- while (node) {
- struct duptree *data = (struct duptree *)node;
-
- if (block < data->block)
- node = node->osi_left;
- else if (block > data->block)
- node = node->osi_right;
- else
- return data;
- }
- return NULL;
-}
-
-struct gfs2_inode *fsck_system_inode(struct gfs2_sbd *sdp, uint64_t block)
-{
- if (lf_dip && lf_dip->i_di.di_num.no_addr == block)
- return lf_dip;
- return is_system_inode(sdp, block);
-}
-
-/* fsck_load_inode - same as gfs2_load_inode() in libgfs2 but system inodes
- get special treatment. */
-struct gfs2_inode *fsck_load_inode(struct gfs2_sbd *sbp, uint64_t block)
-{
- struct gfs2_inode *ip = NULL;
-
- ip = fsck_system_inode(sbp, block);
- if (ip)
- return ip;
- return inode_read(sbp, block);
-}
-
-/* fsck_inode_get - same as inode_get() in libgfs2 but system inodes
- get special treatment. */
-struct gfs2_inode *fsck_inode_get(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *bh)
-{
- struct gfs2_inode *sysip;
-
- sysip = fsck_system_inode(sdp, bh->b_blocknr);
- if (sysip)
- return sysip;
-
- return inode_get(sdp, bh);
-}
-
-/* fsck_inode_put - same as inode_put() in libgfs2 but system inodes
- get special treatment. */
-void fsck_inode_put(struct gfs2_inode **ip_in)
-{
- struct gfs2_inode *ip = *ip_in;
- struct gfs2_inode *sysip;
-
- sysip = fsck_system_inode(ip->i_sbd, ip->i_di.di_num.no_addr);
- if (!sysip)
- inode_put(ip_in);
-}
-
-/**
- * dirent_repair - attempt to repair a corrupt directory entry.
- * @bh - The buffer header that contains the bad dirent
- * @de - The directory entry in native format
- * @dent - The directory entry in on-disk format
- * @type - Type of directory (DIR_LINEAR or DIR_EXHASH)
- * @first - TRUE if this is the first dirent in the buffer
- *
- * This function tries to repair a corrupt directory entry. All we
- * know at this point is that the length field is wrong.
- */
-static int dirent_repair(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
- struct gfs2_dirent *de, struct gfs2_dirent *dent,
- int type, int first)
-{
- char *bh_end, *p;
- int calc_de_name_len = 0;
-
- /* If this is a sentinel, just fix the length and move on */
- if (first && !de->de_inum.no_formal_ino) { /* Is it a sentinel? */
- if (type == DIR_LINEAR)
- de->de_rec_len = ip->i_sbd->bsize -
- sizeof(struct gfs2_dinode);
- else
- de->de_rec_len = ip->i_sbd->bsize -
- sizeof(struct gfs2_leaf);
- } else {
- bh_end = bh->b_data + ip->i_sbd->bsize;
- /* first, figure out a probable name length */
- p = (char *)dent + sizeof(struct gfs2_dirent);
- while (*p && /* while there's a non-zero char and */
- isprint(*p) && /* a printable character and */
- p < bh_end) { /* not past end of buffer */
- calc_de_name_len++;
- p++;
- }
- if (!calc_de_name_len)
- return 1;
- /* There can often be noise at the end, so only */
- /* Trust the shorter of the two in case we have too much */
- /* Or rather, only trust ours if it's shorter. */
- if (!de->de_name_len || de->de_name_len > NAME_MAX ||
- calc_de_name_len < de->de_name_len) /* if dent is hosed */
- de->de_name_len = calc_de_name_len; /* use ours */
- de->de_rec_len = GFS2_DIRENT_SIZE(de->de_name_len);
- }
- gfs2_dirent_out(de, (char *)dent);
- return 0;
-}
-
-/**
- * dirblk_truncate - truncate a directory block
- */
-static void dirblk_truncate(struct gfs2_inode *ip, struct gfs2_dirent *fixb,
- struct gfs2_buffer_head *bh)
-{
- char *bh_end;
- struct gfs2_dirent de;
- uint16_t old_rec_len;
-
- bh_end = bh->b_data + ip->i_sbd->sd_sb.sb_bsize;
- /* truncate the block to save the most dentries. To do this we
- have to patch the previous dent. */
- gfs2_dirent_in(&de, (char *)fixb);
- old_rec_len = de.de_rec_len;
- de.de_rec_len = bh_end - (char *)fixb;
- gfs2_dirent_out(&de, (char *)fixb);
- bmodified(bh);
-}
-
-/*
- * check_entries - check directory entries for a given block
- *
- * @ip - dinode associated with this leaf block
- * bh - buffer for the leaf block
- * type - type of block this is (linear or exhash)
- * @count - set to the count entries
- * @pass - structure pointing to pass-specific functions
- *
- * returns: 0 - good block or it was repaired to be good
- * -1 - error occurred
- */
-static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
- int type, uint16_t *count, struct metawalk_fxns *pass)
-{
- struct gfs2_leaf *leaf = NULL;
- struct gfs2_dirent *dent;
- struct gfs2_dirent de, *prev;
- int error = 0;
- char *bh_end;
- char *filename;
- int first = 1;
-
- bh_end = bh->b_data + ip->i_sbd->bsize;
-
- if(type == DIR_LINEAR) {
- dent = (struct gfs2_dirent *)(bh->b_data + sizeof(struct gfs2_dinode));
- }
- else if (type == DIR_EXHASH) {
- dent = (struct gfs2_dirent *)(bh->b_data + sizeof(struct gfs2_leaf));
- leaf = (struct gfs2_leaf *)bh->b_data;
- log_debug( _("Checking leaf %" PRIu64 " (0x%" PRIx64 ")\n"),
- bh->b_blocknr, bh->b_blocknr);
- }
- else {
- log_err( _("Invalid directory type %d specified\n"), type);
- return -1;
- }
-
- prev = NULL;
- if(!pass->check_dentry)
- return 0;
-
- while(1) {
- if (skip_this_pass || fsck_abort)
- return FSCK_OK;
- memset(&de, 0, sizeof(struct gfs2_dirent));
- gfs2_dirent_in(&de, (char *)dent);
- filename = (char *)dent + sizeof(struct gfs2_dirent);
-
- if (de.de_rec_len < sizeof(struct gfs2_dirent) +
- de.de_name_len ||
- (de.de_inum.no_formal_ino && !de.de_name_len && !first)) {
- log_err( _("Directory block %llu (0x%llx"
- "), entry %d of directory %llu"
- "(0x%llx) is corrupt.\n"),
- (unsigned long long)bh->b_blocknr,
- (unsigned long long)bh->b_blocknr,
- (*count) + 1,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if (query( _("Attempt to repair it? (y/n) "))) {
- if (dirent_repair(ip, bh, &de, dent, type,
- first)) {
- if (first) /* make a new sentinel */
- dirblk_truncate(ip, dent, bh);
- else
- dirblk_truncate(ip, prev, bh);
- log_err( _("Unable to repair corrupt "
- "directory entry; the "
- "entry was removed "
- "instead.\n"));
- return 0;
- } else {
- log_err( _("Corrupt directory entry "
- "repaired.\n"));
- /* keep looping through dentries */
- }
- } else {
- log_err( _("Corrupt directory entry ignored, "
- "stopped after checking %d entries.\n"),
- *count);
- return 0;
- }
- }
- if (!de.de_inum.no_formal_ino){
- if(first){
- log_debug( _("First dirent is a sentinel (place holder).\n"));
- first = 0;
- } else {
- log_err( _("Directory entry with inode number of "
- "zero in leaf %llu (0x%llx) of "
- "directory %llu (0x%llx)!\n"),
- (unsigned long long)bh->b_blocknr,
- (unsigned long long)bh->b_blocknr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if (query(_("Attempt to remove it? (y/n) "))) {
- dirblk_truncate(ip, prev, bh);
- log_err(_("The corrupt directory "
- "entry was removed.\n"));
- } else {
- log_err( _("Corrupt directory entry "
- "ignored, stopped after "
- "checking %d entries.\n"),
- *count);
- }
- return 0;
- }
- } else {
- if (!de.de_inum.no_addr && first) { /* reverse sentinel */
- log_debug( _("First dirent is a Sentinel (place holder).\n"));
- /* Swap the two to silently make it a proper sentinel */
- de.de_inum.no_addr = de.de_inum.no_formal_ino;
- de.de_inum.no_formal_ino = 0;
- gfs2_dirent_out(&de, (char *)dent);
- bmodified(bh);
- /* Mark dirent buffer as modified */
- first = 0;
- } else {
- error = pass->check_dentry(ip, dent, prev, bh,
- filename, count,
- pass->private);
- if(error < 0) {
- stack;
- return -1;
- }
- }
- }
-
- if ((char *)dent + de.de_rec_len >= bh_end){
- log_debug( _("Last entry processed for %lld->%lld "
- "(0x%llx->0x%llx).\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)bh->b_blocknr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)bh->b_blocknr);
- break;
- }
-
- /* If we didn't clear the dentry, or if we did, but it
- * was the first dentry, set prev */
- if(!error || first)
- prev = dent;
- first = 0;
- dent = (struct gfs2_dirent *)((char *)dent + de.de_rec_len);
- }
- return 0;
-}
-
-/* Process a bad leaf pointer and ask to repair the first time. */
-/* The repair process involves extending the previous leaf's entries */
-/* so that they replace the bad ones. We have to hack up the old */
-/* leaf a bit, but it's better than deleting the whole directory, */
-/* which is what used to happen before. */
-static void warn_and_patch(struct gfs2_inode *ip, uint64_t *leaf_no,
- uint64_t *bad_leaf, uint64_t old_leaf,
- uint64_t first_ok_leaf, int pindex, const char *msg)
-{
- if (*bad_leaf != *leaf_no) {
- log_err( _("Directory Inode %llu (0x%llx) points to leaf %llu"
- " (0x%llx) %s.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)*leaf_no,
- (unsigned long long)*leaf_no, msg);
- }
- if (*leaf_no == *bad_leaf ||
- query( _("Attempt to patch around it? (y/n) "))) {
- if (gfs2_check_range(ip->i_sbd, old_leaf) == 0)
- gfs2_put_leaf_nr(ip, pindex, old_leaf);
- else
- gfs2_put_leaf_nr(ip, pindex, first_ok_leaf);
- log_err( _("Directory Inode %llu (0x%llx) repaired.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- }
- else
- log_err( _("Bad leaf left in place.\n"));
- *bad_leaf = *leaf_no;
- *leaf_no = old_leaf;
-}
-
-/*
- * fix_leaf_pointers - fix a directory dinode that has a number of pointers
- * that is not a multiple of 2.
- * dip - the directory inode having the problem
- * lindex - the index of the leaf right after the problem (need to back up)
- * cur_numleafs - current (incorrect) number of instances of the leaf block
- * correct_numleafs - the correct number instances of the leaf block
- */
-static int fix_leaf_pointers(struct gfs2_inode *dip, int *lindex,
- int cur_numleafs, int correct_numleafs)
-{
- int count;
- char *ptrbuf;
- int start_lindex = *lindex - cur_numleafs; /* start of bad ptrs */
- int tot_num_ptrs = (1 << dip->i_di.di_depth) - start_lindex;
- int bufsize = tot_num_ptrs * sizeof(uint64_t);
- int off_by = cur_numleafs - correct_numleafs;
-
- ptrbuf = malloc(bufsize);
- if (!ptrbuf) {
- log_err( _("Error: Cannot allocate memory to fix the leaf "
- "pointers.\n"));
- return -1;
- }
- /* Read all the pointers, starting with the first bad one */
- count = gfs2_readi(dip, ptrbuf, start_lindex * sizeof(uint64_t),
- bufsize);
- if (count != bufsize) {
- log_err( _("Error: bad read while fixing leaf pointers.\n"));
- free(ptrbuf);
- return -1;
- }
-
- bufsize -= off_by * sizeof(uint64_t); /* We need to write fewer */
- /* Write the same pointers, but offset them so they fit within the
- smaller factor of 2. So if we have 12 pointers, write out only
- the last 8 of them. If we have 7, write the last 4, etc.
- We need to write these starting at the current lindex and adjust
- lindex accordingly. */
- count = gfs2_writei(dip, ptrbuf + (off_by * sizeof(uint64_t)),
- start_lindex * sizeof(uint64_t), bufsize);
- if (count != bufsize) {
- log_err( _("Error: bad read while fixing leaf pointers.\n"));
- free(ptrbuf);
- return -1;
- }
- /* Now zero out the hole left at the end */
- memset(ptrbuf, 0, off_by * sizeof(uint64_t));
- gfs2_writei(dip, ptrbuf, (start_lindex * sizeof(uint64_t)) +
- bufsize, off_by * sizeof(uint64_t));
- free(ptrbuf);
- *lindex -= off_by; /* adjust leaf index to account for the change */
- return 0;
-}
-
-/* check_num_ptrs - check a previously processed leaf's pointer count */
-static int check_num_ptrs(struct gfs2_inode *ip, uint64_t old_leaf,
- int *ref_count, int *exp_count, int *lindex,
- struct gfs2_leaf *oldleaf)
-{
- int factor = 0, divisor = *ref_count, multiple = 1, error = 0;
- struct gfs2_buffer_head *lbh;
-
- /* Check to see if the number of pointers we found is a power of 2.
- It needs to be and if it's not we need to fix it.*/
- while (divisor > 1) {
- factor++;
- divisor /= 2;
- multiple = multiple << 1;
- }
- if (*ref_count != multiple) {
- log_err( _("Directory #%llu (0x%llx) has an "
- "invalid number of pointers to "
- "leaf #%llu (0x%llx)\n\tFound: %u, "
- "which is not a factor of 2.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)old_leaf,
- (unsigned long long)old_leaf, *ref_count);
- if (!query( _("Attempt to fix it? (y/n) "))) {
- log_err( _("Directory inode was not fixed.\n"));
- return 1;
- }
- error = fix_leaf_pointers(ip, lindex, *ref_count, multiple);
- if (error)
- return error;
- *ref_count = multiple;
- log_err( _("Directory inode was fixed.\n"));
- }
- /* Check to see if the counted number of leaf pointers is what we
- expect. */
- if (*ref_count != *exp_count) {
- log_err( _("Directory #%llu (0x%llx) has an "
- "incorrect number of pointers to "
- "leaf #%llu (0x%llx)\n\tFound: "
- "%u, Expected: %u\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)old_leaf,
- (unsigned long long)old_leaf, *ref_count, *exp_count);
- if (!query( _("Attempt to fix it? (y/n) "))) {
- log_err( _("Directory leaf was not fixed.\n"));
- return 1;
- }
- lbh = bread(ip->i_sbd, old_leaf);
- gfs2_leaf_in(oldleaf, lbh);
- log_err( _("Leaf depth was %d, changed to %d\n"),
- oldleaf->lf_depth, ip->i_di.di_depth - factor);
- oldleaf->lf_depth = ip->i_di.di_depth - factor;
- gfs2_leaf_out(oldleaf, lbh);
- brelse(lbh);
- *exp_count = *ref_count;
- log_err( _("Directory leaf was fixed.\n"));
- }
- return 0;
-}
-
-/* Checks exhash directory entries */
-static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
-{
- int error;
- struct gfs2_leaf leaf, oldleaf;
- uint64_t leaf_no, old_leaf, bad_leaf = -1;
- uint64_t first_ok_leaf;
- struct gfs2_buffer_head *lbh;
- int lindex;
- struct gfs2_sbd *sbp = ip->i_sbd;
- uint16_t count;
- int ref_count = 0, exp_count = 0;
-
- /* Find the first valid leaf pointer in range and use it as our "old"
- leaf. That way, bad blocks at the beginning will be overwritten
- with the first valid leaf. */
- first_ok_leaf = leaf_no = -1;
- for(lindex = 0; lindex < (1 << ip->i_di.di_depth); lindex++) {
- gfs2_get_leaf_nr(ip, lindex, &leaf_no);
- if (gfs2_check_range(ip->i_sbd, leaf_no) == 0) {
- lbh = bread(sbp, leaf_no);
- /* Make sure it's really a valid leaf block. */
- if (gfs2_check_meta(lbh, GFS2_METATYPE_LF) == 0) {
- brelse(lbh);
- first_ok_leaf = leaf_no;
- break;
- }
- brelse(lbh);
- }
- }
- if (first_ok_leaf == -1) { /* no valid leaf found */
- log_err( _("Directory #%llu (0x%llx) has no valid leaf "
- "blocks\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- return 1;
- }
- old_leaf = -1;
- memset(&oldleaf, 0, sizeof(oldleaf));
- for(lindex = 0; lindex < (1 << ip->i_di.di_depth); lindex++) {
- if (fsck_abort)
- break;
- gfs2_get_leaf_nr(ip, lindex, &leaf_no);
-
- /* GFS has multiple indirect pointers to the same leaf
- * until those extra pointers are needed, so skip the
- * dups */
- if (leaf_no == bad_leaf) {
- gfs2_put_leaf_nr(ip, lindex, old_leaf); /* fill w/old
- leaf info */
- ref_count++;
- continue;
- } else if(old_leaf == leaf_no) {
- ref_count++;
- continue;
- }
-
- do {
- if (gfs2_check_range(ip->i_sbd, old_leaf) == 0) {
- error = check_num_ptrs(ip, old_leaf,
- &ref_count, &exp_count,
- &lindex, &oldleaf);
- if (error)
- return error;
- }
- ref_count = 1;
- count = 0;
- if (fsck_abort)
- break;
- /* Make sure the block number is in range. */
- if(gfs2_check_range(ip->i_sbd, leaf_no)){
- log_err( _("Leaf block #%llu (0x%llx) is out "
- "of range for directory #%llu (0x%llx"
- ").\n"), (unsigned long long)leaf_no,
- (unsigned long long)leaf_no,
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)
- ip->i_di.di_num.no_addr);
- warn_and_patch(ip, &leaf_no, &bad_leaf,
- old_leaf, first_ok_leaf, lindex,
- _("that is out of range"));
- memcpy(&leaf, &oldleaf, sizeof(oldleaf));
- break;
- }
-
- /* Try to read in the leaf block. */
- lbh = bread(sbp, leaf_no);
- /* Make sure it's really a valid leaf block. */
- if (gfs2_check_meta(lbh, GFS2_METATYPE_LF)) {
- warn_and_patch(ip, &leaf_no, &bad_leaf,
- old_leaf, first_ok_leaf, lindex,
- _("that is not really a leaf"));
- memcpy(&leaf, &oldleaf, sizeof(oldleaf));
- bmodified(lbh);
- brelse(lbh);
- break;
- }
- gfs2_leaf_in(&leaf, lbh);
- if(pass->check_leaf)
- error = pass->check_leaf(ip, leaf_no, lbh,
- pass->private);
-
- /*
- * Early versions of GFS2 had an endianess bug in the
- * kernel that set lf_dirent_format to
- * cpu_to_be16(GFS2_FORMAT_DE). This was fixed to use
- * cpu_to_be32(), but we should check for incorrect
- * values and replace them with the correct value. */
-
- if (leaf.lf_dirent_format == (GFS2_FORMAT_DE << 16)) {
- log_debug( _("incorrect lf_dirent_format at leaf #%" PRIu64 "\n"), leaf_no);
- leaf.lf_dirent_format = GFS2_FORMAT_DE;
- gfs2_leaf_out(&leaf, lbh);
- log_debug( _("Fixing lf_dirent_format.\n"));
- }
-
- /* Make sure it's really a leaf. */
- if (leaf.lf_header.mh_type != GFS2_METATYPE_LF) {
- log_err( _("Inode %llu (0x%llx"
- ") points to bad leaf %llu"
- " (0x%llx).\n"),
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)leaf_no,
- (unsigned long long)leaf_no);
- brelse(lbh);
- break;
- }
- exp_count = (1 << (ip->i_di.di_depth - leaf.lf_depth));
- /*log_debug( _("expected count %u - di_depth %u,
- leaf depth %u\n"),
- exp_count, ip->i_di.di_depth, leaf.lf_depth);*/
-
- if (pass->check_dentry && S_ISDIR(ip->i_di.di_mode)) {
- error = check_entries(ip, lbh, DIR_EXHASH,
- &count, pass);
- if(error < 0) {
- stack;
- brelse(lbh);
- return -1;
- }
-
- if(count != leaf.lf_entries) {
- brelse(lbh);
- lbh = bread(sbp, leaf_no);
- gfs2_leaf_in(&leaf, lbh);
-
- log_err( _("Leaf %llu (0x%llx) entry "
- "count in directory %llu"
- " (0x%llx) doesn't match "
- "number of entries found "
- "- is %u, found %u\n"),
- (unsigned long long)leaf_no,
- (unsigned long long)leaf_no,
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- leaf.lf_entries, count);
- if(query( _("Update leaf entry count? (y/n) "))) {
- leaf.lf_entries = count;
- gfs2_leaf_out(&leaf, lbh);
- log_warn( _("Leaf entry count updated\n"));
- } else
- log_err( _("Leaf entry count left in inconsistant state\n"));
- }
- }
- brelse(lbh);
- old_leaf = leaf_no;
- memcpy(&oldleaf, &leaf, sizeof(oldleaf));
- if (!leaf.lf_next)
- break;
- leaf_no = leaf.lf_next;
- log_debug( _("Leaf chain 0x%llx detected.\n"),
- (unsigned long long)leaf_no);
- } while(1); /* while we have chained leaf blocks */
- } /* for every leaf block */
- return 0;
-}
-
-static int check_eattr_entries(struct gfs2_inode *ip,
- struct gfs2_buffer_head *bh,
- struct metawalk_fxns *pass)
-{
- struct gfs2_ea_header *ea_hdr, *ea_hdr_prev = NULL;
- uint64_t *ea_data_ptr = NULL;
- int i;
- int error = 0;
- uint32_t offset = (uint32_t)sizeof(struct gfs2_meta_header);
-
- if(!pass->check_eattr_entry)
- return 0;
-
- ea_hdr = (struct gfs2_ea_header *)(bh->b_data +
- sizeof(struct gfs2_meta_header));
-
- while(1){
- if (ea_hdr->ea_type == GFS2_EATYPE_UNUSED)
- error = 0;
- else
- error = pass->check_eattr_entry(ip, bh, ea_hdr,
- ea_hdr_prev,
- pass->private);
- if(error < 0) {
- stack;
- return -1;
- }
- if(error == 0 && pass->check_eattr_extentry &&
- ea_hdr->ea_num_ptrs) {
- uint32_t tot_ealen = 0;
- struct gfs2_sbd *sdp = ip->i_sbd;
-
- ea_data_ptr = ((uint64_t *)((char *)ea_hdr +
- sizeof(struct gfs2_ea_header) +
- ((ea_hdr->ea_name_len + 7) & ~7)));
-
- /* It is possible when a EA is shrunk
- ** to have ea_num_ptrs be greater than
- ** the number required for ** data.
- ** In this case, the EA ** code leaves
- ** the blocks ** there for **
- ** reuse........... */
-
- for(i = 0; i < ea_hdr->ea_num_ptrs; i++){
- if(pass->check_eattr_extentry(ip,
- ea_data_ptr,
- bh, ea_hdr,
- ea_hdr_prev,
- pass->private)) {
- if (query( _("Repair the bad Extended "
- "Attribute? (y/n) "))) {
- ea_hdr->ea_num_ptrs = i;
- ea_hdr->ea_data_len =
- cpu_to_be32(tot_ealen);
- *ea_data_ptr = 0;
- bmodified(bh);
- /* Endianness doesn't matter
- in this case because it's
- a single byte. */
- fsck_blockmap_set(ip,
- ip->i_di.di_eattr,
- _("extended attribute"),
- gfs2_meta_eattr);
- log_err( _("The EA was "
- "fixed.\n"));
- } else {
- error = 1;
- log_err( _("The bad EA was "
- "not fixed.\n"));
- }
- }
- tot_ealen += sdp->sd_sb.sb_bsize -
- sizeof(struct gfs2_meta_header);
- ea_data_ptr++;
- }
- }
- offset += be32_to_cpu(ea_hdr->ea_rec_len);
- if(ea_hdr->ea_flags & GFS2_EAFLAG_LAST ||
- offset >= ip->i_sbd->sd_sb.sb_bsize || ea_hdr->ea_rec_len == 0){
- break;
- }
- ea_hdr_prev = ea_hdr;
- ea_hdr = (struct gfs2_ea_header *)
- ((char *)(ea_hdr) +
- be32_to_cpu(ea_hdr->ea_rec_len));
- }
-
- return error;
-}
-
-/**
- * check_leaf_eattr
- * @ip: the inode the eattr comes from
- * @block: block number of the leaf
- *
- * Returns: 0 on success, 1 if removal is needed, -1 on error
- */
-static int check_leaf_eattr(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct metawalk_fxns *pass)
-{
- struct gfs2_buffer_head *bh = NULL;
- int error = 0;
-
- log_debug( _("Checking EA leaf block #%"PRIu64" (0x%" PRIx64 ").\n"),
- block, block);
-
- if(pass->check_eattr_leaf) {
- error = pass->check_eattr_leaf(ip, block, parent, &bh,
- pass->private);
- if(error < 0) {
- stack;
- return -1;
- }
- if(error > 0) {
- if (bh)
- brelse(bh);
- return 1;
- }
- if (bh) {
- error = check_eattr_entries(ip, bh, pass);
- brelse(bh);
- }
- return error;
- }
-
- return 0;
-}
-
-/**
- * delete_block - delete a block associated with an inode
- */
-int delete_block(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, const char *btype,
- void *private)
-{
- if (gfs2_check_range(ip->i_sbd, block) == 0) {
- fsck_blockmap_set(ip, block, btype, gfs2_block_free);
- return 0;
- }
- return -1;
-}
-
-/**
- * delete_block_if_notdup - delete blocks associated with an inode
- *
- * Ignore blocks that are already marked free.
- * If it has been identified as duplicate, remove the duplicate reference.
- * If all duplicate references have been removed, delete the block.
- */
-static int delete_block_if_notdup(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh,
- const char *btype, void *private)
-{
- uint8_t q;
- struct duptree *d;
-
- if (gfs2_check_range(ip->i_sbd, block) != 0)
- return -EFAULT;
-
- q = block_type(block);
- if (q == gfs2_block_free) {
- log_info( _("%s block %lld (0x%llx), part of inode "
- "%lld (0x%llx), was already free.\n"),
- btype, (unsigned long long)block,
- (unsigned long long)block,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- return 0;
- }
- d = dupfind(block);
- if (d) {
- log_info( _("Removing duplicate reference %d "
- "to block %lld (0x%llx).\n"), d->refs,
- (unsigned long long)block,
- (unsigned long long)block);
- d->refs--; /* one less reference */
- if (d->refs == 1) /* If down to the last reference */
- dup_delete(d); /* not duplicate now */
- return 1; /* but the original ref still exists
- so return (do not free it). */
- }
- fsck_blockmap_set(ip, block, btype, gfs2_block_free);
- return 0;
-}
-
-/**
- * check_indirect_eattr
- * @ip: the inode the eattr comes from
- * @indirect_block
- *
- * Returns: 0 on success -1 on error
- */
-static int check_indirect_eattr(struct gfs2_inode *ip, uint64_t indirect,
- struct metawalk_fxns *pass)
-{
- int error = 0;
- uint64_t *ea_leaf_ptr, *end;
- uint64_t block;
- struct gfs2_buffer_head *indirect_buf = NULL;
- struct gfs2_sbd *sdp = ip->i_sbd;
- int first_ea_is_bad = 0;
- uint64_t di_eattr_save = ip->i_di.di_eattr;
-
- log_debug( _("Checking EA indirect block #%"PRIu64" (0x%" PRIx64 ").\n"),
- indirect, indirect);
-
- if (!pass->check_eattr_indir)
- return 0;
- error = pass->check_eattr_indir(ip, indirect, ip->i_di.di_num.no_addr,
- &indirect_buf, pass->private);
- if (!error) {
- int leaf_pointers = 0, leaf_pointer_errors = 0;
-
- ea_leaf_ptr = (uint64_t *)(indirect_buf->b_data
- + sizeof(struct gfs2_meta_header));
- end = ea_leaf_ptr + ((sdp->sd_sb.sb_bsize
- - sizeof(struct gfs2_meta_header)) / 8);
-
- while(*ea_leaf_ptr && (ea_leaf_ptr < end)){
- block = be64_to_cpu(*ea_leaf_ptr);
- leaf_pointers++;
- error = check_leaf_eattr(ip, block, indirect, pass);
- if (error) {
- leaf_pointer_errors++;
- if (query( _("Fix the indirect "
- "block too? (y/n) ")))
- *ea_leaf_ptr = 0;
- }
- /* If the first eattr lead is bad, we can't have
- a hole, so we have to treat this as an unrecoverable
- eattr error and delete all eattr info. Calling
- finish_eattr_indir here causes ip->i_di.di_eattr = 0
- and that ensures that subsequent calls to
- check_leaf_eattr result in the eattr
- check_leaf_block nuking them all "due to previous
- errors" */
- if (leaf_pointers == 1 && leaf_pointer_errors == 1) {
- first_ea_is_bad = 1;
- if (pass->finish_eattr_indir)
- pass->finish_eattr_indir(ip,
- leaf_pointers,
- leaf_pointer_errors,
- pass->private);
- } else if (leaf_pointer_errors) {
- /* This is a bit tricky. We can't have eattr
- holes. So if we have 4 good eattrs, 1 bad
- eattr and 5 more good ones: GGGGBGGGGG,
- we need to tell check_leaf_eattr to delete
- all eattrs after the bad one. So we want:
- GGGG when we finish. To do that, we set
- di_eattr to 0 temporarily. */
- ip->i_di.di_eattr = 0;
- bmodified(ip->i_bh);
- }
- ea_leaf_ptr++;
- }
- if (pass->finish_eattr_indir) {
- if (!first_ea_is_bad) {
- /* If the first ea is good but subsequent ones
- were bad and deleted, we need to restore
- the saved di_eattr block. */
- if (leaf_pointer_errors)
- ip->i_di.di_eattr = di_eattr_save;
- pass->finish_eattr_indir(ip, leaf_pointers,
- leaf_pointer_errors,
- pass->private);
- }
- if (leaf_pointer_errors &&
- leaf_pointer_errors == leaf_pointers) {
- delete_block(ip, indirect, NULL, "leaf", NULL);
- error = 1;
- }
- }
- }
- if (indirect_buf)
- brelse(indirect_buf);
-
- return error;
-}
-
-/**
- * check_inode_eattr - check the EA's for a single inode
- * @ip: the inode whose EA to check
- *
- * Returns: 0 on success, -1 on error
- */
-int check_inode_eattr(struct gfs2_inode *ip, struct metawalk_fxns *pass)
-{
- int error = 0;
-
- if(!ip->i_di.di_eattr)
- return 0;
-
- log_debug( _("Extended attributes exist for inode #%llu (0x%llx).\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
-
- if(ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT){
- if((error = check_indirect_eattr(ip, ip->i_di.di_eattr, pass)))
- stack;
- } else {
- error = check_leaf_eattr(ip, ip->i_di.di_eattr,
- ip->i_di.di_num.no_addr, pass);
- if (error)
- stack;
- }
-
- return error;
-}
-
-/**
- * free_metalist - free all metadata on a multi-level metadata list
- */
-static void free_metalist(struct gfs2_inode *ip, osi_list_t *mlp)
-{
- int i;
- struct gfs2_buffer_head *nbh;
-
- for (i = 0; i < GFS2_MAX_META_HEIGHT; i++) {
- osi_list_t *list;
-
- list = &mlp[i];
- while (!osi_list_empty(list)) {
- nbh = osi_list_entry(list->next,
- struct gfs2_buffer_head, b_altlist);
- if (nbh == ip->i_bh)
- osi_list_del(&nbh->b_altlist);
- else
- brelse(nbh);
- }
- }
-}
-
-/**
- * build_and_check_metalist - check a bunch of indirect blocks
- * This includes hash table blocks for directories
- * which are technically "data" in the bitmap.
- *
- * @ip:
- * @mlp:
- */
-static int build_and_check_metalist(struct gfs2_inode *ip, osi_list_t *mlp,
- struct metawalk_fxns *pass)
-{
- uint32_t height = ip->i_di.di_height;
- struct gfs2_buffer_head *bh, *nbh, *metabh = ip->i_bh;
- osi_list_t *prev_list, *cur_list, *tmp;
- int h, head_size, iblk_type;
- uint64_t *ptr, block;
- int error = 0, err;
-
- osi_list_add(&metabh->b_altlist, &mlp[0]);
-
- /* Directories are special. Their 'data' is the hash table, which is
- basically an indirect block list. Their height is not important
- because it checks everything through the hash table using
- "depth" field calculations. However, we still have to check the
- indirect blocks, even if the height == 1. */
- if (S_ISDIR(ip->i_di.di_mode))
- height++;
-
- /* if(<there are no indirect blocks to check>) */
- if (height < 2)
- return 0;
- for (h = 1; h < height; h++) {
- if (h > 1) {
- if (S_ISDIR(ip->i_di.di_mode) &&
- h == ip->i_di.di_height + 1)
- iblk_type = GFS2_METATYPE_JD;
- else
- iblk_type = GFS2_METATYPE_IN;
- head_size = sizeof(struct gfs2_meta_header);
- } else {
- iblk_type = GFS2_METATYPE_DI;
- head_size = sizeof(struct gfs2_dinode);
- }
- prev_list = &mlp[h - 1];
- cur_list = &mlp[h];
-
- for (tmp = prev_list->next; tmp != prev_list; tmp = tmp->next){
- bh = osi_list_entry(tmp, struct gfs2_buffer_head,
- b_altlist);
-
- if (gfs2_check_meta(bh, iblk_type))
- continue;
-
- /* Now check the metadata itself */
- for (ptr = (uint64_t *)(bh->b_data + head_size);
- (char *)ptr < (bh->b_data + ip->i_sbd->bsize);
- ptr++) {
- if (skip_this_pass || fsck_abort)
- return FSCK_OK;
- nbh = NULL;
-
- if (!*ptr)
- continue;
-
- block = be64_to_cpu(*ptr);
- err = pass->check_metalist(ip, block, &nbh, h,
- pass->private);
- /* check_metalist should hold any buffers
- it gets with "bread". */
- if(err < 0) {
- stack;
- error = err;
- goto fail;
- }
- if(err > 0) {
- if (!error)
- error = err;
- log_debug( _("Skipping block %" PRIu64
- " (0x%" PRIx64 ")\n"),
- block, block);
- continue;
- }
- if (gfs2_check_range(ip->i_sbd, block)) {
- log_debug( _("Skipping invalid block "
- "%lld (0x%llx)\n"),
- (unsigned long long)block,
- (unsigned long long)block);
- continue;
- }
- if(!nbh)
- nbh = bread(ip->i_sbd, block);
- osi_list_add(&nbh->b_altlist, cur_list);
- } /* for all data on the indirect block */
- } /* for blocks at that height */
- } /* for height */
- return error;
-fail:
- free_metalist(ip, mlp);
- return error;
-}
-
-/**
- * check_data - check all data pointers for a given buffer
- * This does not include "data" blocks that are really
- * hash table blocks for directories.
- *
- * @ip:
- *
- * returns: +ENOENT if there are too many bad pointers
- * -1 if a more serious error occurred.
- * 0 if no errors occurred
- * 1 if errors were found and corrected
- * 2 (ENOENT) is there were too many bad pointers
- */
-static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass,
- uint64_t *ptr_start, char *ptr_end,
- uint64_t *blks_checked)
-{
- int error = 0, rc = 0;
- uint64_t block, *ptr;
-
- /* If there isn't much pointer corruption check the pointers */
- for (ptr = ptr_start ; (char *)ptr < ptr_end && !fsck_abort; ptr++) {
- if (!*ptr)
- continue;
-
- if (skip_this_pass || fsck_abort)
- return error;
- block = be64_to_cpu(*ptr);
- /* It's important that we don't call gfs2_check_range and
- bypass calling check_data on invalid blocks because that
- would defeat the rangecheck_block related functions in
- pass1. Therefore the individual check_data functions
- should do a range check. */
- rc = pass->check_data(ip, block, pass->private);
- if (rc < 0)
- return rc;
- if (!error && rc)
- error = rc;
- (*blks_checked)++;
- }
- return error;
-}
-
-/**
- * check_metatree
- * @ip:
- * @rgd:
- *
- */
-int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
-{
- osi_list_t metalist[GFS2_MAX_META_HEIGHT];
- osi_list_t *list;
- struct gfs2_buffer_head *bh;
- uint32_t height = ip->i_di.di_height;
- int i, head_size;
- uint64_t blks_checked = 0;
- int error, rc;
-
- if (!height && !S_ISDIR(ip->i_di.di_mode))
- return 0;
-
- for (i = 0; i < GFS2_MAX_META_HEIGHT; i++)
- osi_list_init(&metalist[i]);
-
- /* create and check the metadata list for each height */
- error = build_and_check_metalist(ip, &metalist[0], pass);
- if (error) {
- stack;
- return error;
- }
-
- /* For directories, we've already checked the "data" blocks which
- * comprise the directory hash table, so we perform the directory
- * checks and exit. */
- if (S_ISDIR(ip->i_di.di_mode)) {
- free_metalist(ip, &metalist[0]);
- if (!(ip->i_di.di_flags & GFS2_DIF_EXHASH))
- return 0;
- /* check validity of leaf blocks and leaf chains */
- error = check_leaf_blks(ip, pass);
- return error;
- }
-
- /* Free the metalist buffers from heights we don't need to check.
- For the rest we'll free as we check them to save time.
- metalist[0] will only have the dinode bh, so we can skip it. */
- for (i = 1; i < height - 1; i++) {
- list = &metalist[i];
- while (!osi_list_empty(list)) {
- bh = osi_list_entry(list->next,
- struct gfs2_buffer_head, b_altlist);
- if (bh == ip->i_bh)
- osi_list_del(&bh->b_altlist);
- else
- brelse(bh);
- }
- }
-
- /* check data blocks */
- list = &metalist[height - 1];
- if (ip->i_di.di_blocks > COMFORTABLE_BLKS)
- last_reported_fblock = -10000000;
-
- while (error >= 0 && !osi_list_empty(list)) {
- if (fsck_abort)
- return 0;
- bh = osi_list_entry(list->next, struct gfs2_buffer_head,
- b_altlist);
-
- if (height > 1) {
- if (gfs2_check_meta(bh, GFS2_METATYPE_IN)) {
- if (bh == ip->i_bh)
- osi_list_del(&bh->b_altlist);
- else
- brelse(bh);
- continue;
- }
- head_size = sizeof(struct gfs2_meta_header);
- } else {
- /* if this isn't really a dinode, skip it */
- if (gfs2_check_meta(bh, GFS2_METATYPE_DI)) {
- if (bh == ip->i_bh)
- osi_list_del(&bh->b_altlist);
- else
- brelse(bh);
- continue;
- }
- head_size = sizeof(struct gfs2_dinode);
- }
-
- if (pass->check_data)
- rc = check_data(ip, pass, (uint64_t *)
- (bh->b_data + head_size),
- (bh->b_data + ip->i_sbd->bsize),
- &blks_checked);
- else
- rc = 0;
-
- if (rc && (!error || rc < 0))
- error = rc;
- if (pass->big_file_msg && ip->i_di.di_blocks > COMFORTABLE_BLKS)
- pass->big_file_msg(ip, blks_checked);
- if (bh == ip->i_bh)
- osi_list_del(&bh->b_altlist);
- else
- brelse(bh);
- }
- if (pass->big_file_msg && ip->i_di.di_blocks > COMFORTABLE_BLKS) {
- log_notice( _("\rLarge file at %lld (0x%llx) - 100 percent "
- "complete. "
- "\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- fflush(stdout);
- }
- return error;
-}
-
-/* Checks stuffed inode directories */
-int check_linear_dir(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
- struct metawalk_fxns *pass)
-{
- int error = 0;
- uint16_t count = 0;
-
- error = check_entries(ip, bh, DIR_LINEAR, &count, pass);
- if(error < 0) {
- stack;
- return -1;
- }
-
- return error;
-}
-
-int check_dir(struct gfs2_sbd *sbp, uint64_t block, struct metawalk_fxns *pass)
-{
- struct gfs2_inode *ip;
- int error = 0;
-
- ip = fsck_load_inode(sbp, block);
-
- if(ip->i_di.di_flags & GFS2_DIF_EXHASH)
- error = check_leaf_blks(ip, pass);
- else
- error = check_linear_dir(ip, ip->i_bh, pass);
-
- if(error < 0)
- stack;
-
- fsck_inode_put(&ip); /* does a brelse */
- return error;
-}
-
-static int remove_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
- struct gfs2_dirent *prev_de,
- struct gfs2_buffer_head *bh,
- char *filename, uint16_t *count, void *private)
-{
- /* the metawalk_fxn's private field must be set to the dentry
- * block we want to clear */
- uint64_t *dentryblock = (uint64_t *) private;
- struct gfs2_dirent dentry, *de;
-
- memset(&dentry, 0, sizeof(struct gfs2_dirent));
- gfs2_dirent_in(&dentry, (char *)dent);
- de = &dentry;
-
- if(de->de_inum.no_addr == *dentryblock)
- dirent2_del(ip, bh, prev_de, dent);
- else
- (*count)++;
-
- return 0;
-
-}
-
-int remove_dentry_from_dir(struct gfs2_sbd *sbp, uint64_t dir,
- uint64_t dentryblock)
-{
- struct metawalk_fxns remove_dentry_fxns = {0};
- uint8_t q;
- int error;
-
- log_debug( _("Removing dentry %" PRIu64 " (0x%" PRIx64 ") from directory %"
- PRIu64" (0x%" PRIx64 ")\n"), dentryblock, dentryblock, dir, dir);
- if(gfs2_check_range(sbp, dir)) {
- log_err( _("Parent directory out of range\n"));
- return 1;
- }
- remove_dentry_fxns.private = &dentryblock;
- remove_dentry_fxns.check_dentry = remove_dentry;
-
- q = block_type(dir);
- if(q != gfs2_inode_dir) {
- log_info( _("Parent block is not a directory...ignoring\n"));
- return 1;
- }
- /* Need to run check_dir with a private var of dentryblock,
- * and fxns that remove that dentry if found */
- error = check_dir(sbp, dir, &remove_dentry_fxns);
-
- return error;
-}
-
-int delete_metadata(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h, void *private)
-{
- return delete_block_if_notdup(ip, block, bh, _("metadata"), private);
-}
-
-int delete_leaf(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head *bh, void *private)
-{
- return delete_block_if_notdup(ip, block, &bh, _("leaf"), private);
-}
-
-int delete_data(struct gfs2_inode *ip, uint64_t block, void *private)
-{
- return delete_block_if_notdup(ip, block, NULL, _("data"), private);
-}
-
-int delete_eattr_indir(struct gfs2_inode *ip, uint64_t block, uint64_t parent,
- struct gfs2_buffer_head **bh, void *private)
-{
- return delete_block_if_notdup(ip, block, NULL,
- _("indirect extended attribute"),
- private);
-}
-
-int delete_eattr_leaf(struct gfs2_inode *ip, uint64_t block, uint64_t parent,
- struct gfs2_buffer_head **bh, void *private)
-{
- return delete_block_if_notdup(ip, block, NULL, _("extended attribute"),
- private);
-}
-
-static int alloc_metalist(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h, void *private)
-{
- uint8_t q;
- const char *desc = (const char *)private;
-
- /* No need to range_check here--if it was added, it's in range. */
- /* We can't check the bitmap here because this function is called
- after the bitmap has been set but before the blockmap has. */
- *bh = bread(ip->i_sbd, block);
- q = block_type(block);
- if (blockmap_to_bitmap(q) == GFS2_BLKST_FREE) { /* If not marked yet */
- log_debug(_("%s reference to new metadata block "
- "%lld (0x%llx) is now marked as indirect.\n"),
- desc, (unsigned long long)block,
- (unsigned long long)block);
- gfs2_blockmap_set(bl, block, gfs2_indir_blk);
- }
- return 0;
-}
-
-static int alloc_data(struct gfs2_inode *ip, uint64_t block, void *private)
-{
- uint8_t q;
- const char *desc = (const char *)private;
-
- /* No need to range_check here--if it was added, it's in range. */
- /* We can't check the bitmap here because this function is called
- after the bitmap has been set but before the blockmap has. */
- q = block_type(block);
- if (blockmap_to_bitmap(q) == GFS2_BLKST_FREE) { /* If not marked yet */
- log_debug(_("%s reference to new data block "
- "%lld (0x%llx) is now marked as data.\n"),
- desc, (unsigned long long)block,
- (unsigned long long)block);
- gfs2_blockmap_set(bl, block, gfs2_block_used);
- }
- return 0;
-}
-
-static int alloc_leaf(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head *bh, void *private)
-{
- uint8_t q;
-
- /* No need to range_check here--if it was added, it's in range. */
- /* We can't check the bitmap here because this function is called
- after the bitmap has been set but before the blockmap has. */
- q = block_type(block);
- if (blockmap_to_bitmap(q) == GFS2_BLKST_FREE) /* If not marked yet */
- fsck_blockmap_set(ip, block, _("newly allocated leaf"),
- gfs2_leaf_blk);
- return 0;
-}
-
-struct metawalk_fxns alloc_fxns = {
- .private = NULL,
- .check_leaf = alloc_leaf,
- .check_metalist = alloc_metalist,
- .check_data = alloc_data,
- .check_eattr_indir = NULL,
- .check_eattr_leaf = NULL,
- .check_dentry = NULL,
- .check_eattr_entry = NULL,
- .check_eattr_extentry = NULL,
- .finish_eattr_indir = NULL,
-};
-
-/*
- * reprocess_inode - fixes the blockmap to match the bitmap due to an
- * unexpected block allocation via libgfs2.
- *
- * The problem we're trying to overcome here is when a new block must be
- * added to a dinode because of a write. This will happen when lost+found
- * needs a new indirect block for its hash table. In that case, the write
- * causes a new block to be assigned in the bitmap but that block is not yet
- * accurately reflected in the fsck blockmap. We need to compensate here.
- *
- * We can't really use fsck_blockmap_set here because the new block
- * was already allocated by libgfs2 and therefore it took care of
- * the rgrp free space variable. fsck_blockmap_set adjusts the free space
- * in the rgrp according to the change, which has already been done.
- * So it's only our blockmap that now disagrees with the rgrp bitmap, so we
- * need to fix only that.
- */
-void reprocess_inode(struct gfs2_inode *ip, const char *desc)
-{
- int error;
-
- alloc_fxns.private = (void *)desc;
- log_info( _("%s had blocks added; reprocessing its metadata tree "
- "at height=%d.\n"), desc, ip->i_di.di_height);
- error = check_metatree(ip, &alloc_fxns);
- if (error)
- log_err( _("Error %d reprocessing the %s metadata tree.\n"),
- error, desc);
-}
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
deleted file mode 100644
index 3ee12fe..0000000
--- a/gfs2/fsck/metawalk.h
+++ /dev/null
@@ -1,95 +0,0 @@
-#ifndef _METAWALK_H
-#define _METAWALK_H
-
-#define DIR_LINEAR 1
-#define DIR_EXHASH 2
-
-struct metawalk_fxns;
-
-extern int check_inode_eattr(struct gfs2_inode *ip,
- struct metawalk_fxns *pass);
-extern int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass);
-extern int check_dir(struct gfs2_sbd *sbp, uint64_t block,
- struct metawalk_fxns *pass);
-extern int check_linear_dir(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
- struct metawalk_fxns *pass);
-extern int remove_dentry_from_dir(struct gfs2_sbd *sbp, uint64_t dir,
- uint64_t dentryblock);
-extern int delete_block(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, const char *btype,
- void *private);
-extern int delete_metadata(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h, void *private);
-extern int delete_leaf(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head *bh, void *private);
-extern int delete_data(struct gfs2_inode *ip, uint64_t block, void *private);
-extern int delete_eattr_indir(struct gfs2_inode *ip, uint64_t block, uint64_t parent,
- struct gfs2_buffer_head **bh, void *private);
-extern int delete_eattr_leaf(struct gfs2_inode *ip, uint64_t block, uint64_t parent,
- struct gfs2_buffer_head **bh, void *private);
-extern int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
- const char *btype, enum gfs2_mark_block mark,
- const char *caller, int line);
-extern int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk,
- enum gfs2_mark_block new_blockmap_state);
-extern void reprocess_inode(struct gfs2_inode *ip, const char *desc);
-extern struct duptree *dupfind(uint64_t block);
-extern struct gfs2_inode *fsck_system_inode(struct gfs2_sbd *sdp,
- uint64_t block);
-
-#define is_duplicate(dblock) ((dupfind(dblock)) ? 1 : 0)
-
-#define fsck_blockmap_set(ip, b, bt, m) _fsck_blockmap_set(ip, b, bt, m, \
- __FILE__, __LINE__)
-
-/* metawalk_fxns: function pointers to check various parts of the fs
- *
- * The functions should return -1 on fatal errors, 1 if the block
- * should be skipped, and 0 on success
- *
- * private: Data that should be passed to the fxns
- * check_leaf:
- * check_metalist:
- * check_data:
- * check_eattr_indir:
- * check_eattr_leaf:
- * check_dentry:
- * check_eattr_entry:
- * check_eattr_extentry:
- */
-struct metawalk_fxns {
- void *private;
- int (*check_leaf) (struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head *bh, void *private);
- int (*check_metalist) (struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h,
- void *private);
- int (*check_data) (struct gfs2_inode *ip, uint64_t block,
- void *private);
- int (*check_eattr_indir) (struct gfs2_inode *ip, uint64_t block,
- uint64_t parent,
- struct gfs2_buffer_head **bh, void *private);
- int (*check_eattr_leaf) (struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private);
- int (*check_dentry) (struct gfs2_inode *ip, struct gfs2_dirent *de,
- struct gfs2_dirent *prev,
- struct gfs2_buffer_head *bh,
- char *filename, uint16_t *count, void *private);
- int (*check_eattr_entry) (struct gfs2_inode *ip,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private);
- int (*check_eattr_extentry) (struct gfs2_inode *ip,
- uint64_t *ea_data_ptr,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private);
- int (*finish_eattr_indir) (struct gfs2_inode *ip, int leaf_pointers,
- int leaf_pointer_errors, void *private);
- void (*big_file_msg) (struct gfs2_inode *ip, uint64_t blks_checked);
-};
-
-#endif /* _METAWALK_H */
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
deleted file mode 100644
index 6613bd1..0000000
--- a/gfs2/fsck/pass1.c
+++ /dev/null
@@ -1,1480 +0,0 @@
-/* pass1 checks inodes for format & type, duplicate blocks, & incorrect
- * block count.
- *
- * It builds up tables that contains the state of each block (free,
- * block in use, metadata type, etc), as well as bad blocks and
- * duplicate blocks. (See block_list.[ch] for more info)
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <string.h>
-#include <time.h>
-#include <sys/ioctl.h>
-#include <inttypes.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "fsck.h"
-#include "inode_hash.h"
-#include "util.h"
-#include "link.h"
-#include "metawalk.h"
-
-struct block_count {
- uint64_t indir_count;
- uint64_t data_count;
- uint64_t ea_count;
-};
-
-static int leaf(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head *bh, void *private);
-static int check_metalist(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h, void *private);
-static int undo_check_metalist(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h,
- void *private);
-static int check_data(struct gfs2_inode *ip, uint64_t block, void *private);
-static int undo_check_data(struct gfs2_inode *ip, uint64_t block,
- void *private);
-static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private);
-static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private);
-static int check_eattr_entries(struct gfs2_inode *ip,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private);
-static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t *data_ptr,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private);
-static int finish_eattr_indir(struct gfs2_inode *ip, int leaf_pointers,
- int leaf_pointer_errors, void *private);
-static int invalidate_metadata(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h,
- void *private);
-static int invalidate_leaf(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head *bh, void *private);
-static int invalidate_data(struct gfs2_inode *ip, uint64_t block,
- void *private);
-static int invalidate_eattr_indir(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent,
- struct gfs2_buffer_head **bh,
- void *private);
-static int invalidate_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private);
-static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip);
-
-struct metawalk_fxns pass1_fxns = {
- .private = NULL,
- .check_leaf = leaf,
- .check_metalist = check_metalist,
- .check_data = check_data,
- .check_eattr_indir = check_eattr_indir,
- .check_eattr_leaf = check_eattr_leaf,
- .check_dentry = NULL,
- .check_eattr_entry = check_eattr_entries,
- .check_eattr_extentry = check_extended_leaf_eattr,
- .finish_eattr_indir = finish_eattr_indir,
- .big_file_msg = big_file_comfort,
-};
-
-struct metawalk_fxns undo_fxns = {
- .private = NULL,
- .check_metalist = undo_check_metalist,
- .check_data = undo_check_data,
-};
-
-struct metawalk_fxns invalidate_fxns = {
- .private = NULL,
- .check_metalist = invalidate_metadata,
- .check_data = invalidate_data,
- .check_leaf = invalidate_leaf,
- .check_eattr_indir = invalidate_eattr_indir,
- .check_eattr_leaf = invalidate_eattr_leaf,
-};
-
-/*
- * resuscitate_metalist - make sure a system directory entry's metadata blocks
- * are marked "in use" in the bitmap.
- *
- * This function makes sure metadata blocks for system and root directories are
- * marked "in use" by the bitmap. You don't want root's indirect blocks
- * deleted, do you? Or worse, reused for lost+found.
- */
-static int resuscitate_metalist(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h,
- void *private)
-{
- struct block_count *bc = (struct block_count *)private;
-
- *bh = NULL;
- if (gfs2_check_range(ip->i_sbd, block)){ /* blk outside of FS */
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("itself"), gfs2_bad_block);
- log_err( _("Bad indirect block pointer (out of range) "
- "found in system inode %lld (0x%llx).\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- return 1;
- }
- if (fsck_system_inode(ip->i_sbd, block))
- fsck_blockmap_set(ip, block, _("system file"), gfs2_indir_blk);
- else
- check_n_fix_bitmap(ip->i_sbd, block, gfs2_indir_blk);
- bc->indir_count++;
- return 0;
-}
-
-/*
- * resuscitate_dentry - make sure a system directory entry is alive
- *
- * This function makes sure directory entries in system directories are
- * kept alive. You don't want journal0 deleted from jindex, do you?
- */
-static int resuscitate_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
- struct gfs2_dirent *prev_de,
- struct gfs2_buffer_head *bh, char *filename,
- uint16_t *count, void *priv)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_dirent dentry, *de;
- char tmp_name[PATH_MAX];
- uint64_t block;
- enum gfs2_mark_block dinode_type;
-
- memset(&dentry, 0, sizeof(struct gfs2_dirent));
- gfs2_dirent_in(&dentry, (char *)dent);
- de = &dentry;
- block = de->de_inum.no_addr;
- /* Start of checks */
- memset(tmp_name, 0, sizeof(tmp_name));
- if(de->de_name_len < sizeof(tmp_name))
- strncpy(tmp_name, filename, de->de_name_len);
- else
- strncpy(tmp_name, filename, sizeof(tmp_name) - 1);
- if(gfs2_check_range(sdp, block)) {
- log_err( _("Block # referenced by system directory entry %s "
- "in inode %lld (0x%llx) is out of range; "
- "ignored.\n"),
- tmp_name, (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- return 0;
- }
- if (block == sdp->md.jiinode->i_di.di_num.no_addr ||
- block == sdp->md.pinode->i_di.di_num.no_addr ||
- block == sdp->master_dir->i_di.di_num.no_addr)
- dinode_type = gfs2_inode_dir;
- else
- dinode_type = gfs2_inode_file;
- /* If this is a system dinode, we'll handle it later in
- check_system_inodes. If not, it'll be handled by pass1 but
- since it's in a system directory we need to make sure it's
- represented in the rgrp bitmap. */
- if (fsck_system_inode(sdp, block))
- fsck_blockmap_set(ip, block, _("system file"), dinode_type);
- else
- check_n_fix_bitmap(sdp, block, dinode_type);
- /* Return the number of leaf entries so metawalk doesn't flag this
- leaf as having none. */
- *count = be16_to_cpu(((struct gfs2_leaf *)bh->b_data)->lf_entries);
- return 0;
-}
-
-struct metawalk_fxns sysdir_fxns = {
- .private = NULL,
- .check_metalist = resuscitate_metalist,
- .check_dentry = resuscitate_dentry,
-};
-
-static int leaf(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head *bh, void *private)
-{
- struct block_count *bc = (struct block_count *) private;
-
- fsck_blockmap_set(ip, block, _("directory leaf"), gfs2_leaf_blk);
- bc->indir_count++;
- return 0;
-}
-
-static int check_metalist(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h, void *private)
-{
- uint8_t q;
- int found_dup = 0, iblk_type;
- struct gfs2_buffer_head *nbh;
- struct block_count *bc = (struct block_count *)private;
- const char *blktypedesc;
-
- *bh = NULL;
-
- if (gfs2_check_range(ip->i_sbd, block)){ /* blk outside of FS */
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("itself"), gfs2_bad_block);
- log_debug( _("Bad indirect block pointer (out of range) "
- "found in inode %lld (0x%llx).\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
-
- return 1;
- }
- if (S_ISDIR(ip->i_di.di_mode) && h == ip->i_di.di_height) {
- iblk_type = GFS2_METATYPE_JD;
- blktypedesc = _("a directory hash table block");
- } else {
- iblk_type = GFS2_METATYPE_IN;
- blktypedesc = _("a journaled data block");
- }
- q = block_type(block);
- if(q != gfs2_block_free) {
- log_err( _("Found duplicate block %llu (0x%llx) referenced "
- "as metadata in indirect block for dinode "
- "%llu (0x%llx) - was marked %d (%s)\n"),
- (unsigned long long)block,
- (unsigned long long)block,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr, q,
- block_type_string(q));
- add_duplicate_ref(ip, block, ref_as_meta, 0, INODE_VALID);
- found_dup = 1;
- }
- nbh = bread(ip->i_sbd, block);
-
- if (gfs2_check_meta(nbh, iblk_type)){
- log_err( _("Inode %lld (0x%llx) has a bad indirect block "
- "pointer %lld (0x%llx) (points to something "
- "that is not %s).\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)block,
- (unsigned long long)block, blktypedesc);
- if(!found_dup) {
- fsck_blockmap_set(ip, block, _("bad indirect"),
- gfs2_meta_inval);
- brelse(nbh);
- return 1;
- }
- brelse(nbh);
- nbh = NULL;
- } else /* blk check ok */
- *bh = nbh;
-
- bc->indir_count++;
- if (found_dup) {
- if (nbh)
- brelse(nbh);
- return 1; /* don't process the metadata again */
- } else
- fsck_blockmap_set(ip, block, _("indirect"),
- gfs2_indir_blk);
-
- return 0;
-}
-
-static int undo_check_metalist(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h,
- void *private)
-{
- struct duptree *d;
- int found_dup = 0, iblk_type;
- struct gfs2_buffer_head *nbh;
- struct block_count *bc = (struct block_count *)private;
-
- *bh = NULL;
-
- if (gfs2_check_range(ip->i_sbd, block)){ /* blk outside of FS */
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("itself"), gfs2_block_free);
- return 1;
- }
- if (S_ISDIR(ip->i_di.di_mode) && h == ip->i_di.di_height)
- iblk_type = GFS2_METATYPE_JD;
- else
- iblk_type = GFS2_METATYPE_IN;
-
- d = dupfind(block);
- if (d) {
- log_err( _("Reversing duplicate status of block %llu (0x%llx) "
- "referenced as metadata in indirect block for "
- "dinode %llu (0x%llx)\n"),
- (unsigned long long)block,
- (unsigned long long)block,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- d->refs--; /* one less reference */
- if (d->refs == 1)
- dup_delete(d);
- found_dup = 1;
- }
- nbh = bread(ip->i_sbd, block);
-
- if (gfs2_check_meta(nbh, iblk_type)) {
- if(!found_dup) {
- fsck_blockmap_set(ip, block, _("bad indirect"),
- gfs2_block_free);
- brelse(nbh);
- return 1;
- }
- brelse(nbh);
- nbh = NULL;
- } else /* blk check ok */
- *bh = nbh;
-
- bc->indir_count--;
- if (found_dup) {
- if (nbh)
- brelse(nbh);
- *bh = NULL;
- return 1; /* don't process the metadata again */
- } else
- fsck_blockmap_set(ip, block, _("bad indirect"),
- gfs2_block_free);
- return 0;
-}
-
-static int check_data(struct gfs2_inode *ip, uint64_t block, void *private)
-{
- uint8_t q;
- struct block_count *bc = (struct block_count *) private;
-
- if (gfs2_check_range(ip->i_sbd, block)) {
- log_err( _("inode %lld (0x%llx) has a bad data block pointer "
- "%lld (out of range)\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)block);
- /* Mark the owner of this block with the bad_block
- * designator so we know to check it for out of range
- * blocks later */
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("bad (out of range) data"),
- gfs2_bad_block);
- return 1;
- }
- q = block_type(block);
- if (q != gfs2_block_free) {
- log_err( _("Found duplicate %s block %llu (0x%llx) "
- "referenced as data by dinode %llu (0x%llx)\n"),
- block_type_string(q),
- (unsigned long long)block,
- (unsigned long long)block,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if (q != gfs2_meta_inval) {
- log_info( _("Seems to be a normal duplicate; I'll "
- "sort it out in pass1b.\n"));
- add_duplicate_ref(ip, block, ref_as_data, 0,
- INODE_VALID);
- /* If the prev ref was as data, this is likely a data
- block, so keep the block count for both refs. */
- if (q == gfs2_block_used)
- bc->data_count++;
- return 1;
- }
- log_info( _("The block was invalid as metadata but might be "
- "okay as data. I'll sort it out in pass1b.\n"));
- add_duplicate_ref(ip, block, ref_as_data, 0, INODE_VALID);
- bc->data_count++;
- return 1;
- }
- fsck_blockmap_set(ip, block, _("data"), gfs2_block_used);
- bc->data_count++;
- return 0;
-}
-
-static int undo_check_data(struct gfs2_inode *ip, uint64_t block,
- void *private)
-{
- struct duptree *d;
- struct block_count *bc = (struct block_count *) private;
-
- if (gfs2_check_range(ip->i_sbd, block)) {
- /* Mark the owner of this block with the bad_block
- * designator so we know to check it for out of range
- * blocks later */
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("bad (out of range) data"),
- gfs2_block_free);
- return 1;
- }
- d = dupfind(block);
- if (d) {
- log_err( _("Reversing duplicate status of block %llu (0x%llx) "
- "referenced as data by dinode %llu (0x%llx)\n"),
- (unsigned long long)block,
- (unsigned long long)block,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- d->refs--; /* one less reference */
- if (d->refs == 1)
- dup_delete(d);
- bc->data_count--;
- return 1;
- }
- fsck_blockmap_set(ip, block, _("data"), gfs2_block_free);
- bc->data_count--;
- return 0;
-}
-
-static int remove_inode_eattr(struct gfs2_inode *ip, struct block_count *bc)
-{
- struct duptree *dt;
- struct inode_with_dups *id;
- osi_list_t *ref;
- int moved = 0;
-
- /* If it's a duplicate reference to the block, we need to check
- if the reference is on the valid or invalid inodes list.
- If it's on the valid inode's list, move it to the invalid
- inodes list. The reason is simple: This inode, although
- valid, has an now-invalid reference, so we should not give
- this reference preferential treatment over others. */
- dt = dupfind(ip->i_di.di_eattr);
- if (dt) {
- osi_list_foreach(ref, &dt->ref_inode_list) {
- id = osi_list_entry(ref, struct inode_with_dups, list);
- if (id->block_no == ip->i_di.di_num.no_addr) {
- log_debug( _("Moving inode %lld (0x%llx)'s "
- "duplicate reference to %lld "
- "(0x%llx) from the valid to the "
- "invalid reference list.\n"),
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)
- ip->i_di.di_eattr,
- (unsigned long long)
- ip->i_di.di_eattr);
- /* Move from the normal to the invalid list */
- osi_list_del(&id->list);
- osi_list_add_prev(&id->list,
- &dt->ref_invinode_list);
- moved = 1;
- break;
- }
- }
- if (!moved)
- log_debug( _("Duplicate reference to %lld "
- "(0x%llx) not moved.\n"),
- (unsigned long long)ip->i_di.di_eattr,
- (unsigned long long)ip->i_di.di_eattr);
- } else {
- delete_block(ip, ip->i_di.di_eattr, NULL,
- "extended attribute", NULL);
- }
- ip->i_di.di_eattr = 0;
- bc->ea_count = 0;
- ip->i_di.di_blocks = 1 + bc->indir_count + bc->data_count;
- ip->i_di.di_flags &= ~GFS2_DIF_EA_INDIRECT;
- bmodified(ip->i_bh);
- return 0;
-}
-
-static int ask_remove_inode_eattr(struct gfs2_inode *ip,
- struct block_count *bc)
-{
- log_err( _("Inode %lld (0x%llx) has unrecoverable Extended Attribute "
- "errors.\n"), (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if (query( _("Clear all Extended Attributes from the inode? (y/n) "))){
- if (!remove_inode_eattr(ip, bc))
- log_err( _("Extended attributes were removed.\n"));
- else
- log_err( _("Unable to remove inode eattr pointer; "
- "the error remains.\n"));
- } else {
- log_err( _("Extended attributes were not removed.\n"));
- }
- return 0;
-}
-
-/* clear_eas - clear the extended attributes for an inode
- *
- * @ip - in core inode pointer
- * @bc - pointer to a block count structure
- * block - the block that had the problem
- * duplicate - if this is a duplicate block, don't set it "free"
- * emsg - what to tell the user about the eas being checked
- * Returns: 1 if the EA is fixed, else 0 if it was not fixed.
- */
-static int clear_eas(struct gfs2_inode *ip, struct block_count *bc,
- uint64_t block, int duplicate, const char *emsg)
-{
- log_err( _("Inode #%llu (0x%llx): %s"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr, emsg);
- log_err( _(" at block #%lld (0x%llx).\n"),
- (unsigned long long)block, (unsigned long long)block);
- if (query( _("Clear the bad Extended Attribute? (y/n) "))) {
- if (block == ip->i_di.di_eattr) {
- remove_inode_eattr(ip, bc);
- log_err( _("The bad extended attribute was "
- "removed.\n"));
- } else if (!duplicate) {
- delete_block(ip, block, NULL,
- _("bad extended attribute"), NULL);
- }
- return 1;
- } else {
- log_err( _("The bad Extended Attribute was not fixed.\n"));
- bc->ea_count++;
- return 0;
- }
-}
-
-static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- int ret = 0;
- uint8_t q;
- struct block_count *bc = (struct block_count *) private;
-
- /* This inode contains an eattr - it may be invalid, but the
- * eattr attributes points to a non-zero block */
- if(gfs2_check_range(sdp, indirect)) {
- /*log_warn("EA indirect block #%"PRIu64" is out of range.\n",
- indirect);
- fsck_blockmap_set(parent, "bad", bad_block);*/
- /* Doesn't help to mark this here - this gets checked
- * in pass1c */
- return 1;
- }
- q = block_type(indirect);
-
- /* Special duplicate processing: If we have an EA block,
- check if it really is an EA. If it is, let duplicate
- handling sort it out. If it isn't, clear it but don't
- count it as a duplicate. */
- *bh = bread(sdp, indirect);
- if(gfs2_check_meta(*bh, GFS2_METATYPE_IN)) {
- if(q != gfs2_block_free) { /* Duplicate? */
- add_duplicate_ref(ip, indirect, ref_as_ea, 0,
- INODE_VALID);
- if (!clear_eas(ip, bc, indirect, 1,
- _("Bad indirect Extended Attribute "
- "duplicate found")))
- bc->ea_count++;
- return 1;
- }
- clear_eas(ip, bc, indirect, 0,
- _("Extended Attribute indirect block has incorrect "
- "type"));
- return 1;
- }
- if(q != gfs2_block_free) { /* Duplicate? */
- log_err( _("Inode #%llu (0x%llx): Duplicate Extended "
- "Attribute indirect block found at #%llu "
- "(0x%llx).\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)indirect,
- (unsigned long long)indirect);
- add_duplicate_ref(ip, indirect, ref_as_ea, 0, INODE_VALID);
- bc->ea_count++;
- ret = 1;
- } else {
- fsck_blockmap_set(ip, indirect,
- _("indirect Extended Attribute"),
- gfs2_indir_blk);
- bc->ea_count++;
- }
- return ret;
-}
-
-static int finish_eattr_indir(struct gfs2_inode *ip, int leaf_pointers,
- int leaf_pointer_errors, void *private)
-{
- struct block_count *bc = (struct block_count *) private;
- osi_list_t *head;
- struct special_blocks *b = NULL;
-
- if (leaf_pointer_errors == leaf_pointers) /* All eas were bad */
- return ask_remove_inode_eattr(ip, bc);
- log_debug( _("Marking inode #%llu (0x%llx) with extended "
- "attribute block\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- /* Mark the inode as having an eattr in the block map
- so pass1c can check it. We may have previously added this inode
- to the eattr_blocks list and if we did, it would be the first
- one on the list. So check that one only (to save time) and
- if that one matches, no need to add it again. */
- if (!osi_list_empty(&ip->i_sbd->eattr_blocks.list)) {
- head = &ip->i_sbd->eattr_blocks.list;
- b = osi_list_entry(head->next, struct special_blocks, list);
- }
- if (!b || b->block != ip->i_di.di_num.no_addr)
- gfs2_special_add(&ip->i_sbd->eattr_blocks,
- ip->i_di.di_num.no_addr);
- if (!leaf_pointer_errors)
- return 0;
- log_err( _("Inode %lld (0x%llx) has recoverable indirect "
- "Extended Attribute errors.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if (query( _("Okay to fix the block count for the inode? (y/n) "))) {
- ip->i_di.di_blocks = 1 + bc->indir_count +
- bc->data_count + bc->ea_count;
- bmodified(ip->i_bh);
- log_err( _("Block count fixed.\n"));
- return 1;
- }
- log_err( _("Block count not fixed.\n"));
- return 1;
-}
-
-static int check_leaf_block(struct gfs2_inode *ip, uint64_t block, int btype,
- struct gfs2_buffer_head **bh, void *private)
-{
- struct gfs2_buffer_head *leaf_bh = NULL;
- struct gfs2_sbd *sdp = ip->i_sbd;
- uint8_t q;
- struct block_count *bc = (struct block_count *) private;
-
- q = block_type(block);
- /* Special duplicate processing: If we have an EA block, check if it
- really is an EA. If it is, let duplicate handling sort it out.
- If it isn't, clear it but don't count it as a duplicate. */
- leaf_bh = bread(sdp, block);
- if(gfs2_check_meta(leaf_bh, btype)) {
- if(q != gfs2_block_free) { /* Duplicate? */
- add_duplicate_ref(ip, block, ref_as_ea, 0,
- INODE_VALID);
- clear_eas(ip, bc, block, 1,
- _("Bad Extended Attribute duplicate found"));
- } else {
- clear_eas(ip, bc, block, 0,
- _("Extended Attribute leaf block "
- "has incorrect type"));
- }
- brelse(leaf_bh);
- return 1;
- }
- if(q != gfs2_block_free) { /* Duplicate? */
- log_debug( _("Duplicate block found at #%lld (0x%llx).\n"),
- (unsigned long long)block,
- (unsigned long long)block);
- add_duplicate_ref(ip, block, ref_as_data, 0, INODE_VALID);
- bc->ea_count++;
- brelse(leaf_bh);
- return 1;
- }
- if (ip->i_di.di_eattr == 0) {
- /* Can only get in here if there were unrecoverable ea
- errors that caused clear_eas to be called. What we
- need to do here is remove the subsequent ea blocks. */
- clear_eas(ip, bc, block, 0,
- _("Extended Attribute block removed due to "
- "previous errors.\n"));
- brelse(leaf_bh);
- return 1;
- }
- /* Point of confusion: We've got to set the ea block itself to
- gfs2_meta_eattr here. Elsewhere we mark the inode with
- gfs2_eattr_block meaning it contains an eattr for pass1c. */
- fsck_blockmap_set(ip, block, _("Extended Attribute"), gfs2_meta_eattr);
- bc->ea_count++;
- *bh = leaf_bh;
- return 0;
-}
-
-/**
- * check_extended_leaf_eattr
- * @ip
- * @el_blk: block number of the extended leaf
- *
- * An EA leaf block can contain EA's with pointers to blocks
- * where the data for that EA is kept. Those blocks still
- * have the gfs2 meta header of type GFS2_METATYPE_EA
- *
- * Returns: 0 if correct[able], -1 if removal is needed
- */
-static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t *data_ptr,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private)
-{
- uint64_t el_blk = be64_to_cpu(*data_ptr);
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_buffer_head *bh = NULL;
- int error;
-
- if(gfs2_check_range(sdp, el_blk)){
- log_err( _("Inode #%llu (0x%llx): Extended Attribute block "
- "%llu (0x%llx) has an extended leaf block #%llu "
- "(0x%llx) that is out of range.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_eattr,
- (unsigned long long)ip->i_di.di_eattr,
- (unsigned long long)el_blk,
- (unsigned long long)el_blk);
- fsck_blockmap_set(ip, ip->i_di.di_eattr,
- _("bad (out of range) Extended Attribute "),
- gfs2_bad_block);
- return 1;
- }
- error = check_leaf_block(ip, el_blk, GFS2_METATYPE_ED, &bh, private);
- if (bh)
- brelse(bh);
- return error;
-}
-
-static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- osi_list_t *head;
- struct special_blocks *b = NULL;
-
- /* This inode contains an eattr - it may be invalid, but the
- * eattr attributes points to a non-zero block.
- * Clarification: If we're here we're checking a leaf block, and the
- * source dinode needs to be marked as having extended attributes.
- * That instructs pass1c to check the contents of the ea blocks. */
- log_debug( _("Setting inode %lld (0x%llx) as having eattr "
- "block(s) attached.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if (!osi_list_empty(&ip->i_sbd->eattr_blocks.list)) {
- head = &ip->i_sbd->eattr_blocks.list;
- b = osi_list_entry(head->next, struct special_blocks, list);
- }
- if (!b || b->block != ip->i_di.di_num.no_addr)
- gfs2_special_add(&sdp->eattr_blocks, ip->i_di.di_num.no_addr);
- if (gfs2_check_range(sdp, block)) {
- log_warn( _("Inode #%llu (0x%llx): Extended Attribute leaf "
- "block #%llu (0x%llx) is out of range.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)block, (unsigned long long)block);
- fsck_blockmap_set(ip, ip->i_di.di_eattr,
- _("bad (out of range) Extended "
- "Attribute leaf"), gfs2_bad_block);
- return 1;
- }
- return check_leaf_block(ip, block, GFS2_METATYPE_EA, bh, private);
-}
-
-static int check_eattr_entries(struct gfs2_inode *ip,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- char ea_name[256];
-
- if(!ea_hdr->ea_name_len){
- /* Skip this entry for now */
- return 1;
- }
-
- memset(ea_name, 0, sizeof(ea_name));
- strncpy(ea_name, (char *)ea_hdr + sizeof(struct gfs2_ea_header),
- ea_hdr->ea_name_len);
-
- if(!GFS2_EATYPE_VALID(ea_hdr->ea_type) &&
- ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
- /* Skip invalid entry */
- return 1;
- }
-
- if(ea_hdr->ea_num_ptrs){
- uint32_t avail_size;
- int max_ptrs;
-
- avail_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
- max_ptrs = (be32_to_cpu(ea_hdr->ea_data_len)+avail_size-1)/avail_size;
-
- if(max_ptrs > ea_hdr->ea_num_ptrs) {
- return 1;
- } else {
- log_debug( _(" Pointers Required: %d\n Pointers Reported: %d\n"),
- max_ptrs, ea_hdr->ea_num_ptrs);
- }
- }
- return 0;
-}
-
-/**
- * mark_block_invalid - mark blocks associated with an inode as invalid
- * unless the block is a duplicate.
- *
- * An "invalid" block is now considered free in the bitmap, and pass2 will
- * delete any invalid blocks. This is nearly identical to function
- * delete_block_if_notdup.
- */
-static int mark_block_invalid(struct gfs2_inode *ip, uint64_t block,
- enum dup_ref_type reftype, const char *btype)
-{
- uint8_t q;
-
- if (gfs2_check_range(ip->i_sbd, block) != 0)
- return -EFAULT;
-
- q = block_type(block);
- if (q != gfs2_block_free) {
- add_duplicate_ref(ip, block, reftype, 0, INODE_INVALID);
- log_info( _("%s block %lld (0x%llx), part of inode "
- "%lld (0x%llx), was free so the invalid "
- "reference is ignored.\n"),
- btype, (unsigned long long)block,
- (unsigned long long)block,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- return 0;
- }
- fsck_blockmap_set(ip, block, btype, gfs2_meta_inval);
- return 0;
-}
-
-static int invalidate_metadata(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h,
- void *private)
-{
- return mark_block_invalid(ip, block, ref_as_meta, _("metadata"));
-}
-
-static int invalidate_leaf(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head *bh, void *private)
-{
- return mark_block_invalid(ip, block, ref_as_meta, _("leaf"));
-}
-
-static int invalidate_data(struct gfs2_inode *ip, uint64_t block,
- void *private)
-{
- return mark_block_invalid(ip, block, ref_as_data, _("data"));
-}
-
-static int invalidate_eattr_indir(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent,
- struct gfs2_buffer_head **bh, void *private)
-{
- return mark_block_invalid(ip, block, ref_as_ea,
- _("indirect extended attribute"));
-}
-
-static int invalidate_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- return mark_block_invalid(ip, block, ref_as_ea,
- _("extended attribute"));
-}
-
-/**
- * Check for massive amounts of pointer corruption. If the block has
- * lots of out-of-range pointers, we can't trust any of the pointers.
- * For example, a stray pointer with a value of 0x1d might be
- * corruption/nonsense, and if so, we don't want to delete an
- * important file (like master or the root directory) because of it.
- * We need to check for a large number of bad pointers BEFORE we start
- * messing with them because we don't want to mark a block as a
- * duplicate (for example) until we know if the pointers in general can
- * be trusted. Thus it needs to be in a separate loop.
- */
-static int rangecheck_block(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh,
- const char *btype, void *private)
-{
- long *bad_pointers = (long *)private;
- uint8_t q;
-
- if (gfs2_check_range(ip->i_sbd, block) != 0) {
- (*bad_pointers)++;
- log_debug( _("Bad %s block pointer (out of range #%ld) "
- "found in inode %lld (0x%llx).\n"), btype,
- *bad_pointers,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if ((*bad_pointers) <= BAD_POINTER_TOLERANCE)
- return ENOENT;
- else
- return -ENOENT; /* Exits check_metatree quicker */
- }
- /* See how many duplicate blocks it has */
- q = block_type(block);
- if (q != gfs2_block_free) {
- (*bad_pointers)++;
- log_debug( _("Duplicated %s block pointer (violation #%ld) "
- "found in inode %lld (0x%llx).\n"), btype,
- *bad_pointers,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if ((*bad_pointers) <= BAD_POINTER_TOLERANCE)
- return ENOENT;
- else
- return -ENOENT; /* Exits check_metatree quicker */
- }
- return 0;
-}
-
-static int rangecheck_metadata(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h,
- void *private)
-{
- return rangecheck_block(ip, block, bh, _("metadata"), private);
-}
-
-static int rangecheck_leaf(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head *bh, void *private)
-{
- return rangecheck_block(ip, block, &bh, _("leaf"), private);
-}
-
-static int rangecheck_data(struct gfs2_inode *ip, uint64_t block,
- void *private)
-{
- return rangecheck_block(ip, block, NULL, _("data"), private);
-}
-
-static int rangecheck_eattr_indir(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent,
- struct gfs2_buffer_head **bh, void *private)
-{
- return rangecheck_block(ip, block, NULL,
- _("indirect extended attribute"),
- private);
-}
-
-static int rangecheck_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- return rangecheck_block(ip, block, NULL, _("extended attribute"),
- private);
-}
-
-struct metawalk_fxns rangecheck_fxns = {
- .private = NULL,
- .check_metalist = rangecheck_metadata,
- .check_data = rangecheck_data,
- .check_leaf = rangecheck_leaf,
- .check_eattr_indir = rangecheck_eattr_indir,
- .check_eattr_leaf = rangecheck_eattr_leaf,
-};
-
-/*
- * handle_ip - process an incore structure representing a dinode.
- */
-static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip)
-{
- int error;
- struct block_count bc = {0};
- long bad_pointers;
- uint64_t block = ip->i_bh->b_blocknr;
-
- bad_pointers = 0L;
-
- /* First, check the metadata for massive amounts of pointer corruption.
- Such corruption can only lead us to ruin trying to clean it up,
- so it's better to check it up front and delete the inode if
- there is corruption. */
- rangecheck_fxns.private = &bad_pointers;
- error = check_metatree(ip, &rangecheck_fxns);
- if (bad_pointers > BAD_POINTER_TOLERANCE) {
- log_err( _("Error: inode %llu (0x%llx) has more than "
- "%d bad pointers.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- BAD_POINTER_TOLERANCE);
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("badly corrupt"), gfs2_block_free);
- return 0;
- }
-
- switch(ip->i_di.di_mode & S_IFMT) {
-
- case S_IFDIR:
- if (fsck_blockmap_set(ip, block, _("directory"),
- gfs2_inode_dir))
- goto bad_dinode;
- if(!dirtree_insert(block))
- goto bad_dinode;
- break;
- case S_IFREG:
- if (fsck_blockmap_set(ip, block, _("file"),
- gfs2_inode_file))
- goto bad_dinode;
- break;
- case S_IFLNK:
- if (fsck_blockmap_set(ip, block, _("symlink"),
- gfs2_inode_lnk))
- goto bad_dinode;
- break;
- case S_IFBLK:
- if (fsck_blockmap_set(ip, block, _("block device"),
- gfs2_inode_blk))
- goto bad_dinode;
- break;
- case S_IFCHR:
- if (fsck_blockmap_set(ip, block, _("character device"),
- gfs2_inode_chr))
- goto bad_dinode;
- break;
- case S_IFIFO:
- if (fsck_blockmap_set(ip, block, _("fifo"),
- gfs2_inode_fifo))
- goto bad_dinode;
- break;
- case S_IFSOCK:
- if (fsck_blockmap_set(ip, block, _("socket"),
- gfs2_inode_sock))
- goto bad_dinode;
- break;
- default:
- /* We found a dinode that has an invalid mode, so we can't
- tell if it's a data file, directory or a socket.
- Regardless, we have to invalidate its metadata in case there
- are duplicate blocks referenced. If we don't call
- check_metatree, the blocks it references will be deleted
- wholesale by pass2, and if any of those blocks are
- duplicates--referenced by another dinode for some reason--
- we will mark it free, even though it's in use. In other
- words, we would introduce file system corruption. So we
- need to keep track of the fact that it's invalid and
- skip parts that we can't be sure of based on dinode type. */
- check_metatree(ip, &invalidate_fxns);
- if (fsck_blockmap_set(ip, block, _("invalid mode"),
- gfs2_inode_invalid))
- goto bad_dinode;
- return 0;
- }
- if(set_link_count(ip->i_di.di_num.no_addr, ip->i_di.di_nlink))
- goto bad_dinode;
-
- if (S_ISDIR(ip->i_di.di_mode) &&
- (ip->i_di.di_flags & GFS2_DIF_EXHASH)) {
- if (((1 << ip->i_di.di_depth) * sizeof(uint64_t)) != ip->i_di.di_size){
- log_warn( _("Directory dinode block #%llu (0x%llx"
- ") has bad depth. Found %u, Expected %u\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- ip->i_di.di_depth,
- (1 >> (ip->i_di.di_size/sizeof(uint64_t))));
- if(fsck_blockmap_set(ip, block, _("bad depth"),
- gfs2_block_free))
- goto bad_dinode;
- return 0;
- }
- }
-
- pass1_fxns.private = &bc;
- error = check_metatree(ip, &pass1_fxns);
- if (fsck_abort || error < 0)
- return 0;
- if (error > 0) {
- log_err( _("Error: inode %llu (0x%llx) has unrecoverable "
- "errors; invalidating.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- undo_fxns.private = &bc;
- check_metatree(ip, &undo_fxns);
- /* If we undo the metadata accounting, including metadatas
- duplicate block status, we need to make sure later passes
- don't try to free up the metadata referenced by this inode.
- Therefore we mark the inode as free space. */
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("corrupt"), gfs2_block_free);
- return 0;
- }
-
- error = check_inode_eattr(ip, &pass1_fxns);
-
- if (error &&
- !(ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT))
- ask_remove_inode_eattr(ip, &bc);
-
- if (ip->i_di.di_blocks !=
- (1 + bc.indir_count + bc.data_count + bc.ea_count)) {
- log_err( _("Inode #%llu (0x%llx): Ondisk block count (%llu"
- ") does not match what fsck found (%llu)\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_blocks,
- (unsigned long long)1 + bc.indir_count +
- bc.data_count + bc.ea_count);
- log_info( _("inode has: %lld, but fsck counts: Dinode:1 + "
- "indir:%lld + data: %lld + ea: %lld\n"),
- (unsigned long long)ip->i_di.di_blocks,
- (unsigned long long)bc.indir_count,
- (unsigned long long)bc.data_count,
- (unsigned long long)bc.ea_count);
- if (query( _("Fix ondisk block count? (y/n) "))) {
- ip->i_di.di_blocks = 1 + bc.indir_count + bc.data_count +
- bc.ea_count;
- bmodified(ip->i_bh);
- log_err( _("Block count for #%llu (0x%llx) fixed\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- } else
- log_err( _("Bad block count for #%llu (0x%llx"
- ") not fixed\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- }
-
- return 0;
-bad_dinode:
- stack;
- return -1;
-}
-
-/*
- * handle_di - This is now a wrapper function that takes a gfs2_buffer_head
- * and calls handle_ip, which takes an in-code dinode structure.
- */
-static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh)
-{
- uint8_t q;
- int error = 0;
- uint64_t block = bh->b_blocknr;
- struct gfs2_inode *ip;
-
- ip = fsck_inode_get(sdp, bh);
- q = block_type(block);
- if(q != gfs2_block_free) {
- log_err( _("Found a duplicate inode block at #%" PRIu64
- " (0x%" PRIx64 ") previously marked as a %s\n"),
- block, block, block_type_string(q));
- add_duplicate_ref(ip, block, ref_as_meta, 0, INODE_VALID);
- fsck_inode_put(&ip);
- return 0;
- }
-
- if (ip->i_di.di_num.no_addr != block) {
- log_err( _("Inode #%llu (0x%llx): Bad inode address found: %llu "
- "(0x%llx)\n"), (unsigned long long)block,
- (unsigned long long)block,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if(query( _("Fix address in inode at block #%"
- PRIu64 " (0x%" PRIx64 ")? (y/n) "),
- block, block)) {
- ip->i_di.di_num.no_addr = ip->i_di.di_num.no_formal_ino = block;
- bmodified(ip->i_bh);
- } else
- log_err( _("Address in inode at block #%" PRIu64
- " (0x%" PRIx64 ") not fixed\n"), block, block);
- }
- error = handle_ip(sdp, ip);
- fsck_inode_put(&ip);
- return error;
-}
-
-/* Check system inode and verify it's marked "in use" in the bitmap: */
-/* Should work for all system inodes: root, master, jindex, per_node, etc. */
-/* We have to pass the sysinode as ** because the pointer may change out from
- under the reference by way of the builder() function. */
-static int check_system_inode(struct gfs2_sbd *sdp,
- struct gfs2_inode **sysinode,
- const char *filename,
- int builder(struct gfs2_sbd *sbp),
- enum gfs2_mark_block mark)
-{
- uint64_t iblock = 0;
- struct dir_status ds = {0};
- int error;
-
- log_info( _("Checking system inode '%s'\n"), filename);
- if (*sysinode) {
- /* Read in the system inode, look at its dentries, and start
- * reading through them */
- iblock = (*sysinode)->i_di.di_num.no_addr;
- log_info( _("System inode for '%s' is located at block %"
- PRIu64 " (0x%" PRIx64 ")\n"), filename,
- iblock, iblock);
- if (gfs2_check_meta((*sysinode)->i_bh, GFS2_METATYPE_DI)) {
- log_err( _("Found invalid system dinode at block #"
- "%llu (0x%llx)\n"),
- (unsigned long long)iblock,
- (unsigned long long)iblock);
- gfs2_blockmap_set(bl, iblock, gfs2_block_free);
- check_n_fix_bitmap(sdp, iblock, gfs2_block_free);
- inode_put(sysinode);
- }
- }
- if (*sysinode) {
- ds.q = block_type(iblock);
- /* If the inode exists but the block is marked free, we might
- be recovering from a corrupt bitmap. In that case, don't
- rebuild the inode. Just reuse the inode and fix the
- bitmap. */
- if (ds.q == gfs2_block_free) {
- log_info( _("The inode exists but the block is not "
- "marked 'in use'; fixing it.\n"));
- fsck_blockmap_set(*sysinode,
- (*sysinode)->i_di.di_num.no_addr,
- filename, mark);
- ds.q = mark;
- if (mark == gfs2_inode_dir)
- dirtree_insert((*sysinode)->i_di.di_num.no_addr);
- }
- } else
- log_info( _("System inode for '%s' is corrupt or missing.\n"),
- filename);
- /* If there are errors with the inode here, we need to create a new
- inode and get it all setup - of course, everything will be in
- lost+found then, but we *need* our system inodes before we can
- do any of that. */
- if(!(*sysinode) || ds.q != mark) {
- log_err( _("Invalid or missing %s system inode (should be %d, "
- "is %d).\n"), filename, mark, ds.q);
- if (query(_("Create new %s system inode? (y/n) "), filename)) {
- log_err( _("Rebuilding system file \"%s\"\n"),
- filename);
- error = builder(sdp);
- if (error) {
- log_err( _("Error trying to rebuild system "
- "file %s: Cannot continue\n"),
- filename);
- return error;
- }
- fsck_blockmap_set(*sysinode,
- (*sysinode)->i_di.di_num.no_addr,
- filename, mark);
- ds.q = mark;
- if (mark == gfs2_inode_dir)
- dirtree_insert((*sysinode)->i_di.di_num.no_addr);
- } else {
- log_err( _("Cannot continue without valid %s inode\n"),
- filename);
- return -1;
- }
- }
- if (S_ISDIR((*sysinode)->i_di.di_mode)) {
- struct block_count bc = {0};
-
- sysdir_fxns.private = &bc;
- if ((*sysinode)->i_di.di_flags & GFS2_DIF_EXHASH)
- check_metatree(*sysinode, &sysdir_fxns);
- else
- check_linear_dir(*sysinode, (*sysinode)->i_bh,
- &sysdir_fxns);
- }
- error = handle_ip(sdp, *sysinode);
- return error;
-}
-
-static int build_a_journal(struct gfs2_sbd *sdp)
-{
- char name[256];
-
- /* First, try to delete the journal if it's in jindex */
- sprintf(name, "journal%u", sdp->md.journals);
- gfs2_dirent_del(sdp->md.jiinode, name, strlen(name));
- /* Now rebuild it */
- build_journal(sdp, sdp->md.journals, sdp->md.jiinode);
- return 0;
-}
-
-static int check_system_inodes(struct gfs2_sbd *sdp)
-{
- int journal_count;
-
- /*******************************************************************
- ******* Check the system inode integrity *************
- *******************************************************************/
- if (check_system_inode(sdp, &sdp->master_dir, "master", build_master,
- gfs2_inode_dir)) {
- stack;
- return -1;
- }
- if (check_system_inode(sdp, &sdp->md.rooti, "root", build_root,
- gfs2_inode_dir)) {
- stack;
- return -1;
- }
- if (check_system_inode(sdp, &sdp->md.inum, "inum", build_inum,
- gfs2_inode_file)) {
- stack;
- return -1;
- }
- if (check_system_inode(sdp, &sdp->md.statfs, "statfs", build_statfs,
- gfs2_inode_file)) {
- stack;
- return -1;
- }
- if (check_system_inode(sdp, &sdp->md.jiinode, "jindex", build_jindex,
- gfs2_inode_dir)) {
- stack;
- return -1;
- }
- if (check_system_inode(sdp, &sdp->md.riinode, "rindex", build_rindex,
- gfs2_inode_file)) {
- stack;
- return -1;
- }
- if (check_system_inode(sdp, &sdp->md.qinode, "quota", build_quota,
- gfs2_inode_file)) {
- stack;
- return -1;
- }
- if (check_system_inode(sdp, &sdp->md.pinode, "per_node",
- build_per_node, gfs2_inode_dir)) {
- stack;
- return -1;
- }
- /* We have to play a trick on build_journal: We swap md.journals
- in order to keep a count of which journal we need to build. */
- journal_count = sdp->md.journals;
- for (sdp->md.journals = 0; sdp->md.journals < journal_count;
- sdp->md.journals++) {
- char jname[16];
-
- sprintf(jname, "journal%d", sdp->md.journals);
- if (check_system_inode(sdp, &sdp->md.journal[sdp->md.journals],
- jname, build_a_journal,
- gfs2_inode_file)) {
- stack;
- return -1;
- }
- }
-
- return 0;
-}
-
-/**
- * pass1 - walk through inodes and check inode state
- *
- * this walk can be done using root inode and depth first search,
- * watching for repeat inode numbers
- *
- * format & type
- * link count
- * duplicate blocks
- * bad blocks
- * inodes size
- * dir info
- */
-int pass1(struct gfs2_sbd *sbp)
-{
- struct gfs2_buffer_head *bh;
- osi_list_t *tmp;
- uint64_t block;
- struct rgrp_list *rgd;
- int first;
- uint64_t i;
- uint64_t blk_count;
- uint64_t offset;
- uint64_t rg_count = 0;
-
- /* FIXME: In the gfs fsck, we had to mark things like the
- * journals and indices and such as 'other_meta' - in gfs2,
- * the journals are files and are found in the normal file
- * sweep - is there any metadata we need to mark here before
- * the sweeps start that we won't find otherwise? */
-
- /* Make sure the system inodes are okay & represented in the bitmap. */
- check_system_inodes(sbp);
-
- /* So, do we do a depth first search starting at the root
- * inode, or use the rg bitmaps, or just read every fs block
- * to find the inodes? If we use the depth first search, why
- * have pass3 at all - if we use the rg bitmaps, pass5 is at
- * least partially invalidated - if we read every fs block,
- * things will probably be intolerably slow. The current fsck
- * uses the rg bitmaps, so maybe that's the best way to start
- * things - we can change the method later if necessary.
- */
- for (tmp = sbp->rglist.next; tmp != &sbp->rglist;
- tmp = tmp->next, rg_count++) {
- log_debug( _("Checking metadata in Resource Group #%" PRIu64 "\n"),
- rg_count);
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- for (i = 0; i < rgd->ri.ri_length; i++) {
- log_debug( _("rgrp block %lld (0x%llx) "
- "is now marked as 'rgrp data'\n"),
- rgd->ri.ri_addr + i, rgd->ri.ri_addr + i);
- if (gfs2_blockmap_set(bl, rgd->ri.ri_addr + i,
- gfs2_meta_rgrp)) {
- stack;
- return FSCK_ERROR;
- }
- /* rgrps and bitmaps don't have bits to represent
- their blocks, so don't do this:
- check_n_fix_bitmap(sbp, rgd->ri.ri_addr + i,
- gfs2_meta_rgrp);*/
- }
-
- offset = sizeof(struct gfs2_rgrp);
- blk_count = 1;
- first = 1;
-
- while (1) {
- /* "block" is relative to the entire file system */
- /* Get the next dinode in the file system, according
- to the bitmap. This should ONLY be dinodes. */
- if (gfs2_next_rg_meta(rgd, &block, first))
- break;
- warm_fuzzy_stuff(block);
-
- if (fsck_abort) /* if asked to abort */
- return FSCK_OK;
- if (skip_this_pass) {
- printf( _("Skipping pass 1 is not a good idea.\n"));
- skip_this_pass = FALSE;
- fflush(stdout);
- }
- if (fsck_system_inode(sbp, block)) {
- log_debug(_("Already processed system inode "
- "%lld (0x%llx)\n"),
- (unsigned long long)block,
- (unsigned long long)block);
- first = 0;
- continue;
- }
- bh = bread(sbp, block);
-
- /*log_debug( _("Checking metadata block #%" PRIu64
- " (0x%" PRIx64 ")\n"), block, block);*/
-
- if (gfs2_check_meta(bh, GFS2_METATYPE_DI)) {
- log_err( _("Found invalid inode at block #"
- "%llu (0x%llx)\n"),
- (unsigned long long)block,
- (unsigned long long)block);
- if (gfs2_blockmap_set(bl, block,
- gfs2_block_free)) {
- stack;
- brelse(bh);
- return FSCK_ERROR;
- }
- check_n_fix_bitmap(sbp, block,
- gfs2_block_free);
- } else if (handle_di(sbp, bh) < 0) {
- stack;
- brelse(bh);
- return FSCK_ERROR;
- }
- /* Ignore everything else - they should be hit by the
- handle_di step. Don't check NONE either, because
- check_meta passes everything if GFS2_METATYPE_NONE
- is specified. Hopefully, other metadata types such
- as indirect blocks will be handled when the inode
- itself is processed, and if it's not, it should be
- caught in pass5. */
- brelse(bh);
- first = 0;
- }
- }
- return FSCK_OK;
-}
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
deleted file mode 100644
index 4d97879..0000000
--- a/gfs2/fsck/pass1b.c
+++ /dev/null
@@ -1,668 +0,0 @@
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <libintl.h>
-#include <sys/stat.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "fsck.h"
-#include "osi_list.h"
-#include "util.h"
-#include "metawalk.h"
-#include "inode_hash.h"
-
-struct fxn_info {
- uint64_t block;
- int found;
- int ea_only; /* The only dups were found in EAs */
-};
-
-struct dup_handler {
- struct duptree *b;
- struct inode_with_dups *id;
- int ref_inode_count;
- int ref_count;
-};
-
-static int check_metalist(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h, void *private);
-static int check_data(struct gfs2_inode *ip, uint64_t block, void *private);
-static int check_eattr_indir(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private);
-static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private);
-static int check_eattr_entry(struct gfs2_inode *ip,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private);
-static int check_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private);
-static int find_dentry(struct gfs2_inode *ip, struct gfs2_dirent *de,
- struct gfs2_dirent *prev, struct gfs2_buffer_head *bh,
- char *filename, uint16_t *count, void *priv);
-
-struct metawalk_fxns find_refs = {
- .private = NULL,
- .check_leaf = NULL,
- .check_metalist = check_metalist,
- .check_data = check_data,
- .check_eattr_indir = check_eattr_indir,
- .check_eattr_leaf = check_eattr_leaf,
- .check_dentry = NULL,
- .check_eattr_entry = check_eattr_entry,
- .check_eattr_extentry = check_eattr_extentry,
-};
-
-struct metawalk_fxns find_dirents = {
- .private = NULL,
- .check_leaf = NULL,
- .check_metalist = NULL,
- .check_data = NULL,
- .check_eattr_indir = NULL,
- .check_eattr_leaf = NULL,
- .check_dentry = find_dentry,
- .check_eattr_entry = NULL,
- .check_eattr_extentry = NULL,
-};
-
-static int check_metalist(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h, void *private)
-{
- return add_duplicate_ref(ip, block, ref_as_meta, 1, INODE_VALID);
-}
-
-static int check_data(struct gfs2_inode *ip, uint64_t block, void *private)
-{
- return add_duplicate_ref(ip, block, ref_as_data, 1, INODE_VALID);
-}
-
-static int check_eattr_indir(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- struct gfs2_sbd *sbp = ip->i_sbd;
- int error;
-
- error = add_duplicate_ref(ip, block, ref_as_ea, 1, INODE_VALID);
- if (!error)
- *bh = bread(sbp, block);
-
- return error;
-}
-
-static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- struct gfs2_sbd *sbp = ip->i_sbd;
- int error;
-
- error = add_duplicate_ref(ip, block, ref_as_ea, 1, INODE_VALID);
- if (!error)
- *bh = bread(sbp, block);
- return error;
-}
-
-static int check_eattr_entry(struct gfs2_inode *ip,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev, void *private)
-{
- return 0;
-}
-
-static int check_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private)
-{
- uint64_t block = be64_to_cpu(*ea_data_ptr);
-
- return add_duplicate_ref(ip, block, ref_as_ea, 1, INODE_VALID);
-}
-
-/*
- * check_dir_dup_ref - check for a directory entry duplicate reference
- * and if found, set the name into the id.
- * Returns: 1 if filename was found, otherwise 0
- */
-static int check_dir_dup_ref(struct gfs2_inode *ip, struct gfs2_dirent *de,
- osi_list_t *tmp2, char *filename)
-{
- struct inode_with_dups *id;
-
- id = osi_list_entry(tmp2, struct inode_with_dups, list);
- if(id->name)
- /* We can only have one parent of inodes that contain duplicate
- * blocks...no need to keep looking for this one. */
- return 1;
- if(id->block_no == de->de_inum.no_addr) {
- id->name = strdup(filename);
- id->parent = ip->i_di.di_num.no_addr;
- log_debug( _("Duplicate block %llu (0x%llx"
- ") is in file or directory %llu"
- " (0x%llx) named %s\n"),
- (unsigned long long)id->block_no,
- (unsigned long long)id->block_no,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- filename);
- /* If there are duplicates of duplicates, I guess we'll miss
- them here. */
- return 1;
- }
- return 0;
-}
-
-static int find_dentry(struct gfs2_inode *ip, struct gfs2_dirent *de,
- struct gfs2_dirent *prev,
- struct gfs2_buffer_head *bh, char *filename,
- uint16_t *count, void *priv)
-{
- struct osi_node *n, *next = NULL;
- osi_list_t *tmp2;
- struct duptree *b;
- int found;
-
- for (n = osi_first(&dup_blocks); n; n = next) {
- next = osi_next(n);
- b = (struct duptree *)n;
- found = 0;
- osi_list_foreach(tmp2, &b->ref_invinode_list) {
- if (check_dir_dup_ref(ip, de, tmp2, filename)) {
- found = 1;
- break;
- }
- }
- if (!found) {
- osi_list_foreach(tmp2, &b->ref_inode_list) {
- if (check_dir_dup_ref(ip, de, tmp2, filename))
- break;
- }
- }
- }
- /* Return the number of leaf entries so metawalk doesn't flag this
- leaf as having none. */
- *count = be16_to_cpu(((struct gfs2_leaf *)bh->b_data)->lf_entries);
- return 0;
-}
-
-static int clear_dup_metalist(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, int h,
- void *private)
-{
- struct dup_handler *dh = (struct dup_handler *) private;
- struct duptree *d;
-
- if (gfs2_check_range(ip->i_sbd, block) != 0)
- return 0;
-
- /* This gets tricky. We're traversing a metadata tree trying to
- delete an inode based on it having a duplicate block reference
- somewhere in its metadata. We know this block is listed as data
- or metadata for this inode, but it may or may not be one of the
- actual duplicate references that caused the problem. If it's not
- a duplicate, it's normal metadata that isn't referenced anywhere
- else, but we're deleting the inode out from under it, so we need
- to delete it altogether. If the block is a duplicate referenced
- block, we need to keep its type intact and let the caller sort
- it out once we're down to a single reference. */
- d = dupfind(block);
- if (!d) {
- fsck_blockmap_set(ip, block, _("no longer valid"),
- gfs2_block_free);
- return 0;
- }
- /* This block, having failed the above test, is duplicated somewhere */
- if(block == dh->b->block) {
- log_err( _("Not clearing duplicate reference in inode \"%s\" "
- "at block #%llu (0x%llx) to block #%llu (0x%llx) "
- "because it's valid for another inode.\n"),
- dh->id->name ? dh->id->name : _("unknown name"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)block, (unsigned long long)block);
- log_err( _("Inode %s is in directory %"PRIu64" (0x%" PRIx64 ")\n"),
- dh->id->name ? dh->id->name : "", dh->id->parent,
- dh->id->parent);
- }
- /* We return 1 not 0 because we need build_and_check_metalist to
- bypass adding the metadata below it to the metalist. If that
- were to happen, all the indirect blocks pointed to by the
- duplicate block would be processed twice, which means it might
- be mistakenly freed as "no longer valid" (in this function above)
- even though it's valid metadata for a different inode. Returning
- 1 ensures that the metadata isn't processed again. */
- return 1;
-}
-
-static int clear_dup_data(struct gfs2_inode *ip, uint64_t block, void *private)
-{
- return clear_dup_metalist(ip, block, NULL, 0, private);
-}
-
-static int clear_dup_eattr_indir(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- return clear_dup_metalist(ip, block, NULL, 0, private);
-}
-
-static int clear_dup_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- return clear_dup_metalist(ip, block, NULL, 0, private);
-}
-
-static int clear_eattr_entry (struct gfs2_inode *ip,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- char ea_name[256];
-
- if(!ea_hdr->ea_name_len){
- /* Skip this entry for now */
- return 1;
- }
-
- memset(ea_name, 0, sizeof(ea_name));
- strncpy(ea_name, (char *)ea_hdr + sizeof(struct gfs2_ea_header),
- ea_hdr->ea_name_len);
-
- if(!GFS2_EATYPE_VALID(ea_hdr->ea_type) &&
- ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
- /* Skip invalid entry */
- return 1;
- }
-
- if(ea_hdr->ea_num_ptrs){
- uint32_t avail_size;
- int max_ptrs;
-
- avail_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
- max_ptrs = (be32_to_cpu(ea_hdr->ea_data_len) + avail_size - 1) /
- avail_size;
-
- if(max_ptrs > ea_hdr->ea_num_ptrs)
- return 1;
- else {
- log_debug( _(" Pointers Required: %d\n Pointers Reported: %d\n"),
- max_ptrs, ea_hdr->ea_num_ptrs);
- }
- }
- return 0;
-}
-
-static int clear_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private)
-{
- uint64_t block = be64_to_cpu(*ea_data_ptr);
-
- return clear_dup_metalist(ip, block, NULL, 0, private);
-}
-
-/* Finds all references to duplicate blocks in the metadata */
-static int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode)
-{
- struct gfs2_inode *ip;
- int error = 0;
-
- ip = fsck_load_inode(sbp, inode); /* bread, inode_get */
- /*log_debug( _("Checking inode %" PRIu64 " (0x%" PRIx64 ")'s "
- "metatree for references to duplicate blocks)\n"),
- inode, inode);*/
- /* double-check the meta header just to be sure it's metadata */
- if (ip->i_di.di_header.mh_magic != GFS2_MAGIC ||
- ip->i_di.di_header.mh_type != GFS2_METATYPE_DI) {
- log_debug( _("Block %lld (0x%llx) is not gfs2 metadata.\n"),
- (unsigned long long)inode,
- (unsigned long long)inode);
- return 1;
- }
- error = check_metatree(ip, &find_refs);
- if (error < 0) {
- stack;
- fsck_inode_put(&ip); /* out, brelse, free */
- return error;
- }
-
- /* Exhash dir leafs will be checked by check_metatree (right after
- the "end:" label.) But if this is a linear directory we need to
- check the dir with check_linear_dir. */
- if(S_ISDIR(ip->i_di.di_mode) && !(ip->i_di.di_flags & GFS2_DIF_EXHASH))
- error = check_linear_dir(ip, ip->i_bh, &find_dirents);
-
- /* Check for ea references in the inode */
- if(!error)
- error = check_inode_eattr(ip, &find_refs);
-
- fsck_inode_put(&ip); /* out, brelse, free */
-
- return error;
-}
-
-static void log_inode_reference(struct duptree *b, osi_list_t *tmp, int inval)
-{
- char reftypestring[32];
- struct inode_with_dups *id;
-
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- if (id->dup_count == 1) {
- if (id->reftypecount[ref_as_data])
- strcpy(reftypestring, "as data");
- else if (id->reftypecount[ref_as_meta])
- strcpy(reftypestring, "as metadata");
- else
- strcpy(reftypestring, "as extended attribute");
- } else {
- sprintf(reftypestring, "%d/%d/%d",
- id->reftypecount[ref_as_data],
- id->reftypecount[ref_as_meta],
- id->reftypecount[ref_as_ea]);
- }
- if (inval)
- log_warn( _("Invalid "));
- log_warn( _("Inode %s (%lld/0x%llx) has %d reference(s) to "
- "block %llu (0x%llx) (%s)\n"), id->name,
- (unsigned long long)id->block_no,
- (unsigned long long)id->block_no, id->dup_count,
- (unsigned long long)b->block,
- (unsigned long long)b->block, reftypestring);
-}
-
-static int clear_a_reference(struct gfs2_sbd *sbp, struct duptree *b,
- osi_list_t *ref_list, struct dup_handler *dh,
- int inval)
-{
- struct gfs2_inode *ip;
- struct inode_with_dups *id;
- osi_list_t *tmp, *x;
- struct metawalk_fxns clear_dup_fxns = {
- .private = NULL,
- .check_leaf = NULL,
- .check_metalist = clear_dup_metalist,
- .check_data = clear_dup_data,
- .check_eattr_indir = clear_dup_eattr_indir,
- .check_eattr_leaf = clear_dup_eattr_leaf,
- .check_dentry = NULL,
- .check_eattr_entry = clear_eattr_entry,
- .check_eattr_extentry = clear_eattr_extentry,
- };
-
- osi_list_foreach_safe(tmp, ref_list, x) {
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- dh->b = b;
- dh->id = id;
- if(dh->ref_inode_count == 1) /* down to the last reference */
- return 1;
- if (!(query( _("Okay to clear %s inode %lld (0x%llx)? (y/n) "),
- (inval ? _("invalidated") : ""),
- (unsigned long long)id->block_no,
- (unsigned long long)id->block_no))) {
- log_warn( _("The bad inode was not cleared...\n"));
- continue;
- }
- log_warn( _("Clearing inode %lld (0x%llx)....\n"),
- (unsigned long long)id->block_no,
- (unsigned long long)id->block_no);
- clear_dup_fxns.private = (void *) dh;
- /* Clear the EAs for the inode first */
- ip = fsck_load_inode(sbp, id->block_no);
- check_inode_eattr(ip, &clear_dup_fxns);
- /* If the dup wasn't only in the EA, clear the inode */
- if (id->reftypecount[ref_as_data] ||
- id->reftypecount[ref_as_meta])
- check_metatree(ip, &clear_dup_fxns);
-
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("bad"), gfs2_inode_invalid);
- fsck_inode_put(&ip); /* out, brelse, free */
- (dh->ref_inode_count)--;
- /* Inode is marked invalid and is removed in pass2 */
- /* FIXME: other option should be to duplicate the
- * block for each duplicate and point the metadata at
- * the cloned blocks */
- }
- if(dh->ref_inode_count == 1) /* down to the last reference */
- return 1;
- return 0;
-}
-
-static int handle_dup_blk(struct gfs2_sbd *sbp, struct duptree *b)
-{
- struct gfs2_inode *ip;
- osi_list_t *tmp;
- struct inode_with_dups *id;
- struct dup_handler dh = {0};
- int last_reference, ref_in_invalid_inode = 0;
-
- osi_list_foreach(tmp, &b->ref_invinode_list) {
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- dh.ref_inode_count++;
- dh.ref_count += id->dup_count;
- ref_in_invalid_inode = 1;
- }
- osi_list_foreach(tmp, &b->ref_inode_list) {
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- dh.ref_inode_count++;
- dh.ref_count += id->dup_count;
- }
- /* A single reference to the block implies a possible situation where
- a data pointer points to a metadata block. In other words, the
- duplicate reference in the file system is (1) Metadata block X and
- (2) A dinode reference such as a data pointer pointing to block X.
- We can't really check for that in pass1 because user data might
- just _look_ like metadata by coincidence, and at the time we're
- checking, we might not have processed the referenced block.
- Here in pass1b we're sure. */
- /* Another possibility here is that there is a single reference
- because all the other metadata references were in inodes that got
- invalidated for other reasons, such as bad pointers. So we need to
- make sure at this point that any inode deletes reverse out any
- duplicate reference before we get to this point. */
- if (dh.ref_count == 1) {
- struct gfs2_buffer_head *bh;
- uint32_t cmagic;
-
- bh = bread(sbp, b->block);
- cmagic = ((struct gfs2_meta_header *)(bh->b_data))->mh_magic;
- brelse(bh);
- if (be32_to_cpu(cmagic) == GFS2_MAGIC) {
- if (ref_in_invalid_inode)
- tmp = b->ref_invinode_list.next;
- else
- tmp = b->ref_inode_list.next;
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- log_warn( _("Inode %s (%lld/0x%llx) has a reference to"
- " data block %llu (0x%llx), "
- "but the block is really metadata.\n"),
- id->name, (unsigned long long)id->block_no,
- (unsigned long long)id->block_no,
- (unsigned long long)b->block,
- (unsigned long long)b->block);
- if (query( _("Clear the inode? (y/n) "))) {
- struct inode_info *ii;
-
- log_warn( _("Clearing inode %lld (0x%llx)...\n"),
- (unsigned long long)id->block_no,
- (unsigned long long)id->block_no);
- ip = fsck_load_inode(sbp, id->block_no);
- ii = inodetree_find(ip->i_di.di_num.no_addr);
- if (ii)
- inodetree_delete(ii);
- /* Setting the block to invalid means the inode
- is cleared in pass2 */
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("inode with bad duplicate"),
- gfs2_inode_invalid);
- fsck_inode_put(&ip);
- } else {
- log_warn( _("The bad inode was not cleared."));
- }
- return 0;
- }
- /* The other references may have been discredited due to
- invalid metadata or something. Use the last remaining. */
- log_notice( _("Block %llu (0x%llx) has only one remaining "
- "reference.\n"),
- (unsigned long long)b->block,
- (unsigned long long)b->block);
- return 0;
- }
-
- log_notice( _("Block %llu (0x%llx) has %d inodes referencing it"
- " for a total of %d duplicate references\n"),
- (unsigned long long)b->block, (unsigned long long)b->block,
- dh.ref_inode_count, dh.ref_count);
-
- osi_list_foreach(tmp, &b->ref_invinode_list)
- log_inode_reference(b, tmp, 1);
- osi_list_foreach(tmp, &b->ref_inode_list)
- log_inode_reference(b, tmp, 0);
-
- last_reference = clear_a_reference(sbp, b, &b->ref_invinode_list,
- &dh, 1);
- if (!last_reference)
- last_reference = clear_a_reference(sbp, b, &b->ref_inode_list,
- &dh, 0);
-
- if (last_reference) {
- uint8_t q;
-
- /* If we're down to a single reference (and not all references
- deleted, which may be the case of an inode that has only
- itself and a reference), we need to reset the block type
- from invalid to data or metadata. Start at the first one
- in the list, not the structure's place holder. */
- tmp = (&b->ref_inode_list)->next;
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- log_debug( _("Resetting the type based on the remaining "
- "reference in inode %lld (0x%llx).\n"),
- (unsigned long long)id->block_no,
- (unsigned long long)id->block_no);
- ip = fsck_load_inode(sbp, id->block_no);
-
- q = block_type(id->block_no);
- if (q == gfs2_inode_invalid) {
- log_debug( _("The remaining reference inode %lld "
- "(0x%llx) is marked invalid: Marking "
- "the block as free.\n"),
- (unsigned long long)id->block_no,
- (unsigned long long)id->block_no);
- fsck_blockmap_set(ip, b->block,
- _("reference-repaired leaf"),
- gfs2_block_free);
- } else if (id->reftypecount[ref_as_data]) {
- fsck_blockmap_set(ip, b->block,
- _("reference-repaired data"),
- gfs2_block_used);
- } else if (id->reftypecount[ref_as_meta]) {
- if (S_ISDIR(ip->i_di.di_mode))
- fsck_blockmap_set(ip, b->block,
- _("reference-repaired leaf"),
- gfs2_leaf_blk);
- else
- fsck_blockmap_set(ip, b->block,
- _("reference-repaired "
- "indirect"),
- gfs2_indir_blk);
- } else
- fsck_blockmap_set(ip, b->block,
- _("reference-repaired extended "
- "attribute"),
- gfs2_meta_eattr);
- fsck_inode_put(&ip); /* out, brelse, free */
- } else {
- log_debug( _("All duplicate references were resolved.\n"));
- }
- return 0;
-}
-
-/* Pass 1b handles finding the previous inode for a duplicate block
- * When found, store the inodes pointing to the duplicate block for
- * use in pass2 */
-int pass1b(struct gfs2_sbd *sbp)
-{
- struct duptree *b;
- uint64_t i;
- uint8_t q;
- struct osi_node *n, *next = NULL;
- int rc = FSCK_OK;
-
- log_info( _("Looking for duplicate blocks...\n"));
-
- /* If there were no dups in the bitmap, we don't need to do anymore */
- if (dup_blocks.osi_node == NULL) {
- log_info( _("No duplicate blocks found\n"));
- return FSCK_OK;
- }
-
- /* Rescan the fs looking for pointers to blocks that are in
- * the duplicate block map */
- log_info( _("Scanning filesystem for inodes containing duplicate blocks...\n"));
- log_debug( _("Filesystem has %"PRIu64" (0x%" PRIx64 ") blocks total\n"),
- last_fs_block, last_fs_block);
- for(i = 0; i < last_fs_block; i++) {
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- goto out;
-
- if (dups_found_first == dups_found) {
- log_debug(_("Found all %d original references to "
- "duplicates.\n"), dups_found);
- break;
- }
- q = block_type(i);
-
- if (q < gfs2_inode_dir)
- continue;
- if (q > gfs2_inode_invalid)
- continue;
-
- if (q == gfs2_inode_invalid)
- log_debug( _("Checking invalidated duplicate dinode "
- "%lld (0x%llx)\n"),
- (unsigned long long)i,
- (unsigned long long)i);
-
- warm_fuzzy_stuff(i);
- if (find_block_ref(sbp, i) < 0) {
- stack;
- rc = FSCK_ERROR;
- goto out;
- }
- }
-
- /* Fix dups here - it's going to slow things down a lot to fix
- * it later */
- log_info( _("Handling duplicate blocks\n"));
-out:
- for (n = osi_first(&dup_blocks); n; n = next) {
- next = osi_next(n);
- b = (struct duptree *)n;
- if (!skip_this_pass && !rc) /* no error & not asked to skip the rest */
- handle_dup_blk(sbp, b);
- /* Do not attempt to free the dup_blocks list or its parts
- here because any func that calls check_metatree needs
- to check duplicate status based on this linked list.
- This is especially true for pass2 where it may delete "bad"
- inodes, and we can't delete an inode's indirect block if
- it was a duplicate (therefore in use by another dinode). */
- }
- return rc;
-}
diff --git a/gfs2/fsck/pass1c.c b/gfs2/fsck/pass1c.c
deleted file mode 100644
index 10b92ed..0000000
--- a/gfs2/fsck/pass1c.c
+++ /dev/null
@@ -1,271 +0,0 @@
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "fsck.h"
-#include "util.h"
-#include "metawalk.h"
-
-static int remove_eattr_entry(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *curr,
- struct gfs2_ea_header *prev)
-{
- if (!prev)
- curr->ea_type = GFS2_EATYPE_UNUSED;
- else {
- uint32_t tmp32 = be32_to_cpu(curr->ea_rec_len) +
- be32_to_cpu(prev->ea_rec_len);
- prev->ea_rec_len = cpu_to_be32(tmp32);
- if (curr->ea_flags & GFS2_EAFLAG_LAST)
- prev->ea_flags |= GFS2_EAFLAG_LAST;
- }
- log_err( _("Bad Extended Attribute at block #%"PRIu64
- " (0x%" PRIx64 ") removed.\n"),
- leaf_bh->b_blocknr, leaf_bh->b_blocknr);
- bmodified(leaf_bh);
- return 0;
-}
-
-static int ask_remove_eattr_entry(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *curr,
- struct gfs2_ea_header *prev,
- int fix_curr, int fix_curr_len)
-{
- if (query( _("Remove the bad Extended Attribute entry? (y/n) "))) {
- if (fix_curr)
- curr->ea_flags |= GFS2_EAFLAG_LAST;
- if (fix_curr_len) {
- uint32_t max_size = sdp->sd_sb.sb_bsize;
- uint32_t offset = (uint32_t)(((unsigned long)curr) -
- ((unsigned long)leaf_bh->b_data));
- curr->ea_rec_len = cpu_to_be32(max_size - offset);
- }
- if (remove_eattr_entry(sdp, leaf_bh, curr, prev)) {
- stack;
- return -1;
- }
- } else {
- log_err( _("Bad Extended Attribute not removed.\n"));
- }
- return 1;
-}
-
-static int ask_remove_eattr(struct gfs2_inode *ip)
-{
- if (query( _("Remove the bad Extended Attribute? (y/n) "))) {
- ip->i_di.di_eattr = 0;
- bmodified(ip->i_bh);
- log_err( _("Bad Extended Attribute removed.\n"));
- } else
- log_err( _("Bad Extended Attribute not removed.\n"));
- return 1;
-}
-
-static int check_eattr_indir(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- struct gfs2_sbd *sbp = ip->i_sbd;
- uint8_t q;
- struct gfs2_buffer_head *indir_bh = NULL;
-
- if(gfs2_check_range(sbp, block)) {
- log_err( _("Extended attributes indirect block #%llu"
- " (0x%llx) for inode #%llu"
- " (0x%llx) out of range...removing\n"),
- (unsigned long long)block,
- (unsigned long long)block,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- return ask_remove_eattr(ip);
- }
- q = block_type(block);
- if(q != gfs2_indir_blk) {
- log_err( _("Extended attributes indirect block #%llu"
- " (0x%llx) for inode #%llu"
- " (0x%llx) invalid.\n"),
- (unsigned long long)block,
- (unsigned long long)block,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- return ask_remove_eattr(ip);
- }
- else
- indir_bh = bread(sbp, block);
-
- *bh = indir_bh;
- return 0;
-}
-
-static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- struct gfs2_sbd *sbp = ip->i_sbd;
- uint8_t q;
-
- if(gfs2_check_range(sbp, block)) {
- log_err( _("Extended attributes block for inode #%llu"
- " (0x%llx) out of range.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- return ask_remove_eattr(ip);
- }
- q = block_type(block);
- if(q != gfs2_meta_eattr) {
- log_err( _("Extended attributes block for inode #%llu"
- " (0x%llx) invalid.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- return ask_remove_eattr(ip);
- }
- else
- *bh = bread(sbp, block);
-
- return 0;
-}
-
-static int check_eattr_entry(struct gfs2_inode *ip,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- char ea_name[256];
- uint32_t offset = (uint32_t)(((unsigned long)ea_hdr) -
- ((unsigned long)leaf_bh->b_data));
- uint32_t max_size = sdp->sd_sb.sb_bsize;
-
- if(!ea_hdr->ea_name_len){
- log_err( _("EA has name length == 0\n"));
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 1, 1);
- }
- if(offset + be32_to_cpu(ea_hdr->ea_rec_len) > max_size){
- log_err( _("EA rec length too long\n"));
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 1, 1);
- }
- if(offset + be32_to_cpu(ea_hdr->ea_rec_len) == max_size &&
- (ea_hdr->ea_flags & GFS2_EAFLAG_LAST) == 0){
- log_err( _("last EA has no last entry flag\n"));
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- }
- if(!ea_hdr->ea_name_len){
- log_err( _("EA has name length == 0\n"));
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- }
-
- memset(ea_name, 0, sizeof(ea_name));
- strncpy(ea_name, (char *)ea_hdr + sizeof(struct gfs2_ea_header),
- ea_hdr->ea_name_len);
-
- if(!GFS2_EATYPE_VALID(ea_hdr->ea_type) &&
- ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
- log_err( _("EA (%s) type is invalid (%d > %d).\n"),
- ea_name, ea_hdr->ea_type, GFS2_EATYPE_LAST);
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- }
-
- if(ea_hdr->ea_num_ptrs){
- uint32_t avail_size;
- int max_ptrs;
-
- avail_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
- max_ptrs = (be32_to_cpu(ea_hdr->ea_data_len)+avail_size-1)/avail_size;
-
- if(max_ptrs > ea_hdr->ea_num_ptrs){
- log_err( _("EA (%s) has incorrect number of pointers.\n"), ea_name);
- log_err( _(" Required: %d\n Reported: %d\n"),
- max_ptrs, ea_hdr->ea_num_ptrs);
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- } else {
- log_debug( _(" Pointers Required: %d\n Pointers Reported: %d\n"),
- max_ptrs, ea_hdr->ea_num_ptrs);
- }
- }
- return 0;
-}
-
-static int check_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_ptr,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev, void *private)
-{
- uint8_t q;
- struct gfs2_sbd *sbp = ip->i_sbd;
-
- q = block_type(be64_to_cpu(*ea_ptr));
- if(q != gfs2_meta_eattr) {
- if(remove_eattr_entry(sbp, leaf_bh, ea_hdr, ea_hdr_prev)){
- stack;
- return -1;
- }
- return 1;
- }
- return 0;
-}
-
-/* Go over all inodes with extended attributes and verify the EAs are
- * valid */
-int pass1c(struct gfs2_sbd *sbp)
-{
- uint64_t block_no = 0;
- struct gfs2_buffer_head *bh;
- struct gfs2_inode *ip = NULL;
- struct metawalk_fxns pass1c_fxns = { 0 };
- int error = 0;
- osi_list_t *tmp, *x;
- struct special_blocks *ea_block;
-
- pass1c_fxns.check_eattr_indir = &check_eattr_indir;
- pass1c_fxns.check_eattr_leaf = &check_eattr_leaf;
- pass1c_fxns.check_eattr_entry = &check_eattr_entry;
- pass1c_fxns.check_eattr_extentry = &check_eattr_extentry;
- pass1c_fxns.private = NULL;
-
- log_info( _("Looking for inodes containing ea blocks...\n"));
- osi_list_foreach_safe(tmp, &sbp->eattr_blocks.list, x) {
- ea_block = osi_list_entry(tmp, struct special_blocks, list);
- block_no = ea_block->block;
- warm_fuzzy_stuff(block_no);
-
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return FSCK_OK;
- bh = bread(sbp, block_no);
- if (!gfs2_check_meta(bh, GFS2_METATYPE_DI)) { /* if a dinode */
- log_info( _("EA in inode %"PRIu64" (0x%" PRIx64 ")\n"),
- block_no, block_no);
- gfs2_special_clear(&sbp->eattr_blocks, block_no);
- ip = fsck_inode_get(sbp, bh);
- ip->bh_owned = 1;
-
- log_debug( _("Found eattr at %llu (0x%llx)\n"),
- (unsigned long long)ip->i_di.di_eattr,
- (unsigned long long)ip->i_di.di_eattr);
- /* FIXME: Handle walking the eattr here */
- error = check_inode_eattr(ip, &pass1c_fxns);
- if(error < 0) {
- stack;
- brelse(bh);
- return FSCK_ERROR;
- }
-
- fsck_inode_put(&ip); /* dinode_out, brelse, free */
- } else {
- brelse(bh);
- }
- }
- return FSCK_OK;
-}
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
deleted file mode 100644
index 35acba4..0000000
--- a/gfs2/fsck/pass2.c
+++ /dev/null
@@ -1,821 +0,0 @@
-#include <dirent.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-#include <sys/stat.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "fsck.h"
-#include "util.h"
-#include "eattr.h"
-#include "metawalk.h"
-#include "link.h"
-
-#define MAX_FILENAME 256
-
-/* Set children's parent inode in dir_info structure - ext2 does not set
- * dotdot inode here, but instead in pass3 - should we? */
-static int set_parent_dir(struct gfs2_sbd *sbp, uint64_t childblock,
- uint64_t parentblock)
-{
- struct dir_info *di;
-
- di = dirtree_find(childblock);
- if(!di) {
- log_err( _("Unable to find block %"PRIu64" (0x%" PRIx64
- ") in dir_info list\n"), childblock, childblock);
- return -1;
- }
-
- if(di->dinode == childblock) {
- if (di->treewalk_parent) {
- log_err( _("Another directory at block %" PRIu64
- " (0x%" PRIx64 ") already contains this "
- "child %lld (%llx) - checking parent %"
- PRIu64 " (0x%" PRIx64 ")\n"),
- di->treewalk_parent, di->treewalk_parent,
- (unsigned long long)childblock,
- (unsigned long long)childblock,
- parentblock, parentblock);
- return 1;
- }
- log_debug( _("Child %lld (0x%llx) has parent %lld (0x%llx)\n"),
- (unsigned long long)childblock,
- (unsigned long long)childblock,
- (unsigned long long)parentblock,
- (unsigned long long)parentblock);
- di->treewalk_parent = parentblock;
- }
-
- return 0;
-}
-
-/* Set's the child's '..' directory inode number in dir_info structure */
-static int set_dotdot_dir(struct gfs2_sbd *sbp, uint64_t childblock,
- uint64_t parentblock)
-{
- struct dir_info *di;
-
- di = dirtree_find(childblock);
- if(di) {
- if(di->dinode == childblock) {
- /* Special case for root inode because we set
- * it earlier */
- if(di->dotdot_parent && sbp->md.rooti->i_di.di_num.no_addr
- != di->dinode) {
- /* This should never happen */
- log_crit( _("Dotdot parent already set for"
- " block %"PRIu64" (0x%" PRIx64 ") -> %" PRIu64
- " (0x%" PRIx64 ")\n"), childblock, childblock,
- di->dotdot_parent, di->dotdot_parent);
- return -1;
- }
- di->dotdot_parent = parentblock;
- }
- } else {
- log_err( _("Unable to find block %"PRIu64" (0x%" PRIx64
- ") in dir_info list\n"), childblock, childblock);
- return -1;
- }
-
- return 0;
-
-}
-
-static int check_eattr_indir(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- *bh = bread(ip->i_sbd, block);
- return 0;
-}
-static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- *bh = bread(ip->i_sbd, block);
- return 0;
-}
-
-static const char *de_type_string(uint8_t de_type)
-{
- const char *de_types[15] = {"unknown", "fifo", "chrdev", "invalid",
- "directory", "invalid", "blkdev", "invalid",
- "file", "invalid", "symlink", "invalid",
- "socket", "invalid", "wht"};
- if (de_type < 15)
- return de_types[de_type];
- return de_types[3]; /* invalid */
-}
-
-static int check_file_type(uint8_t de_type, uint8_t blk_type)
-{
- switch(blk_type) {
- case gfs2_inode_dir:
- if(de_type != DT_DIR)
- return 1;
- break;
- case gfs2_inode_file:
- if(de_type != DT_REG)
- return 1;
- break;
- case gfs2_inode_lnk:
- if(de_type != DT_LNK)
- return 1;
- break;
- case gfs2_inode_blk:
- if(de_type != DT_BLK)
- return 1;
- break;
- case gfs2_inode_chr:
- if(de_type != DT_CHR)
- return 1;
- break;
- case gfs2_inode_fifo:
- if(de_type != DT_FIFO)
- return 1;
- break;
- case gfs2_inode_sock:
- if(de_type != DT_SOCK)
- return 1;
- break;
- default:
- log_err( _("Invalid block type\n"));
- return -1;
- break;
- }
- return 0;
-}
-
-struct metawalk_fxns pass2_fxns_delete = {
- .private = NULL,
- .check_metalist = delete_metadata,
- .check_data = delete_data,
- .check_leaf = delete_leaf,
- .check_eattr_indir = delete_eattr_indir,
- .check_eattr_leaf = delete_eattr_leaf,
-};
-
-/* FIXME: should maybe refactor this a bit - but need to deal with
- * FIXMEs internally first */
-static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
- struct gfs2_dirent *prev_de,
- struct gfs2_buffer_head *bh, char *filename,
- uint16_t *count, void *priv)
-{
- struct gfs2_sbd *sbp = ip->i_sbd;
- uint8_t q;
- char tmp_name[MAX_FILENAME];
- uint64_t entryblock;
- struct dir_status *ds = (struct dir_status *) priv;
- int error;
- struct gfs2_inode *entry_ip = NULL;
- struct metawalk_fxns clear_eattrs = {0};
- struct gfs2_dirent dentry, *de;
- uint32_t calculated_hash;
-
- memset(&dentry, 0, sizeof(struct gfs2_dirent));
- gfs2_dirent_in(&dentry, (char *)dent);
- de = &dentry;
-
- clear_eattrs.check_eattr_indir = delete_eattr_indir;
- clear_eattrs.check_eattr_leaf = delete_eattr_leaf;
- clear_eattrs.check_eattr_entry = clear_eattr_entry;
- clear_eattrs.check_eattr_extentry = clear_eattr_extentry;
-
- entryblock = de->de_inum.no_addr;
-
- /* Start of checks */
- memset(tmp_name, 0, MAX_FILENAME);
- if(de->de_name_len < MAX_FILENAME)
- strncpy(tmp_name, filename, de->de_name_len);
- else
- strncpy(tmp_name, filename, MAX_FILENAME - 1);
-
- if(gfs2_check_range(ip->i_sbd, entryblock)) {
- log_err( _("Block # referenced by directory entry %s in inode "
- "%lld (0x%llx) is out of range\n"),
- tmp_name, (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if(query( _("Clear directory entry to out of range block? "
- "(y/n) "))) {
- goto nuke_dentry;
- } else {
- log_err( _("Directory entry to out of range block remains\n"));
- (*count)++;
- ds->entry_count++;
- /* can't do this because the block is out of range:
- increment_link(entryblock); */
- return 0;
- }
- }
-
- if (de->de_rec_len < GFS2_DIRENT_SIZE(de->de_name_len)) {
- log_err( _("Dir entry with bad record or name length\n"
- "\tRecord length = %u\n\tName length = %u\n"),
- de->de_rec_len, de->de_name_len);
- if(!query( _("Clear the directory entry? (y/n) "))) {
- log_err( _("Directory entry not fixed.\n"));
- goto dentry_is_valid;
- }
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("corrupt directory entry"),
- gfs2_inode_invalid);
- log_err( _("Bad directory entry deleted.\n"));
- return 1;
- }
-
- calculated_hash = gfs2_disk_hash(tmp_name, de->de_name_len);
- if (de->de_hash != calculated_hash){
- log_err( _("Dir entry with bad hash or name length\n"
- "\tHash found = %u (0x%x)\n"
- "\tFilename = %s\n"),
- de->de_hash, de->de_hash, tmp_name);
- log_err( _("\tName length found = %u\n"
- "\tHash expected = %u (0x%x)\n"),
- de->de_name_len, calculated_hash, calculated_hash);
- if(!query( _("Fix directory hash for %s? (y/n) "),
- tmp_name)) {
- log_err( _("Directory entry hash for %s not "
- "fixed.\n"), tmp_name);
- goto dentry_is_valid;
- }
- de->de_hash = calculated_hash;
- gfs2_dirent_out(de, (char *)dent);
- bmodified(bh);
- log_err( _("Directory entry hash for %s fixed.\n"),
- tmp_name);
- }
-
- q = block_type(entryblock);
- /* Get the status of the directory inode */
- if(q == gfs2_inode_invalid || q == gfs2_bad_block) {
- /* This entry's inode has bad blocks in it */
-
- /* Handle bad blocks */
- log_err( _("Found a bad directory entry: %s\n"), tmp_name);
-
- if(!query( _("Delete inode containing bad blocks? (y/n)"))) {
- log_warn( _("Entry to inode containing bad blocks remains\n"));
- goto dentry_is_valid;
- }
-
- if (ip->i_di.di_num.no_addr == entryblock)
- entry_ip = ip;
- else
- entry_ip = fsck_load_inode(sbp, entryblock);
- check_inode_eattr(entry_ip, &pass2_fxns_delete);
- check_metatree(entry_ip, &pass2_fxns_delete);
- if (entry_ip != ip)
- fsck_inode_put(&entry_ip);
- fsck_blockmap_set(ip, entryblock,
- _("bad directory entry"), gfs2_block_free);
- goto nuke_dentry;
- }
- if(q < gfs2_inode_dir || q > gfs2_inode_sock) {
- log_err( _("Directory entry '%s' referencing inode %llu "
- "(0x%llx) in dir inode %llu (0x%llx) block type "
- "%d: %s.\n"), tmp_name,
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- q, q == gfs2_inode_invalid ?
- _("was previously marked invalid") :
- _("was deleted or is not an inode"));
-
- if(!query( _("Clear directory entry to non-inode block? "
- "(y/n) "))) {
- log_err( _("Directory entry to non-inode block remains\n"));
- goto dentry_is_valid;
- }
-
- /* Don't decrement the link here: Here in pass2, we increment
- only when we know it's okay.
- decrement_link(ip->i_di.di_num.no_addr); */
- /* If it was previously marked invalid (i.e. known
- to be bad, not just a free block, etc.) then the temptation
- would be to delete any metadata it holds. The trouble is:
- if it's invalid, we may or _may_not_ have traversed its
- metadata tree, and therefore may or may not have marked the
- blocks it points to as a metadata type, or as a duplicate.
- If there is really a duplicate reference, but we didn't
- process the metadata tree because it's invalid, some other
- inode has a reference to the metadata block, in which case
- freeing it would do more harm than good. IOW we cannot
- count on "delete_block_if_notdup" knowing whether it's
- really a duplicate block if we never traversed the metadata
- tree for the invalid inode. */
- goto nuke_dentry;
- }
-
- error = check_file_type(de->de_type, q);
- if(error < 0) {
- log_err( _("Error: directory entry type is "
- "incompatible with block type at block %lld "
- "(0x%llx) in directory inode %llu (0x%llx).\n"),
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- log_err( _("Directory entry type is %d, block type is %d.\n"),
- de->de_type, q);
- stack;
- return -1;
- }
- if(error > 0) {
- log_err( _("Type '%s' in dir entry (%s, %llu/0x%llx) conflicts"
- " with type '%s' in dinode. (Dir entry is stale.)\n"),
- de_type_string(de->de_type), tmp_name,
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
- block_type_string(q));
- if(!query( _("Clear stale directory entry? (y/n) "))) {
- log_err( _("Stale directory entry remains\n"));
- goto dentry_is_valid;
- }
- if (ip->i_di.di_num.no_addr == entryblock)
- entry_ip = ip;
- else
- entry_ip = fsck_load_inode(sbp, entryblock);
- check_inode_eattr(entry_ip, &clear_eattrs);
- if (entry_ip != ip)
- fsck_inode_put(&entry_ip);
- goto nuke_dentry;
- }
-
- if(!strcmp(".", tmp_name)) {
- log_debug( _("Found . dentry\n"));
-
- if(ds->dotdir) {
- log_err( _("Already found '.' entry in directory %llu"
- " (0x%llx)\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if(!query( _("Clear duplicate '.' entry? (y/n) "))) {
- log_err( _("Duplicate '.' entry remains\n"));
- /* FIXME: Should we continue on here
- * and check the rest of the '.' entry? */
- goto dentry_is_valid;
- }
- if (ip->i_di.di_num.no_addr == entryblock)
- entry_ip = ip;
- else
- entry_ip = fsck_load_inode(sbp, entryblock);
- check_inode_eattr(entry_ip, &clear_eattrs);
- if (entry_ip != ip)
- fsck_inode_put(&entry_ip);
- goto nuke_dentry;
- }
-
- /* GFS2 does not rely on '.' being in a certain
- * location */
-
- /* check that '.' refers to this inode */
- if(entryblock != ip->i_di.di_num.no_addr) {
- log_err( _("'.' entry's value incorrect in directory %llu"
- " (0x%llx). Points to %llu"
- " (0x%llx) when it should point to %llu"
- " (0x%llx).\n"),
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if(!query( _("Remove '.' reference? (y/n) "))) {
- log_err( _("Invalid '.' reference remains\n"));
- /* Not setting ds->dotdir here since
- * this '.' entry is invalid */
- goto dentry_is_valid;
- }
- if (ip->i_di.di_num.no_addr == entryblock)
- entry_ip = ip;
- else
- entry_ip = fsck_load_inode(sbp, entryblock);
- check_inode_eattr(entry_ip, &clear_eattrs);
- if (entry_ip != ip)
- fsck_inode_put(&entry_ip);
- goto nuke_dentry;
- }
-
- ds->dotdir = 1;
- goto dentry_is_valid;
- }
- if(!strcmp("..", tmp_name)) {
- log_debug( _("Found .. dentry\n"));
- if(ds->dotdotdir) {
- log_err( _("Already found '..' entry in directory %llu"
- "(0x%llx)\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if(!query( _("Clear duplicate '..' entry? (y/n) "))) {
- log_err( _("Duplicate '..' entry remains\n"));
- /* FIXME: Should we continue on here
- * and check the rest of the '..'
- * entry? */
- goto dentry_is_valid;
- }
-
- if (ip->i_di.di_num.no_addr == entryblock)
- entry_ip = ip;
- else
- entry_ip = fsck_load_inode(sbp, entryblock);
- check_inode_eattr(entry_ip, &clear_eattrs);
- if (entry_ip != ip)
- fsck_inode_put(&entry_ip);
-
- goto nuke_dentry;
- }
-
- if(q != gfs2_inode_dir) {
- log_err( _("Found '..' entry in directory %llu (0x%llx) "
- "pointing to something that's not a directory"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if(!query( _("Clear bad '..' directory entry? (y/n) "))) {
- log_err( _("Bad '..' directory entry remains\n"));
- goto dentry_is_valid;
- }
- if (ip->i_di.di_num.no_addr == entryblock)
- entry_ip = ip;
- else
- entry_ip = fsck_load_inode(sbp, entryblock);
- check_inode_eattr(entry_ip, &clear_eattrs);
- if (entry_ip != ip)
- fsck_inode_put(&entry_ip);
-
- goto nuke_dentry;
- }
- /* GFS2 does not rely on '..' being in a certain location */
-
- /* Add the address this entry is pointing to
- * to this inode's dotdot_parent in
- * dir_info */
- if(set_dotdot_dir(sbp, ip->i_di.di_num.no_addr, entryblock)) {
- stack;
- return -1;
- }
-
- ds->dotdotdir = 1;
- goto dentry_is_valid;
- }
-
- /* After this point we're only concerned with directories */
- if(q != gfs2_inode_dir) {
- log_debug( _("Found non-dir inode dentry pointing to %lld "
- "(0x%llx)\n"),
- (unsigned long long)entryblock,
- (unsigned long long)entryblock);
- goto dentry_is_valid;
- }
-
- /*log_debug( _("Found plain directory dentry\n"));*/
- error = set_parent_dir(sbp, entryblock, ip->i_di.di_num.no_addr);
- if(error > 0) {
- log_err( _("%s: Hard link to block %" PRIu64" (0x%" PRIx64
- ") detected.\n"), tmp_name, entryblock, entryblock);
-
- if(query( _("Clear hard link to directory? (y/n) ")))
- goto nuke_dentry;
- else {
- log_err( _("Hard link to directory remains\n"));
- goto dentry_is_valid;
- }
- } else if (error < 0) {
- stack;
- return -1;
- }
-dentry_is_valid:
- /* This directory inode links to this inode via this dentry */
- increment_link(entryblock, ip->i_di.di_num.no_addr,
- _("valid reference"));
- (*count)++;
- ds->entry_count++;
- /* End of checks */
- return 0;
-
-nuke_dentry:
- dirent2_del(ip, bh, prev_de, dent);
- log_err( _("Bad directory entry '%s' cleared.\n"), tmp_name);
- return 1;
-}
-
-
-struct metawalk_fxns pass2_fxns = {
- .private = NULL,
- .check_leaf = NULL,
- .check_metalist = NULL,
- .check_data = NULL,
- .check_eattr_indir = check_eattr_indir,
- .check_eattr_leaf = check_eattr_leaf,
- .check_dentry = check_dentry,
- .check_eattr_entry = NULL,
-};
-
-/* Check system directory inode */
-/* Should work for all system directories: root, master, jindex, per_node */
-static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
- int builder(struct gfs2_sbd *sbp))
-{
- uint64_t iblock = 0;
- struct dir_status ds = {0};
- char *filename;
- int filename_len;
- char tmp_name[256];
- int error = 0;
-
- log_info( _("Checking system directory inode '%s'\n"), dirname);
-
- if (sysinode) {
- iblock = sysinode->i_di.di_num.no_addr;
- ds.q = block_type(iblock);
- }
- pass2_fxns.private = (void *) &ds;
- if(ds.q == gfs2_bad_block) {
- /* First check that the directory's metatree is valid */
- error = check_metatree(sysinode, &pass2_fxns);
- if (error < 0) {
- stack;
- return error;
- }
- }
- error = check_dir(sysinode->i_sbd, iblock, &pass2_fxns);
- if(error < 0) {
- stack;
- return -1;
- }
- if (error > 0)
- fsck_blockmap_set(sysinode, iblock, dirname,
- gfs2_inode_invalid);
-
- if(check_inode_eattr(sysinode, &pass2_fxns)) {
- stack;
- return -1;
- }
- if(!ds.dotdir) {
- log_err( _("No '.' entry found for %s directory.\n"), dirname);
- if (query( _("Is it okay to add '.' entry? (y/n) "))) {
- uint64_t cur_blks = sysinode->i_di.di_blocks;
-
- sprintf(tmp_name, ".");
- filename_len = strlen(tmp_name); /* no trailing NULL */
- if(!(filename = malloc(sizeof(char) * filename_len))) {
- log_err( _("Unable to allocate name string\n"));
- stack;
- return -1;
- }
- if(!(memset(filename, 0, sizeof(char) *
- filename_len))) {
- log_err( _("Unable to zero name string\n"));
- stack;
- return -1;
- }
- memcpy(filename, tmp_name, filename_len);
- log_warn( _("Adding '.' entry\n"));
- dir_add(sysinode, filename, filename_len,
- &(sysinode->i_di.di_num), DT_DIR);
- if (cur_blks != sysinode->i_di.di_blocks)
- reprocess_inode(sysinode, dirname);
- /* This system inode is linked to itself via '.' */
- increment_link(sysinode->i_di.di_num.no_addr,
- sysinode->i_di.di_num.no_addr,
- "sysinode \".\"");
- ds.entry_count++;
- free(filename);
- } else
- log_err( _("The directory was not fixed.\n"));
- }
- if(sysinode->i_di.di_entries != ds.entry_count) {
- log_err( _("%s inode %llu (0x%llx"
- "): Entries is %d - should be %d\n"), dirname,
- (unsigned long long)sysinode->i_di.di_num.no_addr,
- (unsigned long long)sysinode->i_di.di_num.no_addr,
- sysinode->i_di.di_entries, ds.entry_count);
- if(query( _("Fix entries for %s inode %llu (0x%llx)? (y/n) "),
- dirname,
- (unsigned long long)sysinode->i_di.di_num.no_addr,
- (unsigned long long)sysinode->i_di.di_num.no_addr)) {
- sysinode->i_di.di_entries = ds.entry_count;
- bmodified(sysinode->i_bh);
- log_warn( _("Entries updated\n"));
- } else {
- log_err( _("Entries for inode %llu (0x%llx"
- ") left out of sync\n"),
- (unsigned long long)
- sysinode->i_di.di_num.no_addr,
- (unsigned long long)
- sysinode->i_di.di_num.no_addr);
- }
- }
- return 0;
-}
-
-/**
- * is_system_dir - determine if a given block is for a system directory.
- */
-static inline int is_system_dir(struct gfs2_sbd *sbp, uint64_t block)
-{
- if (block == sbp->md.rooti->i_di.di_num.no_addr ||
- block == sbp->md.jiinode->i_di.di_num.no_addr ||
- block == sbp->md.pinode->i_di.di_num.no_addr ||
- block == sbp->master_dir->i_di.di_num.no_addr)
- return TRUE;
- return FALSE;
-}
-
-/* What i need to do in this pass is check that the dentries aren't
- * pointing to invalid blocks...and verify the contents of each
- * directory. and start filling in the directory info structure*/
-
-/**
- * pass2 - check pathnames
- *
- * verify root inode
- * directory name length
- * entries in range
- */
-int pass2(struct gfs2_sbd *sbp)
-{
- uint64_t dirblk;
- uint8_t q;
- struct dir_status ds = {0};
- struct gfs2_inode *ip;
- char *filename;
- int filename_len;
- char tmp_name[256];
- int error = 0;
-
- /* Check all the system directory inodes. */
- if (check_system_dir(sbp->md.jiinode, "jindex", build_jindex)) {
- stack;
- return FSCK_ERROR;
- }
- if (check_system_dir(sbp->md.pinode, "per_node", build_per_node)) {
- stack;
- return FSCK_ERROR;
- }
- if (check_system_dir(sbp->master_dir, "master", build_master)) {
- stack;
- return FSCK_ERROR;
- }
- if (check_system_dir(sbp->md.rooti, "root", build_root)) {
- stack;
- return FSCK_ERROR;
- }
- log_info( _("Checking directory inodes.\n"));
- /* Grab each directory inode, and run checks on it */
- for(dirblk = 0; dirblk < last_fs_block; dirblk++) {
- warm_fuzzy_stuff(dirblk);
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return FSCK_OK;
-
- /* Skip the system inodes - they're checked above */
- if (is_system_dir(sbp, dirblk))
- continue;
-
- q = block_type(dirblk);
-
- if(q != gfs2_inode_dir)
- continue;
-
- log_debug( _("Checking directory inode at block %"PRIu64" (0x%"
- PRIx64 ")\n"), dirblk, dirblk);
-
- memset(&ds, 0, sizeof(ds));
- pass2_fxns.private = (void *) &ds;
- if(ds.q == gfs2_bad_block) {
- /* First check that the directory's metatree
- * is valid */
- ip = fsck_load_inode(sbp, dirblk);
- error = check_metatree(ip, &pass2_fxns);
- fsck_inode_put(&ip);
- if (error < 0) {
- stack;
- return error;
- }
- }
- error = check_dir(sbp, dirblk, &pass2_fxns);
- if(error < 0) {
- stack;
- return FSCK_ERROR;
- }
- if (error > 0) {
- struct dir_info *di;
-
- di = dirtree_find(dirblk);
- if(!di) {
- stack;
- return FSCK_ERROR;
- }
- if(query( _("Remove directory entry for bad"
- " inode %"PRIu64" (0x%" PRIx64 ") in %"PRIu64
- " (0x%" PRIx64 ")? (y/n)"), dirblk,
- dirblk, di->treewalk_parent,
- di->treewalk_parent)) {
- error = remove_dentry_from_dir(sbp, di->treewalk_parent,
- dirblk);
- if(error < 0) {
- stack;
- return FSCK_ERROR;
- }
- if(error > 0) {
- log_warn( _("Unable to find dentry for %"
- PRIu64 " (0x%" PRIx64 ") in %" PRIu64
- " (0x%" PRIx64 ")\n"),
- dirblk, dirblk,
- di->treewalk_parent,
- di->treewalk_parent);
- }
- log_warn( _("Directory entry removed\n"));
- } else
- log_err( _("Directory entry to invalid inode remains.\n"));
- log_debug( _("Directory block %lld (0x%llx) "
- "is now marked as 'invalid'\n"),
- (unsigned long long)dirblk,
- (unsigned long long)dirblk);
- /* Can't use fsck_blockmap_set here because we don't
- have an inode in memory. */
- gfs2_blockmap_set(bl, dirblk, gfs2_inode_invalid);
- check_n_fix_bitmap(sbp, dirblk, gfs2_inode_invalid);
- }
- ip = fsck_load_inode(sbp, dirblk);
- if(!ds.dotdir) {
- log_err(_("No '.' entry found for directory inode at "
- "block %"PRIu64" (0x%" PRIx64 ")\n"),
- dirblk, dirblk);
-
- if (query( _("Is it okay to add '.' entry? (y/n) "))) {
- uint64_t cur_blks;
-
- sprintf(tmp_name, ".");
- filename_len = strlen(tmp_name); /* no trailing
- NULL */
- if(!(filename = malloc(sizeof(char) *
- filename_len))) {
- log_err(_("Unable to allocate name\n"));
- stack;
- return FSCK_ERROR;
- }
- if(!memset(filename, 0, sizeof(char) *
- filename_len)) {
- log_err( _("Unable to zero name\n"));
- stack;
- return FSCK_ERROR;
- }
- memcpy(filename, tmp_name, filename_len);
-
- cur_blks = ip->i_di.di_blocks;
- dir_add(ip, filename, filename_len,
- &(ip->i_di.di_num), DT_DIR);
- if (cur_blks != ip->i_di.di_blocks) {
- char dirname[80];
-
- sprintf(dirname, _("Directory at %lld "
- "(0x%llx)"),
- (unsigned long long)dirblk,
- (unsigned long long)dirblk);
- reprocess_inode(ip, dirname);
- }
- /* directory links to itself via '.' */
- increment_link(ip->i_di.di_num.no_addr,
- ip->i_di.di_num.no_addr,
- _("\". (itself)\""));
- ds.entry_count++;
- free(filename);
- log_err( _("The directory was fixed.\n"));
- } else {
- log_err( _("The directory was not fixed.\n"));
- }
- }
-
- if(!fsck_abort && ip->i_di.di_entries != ds.entry_count) {
- log_err( _("Entries is %d - should be %d for inode "
- "block %llu (0x%llx)\n"),
- ip->i_di.di_entries, ds.entry_count,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if (query( _("Fix the entry count? (y/n) "))) {
- ip->i_di.di_entries = ds.entry_count;
- bmodified(ip->i_bh);
- } else {
- log_err( _("The entry count was not fixed.\n"));
- }
- }
- fsck_inode_put(&ip); /* does a gfs2_dinode_out, brelse */
- }
- /* Now that we've deleted the inodes marked "bad" we can safely
- get rid of the duplicate block list. If we do it any sooner,
- we won't discover that a given block is a duplicate and avoid
- deleting it from both inodes referencing it. Note: The other
- returns from this function are premature exits of the program
- and gfs2_block_list_destroy should get rid of the list for us. */
- gfs2_dup_free();
- return FSCK_OK;
-}
-
-
-
diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c
deleted file mode 100644
index e1fe5a5..0000000
--- a/gfs2/fsck/pass3.c
+++ /dev/null
@@ -1,301 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <string.h>
-#include <dirent.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "osi_list.h"
-#include "fsck.h"
-#include "lost_n_found.h"
-#include "link.h"
-#include "metawalk.h"
-#include "util.h"
-
-static int attach_dotdot_to(struct gfs2_sbd *sbp, uint64_t newdotdot,
- uint64_t olddotdot, uint64_t block)
-{
- char *filename;
- int filename_len;
- struct gfs2_inode *ip, *pip;
- uint64_t cur_blks;
-
- ip = fsck_load_inode(sbp, block);
- pip = fsck_load_inode(sbp, newdotdot);
- /* FIXME: Need to add some interactive
- * options here and come up with a
- * good default for non-interactive */
- /* FIXME: do i need to correct the
- * '..' entry for this directory in
- * this case? */
-
- filename_len = strlen("..");
- if(!(filename = malloc((sizeof(char) * filename_len) + 1))) {
- log_err( _("Unable to allocate name\n"));
- fsck_inode_put(&ip);
- fsck_inode_put(&pip);
- stack;
- return -1;
- }
- if(!memset(filename, 0, (sizeof(char) * filename_len) + 1)) {
- log_err( _("Unable to zero name\n"));
- fsck_inode_put(&ip);
- fsck_inode_put(&pip);
- stack;
- return -1;
- }
- memcpy(filename, "..", filename_len);
- if(gfs2_dirent_del(ip, filename, filename_len))
- log_warn( _("Unable to remove \"..\" directory entry.\n"));
- else
- decrement_link(olddotdot, block, _("old \"..\""));
- cur_blks = ip->i_di.di_blocks;
- dir_add(ip, filename, filename_len, &pip->i_di.di_num, DT_DIR);
- if (cur_blks != ip->i_di.di_blocks) {
- char dirname[80];
-
- sprintf(dirname, _("Directory at %lld (0x%llx)"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- reprocess_inode(ip, dirname);
- }
- increment_link(newdotdot, block, _("new \"..\""));
- fsck_inode_put(&ip);
- fsck_inode_put(&pip);
- free(filename);
- return 0;
-}
-
-static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp,
- struct dir_info *di)
-{
- struct dir_info *pdi;
- uint8_t q_dotdot, q_treewalk;
-
- di->checked = 1;
-
- if(!di->treewalk_parent)
- return NULL;
-
- if(di->dotdot_parent != di->treewalk_parent) {
- log_warn( _("Directory '..' and treewalk connections disagree for inode %"
- PRIu64 " (0x%" PRIx64 ")\n"), di->dinode, di->dinode);
- log_notice( _("'..' has %" PRIu64" (0x%" PRIx64 "), treewalk has %"
- PRIu64" (0x%" PRIx64 ")\n"), di->dotdot_parent,
- di->dotdot_parent, di->treewalk_parent,
- di->treewalk_parent);
- q_dotdot = block_type(di->dotdot_parent);
- q_treewalk = block_type(di->treewalk_parent);
- /* if the dotdot entry isn't a directory, but the
- * treewalk is, treewalk is correct - if the treewalk
- * entry isn't a directory, but the dotdot is, dotdot
- * is correct - if both are directories, which do we
- * choose? if neither are directories, we have a
- * problem - need to move this directory into lost+found
- */
- if(q_dotdot != gfs2_inode_dir) {
- if(q_treewalk != gfs2_inode_dir) {
- log_err( _("Orphaned directory, move to lost+found\n"));
- return NULL;
- }
- else {
- log_warn( _("Treewalk parent is correct,"
- " fixing dotdot -> %"PRIu64" (0x%" PRIx64 ")\n"),
- di->treewalk_parent, di->treewalk_parent);
- attach_dotdot_to(sbp, di->treewalk_parent,
- di->dotdot_parent, di->dinode);
- di->dotdot_parent = di->treewalk_parent;
- }
- } else {
- if(q_treewalk != gfs2_inode_dir) {
- int error = 0;
- log_warn( _(".. parent is valid, but treewalk"
- "is bad - reattaching to lost+found"));
-
- /* FIXME: add a dinode for this entry instead? */
-
- if(query( _("Remove directory entry for bad"
- " inode %"PRIu64" (0x%" PRIx64 ") in %"PRIu64
- " (0x%" PRIx64 ")? (y/n)"), di->dinode, di->dinode,
- di->treewalk_parent, di->treewalk_parent)) {
- error = remove_dentry_from_dir(sbp, di->treewalk_parent,
- di->dinode);
- if(error < 0) {
- stack;
- return NULL;
- }
- if(error > 0) {
- log_warn( _("Unable to find dentry for block %"
- PRIu64" (0x%" PRIx64 ") in %" PRIu64 " (0x%"
- PRIx64 ")\n"),di->dinode, di->dinode,
- di->treewalk_parent, di->treewalk_parent);
- }
- log_warn( _("Directory entry removed\n"));
- } else {
- log_err( _("Directory entry to invalid inode remains\n"));
- }
- log_info( _("Marking directory unlinked\n"));
-
- return NULL;
- }
- else {
- log_err( _("Both .. and treewalk parents are "
- "directories, going with treewalk "
- "for now...\n"));
- attach_dotdot_to(sbp, di->treewalk_parent,
- di->dotdot_parent,
- di->dinode);
- di->dotdot_parent = di->treewalk_parent;
- }
- }
- }
- else {
- q_dotdot = block_type(di->dotdot_parent);
- if(q_dotdot != gfs2_inode_dir) {
- log_err( _("Orphaned directory at block %" PRIu64 " (0x%" PRIx64
- ") moved to lost+found\n"), di->dinode, di->dinode);
- return NULL;
- }
- }
- pdi = dirtree_find(di->dotdot_parent);
-
- return pdi;
-}
-
-/**
- * pass3 - check connectivity of directories
- *
- * handle disconnected directories
- * handle lost+found directory errors (missing, not a directory, no space)
- */
-int pass3(struct gfs2_sbd *sbp)
-{
- struct osi_node *tmp, *next = NULL;
- struct dir_info *di, *tdi;
- struct gfs2_inode *ip;
- uint8_t q;
-
- di = dirtree_find(sbp->md.rooti->i_di.di_num.no_addr);
- if (di) {
- log_info( _("Marking root inode connected\n"));
- di->checked = 1;
- }
- di = dirtree_find(sbp->master_dir->i_di.di_num.no_addr);
- if (di) {
- log_info( _("Marking master directory inode connected\n"));
- di->checked = 1;
- }
-
- /* Go through the directory list, working up through the parents
- * until we find one that's been checked already. If we don't
- * find a parent, put in lost+found.
- */
- log_info( _("Checking directory linkage.\n"));
- for (tmp = osi_first(&dirtree); tmp; tmp = next) {
- next = osi_next(tmp);
- di = (struct dir_info *)tmp;
- while(!di->checked) {
- /* FIXME: Change this so it returns success or
- * failure and put the parent inode in a
- * param */
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return FSCK_OK;
- tdi = mark_and_return_parent(sbp, di);
-
- if (tdi) {
- log_debug( _("Directory at block %" PRIu64
- " (0x%" PRIx64 ") connected\n"),
- di->dinode, di->dinode);
- di = tdi;
- continue;
- }
- q = block_type(di->dinode);
- if(q == gfs2_bad_block) {
- log_err( _("Found unlinked directory "
- "containing bad block\n"));
- if(query(_("Clear unlinked directory "
- "with bad blocks? (y/n) "))) {
- log_warn( _("inode %lld (0x%llx) is "
- "now marked as free\n"),
- (unsigned long long)
- di->dinode,
- (unsigned long long)
- di->dinode);
- /* Can't use fsck_blockmap_set
- because we don't have ip */
- gfs2_blockmap_set(bl, di->dinode,
- gfs2_block_free);
- check_n_fix_bitmap(sbp, di->dinode,
- gfs2_block_free);
- break;
- } else
- log_err( _("Unlinked directory with bad block remains\n"));
- }
- if(q != gfs2_inode_dir && q != gfs2_inode_file &&
- q != gfs2_inode_lnk && q != gfs2_inode_blk &&
- q != gfs2_inode_chr && q != gfs2_inode_fifo &&
- q != gfs2_inode_sock) {
- log_err( _("Unlinked block marked as an inode "
- "is not an inode\n"));
- if(!query(_("Clear the unlinked block?"
- " (y/n) "))) {
- log_err( _("The block was not "
- "cleared\n"));
- break;
- }
- log_warn( _("inode %lld (0x%llx) is now "
- "marked as free\n"),
- (unsigned long long)di->dinode,
- (unsigned long long)di->dinode);
- /* Can't use fsck_blockmap_set
- because we don't have ip */
- gfs2_blockmap_set(bl, di->dinode,
- gfs2_block_free);
- check_n_fix_bitmap(sbp, di->dinode,
- gfs2_block_free);
- log_err( _("The block was cleared\n"));
- break;
- }
-
- log_err( _("Found unlinked directory at block %" PRIu64
- " (0x%" PRIx64 ")\n"), di->dinode,
- di->dinode);
- ip = fsck_load_inode(sbp, di->dinode);
- /* Don't skip zero size directories with eattrs */
- if(!ip->i_di.di_size && !ip->i_di.di_eattr){
- log_err( _("Unlinked directory has zero "
- "size.\n"));
- if(query( _("Remove zero-size unlinked "
- "directory? (y/n) "))) {
- fsck_blockmap_set(ip, di->dinode,
- _("zero-sized unlinked inode"),
- gfs2_block_free);
- fsck_inode_put(&ip);
- break;
- } else {
- log_err( _("Zero-size unlinked "
- "directory remains\n"));
- }
- }
- if(query( _("Add unlinked directory to "
- "lost+found? (y/n) "))) {
- if(add_inode_to_lf(ip)) {
- fsck_inode_put(&ip);
- stack;
- return FSCK_ERROR;
- }
- log_warn( _("Directory relinked to lost+found\n"));
- } else {
- log_err( _("Unlinked directory remains unlinked\n"));
- }
- fsck_inode_put(&ip);
- break;
- }
- }
- if(lf_dip)
- log_debug( _("At end of pass3, lost+found entries is %u\n"),
- lf_dip->i_di.di_entries);
- return FSCK_OK;
-}
diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c
deleted file mode 100644
index 0fd0aac..0000000
--- a/gfs2/fsck/pass4.c
+++ /dev/null
@@ -1,204 +0,0 @@
-#include <inttypes.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "fsck.h"
-#include "lost_n_found.h"
-#include "inode_hash.h"
-#include "metawalk.h"
-#include "util.h"
-
-struct metawalk_fxns pass4_fxns_delete = {
- .private = NULL,
- .check_metalist = delete_metadata,
- .check_data = delete_data,
- .check_eattr_indir = delete_eattr_indir,
- .check_eattr_leaf = delete_eattr_leaf,
-};
-
-/* Updates the link count of an inode to what the fsck has seen for
- * link count */
-static int fix_link_count(struct inode_info *ii, struct gfs2_inode *ip)
-{
- log_info( _("Fixing inode link count (%d->%d) for %llu (0x%llx) \n"),
- ip->i_di.di_nlink, ii->counted_links,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if(ip->i_di.di_nlink == ii->counted_links)
- return 0;
- ip->i_di.di_nlink = ii->counted_links;
- bmodified(ip->i_bh);
-
- log_debug( _("Changing inode %llu (0x%llx) to have %u links\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- ii->counted_links);
- return 0;
-}
-
-static int scan_inode_list(struct gfs2_sbd *sbp) {
- struct osi_node *tmp, *next = NULL;
- struct inode_info *ii;
- struct gfs2_inode *ip;
- int lf_addition = 0;
- uint8_t q;
-
- /* FIXME: should probably factor this out into a generic
- * scanning fxn */
- for (tmp = osi_first(&inodetree); tmp; tmp = next) {
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return 0;
- next = osi_next(tmp);
- if(!(ii = (struct inode_info *)tmp)) {
- log_crit( _("osi_tree broken in scan_info_list!!\n"));
- exit(FSCK_ERROR);
- }
- if(ii->counted_links == 0) {
- log_err( _("Found unlinked inode at %" PRIu64 " (0x%" PRIx64 ")\n"),
- ii->inode, ii->inode);
- q = block_type(ii->inode);
- if(q == gfs2_bad_block) {
- log_err( _("Unlinked inode %llu (0x%llx) contains"
- "bad blocks\n"),
- (unsigned long long)ii->inode,
- (unsigned long long)ii->inode);
- if(query( _("Delete unlinked inode with bad "
- "blocks? (y/n) "))) {
- ip = fsck_load_inode(sbp, ii->inode);
- check_inode_eattr(ip,
- &pass4_fxns_delete);
- check_metatree(ip, &pass4_fxns_delete);
- fsck_blockmap_set(ip, ii->inode,
- _("bad unlinked"),
- gfs2_block_free);
- fsck_inode_put(&ip);
- continue;
- } else
- log_err( _("Unlinked inode with bad blocks not cleared\n"));
- }
- if(q != gfs2_inode_dir &&
- q != gfs2_inode_file &&
- q != gfs2_inode_lnk &&
- q != gfs2_inode_blk &&
- q != gfs2_inode_chr &&
- q != gfs2_inode_fifo &&
- q != gfs2_inode_sock) {
- log_err( _("Unlinked block %lld (0x%llx) "
- "marked as inode is "
- "not an inode (%d)\n"),
- (unsigned long long)ii->inode,
- (unsigned long long)ii->inode, q);
- ip = fsck_load_inode(sbp, ii->inode);
- if(query(_("Delete unlinked inode? (y/n) "))) {
- check_inode_eattr(ip,
- &pass4_fxns_delete);
- check_metatree(ip, &pass4_fxns_delete);
- fsck_blockmap_set(ip, ii->inode,
- _("invalid unlinked"),
- gfs2_block_free);
- fsck_inode_put(&ip);
- log_err( _("The inode was deleted\n"));
- } else {
- log_err( _("The inode was not "
- "deleted\n"));
- fsck_inode_put(&ip);
- }
- continue;
- }
- ip = fsck_load_inode(sbp, ii->inode);
-
- /* We don't want to clear zero-size files with
- * eattrs - there might be relevent info in
- * them. */
- if(!ip->i_di.di_size && !ip->i_di.di_eattr){
- log_err( _("Unlinked inode has zero size\n"));
- if(query(_("Clear zero-size unlinked inode? "
- "(y/n) "))) {
- fsck_blockmap_set(ip, ii->inode,
- _("unlinked zero-length"),
- gfs2_block_free);
- fsck_inode_put(&ip);
- continue;
- }
-
- }
- if(query( _("Add unlinked inode to lost+found? "
- "(y/n)"))) {
- if(add_inode_to_lf(ip)) {
- stack;
- fsck_inode_put(&ip);
- return -1;
- } else {
- fix_link_count(ii, ip);
- lf_addition = 1;
- }
- } else
- log_err( _("Unlinked inode left unlinked\n"));
- fsck_inode_put(&ip);
- } /* if(ii->counted_links == 0) */
- else if(ii->link_count != ii->counted_links) {
- log_err( _("Link count inconsistent for inode %" PRIu64
- " (0x%" PRIx64 ") has %u but fsck found %u.\n"), ii->inode,
- ii->inode, ii->link_count, ii->counted_links);
- /* Read in the inode, adjust the link count,
- * and write it back out */
- if(query( _("Update link count for inode %" PRIu64
- " (0x%" PRIx64 ") ? (y/n) "),
- ii->inode, ii->inode)) {
- ip = fsck_load_inode(sbp, ii->inode); /* bread, inode_get */
- fix_link_count(ii, ip);
- ii->link_count = ii->counted_links;
- fsck_inode_put(&ip); /* out, brelse, free */
- log_warn( _("Link count updated to %d for "
- "inode %" PRIu64 " (0x%"
- PRIx64 ") \n"), ii->link_count,
- ii->inode, ii->inode);
- } else {
- log_err( _("Link count for inode %" PRIu64 " (0x%" PRIx64
- ") still incorrect\n"), ii->inode, ii->inode);
- }
- }
- log_debug( _("block %" PRIu64 " (0x%" PRIx64 ") has link count %d\n"),
- ii->inode, ii->inode, ii->link_count);
- } /* osi_list_foreach(tmp, list) */
-
- if (lf_addition) {
- if(!(ii = inodetree_find(lf_dip->i_di.di_num.no_addr))) {
- log_crit( _("Unable to find lost+found inode in inode_hash!!\n"));
- return -1;
- } else {
- fix_link_count(ii, lf_dip);
- }
- }
-
- return 0;
-}
-
-/**
- * pass4 - Check reference counts (pass 2 & 6 in current fsck)
- *
- * handle unreferenced files
- * lost+found errors (missing, not a directory, no space)
- * adjust link count
- * handle unreferenced inodes of other types
- * handle bad blocks
- */
-int pass4(struct gfs2_sbd *sbp)
-{
- if(lf_dip)
- log_debug( _("At beginning of pass4, lost+found entries is %u\n"),
- lf_dip->i_di.di_entries);
- log_info( _("Checking inode reference counts.\n"));
- if(scan_inode_list(sbp)) {
- stack;
- return FSCK_ERROR;
- }
-
- if(lf_dip)
- log_debug( _("At end of pass4, lost+found entries is %u\n"),
- lf_dip->i_di.di_entries);
- return FSCK_OK;
-}
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
deleted file mode 100644
index 79493e1..0000000
--- a/gfs2/fsck/pass5.c
+++ /dev/null
@@ -1,217 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "fsck.h"
-#include "util.h"
-
-static int convert_mark(uint8_t q, uint32_t *count)
-{
- switch(q) {
-
- case gfs2_meta_inval:
- case gfs2_inode_invalid:
- /* Convert invalid metadata to free blocks */
- case gfs2_block_free:
- count[0]++;
- return GFS2_BLKST_FREE;
-
- case gfs2_block_used:
- count[2]++;
- return GFS2_BLKST_USED;
-
- case gfs2_inode_dir:
- case gfs2_inode_file:
- case gfs2_inode_lnk:
- case gfs2_inode_blk:
- case gfs2_inode_chr:
- case gfs2_inode_fifo:
- case gfs2_inode_sock:
- count[1]++;
- return GFS2_BLKST_DINODE;
-
- case gfs2_indir_blk:
- case gfs2_leaf_blk:
- case gfs2_meta_rgrp:
- case gfs2_meta_eattr:
- count[2]++;
- return GFS2_BLKST_USED;
-
- default:
- log_err( _("Invalid block type %d found\n"), q);
- return -1;
- }
- return -1;
-}
-
-static int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int buflen,
- uint64_t *rg_block, uint64_t rg_data, uint32_t *count)
-{
- unsigned char *byte, *end;
- unsigned int bit;
- unsigned char rg_status, block_status;
- uint8_t q;
- uint64_t block;
-
- /* FIXME verify cast */
- byte = (unsigned char *) buffer;
- bit = 0;
- end = (unsigned char *) buffer + buflen;
-
- while(byte < end) {
- rg_status = ((*byte >> bit) & GFS2_BIT_MASK);
- block = rg_data + *rg_block;
- warm_fuzzy_stuff(block);
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return 0;
- q = block_type(block);
-
- block_status = convert_mark(q, count);
-
- /* If one node opens a file and another node deletes it, we
- may be left with a block that appears to be "unlinked" in
- the bitmap, but nothing links to it. This is a valid case
- and should be cleaned up by the file system eventually.
- So we ignore it. */
- if (rg_status == GFS2_BLKST_UNLINKED &&
- block_status == GFS2_BLKST_FREE) {
- log_err( _("Unlinked inode block found at "
- "block %llu (0x%llx).\n"),
- (unsigned long long)block,
- (unsigned long long)block);
- if(query(_("Do you want to fix the bitmap? (y/n) "))) {
- if(gfs2_set_bitmap(sbp, block, block_status))
- log_err(_("Unlinked block %llu "
- "(0x%llx) bitmap not fixed."
- "\n"),
- (unsigned long long)block,
- (unsigned long long)block);
- else
- log_err(_("Unlinked block %llu "
- "(0x%llx) bitmap fixed.\n"),
- (unsigned long long)block,
- (unsigned long long)block);
- } else {
- log_info( _("Unlinked block found at block %"
- PRIu64" (0x%" PRIx64 "), left "
- "unchanged.\n"), block, block);
- }
- } else if (rg_status != block_status) {
- const char *blockstatus[] = {"Free", "Data",
- "Unlinked", "inode"};
-
- log_err( _("Ondisk and fsck bitmaps differ at"
- " block %"PRIu64" (0x%" PRIx64 ") \n"), block, block);
- log_err( _("Ondisk status is %u (%s) but FSCK thinks it should be "),
- rg_status, blockstatus[rg_status]);
- log_err("%u (%s)\n", block_status, blockstatus[block_status]);
- log_err( _("Metadata type is %u (%s)\n"), q,
- block_type_string(q));
-
- if(query(_("Fix bitmap for block %" PRIu64
- " (0x%" PRIx64 ") ? (y/n) "),
- block, block)) {
- if(gfs2_set_bitmap(sbp, block, block_status))
- log_err( _("Failed.\n"));
- else
- log_err( _("Succeeded.\n"));
- } else
- log_err( _("Bitmap at block %"PRIu64" (0x%" PRIx64
- ") left inconsistent\n"), block, block);
- }
- (*rg_block)++;
- bit += GFS2_BIT_SIZE;
- if (bit >= 8){
- bit = 0;
- byte++;
- }
- }
-
- return 0;
-}
-
-static void update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp,
- uint32_t *count)
-{
- uint32_t i;
- struct gfs2_bitmap *bits;
- uint64_t rg_block = 0;
- int update = 0;
-
- for(i = 0; i < rgp->ri.ri_length; i++) {
- bits = &rgp->bits[i];
-
- /* update the bitmaps */
- check_block_status(sbp, rgp->bh[i]->b_data + bits->bi_offset,
- bits->bi_len, &rg_block, rgp->ri.ri_data0, count);
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return;
- }
-
- /* actually adjust counters and write out to disk */
- if(rgp->rg.rg_free != count[0]) {
- log_err( _("RG #%llu (0x%llx) free count inconsistent: "
- "is %u should be %u\n"),
- (unsigned long long)rgp->ri.ri_addr,
- (unsigned long long)rgp->ri.ri_addr,
- rgp->rg.rg_free, count[0]);
- rgp->rg.rg_free = count[0];
- update = 1;
- }
- if(rgp->rg.rg_dinodes != count[1]) {
- log_err( _("Inode count inconsistent: is %u should be %u\n"),
- rgp->rg.rg_dinodes, count[1]);
- rgp->rg.rg_dinodes = count[1];
- update = 1;
- }
- if((rgp->ri.ri_data - count[0] - count[1]) != count[2]) {
- /* FIXME not sure how to handle this case ATM - it
- * means that the total number of blocks we've counted
- * exceeds the blocks in the rg */
- log_err( _("Internal fsck error - AAHHH!\n"));
- exit(FSCK_ERROR);
- }
- if(update) {
- if(query( _("Update resource group counts? (y/n) "))) {
- log_warn( _("Resource group counts updated\n"));
- /* write out the rgrp */
- gfs2_rgrp_out(&rgp->rg, rgp->bh[0]);
- } else
- log_err( _("Resource group counts left inconsistent\n"));
- }
-}
-
-/**
- * pass5 - check resource groups
- *
- * fix free block maps
- * fix used inode maps
- */
-int pass5(struct gfs2_sbd *sbp)
-{
- osi_list_t *tmp;
- struct rgrp_list *rgp = NULL;
- uint32_t count[3];
- uint64_t rg_count = 0;
-
- /* Reconcile RG bitmaps with fsck bitmap */
- for(tmp = sbp->rglist.next; tmp != &sbp->rglist; tmp = tmp->next){
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return FSCK_OK;
- log_info( _("Verifying Resource Group #%" PRIu64 "\n"), rg_count);
- memset(count, 0, sizeof(count));
- rgp = osi_list_entry(tmp, struct rgrp_list, list);
-
- rg_count++;
- /* Compare the bitmaps and report the differences */
- update_rgrp(sbp, rgp, count);
- }
- /* Fix up superblock info based on this - don't think there's
- * anything to do here... */
-
- return FSCK_OK;
-}
diff --git a/gfs2/fsck/rgrepair.c b/gfs2/fsck/rgrepair.c
deleted file mode 100644
index 705ba86..0000000
--- a/gfs2/fsck/rgrepair.c
+++ /dev/null
@@ -1,617 +0,0 @@
-#include <unistd.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "osi_list.h"
-#include "fsck.h"
-
-int rindex_modified = FALSE;
-struct special_blocks false_rgrps;
-
-#define ri_equal(ondisk, expected, field) (ondisk.field == expected.field)
-
-#define ri_compare(rg, ondisk, expected, field, fmt) \
- if (ondisk.field != expected.field) { \
- log_warn( _("rindex #%d " #field " discrepancy: index 0x%" \
- fmt " != expected: 0x%" fmt "\n"), \
- rg + 1, ondisk.field, expected.field); \
- ondisk.field = expected.field; \
- rindex_modified = TRUE; \
- }
-
-/*
- * find_journal_entry_rgs - find all RG blocks within all journals
- *
- * Since Resource Groups (RGs) are journaled, it is not uncommon for them
- * to appear inside a journal. But if there is severe damage to the rindex
- * file or some of the RGs, we may need to hunt and peck for RGs and in that
- * case, we don't want to mistake these blocks that look just a real RG
- * for a real RG block. These are "fake" RGs that need to be ignored for
- * the purposes of finding where things are.
- */
-static void find_journaled_rgs(struct gfs2_sbd *sdp)
-{
- int j, new = 0;
- unsigned int jblocks;
- uint64_t b, dblock;
- uint32_t extlen;
- struct gfs2_inode *ip;
- struct gfs2_buffer_head *bh;
-
- osi_list_init(&false_rgrps.list);
- for (j = 0; j < sdp->md.journals; j++) {
- log_debug( _("Checking for RGs in journal%d.\n"), j);
- ip = sdp->md.journal[j];
- jblocks = ip->i_di.di_size / sdp->sd_sb.sb_bsize;
- for (b = 0; b < jblocks; b++) {
- block_map(ip, b, &new, &dblock, &extlen, 0);
- if (!dblock)
- break;
- bh = bread(sdp, dblock);
- if (!gfs2_check_meta(bh, GFS2_METATYPE_RG)) {
- log_debug( _("False RG found at block "
- "0x%" PRIx64 "\n"), dblock);
- gfs2_special_set(&false_rgrps, dblock);
- }
- brelse(bh);
- }
- }
-}
-
-static int is_false_rg(uint64_t block)
-{
- if (blockfind(&false_rgrps, block))
- return 1;
- return 0;
-}
-
-/*
- * gfs2_rindex_rebuild - rebuild a corrupt Resource Group (RG) index manually
- * where trust_lvl == distrust
- *
- * If this routine is called, it means we have RGs in odd/unexpected places,
- * and there is a corrupt RG or RG index entry. It also means we can't trust
- * the RG index to be sane, and the RGs don't agree with how mkfs would have
- * built them by default. So we have no choice but to go through and count
- * them by hand. We've tried twice to recover the RGs and RG index, and
- * failed, so this is our last chance to remedy the situation.
- *
- * This routine tries to minimize performance impact by:
- * 1. Skipping through the filesystem at known increments when possible.
- * 2. Shuffle through every block when RGs are not found at the predicted
- * locations.
- *
- * Note: A GFS2 filesystem differs from a GFS1 file system in that there will
- * only be ONE chunk (i.e. no artificial subdevices on either size of the
- * journals). The journals and even the rindex are kept as part of the file
- * system, so we need to rebuild that information by hand. Also, with GFS1,
- * the different chunks ("subdevices") could have different RG sizes, which
- * made for quite a mess when trying to recover RGs. GFS2 always uses the
- * same RG size determined by the original mkfs, so recovery is easier.
- *
- */
-static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, osi_list_t *ret_list,
- int *num_rgs)
-{
- struct gfs2_buffer_head *bh;
- uint64_t shortest_dist_btwn_rgs;
- uint64_t blk, block_of_last_rg;
- uint64_t fwd_block, block_bump;
- uint64_t first_rg_dist, initial_first_rg_dist;
- struct rgrp_list *calc_rgd, *prev_rgd;
- int number_of_rgs, rgi;
- struct gfs2_rindex buf, tmpndx;
- int rg_was_fnd = FALSE, corrupt_rgs = 0, bitmap_was_fnd;
- osi_list_t *tmp;
-
- /* Figure out if there are any RG-looking blocks in the journal we
- need to ignore. */
- find_journaled_rgs(sdp);
- osi_list_init(ret_list);
- number_of_rgs = 0;
- initial_first_rg_dist = first_rg_dist = sdp->sb_addr + 1;
- block_of_last_rg = sdp->sb_addr + 1;
- /* ------------------------------------------------------------- */
- /* First, hunt and peck for the shortest distance between RGs. */
- /* Sample several of them because an RG that's been blasted may */
- /* look like twice the distance. If we can find 6 of them, that */
- /* should be enough to figure out the correct layout. */
- /* ------------------------------------------------------------- */
- shortest_dist_btwn_rgs = sdp->device.length;
- for (blk = sdp->sb_addr + 1;
- blk < sdp->device.length && number_of_rgs < 6;
- blk++) {
- bh = bread(sdp, blk);
- if (((blk == sdp->sb_addr + 1) ||
- (!gfs2_check_meta(bh, GFS2_METATYPE_RG))) &&
- !is_false_rg(blk)) {
- log_debug( _("RG found at block 0x%" PRIx64 "\n"), blk);
- if (blk > sdp->sb_addr + 1) {
- uint64_t rgdist;
-
- rgdist = blk - block_of_last_rg;
- log_debug("dist 0x%llx = 0x%llx - 0x%llx",
- (unsigned long long)rgdist,
- (unsigned long long)blk,
- (unsigned long long)block_of_last_rg);
- /* ----------------------------------------- */
- /* We found an RG. Check to see if we need */
- /* to set the first_rg_dist based on whether */
- /* it's still at its initial value (i.e. the */
- /* fs.) The first rg distance is different */
- /* from the rest because of the superblock */
- /* and 64K dead space. */
- /* ----------------------------------------- */
- if (first_rg_dist == initial_first_rg_dist)
- first_rg_dist = rgdist;
- if (rgdist < shortest_dist_btwn_rgs) {
- shortest_dist_btwn_rgs = rgdist;
- log_debug( _("(shortest so far)\n"));
- }
- else
- log_debug("\n");
- }
- block_of_last_rg = blk;
- number_of_rgs++;
- blk += 250; /* skip ahead for performance */
- }
- brelse(bh);
- }
- number_of_rgs = 0;
- gfs2_special_free(&false_rgrps);
-
- /* -------------------------------------------------------------- */
- /* Sanity-check our first_rg_dist. If RG #2 got nuked, the */
- /* first_rg_dist would measure from #1 to #3, which would be bad. */
- /* We need to take remedial measures to fix it (from the index). */
- /* -------------------------------------------------------------- */
- log_debug( _("First RG distance: 0x%" PRIx64 "\n"), first_rg_dist);
- log_debug( _("Distance between RGs: 0x%" PRIx64 "\n"),
- shortest_dist_btwn_rgs);
- if (first_rg_dist >= shortest_dist_btwn_rgs +
- (shortest_dist_btwn_rgs / 4)) {
- /* read in the second RG index entry for this subd. */
- gfs2_readi(sdp->md.riinode, (char *)&buf,
- sizeof(struct gfs2_rindex),
- sizeof(struct gfs2_rindex));
- gfs2_rindex_in(&tmpndx, (char *)&buf);
- if (tmpndx.ri_addr > sdp->sb_addr + 1) { /* sanity check */
- log_warn( _("RG 2 is damaged: getting dist from index: "));
- first_rg_dist = tmpndx.ri_addr - (sdp->sb_addr + 1);
- log_warn("0x%" PRIx64 "\n", first_rg_dist);
- }
- else {
- log_warn( _("RG index 2 is damaged: extrapolating dist: "));
- first_rg_dist = sdp->device.length -
- (sdp->rgrps - 1) *
- (sdp->device.length / sdp->rgrps);
- log_warn("0x%" PRIx64 "\n", first_rg_dist);
- }
- log_debug( _("Adjusted first RG distance: 0x%" PRIx64 "\n"),
- first_rg_dist);
- } /* if first RG distance is within tolerance */
- /* -------------------------------------------------------------- */
- /* Now go through the RGs and verify their integrity, fixing as */
- /* needed when corruption is encountered. */
- /* -------------------------------------------------------------- */
- prev_rgd = NULL;
- block_bump = first_rg_dist;
- for (blk = sdp->sb_addr + 1; blk <= sdp->device.length;
- blk += block_bump) {
- log_debug( _("Block 0x%" PRIx64 "\n"), blk);
- bh = bread(sdp, blk);
- rg_was_fnd = (!gfs2_check_meta(bh, GFS2_METATYPE_RG));
- brelse(bh);
- /* Allocate a new RG and index. */
- calc_rgd = malloc(sizeof(struct rgrp_list));
- if (!calc_rgd) {
- log_crit( _("Can't allocate memory for rg repair.\n"));
- return -1;
- }
- memset(calc_rgd, 0, sizeof(struct rgrp_list));
- osi_list_add_prev(&calc_rgd->list, ret_list);
- calc_rgd->ri.ri_length = 1;
- calc_rgd->ri.ri_addr = blk;
- if (!rg_was_fnd) { /* if not an RG */
- /* ------------------------------------------------- */
- /* This SHOULD be an RG but isn't. */
- /* ------------------------------------------------- */
- corrupt_rgs++;
- if (corrupt_rgs < 5)
- log_debug( _("Missing or damaged RG at block %"
- PRIu64 " (0x%" PRIx64 ")\n"),
- blk, blk);
- else {
- log_crit( _("Error: too many bad RGs.\n"));
- return -1;
- }
- }
- /* ------------------------------------------------ */
- /* Now go through and count the bitmaps for this RG */
- /* ------------------------------------------------ */
- bitmap_was_fnd = FALSE;
- for (fwd_block = blk + 1;
- fwd_block < sdp->device.length;
- fwd_block++) {
- bh = bread(sdp, fwd_block);
- bitmap_was_fnd =
- (!gfs2_check_meta(bh, GFS2_METATYPE_RB));
- brelse(bh);
- if (bitmap_was_fnd) /* if a bitmap */
- calc_rgd->ri.ri_length++;
- else
- break; /* end of bitmap, so call it quits. */
- } /* for subsequent bitmaps */
-
- gfs2_compute_bitstructs(sdp, calc_rgd);
- calc_rgd->ri.ri_data0 = calc_rgd->ri.ri_addr +
- calc_rgd->ri.ri_length;
- if (prev_rgd) {
- uint32_t rgblocks, bitblocks;
-
- rgblocks = block_bump;
- rgblocks2bitblocks(sdp->bsize, &rgblocks, &bitblocks);
-
- prev_rgd->ri.ri_length = bitblocks;
- prev_rgd->ri.ri_data = rgblocks;
- prev_rgd->ri.ri_data -= prev_rgd->ri.ri_data %
- GFS2_NBBY;
- prev_rgd->ri.ri_bitbytes = prev_rgd->ri.ri_data /
- GFS2_NBBY;
- log_debug( _("Prev ri_data set to: %" PRIx32 ".\n"),
- prev_rgd->ri.ri_data);
- }
- number_of_rgs++;
- log_warn( _("%c RG %d at block 0x%" PRIX64 " %s"),
- (rg_was_fnd ? ' ' : '*'), number_of_rgs, blk,
- (rg_was_fnd ? "intact" : "*** DAMAGED ***"));
- prev_rgd = calc_rgd;
- block_of_last_rg = blk;
-
- if (blk == sdp->sb_addr + 1)
- block_bump = first_rg_dist;
- else
- block_bump = shortest_dist_btwn_rgs;
- if (block_bump != 1)
- log_warn( _(" [length 0x%" PRIx64 "]\n"), block_bump);
- } /* for each rg block */
- /* ----------------------------------------------------------------- */
- /* If we got to the end of the fs, we still need to fix the */
- /* allocation information for the very last RG. */
- /* ----------------------------------------------------------------- */
- if (prev_rgd && !prev_rgd->ri.ri_data) {
- uint32_t rgblocks, bitblocks;
-
- rgblocks = block_bump;
- rgblocks2bitblocks(sdp->bsize, &rgblocks, &bitblocks);
-
- prev_rgd->ri.ri_length = bitblocks;
- prev_rgd->ri.ri_data = rgblocks;
- prev_rgd->ri.ri_data -= prev_rgd->ri.ri_data % GFS2_NBBY;
- prev_rgd->ri.ri_bitbytes = prev_rgd->ri.ri_data / GFS2_NBBY;
- log_debug( _("Prev ri_data set to: %" PRIx32 ".\n"),
- prev_rgd->ri.ri_data);
- prev_rgd = NULL; /* make sure we don't use it later */
- }
- /* ---------------------------------------------- */
- /* Now dump out the information (if verbose mode) */
- /* ---------------------------------------------- */
- log_debug( _("RG index rebuilt as follows:\n"));
- for (tmp = ret_list, rgi = 0; tmp != ret_list;
- tmp = tmp->next, rgi++) {
- calc_rgd = osi_list_entry(tmp, struct rgrp_list, list);
- log_debug("%d: 0x%llx / %x / 0x%llx"
- " / 0x%x / 0x%x\n", rgi + 1,
- (unsigned long long)calc_rgd->ri.ri_addr,
- calc_rgd->ri.ri_length,
- calc_rgd->ri.ri_data0, calc_rgd->ri.ri_data,
- calc_rgd->ri.ri_bitbytes);
- }
- *num_rgs = number_of_rgs;
- return 0;
-}
-
-/*
- * gfs2_rindex_calculate - calculate what the rindex should look like
- * in a perfect world (trust_lvl == open_minded)
- *
- * Calculate what the rindex should look like,
- * so we can later check if all RG index entries are sane.
- * This is a lot easier for gfs2 because we can just call the same libgfs2
- * functions used by mkfs.
- *
- * Returns: 0 on success, -1 on failure
- * Sets: sdp->rglist to a linked list of fsck_rgrp structs representing
- * what we think the rindex should really look like.
- */
-static int gfs2_rindex_calculate(struct gfs2_sbd *sdp, osi_list_t *ret_list,
- int *num_rgs)
-{
- osi_list_init(ret_list);
- sdp->rgsize = GFS2_DEFAULT_RGSIZE; /* compute_rgrp_layout adjusts */
- if (device_geometry(sdp)) {
- fprintf(stderr, _("Geometry error\n"));
- exit(-1);
- }
- if (fix_device_geometry(sdp)) {
- fprintf(stderr, _("Device is too small (%"PRIu64" bytes)\n"),
- sdp->device.length << GFS2_BASIC_BLOCK_SHIFT);
- exit(-1);
- }
-
- /* Compute the default resource group layout as mkfs would have done */
- compute_rgrp_layout(sdp, FALSE);
- build_rgrps(sdp, FALSE); /* FALSE = calc but don't write to disk. */
- *num_rgs = 0;
- log_debug( _("fs_total_size = 0x%" PRIX64 " blocks.\n"),
- sdp->device.length);
- /* ----------------------------------------------------------------- */
- /* Calculate how many RGs there are supposed to be based on the */
- /* rindex filesize. Remember that our trust level is open-minded */
- /* here. If the filesize of the rindex file is not a multiple of */
- /* our rindex structures, then something's wrong and we can't trust */
- /* the index. */
- /* ----------------------------------------------------------------- */
- *num_rgs = sdp->md.riinode->i_di.di_size / sizeof(struct gfs2_rindex);
- log_warn( _("L2: number of rgs in the index = %d.\n"), *num_rgs);
- /* Move the rg list to the return list */
- ret_list->next = sdp->rglist.next;
- ret_list->prev = sdp->rglist.prev;
- ret_list->next->prev = ret_list;
- ret_list->prev->next = ret_list;
- return 0;
-}
-
-/*
- * rewrite_rg_block - rewrite ("fix") a buffer with rg or bitmap data
- * returns: 0 if the rg was repaired, otherwise 1
- */
-static int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_list *rg,
- uint64_t errblock)
-{
- int x = errblock - rg->ri.ri_addr;
-
- log_err( _("Block #%lld (0x%llx) (%d of %d) is neither"
- " GFS2_METATYPE_RB nor GFS2_METATYPE_RG.\n"),
- (unsigned long long)rg->ri.ri_addr + x,
- (unsigned long long)rg->ri.ri_addr + x,
- (int)x+1, (int)rg->ri.ri_length);
- if (query( _("Fix the Resource Group? (y/n)"))) {
- log_err( _("Attempting to repair the RG.\n"));
- rg->bh[x] = bread(sdp, rg->ri.ri_addr + x);
- if (x) {
- struct gfs2_meta_header mh;
-
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_RB;
- mh.mh_format = GFS2_FORMAT_RB;
- gfs2_meta_header_out(&mh, rg->bh[x]);
- } else {
- memset(&rg->rg, 0, sizeof(struct gfs2_rgrp));
- rg->rg.rg_header.mh_magic = GFS2_MAGIC;
- rg->rg.rg_header.mh_type = GFS2_METATYPE_RG;
- rg->rg.rg_header.mh_format = GFS2_FORMAT_RG;
- rg->rg.rg_free = rg->ri.ri_data;
- gfs2_rgrp_out(&rg->rg, rg->bh[x]);
- }
- brelse(rg->bh[x]);
- rg->bh[x] = NULL;
- return 0;
- }
- return 1;
-}
-
-/*
- * expect_rindex_sanity - the rindex file seems trustworthy, so use those
- * values as our expected values and assume the
- * damage is only to the rgrps themselves.
- */
-static int expect_rindex_sanity(struct gfs2_sbd *sdp, osi_list_t *ret_list,
- int *num_rgs)
-{
- osi_list_t *tmp;
- struct rgrp_list *exp, *rgd; /* expected, actual */
-
- *num_rgs = sdp->md.riinode->i_di.di_size / sizeof(struct gfs2_rindex);
- osi_list_init(ret_list);
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
-
- exp = calloc(1, sizeof(struct rgrp_list));
- if (exp == NULL) {
- fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
- exit(-1);
- }
- exp->start = rgd->start;
- exp->length = rgd->length;
- memcpy(&exp->ri, &rgd->ri, sizeof(exp->ri));
- memcpy(&exp->rg, &rgd->rg, sizeof(exp->rg));
- exp->bits = NULL;
- gfs2_compute_bitstructs(sdp, exp);
- osi_list_add_prev(&exp->list, ret_list);
- }
- sdp->rgrps = *num_rgs;
- return 0;
-}
-
-/*
- * rg_repair - try to repair a damaged rg index (rindex)
- * trust_lvl - This is how much we trust the rindex file.
- * blind_faith means we take the rindex at face value.
- * open_minded means it might be okay, but we should verify it.
- * distrust means it's not to be trusted, so we should go to
- * greater lengths to build it from scratch.
- */
-int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
-{
- int error, discrepancies;
- osi_list_t expected_rglist;
- int calc_rg_count = 0, rgcount_from_index, rg;
- osi_list_t *exp, *act; /* expected, actual */
- struct gfs2_rindex buf;
-
- if (trust_lvl == blind_faith)
- return 0;
- else if (trust_lvl == ye_of_little_faith) { /* if rindex seems sane */
- if (!(*sane)) {
- log_err(_("The rindex file does not meet our "
- "expectations.\n"));
- return -1;
- }
- error = expect_rindex_sanity(sdp, &expected_rglist,
- &calc_rg_count);
- if (error)
- return error;
- } else if (trust_lvl == open_minded) { /* If we can't trust RG index */
- /* Calculate our own RG index for comparison */
- error = gfs2_rindex_calculate(sdp, &expected_rglist,
- &calc_rg_count);
- if (error) { /* If calculated RGs don't match the fs */
- gfs2_rgrp_free(&expected_rglist);
- return -1;
- }
- }
- else if (trust_lvl == distrust) { /* If we can't trust RG index */
- error = gfs2_rindex_rebuild(sdp, &expected_rglist,
- &calc_rg_count);
- if (error) {
- log_crit( _("Error rebuilding rg list.\n"));
- gfs2_rgrp_free(&expected_rglist);
- return -1;
- }
- sdp->rgrps = calc_rg_count;
- }
- /* Read in the rindex */
- osi_list_init(&sdp->rglist); /* Just to be safe */
- rindex_read(sdp, 0, &rgcount_from_index, sane);
- if (sdp->md.riinode->i_di.di_size % sizeof(struct gfs2_rindex)) {
- log_warn( _("WARNING: rindex file is corrupt.\n"));
- gfs2_rgrp_free(&expected_rglist);
- gfs2_rgrp_free(&sdp->rglist);
- return -1;
- }
- log_warn( _("L%d: number of rgs expected = %lld.\n"), trust_lvl + 1,
- (unsigned long long)sdp->rgrps);
- if (calc_rg_count != sdp->rgrps) {
- log_warn( _("L%d: They don't match; either (1) the fs was extended, (2) an odd\n"), trust_lvl + 1);
- log_warn( _("L%d: rg size was used, or (3) we have a corrupt rg index.\n"), trust_lvl + 1);
- gfs2_rgrp_free(&expected_rglist);
- gfs2_rgrp_free(&sdp->rglist);
- return -1;
- }
- /* ------------------------------------------------------------- */
- /* Now compare the rindex to what we think it should be. */
- /* See how far off our expected values are. If too much, abort. */
- /* The theory is: if we calculated the index to have 32 RGs and */
- /* we have a large number that are completely wrong, we should */
- /* abandon this method of recovery and try a better one. */
- /* ------------------------------------------------------------- */
- discrepancies = 0;
- for (rg = 0, act = sdp->rglist.next, exp = expected_rglist.next;
- act != &sdp->rglist && exp != &expected_rglist;
- act = act->next, exp = exp->next, rg++) {
- struct rgrp_list *expected, *actual;
-
- expected = osi_list_entry(exp, struct rgrp_list, list);
- actual = osi_list_entry(act, struct rgrp_list, list);
- if (!ri_equal(actual->ri, expected->ri, ri_addr) ||
- !ri_equal(actual->ri, expected->ri, ri_length) ||
- !ri_equal(actual->ri, expected->ri, ri_data0) ||
- !ri_equal(actual->ri, expected->ri, ri_data) ||
- !ri_equal(actual->ri, expected->ri, ri_bitbytes)) {
- discrepancies++;
- }
- }
- if (trust_lvl < distrust && discrepancies > (trust_lvl * 8)) {
- log_warn( _("Level %d didn't work. Too many descepencies.\n"),
- trust_lvl + 1);
- log_warn( _("%d out of %d RGs did not match what was expected.\n"),
- discrepancies, rg);
- gfs2_rgrp_free(&expected_rglist);
- gfs2_rgrp_free(&sdp->rglist);
- return -1;
- }
- /* ------------------------------------------------------------- */
- /* Now compare the rindex to what we think it should be. */
- /* Our rindex should be pretty predictable unless we've grown */
- /* so look for index problems first before looking at the rgs. */
- /* ------------------------------------------------------------- */
- for (rg = 0, act = sdp->rglist.next, exp = expected_rglist.next;
- act != &sdp->rglist && exp != &expected_rglist;
- act = act->next, exp = exp->next, rg++) {
- struct rgrp_list *expected, *actual;
-
- expected = osi_list_entry(exp, struct rgrp_list, list);
- actual = osi_list_entry(act, struct rgrp_list, list);
- ri_compare(rg, actual->ri, expected->ri, ri_addr, "llx");
- ri_compare(rg, actual->ri, expected->ri, ri_length, PRIx32);
- ri_compare(rg, actual->ri, expected->ri, ri_data0, "llx");
- ri_compare(rg, actual->ri, expected->ri, ri_data, PRIx32);
- ri_compare(rg, actual->ri, expected->ri, ri_bitbytes, PRIx32);
- /* If we modified the index, write it back to disk. */
- if (rindex_modified) {
- if (query( _("Fix the index? (y/n)"))) {
- gfs2_rindex_out(&expected->ri, (char *)&buf);
- gfs2_writei(sdp->md.riinode, (char *)&buf,
- rg * sizeof(struct gfs2_rindex),
- sizeof(struct gfs2_rindex));
- actual->ri.ri_addr = expected->ri.ri_addr;
- actual->ri.ri_length = expected->ri.ri_length;
- actual->ri.ri_data0 = expected->ri.ri_data0;
- actual->ri.ri_data = expected->ri.ri_data;
- actual->ri.ri_bitbytes =
- expected->ri.ri_bitbytes;
- /* If our rindex was hosed, ri_length is bad */
- /* Therefore, gfs2_compute_bitstructs might */
- /* have malloced the wrong length for bitmap */
- /* buffers. So we have to redo it. */
- if (actual->bits)
- free(actual->bits);
- }
- else
- log_err( _("RG index not fixed.\n"));
- gfs2_compute_bitstructs(sdp, actual);
- rindex_modified = FALSE;
- }
- }
- /* ------------------------------------------------------------- */
- /* Read the real RGs and check their integrity. */
- /* Now we can somewhat trust the rindex and the RG addresses, */
- /* so let's read them in, check them and optionally fix them. */
- /* ------------------------------------------------------------- */
- for (rg = 0, act = sdp->rglist.next; act != &sdp->rglist;
- act = act->next, rg++) {
- struct rgrp_list *rgd;
- uint64_t prev_err = 0, errblock;
- int i;
-
- /* Now we try repeatedly to read in the rg. For every block */
- /* we encounter that has errors, repair it and try again. */
- i = 0;
- do {
- rgd = osi_list_entry(act, struct rgrp_list, list);
- errblock = gfs2_rgrp_read(sdp, rgd);
- if (errblock) {
- if (errblock == prev_err)
- break;
- prev_err = errblock;
- rewrite_rg_block(sdp, rgd, errblock);
- } else {
- gfs2_rgrp_relse(rgd);
- break;
- }
- i++;
- } while (i < rgd->ri.ri_length);
- }
- *rg_count = rg;
- gfs2_rgrp_free(&expected_rglist);
- gfs2_rgrp_free(&sdp->rglist);
- return 0;
-}
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
deleted file mode 100644
index 6fe05ab..0000000
--- a/gfs2/fsck/util.c
+++ /dev/null
@@ -1,373 +0,0 @@
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <stdio.h>
-#include <libintl.h>
-#include <ctype.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "fs_bits.h"
-#include "util.h"
-
-const char *reftypes[3] = {"data", "metadata", "extended attribute"};
-
-void big_file_comfort(struct gfs2_inode *ip, uint64_t blks_checked)
-{
- static struct timeval tv;
- static uint32_t seconds = 0;
- static uint64_t percent, fsize, chksize;
- uint64_t one_percent = 0;
- int i, cs;
- const char *human_abbrev = " KMGTPE";
-
- one_percent = ip->i_di.di_blocks / 100;
- if (blks_checked - last_reported_fblock < one_percent)
- return;
-
- last_reported_block = blks_checked;
- gettimeofday(&tv, NULL);
- if (!seconds)
- seconds = tv.tv_sec;
- if (tv.tv_sec == seconds)
- return;
-
- fsize = ip->i_di.di_size;
- for (i = 0; i < 6 && fsize > 1024; i++)
- fsize /= 1024;
- chksize = blks_checked * ip->i_sbd->bsize;
- for (cs = 0; cs < 6 && chksize > 1024; cs++)
- chksize /= 1024;
- seconds = tv.tv_sec;
- percent = (blks_checked * 100) / ip->i_di.di_blocks;
- log_notice( _("\rChecking %lld%c of %lld%c of file at %lld (0x%llx)"
- "- %llu percent complete. \r"),
- (long long)chksize, human_abbrev[cs],
- (unsigned long long)fsize, human_abbrev[i],
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)percent);
- fflush(stdout);
-}
-
-/* Put out a warm, fuzzy message every second so the user */
-/* doesn't think we hung. (This may take a long time). */
-void warm_fuzzy_stuff(uint64_t block)
-{
- static uint64_t one_percent = 0;
- static struct timeval tv;
- static uint32_t seconds = 0;
-
- if (!one_percent)
- one_percent = last_fs_block / 100;
- if (block - last_reported_block >= one_percent) {
- last_reported_block = block;
- gettimeofday(&tv, NULL);
- if (!seconds)
- seconds = tv.tv_sec;
- if (tv.tv_sec - seconds) {
- static uint64_t percent;
-
- seconds = tv.tv_sec;
- if (last_fs_block) {
- percent = (block * 100) / last_fs_block;
- log_notice( _("\r%" PRIu64 " percent complete.\r"), percent);
- fflush(stdout);
- }
- }
- }
-}
-
-/* fsck_query: Same as gfs2_query except it adjusts errors_found and
- errors_corrected. */
-int fsck_query(const char *format, ...)
-{
- va_list args;
- const char *transform;
- char response;
- int ret = 0;
-
- errors_found++;
- fsck_abort = 0;
- if(opts.yes) {
- errors_corrected++;
- return 1;
- }
- if(opts.no)
- return 0;
-
- opts.query = TRUE;
- while (1) {
- va_start(args, format);
- transform = _(format);
- vprintf(transform, args);
- va_end(args);
-
- /* Make sure query is printed out */
- fflush(NULL);
- response = gfs2_getch();
-
- printf("\n");
- fflush(NULL);
- if (response == 0x3) { /* if interrupted, by ctrl-c */
- response = generic_interrupt("Question", "response",
- NULL,
- "Do you want to abort " \
- "or continue (a/c)?",
- "ac");
- if (response == 'a') {
- ret = 0;
- fsck_abort = 1;
- break;
- }
- printf("Continuing.\n");
- } else if(tolower(response) == 'y') {
- errors_corrected++;
- ret = 1;
- break;
- } else if (tolower(response) == 'n') {
- ret = 0;
- break;
- } else {
- printf("Bad response %d, please type 'y' or 'n'.\n",
- response);
- }
- }
-
- opts.query = FALSE;
- return ret;
-}
-
-/*
- * gfs2_dup_set - Flag a block as a duplicate
- * We keep the references in a red/black tree. We can't keep track of every
- * single inode in the file system, so the first time this function is called
- * will actually be for the second reference to the duplicated block.
- * This will return the number of references to the block.
- *
- * create - will be set if the call is supposed to create the reference. */
-static struct duptree *gfs2_dup_set(uint64_t dblock, int create)
-{
- struct osi_node **newn = &dup_blocks.osi_node, *parent = NULL;
- struct duptree *data;
-
- /* Figure out where to put new node */
- while (*newn) {
- struct duptree *cur = (struct duptree *)*newn;
-
- parent = *newn;
- if (dblock < cur->block)
- newn = &((*newn)->osi_left);
- else if (dblock > cur->block)
- newn = &((*newn)->osi_right);
- else
- return cur;
- }
-
- if (!create)
- return NULL;
- data = malloc(sizeof(struct duptree));
- dups_found++;
- memset(data, 0, sizeof(struct duptree));
- /* Add new node and rebalance tree. */
- data->block = dblock;
- data->refs = 1; /* reference 1 is actually the reference we need to
- discover in pass1b. */
- data->first_ref_found = 0;
- osi_list_init(&data->ref_inode_list);
- osi_list_init(&data->ref_invinode_list);
- osi_link_node(&data->node, parent, newn);
- osi_insert_color(&data->node, &dup_blocks);
-
- return data;
-}
-
-/*
- * add_duplicate_ref - Add a duplicate reference to the duplicates tree list
- * A new element of the tree will be created as needed
- * When the first reference is discovered in pass1, it realizes it's a
- * duplicate but it has already forgotten where the first reference was.
- * So we need to recreate the duplicate reference structure if it's not there.
- * Later, in pass1b, it has to go back through the file system
- * and figure out those original references in order to resolve them.
- */
-int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block,
- enum dup_ref_type reftype, int first, int inode_valid)
-{
- osi_list_t *ref;
- struct inode_with_dups *id, *found_id;
- struct duptree *dt;
-
- if (gfs2_check_range(ip->i_sbd, block) != 0)
- return 0;
- /* If this is not the first reference (i.e. all calls from pass1) we
- need to create the duplicate reference. If this is pass1b, we want
- to ignore references that aren't found. */
- dt = gfs2_dup_set(block, !first);
- if (!dt) /* If this isn't a duplicate */
- return 0;
-
- /* If we found the duplicate reference but we've already discovered
- the first reference (in pass1b) and the other references in pass1,
- we don't need to count it, so just return. */
- if (dt->first_ref_found)
- return 0;
-
- /* The first time this is called from pass1 is actually the second
- reference. When we go back in pass1b looking for the original
- reference, we don't want to increment the reference count because
- it's already accounted for. */
- if (first) {
- if (!dt->first_ref_found) {
- dt->first_ref_found = 1;
- dups_found_first++; /* We found another first ref. */
- }
- } else {
- dt->refs++;
- }
-
- /* Check for a previous reference to this duplicate on the "invalid
- inode" reference list. */
- found_id = NULL;
- osi_list_foreach(ref, &dt->ref_invinode_list) {
- id = osi_list_entry(ref, struct inode_with_dups, list);
-
- if (id->block_no == ip->i_di.di_num.no_addr) {
- found_id = id;
- break;
- }
- }
- if (found_id == NULL) {
- osi_list_foreach(ref, &dt->ref_inode_list) {
- id = osi_list_entry(ref, struct inode_with_dups, list);
-
- if (id->block_no == ip->i_di.di_num.no_addr) {
- found_id = id;
- break;
- }
- }
- }
- if (found_id == NULL) {
- /* Check for the inode on the invalid inode reference list. */
- uint8_t q;
-
- if(!(found_id = malloc(sizeof(*found_id)))) {
- log_crit( _("Unable to allocate "
- "inode_with_dups structure\n"));
- return -1;
- }
- if(!(memset(found_id, 0, sizeof(*found_id)))) {
- log_crit( _("Unable to zero inode_with_dups "
- "structure\n"));
- return -1;
- }
- found_id->block_no = ip->i_di.di_num.no_addr;
- q = block_type(ip->i_di.di_num.no_addr);
- /* If it's an invalid dinode, put it first on the invalid
- inode reference list otherwise put it on the normal list. */
- if (!inode_valid || q == gfs2_inode_invalid)
- osi_list_add_prev(&found_id->list,
- &dt->ref_invinode_list);
- else
- osi_list_add_prev(&found_id->list,
- &dt->ref_inode_list);
- }
- found_id->reftypecount[reftype]++;
- found_id->dup_count++;
- log_info( _("Found %d reference(s) to block %llu"
- " (0x%llx) as %s in inode #%llu (0x%llx)\n"),
- found_id->dup_count, (unsigned long long)block,
- (unsigned long long)block, reftypes[reftype],
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if (first)
- log_info( _("This is the original reference.\n"));
- else
- log_info( _("This brings the total to: %d\n"), dt->refs);
- return 0;
-}
-
-struct dir_info *dirtree_insert(uint64_t dblock)
-{
- struct osi_node **newn = &dirtree.osi_node, *parent = NULL;
- struct dir_info *data;
-
- /* Figure out where to put new node */
- while (*newn) {
- struct dir_info *cur = (struct dir_info *)*newn;
-
- parent = *newn;
- if (dblock < cur->dinode)
- newn = &((*newn)->osi_left);
- else if (dblock > cur->dinode)
- newn = &((*newn)->osi_right);
- else
- return cur;
- }
-
- data = malloc(sizeof(struct dir_info));
- if (!data) {
- log_crit( _("Unable to allocate dir_info structure\n"));
- return NULL;
- }
- if (!memset(data, 0, sizeof(struct dir_info))) {
- log_crit( _("Error while zeroing dir_info structure\n"));
- return NULL;
- }
- /* Add new node and rebalance tree. */
- data->dinode = dblock;
- osi_link_node(&data->node, parent, newn);
- osi_insert_color(&data->node, &dirtree);
-
- return data;
-}
-
-struct dir_info *dirtree_find(uint64_t block)
-{
- struct osi_node *node = dirtree.osi_node;
-
- while (node) {
- struct dir_info *data = (struct dir_info *)node;
-
- if (block < data->dinode)
- node = node->osi_left;
- else if (block > data->dinode)
- node = node->osi_right;
- else
- return data;
- }
- return NULL;
-}
-
-void dup_delete(struct duptree *b)
-{
- struct inode_with_dups *id;
- osi_list_t *tmp;
-
- while (!osi_list_empty(&b->ref_invinode_list)) {
- tmp = (&b->ref_invinode_list)->next;
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- if (id->name)
- free(id->name);
- osi_list_del(&id->list);
- free(id);
- }
- while (!osi_list_empty(&b->ref_inode_list)) {
- tmp = (&b->ref_inode_list)->next;
- id = osi_list_entry(tmp, struct inode_with_dups, list);
- if (id->name)
- free(id->name);
- osi_list_del(&id->list);
- free(id);
- }
- osi_erase(&b->node, &dup_blocks);
- free(b);
-}
-
-void dirtree_delete(struct dir_info *b)
-{
- osi_erase(&b->node, &dirtree);
- free(b);
-}
diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h
deleted file mode 100644
index d2c81db..0000000
--- a/gfs2/fsck/util.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __UTIL_H__
-#define __UTIL_H__
-
-#include "fsck.h"
-#include "libgfs2.h"
-
-#define fsck_lseek(fd, off) \
- ((lseek((fd), (off), SEEK_SET) == (off)) ? 0 : -1)
-
-#define INODE_VALID 1
-#define INODE_INVALID 0
-
-struct di_info *search_list(osi_list_t *list, uint64_t addr);
-void big_file_comfort(struct gfs2_inode *ip, uint64_t blks_checked);
-void warm_fuzzy_stuff(uint64_t block);
-int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block,
- enum dup_ref_type reftype, int first, int inode_valid);
-extern const char *reftypes[3];
-
-static inline uint8_t block_type(uint64_t bblock)
-{
- static unsigned char *byte;
- static uint64_t b;
- static uint8_t btype;
-
- byte = bl->map + BLOCKMAP_SIZE4(bblock);
- b = BLOCKMAP_BYTE_OFFSET4(bblock);
- btype = (*byte & (BLOCKMAP_MASK4 << b )) >> b;
- return btype;
-}
-
-#endif /* __UTIL_H__ */
diff --git a/gfs2/include/osi_list.h b/gfs2/include/osi_list.h
deleted file mode 100644
index 3b1483b..0000000
--- a/gfs2/include/osi_list.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef __OSI_LIST_DOT_H__
-#define __OSI_LIST_DOT_H__
-
-
-
-struct osi_list
-{
- struct osi_list *next, *prev;
-};
-typedef struct osi_list osi_list_t;
-
-
-
-#define osi_list_decl(var) osi_list_t var = { &var, &var }
-
-#define osi_list_empty(var) ((var)->next == (var))
-#define osi_list_entry(var, type, mem) ((type *)((unsigned long)(var) - (unsigned long)(&((type *)NULL)->mem)))
-
-
-
-#define osi_list_init(head) \
-do \
-{ \
- osi_list_t *osi_list_var = (head); \
- osi_list_var->next = osi_list_var->prev = osi_list_var; \
-} \
-while (0)
-
-#define osi_list_add(new, head) \
-do \
-{ \
- osi_list_t *osi_list_var_new = (new); \
- osi_list_t *osi_list_var_head = (head); \
- osi_list_var_new->next = osi_list_var_head->next; \
- osi_list_var_new->prev = osi_list_var_head; \
- osi_list_var_head->next->prev = osi_list_var_new; \
- osi_list_var_head->next = osi_list_var_new; \
-} \
-while (0)
-
-#define osi_list_add_next osi_list_add
-
-#define osi_list_add_prev(new, head) \
-do \
-{ \
- osi_list_t *osi_list_var_new = (new); \
- osi_list_t *osi_list_var_head = (head); \
- osi_list_var_new->prev = osi_list_var_head->prev; \
- osi_list_var_new->next = osi_list_var_head; \
- osi_list_var_head->prev->next = osi_list_var_new; \
- osi_list_var_head->prev = osi_list_var_new; \
-} \
-while (0)
-
-#define osi_list_del(var) \
-do \
-{ \
- osi_list_t *osi_list_var = (var); \
- osi_list_var->next->prev = osi_list_var->prev; \
- osi_list_var->prev->next = osi_list_var->next; \
-} \
-while (0)
-
-#define osi_list_del_init(var) \
-do \
-{ \
- osi_list_t *osi_list_var = (var); \
- osi_list_var->next->prev = osi_list_var->prev; \
- osi_list_var->prev->next = osi_list_var->next; \
- osi_list_var->next = osi_list_var->prev = osi_list_var; \
-} \
-while (0)
-
-#define osi_list_foreach(tmp, head) \
- for ((tmp) = (head)->next; (tmp) != (head); (tmp) = (tmp)->next)
-
-#define osi_list_foreach_safe(tmp, head, x) \
- for ((tmp) = (head)->next, (x) = (tmp)->next; \
- (tmp) != (head); \
- (tmp) = (x), (x) = (x)->next)
-
-
-
-#endif /* __OSI_LIST_DOT_H__ */
diff --git a/gfs2/include/osi_tree.h b/gfs2/include/osi_tree.h
deleted file mode 100644
index f0d0768..0000000
--- a/gfs2/include/osi_tree.h
+++ /dev/null
@@ -1,395 +0,0 @@
-#ifndef __OSI_RBTREE_DOT_H__
-#define __OSI_RBTREE_DOT_H__
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <assert.h>
-
-/* Adapted from the kernel's rbtree.c */
-struct osi_node {
- unsigned long osi_parent_color;
-#define OSI_RED 0
-#define OSI_BLACK 1
- struct osi_node *osi_left;
- struct osi_node *osi_right;
- struct osi_node *osi_parent;
-};
-
-#define osi_parent(r) ((struct osi_node *)((r)->osi_parent_color & ~3))
-#define osi_color(r) ((r)->osi_parent_color & 1)
-#define osi_is_red(r) (!osi_color(r))
-#define osi_is_black(r) osi_color(r)
-#define osi_set_red(r) do { (r)->osi_parent_color &= ~1; } while (0)
-#define osi_set_black(r) do { (r)->osi_parent_color |= 1; } while (0)
-
-struct osi_root
-{
- struct osi_node *osi_node;
-};
-
-static inline void osi_set_color(struct osi_node *rb, int color)
-{
- rb->osi_parent_color = (rb->osi_parent_color & ~1) | color;
-}
-
-static inline void osi_set_parent(struct osi_node *rb, struct osi_node *p)
-{
- rb->osi_parent_color = (rb->osi_parent_color & 3) | (unsigned long)p;
-}
-
-static inline void osi_link_node(struct osi_node *node,
- struct osi_node *parent,
- struct osi_node **osi_link)
-{
- node->osi_parent_color = (unsigned long )parent;
- node->osi_left = node->osi_right = NULL;
-
- *osi_link = node;
-}
-
-static inline void __osi_rotate_left(struct osi_node *node,
- struct osi_root *root)
-{
- struct osi_node *right = node->osi_right;
- struct osi_node *parent = osi_parent(node);
-
- if ((node->osi_right = right->osi_left))
- osi_set_parent(right->osi_left, node);
- right->osi_left = node;
-
- osi_set_parent(right, parent);
-
- if (parent) {
- if (node == parent->osi_left)
- parent->osi_left = right;
- else
- parent->osi_right = right;
- }
- else
- root->osi_node = right;
- osi_set_parent(node, right);
-}
-
-static inline void __osi_rotate_right(struct osi_node *node,
- struct osi_root *root)
-{
- struct osi_node *left = node->osi_left;
- struct osi_node *parent = osi_parent(node);
-
- if ((node->osi_left = left->osi_right))
- osi_set_parent(left->osi_right, node);
- left->osi_right = node;
-
- osi_set_parent(left, parent);
-
- if (parent) {
- if (node == parent->osi_right)
- parent->osi_right = left;
- else
- parent->osi_left = left;
- } else
- root->osi_node = left;
- osi_set_parent(node, left);
-}
-
-static inline void osi_insert_color(struct osi_node *node,
- struct osi_root *root)
-{
- struct osi_node *parent, *gparent;
-
- while ((parent = osi_parent(node)) && osi_is_red(parent)) {
- gparent = osi_parent(parent);
-
- if (parent == gparent->osi_left) {
- {
- register struct osi_node *uncle = gparent->osi_right;
- if (uncle && osi_is_red(uncle)) {
- osi_set_black(uncle);
- osi_set_black(parent);
- osi_set_red(gparent);
- node = gparent;
- continue;
- }
- }
-
- if (parent->osi_right == node) {
- register struct osi_node *tmp;
-
- __osi_rotate_left(parent, root);
- tmp = parent;
- parent = node;
- node = tmp;
- }
-
- osi_set_black(parent);
- osi_set_red(gparent);
- __osi_rotate_right(gparent, root);
- } else {
- {
- register struct osi_node *uncle = gparent->osi_left;
- if (uncle && osi_is_red(uncle)) {
- osi_set_black(uncle);
- osi_set_black(parent);
- osi_set_red(gparent);
- node = gparent;
- continue;
- }
- }
-
- if (parent->osi_left == node) {
- register struct osi_node *tmp;
- __osi_rotate_right(parent, root);
- tmp = parent;
- parent = node;
- node = tmp;
- }
-
- osi_set_black(parent);
- osi_set_red(gparent);
- __osi_rotate_left(gparent, root);
- }
- }
-
- osi_set_black(root->osi_node);
-}
-
-static inline void __osi_erase_color(struct osi_node *node,
- struct osi_node *parent,
- struct osi_root *root)
-{
- struct osi_node *other;
-
- while ((!node || osi_is_black(node)) && node != root->osi_node) {
- if (parent->osi_left == node) {
- other = parent->osi_right;
- if (osi_is_red(other)) {
- osi_set_black(other);
- osi_set_red(parent);
- __osi_rotate_left(parent, root);
- other = parent->osi_right;
- }
- if ((!other->osi_left || osi_is_black(other->osi_left)) &&
- (!other->osi_right || osi_is_black(other->osi_right)))
- {
- osi_set_red(other);
- node = parent;
- parent = osi_parent(node);
- } else {
- if (!other->osi_right || osi_is_black(other->osi_right))
- {
- struct osi_node *o_left;
- if ((o_left = other->osi_left))
- osi_set_black(o_left);
- osi_set_red(other);
- __osi_rotate_right(other, root);
- other = parent->osi_right;
- }
- osi_set_color(other, osi_color(parent));
- osi_set_black(parent);
- if (other->osi_right)
- osi_set_black(other->osi_right);
- __osi_rotate_left(parent, root);
- node = root->osi_node;
- break;
- }
- } else {
- other = parent->osi_left;
- if (osi_is_red(other)) {
- osi_set_black(other);
- osi_set_red(parent);
- __osi_rotate_right(parent, root);
- other = parent->osi_left;
- }
- if ((!other->osi_left || osi_is_black(other->osi_left)) &&
- (!other->osi_right || osi_is_black(other->osi_right)))
- {
- osi_set_red(other);
- node = parent;
- parent = osi_parent(node);
- } else {
- if (!other->osi_left || osi_is_black(other->osi_left))
- {
- register struct osi_node *o_right;
- if ((o_right = other->osi_right))
- osi_set_black(o_right);
- osi_set_red(other);
- __osi_rotate_left(other, root);
- other = parent->osi_left;
- }
- osi_set_color(other, osi_color(parent));
- osi_set_black(parent);
- if (other->osi_left)
- osi_set_black(other->osi_left);
- __osi_rotate_right(parent, root);
- node = root->osi_node;
- break;
- }
- }
- }
- if (node)
- osi_set_black(node);
-}
-
-static inline void osi_erase(struct osi_node *node, struct osi_root *root)
-{
- struct osi_node *child, *parent;
- int color;
-
- if (!node->osi_left)
- child = node->osi_right;
- else if (!node->osi_right)
- child = node->osi_left;
- else {
- struct osi_node *old = node, *left;
-
- node = node->osi_right;
- while ((left = node->osi_left) != NULL)
- node = left;
- child = node->osi_right;
- parent = osi_parent(node);
- color = osi_color(node);
-
- if (child)
- osi_set_parent(child, parent);
- if (parent == old) {
- parent->osi_right = child;
- parent = node;
- } else
- parent->osi_left = child;
-
- node->osi_parent_color = old->osi_parent_color;
- node->osi_right = old->osi_right;
- node->osi_left = old->osi_left;
-
- if (osi_parent(old)) {
- if (osi_parent(old)->osi_left == old)
- osi_parent(old)->osi_left = node;
- else
- osi_parent(old)->osi_right = node;
- } else
- root->osi_node = node;
-
- osi_set_parent(old->osi_left, node);
- if (old->osi_right)
- osi_set_parent(old->osi_right, node);
- goto color;
- }
-
- parent = osi_parent(node);
- color = osi_color(node);
-
- if (child)
- osi_set_parent(child, parent);
- if (parent)
- {
- if (parent->osi_left == node)
- parent->osi_left = child;
- else
- parent->osi_right = child;
- }
- else
- root->osi_node = child;
-
- color:
- if (color == OSI_BLACK)
- __osi_erase_color(child, parent, root);
-}
-
-/*
- * This function returns the first node (in sort order) of the tree.
- */
-static inline struct osi_node *osi_first(struct osi_root *root)
-{
- struct osi_node *n;
-
- n = root->osi_node;
- if (!n)
- return NULL;
- while (n->osi_left)
- n = n->osi_left;
- return n;
-}
-
-static inline struct osi_node *osi_last(struct osi_root *root)
-{
- struct osi_node *n;
-
- n = root->osi_node;
- if (!n)
- return NULL;
- while (n->osi_right)
- n = n->osi_right;
- return n;
-}
-
-static inline struct osi_node *osi_next(struct osi_node *node)
-{
- struct osi_node *parent;
-
- /* If we have a right-hand child, go down and then left as far
- as we can. */
- if (node->osi_right) {
- node = node->osi_right;
- while (node->osi_left)
- node=node->osi_left;
- return node;
- }
-
- /* No right-hand children. Everything down and left is
- smaller than us, so any 'next' node must be in the general
- direction of our parent. Go up the tree; any time the
- ancestor is a right-hand child of its parent, keep going
- up. First time it's a left-hand child of its parent, said
- parent is our 'next' node. */
- while ((parent = osi_parent(node)) && node == parent->osi_right)
- node = parent;
-
- return parent;
-}
-
-static inline struct osi_node *osi_prev(struct osi_node *node)
-{
- struct osi_node *parent;
-
- /* If we have a left-hand child, go down and then right as far
- as we can. */
- if (node->osi_left) {
- node = node->osi_left;
- while (node->osi_right)
- node=node->osi_right;
- return node;
- }
-
- /* No left-hand children. Go up till we find an ancestor which
- is a right-hand child of its parent */
- while ((parent = osi_parent(node)) && node == parent->osi_left)
- node = parent;
-
- return parent;
-}
-
-static inline void osi_replace_node(struct osi_node *victim,
- struct osi_node *new,
- struct osi_root *root)
-{
- struct osi_node *parent = osi_parent(victim);
-
- /* Set the surrounding nodes to point to the replacement */
- if (parent) {
- if (victim == parent->osi_left)
- parent->osi_left = new;
- else
- parent->osi_right = new;
- } else {
- root->osi_node = new;
- }
- if (victim->osi_left)
- osi_set_parent(victim->osi_left, new);
- if (victim->osi_right)
- osi_set_parent(victim->osi_right, new);
-
- /* Copy the pointers/colour from the victim to the replacement */
- *new = *victim;
-}
-
-#endif
diff --git a/gfs2/init.d/Makefile b/gfs2/init.d/Makefile
deleted file mode 100644
index 23a57d9..0000000
--- a/gfs2/init.d/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-TARGET= gfs2
-
-INITDT=$(TARGET)
-
-all: $(TARGET)
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-$(TARGET): $(S)/$(TARGET).in
- cat $(S)/$(TARGET).in | sed \
- -e 's#@SBINDIR@#${sbindir}#g' \
- -e 's#@INITDDIR@#${initddir}#g' \
- > $(TARGET)
-
-clean: generalclean
diff --git a/gfs2/init.d/gfs2.in b/gfs2/init.d/gfs2.in
deleted file mode 100644
index 0f0f009..0000000
--- a/gfs2/init.d/gfs2.in
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/bin/bash
-#
-# gfs2 mount/unmount helper
-#
-# chkconfig: - 26 74
-# description: mount/unmount gfs2 filesystems configured in /etc/fstab
-
-### BEGIN INIT INFO
-# Provides: gfs2
-# Required-Start: $network cman
-# Required-Stop: $network cman
-# Default-Start:
-# Default-Stop:
-# Short-Description: mount/unmount gfs2 filesystems configured in /etc/fstab
-# Description: mount/unmount gfs2 filesystems configured in /etc/fstab
-### END INIT INFO
-
-# set secure PATH
-PATH="/bin:/usr/bin:/sbin:/usr/sbin:@SBINDIR@"
-
-### generic wrapper functions
-
-success()
-{
- echo -ne "[ OK ]\r"
-}
-
-failure()
-{
- echo -ne "[FAILED]\r"
-}
-
-ok() {
- success
- echo
-}
-
-nok() {
- echo -e "$errmsg"
- failure
- echo
- exit 1
-}
-
-# rpm based distros
-if [ -d /etc/sysconfig ]; then
- [ -f @INITDDIR@/functions ] && . @INITDDIR@/functions
- [ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster
- [ -f /etc/sysconfig/gfs2 ] && . /etc/sysconfig/gfs2
- [ -z "$LOCK_FILE" ] && LOCK_FILE="/var/lock/subsys/gfs2"
-fi
-
-# deb based distros
-if [ -d /etc/default ]; then
- [ -f /etc/default/cluster ] && . /etc/default/cluster
- [ -f /etc/default/gfs2 ] && . /etc/default/gfs2
- [ -z "$LOCK_FILE" ] && LOCK_FILE="/var/lock/gfs2"
-fi
-
-# proc is required for both status and stop.
-# start could live without, but better be consistent with the behavior
-if [ ! -f /proc/mounts ]; then
- echo "GFS2: /proc is not available, unable to proceed"
- exit 1
-fi
-
-#
-# This script's behavior is modeled closely after the netfs script.
-#
-GFS2FSTAB=$(LC_ALL=C awk '!/^#/ && $3 == "gfs2" && $4 !~ /noauto/ { print $2 }' /etc/fstab)
-GFS2MTAB=$(LC_ALL=C awk '!/^#/ && $3 == "gfs2" && $2 != "/" { print $2 }' /proc/mounts)
-
-if [ -z "$GFS2FSTAB" ]; then
- echo "GFS2: no entries found in /etc/fstab"
- exit 6
-fi
-
-if [ "$EUID" != "0" ]; then
- echo "Only root can execute $0 script"
- exit 4
-fi
-
-is_mounted()
-{
- for i in $GFS2MTAB; do
- if [ "$1" = "$i" ]; then
- return 0
- fi
- done
- return 1
-}
-
-# See how we were called.
-case "$1" in
-start)
- mounted=0
- for fs in $GFS2FSTAB; do
- echo -n "Mounting GFS2 filesystem ($fs): "
- if is_mounted $fs; then
- echo -n "already mounted"
- ok
- mounted=$((mounted + 1))
- continue
- fi
- errmsg="$(mount $fs 2>&1)"
- if [ "$?" != 0 ]; then
- echo -e "$errmsg"
- failure
- echo
- continue
- fi
- ok
- mounted=$((mounted + 1))
- done
- [ $mounted -gt 0 ] && touch $LOCK_FILE
-;;
-stop)
- [ -z "$GFS2MTAB" ] && exit 0
- umount_failed=0
- for fs in $GFS2MTAB; do
- echo -n "Unmounting GFS2 filesystem ($fs): "
- errmsg="$(umount $fs 2>&1)"
- if [ "$?" != 0 ]; then
- echo -e "$errmsg"
- failure
- echo
- umount_failed=1
- continue
- fi
- ok
- done
- modprobe -r gfs2 > /dev/null 2>&1 || true
- [ $umount_failed = 0 ] && rm -f $LOCK_FILE
- ;;
-
-status)
- if [ -z "$GFS2MTAB" ] && [ -f $LOCK_FILE ]; then
- echo "GFS2: Found stale lock file $LOCK_FILE"
- exit 2
- fi
-
- if [ -n "$GFS2FSTAB" ] && [ -z "$GFS2MTAB" ]; then
- echo "GFS2: service is not running"
- exit 3
- fi
-
- echo "Configured GFS2 mountpoints: "
- for fs in $GFS2FSTAB; do
- echo $fs;
- done
-
- echo "Active GFS2 mountpoints: "
- for fs in $GFS2MTAB; do
- echo $fs;
- done
-;;
-condrestart|try-restart)
- $0 status >/dev/null 2>&1 || exit 0
- $0 restart
- exit $?
-;;
-restart|reload|force-reload)
- $0 stop && $0 start
- exit $?
-;;
-*)
- echo "Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status}"
- exit 2
-;;
-esac
-
-exit 0
diff --git a/gfs2/libgfs2/Makefile b/gfs2/libgfs2/Makefile
deleted file mode 100644
index 9411130..0000000
--- a/gfs2/libgfs2/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-TARGET= libgfs2
-
-MAKESTATICLIB = 1
-
-OBJS= block_list.o \
- buf.o \
- device_geometry.o \
- fs_bits.o \
- fs_geometry.o \
- fs_ops.o \
- gfs1.o \
- gfs2_log.o \
- gfs2_disk_hash.o \
- misc.o \
- ondisk.o \
- recovery.o \
- size.o \
- structures.o \
- super.o \
- rgrp.o
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/libs.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_GNU_SOURCE
-CFLAGS += -I${KERNEL_SRC}/fs/gfs2/ -I${KERNEL_SRC}/include/
-CFLAGS += -I$(S)/../include
-CFLAGS += -I${incdir}
-CFLAGS += -fPIC
diff --git a/gfs2/libgfs2/block_list.c b/gfs2/libgfs2/block_list.c
deleted file mode 100644
index faedc54..0000000
--- a/gfs2/libgfs2/block_list.c
+++ /dev/null
@@ -1,137 +0,0 @@
-#include <inttypes.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "libgfs2.h"
-
-static int gfs2_blockmap_create(struct gfs2_bmap *bmap, uint64_t size)
-{
- bmap->size = size;
-
- /* Have to add 1 to BLOCKMAP_SIZE since it's 0-based and mallocs
- * must be 1-based */
- bmap->mapsize = BLOCKMAP_SIZE4(size);
-
- if(!(bmap->map = malloc(sizeof(char) * bmap->mapsize)))
- return -ENOMEM;
- if(!memset(bmap->map, 0, sizeof(char) * bmap->mapsize)) {
- free(bmap->map);
- bmap->map = NULL;
- return -ENOMEM;
- }
- return 0;
-}
-
-static void gfs2_blockmap_destroy(struct gfs2_bmap *bmap)
-{
- if(bmap->map)
- free(bmap->map);
- bmap->size = 0;
- bmap->mapsize = 0;
-}
-
-struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size,
- uint64_t *addl_mem_needed)
-{
- struct gfs2_bmap *il;
-
- *addl_mem_needed = 0L;
- il = malloc(sizeof(*il));
- if (!il || !memset(il, 0, sizeof(*il)))
- return NULL;
-
- if(gfs2_blockmap_create(il, size)) {
- *addl_mem_needed = il->mapsize;
- free(il);
- il = NULL;
- }
- osi_list_init(&sdp->eattr_blocks.list);
- return il;
-}
-
-void gfs2_special_free(struct special_blocks *blist)
-{
- struct special_blocks *f;
-
- while(!osi_list_empty(&blist->list)) {
- f = osi_list_entry(blist->list.next, struct special_blocks,
- list);
- osi_list_del(&f->list);
- free(f);
- }
-}
-
-struct special_blocks *blockfind(struct special_blocks *blist, uint64_t num)
-{
- osi_list_t *head = &blist->list;
- osi_list_t *tmp;
- struct special_blocks *b;
-
- for (tmp = head->next; tmp != head; tmp = tmp->next) {
- b = osi_list_entry(tmp, struct special_blocks, list);
- if (b->block == num)
- return b;
- }
- return NULL;
-}
-
-void gfs2_special_add(struct special_blocks *blocklist, uint64_t block)
-{
- struct special_blocks *b;
-
- b = malloc(sizeof(struct special_blocks));
- if (b) {
- memset(b, 0, sizeof(*b));
- b->block = block;
- osi_list_add(&b->list, &blocklist->list);
- }
-}
-
-void gfs2_special_set(struct special_blocks *blocklist, uint64_t block)
-{
- if (blockfind(blocklist, block))
- return;
- gfs2_special_add(blocklist, block);
-}
-
-void gfs2_special_clear(struct special_blocks *blocklist, uint64_t block)
-{
- struct special_blocks *b;
-
- b = blockfind(blocklist, block);
- if (b) {
- osi_list_del(&b->list);
- free(b);
- }
-}
-
-int gfs2_blockmap_set(struct gfs2_bmap *bmap, uint64_t bblock,
- enum gfs2_mark_block mark)
-{
- static unsigned char *byte;
- static uint64_t b;
-
- if(bblock > bmap->size)
- return -1;
-
- byte = bmap->map + BLOCKMAP_SIZE4(bblock);
- b = BLOCKMAP_BYTE_OFFSET4(bblock);
- *byte &= ~(BLOCKMAP_MASK4 << b);
- *byte |= (mark & BLOCKMAP_MASK4) << b;
- return 0;
-}
-
-void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il)
-{
- if(il) {
- gfs2_blockmap_destroy(il);
- free(il);
- il = NULL;
- }
- gfs2_special_free(&sdp->eattr_blocks);
- return il;
-}
diff --git a/gfs2/libgfs2/buf.c b/gfs2/libgfs2/buf.c
deleted file mode 100644
index 5a0f718..0000000
--- a/gfs2/libgfs2/buf.c
+++ /dev/null
@@ -1,89 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <linux/types.h>
-
-#include "libgfs2.h"
-
-struct gfs2_buffer_head *__bget_generic(struct gfs2_sbd *sdp, uint64_t num,
- int read_disk,
- int line, const char *caller)
-{
- struct gfs2_buffer_head *bh;
-
- bh = calloc(1, sizeof(struct gfs2_buffer_head) + sdp->bsize);
- if (bh == NULL)
- return NULL;
-
- bh->b_blocknr = num;
- bh->sdp = sdp;
- bh->b_data = (char *)bh + sizeof(struct gfs2_buffer_head);
- if (read_disk) {
- if (lseek(sdp->device_fd, num * sdp->bsize, SEEK_SET) !=
- num * sdp->bsize) {
- fprintf(stderr, "bad seek: %s from %s:%d: block "
- "%llu (0x%llx)\n", strerror(errno),
- caller, line, (unsigned long long)num,
- (unsigned long long)num);
- exit(-1);
- }
- if (read(sdp->device_fd, bh->b_data, sdp->bsize) < 0) {
- fprintf(stderr, "bad read: %s from %s:%d: block "
- "%llu (0x%llx)\n", strerror(errno),
- caller, line, (unsigned long long)num,
- (unsigned long long)num);
- exit(-1);
- }
- }
-
- return bh;
-}
-
-struct gfs2_buffer_head *__bget(struct gfs2_sbd *sdp, uint64_t num, int line,
- const char *caller)
-{
- return __bget_generic(sdp, num, FALSE, line, caller);
-}
-
-struct gfs2_buffer_head *__bread(struct gfs2_sbd *sdp, uint64_t num, int line,
- const char *caller)
-{
- return __bget_generic(sdp, num, TRUE, line, caller);
-}
-
-int bwrite(struct gfs2_buffer_head *bh)
-{
- struct gfs2_sbd *sdp = bh->sdp;
-
- if (lseek(sdp->device_fd, bh->b_blocknr * sdp->bsize, SEEK_SET) !=
- bh->b_blocknr * sdp->bsize) {
- return -1;
- }
- if (write(sdp->device_fd, bh->b_data, sdp->bsize) != sdp->bsize)
- return -1;
- sdp->writes++;
- bh->b_modified = 0;
- return 0;
-}
-
-int brelse(struct gfs2_buffer_head *bh)
-{
- int error = 0;
-
- if (bh->b_blocknr == -1)
- printf("Double free!\n");
- if (bh->b_modified)
- error = bwrite(bh);
- bh->b_blocknr = -1;
- if (bh->b_altlist.next && !osi_list_empty(&bh->b_altlist))
- osi_list_del(&bh->b_altlist);
- free(bh);
- return error;
-}
diff --git a/gfs2/libgfs2/device_geometry.c b/gfs2/libgfs2/device_geometry.c
deleted file mode 100644
index a05ae94..0000000
--- a/gfs2/libgfs2/device_geometry.c
+++ /dev/null
@@ -1,126 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <linux/types.h>
-
-#include "libgfs2.h"
-
-#define BLKSSZGET _IO(0x12,104) /* logical_block_size */
-#define BLKIOMIN _IO(0x12,120) /* minimum_io_size */
-#define BLKIOOPT _IO(0x12,121) /* optimal_io_size */
-#define BLKALIGNOFF _IO(0x12,122) /* alignment_offset */
-#define BLKPBSZGET _IO(0x12,123) /* physical_block_size */
-
-/**
- * device_topology - Get the device topology
- * Values not fetched are returned as zero.
- */
-int device_topology(struct gfs2_sbd *sdp)
-{
- if (ioctl(sdp->device_fd, BLKSSZGET, &sdp->logical_block_size) < 0)
- sdp->logical_block_size = 0;
- if (ioctl(sdp->device_fd, BLKIOMIN, &sdp->minimum_io_size) < 0)
- sdp->minimum_io_size = 0;
- if (ioctl(sdp->device_fd, BLKALIGNOFF, &sdp->optimal_io_size) < 0)
- sdp->optimal_io_size = 0;
- if (ioctl(sdp->device_fd, BLKIOOPT, &sdp->alignment_offset) < 0)
- sdp->alignment_offset = 0;
- if (ioctl(sdp->device_fd, BLKPBSZGET, &sdp->physical_block_size) < 0)
- sdp->physical_block_size = 0;
- if (!sdp->debug)
- return 0;
-
- printf("\nDevice Topology:\n");
- printf(" Logical block size: %u\n", sdp->logical_block_size);
- printf(" Physical block size: %u\n", sdp->physical_block_size);
- printf(" Minimum I/O size: %u\n", sdp->minimum_io_size);
- printf(" Optimal I/O size: %u (0 means unknown)\n",
- sdp->optimal_io_size);
- printf(" Alignment offset: %u\n", sdp->alignment_offset);
- return 0;
-}
-
-/**
- * device_geometry - Get the size of a device
- * @w: the command line
- *
- */
-
-int device_geometry(struct gfs2_sbd *sdp)
-{
- struct device *device = &sdp->device;
- uint64_t bytes;
- int error;
-
- error = device_size(sdp->device_fd, &bytes);
- if (error)
- return error;
-
- if (sdp->debug)
- printf("\nPartition size = %"PRIu64"\n",
- bytes >> GFS2_BASIC_BLOCK_SHIFT);
-
- device->start = 0;
- device->length = bytes >> GFS2_BASIC_BLOCK_SHIFT;
- return 0;
-}
-
-/**
- * fix_device_geometry - round off address and lengths and convert to FS blocks
- * @w: the command line
- *
- */
-
-int fix_device_geometry(struct gfs2_sbd *sdp)
-{
- struct device *device = &sdp->device;
- unsigned int bbsize = sdp->bsize >> GFS2_BASIC_BLOCK_SHIFT;
- uint64_t start, length;
- unsigned int remainder;
-
- if (sdp->debug) {
- printf("\nDevice Geometry: (in basic blocks)\n");
- printf(" start = %"PRIu64", length = %"PRIu64", rgf_flags = 0x%.8X\n",
- device->start,
- device->length,
- device->rgf_flags);
- }
-
- start = device->start;
- length = device->length;
-
- if (length < 1 << (20 - GFS2_BASIC_BLOCK_SHIFT)) {
- errno = ENOSPC;
- return -1;
- }
-
- remainder = start % bbsize;
- if (remainder) {
- length -= bbsize - remainder;
- start += bbsize - remainder;
- }
-
- start /= bbsize;
- length /= bbsize;
-
- device->start = start;
- device->length = length;
- sdp->device_size = start + length;
-
- if (sdp->debug) {
- printf("\nDevice Geometry: (in FS blocks)\n");
- printf(" start = %"PRIu64", length = %"
- PRIu64", rgf_flags = 0x%.8X\n",
- device->start, device->length, device->rgf_flags);
- printf("\nDevice Size: %"PRIu64"\n", sdp->device_size);
- }
- return 0;
-}
diff --git a/gfs2/libgfs2/fs_bits.c b/gfs2/libgfs2/fs_bits.c
deleted file mode 100644
index c2934a6..0000000
--- a/gfs2/libgfs2/fs_bits.c
+++ /dev/null
@@ -1,240 +0,0 @@
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "libgfs2.h"
-
-#if BITS_PER_LONG == 32
-#define LBITMASK (0x55555555UL)
-#define LBITSKIP55 (0x55555555UL)
-#define LBITSKIP00 (0x00000000UL)
-#else
-#define LBITMASK (0x5555555555555555UL)
-#define LBITSKIP55 (0x5555555555555555UL)
-#define LBITSKIP00 (0x0000000000000000UL)
-#endif
-
-#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1))
-
-/**
- * gfs2_bit_search
- * @ptr: Pointer to bitmap data
- * @mask: Mask to use (normally 0x55555.... but adjusted for search start)
- * @state: The state we are searching for
- *
- * We xor the bitmap data with a patter which is the bitwise opposite
- * of what we are looking for, this gives rise to a pattern of ones
- * wherever there is a match. Since we have two bits per entry, we
- * take this pattern, shift it down by one place and then and it with
- * the original. All the even bit positions (0,2,4, etc) then represent
- * successful matches, so we mask with 0x55555..... to remove the unwanted
- * odd bit positions.
- *
- * This allows searching of a whole u64 at once (32 blocks) with a
- * single test (on 64 bit arches).
- */
-
-static inline uint64_t gfs2_bit_search(const unsigned long long *ptr,
- unsigned long long mask,
- uint8_t state)
-{
- unsigned long long tmp;
- static const unsigned long long search[] = {
- [0] = 0xffffffffffffffffULL,
- [1] = 0xaaaaaaaaaaaaaaaaULL,
- [2] = 0x5555555555555555ULL,
- [3] = 0x0000000000000000ULL,
- };
- tmp = le64_to_cpu(*ptr) ^ search[state];
- tmp &= (tmp >> 1);
- tmp &= mask;
- return tmp;
-}
-
-/**
- * gfs2_bitfit - Find a free block in the bitmaps
- * @buffer: the buffer that holds the bitmaps
- * @buflen: the length (in bytes) of the buffer
- * @goal: the block to try to allocate
- * @old_state: the state of the block we're looking for
- *
- * Return: the block number that was allocated
- */
-unsigned long gfs2_bitfit(const unsigned char *buf, const unsigned int len,
- unsigned long goal, unsigned char state)
-{
- unsigned long spoint = (goal << 1) & ((8 * sizeof(unsigned long long)) - 1);
- const unsigned long long *ptr = ((unsigned long long *)buf) + (goal >> 5);
- const unsigned long long *end = (unsigned long long *)
- (buf + ALIGN(len, sizeof(unsigned long long)));
- unsigned long long tmp;
- unsigned long long mask = 0x5555555555555555ULL;
- unsigned long bit;
-
- if (state > 3)
- return 0;
-
- /* Mask off bits we don't care about at the start of the search */
- mask <<= spoint;
- tmp = gfs2_bit_search(ptr, mask, state);
- ptr++;
- while(tmp == 0 && ptr < end) {
- tmp = gfs2_bit_search(ptr, 0x5555555555555555ULL, state);
- ptr++;
- }
- /* Mask off any bits which are more than len bytes from the start */
- if (ptr == end && (len & (sizeof(unsigned long long) - 1)))
- tmp &= (((unsigned long long)~0) >>
- (64 - 8 * (len & (sizeof(unsigned long long) - 1))));
- /* Didn't find anything, so return */
- if (tmp == 0)
- return BFITNOENT;
- ptr--;
- bit = ffsll(tmp);
- bit /= 2; /* two bits per entry in the bitmap */
- return (((const unsigned char *)ptr - buf) * GFS2_NBBY) + bit;
-}
-
-/**
- * fs_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(unsigned char *buffer, unsigned int buflen,
- unsigned char state)
-{
- unsigned char *byte, *end;
- unsigned int bit;
- uint32_t count = 0;
-
- byte = buffer;
- bit = 0;
- end = buffer + buflen;
-
- while (byte < end){
- if (((*byte >> bit) & GFS2_BIT_MASK) == state)
- count++;
-
- bit += GFS2_BIT_SIZE;
- if (bit >= 8){
- bit = 0;
- byte++;
- }
- }
- return count;
-}
-
-/*
- * check_range - check if blkno is within FS limits
- * @sdp: super block
- * @blkno: block number
- *
- * Returns: 0 if ok, -1 if out of bounds
- */
-int gfs2_check_range(struct gfs2_sbd *sdp, uint64_t blkno)
-{
- if((blkno > sdp->fssize) || (blkno <= sdp->sb_addr))
- return -1;
- return 0;
-}
-
-/*
- * fs_set_bitmap
- * @sdp: super block
- * @blkno: block number relative to file system
- * @state: one of three possible states
- *
- * This function sets the value of a bit of the
- * file system bitmap.
- *
- * Returns: 0 on success, -1 on error
- */
-int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state)
-{
- int buf;
- uint32_t rgrp_block;
- struct gfs2_bitmap *bits = NULL;
- struct rgrp_list *rgd;
- unsigned char *byte, cur_state;
- unsigned int bit;
-
- /* FIXME: should GFS2_BLKST_INVALID be allowed */
- if ((state < GFS2_BLKST_FREE) || (state > GFS2_BLKST_DINODE))
- return -1;
-
- rgd = gfs2_blk2rgrpd(sdp, blkno);
-
- if(!rgd)
- return -1;
-
- rgrp_block = (uint32_t)(blkno - rgd->ri.ri_data0);
- for(buf= 0; buf < rgd->ri.ri_length; buf++){
- bits = &(rgd->bits[buf]);
- if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS2_NBBY))
- break;
- }
-
- byte = (unsigned char *)(rgd->bh[buf]->b_data + bits->bi_offset) +
- (rgrp_block/GFS2_NBBY - bits->bi_start);
- bit = (rgrp_block % GFS2_NBBY) * GFS2_BIT_SIZE;
-
- cur_state = (*byte >> bit) & GFS2_BIT_MASK;
- *byte ^= cur_state << bit;
- *byte |= state << bit;
-
- bmodified(rgd->bh[buf]);
- return 0;
-}
-
-/*
- * gfs2_get_bitmap - get value of FS bitmap
- * @sdp: super block
- * @blkno: block number relative to file system
- *
- * This function gets the value of a bit of the
- * file system bitmap.
- * Possible state values for a block in the bitmap are:
- * GFS_BLKST_FREE (0)
- * GFS_BLKST_USED (1)
- * GFS_BLKST_INVALID (2)
- * GFS_BLKST_DINODE (3)
- *
- * Returns: state on success, -1 on error
- */
-int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno,
- struct rgrp_list *rgd)
-{
- int i, val;
- uint32_t rgrp_block;
- struct gfs2_bitmap *bits = NULL;
- unsigned int bit;
- unsigned char *byte;
-
- if (rgd == NULL) {
- rgd = gfs2_blk2rgrpd(sdp, blkno);
- if(rgd == NULL)
- return -1;
- }
-
- rgrp_block = (uint32_t)(blkno - rgd->ri.ri_data0);
-
- for (i = 0; i < rgd->ri.ri_length; i++) {
- bits = &(rgd->bits[i]);
- if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS2_NBBY))
- break;
- }
-
- if (i >= rgd->ri.ri_length)
- return -1;
- byte = (unsigned char *)(rgd->bh[i]->b_data + bits->bi_offset) +
- (rgrp_block/GFS2_NBBY - bits->bi_start);
- bit = (rgrp_block % GFS2_NBBY) * GFS2_BIT_SIZE;
-
- val = ((*byte >> bit) & GFS2_BIT_MASK);
-
- return val;
-}
diff --git a/gfs2/libgfs2/fs_geometry.c b/gfs2/libgfs2/fs_geometry.c
deleted file mode 100644
index a06e8a2..0000000
--- a/gfs2/libgfs2/fs_geometry.c
+++ /dev/null
@@ -1,233 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <linux/types.h>
-#include "libgfs2.h"
-
-#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
-
-/**
- * how_many_rgrps - figure out how many RG to put in a subdevice
- * @w: the command line
- * @dev: the device
- *
- * Returns: the number of RGs
- */
-
-static uint64_t how_many_rgrps(struct gfs2_sbd *sdp, struct device *dev, int rgsize_specified)
-{
- uint64_t nrgrp;
-
- while (TRUE) {
- nrgrp = DIV_RU(dev->length, (sdp->rgsize << 20) / sdp->bsize);
-
- if (rgsize_specified || /* If user specified an rg size or */
- nrgrp <= GFS2_EXCESSIVE_RGS || /* not an excessive # of rgs or */
- sdp->rgsize >= 2048) /* we've reached the max rg size */
- break;
-
- sdp->rgsize += GFS2_DEFAULT_RGSIZE; /* Try again w/bigger rgs */
- }
-
- if (sdp->debug)
- printf(" rg sz = %"PRIu32"\n nrgrp = %"PRIu64"\n", sdp->rgsize,
- nrgrp);
-
- return nrgrp;
-}
-
-/**
- * compute_rgrp_layout - figure out where the RG in a FS are
- * @w: the command line
- *
- * Returns: a list of rgrp_list_t structures
- */
-
-void compute_rgrp_layout(struct gfs2_sbd *sdp, int rgsize_specified)
-{
- struct device *dev;
- struct rgrp_list *rl, *rlast = NULL, *rlast2 = NULL;
- osi_list_t *tmp, *head = &sdp->rglist;
- unsigned int rgrp = 0, nrgrp;
- uint64_t rglength;
-
- sdp->new_rgrps = 0;
- dev = &sdp->device;
-
- /* Reserve space for the superblock */
- dev->start += sdp->sb_addr + 1;
-
- /* If this is a new file system, compute the length and number */
- /* of rgs based on the size of the device. */
- /* If we have existing RGs (i.e. gfs2_grow) find the last one. */
- if (osi_list_empty(&sdp->rglist)) {
- dev->length -= sdp->sb_addr + 1;
- nrgrp = how_many_rgrps(sdp, dev, rgsize_specified);
- rglength = dev->length / nrgrp;
- sdp->new_rgrps = nrgrp;
- } else {
- uint64_t old_length, new_chunk;
-
- log_info("Existing resource groups:\n");
- for (rgrp = 0, tmp = head->next; tmp != head;
- tmp = tmp->next, rgrp++) {
- rl = osi_list_entry(tmp, struct rgrp_list, list);
- log_info("%d: start: %" PRIu64 " (0x%"
- PRIx64 "), length = %"PRIu64" (0x%"
- PRIx64 ")\n", rgrp + 1, rl->start, rl->start,
- rl->length, rl->length);
- rlast2 = rlast;
- rlast = rl;
- }
- rlast->start = rlast->ri.ri_addr;
- rglength = rlast->ri.ri_addr - rlast2->ri.ri_addr;
- rlast->length = rglength;
- old_length = rlast->ri.ri_addr + rglength;
- new_chunk = dev->length - old_length;
- sdp->new_rgrps = new_chunk / rglength;
- nrgrp = rgrp + sdp->new_rgrps;
- }
-
- log_info("\nNew resource groups:\n");
- for (; rgrp < nrgrp; rgrp++) {
- rl = calloc(1, sizeof(struct rgrp_list));
- if (rl == NULL) {
- fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
- exit(-1);
- }
-
- if (rgrp) {
- rl->start = rlast->start + rlast->length;
- rl->length = rglength;
- } else {
- rl->start = dev->start;
- rl->length = dev->length -
- (nrgrp - 1) * (dev->length / nrgrp);
- }
-
- log_info("%d: start: %" PRIu64 " (0x%"
- PRIx64 "), length = %"PRIu64" (0x%"
- PRIx64 ")\n", rgrp + 1, rl->start, rl->start,
- rl->length, rl->length);
- osi_list_add_prev(&rl->list, head);
- rlast = rl;
- }
-
- sdp->rgrps = nrgrp;
-
- if (sdp->debug) {
- log_info("\n");
-
- for (tmp = head->next; tmp != head; tmp = tmp->next) {
- rl = osi_list_entry(tmp, struct rgrp_list, list);
- log_info("rg_o = %llu, rg_l = %llu\n",
- (unsigned long long)rl->start,
- (unsigned long long)rl->length);
- }
- }
-}
-
-/**
- * rgblocks2bitblocks -
- * @bsize:
- * @rgblocks:
- * @bitblocks:
- *
- * Given a number of blocks in a RG, figure out the number of blocks
- * needed for bitmaps.
- *
- */
-
-void rgblocks2bitblocks(unsigned int bsize, uint32_t *rgblocks, uint32_t *bitblocks)
-{
- unsigned int bitbytes_provided, last = 0;
- unsigned int bitbytes_needed;
-
- *bitblocks = 1;
- bitbytes_provided = bsize - sizeof(struct gfs2_rgrp);
-
- for (;;) {
- bitbytes_needed = (*rgblocks - *bitblocks) / GFS2_NBBY;
-
- if (bitbytes_provided >= bitbytes_needed) {
- if (last >= bitbytes_needed)
- (*bitblocks)--;
- break;
- }
-
- last = bitbytes_provided;
- (*bitblocks)++;
- bitbytes_provided += bsize - sizeof(struct gfs2_meta_header);
- }
-
- *rgblocks = bitbytes_needed * GFS2_NBBY;
-}
-
-/**
- * build_rgrps - write a bunch of resource groups to disk.
- * If fd > 0, write the data to the given file handle.
- * Otherwise, use gfs2 buffering in buf.c.
- */
-void build_rgrps(struct gfs2_sbd *sdp, int do_write)
-{
- osi_list_t *tmp, *head;
- struct rgrp_list *rl;
- uint32_t rgblocks, bitblocks;
- struct gfs2_rindex *ri;
- struct gfs2_meta_header mh;
- unsigned int x;
-
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_RB;
- mh.mh_format = GFS2_FORMAT_RB;
-
- for (head = &sdp->rglist, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- rl = osi_list_entry(tmp, struct rgrp_list, list);
- ri = &rl->ri;
-
- rgblocks = rl->length;
- rgblocks2bitblocks(sdp->bsize, &rgblocks, &bitblocks);
-
- ri->ri_addr = rl->start;
- ri->ri_length = bitblocks;
- ri->ri_data0 = rl->start + bitblocks;
- ri->ri_data = rgblocks;
- ri->ri_bitbytes = rgblocks / GFS2_NBBY;
-
- memset(&rl->rg, 0, sizeof(rl->rg));
- rl->rg.rg_header.mh_magic = GFS2_MAGIC;
- rl->rg.rg_header.mh_type = GFS2_METATYPE_RG;
- rl->rg.rg_header.mh_format = GFS2_FORMAT_RG;
- rl->rg.rg_free = rgblocks;
-
- gfs2_compute_bitstructs(sdp, rl);
-
- if (do_write) {
- for (x = 0; x < bitblocks; x++) {
- rl->bh[x] = bget(sdp, rl->start + x);
- if (x)
- gfs2_meta_header_out(&mh, rl->bh[x]);
- else
- gfs2_rgrp_out(&rl->rg, rl->bh[x]);
- }
- }
-
- if (sdp->debug) {
- printf("\n");
- gfs2_rindex_print(ri);
- }
-
- sdp->blks_total += rgblocks;
- sdp->fssize = ri->ri_data0 + ri->ri_data;
- }
-}
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
deleted file mode 100644
index 4019894..0000000
--- a/gfs2/libgfs2/fs_ops.c
+++ /dev/null
@@ -1,1743 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <linux/types.h>
-#include "libgfs2.h"
-
-static __inline__ uint64_t *metapointer(struct gfs2_buffer_head *bh,
- unsigned int height,
- struct metapath *mp)
-{
- unsigned int head_size = (height > 0) ?
- sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
-
- return ((uint64_t *)(bh->b_data + head_size)) + mp->mp_list[height];
-}
-
-/* Detect directory is a stuffed inode */
-static int inode_is_stuffed(struct gfs2_inode *ip)
-{
- return !ip->i_di.di_height;
-}
-
-struct gfs2_inode *inode_get(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh)
-{
- struct gfs2_inode *ip;
-
- ip = calloc(1, sizeof(struct gfs2_inode));
- if (ip == NULL) {
- fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
- exit(-1);
- }
- gfs2_dinode_in(&ip->i_di, bh);
- ip->i_bh = bh;
- ip->i_sbd = sdp;
- ip->bh_owned = 0; /* caller did the bread so we don't own the bh */
- return ip;
-}
-
-struct gfs2_inode *inode_read(struct gfs2_sbd *sdp, uint64_t di_addr)
-{
- struct gfs2_inode *ip;
-
- ip = calloc(1, sizeof(struct gfs2_inode));
- if (ip == NULL) {
- fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
- exit(-1);
- }
- ip->i_bh = bread(sdp, di_addr);
- gfs2_dinode_in(&ip->i_di, ip->i_bh);
- ip->i_sbd = sdp;
- ip->bh_owned = 1; /* We did the bread so we own the bh */
- return ip;
-}
-
-struct gfs2_inode *is_system_inode(struct gfs2_sbd *sdp, uint64_t block)
-{
- int j;
-
- if (sdp->md.inum && block == sdp->md.inum->i_di.di_num.no_addr)
- return sdp->md.inum;
- if (sdp->md.statfs && block == sdp->md.statfs->i_di.di_num.no_addr)
- return sdp->md.statfs;
- if (sdp->md.jiinode && block == sdp->md.jiinode->i_di.di_num.no_addr)
- return sdp->md.jiinode;
- if (sdp->md.riinode && block == sdp->md.riinode->i_di.di_num.no_addr)
- return sdp->md.riinode;
- if (sdp->md.qinode && block == sdp->md.qinode->i_di.di_num.no_addr)
- return sdp->md.qinode;
- if (sdp->md.pinode && block == sdp->md.pinode->i_di.di_num.no_addr)
- return sdp->md.pinode;
- if (sdp->md.rooti && block == sdp->md.rooti->i_di.di_num.no_addr)
- return sdp->md.rooti;
- if (sdp->master_dir && block == sdp->master_dir->i_di.di_num.no_addr)
- return sdp->master_dir;
- for (j = 0; j < sdp->md.journals; j++)
- if (sdp->md.journal && sdp->md.journal[j] &&
- block == sdp->md.journal[j]->i_di.di_num.no_addr)
- return sdp->md.journal[j];
- return NULL;
-}
-
-void inode_put(struct gfs2_inode **ip_in)
-{
- struct gfs2_inode *ip = *ip_in;
- uint64_t block = ip->i_di.di_num.no_addr;
- struct gfs2_sbd *sdp = ip->i_sbd;
-
- if (ip->i_bh->b_modified) {
- gfs2_dinode_out(&ip->i_di, ip->i_bh);
- if (!ip->bh_owned && is_system_inode(sdp, block))
- fprintf(stderr, "Warning: Change made to inode "
- "were discarded.\n");
- /* This is for debugging only: a convenient place to set
- a breakpoint. This means a system inode was modified but
- not written. That's not fatal: some places like
- adjust_inode in gfs2_convert will do this on purpose.
- It can also point out a coding problem, but we don't
- want to raise alarm in the users either. */
- }
- if (ip->bh_owned)
- brelse(ip->i_bh);
- ip->i_bh = NULL;
- free(ip);
- *ip_in = NULL; /* make sure the memory isn't accessed again */
-}
-
-static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type)
-{
- osi_list_t *tmp, *head;
- struct rgrp_list *rl = NULL;
- struct gfs2_rindex *ri;
- struct gfs2_rgrp *rg;
- unsigned int block, bn = 0, x = 0, y = 0;
- unsigned int state;
- struct gfs2_buffer_head *bh;
-
- memset(&rg, 0, sizeof(rg));
- for (head = &sdp->rglist, tmp = head->next; tmp != head;
- tmp = tmp->next) {
- rl = osi_list_entry(tmp, struct rgrp_list, list);
- if (rl->rg.rg_free)
- break;
- }
-
- if (tmp == head)
- die("out of space\n");
-
- ri = &rl->ri;
- rg = &rl->rg;
-
- for (block = 0; block < ri->ri_length; block++) {
- bh = rl->bh[block];
- x = (block) ? sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_rgrp);
-
- for (; x < sdp->bsize; x++)
- for (y = 0; y < GFS2_NBBY; y++) {
- state = (bh->b_data[x] >> (GFS2_BIT_SIZE * y)) & 0x03;
- if (state == GFS2_BLKST_FREE)
- goto found;
- bn++;
- }
- }
-
- die("allocation is broken (1): %"PRIu64" %u\n",
- (uint64_t)rl->ri.ri_addr, rl->rg.rg_free);
-
-found:
- if (bn >= ri->ri_bitbytes * GFS2_NBBY)
- die("allocation is broken (2): bn: %u %u rgrp: %"PRIu64
- " (0x%" PRIx64 ") Free:%u\n",
- bn, ri->ri_bitbytes * GFS2_NBBY, (uint64_t)rl->ri.ri_addr,
- (uint64_t)rl->ri.ri_addr, rl->rg.rg_free);
-
- switch (type) {
- case DATA:
- case META:
- state = GFS2_BLKST_USED;
- break;
- case DINODE:
- state = GFS2_BLKST_DINODE;
- rg->rg_dinodes++;
- break;
- default:
- die("bad state\n");
- }
-
- bh->b_data[x] &= ~(0x03 << (GFS2_BIT_SIZE * y));
- bh->b_data[x] |= state << (GFS2_BIT_SIZE * y);
- rg->rg_free--;
-
- bmodified(bh);
- gfs2_rgrp_out(rg, rl->bh[0]);
-
- sdp->blks_alloced++;
- return ri->ri_data0 + bn;
-}
-
-uint64_t data_alloc(struct gfs2_inode *ip)
-{
- uint64_t x;
- x = blk_alloc_i(ip->i_sbd, DATA);
- ip->i_di.di_goal_data = x;
- bmodified(ip->i_bh);
- return x;
-}
-
-uint64_t meta_alloc(struct gfs2_inode *ip)
-{
- uint64_t x;
- x = blk_alloc_i(ip->i_sbd, META);
- ip->i_di.di_goal_meta = x;
- bmodified(ip->i_bh);
- return x;
-}
-
-uint64_t dinode_alloc(struct gfs2_sbd *sdp)
-{
- sdp->dinodes_alloced++;
- return blk_alloc_i(sdp, DINODE);
-}
-
-static __inline__ void buffer_clear_tail(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *bh, int head)
-{
- memset(bh->b_data + head, 0, sdp->bsize - head);
- bmodified(bh);
-}
-
-static __inline__ void
-buffer_copy_tail(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *to_bh, int to_head,
- struct gfs2_buffer_head *from_bh, int from_head)
-{
- memcpy(to_bh->b_data + to_head, from_bh->b_data + from_head,
- sdp->bsize - from_head);
- memset(to_bh->b_data + sdp->bsize + to_head - from_head, 0,
- from_head - to_head);
- bmodified(to_bh);
-}
-
-void unstuff_dinode(struct gfs2_inode *ip)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_buffer_head *bh;
- uint64_t block = 0;
- int isdir = !!(S_ISDIR(ip->i_di.di_mode));
-
- if (ip->i_di.di_size) {
- if (isdir) {
- struct gfs2_meta_header mh;
-
- block = meta_alloc(ip);
- bh = bget(sdp, block);
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_JD;
- mh.mh_format = GFS2_FORMAT_JD;
- gfs2_meta_header_out(&mh, bh);
-
- buffer_copy_tail(sdp, bh,
- sizeof(struct gfs2_meta_header),
- ip->i_bh, sizeof(struct gfs2_dinode));
-
- brelse(bh);
- } else {
- block = data_alloc(ip);
- bh = bget(sdp, block);
-
- buffer_copy_tail(sdp, bh, 0,
- ip->i_bh, sizeof(struct gfs2_dinode));
- brelse(bh);
- }
- }
-
- buffer_clear_tail(sdp, ip->i_bh, sizeof(struct gfs2_dinode));
-
- if (ip->i_di.di_size) {
- *(uint64_t *)(ip->i_bh->b_data + sizeof(struct gfs2_dinode)) = cpu_to_be64(block);
- /* no need: bmodified(ip->i_bh); buffer_clear_tail does it */
- ip->i_di.di_blocks++;
- }
-
- ip->i_di.di_height = 1;
-}
-
-unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- uint64_t *arr;
- unsigned int max, height;
-
- if (ip->i_di.di_size > size)
- size = ip->i_di.di_size;
-
- if (S_ISDIR(ip->i_di.di_mode)) {
- arr = sdp->sd_jheightsize;
- max = sdp->sd_max_jheight;
- } else {
- arr = sdp->sd_heightsize;
- max = sdp->sd_max_height;
- }
-
- for (height = 0; height < max; height++)
- if (arr[height] >= size)
- break;
-
- return height;
-}
-
-void build_height(struct gfs2_inode *ip, int height)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_buffer_head *bh;
- uint64_t block = 0, *bp;
- unsigned int x;
- int new_block;
-
- while (ip->i_di.di_height < height) {
- new_block = FALSE;
- bp = (uint64_t *)(ip->i_bh->b_data + sizeof(struct gfs2_dinode));
- for (x = 0; x < sdp->sd_diptrs; x++, bp++)
- if (*bp) {
- new_block = TRUE;
- break;
- }
-
- if (new_block) {
- struct gfs2_meta_header mh;
-
- block = meta_alloc(ip);
- bh = bget(sdp, block);
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_IN;
- mh.mh_format = GFS2_FORMAT_IN;
- gfs2_meta_header_out(&mh, bh);
- buffer_copy_tail(sdp, bh,
- sizeof(struct gfs2_meta_header),
- ip->i_bh, sizeof(struct gfs2_dinode));
- brelse(bh);
- }
-
- buffer_clear_tail(sdp, ip->i_bh, sizeof(struct gfs2_dinode));
-
- if (new_block) {
- *(uint64_t *)(ip->i_bh->b_data + sizeof(struct gfs2_dinode)) = cpu_to_be64(block);
- /* no need: bmodified(ip->i_bh);*/
- ip->i_di.di_blocks++;
- }
-
- ip->i_di.di_height++;
- }
-}
-
-struct metapath *find_metapath(struct gfs2_inode *ip, uint64_t block)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct metapath *mp;
- uint64_t b = block;
- unsigned int i;
-
- mp = calloc(1, sizeof(struct metapath));
- if (mp == NULL) {
- fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
- exit(-1);
- }
- for (i = ip->i_di.di_height; i--;) {
- mp->mp_list[i] = b % sdp->sd_inptrs;
- b /= sdp->sd_inptrs;
- }
-
- return mp;
-}
-
-void lookup_block(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
- unsigned int height, struct metapath *mp,
- int create, int *new, uint64_t *block)
-{
- uint64_t *ptr = metapointer(bh, height, mp);
-
- if (*ptr) {
- *block = be64_to_cpu(*ptr);
- return;
- }
-
- *block = 0;
-
- if (!create)
- return;
-
- if (height == ip->i_di.di_height - 1&&
- !(S_ISDIR(ip->i_di.di_mode)))
- *block = data_alloc(ip);
- else
- *block = meta_alloc(ip);
-
- *ptr = cpu_to_be64(*block);
- bmodified(bh);
- ip->i_di.di_blocks++;
- bmodified(ip->i_bh);
-
- *new = 1;
-}
-
-void block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
- uint64_t *dblock, uint32_t *extlen, int prealloc)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_buffer_head *bh;
- struct metapath *mp;
- int create = *new;
- unsigned int bsize;
- unsigned int height;
- unsigned int end_of_metadata;
- unsigned int x;
-
- *new = 0;
- *dblock = 0;
- if (extlen)
- *extlen = 0;
-
- if (inode_is_stuffed(ip)) {
- if (!lblock) {
- *dblock = ip->i_di.di_num.no_addr;
- if (extlen)
- *extlen = 1;
- }
- return;
- }
-
- bsize = (S_ISDIR(ip->i_di.di_mode)) ? sdp->sd_jbsize : sdp->bsize;
-
- height = calc_tree_height(ip, (lblock + 1) * bsize);
- if (ip->i_di.di_height < height) {
- if (!create)
- return;
-
- build_height(ip, height);
- }
-
- mp = find_metapath(ip, lblock);
- end_of_metadata = ip->i_di.di_height - 1;
-
- bh = ip->i_bh;
-
- for (x = 0; x < end_of_metadata; x++) {
- lookup_block(ip, bh, x, mp, create, new, dblock);
- if (bh != ip->i_bh)
- brelse(bh);
- if (!*dblock)
- goto out;
-
- if (*new) {
- struct gfs2_meta_header mh;
- bh = bget(sdp, *dblock);
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_IN;
- mh.mh_format = GFS2_FORMAT_IN;
- gfs2_meta_header_out(&mh, bh);
- } else {
- if (*dblock == ip->i_di.di_num.no_addr)
- bh = ip->i_bh;
- else
- bh = bread(sdp, *dblock);
- }
- }
-
- if (!prealloc)
- lookup_block(ip, bh, end_of_metadata, mp, create, new, dblock);
-
- if (extlen && *dblock) {
- *extlen = 1;
-
- if (!*new) {
- uint64_t tmp_dblock;
- int tmp_new;
- unsigned int nptrs;
-
- nptrs = (end_of_metadata) ? sdp->sd_inptrs : sdp->sd_diptrs;
-
- while (++mp->mp_list[end_of_metadata] < nptrs) {
- lookup_block(ip, bh, end_of_metadata, mp, FALSE, &tmp_new,
- &tmp_dblock);
-
- if (*dblock + *extlen != tmp_dblock)
- break;
-
- (*extlen)++;
- }
- }
- }
-
- if (bh != ip->i_bh)
- brelse(bh);
-
- out:
- free(mp);
-}
-
-static void
-copy2mem(struct gfs2_buffer_head *bh, void **buf, unsigned int offset,
- unsigned int size)
-{
- char **p = (char **)buf;
-
- if (bh)
- memcpy(*p, bh->b_data + offset, size);
- else
- memset(*p, 0, size);
-
- *p += size;
-}
-
-int gfs2_readi(struct gfs2_inode *ip, void *buf,
- uint64_t offset, unsigned int size)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_buffer_head *bh;
- uint64_t lblock, dblock;
- unsigned int o;
- uint32_t extlen = 0;
- unsigned int amount;
- int not_new = 0;
- int isdir = !!(S_ISDIR(ip->i_di.di_mode));
- int copied = 0;
-
- if (offset >= ip->i_di.di_size)
- return 0;
-
- if ((offset + size) > ip->i_di.di_size)
- size = ip->i_di.di_size - offset;
-
- if (!size)
- return 0;
-
- if (isdir) {
- lblock = offset;
- o = lblock % sdp->sd_jbsize;
- lblock /= sdp->sd_jbsize;
- } else {
- lblock = offset >> sdp->sd_sb.sb_bsize_shift;
- o = offset & (sdp->bsize - 1);
- }
-
- if (inode_is_stuffed(ip))
- o += sizeof(struct gfs2_dinode);
- else if (isdir)
- o += sizeof(struct gfs2_meta_header);
-
- while (copied < size) {
- amount = size - copied;
- if (amount > sdp->bsize - o)
- amount = sdp->bsize - o;
-
- if (!extlen)
- block_map(ip, lblock, ¬_new, &dblock, &extlen,
- FALSE);
-
- if (dblock) {
- if (dblock == ip->i_di.di_num.no_addr)
- bh = ip->i_bh;
- else
- bh = bread(sdp, dblock);
- dblock++;
- extlen--;
- } else
- bh = NULL;
-
- copy2mem(bh, &buf, o, amount);
- if (bh && bh != ip->i_bh)
- brelse(bh);
-
- copied += amount;
- lblock++;
-
- o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
- }
-
- return copied;
-}
-
-static void copy_from_mem(struct gfs2_buffer_head *bh, void **buf,
- unsigned int offset, unsigned int size)
-{
- char **p = (char **)buf;
-
- memcpy(bh->b_data + offset, *p, size);
- bmodified(bh);
- *p += size;
-}
-
-int gfs2_writei(struct gfs2_inode *ip, void *buf,
- uint64_t offset, unsigned int size)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_buffer_head *bh;
- uint64_t lblock, dblock;
- unsigned int o;
- uint32_t extlen = 0;
- unsigned int amount;
- int new;
- int isdir = !!(S_ISDIR(ip->i_di.di_mode));
- const uint64_t start = offset;
- int copied = 0;
-
- if (!size)
- return 0;
-
- if (inode_is_stuffed(ip) &&
- ((start + size) > (sdp->bsize - sizeof(struct gfs2_dinode))))
- unstuff_dinode(ip);
-
- if (isdir) {
- lblock = offset;
- o = lblock % sdp->sd_jbsize;
- lblock /= sdp->sd_jbsize;
- } else {
- lblock = offset >> sdp->sd_sb.sb_bsize_shift;
- o = offset & (sdp->bsize - 1);
- }
-
- if (inode_is_stuffed(ip))
- o += sizeof(struct gfs2_dinode);
- else if (isdir)
- o += sizeof(struct gfs2_meta_header);
-
- while (copied < size) {
- amount = size - copied;
- if (amount > sdp->bsize - o)
- amount = sdp->bsize - o;
-
- if (!extlen) {
- new = TRUE;
- block_map(ip, lblock, &new, &dblock, &extlen, FALSE);
- }
-
- if (new) {
- bh = bget(sdp, dblock);
- if (isdir) {
- struct gfs2_meta_header mh;
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_JD;
- mh.mh_format = GFS2_FORMAT_JD;
- gfs2_meta_header_out(&mh, bh);
- }
- } else {
- if (dblock == ip->i_di.di_num.no_addr)
- bh = ip->i_bh;
- else
- bh = bread(sdp, dblock);
- }
- copy_from_mem(bh, &buf, o, amount);
- if (bh != ip->i_bh)
- brelse(bh);
-
- copied += amount;
- lblock++;
- dblock++;
- extlen--;
-
- o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
- }
-
- if (ip->i_di.di_size < start + copied) {
- bmodified(ip->i_bh);
- ip->i_di.di_size = start + copied;
- }
-
- return copied;
-}
-
-struct gfs2_buffer_head *get_file_buf(struct gfs2_inode *ip, uint64_t lbn,
- int prealloc)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- uint64_t dbn;
- int new = TRUE;
-
- if (inode_is_stuffed(ip))
- unstuff_dinode(ip);
-
- block_map(ip, lbn, &new, &dbn, NULL, prealloc);
- if (!dbn)
- die("get_file_buf\n");
-
- if (!prealloc && new &&
- ip->i_di.di_size < (lbn + 1) << sdp->sd_sb.sb_bsize_shift) {
- bmodified(ip->i_bh);
- ip->i_di.di_size = (lbn + 1) << sdp->sd_sb.sb_bsize_shift;
- }
- if (dbn == ip->i_di.di_num.no_addr)
- return ip->i_bh;
- else
- return bread(sdp, dbn);
-}
-
-int gfs2_dirent_first(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
- struct gfs2_dirent **dent)
-{
- struct gfs2_meta_header *h = (struct gfs2_meta_header *)bh->b_data;
-
- if (be32_to_cpu(h->mh_type) == GFS2_METATYPE_LF) {
- *dent = (struct gfs2_dirent *)(bh->b_data + sizeof(struct gfs2_leaf));
- return IS_LEAF;
- } else {
- *dent = (struct gfs2_dirent *)(bh->b_data + sizeof(struct gfs2_dinode));
- return IS_DINODE;
- }
-}
-
-int gfs2_dirent_next(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
- struct gfs2_dirent **dent)
-{
- char *bh_end;
- uint16_t cur_rec_len;
-
- bh_end = bh->b_data + dip->i_sbd->bsize;
- cur_rec_len = be16_to_cpu((*dent)->de_rec_len);
-
- if (cur_rec_len == 0 || (char *)(*dent) + cur_rec_len >= bh_end)
- return -ENOENT;
-
- *dent = (struct gfs2_dirent *)((char *)(*dent) + cur_rec_len);
-
- return 0;
-}
-
-static int dirent_alloc(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
- int name_len, struct gfs2_dirent **dent_out)
-{
- struct gfs2_dirent *dent, *new;
- unsigned int rec_len = GFS2_DIRENT_SIZE(name_len);
- unsigned int entries = 0, offset = 0;
- int type;
-
- type = gfs2_dirent_first(dip, bh, &dent);
-
- if (type == IS_LEAF) {
- struct gfs2_leaf *leaf = (struct gfs2_leaf *)bh->b_data;
- entries = be16_to_cpu(leaf->lf_entries);
- offset = sizeof(struct gfs2_leaf);
- } else {
- struct gfs2_dinode *dinode = (struct gfs2_dinode *)bh->b_data;
- entries = be32_to_cpu(dinode->di_entries);
- offset = sizeof(struct gfs2_dinode);
- }
-
- if (!entries) {
- dent->de_rec_len = cpu_to_be16(dip->i_sbd->bsize - offset);
- dent->de_name_len = cpu_to_be16(name_len);
- bmodified(bh);
- *dent_out = dent;
- dip->i_di.di_entries++;
- bmodified(dip->i_bh);
- return 0;
- }
-
- do {
- uint16_t cur_rec_len;
- uint16_t cur_name_len;
- uint16_t new_rec_len;
-
- cur_rec_len = be16_to_cpu(dent->de_rec_len);
- cur_name_len = be16_to_cpu(dent->de_name_len);
-
- if ((!dent->de_inum.no_formal_ino && cur_rec_len >= rec_len) ||
- (cur_rec_len >= GFS2_DIRENT_SIZE(cur_name_len) + rec_len)) {
-
- if (dent->de_inum.no_formal_ino) {
- new = (struct gfs2_dirent *)((char *)dent +
- GFS2_DIRENT_SIZE(cur_name_len));
- memset(new, 0, sizeof(struct gfs2_dirent));
-
- new->de_rec_len = cpu_to_be16(cur_rec_len -
- GFS2_DIRENT_SIZE(cur_name_len));
- new->de_name_len = cpu_to_be16(name_len);
-
- new_rec_len = be16_to_cpu(new->de_rec_len);
- dent->de_rec_len = cpu_to_be16(cur_rec_len - new_rec_len);
-
- *dent_out = new;
- bmodified(bh);
- dip->i_di.di_entries++;
- bmodified(dip->i_bh);
- return 0;
- }
-
- dent->de_name_len = cpu_to_be16(name_len);
-
- *dent_out = dent;
- bmodified(bh);
- dip->i_di.di_entries++;
- bmodified(dip->i_bh);
- return 0;
- }
- } while (gfs2_dirent_next(dip, bh, &dent) == 0);
-
- return -ENOSPC;
-}
-
-void dirent2_del(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
- struct gfs2_dirent *prev, struct gfs2_dirent *cur)
-{
- uint16_t cur_rec_len, prev_rec_len;
-
- bmodified(bh);
- if (gfs2_check_meta(bh, GFS2_METATYPE_LF) == 0) {
- struct gfs2_leaf *lf = (struct gfs2_leaf *)bh->b_data;
-
- lf->lf_entries = be16_to_cpu(lf->lf_entries) - 1;
- lf->lf_entries = cpu_to_be16(lf->lf_entries);
- }
-
- if (dip->i_di.di_entries) {
- bmodified(dip->i_bh);
- dip->i_di.di_entries--;
- }
- if (!prev) {
- cur->de_inum.no_formal_ino = 0;
- return;
- }
-
- prev_rec_len = be16_to_cpu(prev->de_rec_len);
- cur_rec_len = be16_to_cpu(cur->de_rec_len);
-
- prev_rec_len += cur_rec_len;
- prev->de_rec_len = cpu_to_be16(prev_rec_len);
-}
-
-void gfs2_get_leaf_nr(struct gfs2_inode *dip, uint32_t lindex,
- uint64_t *leaf_out)
-{
- uint64_t leaf_no;
- int count;
-
- count = gfs2_readi(dip, (char *)&leaf_no, lindex * sizeof(uint64_t),
- sizeof(uint64_t));
- if (count != sizeof(uint64_t))
- die("gfs2_get_leaf_nr: Bad internal read.\n");
-
- *leaf_out = be64_to_cpu(leaf_no);
-}
-
-void gfs2_put_leaf_nr(struct gfs2_inode *dip, uint32_t inx, uint64_t leaf_out)
-{
- uint64_t leaf_no;
- int count;
-
- leaf_no = cpu_to_be64(leaf_out);
- count = gfs2_writei(dip, (char *)&leaf_no, inx * sizeof(uint64_t),
- sizeof(uint64_t));
- if (count != sizeof(uint64_t))
- die("gfs2_put_leaf_nr: Bad internal write.\n");
-}
-
-static void dir_split_leaf(struct gfs2_inode *dip, uint32_t lindex,
- uint64_t leaf_no)
-{
- struct gfs2_buffer_head *nbh, *obh;
- struct gfs2_leaf *nleaf, *oleaf;
- struct gfs2_dirent *dent, *prev = NULL, *next = NULL, *new;
- uint32_t start, len, half_len, divider;
- uint64_t bn, *lp;
- uint32_t name_len;
- int x, moved = FALSE;
- int count;
-
- bn = meta_alloc(dip);
- nbh = bget(dip->i_sbd, bn);
- {
- struct gfs2_meta_header mh;
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_LF;
- mh.mh_format = GFS2_FORMAT_LF;
- gfs2_meta_header_out(&mh, nbh);
- buffer_clear_tail(dip->i_sbd, nbh,
- sizeof(struct gfs2_meta_header));
- }
-
- nleaf = (struct gfs2_leaf *)nbh->b_data;
- nleaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE);
-
- obh = bread(dip->i_sbd, leaf_no);
- oleaf = (struct gfs2_leaf *)obh->b_data;
-
- len = 1 << (dip->i_di.di_depth - be16_to_cpu(oleaf->lf_depth));
- half_len = len >> 1;
-
- start = (lindex & ~(len - 1));
-
- lp = calloc(1, half_len * sizeof(uint64_t));
- if (lp == NULL) {
- fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
- exit(-1);
- }
- for (x = 0; x < half_len; x++)
- lp[x] = cpu_to_be64(bn);
-
- count = gfs2_writei(dip, (char *)lp, start * sizeof(uint64_t),
- half_len * sizeof(uint64_t));
- if (count != half_len * sizeof(uint64_t))
- die("dir_split_leaf (2)\n");
-
- free(lp);
-
- divider = (start + half_len) << (32 - dip->i_di.di_depth);
-
- gfs2_dirent_first(dip, obh, &dent);
-
- do {
- next = dent;
- if (gfs2_dirent_next(dip, obh, &next))
- next = NULL;
-
- if (dent->de_inum.no_formal_ino &&
- be32_to_cpu(dent->de_hash) < divider) {
- name_len = be16_to_cpu(dent->de_name_len);
-
- if (dirent_alloc(dip, nbh, name_len, &new))
- die("dir_split_leaf (3)\n");
-
- new->de_inum = dent->de_inum;
- new->de_hash = dent->de_hash;
- new->de_type = dent->de_type;
- memcpy((char *)(new + 1), (char *)(dent + 1), name_len);
-
- nleaf->lf_entries = be16_to_cpu(nleaf->lf_entries) + 1;
- nleaf->lf_entries = cpu_to_be16(nleaf->lf_entries);
-
- dirent2_del(dip, obh, prev, dent);
-
- if (!prev)
- prev = dent;
-
- moved = TRUE;
- } else
- prev = dent;
-
- dent = next;
- } while (dent);
-
- if (!moved) {
- if (dirent_alloc(dip, nbh, 0, &new))
- die("dir_split_leaf (4)\n");
- new->de_inum.no_formal_ino = 0;
- }
-
- oleaf->lf_depth = be16_to_cpu(oleaf->lf_depth) + 1;
- oleaf->lf_depth = cpu_to_be16(oleaf->lf_depth);
- nleaf->lf_depth = oleaf->lf_depth;
-
- dip->i_di.di_blocks++;
- bmodified(dip->i_bh);
-
- bmodified(obh); /* Need to do this in case nothing was moved */
- brelse(obh);
- bmodified(nbh);
- brelse(nbh);
-}
-
-static void dir_double_exhash(struct gfs2_inode *dip)
-{
- struct gfs2_sbd *sdp = dip->i_sbd;
- uint64_t *buf;
- uint64_t *from, *to;
- uint64_t block;
- int x;
- int count;
-
- buf = calloc(1, 3 * sdp->sd_hash_bsize);
- if (buf == NULL) {
- fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
- exit(-1);
- }
-
- for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) {
- count = gfs2_readi(dip, (char *)buf,
- block * sdp->sd_hash_bsize,
- sdp->sd_hash_bsize);
- if (count != sdp->sd_hash_bsize)
- die("dir_double_exhash (1)\n");
-
- from = buf;
- to = (uint64_t *)((char *)buf + sdp->sd_hash_bsize);
-
- for (x = sdp->sd_hash_ptrs; x--; from++) {
- *to++ = *from;
- *to++ = *from;
- }
-
- count = gfs2_writei(dip, (char *)buf + sdp->sd_hash_bsize,
- block * sdp->bsize, sdp->bsize);
- if (count != sdp->bsize)
- die("dir_double_exhash (2)\n");
-
- }
-
- free(buf);
-
- dip->i_di.di_depth++;
- bmodified(dip->i_bh);
-}
-
-/**
- * get_leaf - Get leaf
- * @dip:
- * @leaf_no:
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-int gfs2_get_leaf(struct gfs2_inode *dip, uint64_t leaf_no,
- struct gfs2_buffer_head **bhp)
-{
- int error = 0;
-
- *bhp = bread(dip->i_sbd, leaf_no);
- if (error)
- return error;
- error = gfs2_check_meta(*bhp, GFS2_METATYPE_LF);
- if(error)
- brelse(*bhp);
- return error;
-}
-
-/**
- * get_first_leaf - Get first leaf
- * @dip: The GFS2 inode
- * @index:
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int get_first_leaf(struct gfs2_inode *dip, uint32_t lindex,
- struct gfs2_buffer_head **bh_out)
-{
- uint64_t leaf_no;
-
- gfs2_get_leaf_nr(dip, lindex, &leaf_no);
- *bh_out = bread(dip->i_sbd, leaf_no);
- return 0;
-}
-
-/**
- * get_next_leaf - Get next leaf
- * @dip: The GFS2 inode
- * @bh_in: The buffer
- * @bh_out:
- *
- * Returns: 0 on success, error code otherwise
- */
-
-static int get_next_leaf(struct gfs2_inode *dip,struct gfs2_buffer_head *bh_in,
- struct gfs2_buffer_head **bh_out)
-{
- struct gfs2_leaf *leaf;
-
- leaf = (struct gfs2_leaf *)bh_in->b_data;
-
- if (!leaf->lf_next)
- return -1;
- *bh_out = bread(dip->i_sbd, be64_to_cpu(leaf->lf_next));
- return 0;
-}
-
-static void dir_e_add(struct gfs2_inode *dip, const char *filename, int len,
- struct gfs2_inum *inum, unsigned int type)
-{
- struct gfs2_buffer_head *bh, *nbh;
- struct gfs2_leaf *leaf, *nleaf;
- struct gfs2_dirent *dent;
- uint32_t lindex;
- uint32_t hash;
- uint64_t leaf_no, bn;
-
- hash = gfs2_disk_hash(filename, len);
-restart:
- /* Have to kludge because (hash >> 32) gives hash for some reason. */
- if (dip->i_di.di_depth)
- lindex = hash >> (32 - dip->i_di.di_depth);
- else
- lindex = 0;
-
- gfs2_get_leaf_nr(dip, lindex, &leaf_no);
-
- for (;;) {
- bh = bread(dip->i_sbd, leaf_no);
- leaf = (struct gfs2_leaf *)bh->b_data;
-
- if (dirent_alloc(dip, bh, len, &dent)) {
-
- if (be16_to_cpu(leaf->lf_depth) < dip->i_di.di_depth) {
- brelse(bh);
- dir_split_leaf(dip, lindex, leaf_no);
- goto restart;
-
- } else if (dip->i_di.di_depth < GFS2_DIR_MAX_DEPTH) {
- brelse(bh);
- dir_double_exhash(dip);
- goto restart;
-
- } else if (leaf->lf_next) {
- leaf_no = be64_to_cpu(leaf->lf_next);
- brelse(bh);
- continue;
-
- } else {
- struct gfs2_meta_header mh;
-
- bn = meta_alloc(dip);
- nbh = bget(dip->i_sbd, bn);
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_LF;
- mh.mh_format = GFS2_FORMAT_LF;
- gfs2_meta_header_out(&mh, nbh);
-
- leaf->lf_next = cpu_to_be64(bn);
-
- nleaf = (struct gfs2_leaf *)nbh->b_data;
- nleaf->lf_depth = leaf->lf_depth;
- nleaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE);
-
- if (dirent_alloc(dip, nbh, len, &dent))
- die("dir_split_leaf (3)\n");
- dip->i_di.di_blocks++;
- bmodified(dip->i_bh);
- bmodified(bh);
- brelse(bh);
- bh = nbh;
- leaf = nleaf;
- }
- }
-
- gfs2_inum_out(inum, (char *)&dent->de_inum);
- dent->de_hash = cpu_to_be32(hash);
- dent->de_type = cpu_to_be16(type);
- memcpy((char *)(dent + 1), filename, len);
-
- leaf->lf_entries = be16_to_cpu(leaf->lf_entries) + 1;
- leaf->lf_entries = cpu_to_be16(leaf->lf_entries);
-
- bmodified(bh);
- brelse(bh);
- return;
- }
-}
-
-static void dir_make_exhash(struct gfs2_inode *dip)
-{
- struct gfs2_sbd *sdp = dip->i_sbd;
- struct gfs2_dirent *dent;
- struct gfs2_buffer_head *bh;
- struct gfs2_leaf *leaf;
- int y;
- uint32_t x;
- uint64_t *lp, bn;
-
- bn = meta_alloc(dip);
- bh = bget(sdp, bn);
- {
- struct gfs2_meta_header mh;
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_LF;
- mh.mh_format = GFS2_FORMAT_LF;
- gfs2_meta_header_out(&mh, bh);
- }
-
- leaf = (struct gfs2_leaf *)bh->b_data;
- leaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE);
- leaf->lf_entries = cpu_to_be16(dip->i_di.di_entries);
-
- buffer_copy_tail(sdp, bh, sizeof(struct gfs2_leaf),
- dip->i_bh, sizeof(struct gfs2_dinode));
-
- x = 0;
- gfs2_dirent_first(dip, bh, &dent);
-
- do {
- if (!dent->de_inum.no_formal_ino)
- continue;
- if (++x == dip->i_di.di_entries)
- break;
- } while (gfs2_dirent_next(dip, bh, &dent) == 0);
-
- dent->de_rec_len = be16_to_cpu(dent->de_rec_len);
- dent->de_rec_len = cpu_to_be16(dent->de_rec_len +
- sizeof(struct gfs2_dinode) - sizeof(struct gfs2_leaf));
-
- /* no need to: bmodified(bh); (buffer_copy_tail does it) */
- brelse(bh);
-
- buffer_clear_tail(sdp, dip->i_bh, sizeof(struct gfs2_dinode));
-
- lp = (uint64_t *)(dip->i_bh->b_data + sizeof(struct gfs2_dinode));
-
- for (x = sdp->sd_hash_ptrs; x--; lp++)
- *lp = cpu_to_be64(bn);
-
- dip->i_di.di_size = sdp->bsize / 2;
- dip->i_di.di_blocks++;
- dip->i_di.di_flags |= GFS2_DIF_EXHASH;
- dip->i_di.di_payload_format = 0;
- /* no need: bmodified(dip->i_bh); buffer_clear_tail does it. */
-
- for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ;
- dip->i_di.di_depth = y;
-
- gfs2_dinode_out(&dip->i_di, dip->i_bh);
- bwrite(dip->i_bh);
-}
-
-static void dir_l_add(struct gfs2_inode *dip, const char *filename, int len,
- struct gfs2_inum *inum, unsigned int type)
-{
- struct gfs2_dirent *dent;
-
- if (dirent_alloc(dip, dip->i_bh, len, &dent)) {
- dir_make_exhash(dip);
- dir_e_add(dip, filename, len, inum, type);
- return;
- }
-
- gfs2_inum_out(inum, (char *)&dent->de_inum);
- dent->de_hash = gfs2_disk_hash(filename, len);
- dent->de_hash = cpu_to_be32(dent->de_hash);
- dent->de_type = cpu_to_be16(type);
- memcpy((char *)(dent + 1), filename, len);
-}
-
-void dir_add(struct gfs2_inode *dip, const char *filename, int len,
- struct gfs2_inum *inum, unsigned int type)
-{
- if (dip->i_di.di_flags & GFS2_DIF_EXHASH)
- dir_e_add(dip, filename, len, inum, type);
- else
- dir_l_add(dip, filename, len, inum, type);
-}
-
-struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp,
- struct gfs2_inum *inum, unsigned int mode,
- uint32_t flags, struct gfs2_inum *parent)
-{
- struct gfs2_buffer_head *bh;
- struct gfs2_dinode di;
-
- bh = bget(sdp, inum->no_addr);
-
- memset(&di, 0, sizeof(struct gfs2_dinode));
- di.di_header.mh_magic = GFS2_MAGIC;
- di.di_header.mh_type = GFS2_METATYPE_DI;
- di.di_header.mh_format = GFS2_FORMAT_DI;
- di.di_num = *inum;
- di.di_mode = mode;
- di.di_nlink = 1;
- di.di_blocks = 1;
- di.di_atime = di.di_mtime = di.di_ctime = sdp->time;
- di.di_goal_meta = di.di_goal_data = bh->b_blocknr;
- di.di_flags = flags;
-
- if (S_ISDIR(mode)) {
- struct gfs2_dirent de1, de2;
-
- memset(&de1, 0, sizeof(struct gfs2_dirent));
- de1.de_inum = di.di_num;
- de1.de_hash = gfs2_disk_hash(".", 1);
- de1.de_rec_len = GFS2_DIRENT_SIZE(1);
- de1.de_name_len = 1;
- de1.de_type = IF2DT(S_IFDIR);
-
- memset(&de2, 0, sizeof(struct gfs2_dirent));
- de2.de_inum = *parent;
- de2.de_hash = gfs2_disk_hash("..", 2);
- de2.de_rec_len = sdp->bsize - sizeof(struct gfs2_dinode) - de1.de_rec_len;
- de2.de_name_len = 2;
- de2.de_type = IF2DT(S_IFDIR);
-
- gfs2_dirent_out(&de1, bh->b_data + sizeof(struct gfs2_dinode));
- memcpy(bh->b_data +
- sizeof(struct gfs2_dinode) +
- sizeof(struct gfs2_dirent),
- ".", 1);
- gfs2_dirent_out(&de2, bh->b_data + sizeof(struct gfs2_dinode) + de1.de_rec_len);
- memcpy(bh->b_data +
- sizeof(struct gfs2_dinode) +
- de1.de_rec_len +
- sizeof(struct gfs2_dirent),
- "..", 2);
-
- di.di_nlink = 2;
- di.di_size = sdp->bsize - sizeof(struct gfs2_dinode);
- di.di_flags |= GFS2_DIF_JDATA;
- di.di_payload_format = GFS2_FORMAT_DE;
- di.di_entries = 2;
- }
-
- gfs2_dinode_out(&di, bh);
-
- return bh;
-}
-
-struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename,
- unsigned int mode, uint32_t flags)
-{
- struct gfs2_sbd *sdp = dip->i_sbd;
- uint64_t bn;
- struct gfs2_inum inum;
- struct gfs2_buffer_head *bh;
- struct gfs2_inode *ip;
-
- gfs2_lookupi(dip, filename, strlen(filename), &ip);
- if (!ip) {
- bn = dinode_alloc(sdp);
-
- inum.no_formal_ino = sdp->md.next_inum++;
- inum.no_addr = bn;
-
- dir_add(dip, filename, strlen(filename), &inum, IF2DT(mode));
-
- if(S_ISDIR(mode)) {
- bmodified(dip->i_bh);
- dip->i_di.di_nlink++;
- }
-
- bh = init_dinode(sdp, &inum, mode, flags, &dip->i_di.di_num);
- ip = inode_get(sdp, bh);
- bmodified(bh);
- }
- ip->bh_owned = 1;
- return ip;
-}
-
-/**
- * gfs2_filecmp - Compare two filenames
- * @file1: The first filename
- * @file2: The second filename
- * @len_of_file2: The length of the second file
- *
- * This routine compares two filenames and returns 1 if they are equal.
- *
- * Returns: 1 if the files are the same, otherwise 0.
- */
-
-static int gfs2_filecmp(const char *file1, const char *file2, int len_of_file2)
-{
- if (strlen(file1) != len_of_file2)
- return 0;
- if (memcmp(file1, file2, len_of_file2))
- return 0;
- return 1;
-}
-
-/**
- * leaf_search
- * @bh:
- * @id:
- * @dent_out:
- * @dent_prev:
- *
- * Returns:
- */
-static int leaf_search(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
- const char *filename, int len,
- struct gfs2_dirent **dent_out,
- struct gfs2_dirent **dent_prev)
-{
- uint32_t hash;
- struct gfs2_dirent *dent, *prev = NULL;
- unsigned int entries = 0, x = 0;
- int type;
-
- type = gfs2_dirent_first(dip, bh, &dent);
-
- if (type == IS_LEAF){
- struct gfs2_leaf *leaf = (struct gfs2_leaf *)bh->b_data;
- entries = be16_to_cpu(leaf->lf_entries);
- } else if (type == IS_DINODE) {
- struct gfs2_dinode *dinode = (struct gfs2_dinode *)bh->b_data;
- entries = be32_to_cpu(dinode->di_entries);
- } else
- return -1;
-
- hash = gfs2_disk_hash(filename, len);
-
- do{
- if (!dent->de_inum.no_formal_ino){
- prev = dent;
- continue;
- }
-
- if (be32_to_cpu(dent->de_hash) == hash &&
- gfs2_filecmp(filename, (char *)(dent + 1),
- be16_to_cpu(dent->de_name_len))){
- *dent_out = dent;
- if (dent_prev)
- *dent_prev = prev;
- return 0;
- }
-
- if(x >= entries)
- return -1;
- x++;
- prev = dent;
- } while (gfs2_dirent_next(dip, bh, &dent) == 0);
-
- return -ENOENT;
-}
-
-/**
- * linked_leaf_search - Linked leaf search
- * @dip: The GFS2 inode
- * @id:
- * @dent_out:
- * @dent_prev:
- * @bh_out:
- *
- * Returns: 0 on sucess, error code otherwise
- */
-
-static int linked_leaf_search(struct gfs2_inode *dip, const char *filename,
- int len, struct gfs2_dirent **dent_out,
- struct gfs2_buffer_head **bh_out)
-{
- struct gfs2_buffer_head *bh = NULL, *bh_next;
- uint32_t hsize, lindex;
- uint32_t hash;
- int error = 0;
-
- hsize = 1 << dip->i_di.di_depth;
- if(hsize * sizeof(uint64_t) != dip->i_di.di_size)
- return -1;
-
- /* Figure out the address of the leaf node. */
-
- hash = gfs2_disk_hash(filename, len);
- lindex = hash >> (32 - dip->i_di.di_depth);
-
- error = get_first_leaf(dip, lindex, &bh_next);
- if (error)
- return error;
-
- /* Find the entry */
- do{
- if (bh && bh != dip->i_bh)
- brelse(bh);
-
- bh = bh_next;
-
- error = leaf_search(dip, bh, filename, len, dent_out, NULL);
- switch (error){
- case 0:
- *bh_out = bh;
- return 0;
-
- case -ENOENT:
- break;
-
- default:
- if (bh && bh != dip->i_bh)
- brelse(bh);
- return error;
- }
-
- error = get_next_leaf(dip, bh, &bh_next);
- } while (!error);
-
- if (bh && bh != dip->i_bh)
- brelse(bh);
-
- return error;
-}
-
-/**
- * dir_e_search -
- * @dip: The GFS2 inode
- * @id:
- * @inode:
- *
- * Returns:
- */
-static int dir_e_search(struct gfs2_inode *dip, const char *filename,
- int len, unsigned int *type, struct gfs2_inum *inum)
-{
- struct gfs2_buffer_head *bh = NULL;
- struct gfs2_dirent *dent;
- int error;
-
- error = linked_leaf_search(dip, filename, len, &dent, &bh);
- if (error)
- return error;
-
- gfs2_inum_in(inum, (char *)&dent->de_inum);
- if (type)
- *type = be16_to_cpu(dent->de_type);
-
- brelse(bh);
-
- return 0;
-}
-
-
-/**
- * dir_l_search -
- * @dip: The GFS2 inode
- * @id:
- * @inode:
- *
- * Returns:
- */
-static int dir_l_search(struct gfs2_inode *dip, const char *filename,
- int len, unsigned int *type, struct gfs2_inum *inum)
-{
- struct gfs2_dirent *dent;
- int error;
-
- if(!inode_is_stuffed(dip))
- return -1;
-
- error = leaf_search(dip, dip->i_bh, filename, len, &dent, NULL);
- if (!error) {
- gfs2_inum_in(inum, (char *)&dent->de_inum);
- if(type)
- *type = be16_to_cpu(dent->de_type);
- }
- return error;
-}
-
-/**
- * dir_search - Search a directory
- * @dip: The GFS inode
- * @id
- * @type:
- *
- * This routine searches a directory for a file or another directory
- * given its filename. The component of the identifier that is
- * not being used to search will be filled in and must be freed by
- * the caller.
- *
- * Returns: 0 if found, -1 on failure, -ENOENT if not found.
- */
-int dir_search(struct gfs2_inode *dip, const char *filename, int len,
- unsigned int *type, struct gfs2_inum *inum)
-{
- int error;
-
- if(!S_ISDIR(dip->i_di.di_mode))
- return -1;
-
- if (dip->i_di.di_flags & GFS2_DIF_EXHASH)
- error = dir_e_search(dip, filename, len, type, inum);
- else
- error = dir_l_search(dip, filename, len, type, inum);
-
- return error;
-}
-
-static int dir_e_del(struct gfs2_inode *dip, const char *filename, int len)
-{
- int lindex;
- int error;
- int found = 0;
- uint64_t leaf_no;
- struct gfs2_buffer_head *bh = NULL;
- struct gfs2_dirent *cur, *prev;
-
- lindex = (1 << (dip->i_di.di_depth))-1;
-
- for(; (lindex >= 0) && !found; lindex--){
- gfs2_get_leaf_nr(dip, lindex, &leaf_no);
-
- while(leaf_no && !found){
- bh = bread(dip->i_sbd, leaf_no);
- error = leaf_search(dip, bh, filename, len, &cur, &prev);
- if (error) {
- if(error != -ENOENT){
- brelse(bh);
- return -1;
- }
- leaf_no = be64_to_cpu(((struct gfs2_leaf *)bh->b_data)->lf_next);
- brelse(bh);
- } else
- found = 1;
- }
- }
-
- if(!found)
- return 1;
-
- if (bh) {
- dirent2_del(dip, bh, prev, cur);
- brelse(bh);
- }
- return 0;
-}
-
-static int dir_l_del(struct gfs2_inode *dip, const char *filename, int len)
-{
- int error=0;
- struct gfs2_dirent *cur, *prev;
-
- if(!inode_is_stuffed(dip))
- return -1;
-
- error = leaf_search(dip, dip->i_bh, filename, len, &cur, &prev);
- if (error) {
- if (error == -ENOENT)
- return 1;
- else
- return -1;
- }
-
- dirent2_del(dip, dip->i_bh, prev, cur);
- return 0;
-}
-
-
-/*
- * gfs2_dirent_del
- * @dip
- * filename
- *
- * Delete a directory entry from a directory. This _only_
- * removes the directory entry - leaving the dinode in
- * place. (Likely without a link.)
- *
- * Returns: 0 on success (or if it doesn't already exist), -1 on failure
- */
-int gfs2_dirent_del(struct gfs2_inode *dip, const char *filename, int len)
-{
- int error;
-
- if(!S_ISDIR(dip->i_di.di_mode))
- return -1;
-
- if (dip->i_di.di_flags & GFS2_DIF_EXHASH)
- error = dir_e_del(dip, filename, len);
- else
- error = dir_l_del(dip, filename, len);
- bmodified(dip->i_bh);
- return error;
-}
-
-/**
- * gfs2_lookupi - Look up a filename in a directory and return its inode
- * @dip: The directory to search
- * @name: The name of the inode to look for
- * @ipp: Used to return the found inode if any
- *
- * Returns: 0 on success, -EXXXX on failure
- */
-int gfs2_lookupi(struct gfs2_inode *dip, const char *filename, int len,
- struct gfs2_inode **ipp)
-{
- struct gfs2_sbd *sdp = dip->i_sbd;
- int error = 0;
- struct gfs2_inum inum;
-
- *ipp = NULL;
-
- if (!len || len > GFS2_FNAMESIZE)
- return -ENAMETOOLONG;
- if (gfs2_filecmp(filename, (char *)".", 1)) {
- *ipp = dip;
- return 0;
- }
- error = dir_search(dip, filename, len, NULL, &inum);
- if (error) {
- if (error == -ENOENT)
- return 0;
- }
- else
- *ipp = inode_read(sdp, inum.no_addr);
-
- return error;
-}
-
-/**
- * gfs2_free_block - free up a block given its block number
- */
-void gfs2_free_block(struct gfs2_sbd *sdp, uint64_t block)
-{
- struct rgrp_list *rgd;
-
- /* Adjust the free space count for the freed block */
- rgd = gfs2_blk2rgrpd(sdp, block); /* find the rg for indir block */
- if (rgd) {
- gfs2_set_bitmap(sdp, block, GFS2_BLKST_FREE);
- rgd->rg.rg_free++; /* adjust the free count */
- gfs2_rgrp_out(&rgd->rg, rgd->bh[0]); /* back to the buffer */
- sdp->blks_alloced--;
- }
-}
-
-/**
- * gfs2_freedi - unlink a disk inode by block number.
- * Note: currently only works for regular files.
- */
-int gfs2_freedi(struct gfs2_sbd *sdp, uint64_t diblock)
-{
- struct gfs2_inode *ip;
- struct gfs2_buffer_head *bh, *nbh;
- int h, head_size;
- uint64_t *ptr, block;
- struct rgrp_list *rgd;
- uint32_t height;
- osi_list_t metalist[GFS2_MAX_META_HEIGHT];
- osi_list_t *cur_list, *next_list, *tmp;
-
- for (h = 0; h < GFS2_MAX_META_HEIGHT; h++)
- osi_list_init(&metalist[h]);
-
- bh = bread(sdp, diblock);
- ip = inode_get(sdp, bh);
- height = ip->i_di.di_height;
- osi_list_add(&bh->b_altlist, &metalist[0]);
-
- for (h = 0; h < height; h++){
- cur_list = &metalist[h];
- next_list = &metalist[h + 1];
- head_size = (h > 0 ? sizeof(struct gfs2_meta_header) :
- sizeof(struct gfs2_dinode));
-
- for (tmp = cur_list->next; tmp != cur_list; tmp = tmp->next){
- bh = osi_list_entry(tmp, struct gfs2_buffer_head,
- b_altlist);
-
- for (ptr = (uint64_t *)(bh->b_data + head_size);
- (char *)ptr < (bh->b_data + sdp->bsize); ptr++) {
- if (!*ptr)
- continue;
-
- block = be64_to_cpu(*ptr);
- gfs2_free_block(sdp, block);
- if (h == height - 1) /* if not metadata */
- continue; /* don't queue it up */
- /* Read the next metadata block in the chain */
- nbh = bread(sdp, block);
- osi_list_add(&nbh->b_altlist, next_list);
- brelse(nbh);
- }
- }
- }
- /* Set the bitmap type for inode to free space: */
- gfs2_set_bitmap(sdp, ip->i_di.di_num.no_addr, GFS2_BLKST_FREE);
- inode_put(&ip);
- /* inode_put deallocated the extra block used by the disk inode, */
- /* so adjust it in the superblock struct */
- sdp->blks_alloced--;
- /* Now we have to adjust the rg freespace count and inode count: */
- rgd = gfs2_blk2rgrpd(sdp, diblock);
- rgd->rg.rg_free++;
- rgd->rg.rg_dinodes--; /* one less inode in use */
- gfs2_rgrp_out(&rgd->rg, rgd->bh[0]);
- sdp->dinodes_alloced--;
- return 0;
-}
diff --git a/gfs2/libgfs2/gfs1.c b/gfs2/libgfs2/gfs1.c
deleted file mode 100644
index 5018334..0000000
--- a/gfs2/libgfs2/gfs1.c
+++ /dev/null
@@ -1,446 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <linux/types.h>
-#include <linux/gfs2_ondisk.h>
-
-#include "osi_list.h"
-#include "libgfs2.h"
-
-/* GFS1 compatibility functions - so that programs like gfs2_convert
- and gfs2_edit can examine/manipulate GFS1 file systems. */
-
-static __inline__ int fs_is_jdata(struct gfs2_inode *ip)
-{
- return ip->i_di.di_flags & GFS2_DIF_JDATA;
-}
-
-static __inline__ uint64_t *
-gfs1_metapointer(struct gfs2_buffer_head *bh, unsigned int height,
- struct metapath *mp)
-{
- unsigned int head_size = (height > 0) ?
- sizeof(struct gfs_indirect) : sizeof(struct gfs_dinode);
-
- return ((uint64_t *)(bh->b_data + head_size)) + mp->mp_list[height];
-}
-
-void gfs1_lookup_block(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
- unsigned int height, struct metapath *mp,
- int create, int *new, uint64_t *block)
-{
- uint64_t *ptr = gfs1_metapointer(bh, height, mp);
-
- if (*ptr) {
- *block = be64_to_cpu(*ptr);
- return;
- }
-
- *block = 0;
-
- if (!create)
- return;
-
- if (height == ip->i_di.di_height - 1&&
- !(S_ISDIR(ip->i_di.di_mode)))
- *block = data_alloc(ip);
- else
- *block = meta_alloc(ip);
-
- *ptr = cpu_to_be64(*block);
- ip->i_di.di_blocks++;
-
- *new = 1;
-}
-
-void gfs1_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
- uint64_t *dblock, uint32_t *extlen, int prealloc)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_buffer_head *bh;
- struct metapath *mp;
- int create = *new;
- unsigned int bsize;
- unsigned int height;
- unsigned int end_of_metadata;
- unsigned int x;
-
- *new = 0;
- *dblock = 0;
- if (extlen)
- *extlen = 0;
-
- if (!ip->i_di.di_height) { /* stuffed */
- if (!lblock) {
- *dblock = ip->i_di.di_num.no_addr;
- if (extlen)
- *extlen = 1;
- }
- return;
- }
-
- bsize = (fs_is_jdata(ip)) ? sdp->sd_jbsize : sdp->bsize;
-
- height = calc_tree_height(ip, (lblock + 1) * bsize);
- if (ip->i_di.di_height < height) {
- if (!create)
- return;
-
- build_height(ip, height);
- }
-
- mp = find_metapath(ip, lblock);
- end_of_metadata = ip->i_di.di_height - 1;
-
- bh = ip->i_bh;
-
- for (x = 0; x < end_of_metadata; x++) {
- gfs1_lookup_block(ip, bh, x, mp, create, new, dblock);
- if (bh != ip->i_bh)
- brelse(bh);
- if (!*dblock)
- goto out;
-
- if (*new) {
- struct gfs2_meta_header mh;
-
- bh = bget(sdp, *dblock);
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_IN;
- mh.mh_format = GFS2_FORMAT_IN;
- gfs2_meta_header_out(&mh, bh);
- } else {
- bh = bread(sdp, *dblock);
- }
- }
-
- if (!prealloc)
- gfs1_lookup_block(ip, bh, end_of_metadata, mp, create, new,
- dblock);
-
- if (extlen && *dblock) {
- *extlen = 1;
-
- if (!*new) {
- uint64_t tmp_dblock;
- int tmp_new;
- unsigned int nptrs;
-
- nptrs = (end_of_metadata) ? sdp->sd_inptrs : sdp->sd_diptrs;
-
- while (++mp->mp_list[end_of_metadata] < nptrs) {
- gfs1_lookup_block(ip, bh, end_of_metadata, mp,
- FALSE, &tmp_new,
- &tmp_dblock);
-
- if (*dblock + *extlen != tmp_dblock)
- break;
-
- (*extlen)++;
- }
- }
- }
-
- if (bh != ip->i_bh)
- brelse(bh);
-
- out:
- free(mp);
-}
-
-int gfs1_readi(struct gfs2_inode *ip, void *bufin,
- uint64_t offset, unsigned int size)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_buffer_head *bh;
- uint64_t lblock, dblock = 0;
- uint32_t extlen = 0;
- unsigned int amount;
- int not_new = 0;
- int journaled = fs_is_jdata(ip);
- int copied = 0;
- char *buf = bufin;
-
- if (offset >= ip->i_di.di_size)
- return 0;
-
- if ((offset + size) > ip->i_di.di_size)
- size = ip->i_di.di_size - offset;
-
- if (!size)
- return 0;
-
- if (journaled) {
- lblock = offset / sdp->sd_jbsize;
- offset %= sdp->sd_jbsize;
- } else {
- lblock = offset >> sdp->sd_sb.sb_bsize_shift;
- offset &= sdp->sd_sb.sb_bsize - 1;
- }
-
- if (!ip->i_di.di_height) /* stuffed */
- offset += sizeof(struct gfs_dinode);
- else if (journaled)
- offset += sizeof(struct gfs2_meta_header);
-
- while (copied < size) {
- amount = size - copied;
- if (amount > sdp->bsize - offset)
- amount = sdp->bsize - offset;
-
- if (!extlen)
- gfs1_block_map(ip, lblock, ¬_new, &dblock,
- &extlen, FALSE);
-
- if (dblock) {
- bh = bread(sdp, dblock);
- dblock++;
- extlen--;
- } else
- bh = NULL;
-
-
- if (bh) {
- memcpy(buf+copied, bh->b_data + offset, amount);
- brelse(bh);
- } else
- memset(buf+copied, 0, amount);
- copied += amount;
- lblock++;
-
- offset = (journaled) ? sizeof(struct gfs2_meta_header) : 0;
- }
-
- return copied;
-}
-
-/**
- * gfs1_rindex_read - read in the rg index file
- * Stolen from libgfs2/super.c, but modified to handle gfs1.
- * @sdp: the incore superblock pointer
- * fd: optional file handle for rindex file (if meta_fs file system is mounted)
- * (if fd is <= zero, it will read from raw device)
- * @count1: return count of the rgs.
- *
- * Returns: 0 on success, -1 on failure
- */
-int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1)
-{
- unsigned int rg;
- int error;
- struct gfs2_rindex buf;
- struct rgrp_list *rgd, *prev_rgd;
- uint64_t prev_length = 0;
-
- *count1 = 0;
- prev_rgd = NULL;
- for (rg = 0; ; rg++) {
- if (fd > 0)
- error = read(fd, &buf, sizeof(struct gfs2_rindex));
- else
- error = gfs1_readi(sdp->md.riinode, (char *)&buf,
- (rg * sizeof(struct gfs2_rindex)),
- sizeof(struct gfs2_rindex));
- if (!error)
- break;
- if (error != sizeof(struct gfs2_rindex))
- return -1;
-
- rgd = (struct rgrp_list *)malloc(sizeof(struct rgrp_list));
- if (!rgd) {
- log_crit("Cannot allocate memory for rindex.\n");
- exit(-1);
- }
- memset(rgd, 0, sizeof(struct rgrp_list));
- osi_list_add_prev(&rgd->list, &sdp->rglist);
-
- gfs2_rindex_in(&rgd->ri, (char *)&buf);
-
- rgd->start = rgd->ri.ri_addr;
- if (prev_rgd) {
- prev_length = rgd->start - prev_rgd->start;
- prev_rgd->length = prev_length;
- }
-
- if(gfs2_compute_bitstructs(sdp, rgd))
- return -1;
-
- (*count1)++;
- prev_rgd = rgd;
- }
- if (prev_rgd)
- prev_rgd->length = prev_length;
- return 0;
-}
-
-/**
- * gfs1_ri_update - attach rgrps to the super block
- * Stolen from libgfs2/super.c, but modified to handle gfs1.
- * @sdp:
- *
- * Given the rgrp index inode, link in all rgrps into the super block
- * and be sure that they can be read.
- *
- * Returns: 0 on success, -1 on failure.
- */
-int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet)
-{
- struct rgrp_list *rgd;
- struct gfs2_rindex *ri;
- osi_list_t *tmp;
- int count1 = 0, count2 = 0;
- uint64_t errblock = 0;
- uint64_t rmax = 0;
-
- if (gfs1_rindex_read(sdp, fd, &count1))
- goto fail;
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- errblock = gfs2_rgrp_read(sdp, rgd);
- if (errblock)
- return errblock;
- count2++;
- if (!quiet && count2 % 100 == 0) {
- printf(".");
- fflush(stdout);
- }
- ri = &rgd->ri;
- if (ri->ri_data0 + ri->ri_data - 1 > rmax)
- rmax = ri->ri_data0 + ri->ri_data - 1;
- }
-
- sdp->fssize = rmax;
- *rgcount = count1;
- if (count1 != count2)
- goto fail;
-
- return 0;
-
- fail:
- gfs2_rgrp_free(&sdp->rglist);
- return -1;
-}
-
-/* ------------------------------------------------------------------------ */
-/* gfs_dinode_in */
-/* ------------------------------------------------------------------------ */
-static void gfs_dinode_in(struct gfs_dinode *di, struct gfs2_buffer_head *bh)
-{
- struct gfs_dinode *str = (struct gfs_dinode *)bh->b_data;
-
- gfs2_meta_header_in(&di->di_header, bh);
- gfs2_inum_in(&di->di_num, (char *)&str->di_num);
-
- di->di_mode = be32_to_cpu(str->di_mode);
- di->di_uid = be32_to_cpu(str->di_uid);
- di->di_gid = be32_to_cpu(str->di_gid);
- di->di_nlink = be32_to_cpu(str->di_nlink);
- di->di_size = be64_to_cpu(str->di_size);
- di->di_blocks = be64_to_cpu(str->di_blocks);
- di->di_atime = be64_to_cpu(str->di_atime);
- di->di_mtime = be64_to_cpu(str->di_mtime);
- di->di_ctime = be64_to_cpu(str->di_ctime);
- di->di_major = be32_to_cpu(str->di_major);
- di->di_minor = be32_to_cpu(str->di_minor);
- di->di_goal_dblk = be64_to_cpu(str->di_goal_dblk);
- di->di_goal_mblk = be64_to_cpu(str->di_goal_mblk);
- di->di_flags = be32_to_cpu(str->di_flags);
- di->di_payload_format = be32_to_cpu(str->di_payload_format);
- di->di_type = be16_to_cpu(str->di_type);
- di->di_height = be16_to_cpu(str->di_height);
- di->di_depth = be16_to_cpu(str->di_depth);
- di->di_entries = be32_to_cpu(str->di_entries);
- di->di_eattr = be64_to_cpu(str->di_eattr);
-}
-
-struct gfs2_inode *gfs_inode_get(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *bh)
-{
- struct gfs_dinode gfs1_dinode;
- struct gfs2_inode *ip;
-
- ip = calloc(1, sizeof(struct gfs2_inode));
- if (ip == NULL) {
- fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
- exit(-1);
- }
-
- gfs_dinode_in(&gfs1_dinode, bh);
- memcpy(&ip->i_di.di_header, &gfs1_dinode.di_header,
- sizeof(struct gfs2_meta_header));
- memcpy(&ip->i_di.di_num, &gfs1_dinode.di_num,
- sizeof(struct gfs2_inum));
- ip->i_di.di_mode = gfs1_dinode.di_mode;
- ip->i_di.di_uid = gfs1_dinode.di_uid;
- ip->i_di.di_gid = gfs1_dinode.di_gid;
- ip->i_di.di_nlink = gfs1_dinode.di_nlink;
- ip->i_di.di_size = gfs1_dinode.di_size;
- ip->i_di.di_blocks = gfs1_dinode.di_blocks;
- ip->i_di.di_atime = gfs1_dinode.di_atime;
- ip->i_di.di_mtime = gfs1_dinode.di_mtime;
- ip->i_di.di_ctime = gfs1_dinode.di_ctime;
- ip->i_di.di_major = gfs1_dinode.di_major;
- ip->i_di.di_minor = gfs1_dinode.di_minor;
- ip->i_di.di_goal_data = gfs1_dinode.di_goal_dblk;
- ip->i_di.di_goal_meta = gfs1_dinode.di_goal_mblk;
- ip->i_di.di_flags = gfs1_dinode.di_flags;
- ip->i_di.di_payload_format = gfs1_dinode.di_payload_format;
- ip->i_di.__pad1 = gfs1_dinode.di_type;
- ip->i_di.di_height = gfs1_dinode.di_height;
- ip->i_di.di_depth = gfs1_dinode.di_depth;
- ip->i_di.di_entries = gfs1_dinode.di_entries;
- ip->i_di.di_eattr = gfs1_dinode.di_eattr;
- ip->i_bh = bh;
- ip->i_sbd = sdp;
- ip->bh_owned = 0;
- return ip;
-}
-
-struct gfs2_inode *gfs_inode_read(struct gfs2_sbd *sdp, uint64_t di_addr)
-{
- struct gfs_dinode gfs1_dinode;
- struct gfs2_inode *ip;
-
- ip = calloc(1, sizeof(struct gfs2_inode));
- if (ip == NULL) {
- fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
- exit(-1);
- }
-
- ip->i_bh = bread(sdp, di_addr);
- gfs_dinode_in(&gfs1_dinode, ip->i_bh);
- memcpy(&ip->i_di.di_header, &gfs1_dinode.di_header,
- sizeof(struct gfs2_meta_header));
- memcpy(&ip->i_di.di_num, &gfs1_dinode.di_num,
- sizeof(struct gfs2_inum));
- ip->i_di.di_mode = gfs1_dinode.di_mode;
- ip->i_di.di_uid = gfs1_dinode.di_uid;
- ip->i_di.di_gid = gfs1_dinode.di_gid;
- ip->i_di.di_nlink = gfs1_dinode.di_nlink;
- ip->i_di.di_size = gfs1_dinode.di_size;
- ip->i_di.di_blocks = gfs1_dinode.di_blocks;
- ip->i_di.di_atime = gfs1_dinode.di_atime;
- ip->i_di.di_mtime = gfs1_dinode.di_mtime;
- ip->i_di.di_ctime = gfs1_dinode.di_ctime;
- ip->i_di.di_major = gfs1_dinode.di_major;
- ip->i_di.di_minor = gfs1_dinode.di_minor;
- ip->i_di.di_goal_data = gfs1_dinode.di_goal_dblk;
- ip->i_di.di_goal_meta = gfs1_dinode.di_goal_mblk;
- ip->i_di.di_flags = gfs1_dinode.di_flags;
- ip->i_di.di_payload_format = gfs1_dinode.di_payload_format;
- ip->i_di.__pad1 = gfs1_dinode.di_type;
- ip->i_di.di_height = gfs1_dinode.di_height;
- ip->i_di.di_depth = gfs1_dinode.di_depth;
- ip->i_di.di_entries = gfs1_dinode.di_entries;
- ip->i_di.di_eattr = gfs1_dinode.di_eattr;
- ip->i_sbd = sdp;
- ip->bh_owned = 1;
- return ip;
-}
-
diff --git a/gfs2/libgfs2/gfs2_disk_hash.c b/gfs2/libgfs2/gfs2_disk_hash.c
deleted file mode 100644
index 5da6103..0000000
--- a/gfs2/libgfs2/gfs2_disk_hash.c
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <stdio.h>
-#include "libgfs2.h"
-
-static const uint32_t crc_32_tab[] =
-{
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-/**
- * gfs2_disk_hash - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- *
- * This function must produce the same results as the one in the kernel:
- * crc32_le(0xFFFFFFFF, data, len) ^ 0xFFFFFFFF
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * The hash function is a 32-bit CRC of the data. The algorithm uses
- * the crc_32_tab table above.
- *
- * This may not be the fastest hash function, but it does a fair bit better
- * at providing uniform results than the others I've looked at. That's
- * really important for efficient directories.
- *
- * Returns: the hash
- */
-
-uint32_t gfs2_disk_hash(const char *data, int len)
-{
- uint32_t hash = 0xFFFFFFFF;
-
- for (; len--; data++)
- hash = crc_32_tab[(hash ^ *data) & 0xFF] ^ (hash >> 8);
-
- hash = ~hash;
-
- return hash;
-}
-
-
diff --git a/gfs2/libgfs2/gfs2_log.c b/gfs2/libgfs2/gfs2_log.c
deleted file mode 100644
index 75a06a7..0000000
--- a/gfs2/libgfs2/gfs2_log.c
+++ /dev/null
@@ -1,192 +0,0 @@
-#include <stdio.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <libintl.h>
-#include <sys/select.h>
-#include <signal.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "libgfs2.h"
-
-#define _(String) gettext(String)
-
-int print_level = MSG_NOTICE;
-
-void increase_verbosity(void)
-{
- print_level++;
-}
-
-void decrease_verbosity(void)
-{
- print_level--;
-}
-
-static __attribute__((format (printf, 4, 0)))
-void print_msg(int priority, const char *file, int line,
- const char *format, va_list args) {
-
- switch (priority) {
-
- case MSG_DEBUG:
- printf("(%s:%d) ", file, line);
- vprintf(format, args);
- break;
- case MSG_INFO:
- case MSG_NOTICE:
- case MSG_WARN:
- vprintf(format, args);
- fflush(NULL);
- break;
- case MSG_ERROR:
- case MSG_CRITICAL:
- default:
- vfprintf(stderr, format, args);
- break;
- }
-}
-
-
-void print_fsck_log(int priority, const char *file, int line,
- const char *format, ...)
-{
- va_list args;
- const char *transform;
-
- va_start(args, format);
- transform = _(format);
- print_msg(priority, file, line, transform, args);
- va_end(args);
-}
-
-char gfs2_getch(void)
-{
- struct termios termattr, savetermattr;
- char ch;
- ssize_t size;
-
- tcgetattr (STDIN_FILENO, &termattr);
- savetermattr = termattr;
- termattr.c_lflag &= ~(ICANON | IEXTEN | ISIG);
- termattr.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
- termattr.c_cflag &= ~(CSIZE | PARENB);
- termattr.c_cflag |= CS8;
- termattr.c_oflag &= ~(OPOST);
- termattr.c_cc[VMIN] = 0;
- termattr.c_cc[VTIME] = 0;
-
- tcsetattr (STDIN_FILENO, TCSANOW, &termattr);
- do {
- size = read(STDIN_FILENO, &ch, 1);
- if (size)
- break;
- usleep(50000);
- } while (!size);
-
- tcsetattr (STDIN_FILENO, TCSANOW, &savetermattr);
- return ch;
-}
-
-char generic_interrupt(const char *caller, const char *where,
- const char *progress, const char *question,
- const char *answers)
-{
- fd_set rfds;
- struct timeval tv;
- char response;
- int err, i;
-
- FD_ZERO(&rfds);
- FD_SET(STDIN_FILENO, &rfds);
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- /* Make sure there isn't extraneous input before asking the
- * user the question */
- while((err = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv))) {
- if(err < 0) {
- log_debug("Error in select() on stdin\n");
- break;
- }
- if(read(STDIN_FILENO, &response, sizeof(char)) < 0) {
- log_debug("Error in read() on stdin\n");
- break;
- }
- }
- while (TRUE) {
- printf("\n%s interrupted during %s: ", caller, where);
- if (progress)
- printf("%s.\n", progress);
- printf("%s", question);
-
- /* Make sure query is printed out */
- fflush(NULL);
- response = gfs2_getch();
- printf("\n");
- fflush(NULL);
- if (strchr(answers, response))
- break;
- printf("Bad response, please type ");
- for (i = 0; i < strlen(answers) - 1; i++)
- printf("'%c', ", answers[i]);
- printf(" or '%c'.\n", answers[i]);
- }
- return response;
-}
-
-int gfs2_query(int *setonabort, struct gfs2_options *opts,
- const char *format, ...)
-{
- va_list args;
- const char *transform;
- char response;
- int ret = 0;
-
- *setonabort = 0;
- if(opts->yes)
- return 1;
- if(opts->no)
- return 0;
-
- opts->query = TRUE;
- while (1) {
- va_start(args, format);
- transform = _(format);
- vprintf(transform, args);
- va_end(args);
-
- /* Make sure query is printed out */
- fflush(NULL);
- response = gfs2_getch();
-
- printf("\n");
- fflush(NULL);
- if (response == 0x3) { /* if interrupted, by ctrl-c */
- response = generic_interrupt("Question", "response",
- NULL,
- "Do you want to abort " \
- "or continue (a/c)?",
- "ac");
- if (response == 'a') {
- ret = 0;
- *setonabort = 1;
- break;
- }
- printf("Continuing.\n");
- } else if(tolower(response) == 'y') {
- ret = 1;
- break;
- } else if (tolower(response) == 'n') {
- ret = 0;
- break;
- } else {
- printf("Bad response %d, please type 'y' or 'n'.\n",
- response);
- }
- }
-
- opts->query = FALSE;
- return ret;
-}
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
deleted file mode 100644
index c798bda..0000000
--- a/gfs2/libgfs2/libgfs2.h
+++ /dev/null
@@ -1,745 +0,0 @@
-#ifndef __LIBGFS2_DOT_H__
-#define __LIBGFS2_DOT_H__
-
-#include <features.h>
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <linux/types.h>
-#include <linux/limits.h>
-#include <endian.h>
-#include <byteswap.h>
-
-#include <linux/gfs2_ondisk.h>
-#include "osi_list.h"
-
-__BEGIN_DECLS
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-
-#define be16_to_cpu(x) (x)
-#define be32_to_cpu(x) (x)
-#define be64_to_cpu(x) (x)
-
-#define cpu_to_be16(x) (x)
-#define cpu_to_be32(x) (x)
-#define cpu_to_be64(x) (x)
-
-#define le16_to_cpu(x) (bswap_16((x)))
-#define le32_to_cpu(x) (bswap_32((x)))
-#define le64_to_cpu(x) (bswap_64((x)))
-
-#define cpu_to_le16(x) (bswap_16((x)))
-#define cpu_to_le32(x) (bswap_32((x)))
-#define cpu_to_le64(x) (bswap_64((x)))
-
-#endif /* __BYTE_ORDER == __BIG_ENDIAN */
-
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-
-#define be16_to_cpu(x) (bswap_16((x)))
-#define be32_to_cpu(x) (bswap_32((x)))
-#define be64_to_cpu(x) (bswap_64((x)))
-
-#define cpu_to_be16(x) (bswap_16((x)))
-#define cpu_to_be32(x) (bswap_32((x)))
-#define cpu_to_be64(x) (bswap_64((x)))
-
-#define le16_to_cpu(x) (x)
-#define le32_to_cpu(x) (x)
-#define le64_to_cpu(x) (x)
-
-#define cpu_to_le16(x) (x)
-#define cpu_to_le32(x) (x)
-#define cpu_to_le64(x) (x)
-
-#endif /* __BYTE_ORDER == __LITTLE_ENDIAN */
-
-#define BLOCKMAP_SIZE4(size) (size >> 1)
-#define BLOCKMAP_BYTE_OFFSET4(x) ((x & 0x0000000000000001) << 2)
-#define BLOCKMAP_MASK4 (0xf)
-
-static __inline__ __attribute__((noreturn, format (printf, 1, 2)))
-void die(const char *fmt, ...)
-{
- va_list ap;
- fprintf(stderr, "%s: ", __FILE__);
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- exit(-1);
-}
-
-struct device {
- uint64_t start;
- uint64_t length;
- uint32_t rgf_flags;
-};
-
-struct gfs2_bitmap
-{
- uint32_t bi_offset; /* The offset in the buffer of the first byte */
- uint32_t bi_start; /* The position of the first byte in this block */
- uint32_t bi_len; /* The number of bytes in this block */
-};
-
-struct rgrp_list {
- osi_list_t list;
- uint64_t start; /* The offset of the beginning of this resource group */
- uint64_t length; /* The length of this resource group */
-
- struct gfs2_rindex ri;
- struct gfs2_rgrp rg;
- struct gfs2_bitmap *bits;
- struct gfs2_buffer_head **bh;
-};
-
-struct gfs2_buffer_head {
- osi_list_t b_altlist; /* alternate list */
- uint64_t b_blocknr;
- int b_modified;
- char *b_data;
- struct gfs2_sbd *sdp;
-};
-
-struct special_blocks {
- osi_list_t list;
- uint64_t block;
-};
-
-struct gfs2_sbd;
-struct gfs2_inode {
- int bh_owned; /* Is this bh owned, iow, should we release it later? */
- struct gfs2_dinode i_di;
- struct gfs2_buffer_head *i_bh;
- struct gfs2_sbd *i_sbd;
-};
-
-#define BUF_HASH_SHIFT (13) /* # hash buckets = 8K */
-#define BUF_HASH_SIZE (1 << BUF_HASH_SHIFT)
-#define BUF_HASH_MASK (BUF_HASH_SIZE - 1)
-
-/* FIXME not sure that i want to keep a record of the inodes or the
- * contents of them, or both ... if I need to write back to them, it
- * would be easier to hold the inode as well */
-struct per_node
-{
- struct gfs2_inode *inum;
- struct gfs2_inum_range inum_range;
- struct gfs2_inode *statfs;
- struct gfs2_statfs_change statfs_change;
- struct gfs2_inode *unlinked;
- struct gfs2_inode *quota;
- struct gfs2_quota_change quota_change;
-};
-
-struct master_dir
-{
- struct gfs2_inode *inum;
- uint64_t next_inum;
- struct gfs2_inode *statfs;
- struct gfs2_statfs_change statfs_change;
-
- struct gfs2_rindex rindex;
- struct gfs2_inode *qinode;
- struct gfs2_quota quotas;
-
- struct gfs2_inode *jiinode;
- struct gfs2_inode *riinode;
- struct gfs2_inode *rooti;
- struct gfs2_inode *pinode;
-
- struct gfs2_inode **journal; /* Array of journals */
- uint32_t journals; /* Journal count */
- struct per_node *pn; /* Array of per_node entries */
-};
-
-struct gfs2_sbd {
- struct gfs2_sb sd_sb; /* a copy of the ondisk structure */
- char lockproto[GFS2_LOCKNAME_LEN];
- char locktable[GFS2_LOCKNAME_LEN];
-
- unsigned int bsize; /* The block size of the FS (in bytes) */
- unsigned int jsize; /* Size of journals (in MB) */
- unsigned int rgsize; /* Size of resource groups (in MB) */
- unsigned int utsize; /* Size of unlinked tag files (in MB) */
- unsigned int qcsize; /* Size of quota change files (in MB) */
-
- int debug;
- int quiet;
- int expert;
- int override;
-
- char device_name[PATH_MAX];
- char *path_name;
-
- /* Constants */
-
- uint32_t sd_fsb2bb;
- uint32_t sd_fsb2bb_shift;
- uint32_t sd_diptrs;
- uint32_t sd_inptrs;
- uint32_t sd_jbsize;
- uint32_t sd_hash_bsize;
- uint32_t sd_hash_bsize_shift;
- uint32_t sd_hash_ptrs;
- uint32_t sd_max_dirres;
- uint32_t sd_max_height;
- uint64_t sd_heightsize[GFS2_MAX_META_HEIGHT];
- uint32_t sd_max_jheight;
- uint64_t sd_jheightsize[GFS2_MAX_META_HEIGHT];
-
- /* Not specified on the command line, but... */
-
- int64_t time;
-
- struct device device;
- uint64_t device_size;
-
- int device_fd;
- int path_fd;
-
- uint64_t sb_addr;
-
- uint64_t orig_fssize;
- uint64_t fssize;
- uint64_t blks_total;
- uint64_t blks_alloced;
- uint64_t dinodes_alloced;
-
- uint64_t orig_rgrps;
- uint64_t rgrps;
- uint64_t new_rgrps;
- osi_list_t rglist;
-
- unsigned int orig_journals;
-
- struct gfs2_inode *master_dir;
- struct master_dir md;
-
- unsigned int writes;
- int metafs_fd;
- char metafs_path[PATH_MAX]; /* where metafs is mounted */
- struct special_blocks eattr_blocks;
-
- /* device topology information: */
- uint32_t logical_block_size;
- uint32_t minimum_io_size;
- uint32_t optimal_io_size;
- uint32_t alignment_offset;
- uint32_t physical_block_size;
- uint64_t rg_one_length;
- uint64_t rg_length;
-};
-
-struct metapath {
- unsigned int mp_list[GFS2_MAX_META_HEIGHT];
-};
-
-
-#define GFS2_DEFAULT_BSIZE (4096)
-#define GFS2_DEFAULT_JSIZE (128)
-#define GFS2_DEFAULT_RGSIZE (256)
-#define GFS2_DEFAULT_UTSIZE (1)
-#define GFS2_DEFAULT_QCSIZE (1)
-#define GFS2_DEFAULT_LOCKPROTO "lock_dlm"
-#define GFS2_MIN_GROW_SIZE (10)
-#define GFS2_EXCESSIVE_RGS (10000)
-
-#define DATA (1)
-#define META (2)
-#define DINODE (3)
-
-/* bitmap.c */
-struct gfs2_bmap {
- uint64_t size;
- uint64_t mapsize;
- unsigned char *map;
-};
-
-/* block_list.c */
-
-enum gfs2_mark_block {
- gfs2_block_free = (0x0),
- gfs2_block_used = (0x1),
- gfs2_indir_blk = (0x2),
- gfs2_inode_dir = (0x3),
- gfs2_inode_file = (0x4),
-
- gfs2_inode_lnk = (0x5),
- gfs2_inode_blk = (0x6),
- gfs2_inode_chr = (0x7),
- gfs2_inode_fifo = (0x8),
- gfs2_inode_sock = (0x9),
-
- gfs2_inode_invalid = (0xa),
- gfs2_meta_inval = (0xb),
- gfs2_leaf_blk = (0xc),
- gfs2_meta_rgrp = (0xd),
- gfs2_meta_eattr = (0xe),
-
- gfs2_bad_block = (0xf), /* Contains at least one bad block */
-};
-
-static const inline char *block_type_string(uint8_t q)
-{
- const char *blktyp[] = {
- "free",
- "data",
- "indirect data",
- "directory",
- "file",
-
- "symlink",
- "block device",
- "char device",
- "fifo",
- "socket",
-
- "invalid inode",
- "invalid meta",
- "dir leaf",
- "rgrp meta",
- "eattribute",
-
- "bad"};
- if (q < 16)
- return (blktyp[q]);
- return blktyp[15];
-}
-
-/* Must be kept in sync with gfs2_mark_block enum above. Blocks marked as
- invalid or bad are considered metadata until actually freed. */
-static inline int blockmap_to_bitmap(enum gfs2_mark_block m)
-{
- static int bitmap_states[16] = {
- GFS2_BLKST_FREE,
- GFS2_BLKST_USED,
- GFS2_BLKST_USED,
- GFS2_BLKST_DINODE,
- GFS2_BLKST_DINODE,
-
- GFS2_BLKST_DINODE,
- GFS2_BLKST_DINODE,
- GFS2_BLKST_DINODE,
- GFS2_BLKST_DINODE,
- GFS2_BLKST_DINODE,
-
- GFS2_BLKST_FREE,
- GFS2_BLKST_FREE,
- GFS2_BLKST_USED,
- GFS2_BLKST_USED,
- GFS2_BLKST_USED,
-
- GFS2_BLKST_USED
- };
- return bitmap_states[m];
-}
-
-extern struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size,
- uint64_t *addl_mem_needed);
-extern struct special_blocks *blockfind(struct special_blocks *blist, uint64_t num);
-extern void gfs2_special_add(struct special_blocks *blocklist, uint64_t block);
-extern void gfs2_special_set(struct special_blocks *blocklist, uint64_t block);
-extern void gfs2_special_free(struct special_blocks *blist);
-extern int gfs2_blockmap_set(struct gfs2_bmap *il, uint64_t block,
- enum gfs2_mark_block mark);
-extern void gfs2_special_clear(struct special_blocks *blocklist,
- uint64_t block);
-extern void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il);
-
-/* buf.c */
-extern struct gfs2_buffer_head *__bget_generic(struct gfs2_sbd *sdp,
- uint64_t num,
- int read_disk, int line,
- const char *caller);
-extern struct gfs2_buffer_head *__bget(struct gfs2_sbd *sdp, uint64_t num,
- int line, const char *caller);
-extern struct gfs2_buffer_head *__bread(struct gfs2_sbd *sdp, uint64_t num,
- int line, const char *caller);
-extern int bwrite(struct gfs2_buffer_head *bh);
-extern int brelse(struct gfs2_buffer_head *bh);
-
-#define bmodified(bh) do { bh->b_modified = 1; } while(0)
-
-#define bget_generic(bl, num, find, read) __bget_generic(bl, num, find, read, \
- __LINE__, \
- __FUNCTION__)
-#define bget(bl, num) __bget(bl, num, __LINE__, __FUNCTION__)
-#define bread(bl, num) __bread(bl, num, __LINE__, __FUNCTION__)
-#define bsync(bl) do { __bsync(bl, __LINE__, __FUNCTION__); } while(0)
-#define bcommit(bl) do { __bcommit(bl, __LINE__, __FUNCTION__); } while(0)
-
-/* device_geometry.c */
-extern int device_topology(struct gfs2_sbd *sdp);
-extern int device_geometry(struct gfs2_sbd *sdp);
-extern int fix_device_geometry(struct gfs2_sbd *sdp);
-
-/* fs_bits.c */
-#define BFITNOENT (0xFFFFFFFF)
-
-/* functions with blk #'s that are buffer relative */
-extern uint32_t gfs2_bitcount(unsigned char *buffer, unsigned int buflen,
- unsigned char state);
-extern unsigned long gfs2_bitfit(const unsigned char *buffer,
- const unsigned int buflen,
- unsigned long goal, unsigned char old_state);
-
-/* functions with blk #'s that are rgrp relative */
-extern uint32_t gfs2_blkalloc_internal(struct rgrp_list *rgd, uint32_t goal,
- unsigned char old_state,
- unsigned char new_state, int do_it);
-extern int gfs2_check_range(struct gfs2_sbd *sdp, uint64_t blkno);
-
-/* functions with blk #'s that are file system relative */
-extern int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno,
- struct rgrp_list *rgd);
-extern int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state);
-
-/* fs_geometry.c */
-extern void rgblocks2bitblocks(unsigned int bsize, uint32_t *rgblocks,
- uint32_t *bitblocks);
-extern void compute_rgrp_layout(struct gfs2_sbd *sdp, int rgsize_specified);
-extern void build_rgrps(struct gfs2_sbd *sdp, int write);
-
-/* fs_ops.c */
-#define IS_LEAF (1)
-#define IS_DINODE (2)
-
-extern struct metapath *find_metapath(struct gfs2_inode *ip, uint64_t block);
-extern void lookup_block(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
- unsigned int height, struct metapath *mp,
- int create, int *new, uint64_t *block);
-extern struct gfs2_inode *inode_get(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *bh);
-extern struct gfs2_inode *inode_read(struct gfs2_sbd *sdp, uint64_t di_addr);
-extern struct gfs2_inode *is_system_inode(struct gfs2_sbd *sdp,
- uint64_t block);
-extern void inode_put(struct gfs2_inode **ip);
-extern uint64_t data_alloc(struct gfs2_inode *ip);
-extern uint64_t meta_alloc(struct gfs2_inode *ip);
-extern uint64_t dinode_alloc(struct gfs2_sbd *sdp);
-extern int gfs2_readi(struct gfs2_inode *ip, void *buf, uint64_t offset,
- unsigned int size);
-extern int gfs2_writei(struct gfs2_inode *ip, void *buf, uint64_t offset,
- unsigned int size);
-extern struct gfs2_buffer_head *get_file_buf(struct gfs2_inode *ip,
- uint64_t lbn, int prealloc);
-extern struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp,
- struct gfs2_inum *inum,
- unsigned int mode, uint32_t flags,
- struct gfs2_inum *parent);
-extern struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename,
- unsigned int mode, uint32_t flags);
-extern void dirent2_del(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
- struct gfs2_dirent *prev, struct gfs2_dirent *cur);
-extern int dir_search(struct gfs2_inode *dip, const char *filename, int len,
- unsigned int *type, struct gfs2_inum *inum);
-extern int gfs2_lookupi(struct gfs2_inode *dip, const char *filename, int len,
- struct gfs2_inode **ipp);
-extern void dir_add(struct gfs2_inode *dip, const char *filename, int len,
- struct gfs2_inum *inum, unsigned int type);
-extern int gfs2_dirent_del(struct gfs2_inode *dip, const char *filename,
- int filename_len);
-extern void block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
- uint64_t *dblock, uint32_t *extlen, int prealloc);
-extern void gfs2_get_leaf_nr(struct gfs2_inode *dip, uint32_t index,
- uint64_t *leaf_out);
-extern void gfs2_put_leaf_nr(struct gfs2_inode *dip, uint32_t inx, uint64_t leaf_out);
-extern void gfs2_free_block(struct gfs2_sbd *sdp, uint64_t block);
-extern int gfs2_freedi(struct gfs2_sbd *sdp, uint64_t block);
-extern int gfs2_get_leaf(struct gfs2_inode *dip, uint64_t leaf_no,
- struct gfs2_buffer_head **bhp);
-extern int gfs2_dirent_first(struct gfs2_inode *dip,
- struct gfs2_buffer_head *bh,
- struct gfs2_dirent **dent);
-extern int gfs2_dirent_next(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
- struct gfs2_dirent **dent);
-extern void build_height(struct gfs2_inode *ip, int height);
-extern void unstuff_dinode(struct gfs2_inode *ip);
-extern unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size);
-extern int write_journal(struct gfs2_sbd *sdp, unsigned int j,
- unsigned int blocks);
-
-/**
- * device_size - figure out a device's size
- * @fd: the file descriptor of a device
- * @bytes: the number of bytes the device holds
- *
- * Returns: -1 on error (with errno set), 0 on success (with @bytes set)
- */
-
-extern int device_size(int fd, uint64_t *bytes);
-
-/* gfs1.c - GFS1 backward compatibility functions */
-struct gfs_indirect {
- struct gfs2_meta_header in_header;
-
- char in_reserved[64];
-};
-
-struct gfs_dinode {
- struct gfs2_meta_header di_header;
-
- struct gfs2_inum di_num; /* formal inode # and block address */
-
- uint32_t di_mode; /* mode of file */
- uint32_t di_uid; /* owner's user id */
- uint32_t di_gid; /* owner's group id */
- uint32_t di_nlink; /* number (qty) of links to this file */
- uint64_t di_size; /* number (qty) of bytes in file */
- uint64_t di_blocks; /* number (qty) of blocks in file */
- int64_t di_atime; /* time last accessed */
- int64_t di_mtime; /* time last modified */
- int64_t di_ctime; /* time last changed */
-
- /* Non-zero only for character or block device nodes */
- uint32_t di_major; /* device major number */
- uint32_t di_minor; /* device minor number */
-
- /* Block allocation strategy */
- uint64_t di_rgrp; /* dinode rgrp block number */
- uint64_t di_goal_rgrp; /* rgrp to alloc from next */
- uint32_t di_goal_dblk; /* data block goal */
- uint32_t di_goal_mblk; /* metadata block goal */
-
- uint32_t di_flags; /* GFS_DIF_... */
-
- /* struct gfs_rindex, struct gfs_jindex, or struct gfs_dirent */
- uint32_t di_payload_format; /* GFS_FORMAT_... */
- uint16_t di_type; /* GFS_FILE_... type of file */
- uint16_t di_height; /* height of metadata (0 == stuffed) */
- uint32_t di_incarn; /* incarnation (unused, see gfs_meta_header) */
- uint16_t di_pad;
-
- /* These only apply to directories */
- uint16_t di_depth; /* Number of bits in the table */
- uint32_t di_entries; /* The # (qty) of entries in the directory */
-
- /* This formed an on-disk chain of unused dinodes */
- struct gfs2_inum di_next_unused; /* used in old versions only */
-
- uint64_t di_eattr; /* extended attribute block number */
-
- char di_reserved[56];
-};
-
-extern void gfs1_lookup_block(struct gfs2_inode *ip,
- struct gfs2_buffer_head *bh,
- unsigned int height, struct metapath *mp,
- int create, int *new, uint64_t *block);
-extern void gfs1_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
- uint64_t *dblock, uint32_t *extlen, int prealloc);
-extern int gfs1_readi(struct gfs2_inode *ip, void *buf, uint64_t offset,
- unsigned int size);
-extern int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1);
-extern int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet);
-extern struct gfs2_inode *gfs_inode_get(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *bh);
-extern struct gfs2_inode *gfs_inode_read(struct gfs2_sbd *sdp,
- uint64_t di_addr);
-
-/* gfs2_log.c */
-struct gfs2_options {
- char *device;
- unsigned int yes:1;
- unsigned int no:1;
- unsigned int query:1;
-};
-
-extern int print_level;
-
-#define MSG_DEBUG 7
-#define MSG_INFO 6
-#define MSG_NOTICE 5
-#define MSG_WARN 4
-#define MSG_ERROR 3
-#define MSG_CRITICAL 2
-#define MSG_NULL 1
-
-#define print_log(priority, format...) \
- do { print_fsck_log(priority, __FILE__, __LINE__, ## format); } while(0)
-
-#define log_debug(format...) \
- do { if(print_level >= MSG_DEBUG) print_log(MSG_DEBUG, format); } while(0)
-#define log_info(format...) \
- do { if(print_level >= MSG_INFO) print_log(MSG_INFO, format); } while(0)
-
-#define log_notice(format...) \
- do { if(print_level >= MSG_NOTICE) print_log(MSG_NOTICE, format); } while(0)
-
-#define log_warn(format...) \
- do { if(print_level >= MSG_WARN) print_log(MSG_WARN, format); } while(0)
-
-#define log_err(format...) \
- do { if(print_level >= MSG_ERROR) print_log(MSG_ERROR, format); } while(0)
-
-#define log_crit(format...) \
- do { if(print_level >= MSG_CRITICAL) print_log(MSG_CRITICAL, format); } while(0)
-
-#define stack log_debug("<backtrace> - %s()\n", __func__)
-
-extern char gfs2_getch(void);
-extern void increase_verbosity(void);
-extern void decrease_verbosity(void);
-extern void print_fsck_log(int priority, const char *file, int line,
- const char *format, ...)
- __attribute__((format(printf,4,5)));
-extern char generic_interrupt(const char *caller, const char *where,
- const char *progress, const char *question,
- const char *answers);
-extern int gfs2_query(int *setonabort, struct gfs2_options *opts,
- const char *format, ...)
- __attribute__((format(printf,3,4)));
-
-/* misc.c */
-
-extern int compute_heightsize(struct gfs2_sbd *sdp, uint64_t *heightsize,
- uint32_t *maxheight, uint32_t bsize1, int diptrs, int inptrs);
-extern int compute_constants(struct gfs2_sbd *sdp);
-extern int is_pathname_mounted(struct gfs2_sbd *sdp, int *ro_mount);
-extern int is_gfs2(struct gfs2_sbd *sdp);
-extern int find_gfs2_meta(struct gfs2_sbd *sdp);
-extern int dir_exists(const char *dir);
-extern int check_for_gfs2(struct gfs2_sbd *sdp);
-extern int mount_gfs2_meta(struct gfs2_sbd *sdp);
-extern void cleanup_metafs(struct gfs2_sbd *sdp);
-extern char *find_debugfs_mount(void);
-extern char *mp2fsname(char *mp);
-extern char *get_sysfs(const char *fsname, const char *filename);
-extern int get_sysfs_uint(const char *fsname, const char *filename, unsigned int *val);
-extern int set_sysfs(const char *fsname, const char *filename, const char *val);
-extern int is_fsname(char *name);
-extern void get_random_bytes(void *buf, int nbytes);
-
-/* recovery.c */
-extern void gfs2_replay_incr_blk(struct gfs2_inode *ip, unsigned int *blk);
-extern int gfs2_replay_read_block(struct gfs2_inode *ip, unsigned int blk,
- struct gfs2_buffer_head **bh);
-extern int gfs2_revoke_add(struct gfs2_sbd *sdp, uint64_t blkno, unsigned int where);
-extern int gfs2_revoke_check(struct gfs2_sbd *sdp, uint64_t blkno,
- unsigned int where);
-extern void gfs2_revoke_clean(struct gfs2_sbd *sdp);
-extern int get_log_header(struct gfs2_inode *ip, unsigned int blk,
- struct gfs2_log_header *head);
-extern int find_good_lh(struct gfs2_inode *ip, unsigned int *blk,
- struct gfs2_log_header *head);
-extern int jhead_scan(struct gfs2_inode *ip, struct gfs2_log_header *head);
-extern int gfs2_find_jhead(struct gfs2_inode *ip, struct gfs2_log_header *head);
-extern int clean_journal(struct gfs2_inode *ip, struct gfs2_log_header *head);
-
-/* rgrp.c */
-extern int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd);
-extern struct rgrp_list *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk);
-extern uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd);
-extern void gfs2_rgrp_relse(struct rgrp_list *rgd);
-extern void gfs2_rgrp_free(osi_list_t *rglist);
-
-/* structures.c */
-extern int build_master(struct gfs2_sbd *sdp);
-extern void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid);
-extern int build_journal(struct gfs2_sbd *sdp, int j,
- struct gfs2_inode *jindex);
-extern int build_jindex(struct gfs2_sbd *sdp);
-extern int build_per_node(struct gfs2_sbd *sdp);
-extern int build_inum(struct gfs2_sbd *sdp);
-extern int build_statfs(struct gfs2_sbd *sdp);
-extern int build_rindex(struct gfs2_sbd *sdp);
-extern int build_quota(struct gfs2_sbd *sdp);
-extern int build_root(struct gfs2_sbd *sdp);
-extern int do_init_inum(struct gfs2_sbd *sdp);
-extern int do_init_statfs(struct gfs2_sbd *sdp);
-extern int gfs2_check_meta(struct gfs2_buffer_head *bh, int type);
-extern int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block,
- int first);
-extern int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
- uint64_t *block, uint32_t type, int first);
-/* super.c */
-extern int check_sb(struct gfs2_sb *sb);
-extern int read_sb(struct gfs2_sbd *sdp);
-extern int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane);
-extern int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int *sane);
-extern int write_sb(struct gfs2_sbd *sdp);
-
-/* ondisk.c */
-extern uint32_t gfs2_disk_hash(const char *data, int len);
-extern const char *str_uuid(const unsigned char *uuid);
-extern void gfs2_print_uuid(const unsigned char *uuid);
-extern void print_it(const char *label, const char *fmt, const char *fmt2, ...)
- __attribute__((format(printf,2,4)));
-
-/* Translation functions */
-
-extern void gfs2_inum_in(struct gfs2_inum *no, char *buf);
-extern void gfs2_inum_out(struct gfs2_inum *no, char *buf);
-extern void gfs2_meta_header_in(struct gfs2_meta_header *mh,
- struct gfs2_buffer_head *bh);
-extern void gfs2_meta_header_out(struct gfs2_meta_header *mh,
- struct gfs2_buffer_head *bh);
-extern void gfs2_sb_in(struct gfs2_sb *sb, struct gfs2_buffer_head *bh);
-extern void gfs2_sb_out(struct gfs2_sb *sb, struct gfs2_buffer_head *bh);
-extern void gfs2_rindex_in(struct gfs2_rindex *ri, char *buf);
-extern void gfs2_rindex_out(struct gfs2_rindex *ri, char *buf);
-extern void gfs2_rgrp_in(struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh);
-extern void gfs2_rgrp_out(struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh);
-extern void gfs2_quota_in(struct gfs2_quota *qu, char *buf);
-extern void gfs2_quota_out(struct gfs2_quota *qu, char *buf);
-extern void gfs2_dinode_in(struct gfs2_dinode *di,
- struct gfs2_buffer_head *bh);
-extern void gfs2_dinode_out(struct gfs2_dinode *di,
- struct gfs2_buffer_head *bh);
-extern void gfs2_dirent_in(struct gfs2_dirent *de, char *buf);
-extern void gfs2_dirent_out(struct gfs2_dirent *de, char *buf);
-extern void gfs2_leaf_in(struct gfs2_leaf *lf, struct gfs2_buffer_head *bh);
-extern void gfs2_leaf_out(struct gfs2_leaf *lf, struct gfs2_buffer_head *bh);
-extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, char *buf);
-extern void gfs2_ea_header_out(struct gfs2_ea_header *ea, char *buf);
-extern void gfs2_log_header_in(struct gfs2_log_header *lh,
- struct gfs2_buffer_head *bh);
-extern void gfs2_log_header_out(struct gfs2_log_header *lh,
- struct gfs2_buffer_head *bh);
-extern void gfs2_log_descriptor_in(struct gfs2_log_descriptor *ld,
- struct gfs2_buffer_head *bh);
-extern void gfs2_log_descriptor_out(struct gfs2_log_descriptor *ld,
- struct gfs2_buffer_head *bh);
-extern void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, char *buf);
-extern void gfs2_statfs_change_out(struct gfs2_statfs_change *sc, char *buf);
-extern void gfs2_quota_change_in(struct gfs2_quota_change *qc,
- struct gfs2_buffer_head *bh);
-extern void gfs2_quota_change_out(struct gfs2_quota_change *qc,
- struct gfs2_buffer_head *bh);
-
-/* Printing functions */
-
-extern void gfs2_inum_print(struct gfs2_inum *no);
-extern void gfs2_meta_header_print(struct gfs2_meta_header *mh);
-extern void gfs2_sb_print(struct gfs2_sb *sb);
-extern void gfs2_rindex_print(struct gfs2_rindex *ri);
-extern void gfs2_rgrp_print(struct gfs2_rgrp *rg);
-extern void gfs2_quota_print(struct gfs2_quota *qu);
-extern void gfs2_dinode_print(struct gfs2_dinode *di);
-extern void gfs2_dirent_print(struct gfs2_dirent *de, char *name);
-extern void gfs2_leaf_print(struct gfs2_leaf *lf);
-extern void gfs2_ea_header_print(struct gfs2_ea_header *ea, char *name);
-extern void gfs2_log_header_print(struct gfs2_log_header *lh);
-extern void gfs2_log_descriptor_print(struct gfs2_log_descriptor *ld);
-extern void gfs2_statfs_change_print(struct gfs2_statfs_change *sc);
-extern void gfs2_quota_change_print(struct gfs2_quota_change *qc);
-
-__END_DECLS
-
-#endif /* __LIBGFS2_DOT_H__ */
diff --git a/gfs2/libgfs2/misc.c b/gfs2/libgfs2/misc.c
deleted file mode 100644
index 31fc665..0000000
--- a/gfs2/libgfs2/misc.c
+++ /dev/null
@@ -1,459 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#include <sys/mount.h>
-#include <linux/types.h>
-#include <sys/file.h>
-#include <dirent.h>
-#include <linux/kdev_t.h>
-#include <sys/sysmacros.h>
-#include <mntent.h>
-#include <sys/time.h>
-
-#include "libgfs2.h"
-
-#define PAGE_SIZE (4096)
-#define SYS_BASE "/sys/fs/gfs2" /* FIXME: Look in /proc/mounts to find this */
-#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
-
-static char sysfs_buf[PAGE_SIZE];
-
-int compute_heightsize(struct gfs2_sbd *sdp, uint64_t *heightsize,
- uint32_t *maxheight, uint32_t bsize1, int diptrs, int inptrs)
-{
- heightsize[0] = sdp->bsize - sizeof(struct gfs2_dinode);
- heightsize[1] = bsize1 * diptrs;
- for (*maxheight = 2;; (*maxheight)++) {
- uint64_t space, d;
- uint32_t m;
-
- space = heightsize[*maxheight - 1] * inptrs;
- m = space % inptrs;
- d = space / inptrs;
-
- if (d != heightsize[*maxheight - 1] || m)
- break;
- heightsize[*maxheight] = space;
- }
- if (*maxheight > GFS2_MAX_META_HEIGHT) {
- errno = EINVAL;
- return -1;
- }
- return 0;
-}
-
-int compute_constants(struct gfs2_sbd *sdp)
-{
- uint32_t hash_blocks, ind_blocks, leaf_blocks;
- uint32_t tmp_blocks;
-
- sdp->md.next_inum = 1;
-
- sdp->sd_sb.sb_bsize_shift = ffs(sdp->bsize) - 1;
- sdp->sb_addr = GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sdp->bsize;
-
- sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift -
- GFS2_BASIC_BLOCK_SHIFT;
- sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;
- sdp->sd_diptrs = (sdp->bsize - sizeof(struct gfs2_dinode)) /
- sizeof(uint64_t);
- sdp->sd_inptrs = (sdp->bsize - sizeof(struct gfs2_meta_header)) /
- sizeof(uint64_t);
- sdp->sd_jbsize = sdp->bsize - sizeof(struct gfs2_meta_header);
- sdp->sd_hash_bsize = sdp->bsize / 2;
- sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1;
- sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
-
- /* Compute maximum reservation required to add a entry to a directory */
-
- hash_blocks = DIV_RU(sizeof(uint64_t) * (1 << GFS2_DIR_MAX_DEPTH),
- sdp->sd_jbsize);
-
- ind_blocks = 0;
- for (tmp_blocks = hash_blocks; tmp_blocks > sdp->sd_diptrs;) {
- tmp_blocks = DIV_RU(tmp_blocks, sdp->sd_inptrs);
- ind_blocks += tmp_blocks;
- }
-
- leaf_blocks = 2 + GFS2_DIR_MAX_DEPTH;
-
- sdp->sd_max_dirres = hash_blocks + ind_blocks + leaf_blocks;
-
- if (compute_heightsize(sdp, sdp->sd_heightsize, &sdp->sd_max_height,
- sdp->bsize, sdp->sd_diptrs, sdp->sd_inptrs)) {
- return -1;
- }
- if (compute_heightsize(sdp, sdp->sd_jheightsize, &sdp->sd_max_jheight,
- sdp->sd_jbsize, sdp->sd_diptrs, sdp->sd_inptrs)) {
- return -1;
- }
- return 0;
-}
-
-int is_pathname_mounted(struct gfs2_sbd *sdp, int *ro_mount)
-{
- FILE *fp;
- struct mntent *mnt;
- dev_t file_dev=0, file_rdev=0;
- ino_t file_ino=0;
- struct stat st_buf;
-
- *ro_mount = 0;
- if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
- perror("open: /proc/mounts");
- return 0;
- }
- if (stat(sdp->path_name, &st_buf) == 0) {
- if (S_ISBLK(st_buf.st_mode)) {
- file_rdev = st_buf.st_rdev;
- } else {
- file_dev = st_buf.st_dev;
- file_ino = st_buf.st_ino;
- }
- }
- while ((mnt = getmntent (fp)) != NULL) {
- /* Check if they specified the device instead of mnt point */
- if (strcmp(sdp->device_name, mnt->mnt_fsname) == 0) {
- strcpy(sdp->path_name, mnt->mnt_dir); /* fix it */
- break;
- }
- if (strcmp(sdp->path_name, mnt->mnt_dir) == 0) {
- strcpy(sdp->device_name, mnt->mnt_fsname); /* fix it */
- break;
- }
- if (stat(mnt->mnt_fsname, &st_buf) != 0)
- continue;
-
- if (S_ISBLK(st_buf.st_mode)) {
- if (file_rdev && (file_rdev == st_buf.st_rdev)) {
- strcpy(sdp->device_name, mnt->mnt_fsname);
- strcpy(sdp->path_name, mnt->mnt_dir);
- break;
- }
- } else {
- if (file_dev && ((file_dev == st_buf.st_dev) &&
- (file_ino == st_buf.st_ino))) {
- strcpy(sdp->device_name, mnt->mnt_fsname);
- strcpy(sdp->path_name, mnt->mnt_dir);
- break;
- }
- }
- }
- endmntent (fp);
- if (mnt == NULL)
- return 0;
- if (stat(mnt->mnt_dir, &st_buf) < 0) {
- if (errno == ENOENT)
- return 0;
- }
- /* Can't trust fstype because / has "rootfs". */
- if (file_rdev && (st_buf.st_dev != file_rdev))
- return 0;
- if (hasmntopt(mnt, MNTOPT_RO))
- *ro_mount = 1;
- return 1; /* mounted */
-}
-
-int is_gfs2(struct gfs2_sbd *sdp)
-{
- int fd, rc;
- struct gfs2_sb sb;
-
- fd = open(sdp->device_name, O_RDWR);
- if (fd < 0)
- return 0;
-
- rc = 0;
- if (lseek(fd, GFS2_SB_ADDR * GFS2_BASIC_BLOCK, SEEK_SET) >= 0 &&
- read(fd, &sb, sizeof(sb)) == sizeof(sb) &&
- be32_to_cpu(sb.sb_header.mh_magic) == GFS2_MAGIC &&
- be32_to_cpu(sb.sb_header.mh_type) == GFS2_METATYPE_SB)
- rc = 1;
- close(fd);
- return rc;
-}
-
-int check_for_gfs2(struct gfs2_sbd *sdp)
-{
- int ro;
-
- if (!is_pathname_mounted(sdp, &ro))
- return -1;
- if (!is_gfs2(sdp))
- return -1;
- return 0;
-}
-
-static int lock_for_admin(struct gfs2_sbd *sdp)
-{
- int error;
-
- if (sdp->debug)
- printf("\nTrying to get admin lock...\n");
-
- sdp->metafs_fd = open(sdp->metafs_path, O_RDONLY | O_NOFOLLOW);
- if (sdp->metafs_fd < 0)
- return -1;
-
- error = flock(sdp->metafs_fd, LOCK_EX);
- if (error)
- return -1;
- if (sdp->debug)
- printf("Got it.\n");
- return 0;
-}
-
-
-int mount_gfs2_meta(struct gfs2_sbd *sdp)
-{
- int ret;
-
- memset(sdp->metafs_path, 0, PATH_MAX);
- snprintf(sdp->metafs_path, PATH_MAX - 1, "/tmp/.gfs2meta.XXXXXX");
-
- if(!mkdtemp(sdp->metafs_path))
- return -1;
-
- ret = mount(sdp->path_name, sdp->metafs_path, "gfs2meta", 0, NULL);
- if (ret) {
- rmdir(sdp->metafs_path);
- return -1;
- }
- if (lock_for_admin(sdp))
- return -1;
- return 0;
-}
-
-void cleanup_metafs(struct gfs2_sbd *sdp)
-{
- int ret;
-
- if (sdp->metafs_fd <= 0)
- return;
-
- fsync(sdp->metafs_fd);
- close(sdp->metafs_fd);
- ret = umount(sdp->metafs_path);
- if (ret)
- fprintf(stderr, "Couldn't unmount %s : %s\n",
- sdp->metafs_path, strerror(errno));
- else
- rmdir(sdp->metafs_path);
-}
-
-static char *__get_sysfs(const char *fsname, const char *filename)
-{
- char path[PATH_MAX];
- int fd, rv;
-
- memset(path, 0, PATH_MAX);
- memset(sysfs_buf, 0, PAGE_SIZE);
- snprintf(path, PATH_MAX - 1, "%s/%s/%s", SYS_BASE, fsname, filename);
-
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return NULL;
- rv = read(fd, sysfs_buf, PAGE_SIZE);
- if (rv < 0) {
- close(fd);
- return NULL;
- }
-
- close(fd);
- return sysfs_buf;
-}
-
-char *get_sysfs(const char *fsname, const char *filename)
-{
- char *s;
- char *p;
-
- s = __get_sysfs(fsname, filename);
- if (!s)
- return NULL;
- p = strchr(s, '\n');
- if (p)
- *p = '\0';
- return sysfs_buf;
-}
-
-int get_sysfs_uint(const char *fsname, const char *filename, unsigned int *val)
-{
- char *s = __get_sysfs(fsname, filename);
- int ret;
- if (!s)
- return -1;
- ret = sscanf(s, "%u", val);
- if (1 != ret) {
- errno = ENOMSG;
- return -1;
- }
- return 0;
-}
-
-int set_sysfs(const char *fsname, const char *filename, const char *val)
-{
- char path[PATH_MAX];
- int fd, rv, len;
-
- len = strlen(val) + 1;
- if (len > PAGE_SIZE) {
- errno = EINVAL;
- return -1;
- }
-
- memset(path, 0, PATH_MAX);
- snprintf(path, PATH_MAX - 1, "%s/%s/%s", SYS_BASE, fsname, filename);
-
- fd = open(path, O_WRONLY);
- if (fd < 0)
- return -1;
-
- rv = write(fd, val, len);
- if (rv != len) {
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
-}
-
-char *find_debugfs_mount(void)
-{
- FILE *file;
- char line[PATH_MAX];
- char device[PATH_MAX], type[PATH_MAX];
- char *path;
-
- file = fopen("/proc/mounts", "rt");
- if (!file)
- return NULL;
-
- path = malloc(PATH_MAX);
- if (!path) {
- fclose(file);
- return NULL;
- }
- while (fgets(line, PATH_MAX, file)) {
-
- if (sscanf(line, "%s %s %s", device, path, type) != 3)
- continue;
- if (!strcmp(type, "debugfs")) {
- fclose(file);
- return path;
- }
- }
-
- free(path);
- fclose(file);
- return NULL;
-}
-
-/**
- * mp2fsname - Find the name for a filesystem given its mountpoint
- *
- * We do this by iterating through gfs2 dirs in /sys/fs/gfs2/ looking for
- * one where the "id" attribute matches the device id returned by stat for
- * the mount point. The reason we go through all this is simple: the
- * kernel's sysfs is named after the VFS s_id, not the device name.
- * So it's perfectly legal to do something like this to simulate user
- * conditions without the proper hardware:
- * # rm /dev/sdb1
- * # mkdir /dev/cciss
- * # mknod /dev/cciss/c0d0p1 b 8 17
- * # mount -tgfs2 /dev/cciss/c0d0p1 /mnt/gfs2
- * # gfs2_tool gettune /mnt/gfs2
- * In this example the tuning variables are in a directory named after the
- * VFS s_id, which in this case would be /sys/fs/gfs2/sdb1/
- *
- * Returns: the fsname
- */
-
-char *mp2fsname(char *mp)
-{
- char device_id[PATH_MAX], *fsname = NULL;
- struct stat statbuf;
- DIR *d;
- struct dirent *de;
- char *id;
-
- if (stat(mp, &statbuf))
- return NULL;
-
- memset(device_id, 0, sizeof(device_id));
- sprintf(device_id, "%i:%i", major(statbuf.st_dev),
- minor(statbuf.st_dev));
-
- d = opendir(SYS_BASE);
- if (!d)
- return NULL;
-
- while ((de = readdir(d))) {
- if (de->d_name[0] == '.')
- continue;
-
- id = get_sysfs(de->d_name, "id");
- if (!id)
- continue;
- if (strcmp(id, device_id) == 0) {
- fsname = strdup(de->d_name);
- break;
- }
- }
-
- closedir(d);
-
- return fsname;
-}
-
-/*
- * get_random_bytes - Generate a series of random bytes using /dev/urandom.
- *
- * Modified from original code in gen_uuid.c in e2fsprogs/lib
- */
-void get_random_bytes(void *buf, int nbytes)
-{
- int i, n = nbytes, fd;
- int lose_counter = 0;
- unsigned char *cp = (unsigned char *) buf;
- struct timeval tv;
-
- gettimeofday(&tv, 0);
- fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
- srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
- /* Crank the random number generator a few times */
- gettimeofday(&tv, 0);
- for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
- rand();
- if (fd >= 0) {
- while (n > 0) {
- i = read(fd, cp, n);
- if (i <= 0) {
- if (lose_counter++ > 16)
- break;
- continue;
- }
- n -= i;
- cp += i;
- lose_counter = 0;
- }
- close(fd);
- }
-
- /*
- * We do this all the time, but this is the only source of
- * randomness if /dev/random/urandom is out to lunch.
- */
- for (cp = buf, i = 0; i < nbytes; i++)
- *cp++ ^= (rand() >> 7) & 0xFF;
-
- return;
-}
diff --git a/gfs2/libgfs2/ondisk.c b/gfs2/libgfs2/ondisk.c
deleted file mode 100644
index 2902ba1..0000000
--- a/gfs2/libgfs2/ondisk.c
+++ /dev/null
@@ -1,630 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <ctype.h>
-
-#include <linux/types.h>
-#include "libgfs2.h"
-
-#define pv(struct, member, fmt, fmt2) do { \
- print_it(" "#member, fmt, fmt2, struct->member); \
- } while (FALSE);
-#define pv2(struct, member, fmt, fmt2) do { \
- print_it(" ", fmt, fmt2, struct->member); \
- } while (FALSE);
-
-
-#define CPIN_08(s1, s2, member, count) {memcpy((s1->member), (s2->member), (count));}
-#define CPOUT_08(s1, s2, member, count) {memcpy((s2->member), (s1->member), (count));}
-#define CPIN_16(s1, s2, member) {(s1->member) = be16_to_cpu((s2->member));}
-#define CPOUT_16(s1, s2, member) {(s2->member) = cpu_to_be16((s1->member));}
-#define CPIN_32(s1, s2, member) {(s1->member) = be32_to_cpu((s2->member));}
-#define CPOUT_32(s1, s2, member) {(s2->member) = cpu_to_be32((s1->member));}
-#define CPIN_64(s1, s2, member) {(s1->member) = be64_to_cpu((s2->member));}
-#define CPOUT_64(s1, s2, member) {(s2->member) = cpu_to_be64((s1->member));}
-
-/*
- * gfs2_xxx_in - read in an xxx struct
- * first arg: the cpu-order structure
- * bh: the disk-order buffer_head
- *
- * gfs2_xxx_out - write out an xxx struct
- * first arg: the cpu-order structure
- * bh: the disk-order buffer_head
- *
- * gfs2_xxx_print - print out an xxx struct
- * first arg: the cpu-order structure
- */
-
-void gfs2_inum_in(struct gfs2_inum *no, char *buf)
-{
- struct gfs2_inum *str = (struct gfs2_inum *)buf;
-
- CPIN_64(no, str, no_formal_ino);
- CPIN_64(no, str, no_addr);
-}
-
-void gfs2_inum_out(struct gfs2_inum *no, char *buf)
-{
- struct gfs2_inum *str = (struct gfs2_inum *)buf;
-
- CPOUT_64(no, str, no_formal_ino);
- CPOUT_64(no, str, no_addr);
-}
-
-void gfs2_inum_print(struct gfs2_inum *no)
-{
- pv(no, no_formal_ino, "%llu", "0x%llx");
- pv(no, no_addr, "%llu", "0x%llx");
-}
-
-void gfs2_meta_header_in(struct gfs2_meta_header *mh,
- struct gfs2_buffer_head *bh)
-{
- struct gfs2_meta_header *str = (struct gfs2_meta_header *)bh->b_data;
-
- CPIN_32(mh, str, mh_magic);
- CPIN_32(mh, str, mh_type);
- CPIN_32(mh, str, mh_format);
-}
-
-void gfs2_meta_header_out(struct gfs2_meta_header *mh,
- struct gfs2_buffer_head *bh)
-{
- struct gfs2_meta_header *str = (struct gfs2_meta_header *)bh->b_data;
-
- CPOUT_32(mh, str, mh_magic);
- CPOUT_32(mh, str, mh_type);
- CPOUT_32(mh, str, mh_format);
- str->__pad0 = 0;
- str->__pad1 = 0;
- bmodified(bh);
-}
-
-void gfs2_meta_header_print(struct gfs2_meta_header *mh)
-{
- pv(mh, mh_magic, "0x%08X", NULL);
- pv(mh, mh_type, "%u", "0x%x");
- pv(mh, mh_format, "%u", "0x%x");
-}
-
-void gfs2_sb_in(struct gfs2_sb *sb, struct gfs2_buffer_head *bh)
-{
- struct gfs2_sb *str = (struct gfs2_sb *)bh->b_data;
-
- gfs2_meta_header_in(&sb->sb_header, bh);
-
- CPIN_32(sb, str, sb_fs_format);
- CPIN_32(sb, str, sb_multihost_format);
-
- CPIN_32(sb, str, sb_bsize);
- CPIN_32(sb, str, sb_bsize_shift);
-
- gfs2_inum_in(&sb->sb_master_dir, (char *)&str->sb_master_dir);
- gfs2_inum_in(&sb->sb_root_dir, (char *)&str->sb_root_dir);
-
- CPIN_08(sb, str, sb_lockproto, GFS2_LOCKNAME_LEN);
- CPIN_08(sb, str, sb_locktable, GFS2_LOCKNAME_LEN);
-#ifdef GFS2_HAS_UUID
- CPIN_08(sb, str, sb_uuid, sizeof(sb->sb_uuid));
-#endif
-}
-
-void gfs2_sb_out(struct gfs2_sb *sb, struct gfs2_buffer_head *bh)
-{
- struct gfs2_sb *str = (struct gfs2_sb *)bh->b_data;
-
- gfs2_meta_header_out(&sb->sb_header, bh);
-
- CPOUT_32(sb, str, sb_fs_format);
- CPOUT_32(sb, str, sb_multihost_format);
-
- CPOUT_32(sb, str, sb_bsize);
- CPOUT_32(sb, str, sb_bsize_shift);
-
- gfs2_inum_out(&sb->sb_master_dir, (char *)&str->sb_master_dir);
- gfs2_inum_out(&sb->sb_root_dir, (char *)&str->sb_root_dir);
-
- CPOUT_08(sb, str, sb_lockproto, GFS2_LOCKNAME_LEN);
- CPOUT_08(sb, str, sb_locktable, GFS2_LOCKNAME_LEN);
-#ifdef GFS2_HAS_UUID
- memcpy(str->sb_uuid, sb->sb_uuid, 16);
-#endif
- bmodified(bh);
-}
-
-const char *str_uuid(const unsigned char *uuid)
-{
- static char str[64];
- char *ch;
- int i;
-
- memset(str, 0, sizeof(str));
- ch = str;
- for (i = 0; i < 16; i++) {
- sprintf(ch, "%02x", uuid[i]);
- ch += 2;
- if ((i == 3) || (i == 5) || (i == 7) || (i == 9)) {
- *ch = '-';
- ch++;
- }
- }
- return str;
-}
-
-#ifdef GFS2_HAS_UUID
-void gfs2_print_uuid(const unsigned char *uuid)
-{
- print_it(" uuid", "%s", NULL, str_uuid(uuid));
-}
-#endif
-
-void gfs2_sb_print(struct gfs2_sb *sb)
-{
- gfs2_meta_header_print(&sb->sb_header);
-
- pv(sb, sb_fs_format, "%u", "0x%x");
- pv(sb, sb_multihost_format, "%u", "0x%x");
-
- pv(sb, sb_bsize, "%u", "0x%x");
- pv(sb, sb_bsize_shift, "%u", "0x%x");
-
- gfs2_inum_print(&sb->sb_master_dir);
- gfs2_inum_print(&sb->sb_root_dir);
-
- pv(sb, sb_lockproto, "%s", NULL);
- pv(sb, sb_locktable, "%s", NULL);
-
-#ifdef GFS2_HAS_UUID
- gfs2_print_uuid(sb->sb_uuid);
-#endif
-}
-
-void gfs2_rindex_in(struct gfs2_rindex *ri, char *buf)
-{
- struct gfs2_rindex *str = (struct gfs2_rindex *)buf;
-
- CPIN_64(ri, str, ri_addr);
- CPIN_32(ri, str, ri_length);
-
- CPIN_64(ri, str, ri_data0);
- CPIN_32(ri, str, ri_data);
-
- CPIN_32(ri, str, ri_bitbytes);
-
- CPIN_08(ri, str, ri_reserved, 64);
-}
-
-void gfs2_rindex_out(struct gfs2_rindex *ri, char *buf)
-{
- struct gfs2_rindex *str = (struct gfs2_rindex *)buf;
-
- CPOUT_64(ri, str, ri_addr);
- CPOUT_32(ri, str, ri_length);
- ri->__pad = 0;
-
- CPOUT_64(ri, str, ri_data0);
- CPOUT_32(ri, str, ri_data);
-
- CPOUT_32(ri, str, ri_bitbytes);
-
- CPOUT_08(ri, str, ri_reserved, 64);
-}
-
-void gfs2_rindex_print(struct gfs2_rindex *ri)
-{
- pv(ri, ri_addr, "%llu", "0x%llx");
- pv(ri, ri_length, "%u", "0x%x");
-
- pv(ri, ri_data0, "%llu", "0x%llx");
- pv(ri, ri_data, "%u", "0x%x");
-
- pv(ri, ri_bitbytes, "%u", "0x%x");
-}
-
-void gfs2_rgrp_in(struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh)
-{
- struct gfs2_rgrp *str = (struct gfs2_rgrp *)bh->b_data;
-
- gfs2_meta_header_in(&rg->rg_header, bh);
- CPIN_32(rg, str, rg_flags);
- CPIN_32(rg, str, rg_free);
- CPIN_32(rg, str, rg_dinodes);
-
- CPIN_08(rg, str, rg_reserved, 36);
-}
-
-void gfs2_rgrp_out(struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh)
-{
- struct gfs2_rgrp *str = (struct gfs2_rgrp *)bh->b_data;
-
- gfs2_meta_header_out(&rg->rg_header, bh);
- CPOUT_32(rg, str, rg_flags);
- CPOUT_32(rg, str, rg_free);
- CPOUT_32(rg, str, rg_dinodes);
-
- CPOUT_08(rg, str, rg_reserved, 36);
- bmodified(bh);
-}
-
-void gfs2_rgrp_print(struct gfs2_rgrp *rg)
-{
- gfs2_meta_header_print(&rg->rg_header);
- pv(rg, rg_flags, "%u", "0x%x");
- pv(rg, rg_free, "%u", "0x%x");
- pv(rg, rg_dinodes, "%u", "0x%x");
-}
-
-void gfs2_quota_in(struct gfs2_quota *qu, char *buf)
-{
- struct gfs2_quota *str = (struct gfs2_quota *)buf;
-
- CPIN_64(qu, str, qu_limit);
- CPIN_64(qu, str, qu_warn);
- CPIN_64(qu, str, qu_value);
- CPIN_08(qu, str, qu_reserved, sizeof(qu->qu_reserved));
-}
-
-void gfs2_quota_out(struct gfs2_quota *qu, char *buf)
-{
- struct gfs2_quota *str = (struct gfs2_quota *)buf;
-
- CPOUT_64(qu, str, qu_limit);
- CPOUT_64(qu, str, qu_warn);
- CPOUT_64(qu, str, qu_value);
- memset(qu->qu_reserved, 0, sizeof(qu->qu_reserved));
-}
-
-void gfs2_quota_print(struct gfs2_quota *qu)
-{
- pv(qu, qu_limit, "%llu", "0x%llx");
- pv(qu, qu_warn, "%llu", "0x%llx");
- pv(qu, qu_value, "%lld", "0x%llx");
-}
-
-void gfs2_dinode_in(struct gfs2_dinode *di, struct gfs2_buffer_head *bh)
-{
- struct gfs2_dinode *str = (struct gfs2_dinode *)bh->b_data;
-
- gfs2_meta_header_in(&di->di_header, bh);
- gfs2_inum_in(&di->di_num, (char *)&str->di_num);
-
- CPIN_32(di, str, di_mode);
- CPIN_32(di, str, di_uid);
- CPIN_32(di, str, di_gid);
- CPIN_32(di, str, di_nlink);
- CPIN_64(di, str, di_size);
- CPIN_64(di, str, di_blocks);
- CPIN_64(di, str, di_atime);
- CPIN_64(di, str, di_mtime);
- CPIN_64(di, str, di_ctime);
- CPIN_32(di, str, di_major);
- CPIN_32(di, str, di_minor);
-
- CPIN_64(di, str, di_goal_meta);
- CPIN_64(di, str, di_goal_data);
-
- CPIN_32(di, str, di_flags);
- CPIN_32(di, str, di_payload_format);
- CPIN_16(di, str, __pad1);
- CPIN_16(di, str, di_height);
-
- CPIN_16(di, str, di_depth);
- CPIN_32(di, str, di_entries);
-
- CPIN_64(di, str, di_eattr);
-
- CPIN_08(di, str, di_reserved, 32);
-}
-
-void gfs2_dinode_out(struct gfs2_dinode *di, struct gfs2_buffer_head *bh)
-{
- struct gfs2_dinode *str = (struct gfs2_dinode *)bh->b_data;
-
- gfs2_meta_header_out(&di->di_header, bh);
- gfs2_inum_out(&di->di_num, (char *)&str->di_num);
-
- CPOUT_32(di, str, di_mode);
- CPOUT_32(di, str, di_uid);
- CPOUT_32(di, str, di_gid);
- CPOUT_32(di, str, di_nlink);
- CPOUT_64(di, str, di_size);
- CPOUT_64(di, str, di_blocks);
- CPOUT_64(di, str, di_atime);
- CPOUT_64(di, str, di_mtime);
- CPOUT_64(di, str, di_ctime);
- CPOUT_32(di, str, di_major);
- CPOUT_32(di, str, di_minor);
-
- CPOUT_64(di, str, di_goal_meta);
- CPOUT_64(di, str, di_goal_data);
-
- CPOUT_32(di, str, di_flags);
- CPOUT_32(di, str, di_payload_format);
- CPOUT_16(di, str, di_height);
-
- CPOUT_16(di, str, di_depth);
- CPOUT_32(di, str, di_entries);
-
- CPOUT_64(di, str, di_eattr);
-
- CPOUT_08(di, str, di_reserved, 32);
- bmodified(bh);
-}
-
-void gfs2_dinode_print(struct gfs2_dinode *di)
-{
- gfs2_meta_header_print(&di->di_header);
- gfs2_inum_print(&di->di_num);
-
- pv(di, di_mode, "0%o", NULL);
- pv(di, di_uid, "%u", "0x%x");
- pv(di, di_gid, "%u", "0x%x");
- pv(di, di_nlink, "%u", "0x%x");
- pv(di, di_size, "%llu", "0x%llx");
- pv(di, di_blocks, "%llu", "0x%llx");
- pv(di, di_atime, "%lld", "0x%llx");
- pv(di, di_mtime, "%lld", "0x%llx");
- pv(di, di_ctime, "%lld", "0x%llx");
- pv(di, di_major, "%u", "0x%llx");
- pv(di, di_minor, "%u", "0x%llx");
-
- pv(di, di_goal_meta, "%llu", "0x%llx");
- pv(di, di_goal_data, "%llu", "0x%llx");
-
- pv(di, di_flags, "0x%.8X", NULL);
- pv(di, di_payload_format, "%u", "0x%x");
- pv(di, di_height, "%u", "0x%x");
-
- pv(di, di_depth, "%u", "0x%x");
- pv(di, di_entries, "%u", "0x%x");
-
- pv(di, di_eattr, "%llu", "0x%llx");
-}
-
-void gfs2_dirent_in(struct gfs2_dirent *de, char *buf)
-{
- struct gfs2_dirent *str = (struct gfs2_dirent *)buf;
-
- gfs2_inum_in(&de->de_inum, buf);
- CPIN_32(de, str, de_hash);
- CPIN_16(de, str, de_rec_len);
- CPIN_16(de, str, de_name_len);
- CPIN_16(de, str, de_type);
-}
-
-void gfs2_dirent_out(struct gfs2_dirent *de, char *buf)
-{
- struct gfs2_dirent *str = (struct gfs2_dirent *)buf;
-
- gfs2_inum_out(&de->de_inum, buf);
- CPOUT_32(de, str, de_hash);
- CPOUT_16(de, str, de_rec_len);
- CPOUT_16(de, str, de_name_len);
- CPOUT_16(de, str, de_type);
- memset(str->__pad, 0, sizeof(str->__pad));
-}
-
-void gfs2_dirent_print(struct gfs2_dirent *de, char *name)
-{
- char buf[GFS2_FNAMESIZE + 1];
-
- gfs2_inum_print(&de->de_inum);
- pv(de, de_hash, "0x%.8X", NULL);
- pv(de, de_rec_len, "%u", "0x%x");
- pv(de, de_name_len, "%u", "0x%x");
- pv(de, de_type, "%u", "0x%x");
-
- memset(buf, 0, GFS2_FNAMESIZE + 1);
- memcpy(buf, name, de->de_name_len);
- print_it(" name", "%s", NULL, buf);
-}
-
-void gfs2_leaf_in(struct gfs2_leaf *lf, struct gfs2_buffer_head *bh)
-{
- struct gfs2_leaf *str = (struct gfs2_leaf *)bh->b_data;
-
- gfs2_meta_header_in(&lf->lf_header, bh);
- CPIN_16(lf, str, lf_depth);
- CPIN_16(lf, str, lf_entries);
- CPIN_32(lf, str, lf_dirent_format);
- CPIN_64(lf, str, lf_next);
-
- CPIN_08(lf, str, lf_reserved, 32);
-}
-
-void gfs2_leaf_out(struct gfs2_leaf *lf, struct gfs2_buffer_head *bh)
-{
- struct gfs2_leaf *str = (struct gfs2_leaf *)bh->b_data;
-
- gfs2_meta_header_out(&lf->lf_header, bh);
- CPOUT_16(lf, str, lf_depth);
- CPOUT_16(lf, str, lf_entries);
- CPOUT_32(lf, str, lf_dirent_format);
- CPOUT_64(lf, str, lf_next);
-
- CPOUT_08(lf, str, lf_reserved, 32);
- bmodified(bh);
-}
-
-void gfs2_leaf_print(struct gfs2_leaf *lf)
-{
- gfs2_meta_header_print(&lf->lf_header);
- pv(lf, lf_depth, "%u", "0x%x");
- pv(lf, lf_entries, "%u", "0x%x");
- pv(lf, lf_dirent_format, "%u", "0x%x");
- pv(lf, lf_next, "%llu", "0x%llx");
-}
-
-void gfs2_ea_header_in(struct gfs2_ea_header *ea, char *buf)
-{
- struct gfs2_ea_header *str = (struct gfs2_ea_header *)buf;
-
- CPIN_32(ea, str, ea_rec_len);
- CPIN_32(ea, str, ea_data_len);
- ea->ea_name_len = str->ea_name_len;
- ea->ea_type = str->ea_type;
- ea->ea_flags = str->ea_flags;
- ea->ea_num_ptrs = str->ea_num_ptrs;
-}
-
-void gfs2_ea_header_out(struct gfs2_ea_header *ea, char *buf)
-{
- struct gfs2_ea_header *str = (struct gfs2_ea_header *)buf;
-
- CPOUT_32(ea, str, ea_rec_len);
- CPOUT_32(ea, str, ea_data_len);
- str->ea_name_len = ea->ea_name_len;
- str->ea_type = ea->ea_type;
- str->ea_flags = ea->ea_flags;
- str->ea_num_ptrs = ea->ea_num_ptrs;
- str->__pad = 0;
-}
-
-void gfs2_ea_header_print(struct gfs2_ea_header *ea, char *name)
-{
- char buf[GFS2_EA_MAX_NAME_LEN + 1];
-
- pv(ea, ea_rec_len, "%u", "0x%x");
- pv(ea, ea_data_len, "%u", "0x%x");
- pv(ea, ea_name_len, "%u", "0x%x");
- pv(ea, ea_type, "%u", "0x%x");
- pv(ea, ea_flags, "%u", "0x%x");
- pv(ea, ea_num_ptrs, "%u", "0x%x");
-
- memset(buf, 0, GFS2_EA_MAX_NAME_LEN + 1);
- memcpy(buf, name, ea->ea_name_len);
- print_it(" name", "%s", NULL, buf);
-}
-
-void gfs2_log_header_in(struct gfs2_log_header *lh,
- struct gfs2_buffer_head *bh)
-{
- struct gfs2_log_header *str = (struct gfs2_log_header *)bh->b_data;
-
- gfs2_meta_header_in(&lh->lh_header, bh);
- CPIN_64(lh, str, lh_sequence);
- CPIN_32(lh, str, lh_flags);
- CPIN_32(lh, str, lh_tail);
- CPIN_32(lh, str, lh_blkno);
- CPIN_32(lh, str, lh_hash);
-}
-
-void gfs2_log_header_out(struct gfs2_log_header *lh,
- struct gfs2_buffer_head *bh)
-{
- struct gfs2_log_header *str = (struct gfs2_log_header *)bh->b_data;
-
- gfs2_meta_header_out(&lh->lh_header, bh);
- CPOUT_64(lh, str, lh_sequence);
- CPOUT_32(lh, str, lh_flags);
- CPOUT_32(lh, str, lh_tail);
- CPOUT_32(lh, str, lh_blkno);
- CPOUT_32(lh, str, lh_hash);
- bmodified(bh);
-}
-
-void gfs2_log_header_print(struct gfs2_log_header *lh)
-{
- gfs2_meta_header_print(&lh->lh_header);
- pv(lh, lh_sequence, "%llu", "0x%llx");
- pv(lh, lh_flags, "0x%.8X", NULL);
- pv(lh, lh_tail, "%u", "0x%x");
- pv(lh, lh_blkno, "%u", "0x%x");
- pv(lh, lh_hash, "0x%.8X", NULL);
-}
-
-void gfs2_log_descriptor_in(struct gfs2_log_descriptor *ld,
- struct gfs2_buffer_head *bh)
-{
- struct gfs2_log_descriptor *str = (struct gfs2_log_descriptor *)bh->b_data;
-
- gfs2_meta_header_in(&ld->ld_header, bh);
- CPIN_32(ld, str, ld_type);
- CPIN_32(ld, str, ld_length);
- CPIN_32(ld, str, ld_data1);
- CPIN_32(ld, str, ld_data2);
-
- CPIN_08(ld, str, ld_reserved, 32);
-}
-
-void gfs2_log_descriptor_out(struct gfs2_log_descriptor *ld,
- struct gfs2_buffer_head *bh)
-{
- struct gfs2_log_descriptor *str = (struct gfs2_log_descriptor *)bh->b_data;
-
- gfs2_meta_header_out(&ld->ld_header, bh);
- CPOUT_32(ld, str, ld_type);
- CPOUT_32(ld, str, ld_length);
- CPOUT_32(ld, str, ld_data1);
- CPOUT_32(ld, str, ld_data2);
-
- CPOUT_08(ld, str, ld_reserved, 32);
- bmodified(bh);
-}
-
-void gfs2_log_descriptor_print(struct gfs2_log_descriptor *ld)
-{
- gfs2_meta_header_print(&ld->ld_header);
- pv(ld, ld_type, "%u", "0x%x");
- pv(ld, ld_length, "%u", "0x%x");
- pv(ld, ld_data1, "%u", "0x%x");
- pv(ld, ld_data2, "%u", "0x%x");
-}
-
-void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, char *buf)
-{
- struct gfs2_statfs_change *str = (struct gfs2_statfs_change *)buf;
-
- CPIN_64(sc, str, sc_total);
- CPIN_64(sc, str, sc_free);
- CPIN_64(sc, str, sc_dinodes);
-}
-
-void gfs2_statfs_change_out(struct gfs2_statfs_change *sc, char *buf)
-{
- struct gfs2_statfs_change *str = (struct gfs2_statfs_change *)buf;
-
- CPOUT_64(sc, str, sc_total);
- CPOUT_64(sc, str, sc_free);
- CPOUT_64(sc, str, sc_dinodes);
-}
-
-void gfs2_statfs_change_print(struct gfs2_statfs_change *sc)
-{
- pv(sc, sc_total, "%lld", "0x%llx");
- pv(sc, sc_free, "%lld", "0x%llx");
- pv(sc, sc_dinodes, "%lld", "0x%llx");
-}
-
-void gfs2_quota_change_in(struct gfs2_quota_change *qc,
- struct gfs2_buffer_head *bh)
-{
- struct gfs2_quota_change *str = (struct gfs2_quota_change *)bh->b_data;
-
- CPIN_64(qc, str, qc_change);
- CPIN_32(qc, str, qc_flags);
- CPIN_32(qc, str, qc_id);
-}
-
-void gfs2_quota_change_out(struct gfs2_quota_change *qc,
- struct gfs2_buffer_head *bh)
-{
- struct gfs2_quota_change *str = (struct gfs2_quota_change *)bh->b_data;
-
- CPOUT_64(qc, str, qc_change);
- CPOUT_32(qc, str, qc_flags);
- CPOUT_32(qc, str, qc_id);
- bmodified(bh);
-}
-
-void gfs2_quota_change_print(struct gfs2_quota_change *qc)
-{
- pv(qc, qc_change, "%lld", "0x%llx");
- pv(qc, qc_flags, "0x%.8X", NULL);
- pv(qc, qc_id, "%u", "0x%x");
-}
-
-
diff --git a/gfs2/libgfs2/recovery.c b/gfs2/libgfs2/recovery.c
deleted file mode 100644
index 74f896e..0000000
--- a/gfs2/libgfs2/recovery.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * NOTE:
- *
- * This code was pilfered from the gfs2 kernel and adapted to userland.
- * If you change this part, you should evaluate whether the upstream kernel
- * version of recovery.c should be changed as well. Likewise, if the
- * upstream version changes, this part should be kept in sync.
- *
- */
-
-#include <errno.h>
-#include <string.h>
-#include "libgfs2.h"
-
-void gfs2_replay_incr_blk(struct gfs2_inode *ip, unsigned int *blk)
-{
- uint32_t jd_blocks = ip->i_di.di_size / ip->i_sbd->sd_sb.sb_bsize;
-
- if (++*blk == jd_blocks)
- *blk = 0;
-}
-
-int gfs2_replay_read_block(struct gfs2_inode *ip, unsigned int blk,
- struct gfs2_buffer_head **bh)
-{
- int new = 0;
- uint64_t dblock;
- uint32_t extlen;
-
- block_map(ip, blk, &new, &dblock, &extlen, FALSE);
- if (!dblock)
- return -EIO;
-
- *bh = bread(ip->i_sbd, dblock);
- return 0;
-}
-
-/**
- * get_log_header - read the log header for a given segment
- * @ip: the journal incore inode
- * @blk: the block to look at
- * @lh: the log header to return
- *
- * Read the log header for a given segement in a given journal. Do a few
- * sanity checks on it.
- *
- * Returns: 0 on success,
- * 1 if the header was invalid or incomplete,
- * errno on error
- */
-
-int get_log_header(struct gfs2_inode *ip, unsigned int blk,
- struct gfs2_log_header *head)
-{
- struct gfs2_buffer_head *bh;
- struct gfs2_log_header lh, *tmp;
- uint32_t hash, saved_hash;
- int error;
-
- error = gfs2_replay_read_block(ip, blk, &bh);
- if (error)
- return error;
-
- tmp = (struct gfs2_log_header *)bh->b_data;
- saved_hash = tmp->lh_hash;
- tmp->lh_hash = 0;
- hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header));
- tmp->lh_hash = saved_hash;
- gfs2_log_header_in(&lh, bh);
- brelse(bh);
-
- if (error || lh.lh_blkno != blk || lh.lh_hash != hash)
- return 1;
-
- *head = lh;
-
- return 0;
-}
-
-/**
- * find_good_lh - find a good log header
- * @ip: the journal incore inode
- * @blk: the segment to start searching from
- * @lh: the log header to fill in
- * @forward: if true search forward in the log, else search backward
- *
- * Call get_log_header() to get a log header for a segment, but if the
- * segment is bad, either scan forward or backward until we find a good one.
- *
- * Returns: errno
- */
-
-int find_good_lh(struct gfs2_inode *ip, unsigned int *blk,
- struct gfs2_log_header *head)
-{
- unsigned int orig_blk = *blk;
- int error;
- uint32_t jd_blocks = ip->i_di.di_size / ip->i_sbd->sd_sb.sb_bsize;
-
- for (;;) {
- error = get_log_header(ip, *blk, head);
- if (error <= 0)
- return error;
-
- if (++*blk == jd_blocks)
- *blk = 0;
-
- if (*blk == orig_blk)
- return -EIO;
- }
-}
-
-/**
- * jhead_scan - make sure we've found the head of the log
- * @jd: the journal
- * @head: this is filled in with the log descriptor of the head
- *
- * At this point, seg and lh should be either the head of the log or just
- * before. Scan forward until we find the head.
- *
- * Returns: errno
- */
-
-int jhead_scan(struct gfs2_inode *ip, struct gfs2_log_header *head)
-{
- unsigned int blk = head->lh_blkno;
- uint32_t jd_blocks = ip->i_di.di_size / ip->i_sbd->sd_sb.sb_bsize;
- struct gfs2_log_header lh;
- int error;
-
- for (;;) {
- if (++blk == jd_blocks)
- blk = 0;
-
- error = get_log_header(ip, blk, &lh);
- if (error < 0)
- return error;
- if (error == 1)
- continue;
-
- if (lh.lh_sequence == head->lh_sequence)
- return -EIO;
- if (lh.lh_sequence < head->lh_sequence)
- break;
-
- *head = lh;
- }
-
- return 0;
-}
-
-/**
- * gfs2_find_jhead - find the head of a log
- * @jd: the journal
- * @head: the log descriptor for the head of the log is returned here
- *
- * Do a binary search of a journal and find the valid log entry with the
- * highest sequence number. (i.e. the log head)
- *
- * Returns: errno
- */
-
-int gfs2_find_jhead(struct gfs2_inode *ip, struct gfs2_log_header *head)
-{
- struct gfs2_log_header lh_1, lh_m;
- uint32_t blk_1, blk_2, blk_m;
- uint32_t jd_blocks = ip->i_di.di_size / ip->i_sbd->sd_sb.sb_bsize;
- int error;
-
- blk_1 = 0;
- blk_2 = jd_blocks - 1;
-
- for (;;) {
- blk_m = (blk_1 + blk_2) / 2;
-
- error = find_good_lh(ip, &blk_1, &lh_1);
- if (error)
- return error;
-
- error = find_good_lh(ip, &blk_m, &lh_m);
- if (error)
- return error;
-
- if (blk_1 == blk_m || blk_m == blk_2)
- break;
-
- if (lh_1.lh_sequence <= lh_m.lh_sequence)
- blk_1 = blk_m;
- else
- blk_2 = blk_m;
- }
-
- error = jhead_scan(ip, &lh_1);
- if (error)
- return error;
-
- *head = lh_1;
-
- return error;
-}
-
-/**
- * clean_journal - mark a dirty journal as being clean
- * @sdp: the filesystem
- * @jd: the journal
- * @head: the head journal to start from
- *
- * Returns: errno
- */
-
-int clean_journal(struct gfs2_inode *ip, struct gfs2_log_header *head)
-{
- unsigned int lblock;
- struct gfs2_log_header *lh;
- uint32_t hash, extlen;
- struct gfs2_buffer_head *bh;
- int new = 0;
- uint64_t dblock;
-
- lblock = head->lh_blkno;
- gfs2_replay_incr_blk(ip, &lblock);
- block_map(ip, lblock, &new, &dblock, &extlen, 0);
- if (!dblock)
- return -EIO;
-
- bh = bread(ip->i_sbd, dblock);
- memset(bh->b_data, 0, ip->i_sbd->bsize);
-
- lh = (struct gfs2_log_header *)bh->b_data;
- memset(lh, 0, sizeof(struct gfs2_log_header));
- lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
- lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
- lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH);
- lh->lh_sequence = cpu_to_be64(head->lh_sequence + 1);
- lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT);
- lh->lh_blkno = cpu_to_be32(lblock);
- hash = gfs2_disk_hash((const char *)lh, sizeof(struct gfs2_log_header));
- lh->lh_hash = cpu_to_be32(hash);
- bmodified(bh);
- brelse(bh);
-
- return 0;
-}
-
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
deleted file mode 100644
index d37ed1b..0000000
--- a/gfs2/libgfs2/rgrp.c
+++ /dev/null
@@ -1,193 +0,0 @@
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "libgfs2.h"
-
-#define RG_SYNC_TOLERANCE 1000
-
-/**
- * gfs2_compute_bitstructs - Compute the bitmap sizes
- * @rgd: The resource group descriptor
- *
- * Returns: 0 on success, -1 on error
- */
-int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd)
-{
- struct gfs2_bitmap *bits;
- uint32_t length = rgd->ri.ri_length;
- uint32_t bytes_left, bytes;
- int x;
-
- /* Max size of an rg is 2GB. A 2GB RG with (minimum) 512-byte blocks
- has 4194304 blocks. We can represent 4 blocks in one bitmap byte.
- Therefore, all 4194304 blocks can be represented in 1048576 bytes.
- Subtract a metadata header for each 512-byte block and we get
- 488 bytes of bitmap per block. Divide 1048576 by 488 and we can
- be assured we should never have more than 2149 of them. */
- if (length > 2149 || length == 0)
- return -1;
- if(rgd->bits == NULL && !(rgd->bits = (struct gfs2_bitmap *)
- malloc(length * sizeof(struct gfs2_bitmap))))
- return -1;
- if(!memset(rgd->bits, 0, length * sizeof(struct gfs2_bitmap)))
- return -1;
-
- bytes_left = rgd->ri.ri_bitbytes;
-
- for (x = 0; x < length; x++){
- bits = &rgd->bits[x];
-
- if (length == 1){
- bytes = bytes_left;
- bits->bi_offset = sizeof(struct gfs2_rgrp);
- bits->bi_start = 0;
- bits->bi_len = bytes;
- }
- else if (x == 0){
- bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_rgrp);
- bits->bi_offset = sizeof(struct gfs2_rgrp);
- bits->bi_start = 0;
- bits->bi_len = bytes;
- }
- else if (x + 1 == length){
- bytes = bytes_left;
- bits->bi_offset = sizeof(struct gfs2_meta_header);
- bits->bi_start = rgd->ri.ri_bitbytes - bytes_left;
- bits->bi_len = bytes;
- }
- else{
- bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
- bits->bi_offset = sizeof(struct gfs2_meta_header);
- bits->bi_start = rgd->ri.ri_bitbytes - bytes_left;
- bits->bi_len = bytes;
- }
-
- bytes_left -= bytes;
- }
-
- if(bytes_left)
- return -1;
-
- if((rgd->bits[length - 1].bi_start +
- rgd->bits[length - 1].bi_len) * GFS2_NBBY != rgd->ri.ri_data)
- return -1;
-
- if (rgd->bh) /* If we already have a bh allocated */
- return 0; /* don't want to allocate another */
- if(!(rgd->bh = (struct gfs2_buffer_head **)
- malloc(length * sizeof(struct gfs2_buffer_head *))))
- return -1;
- if(!memset(rgd->bh, 0, length * sizeof(struct gfs2_buffer_head *)))
- return -1;
-
- return 0;
-}
-
-
-/**
- * blk2rgrpd - Find resource group for a given data block number
- * @sdp: The GFS superblock
- * @n: The data block number
- *
- * Returns: Ths resource group, or NULL if not found
- */
-struct rgrp_list *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk)
-{
- osi_list_t *tmp;
- struct rgrp_list *rgd;
- static struct rgrp_list *prev_rgd = NULL;
- struct gfs2_rindex *ri;
-
- if (prev_rgd) {
- ri = &prev_rgd->ri;
- if (ri->ri_data0 <= blk && blk < ri->ri_data0 + ri->ri_data)
- return prev_rgd;
- if (blk >= ri->ri_addr && blk < ri->ri_addr + ri->ri_length)
- return prev_rgd;
- }
-
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- ri = &rgd->ri;
-
- if (blk >= ri->ri_addr && blk < ri->ri_addr + ri->ri_length) {
- prev_rgd = rgd;
- return rgd;
- }
- if (ri->ri_data0 <= blk && blk < ri->ri_data0 + ri->ri_data) {
- prev_rgd = rgd;
- return rgd;
- }
- }
- return NULL;
-}
-
-/**
- * gfs2_rgrp_read - read in the resource group information from disk.
- * @rgd - resource group structure
- * returns: 0 if no error, otherwise the block number that failed
- */
-uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd)
-{
- int x, length = rgd->ri.ri_length;
-
- for (x = 0; x < length; x++){
- rgd->bh[x] = bread(sdp, rgd->ri.ri_addr + x);
- if(gfs2_check_meta(rgd->bh[x],
- (x) ? GFS2_METATYPE_RB : GFS2_METATYPE_RG))
- {
- uint64_t error;
-
- error = rgd->ri.ri_addr + x;
- for (; x >= 0; x--) {
- brelse(rgd->bh[x]);
- rgd->bh[x] = NULL;
- }
- return error;
- }
- }
-
- gfs2_rgrp_in(&rgd->rg, rgd->bh[0]);
- return 0;
-}
-
-void gfs2_rgrp_relse(struct rgrp_list *rgd)
-{
- int x, length = rgd->ri.ri_length;
-
- for (x = 0; x < length; x++) {
- brelse(rgd->bh[x]);
- rgd->bh[x] = NULL;
- }
-}
-
-void gfs2_rgrp_free(osi_list_t *rglist)
-{
- struct rgrp_list *rgd;
- int rgs_since_sync = 0;
- struct gfs2_sbd *sdp = NULL;
-
- while(!osi_list_empty(rglist->next)){
- rgd = osi_list_entry(rglist->next, struct rgrp_list, list);
- if (rgd->bh && rgd->bh[0]) { /* if a buffer exists */
- rgs_since_sync++;
- if (rgs_since_sync >= RG_SYNC_TOLERANCE) {
- if (!sdp)
- sdp = rgd->bh[0]->sdp;
- fsync(sdp->device_fd);
- rgs_since_sync = 0;
- }
- gfs2_rgrp_relse(rgd); /* free them all. */
- }
- if(rgd->bits)
- free(rgd->bits);
- if(rgd->bh) {
- free(rgd->bh);
- rgd->bh = NULL;
- }
- osi_list_del(&rgd->list);
- free(rgd);
- }
-}
diff --git a/gfs2/libgfs2/size.c b/gfs2/libgfs2/size.c
deleted file mode 100644
index d9d2c54..0000000
--- a/gfs2/libgfs2/size.c
+++ /dev/null
@@ -1,67 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/mount.h>
-
-#include "libgfs2.h"
-
-#ifndef BLKGETSIZE64
-#define BLKGETSIZE64 _IOR(0x12, 114, size_t)
-#endif
-
-/**
- * do_device_size - determine the size of a Linux block device
- * @device: the path to the device node
- *
- * Returns: -1 on error (with errno set), 0 on success (with @bytes set)
- */
-
-static int do_device_size(int fd, uint64_t *bytes)
-{
- off_t off;
-
- off = lseek(fd, 0, SEEK_END);
- if (off >= 0) {
- *bytes = off;
- return 0;
- }
-
- return -1;
-}
-
-/**
- * device_size - figure out a device's size
- * @fd: the file descriptor of a device
- * @bytes: the number of bytes the device holds
- *
- * Returns: -1 on error (with errno set), 0 on success (with @bytes set)
- */
-
-int device_size(int fd, uint64_t *bytes)
-{
- struct stat st;
- int error;
-
- error = fstat(fd, &st);
- if (error)
- return error;
-
- if (S_ISREG(st.st_mode)) {
- *bytes = st.st_size;
- return 0;
- } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))
- return do_device_size(fd, bytes);
- else if (S_ISDIR(st.st_mode))
- errno = EISDIR;
- else
- errno = EINVAL;
-
- return -1;
-}
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
deleted file mode 100644
index 66a5733..0000000
--- a/gfs2/libgfs2/structures.c
+++ /dev/null
@@ -1,514 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <linux/types.h>
-
-#include "libgfs2.h"
-
-int build_master(struct gfs2_sbd *sdp)
-{
- struct gfs2_inum inum;
- uint64_t bn;
- struct gfs2_buffer_head *bh;
-
- bn = dinode_alloc(sdp);
- inum.no_formal_ino = sdp->md.next_inum++;
- inum.no_addr = bn;
-
- bh = init_dinode(sdp, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, &inum);
-
- sdp->master_dir = inode_get(sdp, bh);
-
- if (sdp->debug) {
- printf("\nMaster dir:\n");
- gfs2_dinode_print(&sdp->master_dir->i_di);
- }
- sdp->master_dir->bh_owned = 1;
- return 0;
-}
-
-void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid)
-{
- unsigned int x;
- struct gfs2_buffer_head *bh;
- struct gfs2_sb sb;
-
- /* Zero out the beginning of the device up to the superblock */
- for (x = 0; x < sdp->sb_addr; x++) {
- bh = bget(sdp, x);
- memset(bh->b_data, 0, sdp->bsize);
- bmodified(bh);
- brelse(bh);
- }
-
- memset(&sb, 0, sizeof(struct gfs2_sb));
- sb.sb_header.mh_magic = GFS2_MAGIC;
- sb.sb_header.mh_type = GFS2_METATYPE_SB;
- sb.sb_header.mh_format = GFS2_FORMAT_SB;
- sb.sb_fs_format = GFS2_FORMAT_FS;
- sb.sb_multihost_format = GFS2_FORMAT_MULTI;
- sb.sb_bsize = sdp->bsize;
- sb.sb_bsize_shift = ffs(sdp->bsize) - 1;
- sb.sb_master_dir = sdp->master_dir->i_di.di_num;
- sb.sb_root_dir = sdp->md.rooti->i_di.di_num;
- strcpy(sb.sb_lockproto, sdp->lockproto);
- strcpy(sb.sb_locktable, sdp->locktable);
-#ifdef GFS2_HAS_UUID
- memcpy(sb.sb_uuid, uuid, sizeof(sb.sb_uuid));
-#endif
- bh = bget(sdp, sdp->sb_addr);
- gfs2_sb_out(&sb, bh);
- brelse(bh);
-
- if (sdp->debug) {
- printf("\nSuper Block:\n");
- gfs2_sb_print(&sb);
- }
-}
-
-int write_journal(struct gfs2_sbd *sdp, unsigned int j, unsigned int blocks)
-{
- struct gfs2_log_header lh;
- unsigned int x;
- uint64_t seq = ((blocks) * (random() / (RAND_MAX + 1.0)));
- uint32_t hash;
- unsigned int height;
-
- /* Build the height up so our journal blocks will be contiguous and */
- /* not broken up by indirect block pages. */
- height = calc_tree_height(sdp->md.journal[j],
- (blocks + 1) * sdp->bsize);
- build_height(sdp->md.journal[j], height);
-
- memset(&lh, 0, sizeof(struct gfs2_log_header));
- lh.lh_header.mh_magic = GFS2_MAGIC;
- lh.lh_header.mh_type = GFS2_METATYPE_LH;
- lh.lh_header.mh_format = GFS2_FORMAT_LH;
- lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
-
- for (x = 0; x < blocks; x++) {
- struct gfs2_buffer_head *bh = get_file_buf(sdp->md.journal[j],
- x, TRUE);
- if (!bh)
- return -1;
- bmodified(bh);
- brelse(bh);
- }
- for (x = 0; x < blocks; x++) {
- struct gfs2_buffer_head *bh = get_file_buf(sdp->md.journal[j],
- x, FALSE);
- if (!bh)
- return -1;
-
- memset(bh->b_data, 0, sdp->bsize);
- lh.lh_sequence = seq;
- lh.lh_blkno = x;
- gfs2_log_header_out(&lh, bh);
- hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header));
- ((struct gfs2_log_header *)bh->b_data)->lh_hash = cpu_to_be32(hash);
-
- bmodified(bh);
- brelse(bh);
-
- if (++seq == blocks)
- seq = 0;
- }
-
- if (sdp->debug) {
- printf("\nJournal %u:\n", j);
- gfs2_dinode_print(&sdp->md.journal[j]->i_di);
- }
- return 0;
-}
-
-int build_journal(struct gfs2_sbd *sdp, int j, struct gfs2_inode *jindex)
-{
- char name[256];
- int ret;
-
- sprintf(name, "journal%u", j);
- sdp->md.journal[j] = createi(jindex, name, S_IFREG | 0600,
- GFS2_DIF_SYSTEM);
- ret = write_journal(sdp, j,
- sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
- return ret;
-}
-
-int build_jindex(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *jindex;
- unsigned int j;
- int ret;
-
- jindex = createi(sdp->master_dir, "jindex", S_IFDIR | 0700,
- GFS2_DIF_SYSTEM);
- sdp->md.journal = malloc(sdp->md.journals *
- sizeof(struct gfs2_inode *));
- for (j = 0; j < sdp->md.journals; j++) {
- ret = build_journal(sdp, j, jindex);
- if (ret)
- return ret;
- inode_put(&sdp->md.journal[j]);
- }
- if (sdp->debug) {
- printf("\nJindex:\n");
- gfs2_dinode_print(&jindex->i_di);
- }
-
- free(sdp->md.journal);
- inode_put(&jindex);
- return 0;
-}
-
-static int build_inum_range(struct gfs2_inode *per_node, unsigned int j)
-{
- struct gfs2_sbd *sdp = per_node->i_sbd;
- char name[256];
- struct gfs2_inode *ip;
-
- sprintf(name, "inum_range%u", j);
- ip = createi(per_node, name, S_IFREG | 0600,
- GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
- ip->i_di.di_size = sizeof(struct gfs2_inum_range);
- gfs2_dinode_out(&ip->i_di, ip->i_bh);
-
- if (sdp->debug) {
- printf("\nInum Range %u:\n", j);
- gfs2_dinode_print(&ip->i_di);
- }
-
- inode_put(&ip);
- return 0;
-}
-
-static void build_statfs_change(struct gfs2_inode *per_node, unsigned int j)
-{
- struct gfs2_sbd *sdp = per_node->i_sbd;
- char name[256];
- struct gfs2_inode *ip;
-
- sprintf(name, "statfs_change%u", j);
- ip = createi(per_node, name, S_IFREG | 0600,
- GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
- ip->i_di.di_size = sizeof(struct gfs2_statfs_change);
- gfs2_dinode_out(&ip->i_di, ip->i_bh);
-
- if (sdp->debug) {
- printf("\nStatFS Change %u:\n", j);
- gfs2_dinode_print(&ip->i_di);
- }
-
- inode_put(&ip);
-}
-
-static int build_quota_change(struct gfs2_inode *per_node, unsigned int j)
-{
- struct gfs2_sbd *sdp = per_node->i_sbd;
- struct gfs2_meta_header mh;
- char name[256];
- struct gfs2_inode *ip;
- unsigned int blocks = sdp->qcsize << (20 - sdp->sd_sb.sb_bsize_shift);
- unsigned int x;
- unsigned int hgt;
- struct gfs2_buffer_head *bh;
-
- memset(&mh, 0, sizeof(struct gfs2_meta_header));
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_QC;
- mh.mh_format = GFS2_FORMAT_QC;
-
- sprintf(name, "quota_change%u", j);
- ip = createi(per_node, name, S_IFREG | 0600, GFS2_DIF_SYSTEM);
-
- hgt = calc_tree_height(ip, (blocks + 1) * sdp->bsize);
- build_height(ip, hgt);
-
- for (x = 0; x < blocks; x++) {
- bh = get_file_buf(ip, x, FALSE);
- if (!bh)
- return -1;
-
- memset(bh->b_data, 0, sdp->bsize);
- gfs2_meta_header_out(&mh, bh);
- brelse(bh);
- }
-
- if (sdp->debug) {
- printf("\nQuota Change %u:\n", j);
- gfs2_dinode_print(&ip->i_di);
- }
-
- inode_put(&ip);
- return 0;
-}
-
-int build_per_node(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *per_node;
- unsigned int j;
-
- per_node = createi(sdp->master_dir, "per_node", S_IFDIR | 0700,
- GFS2_DIF_SYSTEM);
-
- for (j = 0; j < sdp->md.journals; j++) {
- build_inum_range(per_node, j);
- build_statfs_change(per_node, j);
- build_quota_change(per_node, j);
- }
-
- if (sdp->debug) {
- printf("\nper_node:\n");
- gfs2_dinode_print(&per_node->i_di);
- }
-
- inode_put(&per_node);
- return 0;
-}
-
-int build_inum(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *ip;
-
- ip = createi(sdp->master_dir, "inum", S_IFREG | 0600,
- GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
-
- if (sdp->debug) {
- printf("\nInum Inode:\n");
- gfs2_dinode_print(&ip->i_di);
- }
-
- sdp->md.inum = ip;
- return 0;
-}
-
-int build_statfs(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *ip;
-
- ip = createi(sdp->master_dir, "statfs", S_IFREG | 0600,
- GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
-
- if (sdp->debug) {
- printf("\nStatFS Inode:\n");
- gfs2_dinode_print(&ip->i_di);
- }
-
- sdp->md.statfs = ip;
- return 0;
-}
-
-int build_rindex(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *ip;
- osi_list_t *tmp, *head;
- struct rgrp_list *rl;
- char buf[sizeof(struct gfs2_rindex)];
- int count;
-
- ip = createi(sdp->master_dir, "rindex", S_IFREG | 0600,
- GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
- ip->i_di.di_payload_format = GFS2_FORMAT_RI;
- bmodified(ip->i_bh);
-
- for (head = &sdp->rglist, tmp = head->next; tmp != head;
- tmp = tmp->next) {
- rl = osi_list_entry(tmp, struct rgrp_list, list);
-
- gfs2_rindex_out(&rl->ri, buf);
-
- count = gfs2_writei(ip, buf, ip->i_di.di_size,
- sizeof(struct gfs2_rindex));
- if (count != sizeof(struct gfs2_rindex))
- return -1;
- }
-
- if (sdp->debug) {
- printf("\nResource Index:\n");
- gfs2_dinode_print(&ip->i_di);
- }
-
- inode_put(&ip);
- return 0;
-}
-
-int build_quota(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *ip;
- struct gfs2_quota qu;
- char buf[sizeof(struct gfs2_quota)];
- int count;
-
- ip = createi(sdp->master_dir, "quota", S_IFREG | 0600,
- GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
- ip->i_di.di_payload_format = GFS2_FORMAT_QU;
- bmodified(ip->i_bh);
-
- memset(&qu, 0, sizeof(struct gfs2_quota));
- qu.qu_value = 1;
- gfs2_quota_out(&qu, buf);
-
- count = gfs2_writei(ip, buf, ip->i_di.di_size, sizeof(struct gfs2_quota));
- if (count != sizeof(struct gfs2_quota))
- return -1;
- count = gfs2_writei(ip, buf, ip->i_di.di_size, sizeof(struct gfs2_quota));
- if (count != sizeof(struct gfs2_quota))
- return -1;
-
- if (sdp->debug) {
- printf("\nRoot quota:\n");
- gfs2_quota_print(&qu);
- }
-
- inode_put(&ip);
- return 0;
-}
-
-int build_root(struct gfs2_sbd *sdp)
-{
- struct gfs2_inum inum;
- uint64_t bn;
- struct gfs2_buffer_head *bh;
-
- bn = dinode_alloc(sdp);
- inum.no_formal_ino = sdp->md.next_inum++;
- inum.no_addr = bn;
-
- bh = init_dinode(sdp, &inum, S_IFDIR | 0755, 0, &inum);
- sdp->md.rooti = inode_get(sdp, bh);
-
- if (sdp->debug) {
- printf("\nRoot directory:\n");
- gfs2_dinode_print(&sdp->md.rooti->i_di);
- }
- sdp->md.rooti->bh_owned = 1;
- return 0;
-}
-
-int do_init_inum(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *ip = sdp->md.inum;
- uint64_t buf;
- int count;
-
- buf = cpu_to_be64(sdp->md.next_inum);
- count = gfs2_writei(ip, &buf, 0, sizeof(uint64_t));
- if (count != sizeof(uint64_t))
- return -1;
-
- if (sdp->debug)
- printf("\nNext Inum: %"PRIu64"\n",
- sdp->md.next_inum);
- return 0;
-}
-
-int do_init_statfs(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *ip = sdp->md.statfs;
- struct gfs2_statfs_change sc;
- char buf[sizeof(struct gfs2_statfs_change)];
- int count;
-
- sc.sc_total = sdp->blks_total;
- sc.sc_free = sdp->blks_total - sdp->blks_alloced;
- sc.sc_dinodes = sdp->dinodes_alloced;
-
- gfs2_statfs_change_out(&sc, buf);
- count = gfs2_writei(ip, buf, 0, sizeof(struct gfs2_statfs_change));
- if (count != sizeof(struct gfs2_statfs_change))
- return -1;
-
- if (sdp->debug) {
- printf("\nStatfs:\n");
- gfs2_statfs_change_print(&sc);
- }
- return 0;
-}
-
-int gfs2_check_meta(struct gfs2_buffer_head *bh, int type)
-{
- uint32_t check_magic = ((struct gfs2_meta_header *)(bh->b_data))->mh_magic;
- uint32_t check_type = ((struct gfs2_meta_header *)(bh->b_data))->mh_type;
-
- check_magic = be32_to_cpu(check_magic);
- check_type = be32_to_cpu(check_type);
- if((check_magic != GFS2_MAGIC) || (type && (check_type != type)))
- return -1;
- return 0;
-}
-
-/**
- * gfs2_next_rg_meta
- * @rgd:
- * @block:
- * @first: if set, start at zero and ignore block
- *
- * The position to start looking from is *block. When a block
- * is found, it is returned in block.
- *
- * Returns: 0 on success, -1 when finished
- */
-int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block, int first)
-{
- struct gfs2_bitmap *bits = NULL;
- uint32_t length = rgd->ri.ri_length;
- uint32_t blk = (first)? 0: (uint32_t)((*block+1)-rgd->ri.ri_data0);
- int i;
-
- if(!first && (*block < rgd->ri.ri_data0)) {
- log_err("next_rg_meta: Start block is outside rgrp bounds.\n");
- exit(1);
- }
- for(i=0; i < length; i++){
- bits = &rgd->bits[i];
- if(blk < bits->bi_len*GFS2_NBBY)
- break;
- blk -= bits->bi_len*GFS2_NBBY;
- }
- for(; i < length; i++){
- bits = &rgd->bits[i];
- blk = gfs2_bitfit((unsigned char *)rgd->bh[i]->b_data +
- bits->bi_offset, bits->bi_len, blk,
- GFS2_BLKST_DINODE);
- if(blk != BFITNOENT){
- *block = blk + (bits->bi_start * GFS2_NBBY) + rgd->ri.ri_data0;
- break;
- }
- blk=0;
- }
- if(i == length)
- return -1;
- return 0;
-}
-
-/**
- * next_rg_metatype
- * @rgd:
- * @block:
- * @type: the type of metadata we're looking for
- * @first: if set we should start at block zero and block is ignored
- *
- * Returns: 0 on success, -1 on error or finished
- */
-int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
- uint64_t *block, uint32_t type, int first)
-{
- struct gfs2_buffer_head *bh = NULL;
-
- do{
- if (bh)
- brelse(bh);
- if (gfs2_next_rg_meta(rgd, block, first))
- return -1;
- bh = bread(sdp, *block);
- first = 0;
- } while(gfs2_check_meta(bh, type));
- brelse(bh);
- return 0;
-}
diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
deleted file mode 100644
index 5d232a6..0000000
--- a/gfs2/libgfs2/super.c
+++ /dev/null
@@ -1,251 +0,0 @@
-#include <unistd.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "libgfs2.h"
-#include "osi_list.h"
-
-/**
- * check_sb - Check superblock
- * @sdp: the filesystem
- * @sb: The superblock
- *
- * Checks the version code of the FS is one that we understand how to
- * read and that the sizes of the various on-disk structures have not
- * changed.
- *
- * Returns: 0 on success, -1 on failure
- */
-int check_sb(struct gfs2_sb *sb)
-{
- if (sb->sb_header.mh_magic != GFS2_MAGIC ||
- sb->sb_header.mh_type != GFS2_METATYPE_SB) {
- log_crit("Either the super block is corrupted, or this "
- "is not a GFS2 filesystem\n");
- log_debug("Header magic: %X Header Type: %X\n",
- sb->sb_header.mh_magic,
- sb->sb_header.mh_type);
- return -EINVAL;
- }
- /* If format numbers match exactly, we're done. */
- if (sb->sb_fs_format != GFS2_FORMAT_FS ||
- sb->sb_multihost_format != GFS2_FORMAT_MULTI) {
- log_crit("Old gfs1 file system detected.\n");
- return -EINVAL;
- }
- return 0;
-}
-
-
-/*
- * read_sb: read the super block from disk
- * sdp: in-core super block
- *
- * This function reads in the super block from disk and
- * initializes various constants maintained in the super
- * block
- *
- * Returns: 0 on success, -1 on failure.
- */
-int read_sb(struct gfs2_sbd *sdp)
-{
- struct gfs2_buffer_head *bh;
- uint64_t space = 0;
- unsigned int x;
- int error;
-
- bh = bread(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
- gfs2_sb_in(&sdp->sd_sb, bh);
- brelse(bh);
-
- error = check_sb(&sdp->sd_sb);
- if (error)
- goto out;
-
- sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT;
- sdp->bsize = sdp->sd_sb.sb_bsize;
- sdp->sd_diptrs =
- (sdp->sd_sb.sb_bsize-sizeof(struct gfs2_dinode)) /
- sizeof(uint64_t);
- sdp->sd_inptrs =
- (sdp->sd_sb.sb_bsize-sizeof(struct gfs2_meta_header)) /
- sizeof(uint64_t);
- sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
- sdp->sd_hash_bsize = sdp->bsize / 2;
- sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1;
- sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
- sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
- sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs;
- for (x = 2; ; x++){
- space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs;
- /* FIXME: Do we really need this first check?? */
- if (space / sdp->sd_inptrs != sdp->sd_heightsize[x - 1] ||
- space % sdp->sd_inptrs != 0)
- break;
- sdp->sd_heightsize[x] = space;
- }
- if (x > GFS2_MAX_META_HEIGHT){
- log_err("Bad max metadata height.\n");
- error = -1;
- goto out;
- }
-
- sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
- sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs;
- for (x = 2; ; x++){
- space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs;
- if (space / sdp->sd_inptrs != sdp->sd_jheightsize[x - 1] ||
- space % sdp->sd_inptrs != 0)
- break;
- sdp->sd_jheightsize[x] = space;
- }
- sdp->sd_max_jheight = x;
- if(sdp->sd_max_jheight > GFS2_MAX_META_HEIGHT) {
- log_err("Bad max jheight.\n");
- error = -1;
- }
- sdp->fssize = lseek(sdp->device_fd, 0, SEEK_END) / sdp->sd_sb.sb_bsize;
- sdp->sb_addr = GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sdp->bsize;
-
- out:
-
- return error;
-}
-
-/**
- * rindex_read - read in the rg index file
- * @sdp: the incore superblock pointer
- * fd: optional file handle for rindex file (if meta_fs file system is mounted)
- * (if fd is <= zero, it will read from raw device)
- * @count1: return count of the rgs.
- * @sane: return whether rindex is consistent
- *
- * Returns: 0 on success, -1 on failure
- */
-int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane)
-{
- unsigned int rg;
- int error;
- struct gfs2_rindex buf;
- struct rgrp_list *rgd, *prev_rgd;
- uint64_t prev_length = 0;
-
- *sane = 1;
- *count1 = 0;
- prev_rgd = NULL;
- if (!fd && sdp->md.riinode->i_di.di_size % sizeof(struct gfs2_rindex))
- *sane = 0; /* rindex file size must be a multiple of 96 */
- for (rg = 0; ; rg++) {
- if (fd > 0)
- error = read(fd, &buf, sizeof(struct gfs2_rindex));
- else
- error = gfs2_readi(sdp->md.riinode, (char *)&buf,
- rg * sizeof(struct gfs2_rindex),
- sizeof(struct gfs2_rindex));
- if (!error)
- break;
- if (error != sizeof(struct gfs2_rindex))
- return -1;
-
- rgd = (struct rgrp_list *)malloc(sizeof(struct rgrp_list));
- if (!rgd) {
- log_crit("Cannot allocate memory for rindex.\n");
- exit(-1);
- }
- memset(rgd, 0, sizeof(struct rgrp_list));
- osi_list_add_prev(&rgd->list, &sdp->rglist);
-
- gfs2_rindex_in(&rgd->ri, (char *)&buf);
-
- rgd->start = rgd->ri.ri_addr;
- if (prev_rgd) {
- /* If rg addresses go backwards, it's not sane
- (or it's converted from gfs1). */
- if (prev_rgd->start >= rgd->start)
- *sane = 0;
- /* If rg lengths are not consistent, it's not sane
- (or it's converted from gfs1). The first RG will
- be a different length due to space allocated for
- the superblock, so we can't detect this until
- we check rgrp 3, when we can compare the distance
- between rgrp 1 and rgrp 2. */
- if (rg > 2 && prev_length &&
- prev_length != rgd->start - prev_rgd->start)
- *sane = 0;
- prev_length = rgd->start - prev_rgd->start;
- prev_rgd->length = prev_length;
- }
-
- if(gfs2_compute_bitstructs(sdp, rgd)) {
- *sane = 0;
- return -1;
- }
-
- (*count1)++;
- prev_rgd = rgd;
- }
- if (prev_rgd)
- prev_rgd->length = prev_length;
- return 0;
-}
-
-/**
- * ri_update - attach rgrps to the super block
- * @sdp: incore superblock data
- * fd: optional file handle for rindex (through the meta_fs)
- * @rgcount: returned count of rgs
- *
- * Given the rgrp index inode, link in all rgrps into the super block
- * and be sure that they can be read.
- *
- * Returns: 0 on success, -1 on failure.
- */
-int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int *sane)
-{
- struct rgrp_list *rgd;
- struct gfs2_rindex *ri;
- osi_list_t *tmp;
- int count1 = 0, count2 = 0;
- uint64_t errblock = 0;
- uint64_t rmax = 0;
-
- if (rindex_read(sdp, fd, &count1, sane))
- goto fail;
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
- errblock = gfs2_rgrp_read(sdp, rgd);
- if (errblock)
- return errblock;
- ri = &rgd->ri;
- if (ri->ri_data0 + ri->ri_data - 1 > rmax)
- rmax = ri->ri_data0 + ri->ri_data - 1;
- count2++;
- }
-
- sdp->fssize = rmax;
- *rgcount = count1;
- if (count1 != count2)
- goto fail;
-
- return 0;
-
- fail:
- gfs2_rgrp_free(&sdp->rglist);
- return -1;
-}
-
-int write_sb(struct gfs2_sbd *sbp)
-{
- struct gfs2_buffer_head *bh;
-
- bh = bread(sbp, GFS2_SB_ADDR >> sbp->sd_fsb2bb_shift);
- gfs2_sb_out(&sbp->sd_sb, bh);
- brelse(bh);
- fsync(sbp->device_fd); /* make sure the change gets to disk ASAP */
- return 0;
-}
-
diff --git a/gfs2/man/Makefile b/gfs2/man/Makefile
deleted file mode 100644
index 8e8e4f1..0000000
--- a/gfs2/man/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-MANTARGET= \
- gfs2.8 \
- gfs2_convert.8 \
- gfs2_edit.8 \
- fsck.gfs2.8 \
- gfs2_grow.8 \
- gfs2_jadd.8 \
- mount.gfs2.8 \
- gfs2_quota.8 \
- gfs2_tool.8 \
- mkfs.gfs2.8
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-all:
-
-clean:
diff --git a/gfs2/man/fsck.gfs2.8 b/gfs2/man/fsck.gfs2.8
deleted file mode 100644
index 462e918..0000000
--- a/gfs2/man/fsck.gfs2.8
+++ /dev/null
@@ -1,88 +0,0 @@
-.TH fsck.gfs2 8
-
-.SH NAME
-fsck.gfs2 - Offline GFS2 file system checker
-
-.SH SYNOPSIS
-.B fsck.gfs2
-[\fIOPTION\fR]... \fIDEVICE\fR
-
-.SH WARNING
-All GFS2 nodes \fImust\fP have the GFS2 filesystem unmounted before running
-fsck.gfs2. Failure to unmount all nodes may result in filesystem corruption.
-
-.SH DESCRIPTION
-fsck.gfs2 will check that the GFS2 file system on a device is structurally valid.
-It should not be run on a mounted file system. If file system corruption is
-detected, it will attempt to repair the file system. There is a limit to what
-fsck.gfs2 can do. If important file system structures are destroyed, such that
-the checker cannot determine what the repairs should be, reparations could
-fail.
-
-GFS2 is a journaled file system, and as such should be able to repair damage to
-the file system on its own. However, faulty hardware has the ability to write
-incomplete blocks to a file system thereby causing corruption that GFS2 cannot
-fix. The first step to ensuring a healthy file system is the selection of
-reliable hardware (i.e. storage systems that will write complete blocks - even
-in the event of power failure).
-
-Note: Most file system checkers will not check the file system if it is
-"clean" (i.e. unmounted since the last use). The fsck.gfs program behaves
-differently because the storage may be shared among several nodes in a
-cluster, and therefore problems may have been introduced on a different
-computer. Therefore, fsck.gfs2 will always check the file system unless
-the -p (preen) option is used, in which case it follows special rules
-(see below).
-
-.SH OPTIONS
-.TP
-\fB-a\fP
-Same as the -p (preen) option.
-.TP
-\fB-f\fP
-Force checking even if the file system seems clean.
-.TP
-\fB-h\fP
-Help.
-
-This prints out the proper command line usage syntax.
-.TP
-\fB-q\fP
-Quiet.
-.TP
-\fB-n\fP
-No to all questions.
-
-By specifying this option, fsck.gfs2 will only show the changes that
-would be made, but not make any changes to the filesystem.
-.TP
-\fB-p\fP
-Preen (same as -a: automatically repair the file system if it is dirty,
-and safe to do so, otherwise exit.)
-
-Note: If the file system has locking protocol lock_nolock, the file system
-is considered a non-shared storage device and the fsck is deemed safe.
-However, fsck.gfs2 does not know whether it was called automatically
-from the init process, due to options in the /etc/fstab file. Therefore, if
-the locking protocol is lock_dlm and -a or -p was specified, fsck.gfs2
-cannot determine whether the disk is mounted by other nodes in the cluster.
-Therefore, the fsck is deemed to be unsafe and a warning is given
-if any damage or dirty journals are found. In that case, the file system
-should be unmounted from all nodes in the cluster and fsck.gfs2 should be
-run manually without the -a or -p options.
-.TP
-\fB-V\fP
-Version.
-
-Print out the program version information.
-.TP
-\fB-v\fP
-Verbose operation.
-
-Print more information while running.
-.TP
-\fB-y\fP
-Yes to all questions.
-
-By specifying this option, fsck.gfs2 will not prompt before making
-changes.
diff --git a/gfs2/man/gfs2.8 b/gfs2/man/gfs2.8
deleted file mode 100644
index d2b50fc..0000000
--- a/gfs2/man/gfs2.8
+++ /dev/null
@@ -1,40 +0,0 @@
-.TH gfs2 8
-
-.SH NAME
-gfs2 \- GFS2 reference guide
-
-.SH SYNOPSIS
-Overview of manpages and their locations
-
-.SH DESCRIPTION
-The GFS2 documentation has been split into a number of sections. Please
-refer to the table below to determine which man page coincides with the
-command/feature you are looking for.
-.TP 16
-gfs2
-GFS2 overview (this man page)
-.TP
-mount.gfs2
-Mounting a GFS2 file system
-.TP
-gfs2_edit
-A GFS2 debug tool (use with caution)
-.TP
-fsck.gfs2
-The GFS2 file system checker
-.TP
-gfs2_grow
-Growing a GFS2 file system
-.TP
-gfs2_jadd
-Adding a journal to a GFS2 file system
-.TP
-mkfs.gfs2
-Make a GFS2 file system
-.TP
-gfs2_quota
-Manipulate GFS2 disk quotas
-.TP
-gfs2_tool
-Tool to manipulate a GFS2 file system
-
diff --git a/gfs2/man/gfs2_convert.8 b/gfs2/man/gfs2_convert.8
deleted file mode 100644
index 5969432..0000000
--- a/gfs2/man/gfs2_convert.8
+++ /dev/null
@@ -1,68 +0,0 @@
-.TH gfs2_convert 8
-
-.SH NAME
-gfs2_convert - Convert a GFS1 filesystem to GFS2
-
-.SH SYNOPSIS
-.B gfs2_convert
-[\fIOPTION\fR]... \fIDEVICE\fR
-
-.SH DESCRIPTION
-gfs2_convert is used to convert a filesystem from GFS1 to GFS2. It is
-required that the GFS1 filesystem be checked and fixed for errors using
-\fBgfs_fsck\fP and that the filesystem be backed up before
-attempting to convert it. The convert process is irreversible and any
-error encountered during the conversion can result in the abrupt
-termination of the program and consequently an unusable filesystem.
-See \fBNOTES\fP section below for more information.
-
-.SH OPTIONS
-.TP
-\fB-h\fP
-Help.
-
-This prints out the proper command line usage syntax.
-.TP
-\fB-q\fP
-Quiet. Print less information while running.
-.TP
-\fB-n\fP
-No to all questions.
-.TP
-\fB-V\fP
-Print program Version information only.
-
-Print out the current version name.
-.TP
-\fB-v\fP
-Verbose operation.
-
-Print more information while running.
-.TP
-\fB-y\fP
-Yes to all questions.
-
-By specifying this option, gfs2_convert will not prompt before making
-changes.
-
-.SH EXAMPLE
-.TP
-gfs2_convert /dev/vg0/lvol0
-This will convert the Global File System on the block device
-"/dev/vg0/lvol0" to gfs2 format.
-
-.SH NOTES
-If gfs2_convert is interrupted for some reason other than a conversion
-failure, DO NOT run \fBgfs2_fsck\fP on this partially converted filesystem.
-When this occurs, reissue the gfs2_convert command on the partially converted
-filesystem to complete the conversion process.
-
-The GFS2 filesystem does not support Context-Dependent Path Names (CDPNs).
-gfs2_convert identifies such CDPNs and replaces them with empty directories
-with the same name. The administrator can use bind mounts on these
-directories to get the same effect as CDPNs.
-
-When converting full or nearly full filesystems, it is possible that there
-won't be enough space available to fit all the GFS2 filesystem data
-structures. In such cases, the size of all the journals is reduced uniformly
-such that everything fits in the available space.
diff --git a/gfs2/man/gfs2_edit.8 b/gfs2/man/gfs2_edit.8
deleted file mode 100644
index 2546c7b..0000000
--- a/gfs2/man/gfs2_edit.8
+++ /dev/null
@@ -1,415 +0,0 @@
-.TH gfs2_edit 8
-
-.SH NAME
-gfs2_edit - Display, print or edit GFS2 or GFS internal structures.
-
-.SH SYNOPSIS
-.B gfs2_edit
-[\fIOPTION\fR]... [\fIDEVICE\fR]
-
-.SH DESCRIPTION
-The gfs2_edit command is a tool used to examine, edit or
-display internal data structures of a GFS2 or GFS file system.
-The gfs2_edit command can be run interactively, as described
-below in INTERACTIVE MODE.
-
-Caution: Several options of the gfs2_edit command alter the
-file system metadata and can cause file system corruption.
-These options should be used with great care.
-
-.SH OPTIONS
-.TP
-\fB-p\fP [\fIstruct\fR | \fIblock\fR] [\fIblocktype\fR] [\fIblockalloc [val]\fR] [\fIblockbits\fR] [\fIblockrg\fR] [\fIfind sb|rg|rb|di|in|lf|jd|lh|ld|ea|ed|lb|13|qc\fR] [\fIfield <field> [val]\fR]
-Print a gfs2 data structure in human-readable format to stdout.
-You can enter either a block number or a data structure name. Block numbers
-may be specified in hex (e.g., 0x10) or decimal (e.g., 16).
-
-You can specify the following well-known locations with the -p option.
-
-\fIsb\fR, \fIsuperblock\fR - Print the superblock.
-
-\fIroot\fR - Print the root directory.
-
-\fImaster\fR - Print the master system directory.
-
-\fIjindex\fR - Print the journal index system directory.
-
-\fIper_node\fR - Print the per_node system directory.
-
-\fIinum\fR - Print the system inum file.
-
-\fIstatfs\fR - Print the system statfs file.
-
-\fIrindex\fR, \fIrgindex\fR - Print the resource group index system file.
-
-\fIrg X\fR - Print the resource group information for RG X (zero-based).
-
-\fIrgs\fR - Print the resource group information.
-
-\fIquota\fR - Print the contents of the system quota file.
-
-\fIidentify\fR - Identify a data block rather than print the block's contents.
-
-\fIsize\fR - Print the device size information.
-
-\fIjournalX\fR - Print the contents of journal X, where X is a journal
-number from 0 to <the number of journals in your file system - 1>.
-Only the journal headers and journal descriptors are dumped. For journal
-descriptors, this option prints out every file system block number logged
-in that section of the journal. The actual journaled blocks are not printed.
-
-If you specify a block number rather than a structure name, gfs2_edit will
-print out a breakdown of the structure for that block.
-For example: \fBgfs2_edit -p sb\fP will print the superblock, but so does
-\fBgfs2_edit -p 0x10\fP and \fBgfs2_edit -p 16\fP.
-
-If you specify -p without a block or structure name, gfs2_edit prints the
-superblock.
-
-You can specify more than one data structure with a single -p option.
-For example, \fBgfs2_edit -p inum statfs /dev/sda1\fP prints the system inum
-file and the system statfs file on /dev/sda1.
-
-Optionally, you may specify the keyword \fIblocktype\fR to print out the
-gfs2 block type for the specified block. Valid gfs2 block types are:
-0 (Clump), 1 (Superblock), 2 (Resource Group Header), 3 (Resource Group
-Bitmap), 4 (Dinode), 5 (Indirect Block), 6 (Leaf), 7 (Journaled data),
-8 (Log Header), 9 (Log descriptor), 10 (Extended attribute),
-11 (Eattr Data), 12 (Log Buffer), 13 (Invalid), and 14 (Quota Change).
-
-Optionally, you may specify the keyword \fIblockalloc\fR with an
-optional value to assign. If no value is specified, the blockalloc
-keyword will print the block allocation type for the specified block.
-Valid block allocation types are: 0 (Free block), 1 (Data block),
-2 (Unlinked block), and 3 (Metadata block). If a value from 0 to 3 is
-specified, the resource group bitmap will be changed to the new value.
-This may be used, for example, to artificially free or allocate a block
-in order to test fsck.gfs2's ability to detect and fix the problem.
-
-Optionally, you may specify the keyword \fIblockbits\fR. This option
-will locate and print the block containing the bitmap corresponding to
-the specified block.
-
-Optionally, you may specify the keyword \fIblockrg\fR. This option
-will locate and print the block number of the resource group that holds
-information about the specified block.
-
-You may also use gfs2_edit to find the next occurrence of a metadata
-block of a certain type. Valid metadata types are: \fInone\fR (unused
-metadata clump block), \fIsb\fR (superblock), \fIrg\fR (resource group),
-\fIrb\fR (rg bitmap), \fIdi\fR (disk inode aka dinode), \fIin\fR (indirect
-block list), \fIlf\fR (directory leaf), \fIjd\fR (journaled data),
-\fIlh\fR (journal log header), \fIld\fR (journal log descriptor),
-\fIea\fR (extended attribute), \fIed\fR (ea data block), \fIlb\fR (log buffer),
-\fI13\fR (unused block type 13), \fIqc\fR (quota change).
-The block AFTER the one specified with -p is the starting point for
-the search. For example, if you specify \fBgfs2_edit -p rg 12 find rg
-/dev/your/device\fP, it will find the rg that follows rg 12 (normally,
-this would be rg 13). Note, however, that since metadata often appears
-in the journals, it could be a copy of a different RG, inside a journal.
-Also note that gfs2_edit will only find \fBallocated\fR metadata blocks
-unless the type specified is none, sb, rg or rb. In other words, if you
-try to find a disk inode, it will only find an allocated dinode, not a
-deallocated one.
-
-Optionally, you may specify the keyword \fIfield\fR followed by a
-valid metadata field name. Right now, only the fields in disk inodes
-and resource groups are allowed. If no value is specified after the
-field, the value of the field will be printed to stdout. If a value
-is specified, the field's value will be changed. This may be used,
-for example, to artificially change the di_size field for an inode
-in order to test fsck.gfs2's ability to detect and fix the problem.
-
-.TP
-\fB-s\fs [\fIstructure\fR | \fIblock\fR]
-Specify a starting block for interactive mode. Any of the well-known
-locations found in the -p option may be specified. If you want to start
-on a particular resource group, specify it in quotes, e.g. -s "rg 3"
-.TP
-\fB-h, -help, -usage\fP
-Print help information.
-.TP
-\fB-c\fP [\fI0\fR | \fI1\fR]
-Use alternate color scheme for interactive mode: 0=normal (dark colors on
-white background), or 1 (light colors on black background).
-.TP
-\fB-V\fP
-Print program version information only.
-.TP
-\fB-x\fP
-Print in hex mode.
-
-.TP
-\fBrg\fP \fI<rg>\fR \fI<device>\fR
-Print the contents of Resource Group \fI<rg>\fR on \fI<device>\fR.
-
-\fI<rg>\fR is a number from 0 to X - 1, where X is the number of RGs.
-.TP
-\fBrgcount\fP \fI<device>\fR
-Print the number of Resource Groups in the file system on \fI<device>\fR.
-.TP
-\fBrgflags\fP \fI<rg>\fR [\fInew_value\fR] \fI<device>\fR
-Print and/or modify the rg_flags value of Resource Group \fI<rg>\fR on
-\fI<device>\fR.
-
-\fI<rg>\fR is a number from 0 to X - 1, where X is the number of RGs.
-If \fInew_value\fR is not specified, the current rg_flags value will be
-printed but not modified. If \fInew_value\fR is specified, the rg_flags
-field will be overwritten with the new value.
-.TP
-\fBprintsavedmeta\fP \fI<filename>\fR
-Print off a list of blocks from <filename> that were saved with the savemeta
-option.
-.TP
-\fBsavemeta\fP \fI<device>\fR \fI<filename>\fR
-Save off the GFS2 metadata (not user data) for the file system on the
-specified device to a file given by <filename>. You can use this option
-to analyze file system problems without revealing sensitive information
-that may be contained in the files. This option works quickly by
-using the system bitmap blocks in the resource groups to determine the
-location of all the metadata. If there is corruption
-in the bitmaps, resource groups or rindex file, this method may fail and
-you may need to use the savemetaslow option.
-The destination file is not compressed. You may want to compress it
-with a program such as bzip2 before sending it for analysis.
-.TP
-\fBsavemetaslow\fP \fI<device>\fR \fI<filename>\fR
-Save off GFS2 metadata, as with the savemeta option, examining every
-block in the file system for metadata. This option is less prone to failure
-due to file system corruption than the savemeta option, but it is
-extremely slow.
-.TP
-\fBsavergs\fP \fI<device>\fR \fI<filename>\fR
-Save off only the GFS2 resource group metadata for the file system on the
-specified device to a file given by <filename>.
-.TP
-\fBrestoremeta\fP \fI<filename>\fR \fI<dest device>\fR
-Take a file created with the savemeta option and restores its
-contents on top of the specified destination device. \fBWARNING\fP:
-When you use this option, the file system and all data on the
-destination device is destroyed. Since only metadata (but no data)
-is restored, every file in the resulting file system is likely to be
-corrupt. The ONLY purpose of this option is to examine and debug file
-system problems by restoring and examining the state of the saved metadata.
-If the destination file system is the same size or larger than the source
-file system where the metadata was saved, the resulting file system
-will be the same size as the source. If the destination device is
-smaller than the source file system, gfs2_edit will restore as much as
-it can, then quit, leaving you with a file system that probably will not
-mount, but from which you might still be able to figure out what is
-wrong with the source file system.
-
-.SH INTERACTIVE MODE
-If you specify a device on the gfs2_edit command line and you specify
-no options other than -c, gfs2_edit will act as an interactive GFS2
-file system editor for the file system you specify. There
-are three display modes: hex mode, structure mode and pointers mode.
-You use the m key to switch between the modes, as described below.
-The modes are as follows:
-.TP
-Hex mode (default)
-Display or edit blocks of the file system in hexadecimal and ascii.
-
-Lines at the top indicate the currently displayed block in both hex and
-decimal. If the block contains a GFS2 data structure, the name of that
-structure will appear in the upper right corner of the display.
-If the block is a well-known block, such as the superblock or rindex,
-there will be a line to indicate what it is.
-
-In hex mode, you can edit blocks by pressing \fB<enter>\fP and entering
-hexadecimal digits to replace the highlighted hex digits. Do NOT precede
-the numbers with "0x". For example, if you want to change the value at
-offset 0x60 from a 0x12 to 0xef, position your cursor to offset 0x60,
-so that the 12 is highlighted, then press \fB<enter>\fP and type in "ef".
-Press \fB<escape>\fP or \fB<enter>\fP to exit edit mode.
-
-In hex mode, different colors indicate different things.
-For example, in the default color scheme, the GFS2 data structure will
-be black, data offsets will be light blue, and actual data (anything after
-the gfs2 data structure) will be red.
-
-.TP
-Structure mode
-Decode the file system block into its GFS2 structure and
-display the values of that structure. This mode is most useful for
-jumping around the file system. For example, you can use the arrow
-keys to position down to a pointer and press \fBJ\fP to jump to that block.
-
-.TP
-Pointers mode
-Display any additional information appearing on the block.
-For example, if an inode has block pointers, this will display them and
-allow you to scroll through them. You can also position to one of them
-and press \fBJ\fP to jump to that block.
-
-.SH Interactive mode command keys:
-.TP
-\fBq\fP or \fB<esc>\fP
-The \fBq\fP or \fB<escape>\fP keys are used to exit gfs2_edit.
-
-.TP
-\fB<arrow/movement keys>\fP up, down, right, left, pg-up, pg-down, home, end
-The arrow keys are used to highlight an area of the display. The \fBJ\fP
-key may be used to jump to the block that is highlighted.
-
-.TP
-\fBm\fP - Mode switch
-The \fBm\fP key is used to switch between the three display modes.
-The initial mode is hex mode. Pressing the \fBm\fP key once switches to
-structure mode. Pressing it a second time switches from structure mode
-to pointers mode. Pressing it a third time takes you back to hex mode again.
-
-.TP
-\fBj\fP - Jump to block
-The \fBj\fP key jumps to the block number that is currently highlighted.
-In hex mode, hitting J will work when any byte of the pointer is highlighted.
-
-.TP
-\fBg\fP - Goto block
-The \fBg\fP key asks for a block number, then jumps there. Note that
-in many cases, you can also arrow up so that the current block number
-is highlighted, then press \fB<enter>\fP to enter a block number to jump to.
-
-.TP
-\fBh\fP - Help display
-The \fBh\fP key causes the interactive help display to be shown.
-
-.TP
-\fBe\fP - Extended mode
-The \fBe\fP key causes gfs2_edit to switch to extended ("pointers") mode.
-
-.TP
-\fBc\fP - Color scheme
-The \fBc\fP key causes gfs2_edit to switch to its alternate color scheme.
-
-.TP
-\fBf\fP - Forward block
-The \fBf\fP key causes you to scroll forward one block. This does
-not affect the "jump" status. In other words, if you use the \fBf\fP
-key to move forward several blocks, pressing \fB<backspace>\fP will
-not roll you back up.
-
-.TP
-\fB<enter>\fP - Edit value
-The \fB<enter>\fP key causes you to go from display mode to edit mode.
-If you are in hex mode and you hit enter, you can type new hex values
-at the cursor's current location. Note: pressing \fB<enter>\fP
-in structure mode allows you to enter a new value, with the following
-restrictions: For gfs2 disk inodes and resource groups, it will
-actually change the value on disk. However, inode numbers may not be
-changed. For all other structures, the values entered are ignored.
-
-If you use the up arrow key to highlight the block number, then press
-\fB<enter>\fP, you may then enter a new block number, or any of the
-well-known block locations listed above (e.g. sb, rindex, inum, rg 17,
-etc.) and gfs2_edit will jump to the block specified. If you specify
-a slash character followed by a metadata type, gfs2_edit will search for
-the next occurrence of that metadata block type, and jump there. It
-will take you to block 0 if it does not find any more blocks of the
-specified metadata type.
-
-.TP
-\fB<home>\fP
-If you are in pointers mode, this takes you back to the starts of the
-pointers you are viewing. Otherwise it takes you back to the superblock.
-
-.TP
-\fB<backspace>\fP
-This takes you back to the block you were displaying before a jump.
-
-.TP
-\fB<space>\fP
-This takes you forward to the block you were displaying when you hit
-\fB<backspace>\fP.
-
-.SH EXAMPLES
-.TP
-gfs2_edit /dev/roth_vg/roth_lv
-Display and optionally edit the file system on /dev/roth_vg/roth_lv
-
-.TP
-gfs2_edit -p sb /dev/vg0/lvol0
-Print the superblock of the gfs2 file system located on
-/dev/vg0/lvol0.
-
-.TP
-gfs2_edit -p identify 2746 2748 /dev/sda2
-Print out what kind of blocks are at block numbers 2746 and 2748 on
-device /dev/sda2.
-
-.TP
-gfs2_edit -p rindex /dev/sda1
-Print the resource group index system file located on device
-/dev/sda1.
-
-.TP
-gfs2_edit savemeta /dev/sda1 /tmp/our_fs
-Save off all metadata (but no user data) to file /tmp/our_fs.
-
-.TP
-gfs2_edit -p root /dev/my_vg/my_lv
-Print the contents of the root directory in /dev/my_vg/my_lv.
-
-.TP
-gfs2-edit -x -p 0x3f7a /dev/sda1
-Print the contents of block 16250 of /dev/sda1 in hex.
-
-.TP
-gfs2_edit -p 12345 /dev/sdc2
-Print the gfs2 data structure at block 12345.
-
-.TP
-gfs2_edit rgcount /dev/sdb1
-Print how many Resource Groups exist for /dev/sdb1.
-
-.TP
-gfs2_edit -p rg 17 /dev/sdb1
-Print the contents of the eighteenth Resource Group on /dev/sdb1.
-
-.TP
-gfs2_edit rgflags 3 /dev/sdb1
-Print the rg_flags value for the fourth Resource Group on /dev/sdb1.
-
-.TP
-gfs2_edit rgflags 3 8 /dev/sdb1
-Set the GFS2_RGF_NOALLOC flag on for the fourth Resource Group on /dev/sdb1.
-
-.TP
-gfs2_edit -p 25 blockalloc /dev/roth_vg/roth_lv
-Print the block allocation type of block 25.
-May produce this output:
-3 (Metadata)
-
-.TP
-gfs2_edit -p 25 blockalloc 1 /dev/roth_vg/roth_lv
-Change the block allocation type of block 25 to data.
-May produce this output:
-1
-
-.TP
-gfs2_edit -p 25 blocktype /dev/roth_vg/roth_lv
-Print the metadata block type of block 25.
-May produce this output:
-4 (Block 25 is type 4: Dinode)
-
-.TP
-gfs2_edit -p 25 field di_size /dev/roth_vg/roth_lv
-Print the di_size field of block 25.
-May produce this output:
-134217728
-
-.TP
-gfs2_edit -x -p 25 field di_size /dev/roth_vg/roth_lv
-Print the di_size field of block 25, in hexidecimal.
-May produce this output:
-0x8000000
-
-.TP
-gfs2_edit -p 25 field di_size 0x4000 /dev/roth_vg/roth_lv
-Change the di_size field of block 25 to the hexidecimal value 0x4000.
-May produce this output:
-16384
-.SH KNOWN BUGS
-.TP
-The directory code does not work well. It might be confused
-by directory "sentinel" entries.
diff --git a/gfs2/man/gfs2_grow.8 b/gfs2/man/gfs2_grow.8
deleted file mode 100644
index 317d4f2..0000000
--- a/gfs2/man/gfs2_grow.8
+++ /dev/null
@@ -1,66 +0,0 @@
-.TH gfs2_grow 8
-
-.SH NAME
-gfs2_grow - Expand a GFS2 filesystem
-
-.SH SYNOPSIS
-.B gfs2_grow
-[\fIOPTION\fR]... <\fIDEVICE\fR|\fIMOUNTPOINT\fR>...
-
-.SH DESCRIPTION
-gfs2_grow is used to expand a GFS2 filesystem after the device
-upon which the filesystem resides has also been expanded. By
-running gfs2_grow on a GFS2 filesystem, you are requesting that
-any spare space between the current end of the filesystem and
-the end of the device is filled with a newly initialized GFS2
-filesystem extension. When this operation is complete, the resource
-group index for the filesystem is updated so that all nodes in the
-cluster can use the extra storage space that has been added.
-
-You may only run gfs2_grow on a mounted filesystem; expansion of
-unmounted filesystems is not supported. You only need to
-run gfs2_grow on one node in the cluster. All the other nodes will
-see the expansion has occurred and automatically start to use the
-newly available space.
-
-You must be superuser to execute \fBgfs2_grow\fP. The gfs2_grow
-tool tries to prevent you from corrupting your filesystem by checking as
-many of the likely problems as it can. When expanding a filesystem,
-only the last step of updating the resource index affects the currently
-mounted filesystem and so failure part way through the expansion process
-should leave your filesystem in its original unexpanded state.
-
-You can run gfs2_grow with the \fB-T\fP flag to get a display
-of the current state of a mounted GFS2 filesystem.
-
-The gfs2_grow tool uses the resource group (RG) size that was originally
-calculated when mkfs.gfs2 was done. This allows tools like fsck.gfs2
-to better ensure the integrity of the file system. Since the new free
-space often does not lie on even boundaries based on that RG size,
-there may be some unused space on the device after gfs2_grow is run.
-.SH OPTIONS
-.TP
-\fB-D\fP
-Print out debugging information about the filesystem layout.
-.TP
-\fB-h\fP
-Prints out a short usage message and exits.
-.TP
-\fB-q\fP
-Be quiet. Don't print anything.
-.TP
-\fB-T\fP
-Test. Do all calculations, but do not write any data to the disk and do
-not expand the filesystem. This is used to discover what the tool would
-have done were it run without this flag.
-.TP
-\fB-V\fP
-Version. Print out version information, then exit.
-
-.SH BUGS
-
-There is no way to shrink a GFS2 filesystem.
-
-.SH SEE ALSO
-mkfs.gfs2(8) gfs2_jadd(8)
-
diff --git a/gfs2/man/gfs2_jadd.8 b/gfs2/man/gfs2_jadd.8
deleted file mode 100644
index a645fb7..0000000
--- a/gfs2/man/gfs2_jadd.8
+++ /dev/null
@@ -1,60 +0,0 @@
-.TH gfs2_jadd 8
-
-.SH NAME
-gfs2_jadd \- Add journals to a GFS2 filesystem
-
-.SH SYNOPSIS
-.B gfs2_jadd
-[\fIOPTION\fR]... <\fIDEVICE\fR|\fIMOINTPOINT\fR>...
-
-.SH DESCRIPTION
-\fIgfs2_jadd\fR is used to add journals (and a few other per-node
-files) to a GFS2 filesystem. When this operation is complete, the
-journal index is updated so that machines mounting the filesystem at a
-later date will see the newly created journals in addition to the
-journals already there. Machines which are already running in the
-cluster are unaffected.
-
-You may only run \fIgfs2_jadd\fR on a mounted filesystem, addition of
-journals to unmounted filesystems is not supported. You only need to
-run \fIgfs2_jadd\fR on one node in the cluster. All the other nodes
-will see the expansion has occurred when required.
-
-You must be superuser to execute \fIgfs2_jadd\fR. The \fIgfs2_jadd\fR
-tool tries to prevent you from corrupting your filesystem by checking
-as many of the likely problems as it can. When growing a filesystem,
-only the last step of updating the journal index affects the currently
-mounted filesystem and so failure part way through the expansion
-process should leave your filesystem in its original state.
-
-.SH OPTIONS
-.TP
-\fB-c MegaBytes\fP
-Initial size of each journal's quota change file
-.TP
-\fB-D\fP
-Print out debugging information about the filesystem layout.
-.TP
-\fB-h\fP
-Prints out a short usage message and exits.
-.TP
-\fB-J size\fP
-The size of the new journals in megabytes. The defaults to 32MB (the
-minimum size allowed is 8MB). If you want to add journals of different
-sizes to the filesystem, you'll need to run gfs2_jadd once for each
-different size of journal.
-.TP
-\fB-j num\fP
-The number of new journals to add.
-.TP
-\fB-q\fP
-Be quiet. Don't print anything.
-.TP
-\fB-u MegaBytes\fP
-Initial size of each journal's unlinked tag file
-.TP
-\fB-V\fP
-Version. Print version information, then exit.
-.
-.SH SEE ALSO
-mkfs.gfs2(8) gfs2_grow(8)
diff --git a/gfs2/man/gfs2_quota.8 b/gfs2/man/gfs2_quota.8
deleted file mode 100644
index 04e09e8..0000000
--- a/gfs2/man/gfs2_quota.8
+++ /dev/null
@@ -1,105 +0,0 @@
-.TH gfs2_quota 8
-
-.SH NAME
-gfs2_quota - Manipulate GFS2 disk quotas
-
-.SH SYNOPSIS
-.B gfs2_quota
-<list|sync|get|limit|warn|check|init|reset> [\fIOPTION\fR]...
-
-.SH DESCRIPTION
-gfs2_quota is used to examine and change quota values in a GFS2 filesystem.
-This command has a number of different actions.
-
-GFS2 introduced a new linked list format for the quotas in the quota file.
-This list format allows for faster \fBlist\fP, \fBcheck\fP and \fBinit\fP
-operations. Older GFS2 quota files may be migrated to this newer format using
-the \fBgfs2_quota reset\fP command.
-
-.SH ACTIONS
-.TP
-\fBlist\fP
-List the contents of the quota file. Only IDs that have a non-zero hard limit,
-warn limit, or value are printed.
-.TP
-\fBsync\fP
-Sync any local quota changes to the quota file.
-.TP
-\fBget\fP
-Get the current data for the ID specified by the -u or -g argument.
-.TP
-\fBlimit\fP
-Set the current hard limit for the ID specified by the -u or -g argument to
-the value specified by the -l argument on the specified filesystem.
-The filesystem won't let the user or group use more than this much space.
-A value of zero here means that no limit is enforced.
-.TP
-\fBwarn\fP
-Set the current warn limit for the ID specified by the -u or -g argument to
-the value specified by the -l argument on the specified filesystem.
-The filesystem will start complaining to the user or group when more
-than this much space is used. A value of zero here means that the
-user won't ever be warned.
-.TP
-\fBcheck\fP
-Scan a filesystem and make sure that what's out there on the disk matches
-what's in the quota file. This is only accurate if the filesystem is
-idle when this is running. If there is a mismatch, it is printed to
-stdout. Note: GFS2 quotas are transactional and a quota check is \fBnot\fP
-needed every time there is a system crash.
-.TP
-\fBinit\fP
-Scan a filesystem and initialize the quota file with the values obtained
-from the scan. The filesystem should be idle when this is run. You should
-only need to do this if you upgrade a pre-quota GFS2 filesystem (pre-GFS2 5.1).
-.TP
-\fBreset\fP
-The \fBreset\fP operation will truncate the quota file and all quota
-information (values, limits, warnings) will be lost. All quota limits and
-warnings will have to be reassigned after this operation.
-
-.SH OPTIONS
-\fB-b\fP
-The units for disk space are filesystem blocks.
-.TP
-\fB-f\fP \fIDirectory\fR
-Specifies which filesystem to perform the action on.
-.TP
-\fB-g\fP \fIGID\fR
-Specifies the group ID for get, limit, or warn. It can be either
-the group name from the group file, or the GID number.
-.TP
-\fB-h\fP
-Print out a help message describing available
-options, then exit.
-.TP
-\fB-k\fP
-The units for disk space are kilobytes.
-.TP
-\fB-l\fP \fISize\fR
-Specifies the new value for the limit or warn actions.
-The value is assumed to be in the units specified by the
--m, -k, -s, -b arguments. The default is megabytes.
-.TP
-\fB-m\fP
-The units for disk space are megabytes. This is the default.
-.TP
-\fB-n\fP
-Don't try to resolve UIDs and GIDs into user and group names.
-.TP
-\fB-s\fP
-The units for disk space are sectors (512-byte blocks).
-.TP
-\fB-u\fP \fIUID\fR
-Specifies the user ID for get, limit, or warn. It can be either
-the username from the password file, or the UID number.
-.TP
-\fB-V\fP
-Print program version information, then exit.
-
-.SH EXAMPLE
-To set the hard limit for user "nobody" to
-1048576 kilobytes on filesystem /gfs20
-
-gfs2_quota limit -l 1048576 -k -u nobody -f /gfs20
-
diff --git a/gfs2/man/gfs2_tool.8 b/gfs2/man/gfs2_tool.8
deleted file mode 100644
index dccd631..0000000
--- a/gfs2/man/gfs2_tool.8
+++ /dev/null
@@ -1,117 +0,0 @@
-.TH gfs2_tool 8
-
-.SH NAME
-gfs2_tool - interface to gfs2 ioctl/sysfs calls
-
-.SH SYNOPSIS
-.B gfs2_tool
-\fICOMMAND\fR [\fIOPTION\fR]...
-
-.SH DESCRIPTION
-gfs2_tool is an interface to a variety of the GFS2 ioctl/sysfs calls. Some
-of the functions of gfs_tool have been replaced by standard system tools
-such as mount and chattr, so gfs2_tool doesn't have as many options
-as gfs_tool used to.
-
-.SH COMMANDS
-.TP
-\fBclearflag\fP \fIFlag\fR \fIFile1\fR \fIFile2\fR \fI...\fR
-Clear an attribute flag on a file. This is now obsolete and kept
-only for backward compatibility, chattr is the preferred way to
-clear attribute flags. See \fBsetflag\fP for available flags. This
-option will probably be removed at a future date.
-.TP
-\fBfreeze\fP \fIMountPoint\fR
-Freeze (quiesce) a GFS2 cluster.
-.TP
-\fBgettune\fP \fIMountPoint\fR
-Print out the current values of the tuning parameters in a running
-filesystem. A better source of similar (more comprehensive) information
-is that in the /proc/mounts file. Running the mount command with no
-arguments will also provide the same information. This option is
-considered obsolete and will probably be removed at some future
-date.
-.TP
-\fBjournals\fP \fIMountPoint\fR
-Print out information about the journals in a mounted filesystem.
-.TP
-\fBlockdump\fP \fIMountPoint\fR
-Print out information about the locks this machine holds for a given
-filesystem. This information is also available via the debugfs
-glock dump file, and accessing that file is the preferred method
-of obtaining a dump of the glock state.
-.\".TP
-.\"\fBrindex\fP \fIMountPoint\fR
-.\"Print out the resource group index of a mounted filesystem.
-.TP
-\fBsb\fP \fIdevice\fR \fBproto\fP \fI[newvalue]\fR
-View (and possibly replace) the name of the locking protocol in the
-file system superblock. The file system shouldn't be mounted by any
-client when you do this.
-.TP
-\fBsb\fP \fIdevice\fR \fBtable\fP \fI[newvalue]\fR
-View (and possibly replace) the name of the locking table in the
-file system superblock. The file system shouldn't be mounted by any
-client when you do this.
-.TP
-\fBsb\fP \fIdevice\fR \fBondisk\fP \fI[newvalue]\fR
-View (and possibly replace) the ondisk format number in the
-file system superblock. The file system shouldn't be mounted by any
-client when you do this. No one should have to use this.
-.TP
-\fBsb\fP \fIdevice\fR \fBmultihost\fP \fI[newvalue]\fR
-View (and possibly replace) the multihost format number in the
-file system superblock. The file system shouldn't be mounted by any
-client when you do this. No one should have to use this.
-.TP
-\fBsb\fP \fIdevice\fR \fBuuid\fP \fI[newvalue]\fR
-View (and possibly replace) the uuid in the file system superblock.
-The file system shouldn't be mounted by any client when you do this.
-The new uuid value should be in the standard uuid format. For
-example: 1AEA8269-15C5-72BD-6D83-8720B17AA4EE
-.TP
-\fBsb\fP \fIdevice\fR \fBall\fP
-Print out the superblock.
-.TP
-\fBsetflag\fP \fIFlag\fR \fIFile1\fR \fIFile2\fR \fI...\fR
-Set an attribute flag on a file. The currently supported flags are
-jdata, immutable, appendonly, noatime, and sync. The
-chattr command is the preferred way to set attributes on
-files. This option will probably be removed at a future date.
-
-The \fIjdata\fR flag causes all the data written to a file
-to be journaled. If the \fIjdata\fR flag is set for a directory,
-all files and directories subsequently created within that directory
-are also journaled. This behavior replaces the old \fIinherit_jdata\fR
-flag from gfs. Same as chattr +j.
-
-The \fIimmutable\fR flag marks the file immutable. The behavior is
-similar to the immutable flag in the ext2/3 filesystems. All write
-access is denied. Same as chattr +i.
-
-The \fIappendonly\fR flag causes all data to be written at the end of
-the file. Same as chattr +a.
-
-The \fInoatime\fR flag disables updates to the file's access time.
-Same as chattr +A.
-
-The \fIsync\fR flag causes data written to the file to be sync'ed to
-stable storage immediately. Same as chattr +S.
-.TP
-\fBsettune\fP \fIMountPoint\fR \fIparameter\fR \fInewvalue\fR
-Set the value of tuning parameter. Use \fBgettune\fP for a listing of
-tunable parameters. The mount -oremount command is the preferred way
-to set the values of tunable parameters. At some future stage, when
-all parameters can be set via mount, this option will be removed.
-.TP
-\fBunfreeze\fP \fIMountPoint\fR
-Unfreeze a GFS2 cluster.
-.TP
-\fBversion\fP
-Print out the version of GFS2 that this program goes with.
-.TP
-\fBwithdraw\fP \fIMountPoint\fR
-Cause GFS2 to abnormally shutdown a given filesystem on this node.
-This feature is only useful for testing and should not be used
-during normal filesystem operation.
-
diff --git a/gfs2/man/mkfs.gfs2.8 b/gfs2/man/mkfs.gfs2.8
deleted file mode 100644
index 279c12f..0000000
--- a/gfs2/man/mkfs.gfs2.8
+++ /dev/null
@@ -1,95 +0,0 @@
-.TH mkfs.gfs2 8
-
-.SH NAME
-mkfs.gfs2 - Make a GFS2 filesystem
-
-.SH SYNOPSIS
-.B mkfs.gfs2
-[\fIOPTION\fR]... \fIDEVICE\fR \fI[ block-count ]\fR
-
-.SH DESCRIPTION
-mkfs.gfs2 is used to create a Global File System.
-
-.SH OPTIONS
-.TP
-\fB-b\fP \fIBlockSize\fR
-Set the filesystem block size to \fIBlockSize\fR (must be a power of
-two). The minimum block size is 512. The FS block size cannot exceed
-the machine's memory page size. On the most architectures (i386,
-x86_64, s390, s390x), the memory page size is 4096 bytes. On other
-architectures it may be bigger. The default block size is 4096 bytes.
-In general, GFS2 filesystems should not deviate from the default value.
-.TP
-\fB-c\fP \fIMegaBytes\fR
-Initial size of each journal's quota change file
-.TP
-\fB-D\fP
-Enable debugging output.
-.TP
-\fB-h\fP
-Print out a help message describing available
-options, then exit.
-.TP
-\fB-J\fP \fIMegaBytes\fR
-The size of the journals in Megabytes. The default journal size is
-128 megabytes. The minimum size is 8 megabytes.
-.TP
-\fB-j\fP \fINumber\fR
-The number of journals for gfs2_mkfs to create. You need at least one
-journal per machine that will mount the filesystem. If this option is
-not specified, one journal will be created.
-.TP
-\fB-O\fP
-This option prevents gfs2_mkfs from asking for confirmation before writing
-the filesystem.
-.TP
-\fB-p\fP \fILockProtoName\fR
-LockProtoName is the name of the locking protocol to use. Acceptable
-locking protocols are \fIlock_dlm\fR (for shared storage) or if you are
-using GFS2 as a local filesystem (\fB1 node only\fP), you can specify the
-\fIlock_nolock\fR protocol. If this option is not specified,
-\fIlock_dlm\fR protocol will be assumed.
-.TP
-\fB-q\fP
-Be quiet. Don't print anything.
-.TP
-\fB-r\fP \fIMegaBytes\fR
-gfs2_mkfs will try to make Resource Groups about this big.
-Minimum RG size is 32 MB. Maximum RG size is 2048 MB.
-A large RG size may increase performance on very large file systems.
-If not specified, mkfs.gfs2 will choose the RG size based on the size
-of the file system: average size file systems will have 256 MB RGs, and
-bigger file systems will have bigger RGs for better performance.
-.TP
-\fB-t\fP \fILockTableName\fR
-The lock table field appropriate to the lock module you're using.
-It is \fIclustername:fsname\fR.
-Clustername must match that in cluster.conf; only members of this
-cluster are permitted to use this file system.
-Fsname is a unique file system name used to distinguish this GFS2 file
-system from others created (1 to 16 characters). Lock_nolock doesn't
-use this field.
-.TP
-\fB-u\fP \fIMegaBytes\fR
-Initial size of each journal's unlinked tag file
-.TP
-\fB-V\fP
-Print program version information, then exit.
-
-.TP
-[ \fIblock-count\fR ]
-Make the file system this many blocks in size. If not specified, the
-entire length of the specified device is used.
-
-.SH EXAMPLE
-.TP
-gfs2_mkfs -t mycluster:mygfs2 -p lock_dlm -j 2 /dev/vg0/mygfs2
-This will make a Global File System on the block device
-"/dev/vg0/mygfs2". It will belong to "mycluster" and register itself
-as wanting locking for "mygfs2". It will use DLM for locking and make
-two journals.
-.TP
-gfs2_mkfs -t mycluster:mygfs2 -p lock_nolock -j 3 /dev/vg0/mygfs2
-This will make a Global File System on the block device
-"/dev/vg0/mygfs2". It will belong to "mycluster" and but have no
-cluster locking. It will have three journals.
diff --git a/gfs2/man/mount.gfs2.8 b/gfs2/man/mount.gfs2.8
deleted file mode 100644
index 29d14c8..0000000
--- a/gfs2/man/mount.gfs2.8
+++ /dev/null
@@ -1,233 +0,0 @@
-.TH mount.gfs2 8
-
-.SH NAME
-mount.gfs2 - GFS2 mount options
-
-.SH SYNOPSIS
-.BI "mount \-a [\-fnrsvw] \-t " gfs2 " [\-O " options "]
-.br
-.BI "mount [\-fnrsvw] \-t " gfs2 " [\-o " options " ] " "device dir"
-
-.SH DESCRIPTION
-For details on the common mount options, please see the
-\fBmount\fP(8) command man page.
-The \fIdevice\fR may be any block device on which you
-have created a GFS2 filesystem. Examples include a
-single disk partition (e.g. /dev/sdb3), a loopback device, a device exported
-from another node (e.g. an iSCSI device), or a
-logical volume (typically comprised of a number of individual disks).
-
-\fIdevice\fR does not necessarily need to match the device name as seen on
-another node in the cluster, nor does it need to be a logical volume. However,
-the use of a cluster-aware volume manager such as CLVM2 (see \fBlvm\fP(8))
-will guarantee that the managed devices are named identically on each node in a
-cluster (for much easier management), and will allow you to configure a very
-large volume from multiple storage units (e.g. disk drives).
-
-\fIdevice\fR must make the entire filesystem storage area visible to the
-computer. That is, you cannot mount different parts of a single filesystem on
-different computers. Each computer must see an entire filesystem. You
-may, however, mount several GFS2 filesystems if you want to distribute your
-data storage in a controllable way.
-
-This man page describes GFS2-specific options that can be passed to the GFS2
-file system at mount time, using the \fB-o\fP flag. There are many other
-\fB-o\fP options handled by the generic mount command \fBmount\fP(8).
-However, the options described below are specifically for GFS2, and are not
-interpreted by the mount command nor by the kernel's Virtual File System. GFS2
-and non-GFS2 options may be intermingled after the \fB-o\fP, separated by
-commas (but no spaces).
-
-The options commit, discard, errors, quota_quantum, statfs_quantum, statfs_percent, barrier, acl, quota, suiddir, and data can be
-changed after mount using the "mount -o remount,option /mountpoint" command.
-The options quota, discard, barrier, acl, and suiddir support the "no"
-prefix. For example, "noacl" turns off what "acl" turns on.
-
-If you have trouble mounting GFS2, check the syslog (e.g. /var/log/messages)
-for specific error messages.
-
-.SH OPTIONS
-.TP
-\fBlockproto=\fP\fILockProtoName\fR
-This specifies which inter-node lock protocol is used by the GFS2 filesystem
-for this mount, overriding the default lock protocol name stored in the
-filesystem's on-disk superblock.
-
-The \fILockProtoName\fR must be one of the supported locking protocols,
-currently these are \fIlock_nolock\fR and \fIlock_dlm\fR.
-
-The default lock protocol name is written to disk initially when creating the
-filesystem with \fBmkfs.gfs2\fP(8), -p option. It can be changed on-disk by
-using the \fBgfs2_tool\fP(8) utility's \fBsb proto\fP command.
-
-The \fBlockproto\fP mount option should be used only under special
-circumstances in which you want to temporarily use a different lock protocol
-without changing the on-disk default. Using the incorrect lock protocol
-on a cluster filesystem mounted from more than one node will almost
-certainly result in filesystem corruption.
-.TP
-\fBlocktable=\fP\fILockTableName\fR
-This specifies the identity of the cluster and of the filesystem for this
-mount, overriding the default cluster/filesystem identify stored in the
-filesystem's on-disk superblock. The cluster/filesystem name is recognized
-globally throughout the cluster, and establishes a unique namespace for
-the inter-node locking system, enabling the mounting of multiple GFS2
-filesystems.
-
-The format of \fILockTableName\fR is lock-module-specific. For
-\fIlock_dlm\fR, the format is \fIclustername:fsname\fR. For
-\fIlock_nolock\fR, the field is ignored.
-
-The default cluster/filesystem name is written to disk initially when creating
-the filesystem with \fBmkfs.gfs2\fP(8), -t option. It can be changed on-disk
-by using the \fBgfs2_tool\fP(8) utility's \fBsb table\fP command.
-
-The \fBlocktable\fP mount option should be used only under special
-circumstances in which you want to mount the filesystem in a different cluster,
-or mount it as a different filesystem name, without changing the on-disk
-default.
-.TP
-\fBlocalcaching\fP
-This flag tells GFS2 that it is running as a local (not clustered) filesystem,
-so it can turn on some block caching optimizations that can't be used when
-running in cluster mode.
-
-This is turned on automatically by the lock_nolock module,
-but can be overridden by using the \fBignore_local_fs\fP option.
-.TP
-\fBlocalflocks\fP
-This flag tells GFS2 that it is running as a local (not clustered) filesystem,
-so it can allow the kernel VFS layer to do all flock and fcntl file locking.
-When running in cluster mode, these file locks require inter-node locks,
-and require the support of GFS2. When running locally, better performance
-is achieved by letting VFS handle the whole job.
-
-This is turned on automatically by the lock_nolock module,
-but can be overridden by using the \fBignore_local_fs\fP option.
-.TP
-\fBerrors=\fP\fI[panic|withdraw]\fR
-Setting errors=panic causes GFS2 to oops when encountering an error that
-would otherwise cause the
-mount to withdraw or print an assertion warning. The default setting
-is errors=withdraw. This option should not be used in a production system.
-It replaces the earlier \fBdebug\fP option on kernel versions 2.6.31 and
-above.
-.TP
-\fBignore_local_fs\fP
-By default, using the nolock lock module automatically turns on the
-\fBlocalcaching\fP and \fBlocalflocks\fP optimizations. \fBignore_local_fs\fP
-forces GFS2 to treat the filesystem as if it were a multihost (clustered)
-filesystem, with \fBlocalcaching\fP and \fBlocalflocks\fP optimizations
-turned off.
-.TP
-\fBupgrade\fP
-This flag tells GFS2 to upgrade the filesystem's on-disk format to the version
-supported by the current GFS2 software installation on this computer.
-If you try to mount an old-version disk image, GFS2 will notify you via a syslog
-message that you need to upgrade. Try mounting again, using the
-\fB-o upgrade\fP option. When upgrading, only one node may mount the GFS2
-filesystem.
-.TP
-\fBacl\fP
-Enables POSIX Access Control List \fBacl\fP(5) support within GFS2.
-.TP
-\fBspectator\fP
-Mount this filesystem using a special form of read-only mount. The mount
-does not use one of the filesystem's journals. The node is unable to
-recover journals for other nodes.
-.TP
-\fBsuiddir\fP
-Sets owner of any newly created file or directory to be that of parent
-directory, if parent directory has S_ISUID permission attribute bit set.
-Sets S_ISUID in any new directory, if its parent directory's S_ISUID is set.
-Strips all execution bits on a new file, if parent directory owner is different
-from owner of process creating the file. Set this option only if you know
-why you are setting it.
-.TP
-\fBquota=\fP\fI[off/account/on]\fR
-Turns quotas on or off for a filesystem. Setting the quotas to be in
-the "account" state causes the per UID/GID usage statistics to be
-correctly maintained by the filesystem, limit and warn values are
-ignored. The default value is "off".
-.TP
-\fBdiscard\fP
-Causes GFS2 to generate "discard" I/O requests for blocks which have
-been freed. These can be used by suitable hardware to implement
-thin-provisioning and similar schemes. This feature is supported
-in kernel version 2.6.30 and above.
-.TP
-\fBbarrier\fP
-This option, which defaults to on, causes GFS2 to send I/O barriers
-when flushing the journal. The option is automatically turned off
-if the underlying device does not support I/O barriers. We highly
-recommend the use of I/O barriers with GFS2 at all times unless
-the block device is designed so that it cannot lose its write cache
-content (e.g. its on a UPS, or it doesn't have a write cache)
-.TP
-\fBcommit=\fP\fIsecs\fR
-This is similar to the ext3 \fBcommit=\fP option in that it sets
-the maximum number of seconds between journal commits if there is
-dirty data in the journal. The default is 60 seconds. This option
-is only provided in kernel versions 2.6.31 and above.
-.TP
-\fBdata=\fP\fI[ordered|writeback]\fR
-When data=ordered is set, the user data modified by a transaction is
-flushed to the disk before the transaction is committed to disk. This
-should prevent the user from seeing uninitialized blocks in a file
-after a crash. Data=writeback mode writes the user data to the disk
-at any time after it's dirtied. This doesn't provide the same
-consistency guarantee as ordered mode, but it should be slightly
-faster for some workloads. The default is ordered mode.
-.TP
-\fBmeta\fP
-This option results in selecting the meta filesystem root rather than
-the normal filesystem root. This option is normally only used by
-the GFS2 utility functions. Altering any file on the GFS2 meta filesystem
-may render the filesystem unusable, so only experts in the GFS2
-on-disk layout should use this option.
-.TP
-\fBquota_quantum=\fP\fIsecs\fR
-This sets the number of seconds for which a change in the quota
-information may sit on one node before being written to the quota
-file. This is the preferred way to set this parameter. The value
-is an integer number of seconds greater than zero. The default is
-60 seconds. Shorter settings result in faster updates of the lazy
-quota information and less likelihood of someone exceeding their
-quota. Longer settings make filesystem operations involving quotas
-faster and more efficient.
-.TP
-\fBstatfs_quantum=\fP\fIsecs\fR
-Setting statfs_quantum to 0 is the preferred way to set the slow version
-of statfs. The default value is 30 secs which sets the maximum time
-period before statfs changes will be syned to the master statfs file.
-This can be adjusted to allow for faster, less accurate statfs values
-or slower more accurate values. When set to 0, statfs will always
-report the true values.
-.TP
-\fBstatfs_percent=\fP\fIvalue\fR
-This setting provides a bound on the maximum percentage change in
-the statfs information on a local basis before it is synced back
-to the master statfs file, even if the time period has not
-expired. If the setting of statfs_quantum is 0, then this setting
-is ignored.
-
-.SH BUGS
-
-GFS2 doesn't support \fBerrors=\fP\fIremount-ro\fR or \fBdata=\fP\fIjournal\fR.
-It is not possible to switch support for user and group quotas on and
-off independently of each other. Some of the error messages are rather
-cryptic, if you encounter one of these messages check firstly that gfs_controld
-is running and secondly that you have enough journals on the filesystem
-for the number of nodes in use.
-
-.SH SEE ALSO
-
-\fBgfs2\fP(8),
-\fBmount\fP(8) for general mount options,
-\fBchmod\fP(1) and \fBchmod\fP(2) for access permission flags,
-\fBacl\fP(5) for access control lists,
-\fBlvm\fP(8) for volume management,
-\fBccs\fP(7) for cluster management,
-\fBumount\fP(8),
-\fBinitrd\fP(4).
-
diff --git a/gfs2/mkfs/Makefile b/gfs2/mkfs/Makefile
deleted file mode 100644
index 7a67898..0000000
--- a/gfs2/mkfs/Makefile
+++ /dev/null
@@ -1,46 +0,0 @@
-TARGET1= mkfs.gfs2
-TARGET2= gfs2_jadd
-TARGET3= gfs2_grow
-
-FORCESBINT= $(TARGET1)
-
-SBINSYMT=$(TARGET2) $(TARGET3)
-
-all: depends ${TARGET1} ${TARGET2} ${TARGET3}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= main.o \
- main_mkfs.o \
- main_grow.o \
- main_jadd.o
-
-CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_GNU_SOURCE
-CFLAGS += -I${KERNEL_SRC}/include/
-CFLAGS += -I$(S)/../include -I$(S)/../libgfs2
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L../libgfs2 -lgfs2
-LDFLAGS += -L${libdir}
-
-LDDEPS += ../libgfs2/libgfs2.a
-
-${TARGET1}: ${OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-${TARGET2}: ${TARGET1}
- ln -sf ${relativesbin}/${TARGET1} ${TARGET2}
-
-${TARGET3}: ${TARGET1}
- ln -sf ${relativesbin}/${TARGET1} ${TARGET3}
-
-depends:
- $(MAKE) -C ../libgfs2 all
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs2/mkfs/README b/gfs2/mkfs/README
deleted file mode 100644
index 784df7d..0000000
--- a/gfs2/mkfs/README
+++ /dev/null
@@ -1,25 +0,0 @@
-
-#
-# mkfs for GFS2 filesystem
-#
-
-To install:
-
- 1. Edit the Makefile to point at your local copy of the kernel source
-with GFS2 included in it, for my set up that means:
-
-INCLUDEPATH=-I/home/steve/linux-2.6/include/
-
- 2. make
- 3. make install
-
-
-You can then use it just like other mkfs programs (for example):
-
-/sbin/mkfs -t gfs2 -j 1 -p lock_nolock /dev/sdb1
-
-This will create a filesystem with one journal (i.e. mountable by a
-maximum of one node at a time) with the nolock module (single node
-use only) on /dev/sdb1. Running mkfs -f gfs2 -h will produce help
-information.
-
diff --git a/gfs2/mkfs/gfs2_mkfs.h b/gfs2/mkfs/gfs2_mkfs.h
deleted file mode 100644
index 14bf4f6..0000000
--- a/gfs2/mkfs/gfs2_mkfs.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef __GFS2_MKFS_DOT_H__
-#define __GFS2_MKFS_DOT_H__
-
-#include <linux/gfs2_ondisk.h>
-#include "osi_list.h"
-#include "copyright.cf"
-
-/* main_grow */
-void main_grow(int argc, char *argv[]);
-
-/* main_jadd */
-void main_jadd(int argc, char *argv[]);
-
-/* main_mkfs */
-void main_mkfs(int argc, char *argv[]);
-
-/* main_shrink */
-void main_shrink(int argc, char *argv[]);
-
-/*
- * The following inode IOCTL macros and inode flags
- * are copied from linux/fs.h, because we have duplicate
- * definition of symbols when we include both linux/fs.h and
- * sys/mount.h in our program
- */
-
-#define FS_IOC_GETFLAGS _IOR('f', 1, long)
-#define FS_IOC_SETFLAGS _IOW('f', 2, long)
-#define FS_IOC_GETVERSION _IOR('v', 1, long)
-#define FS_IOC_SETVERSION _IOW('v', 2, long)
-#define FS_IOC32_GETFLAGS _IOR('f', 1, int)
-#define FS_IOC32_SETFLAGS _IOW('f', 2, int)
-#define FS_IOC32_GETVERSION _IOR('v', 1, int)
-#define FS_IOC32_SETVERSION _IOW('v', 2, int)
-
-/*
- * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
- */
-#define FS_SECRM_FL 0x00000001 /* Secure deletion */
-#define FS_UNRM_FL 0x00000002 /* Undelete */
-#define FS_COMPR_FL 0x00000004 /* Compress file */
-#define FS_SYNC_FL 0x00000008 /* Synchronous updates */
-#define FS_IMMUTABLE_FL 0x00000010 /* Immutable file */
-#define FS_APPEND_FL 0x00000020 /* writes to file may only append */
-#define FS_NODUMP_FL 0x00000040 /* do not dump file */
-#define FS_NOATIME_FL 0x00000080 /* do not update atime */
-/* Reserved for compression usage... */
-#define FS_DIRTY_FL 0x00000100
-#define FS_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
-#define FS_NOCOMP_FL 0x00000400 /* Don't compress */
-#define FS_ECOMPR_FL 0x00000800 /* Compression error */
-/* End compression flags --- maybe not all used */
-#define FS_BTREE_FL 0x00001000 /* btree format dir */
-#define FS_INDEX_FL 0x00001000 /* hash-indexed directory */
-#define FS_IMAGIC_FL 0x00002000 /* AFS directory */
-#define FS_JOURNAL_DATA_FL 0x00004000 /* Reserved for ext3 */
-#define FS_NOTAIL_FL 0x00008000 /* file tail should not be merged */
-#define FS_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
-#define FS_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
-#define FS_EXTENT_FL 0x00080000 /* Extents */
-#define FS_DIRECTIO_FL 0x00100000 /* Use direct i/o */
-#define FS_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
-
-#define FS_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
-#define FS_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
-
-#endif /* __GFS2_MKFS_DOT_H__ */
diff --git a/gfs2/mkfs/main.c b/gfs2/mkfs/main.c
deleted file mode 100644
index 58b933c..0000000
--- a/gfs2/mkfs/main.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#include <libgen.h>
-#include <libintl.h>
-#include <locale.h>
-#define _(String) gettext(String)
-
-#include <linux/types.h>
-#include "libgfs2.h"
-#include "gfs2_mkfs.h"
-
-/**
- * main - do everything
- * @argc:
- * @argv:
- *
- * Returns: 0 on success, non-0 on failure
- */
-
-int
-main(int argc, char *argv[])
-{
- char *p, *whoami;
-
- setlocale(LC_ALL, "");
- textdomain("gfs2-utils");
-
- srandom(time(NULL) ^ getpid());
-
- p = strdup(argv[0]);
- whoami = basename(p);
-
- if (!strcmp(whoami, "gfs2_jadd"))
- main_jadd(argc, argv);
- else if (!strcmp(whoami, "gfs2_mkfs") || !strcmp(whoami, "mkfs.gfs2"))
- main_mkfs(argc, argv);
- else if (!strcmp(whoami, "gfs2_grow"))
- main_grow(argc, argv);
- else
- die( _("I don't know who I am!\n"));
-
- free(p);
-
- return 0;
-}
diff --git a/gfs2/mkfs/main_grow.c b/gfs2/mkfs/main_grow.c
deleted file mode 100644
index 34f5291..0000000
--- a/gfs2/mkfs/main_grow.c
+++ /dev/null
@@ -1,357 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/file.h>
-#include <sys/vfs.h>
-#include <sys/mount.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <linux/types.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include "libgfs2.h"
-#include "gfs2_mkfs.h"
-
-#define BUF_SIZE 4096
-#define MB (1024 * 1024)
-
-static uint64_t override_device_size = 0;
-static int test = 0;
-static uint64_t fssize = 0, fsgrowth;
-static unsigned int rgsize = 0;
-
-extern int create_new_inode(struct gfs2_sbd *sdp);
-extern int rename2system(struct gfs2_sbd *sdp, char *new_dir, char *new_name);
-
-/**
- * usage - Print out the usage message
- *
- * This function does not include documentation for the -D option
- * since normal users have no use for it at all. The -D option is
- * only for developers. It intended use is in combination with the
- * -T flag to find out what the result would be of trying different
- * device sizes without actually having to try them manually.
- */
-
-static void usage(void)
-{
- fprintf(stdout,
- _("Usage:\n"
- "\n"
- "gfs2_grow [options] /path/to/filesystem\n"
- "\n"
- "Options:\n"
- " -h Usage information\n"
- " -q Quiet, reduce verbosity\n"
- " -T Test, do everything except update FS\n"
- " -V Version information\n"
- " -v Verbose, increase verbosity\n"));
-}
-
-static void decode_arguments(int argc, char *argv[], struct gfs2_sbd *sdp)
-{
- int opt;
-
- while ((opt = getopt(argc, argv, "VD:hqTv?")) != EOF) {
- switch (opt) {
- case 'D': /* This option is for testing only */
- override_device_size = atoi(optarg);
- override_device_size <<= 20;
- break;
- case 'V':
- printf("%s %s (built %s %s)\n", argv[0],
- RELEASE_VERSION, __DATE__, __TIME__);
- printf( _(REDHAT_COPYRIGHT "\n"));
- exit(0);
- case 'h':
- usage();
- exit(0);
- case 'q':
- decrease_verbosity();
- break;
- case 'T':
- printf( _("(Test mode--File system will not "
- "be changed)\n"));
- test = 1;
- break;
- case 'v':
- increase_verbosity();
- break;
- case ':':
- case '?':
- /* Unknown flag */
- fprintf(stderr, _("Please use '-h' for usage.\n"));
- exit(EXIT_FAILURE);
- default:
- fprintf(stderr, _("Bad programmer! You forgot"
- " to catch the %c flag\n"), opt);
- exit(EXIT_FAILURE);
- break;
- }
- }
-
- if (optind == argc) {
- usage();
- exit(EXIT_FAILURE);
- }
-}
-
-/**
- * figure_out_rgsize
- */
-static void figure_out_rgsize(struct gfs2_sbd *sdp, unsigned int *orgsize)
-{
- osi_list_t *head = &sdp->rglist;
- struct rgrp_list *r1, *r2;
-
- sdp->rgsize = GFS2_DEFAULT_RGSIZE;
- r1 = osi_list_entry(head->next->next, struct rgrp_list, list);
- r2 = osi_list_entry(head->next->next->next, struct rgrp_list, list);
-
- *orgsize = r2->ri.ri_addr - r1->ri.ri_addr;
-}
-
-/**
- * filesystem_size - Calculate the size of the filesystem
- *
- * Reads the lists of resource groups in order to
- * work out where the last block of the filesystem is located.
- *
- * Returns: The calculated size
- */
-
-static uint64_t filesystem_size(struct gfs2_sbd *sdp)
-{
- osi_list_t *tmp;
- struct rgrp_list *rgl;
- uint64_t size = 0, extent;
-
- tmp = &sdp->rglist;
- for (;;) {
- tmp = tmp->next;
- if (tmp == &sdp->rglist)
- break;
- rgl = osi_list_entry(tmp, struct rgrp_list, list);
- extent = rgl->ri.ri_addr + rgl->ri.ri_length + rgl->ri.ri_data;
- if (extent > size)
- size = extent;
- }
- return size;
-}
-
-/**
- * initialize_new_portion - Write the new rg information to disk buffers.
- */
-static void initialize_new_portion(struct gfs2_sbd *sdp, int *old_rg_count)
-{
- uint64_t rgrp = 0;
- osi_list_t *head = &sdp->rglist;
-
- *old_rg_count = 0;
- /* Delete the old RGs from the rglist */
- for (rgrp = 0; !osi_list_empty(head) &&
- rgrp < (sdp->rgrps - sdp->new_rgrps); rgrp++) {
- (*old_rg_count)++;
- osi_list_del(head->next);
- }
- /* Build the remaining resource groups */
- build_rgrps(sdp, !test);
-
- inode_put(&sdp->md.riinode);
- inode_put(&sdp->master_dir);
-
- /* We're done with the libgfs portion, so commit it to disk. */
- fsync(sdp->device_fd);
-}
-
-/**
- * fix_rindex - Add the new entries to the end of the rindex file.
- */
-static void fix_rindex(struct gfs2_sbd *sdp, int rindex_fd, int old_rg_count)
-{
- int count, rg;
- struct rgrp_list *rl;
- char *buf, *bufptr;
- osi_list_t *tmp;
- ssize_t writelen;
-
- /* Count the number of new RGs. */
- rg = 0;
- osi_list_foreach(tmp, &sdp->rglist)
- rg++;
- log_info( _("%d new rindex entries.\n"), rg);
- writelen = rg * sizeof(struct gfs2_rindex);
- buf = calloc(1, writelen);
- if (buf == NULL) {
- fprintf(stderr, _("Out of memory in %s\n"), __FUNCTION__);
- exit(-1);
- }
- /* Now add the new rg entries to the rg index. Here we */
- /* need to use the gfs2 kernel code rather than the libgfs2 */
- /* code so we have a live update while mounted. */
- bufptr = buf;
- osi_list_foreach(tmp, &sdp->rglist) {
- rg++;
- rl = osi_list_entry(tmp, struct rgrp_list, list);
- gfs2_rindex_out(&rl->ri, bufptr);
- bufptr += sizeof(struct gfs2_rindex);
- }
- gfs2_rgrp_free(&sdp->rglist);
- fsync(sdp->device_fd);
- if (!test) {
- /* Now write the new RGs to the end of the rindex */
- lseek(rindex_fd, 0, SEEK_END);
- count = write(rindex_fd, buf, writelen);
- if (count != writelen)
- log_crit("Error writing new rindex entries;"
- "aborted.\n");
- fsync(rindex_fd);
- }
- free(buf);
-}
-
-/**
- * print_info - Print out various bits of (interesting?) information
- *
- */
-static void print_info(struct gfs2_sbd *sdp)
-{
- log_notice("FS: Mount Point: %s\n", sdp->path_name);
- log_notice("FS: Device: %s\n", sdp->device_name);
- log_notice("FS: Size: %" PRIu64 " (0x%" PRIx64 ")\n",
- fssize, fssize);
- log_notice("FS: RG size: %u (0x%x)\n", rgsize, rgsize);
- log_notice("DEV: Size: %"PRIu64" (0x%" PRIx64")\n",
- sdp->device.length, sdp->device.length);
- log_notice("The file system grew by %" PRIu64 "MB.\n",
- fsgrowth / MB);
-}
-
-/**
- * main_grow - do everything
- * @argc:
- * @argv:
- */
-void
-main_grow(int argc, char *argv[])
-{
- struct gfs2_sbd sbd, *sdp = &sbd;
- int rgcount, rindex_fd;
- char rindex_name[PATH_MAX];
- osi_list_t *head = &sdp->rglist;
-
- memset(sdp, 0, sizeof(struct gfs2_sbd));
- sdp->bsize = GFS2_DEFAULT_BSIZE;
- sdp->rgsize = -1;
- sdp->jsize = GFS2_DEFAULT_JSIZE;
- sdp->qcsize = GFS2_DEFAULT_QCSIZE;
- sdp->md.journals = 1;
- decode_arguments(argc, argv, sdp);
-
- while ((argc - optind) > 0) {
- int sane;
-
- sdp->path_name = argv[optind++];
- sdp->path_fd = open(sdp->path_name, O_RDONLY | O_CLOEXEC);
- if (sdp->path_fd < 0)
- die("can't open root directory %s: %s\n",
- sdp->path_name, strerror(errno));
-
- if (check_for_gfs2(sdp)) {
- if (errno == EINVAL)
- fprintf(stderr,
- _("Not a valid GFS2 mount point: %s\n"),
- sdp->path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
- sdp->device_fd = open(sdp->device_name,
- (test ? O_RDONLY : O_RDWR) | O_CLOEXEC);
- if (sdp->device_fd < 0)
- die( _("can't open device %s: %s\n"),
- sdp->device_name, strerror(errno));
- if (device_geometry(sdp)) {
- fprintf(stderr, _("Geometry error\n"));
- exit(-1);
- }
- log_info( _("Initializing lists...\n"));
- osi_list_init(&sdp->rglist);
-
- sdp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
- sdp->bsize = sdp->sd_sb.sb_bsize;
- if (compute_constants(sdp)) {
- log_crit(_("Bad constants (1)\n"));
- exit(-1);
- }
- if(read_sb(sdp) < 0)
- die( _("gfs: Error reading superblock.\n"));
-
- if (fix_device_geometry(sdp)) {
- fprintf(stderr, _("Device is too small (%"PRIu64" bytes)\n"),
- sdp->device.length << GFS2_BASIC_BLOCK_SHIFT);
- exit(-1);
- }
-
- if (mount_gfs2_meta(sdp)) {
- fprintf(stderr, _("Error mounting GFS2 metafs: %s\n"),
- strerror(errno));
- exit(-1);
- }
-
- sprintf(rindex_name, "%s/rindex", sdp->metafs_path);
- rindex_fd = open(rindex_name, (test ? O_RDONLY : O_RDWR) | O_CLOEXEC);
- if (rindex_fd < 0) {
- cleanup_metafs(sdp);
- die( _("GFS2 rindex not found. Please run gfs2_fsck.\n"));
- }
- /* Get master dinode */
- sdp->master_dir =
- inode_read(sdp, sdp->sd_sb.sb_master_dir.no_addr);
- gfs2_lookupi(sdp->master_dir, "rindex", 6, &sdp->md.riinode);
- /* Fetch the rindex from disk. We aren't using gfs2 here, */
- /* which means that the bitmaps will most likely be cached */
- /* and therefore out of date. It shouldn't matter because */
- /* we're only going to write out new RG information after */
- /* the existing RGs, and only write to the index at EOF. */
- ri_update(sdp, rindex_fd, &rgcount, &sane);
- fssize = filesystem_size(sdp);
- figure_out_rgsize(sdp, &rgsize);
- fsgrowth = ((sdp->device.length - fssize) * sdp->bsize);
- if (fsgrowth < rgsize * sdp->bsize) {
- log_err( _("Error: The device has grown by less than "
- "one Resource Group (RG).\n"));
- log_err( _("The device grew by %" PRIu64 "MB. "),
- fsgrowth / MB);
- log_err( _("One RG is %uMB for this file system.\n"),
- (rgsize * sdp->bsize) / MB);
- }
- else {
- int old_rg_count;
-
- compute_rgrp_layout(sdp, TRUE);
- print_info(sdp);
- initialize_new_portion(sdp, &old_rg_count);
- fix_rindex(sdp, rindex_fd, old_rg_count);
- }
- /* Delete the remaining RGs from the rglist */
- while (!osi_list_empty(head))
- osi_list_del(head->next);
- close(rindex_fd);
- cleanup_metafs(sdp);
- close(sdp->device_fd);
- }
- close(sdp->path_fd);
- sync();
- log_notice( _("gfs2_grow complete.\n"));
-}
diff --git a/gfs2/mkfs/main_jadd.c b/gfs2/mkfs/main_jadd.c
deleted file mode 100644
index be13271..0000000
--- a/gfs2/mkfs/main_jadd.c
+++ /dev/null
@@ -1,536 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/file.h>
-#include <sys/vfs.h>
-#include <sys/mount.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include <linux/types.h>
-#include "libgfs2.h"
-#include "gfs2_mkfs.h"
-
-#define BUF_SIZE 4096
-#define RANDOM(values) ((values) * (random() / (RAND_MAX + 1.0)))
-
-static void
-make_jdata(int fd, const char *value)
-{
- int err;
- uint32_t val;
-
- err = ioctl(fd, FS_IOC_GETFLAGS, &val);
- if (err)
- die( _("error doing get flags (%d): %s\n"), err, strerror(errno));
- if (strcmp(value, "set") == 0)
- val |= FS_JOURNAL_DATA_FL;
- if (strcmp(value, "clear") == 0)
- val &= ~FS_JOURNAL_DATA_FL;
- err = ioctl(fd, FS_IOC_SETFLAGS, &val);
- if (err)
- die( _("error doing set flags (%d): %s\n"), err, strerror(errno));
-}
-
-static int
-rename2system(struct gfs2_sbd *sdp, const char *new_dir, const char *new_name)
-{
- char oldpath[PATH_MAX], newpath[PATH_MAX];
- int error = 0;
- error = snprintf(oldpath, PATH_MAX, "%s/new_inode",
- sdp->metafs_path);
- if (error >= PATH_MAX)
- die( _("rename2system (1)\n"));
-
- error = snprintf(newpath, PATH_MAX, "%s/%s/%s",
- sdp->metafs_path, new_dir, new_name);
- if (error >= PATH_MAX)
- die( _("rename2system (2)\n"));
-
- return rename(oldpath, newpath);
-}
-
-/**
- * print_usage - print out usage information
- * @prog_name: The name of this program
- */
-
-static void print_usage(const char *prog_name)
-{
- printf( _("Usage:\n\n"
- "%s [options] /path/to/filesystem\n\n"
- "Options:\n\n"
- " -c <MB> Size of quota change file\n"
- " -D Enable debugging code\n"
- " -h Print this help, then exit\n"
- " -J <MB> Size of journals\n"
- " -j <num> Number of journals\n"
- " -q Don't print anything\n"
- " -V Print program version information, then exit\n"), prog_name);
-}
-
-/**
- * decode_arguments - decode command line arguments and fill in the struct gfs2_sbd
- * @argc:
- * @argv:
- * @sdp: the decoded command line arguments
- *
- */
-
-static void decode_arguments(int argc, char *argv[], struct gfs2_sbd *sdp)
-{
- int cont = TRUE;
- int optchar;
-
- while (cont) {
- optchar = getopt(argc, argv, "c:DhJ:j:qu:VX");
-
- switch (optchar) {
- case 'c':
- sdp->qcsize = atoi(optarg);
- break;
- case 'D':
- sdp->debug = TRUE;
- break;
- case 'h':
- print_usage(argv[0]);
- exit(0);
- break;
- case 'J':
- sdp->jsize = atoi(optarg);
- break;
- case 'j':
- sdp->md.journals = atoi(optarg);
- break;
- case 'q':
- sdp->quiet = TRUE;
- break;
- case 'V':
- printf("gfs2_jadd %s (built %s %s)\n", RELEASE_VERSION,
- __DATE__, __TIME__);
- printf( _(REDHAT_COPYRIGHT "\n"));
- exit(0);
- break;
- case 'X':
- sdp->expert = TRUE;
- break;
- case ':':
- case '?':
- fprintf(stderr, _("Please use '-h' for usage.\n"));
- exit(EXIT_FAILURE);
- break;
- case EOF:
- cont = FALSE;
- break;
- default:
- die( _("unknown option: %c\n"), optchar);
- break;
- };
- }
-
- if (optind < argc) {
- sdp->path_name = argv[optind];
- optind++;
- } else
- die( _("no path specified (try -h for help)\n"));
-
- if (optind < argc)
- die( _("Unrecognized option: %s\n"), argv[optind]);
-
- if (sdp->debug) {
- printf( _("Command Line Arguments:\n"));
- printf(" qcsize = %u\n", sdp->qcsize);
- printf(" jsize = %u\n", sdp->jsize);
- printf(" journals = %u\n", sdp->md.journals);
- printf(" quiet = %d\n", sdp->quiet);
- printf(" path = %s\n", sdp->path_name);
- }
-}
-
-static void
-verify_arguments(struct gfs2_sbd *sdp)
-{
- if (!sdp->md.journals)
- die( _("no journals specified\n"));
- if (sdp->jsize < 32 || sdp->jsize > 1024)
- die( _("bad journal size\n"));
- if (!sdp->qcsize || sdp->qcsize > 64)
- die( _("bad quota change size\n"));
-}
-
-/**
- * print_results - print out summary information
- * @sdp: the command line
- *
- */
-
-static void
-print_results(struct gfs2_sbd *sdp)
-{
- if (sdp->debug)
- printf("\n");
- else if (sdp->quiet)
- return;
-
- if (sdp->expert)
- printf("Expert mode: on\n");
-
- printf( _("Filesystem: %s\n"), sdp->path_name);
- printf( _("Old Journals %u\n"), sdp->orig_journals);
- printf( _("New Journals %u\n"), sdp->md.journals);
-
-}
-
-static int
-create_new_inode(struct gfs2_sbd *sdp)
-{
- char name[PATH_MAX];
- int fd;
- int error;
-
- error = snprintf(name, PATH_MAX, "%s/new_inode", sdp->metafs_path);
- if (error >= PATH_MAX)
- die("create_new_inode (1)\n");
-
- for (;;) {
- fd = open(name, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
- if (fd >= 0)
- break;
- if (errno == EEXIST) {
- error = unlink(name);
- if (error)
- die( _("can't unlink %s: %s\n"),
- name, strerror(errno));
- } else
- die( _("can't create %s: %s\n"), name, strerror(errno));
- }
-
- return fd;
-}
-
-static void
-add_ir(struct gfs2_sbd *sdp)
-{
- int fd;
- char new_name[256];
- int error;
-
- fd = create_new_inode(sdp);
-
- {
- struct gfs2_inum_range ir;
- make_jdata(fd, "set");
- memset(&ir, 0, sizeof(struct gfs2_inum_range));
- if (write(fd, (void*)&ir, sizeof(struct gfs2_inum_range)) !=
- sizeof(struct gfs2_inum_range)) {
- fprintf(stderr, _( "write error: %s from %s:%d: "
- "offset 0\n"), strerror(errno),
- __FUNCTION__, __LINE__);
- exit(-1);
- }
- }
-
- close(fd);
-
- sprintf(new_name, "inum_range%u", sdp->md.journals);
- error = rename2system(sdp, "per_node", new_name);
- if (error < 0 && errno != EEXIST)
- die( _("can't rename2system %s (%d): %s\n"),
- new_name, error, strerror(errno));
-}
-
-static void
-add_sc(struct gfs2_sbd *sdp)
-{
- int fd;
- char new_name[256];
- int error;
-
- fd = create_new_inode(sdp);
-
- {
- struct gfs2_statfs_change sc;
- make_jdata(fd, "set");
-
- memset(&sc, 0, sizeof(struct gfs2_statfs_change));
- if (write(fd, (void*)&sc, sizeof(struct gfs2_statfs_change)) !=
- sizeof(struct gfs2_statfs_change)) {
- fprintf(stderr, _("write error: %s from %s:%d: "
- "offset 0\n"), strerror(errno),
- __FUNCTION__, __LINE__);
- exit(-1);
- }
- }
-
- close(fd);
-
- sprintf(new_name, "statfs_change%u", sdp->md.journals);
- error = rename2system(sdp, "per_node", new_name);
- if (error < 0 && errno != EEXIST)
- die( _("can't rename2system %s (%d): %s\n"),
- new_name, error, strerror(errno));
-}
-
-static void
-add_qc(struct gfs2_sbd *sdp)
-{
- int fd;
- char new_name[256];
- int error;
-
- fd = create_new_inode(sdp);
-
- {
- char buf[sdp->bsize];
- unsigned int blocks =
- sdp->qcsize << (20 - sdp->sd_sb.sb_bsize_shift);
- unsigned int x;
- struct gfs2_meta_header mh;
- struct gfs2_buffer_head dummy_bh;
-
- dummy_bh.b_data = buf;
- make_jdata(fd, "clear");
- memset(buf, 0, sdp->bsize);
-
- for (x=0; x<blocks; x++) {
- if (write(fd, buf, sdp->bsize) != sdp->bsize) {
- fprintf(stderr, _("write error: %s from %s:%d: "
- "block %lld (0x%llx)\n"),
- strerror(errno),
- __FUNCTION__, __LINE__,
- (unsigned long long)x,
- (unsigned long long)x);
- exit(-1);
- }
- }
-
- lseek(fd, 0, SEEK_SET);
-
- memset(&mh, 0, sizeof(struct gfs2_meta_header));
- mh.mh_magic = GFS2_MAGIC;
- mh.mh_type = GFS2_METATYPE_QC;
- mh.mh_format = GFS2_FORMAT_QC;
- gfs2_meta_header_out(&mh, &dummy_bh);
-
- for (x=0; x<blocks; x++) {
- if (write(fd, buf, sdp->bsize) != sdp->bsize) {
- fprintf(stderr, _("write error: %s from %s:%d: "
- "block %lld (0x%llx)\n"),
- strerror(errno),
- __FUNCTION__, __LINE__,
- (unsigned long long)x,
- (unsigned long long)x);
- exit(-1);
- }
- }
-
- error = fsync(fd);
- if (error)
- die( _("can't fsync: %s\n"),
- strerror(errno));
- }
-
- close(fd);
-
- sprintf(new_name, "quota_change%u", sdp->md.journals);
- error = rename2system(sdp, "per_node", new_name);
- if (error < 0 && errno != EEXIST)
- die( _("can't rename2system %s (%d): %s\n"),
- new_name, error, strerror(errno));
-}
-
-static void
-gather_info(struct gfs2_sbd *sdp)
-{
- struct statfs statbuf;
- if (statfs(sdp->path_name, &statbuf) < 0) {
- die( _("Could not statfs the filesystem %s: %s\n"),
- sdp->path_name, strerror(errno));
- }
- sdp->bsize = statbuf.f_bsize;
-}
-
-static void
-find_current_journals(struct gfs2_sbd *sdp)
-{
- char jindex[PATH_MAX];
- struct dirent *dp;
- DIR *dirp;
- int existing_journals = 0;
-
- sprintf(jindex, "%s/jindex", sdp->metafs_path);
- dirp = opendir(jindex);
- if (!dirp) {
- die( _("Could not find the jindex directory "
- "in gfs2meta mount! error: %s\n"), strerror(errno));
- }
- while (dirp) {
- if ((dp = readdir(dirp)) != NULL) {
- if (strncmp(dp->d_name, "journal", 7) == 0)
- existing_journals++;
- } else
- goto close;
- }
-close:
- closedir(dirp);
- if (existing_journals <= 0) {
- die( _("There are no journals for this "
- "gfs2 fs! Did you mkfs.gfs2 correctly?\n"));
- }
-
- sdp->orig_journals = existing_journals;
-}
-
-static void
-add_j(struct gfs2_sbd *sdp)
-{
- int fd;
- char new_name[256];
- int error;
-
- fd = create_new_inode(sdp);
-
- {
- char buf[sdp->bsize];
- unsigned int blocks =
- sdp->jsize << (20 - sdp->sd_sb.sb_bsize_shift);
- unsigned int x;
- struct gfs2_log_header lh;
- uint64_t seq = RANDOM(blocks);
-
- make_jdata(fd, "clear");
- memset(buf, 0, sdp->bsize);
- for (x=0; x<blocks; x++) {
- if (write(fd, buf, sdp->bsize) != sdp->bsize) {
- fprintf(stderr, _("write error: %s from %s:%d: "
- "block %lld (0x%llx)\n"),
- strerror(errno),
- __FUNCTION__, __LINE__,
- (unsigned long long)x,
- (unsigned long long)x);
- exit(-1);
- }
- }
-
- lseek(fd, 0, SEEK_SET);
-
- memset(&lh, 0, sizeof(struct gfs2_log_header));
- lh.lh_header.mh_magic = GFS2_MAGIC;
- lh.lh_header.mh_type = GFS2_METATYPE_LH;
- lh.lh_header.mh_format = GFS2_FORMAT_LH;
- lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
-
- for (x=0; x<blocks; x++) {
- uint32_t hash;
- struct gfs2_buffer_head dummy_bh;
-
- dummy_bh.b_data = buf;
- lh.lh_sequence = seq;
- lh.lh_blkno = x;
- gfs2_log_header_out(&lh, &dummy_bh);
- hash = gfs2_disk_hash(buf, sizeof(struct gfs2_log_header));
- ((struct gfs2_log_header *)buf)->lh_hash = cpu_to_be32(hash);
-
- if (write(fd, buf, sdp->bsize) != sdp->bsize) {
- fprintf(stderr, _("write error: %s from %s:%d: "
- "block %lld (0x%llx)\n"),
- strerror(errno),
- __FUNCTION__, __LINE__,
- (unsigned long long)x,
- (unsigned long long)x);
- exit(-1);
- }
-
- if (++seq == blocks)
- seq = 0;
- }
-
- error = fsync(fd);
- if (error)
- die( _("can't fsync: %s\n"),
- strerror(errno));
- }
-
- close(fd);
-
- sprintf(new_name, "journal%u", sdp->md.journals);
- error = rename2system(sdp, "jindex", new_name);
- if (error < 0 && errno != EEXIST)
- die( _("can't rename2system %s (%d): %s\n"),
- new_name, error, strerror(errno));
-}
-
-/**
- * main_jadd - do everything
- * @argc:
- * @argv:
- *
- */
-
-void main_jadd(int argc, char *argv[])
-{
- struct gfs2_sbd sbd, *sdp = &sbd;
- unsigned int total;
-
- memset(sdp, 0, sizeof(struct gfs2_sbd));
- sdp->jsize = GFS2_DEFAULT_JSIZE;
- sdp->qcsize = GFS2_DEFAULT_QCSIZE;
- sdp->md.journals = 1;
-
- decode_arguments(argc, argv, sdp);
- verify_arguments(sdp);
-
- sdp->path_fd = open(sdp->path_name, O_RDONLY | O_CLOEXEC);
- if (sdp->path_fd < 0)
- die( _("can't open root directory %s: %s\n"),
- sdp->path_name, strerror(errno));
-
- if (check_for_gfs2(sdp)) {
- if (errno == EINVAL)
- fprintf(stderr, _("Not a valid GFS2 mount point: %s\n"),
- sdp->path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
-
- gather_info(sdp);
-
- if (mount_gfs2_meta(sdp)) {
- fprintf(stderr, _("Error mounting GFS2 metafs: %s\n"),
- strerror(errno));
- exit(-1);
- }
-
- if (compute_constants(sdp)) {
- fprintf(stderr, _("Bad constants (1)\n"));
- exit(-1);
- }
- find_current_journals(sdp);
-
- total = sdp->orig_journals + sdp->md.journals;
- for (sdp->md.journals = sdp->orig_journals;
- sdp->md.journals < total;
- sdp->md.journals++) {
- add_ir(sdp);
- add_sc(sdp);
- add_qc(sdp);
- add_j(sdp);
- }
-
- close(sdp->path_fd);
- cleanup_metafs(sdp);
- sync();
- print_results(sdp);
-}
diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c
deleted file mode 100644
index 6af8c3a..0000000
--- a/gfs2/mkfs/main_mkfs.c
+++ /dev/null
@@ -1,662 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <mntent.h>
-#include <ctype.h>
-#include <poll.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <libintl.h>
-
-#define _(String) gettext(String)
-
-#include <linux/types.h>
-#include "libgfs2.h"
-#include "gfs2_mkfs.h"
-
-/**
- * This function is for libgfs2's sake.
- */
-void print_it(const char *label, const char *fmt, const char *fmt2, ...)
-{
- va_list args;
-
- va_start(args, fmt2);
- printf("%s: ", label);
- vprintf(fmt, args);
- va_end(args);
-}
-
-/**
- * print_usage - print out usage information
- * @prog_name: The name of this program
- */
-
-static void
-print_usage(const char *prog_name)
-{
- printf( _("Usage:\n\n"
- "%s [options] <device> [ block-count ]\n\n"
- "Options:\n\n"
- " -b <bytes> Filesystem block size\n"
- " -c <MB> Size of quota change file\n"
- " -D Enable debugging code\n"
- " -h Print this help, then exit\n"
- " -J <MB> Size of journals\n"
- " -j <num> Number of journals\n"
- " -O Don't ask for confirmation\n"
- " -p <name> Name of the locking protocol\n"
- " -q Don't print anything\n"
- " -r <MB> Resource Group Size\n"
- " -t <name> Name of the lock table\n"
- " -u <MB> Size of unlinked file\n"
- " -V Print program version information, then exit\n"), prog_name);
-}
-
-/**
- * decode_arguments - decode command line arguments and fill in the struct gfs2_sbd
- * @argc:
- * @argv:
- * @sdp: the decoded command line arguments
- *
- */
-
-static void decode_arguments(int argc, char *argv[], struct gfs2_sbd *sdp)
-{
- int cont = TRUE;
- int optchar;
-
- memset(sdp->device_name, 0, sizeof(sdp->device_name));
- sdp->md.journals = 1;
- sdp->orig_fssize = 0;
-
- while (cont) {
- optchar = getopt(argc, argv, "-b:c:DhJ:j:Op:qr:t:u:VX");
-
- switch (optchar) {
- case 'b':
- sdp->bsize = atoi(optarg);
- break;
-
- case 'c':
- sdp->qcsize = atoi(optarg);
- break;
-
- case 'D':
- sdp->debug = TRUE;
- break;
-
- case 'h':
- print_usage(argv[0]);
- exit(0);
- break;
-
- case 'J':
- sdp->jsize = atoi(optarg);
- break;
-
- case 'j':
- sdp->md.journals = atoi(optarg);
- break;
-
- case 'O':
- sdp->override = TRUE;
- break;
-
- case 'p':
- if (strlen(optarg) >= GFS2_LOCKNAME_LEN)
- die( _("lock protocol name %s is too long\n"),
- optarg);
- strcpy(sdp->lockproto, optarg);
- break;
-
- case 'q':
- sdp->quiet = TRUE;
- break;
-
- case 'r':
- sdp->rgsize = atoi(optarg);
- break;
-
- case 't':
- if (strlen(optarg) >= GFS2_LOCKNAME_LEN)
- die( _("lock table name %s is too long\n"), optarg);
- strcpy(sdp->locktable, optarg);
- break;
-
- case 'u':
- sdp->utsize = atoi(optarg);
- break;
-
- case 'V':
- printf("gfs2_mkfs %s (built %s %s)\n", RELEASE_VERSION,
- __DATE__, __TIME__);
- printf( _(REDHAT_COPYRIGHT "\n"));
- exit(EXIT_SUCCESS);
- break;
-
- case 'X':
- sdp->expert = TRUE;
- break;
-
- case ':':
- case '?':
- fprintf(stderr, _("Please use '-h' for usage.\n"));
- exit(EXIT_FAILURE);
- break;
-
- case EOF:
- cont = FALSE;
- break;
-
- case 1:
- if (strcmp(optarg, "gfs2") == 0)
- continue;
- if (!sdp->device_name[0])
- strcpy(sdp->device_name, optarg);
- else if (!sdp->orig_fssize &&
- isdigit(optarg[0]))
- sdp->orig_fssize = atol(optarg);
- else
- die( _("More than one device specified (try -h for help)\n"));
- break;
-
- default:
- die( _("unknown option: %c\n"), optchar);
- break;
- };
- }
-
- if ((sdp->device_name[0] == 0) && (optind < argc))
- strcpy(sdp->device_name, argv[optind++]);
-
- if (sdp->device_name[0] == '\0')
- die( _("no device specified (try -h for help)\n"));
-
- if (optind < argc)
- sdp->orig_fssize = atol(argv[optind++]);
-
- if (optind < argc)
- die( _("Unrecognized argument: %s\n"), argv[optind]);
-
- if (sdp->debug) {
- printf( _("Command Line Arguments:\n"));
- if (sdp->bsize != -1)
- printf(" bsize = %u\n", sdp->bsize);
- printf(" qcsize = %u\n", sdp->qcsize);
- printf(" jsize = %u\n", sdp->jsize);
- printf(" journals = %u\n", sdp->md.journals);
- printf(" override = %d\n", sdp->override);
- printf(" proto = %s\n", sdp->lockproto);
- printf(" quiet = %d\n", sdp->quiet);
- if (sdp->rgsize==-1)
- printf( _(" rgsize = optimize for best performance\n"));
- else
- printf(" rgsize = %u\n", sdp->rgsize);
- printf(" table = %s\n", sdp->locktable);
- printf(" utsize = %u\n", sdp->utsize);
- printf(" device = %s\n", sdp->device_name);
- if (sdp->orig_fssize)
- printf(" block-count = %llu\n",
- (unsigned long long)sdp->orig_fssize);
- }
-}
-
-/**
- * test_locking - Make sure the GFS2 is set up to use the right lock protocol
- * @lockproto: the lock protocol to mount
- * @locktable: the locktable name
- *
- */
-
-static void test_locking(char *lockproto, char *locktable)
-{
- char *c;
-
- if (strcmp(lockproto, "lock_nolock") == 0) {
- /* Nolock is always ok. */
- } else if (strcmp(lockproto, "lock_gulm") == 0 ||
- strcmp(lockproto, "lock_dlm") == 0) {
- for (c = locktable; *c; c++) {
- if (isspace(*c))
- die( _("locktable error: contains space characters\n"));
- if (!isprint(*c))
- die( _("locktable error: contains unprintable characters\n"));
- }
-
- c = strstr(locktable, ":");
- if (!c)
- die( _("locktable error: missing colon in the locktable\n"));
-
- if (c == locktable)
- die( _("locktable error: missing cluster name\n"));
- if (c - locktable > 16)
- die( _("locktable error: cluster name too long\n"));
-
- c++;
- if (!c)
- die( _("locktable error: missing filesystem name\n"));
-
- if (strstr(c, ":"))
- die( _("locktable error: more than one colon present\n"));
-
- if (!strlen(c))
- die( _("locktable error: missing filesystem name\n"));
- if (strlen(c) > 16)
- die( _("locktable error: filesystem name too long\n"));
- } else {
- die( _("lockproto error: %s unknown\n"), lockproto);
- }
-}
-
-static void verify_bsize(struct gfs2_sbd *sdp)
-{
- unsigned int x;
- char input[32];
-
- /* Block sizes must be a power of two from 512 to 65536 */
-
- for (x = 512; x; x <<= 1)
- if (x == sdp->bsize)
- break;
-
- if (!x || sdp->bsize > getpagesize())
- die( _("block size must be a power of two between 512 and "
- "%d\n"), getpagesize());
-
- if (sdp->bsize < sdp->logical_block_size) {
- die( _("Error: Block size %d is less than minimum logical "
- "block size (%d).\n"), sdp->bsize,
- sdp->logical_block_size);
- }
-
- if (sdp->bsize < sdp->physical_block_size) {
- printf( _("WARNING: Block size %d is inefficient because it "
- "is less than the physical block size (%d).\n"),
- sdp->bsize, sdp->physical_block_size);
- if (sdp->override)
- return;
-
- printf( _("\nAre you sure you want to proceed? [y/n] "));
- if(!fgets(input, 32, stdin))
- die( _("unable to read from stdin\n"));
-
- if (input[0] != 'y')
- die( _("aborted\n"));
- else
- printf("\n");
- }
-}
-
-static void verify_arguments(struct gfs2_sbd *sdp)
-{
- if (!sdp->expert)
- test_locking(sdp->lockproto, sdp->locktable);
- /* Look at this! Why can't we go bigger than 2GB? */
- if (sdp->expert) {
- if (1 > sdp->rgsize || sdp->rgsize > 2048)
- die( _("bad resource group size\n"));
- } else {
- if (32 > sdp->rgsize || sdp->rgsize > 2048)
- die( _("bad resource group size\n"));
- }
-
- if (!sdp->md.journals)
- die( _("no journals specified\n"));
-
- if (sdp->jsize < 8 || sdp->jsize > 1024)
- die( _("bad journal size\n"));
-
- if (!sdp->utsize || sdp->utsize > 64)
- die( _("bad unlinked size\n"));
-
- if (!sdp->qcsize || sdp->qcsize > 64)
- die( _("bad quota change size\n"));
-}
-
-static int get_file_output(int fd, char *buffer, size_t buflen)
-{
- struct pollfd pf = { .fd = fd, .events = POLLIN|POLLRDHUP };
- int flags;
- int pos = 0;
- int rv;
-
- flags = fcntl(fd, F_GETFL, 0);
- if (flags < 0)
- return flags;
-
- flags |= O_NONBLOCK;
- rv = fcntl(fd, F_SETFL, flags);
- if (rv < 0)
- return rv;
-
- while (1) {
- rv = poll(&pf, 1, 10 * 1000);
- if (rv == 0)
- break;
- if (rv < 0)
- return rv;
- if (pf.revents & POLLIN) {
- rv = read(fd, buffer + pos,
- buflen - pos);
- if (rv < 0) {
- if (errno == EAGAIN)
- continue;
- return rv;
- }
- if (rv == 0)
- break;
- pos += rv;
- if (pos >= buflen)
- return -1;
- buffer[pos] = 0;
- continue;
- }
- if (pf.revents & (POLLRDHUP | POLLHUP | POLLERR))
- break;
- }
- return 0;
-}
-
-static void check_dev_content(const char *devname)
-{
- struct sigaction sa;
- char content[1024] = { 0, };
- char * args[] = {
- (char *)"/usr/bin/file",
- (char *)"-bs",
- (char *)devname,
- NULL };
- int p[2];
- int ret;
- int pid;
-
- ret = sigaction(SIGCHLD, NULL, &sa);
- if (ret)
- return;
- sa.sa_handler = SIG_IGN;
- sa.sa_flags |= (SA_NOCLDSTOP | SA_NOCLDWAIT);
- ret = sigaction(SIGCHLD, &sa, NULL);
- if (ret)
- goto fail;
-
- ret = pipe(p);
- if (ret)
- goto fail;
-
- pid = fork();
-
- if (pid < 0) {
- close(p[1]);
- goto fail;
- }
-
- if (pid) {
- close(p[1]);
- ret = get_file_output(p[0], content, sizeof(content));
- if (ret) {
-fail:
- printf( _("Content of file or device unknown (do you have GNU fileutils installed?)\n"));
- } else {
- if (*content == 0)
- goto fail;
- printf( _("It appears to contain: %s"), content);
- }
- close(p[0]);
- return;
- }
-
- close(p[0]);
- dup2(p[1], STDOUT_FILENO);
- close(STDIN_FILENO);
- exit(execv(args[0], args));
-}
-
-/**
- * are_you_sure - protect lusers from themselves
- * @sdp: the command line
- *
- */
-
-static void are_you_sure(struct gfs2_sbd *sdp)
-{
- char input[32];
- int fd;
-
- fd = open(sdp->device_name, O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- die( _("Error: device %s not found.\n"), sdp->device_name);
- printf( _("This will destroy any data on %s.\n"), sdp->device_name);
- check_dev_content(sdp->device_name);
- close(fd);
- printf( _("\nAre you sure you want to proceed? [y/n] "));
- if(!fgets(input, 32, stdin))
- die( _("unable to read from stdin\n"));
-
- if (input[0] != 'y')
- die( _("aborted\n"));
- else
- printf("\n");
-}
-
-/**
- * check_mount - check to see if device is mounted/busy
- * @device: the device to create the filesystem on
- *
- */
-
-static void check_mount(char *device)
-{
- struct stat st_buf;
- int fd;
-
- if (stat(device, &st_buf) < 0)
- die( _("could not stat device %s\n"), device);
- if (!S_ISBLK(st_buf.st_mode))
- die( _("%s is not a block device\n"), device);
-
- fd = open(device, O_RDONLY | O_NONBLOCK | O_EXCL | O_CLOEXEC);
-
- if (fd < 0) {
- if (errno == EBUSY) {
- die( _("device %s is busy\n"), device);
- }
- }
- else {
- close(fd);
- }
-
- return;
-}
-
-/**
- * print_results - print out summary information
- * @sdp: the command line
- *
- */
-
-static void
-print_results(struct gfs2_sbd *sdp, uint64_t real_device_size,
- unsigned char uuid[16])
-{
- if (sdp->debug)
- printf("\n");
- else if (sdp->quiet)
- return;
-
- if (sdp->expert)
- printf( _("Expert mode: on\n"));
-
- printf( _("Device: %s\n"), sdp->device_name);
-
- printf( _("Blocksize: %u\n"), sdp->bsize);
- printf( _("Device Size %.2f GB (%"PRIu64" blocks)\n"),
- real_device_size / ((float)(1 << 30)),
- real_device_size / sdp->bsize);
- printf( _("Filesystem Size: %.2f GB (%"PRIu64" blocks)\n"),
- sdp->fssize / ((float)(1 << 30)) * sdp->bsize, sdp->fssize);
-
- printf( _("Journals: %u\n"), sdp->md.journals);
- printf( _("Resource Groups: %"PRIu64"\n"), sdp->rgrps);
-
- printf( _("Locking Protocol: \"%s\"\n"), sdp->lockproto);
- printf( _("Lock Table: \"%s\"\n"), sdp->locktable);
-
- if (sdp->debug) {
- printf("\n");
- printf( _("Writes: %u\n"), sdp->writes);
- }
-
- printf( _("UUID: %s\n"), str_uuid(uuid));
- printf("\n");
-}
-
-/**
- * main_mkfs - do everything
- * @argc:
- * @argv:
- *
- */
-
-void main_mkfs(int argc, char *argv[])
-{
- struct gfs2_sbd sbd, *sdp = &sbd;
- int error;
- int rgsize_specified = 0;
- uint64_t real_device_size;
- unsigned char uuid[16];
-
- memset(sdp, 0, sizeof(struct gfs2_sbd));
- sdp->bsize = -1;
- sdp->jsize = GFS2_DEFAULT_JSIZE;
- sdp->rgsize = -1;
- sdp->utsize = GFS2_DEFAULT_UTSIZE;
- sdp->qcsize = GFS2_DEFAULT_QCSIZE;
- strcpy(sdp->lockproto, GFS2_DEFAULT_LOCKPROTO);
- sdp->time = time(NULL);
- osi_list_init(&sdp->rglist);
-
- decode_arguments(argc, argv, sdp);
- if (sdp->rgsize == -1) /* if rg size not specified */
- sdp->rgsize = GFS2_DEFAULT_RGSIZE; /* default it for now */
- else
- rgsize_specified = TRUE;
-
- verify_arguments(sdp);
-
- check_mount(sdp->device_name);
-
- sdp->device_fd = open(sdp->device_name, O_RDWR | O_CLOEXEC);
- if (sdp->device_fd < 0)
- die( _("can't open device %s: %s\n"),
- sdp->device_name, strerror(errno));
-
- if (!sdp->override)
- are_you_sure(sdp);
-
- if (device_topology(sdp)) {
- fprintf(stderr, _("Device topology error\n"));
- exit(-1);
- }
-
- if (sdp->bsize == -1) {
- /* See if optimal_io_size (the biggest I/O we can submit
- without incurring a penalty) is a suitable block size. */
- if (sdp->optimal_io_size <= getpagesize() &&
- sdp->optimal_io_size >= sdp->minimum_io_size)
- sdp->bsize = sdp->optimal_io_size;
- /* See if physical_block_size (the smallest unit we can write
- without incurring read-modify-write penalty) is suitable. */
- else if (sdp->physical_block_size <= getpagesize() &&
- sdp->physical_block_size >= GFS2_DEFAULT_BSIZE)
- sdp->bsize = sdp->physical_block_size;
- else
- sdp->bsize = GFS2_DEFAULT_BSIZE;
-
- if (sdp->debug)
- printf("\nUsing block size: %u\n", sdp->bsize);
- }
- verify_bsize(sdp);
-
- if (compute_constants(sdp)) {
- fprintf(stderr, _("Bad constants (1)\n"));
- exit(-1);
- }
-
- /* Get the device geometry */
-
- device_size(sdp->device_fd, &real_device_size);
- if (device_geometry(sdp)) {
- fprintf(stderr, _("Geometry error\n"));
- exit(-1);
- }
- /* Convert optional block-count to basic blocks */
- if (sdp->orig_fssize) {
- sdp->orig_fssize *= sdp->bsize;
- sdp->orig_fssize >>= GFS2_BASIC_BLOCK_SHIFT;
- if (sdp->orig_fssize > sdp->device.length) {
- fprintf(stderr, _("%s: Specified block count is bigger "
- "than the actual device.\n"), argv[0]);
- die( _("Device Size is %.2f GB (%"PRIu64" blocks)\n"),
- real_device_size / ((float)(1 << 30)),
- real_device_size / sdp->bsize);
- }
- sdp->device.length = sdp->orig_fssize;
- }
- if (fix_device_geometry(sdp)) {
- fprintf(stderr, _("Device is too small (%"PRIu64" bytes)\n"),
- sdp->device.length << GFS2_BASIC_BLOCK_SHIFT);
- exit(-1);
- }
-
- /* Compute the resource group layouts */
-
- compute_rgrp_layout(sdp, rgsize_specified);
-
- /* Generate a random uuid */
- get_random_bytes(uuid, sizeof(uuid));
-
- /* Build ondisk structures */
-
- build_rgrps(sdp, TRUE);
- build_root(sdp);
- build_master(sdp);
- build_sb(sdp, uuid);
- build_jindex(sdp);
- build_per_node(sdp);
- build_inum(sdp);
- build_statfs(sdp);
- build_rindex(sdp);
- build_quota(sdp);
-
- do_init_inum(sdp);
- do_init_statfs(sdp);
-
- /* Cleanup */
-
- inode_put(&sdp->md.rooti);
- inode_put(&sdp->master_dir);
- inode_put(&sdp->md.inum);
- inode_put(&sdp->md.statfs);
-
- gfs2_rgrp_free(&sdp->rglist);
- error = fsync(sdp->device_fd);
- if (error)
- die( _("can't fsync device (%d): %s\n"),
- error, strerror(errno));
- error = close(sdp->device_fd);
- if (error)
- die( _("error closing device (%d): %s\n"),
- error, strerror(errno));
-
- print_results(sdp, real_device_size, uuid);
-}
diff --git a/gfs2/mount/Makefile b/gfs2/mount/Makefile
deleted file mode 100644
index e653348..0000000
--- a/gfs2/mount/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-TARGET= mount.gfs2
-
-FORCESBINT= $(TARGET)
-
-all: ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= mount.gfs2.o \
- ondisk1.o \
- util.o \
- mtab.o
-
-CFLAGS += -DHELPER_PROGRAM -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
-CFLAGS += -I${gfskincdir}
-CFLAGS += -I${KERNEL_SRC}/fs/gfs2/ -I${KERNEL_SRC}/include/
-CFLAGS += -I$(SRCDIR)/group/libgfscontrol
-CFLAGS += -I$(S)/../include
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L../../group/libgfscontrol -lgfscontrol
-LDFLAGS += -L${libdir}
-
-LDDEPS += ../../group/libgfscontrol/libgfscontrol.a
-
-${TARGET}: ${OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs2/mount/mount.gfs2.c b/gfs2/mount/mount.gfs2.c
deleted file mode 100644
index d8e19a7..0000000
--- a/gfs2/mount/mount.gfs2.c
+++ /dev/null
@@ -1,237 +0,0 @@
-#include "util.h"
-
-const char *fsname;
-int verbose, fake_mount = 0, no_mtab = 0;
-static sigset_t old_sigset;
-
-static void print_version(void)
-{
- printf("mount.gfs2 %s (built %s %s)\n", RELEASE_VERSION,
- __DATE__, __TIME__);
-}
-
-static void print_usage(void)
-{
- printf("Usage:\n");
- printf("This program is called by mount(8), it should not be used directly.\n");
-}
-
-static void block_sigint(void)
-{
- sigset_t new;
-
- sigemptyset(&new);
- sigaddset(&new, SIGINT);
- sigprocmask(SIG_BLOCK, &new, &old_sigset);
-}
-
-static void unblock_sigint(void)
-{
- sigprocmask(SIG_SETMASK, &old_sigset, NULL);
-}
-
-static void read_options(int argc, char **argv, struct mount_options *mo)
-{
- int cont = 1;
- int optchar;
- char *real;
-
- /* FIXME: check for "quiet" option and don't print in that case */
-
- while (cont) {
- optchar = getopt(argc, argv, "hVo:t:vfn");
-
- switch (optchar) {
- case EOF:
- cont = 0;
- break;
-
- case 'h':
- print_usage();
- exit(EXIT_SUCCESS);
-
- case 'V':
- print_version();
- exit(EXIT_SUCCESS);
-
- case 'v':
- ++verbose;
- break;
-
- case 'o':
- if (optarg)
- strncpy(mo->opts, optarg, PATH_MAX);
- break;
-
- case 't':
- if (optarg)
- strncpy(mo->type, optarg, 4);
- break;
-
- case 'f':
- fake_mount = 1;
- break;
-
- case 'n':
- no_mtab = 1;
- break;
-
- default:
- break;
- }
- }
-
- if (optind < argc && argv[optind]) {
- real = realpath(argv[optind], NULL);
- if (!real)
- die("invalid device path \"%s\"\n", argv[optind]);
- strncpy(mo->dev, real, PATH_MAX);
- strncpy(mo->specified_dev, argv[optind], PATH_MAX);
- free(real);
- }
-
- ++optind;
-
- if (optind < argc && argv[optind]) {
- real = realpath(argv[optind], NULL);
- if (!real)
- die("invalid mount point path \"%s\"\n", argv[optind]);
- strncpy(mo->dir, real, PATH_MAX);
- free(real);
- }
-
- log_debug("mount %s %s", mo->dev, mo->dir);
-}
-
-static void check_options(struct mount_options *mo)
-{
- struct stat buf;
-
- if (!strlen(mo->dev))
- die("no device name specified\n");
-
- if (!strlen(mo->dir))
- die("no mount point specified\n");
-
- if (strlen(mo->type) && strcmp(mo->type, fsname))
- die("unknown file system type \"%s\"\n", mo->type);
-
- if (stat(mo->dir, &buf) < 0)
- die("mount point %s does not exist\n", mo->dir);
-
- if (!S_ISDIR(buf.st_mode))
- die("mount point %s is not a directory\n", mo->dir);
-}
-
-static int mount_lockproto(char *proto, struct mount_options *mo,
- struct gen_sb *sb)
-{
- int rv = 0;
-
- if (!strcmp(proto, "lock_dlm")) {
- if (mo->flags & MS_REMOUNT) {
- rv = lock_dlm_remount(mo, sb);
- strncpy(mo->extra_plus, mo->extra, PATH_MAX);
- }
- else
- rv = lock_dlm_join(mo, sb);
- } else
- strncpy(mo->extra_plus, mo->extra, PATH_MAX);
-
- return rv;
-}
-
-static void mount_done_lockproto(char *proto, struct mount_options *mo,
- struct gen_sb *sb, int result)
-{
- if (!strcmp(proto, "lock_dlm"))
- lock_dlm_mount_done(mo, sb, result);
-}
-
-static void umount_lockproto(char *proto, struct mount_options *mo,
- struct gen_sb *sb, int mnterr)
-{
- if (!strcmp(proto, "lock_dlm"))
- lock_dlm_leave(mo, sb, mnterr);
-}
-
-int main(int argc, char **argv)
-{
- struct mount_options mo;
- struct gen_sb sb;
- char *proto;
- int rv = 0;
-
- memset(&mo, 0, sizeof(mo));
- memset(&sb, 0, sizeof(sb));
-
- if (!strstr(argv[0], "gfs"))
- die("invalid mount helper name \"%s\"\n", argv[0]);
-
- fsname = (strstr(argv[0], "gfs2")) ? "gfs2" : "gfs";
- strcpy(mo.type, fsname);
-
- if (argc < 2) {
- print_usage();
- exit(EXIT_SUCCESS);
- }
-
- /* This breaks on-demand fs module loading from the kernel; could we
- try to load the module first here and then check again and fail if
- nothing? I'd really like to avoid joining the group and then
- backing out if the mount fails to load the module. */
- /* check_sys_fs(fsname); */
-
- read_options(argc, argv, &mo);
- check_options(&mo);
- get_sb(mo.dev, &sb);
- parse_opts(&mo);
-
- proto = select_lockproto(&mo, &sb);
-
- /* there are three parts to the mount and we want all three or none
- to happen: joining the mountgroup, doing the kernel mount, and
- adding the mtab entry */
- block_sigint();
-
- if (fake_mount)
- goto do_mtab;
-
- rv = mount_lockproto(proto, &mo, &sb);
- if (rv < 0)
- die("error mounting lockproto %s\n", proto);
-
- rv = mount(mo.dev, mo.dir, fsname, mo.flags, mo.extra_plus);
- if (rv) {
- log_debug("mount(2) failed error %d errno %d", rv, errno);
- mount_done_lockproto(proto, &mo, &sb, rv);
-
- if (!(mo.flags & MS_REMOUNT))
- umount_lockproto(proto, &mo, &sb, errno);
-
- if (errno == EBUSY)
- die("%s already mounted or %s busy\n", mo.dev, mo.dir);
- else if (errno == EUSERS)
- die("Too many nodes mounting filesystem, no free journals\n");
- die("error mounting %s on %s: %s\n", mo.dev, mo.dir,
- strerror(errno));
- }
- log_debug("mount(2) ok");
- mount_done_lockproto(proto, &mo, &sb, 0);
-
- do_mtab:
- if (no_mtab)
- goto out;
-
- if (mo.flags & MS_REMOUNT) {
- del_mtab_entry(&mo);
- add_mtab_entry(&mo);
- } else
- add_mtab_entry(&mo);
-
- out:
- unblock_sigint();
-
- return rv ? 1 : 0;
-}
-
diff --git a/gfs2/mount/mtab.c b/gfs2/mount/mtab.c
deleted file mode 100644
index a43d04e..0000000
--- a/gfs2/mount/mtab.c
+++ /dev/null
@@ -1,197 +0,0 @@
-#include "util.h"
-
-extern char *fsname;
-extern int verbose;
-static int ignoring_mtab;
-
-/* Don't bother with /etc/mtab if:
- - /etc/mtab is a link to /proc/mounts
- - there is no /etc/mtab file
- - we can't write to /etc/mtab */
-
-static int ignore_mtab(void)
-{
- struct stat sbuf;
- int fd;
-
- if (ignoring_mtab)
- return 1;
-
- if (lstat("/etc/mtab", &sbuf) < 0)
- goto do_ignore;
-
- if (S_ISLNK(sbuf.st_mode))
- goto do_ignore;
-
- fd = open("/etc/mtab", O_RDWR, 0644);
- if (fd < 0)
- goto do_ignore;
-
- close(fd);
- return 0;
-
- do_ignore:
- ignoring_mtab = 1;
- return 1;
-}
-
-/* Whichever process successfully links their own /etc/mtab~pid file to
- /etc/mtab~ gets the lock. We just sleep/retry until we get the lock.
- This is the locking method used by util-linux/mount/fstab.c which we
- need to keep in sync with. */
-
-static void lock_mtab(void)
-{
- char fname[32];
- int rv, fd, e, retries = 0;
-
- if (ignore_mtab())
- return;
-
- sprintf(fname, "/etc/mtab~%d", getpid());
- retry:
- fd = open(fname, O_WRONLY|O_CREAT, 0);
- e = errno;
- if (fd < 0)
- die("can't create mtab lock file %s: %s\n", fname, strerror(e));
- close(fd);
-
- rv = link(fname, "/etc/mtab~");
- e = errno;
-
- unlink(fname);
-
- if (rv < 0 && e != EEXIST)
- die("can't link %s to /etc/mtab~: %s\n", fname, strerror(e));
-
- if (rv < 0) {
- if (++retries > 5)
- warn("waiting to lock /etc/mtab~: try unlinking "
- "stale /etc/mtab~ file\n");
- sleep(1);
- goto retry;
- }
-}
-
-static void unlock_mtab(void)
-{
- if (ignore_mtab())
- return;
- unlink("/etc/mtab~");
-}
-
-void add_mtab_entry(struct mount_options *mo)
-{
- FILE *file;
-
- read_proc_mounts(mo);
-
- if (ignore_mtab())
- return;
-
- lock_mtab();
-
- file = fopen("/etc/mtab", "a");
- if (!file) {
- warn("can't add entry to /etc/mtab");
- return;
- }
-
- fprintf(file, "%s%s", mo->specified_dev, strchr(mo->proc_entry, ' '));
-
- fclose(file);
-
- unlock_mtab();
-}
-
-/* This follows what util-linux/mount/fstab.c does wrt writing new mtab.tmp
- and replacing /etc/mtab with it, we need to keep in sync with fstab.c's
- procedure for this. */
-
-void del_mtab_entry(struct mount_options *mo)
-{
- char line[PATH_MAX];
- char device[PATH_MAX];
- char path[PATH_MAX];
- char type[16];
- FILE *mtab, *mtmp;
- mode_t old_umask;
- struct stat sbuf;
- int found = 0;
-
- if (ignore_mtab())
- return;
-
- lock_mtab();
-
- old_umask = umask(077);
-
- mtmp = fopen("/etc/mtab.tmp", "w");
- mtab = fopen("/etc/mtab", "r");
-
- umask(old_umask);
-
- if (!mtmp || !mtab)
- goto fail;
-
- while (fgets(line, PATH_MAX, mtab)) {
- /* exclude the line matching the fs being unmounted
- from the next version of mtab */
-
- if ((sscanf(line, "%s %s %s", device, path, type) == 3) &&
- (strncmp(type, "gfs", 3) == 0) &&
- (strcmp(path, mo->dir) == 0) &&
- (strcmp(device, mo->dev) == 0)) {
- found = 1;
- continue;
- }
-
- /* all other lines from mtab are included in
- the next version of mtab */
-
- if (fprintf(mtmp, "%s", line) < 0) {
- int e = errno;
- warn("error writing to /etc/mtab.tmp: %s", strerror(e));
- }
- }
-
- if (!found) {
- warn("file system mounted on %s not found in mtab", mo->dir);
- goto fail;
- }
-
- if (fchmod(fileno(mtmp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
- int e = errno;
- warn("error changing mode of /etc/mtab.tmp: %s", strerror(e));
- }
-
- if (stat("/etc/mtab", &sbuf) < 0) {
- int e = errno;
- warn("error stating /etc/mtab: %s", strerror(e));
- } else
- if(chown("/etc/mtab.tmp", sbuf.st_uid, sbuf.st_gid) < 0) {
- int e = errno;
- warn("error changing owner of /etc/mtab.tmp: %s", strerror(e));
- }
-
- fclose(mtmp);
- fclose(mtab);
-
- if (rename("/etc/mtab.tmp", "/etc/mtab") < 0) {
- int e = errno;
- warn("can't rename /etc/mtab.tmp to /etc/mtab: %s",
- strerror(e));
- goto fail_unlink;
- }
-
- unlock_mtab();
- return;
-
- fail:
- fclose(mtmp);
- fclose(mtab);
- fail_unlink:
- unlink("/etc/mtab.tmp");
- unlock_mtab();
-}
-
diff --git a/gfs2/mount/ondisk1.c b/gfs2/mount/ondisk1.c
deleted file mode 100644
index 8b3d2c4..0000000
--- a/gfs2/mount/ondisk1.c
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <endian.h>
-#include <byteswap.h>
-
-#define printk printf
-#define pv(struct, member, fmt) printf(" "#member" = "fmt"\n", struct->member);
-
-#define ENTER(x)
-#define EXIT(x)
-#define RET(x) return
-#define RETURN(x, y) return y
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-
-#define be16_to_cpu(x) (x)
-#define be32_to_cpu(x) (x)
-#define be64_to_cpu(x) (x)
-
-#define cpu_to_be16(x) (x)
-#define cpu_to_be32(x) (x)
-#define cpu_to_be64(x) (x)
-
-#define le16_to_cpu(x) (bswap_16((x)))
-#define le32_to_cpu(x) (bswap_32((x)))
-#define le64_to_cpu(x) (bswap_64((x)))
-
-#define cpu_to_le16(x) (bswap_16((x)))
-#define cpu_to_le32(x) (bswap_32((x)))
-#define cpu_to_le64(x) (bswap_64((x)))
-
-#endif /* __BYTE_ORDER == __BIG_ENDIAN */
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-
-#define be16_to_cpu(x) (bswap_16((x)))
-#define be32_to_cpu(x) (bswap_32((x)))
-#define be64_to_cpu(x) (bswap_64((x)))
-
-#define cpu_to_be16(x) (bswap_16((x)))
-#define cpu_to_be32(x) (bswap_32((x)))
-#define cpu_to_be64(x) (bswap_64((x)))
-
-#define le16_to_cpu(x) (x)
-#define le32_to_cpu(x) (x)
-#define le64_to_cpu(x) (x)
-
-#define cpu_to_le16(x) (x)
-#define cpu_to_le32(x) (x)
-#define cpu_to_le64(x) (x)
-
-#endif /* __BYTE_ORDER == __LITTLE_ENDIAN */
-
-#define WANT_GFS_CONVERSION_FUNCTIONS
-#include "gfs_ondisk.h"
-
diff --git a/gfs2/mount/util.c b/gfs2/mount/util.c
deleted file mode 100644
index 5a1f999..0000000
--- a/gfs2/mount/util.c
+++ /dev/null
@@ -1,692 +0,0 @@
-#include <endian.h>
-#include <byteswap.h>
-#include "util.h"
-#include "libgfscontrol.h"
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-
-#define be16_to_cpu(x) (x)
-#define be32_to_cpu(x) (x)
-#define be64_to_cpu(x) (x)
-
-#define cpu_to_be16(x) (x)
-#define cpu_to_be32(x) (x)
-#define cpu_to_be64(x) (x)
-
-#define le16_to_cpu(x) (bswap_16((x)))
-#define le32_to_cpu(x) (bswap_32((x)))
-#define le64_to_cpu(x) (bswap_64((x)))
-
-#define cpu_to_le16(x) (bswap_16((x)))
-#define cpu_to_le32(x) (bswap_32((x)))
-#define cpu_to_le64(x) (bswap_64((x)))
-
-#endif /* __BYTE_ORDER == __BIG_ENDIAN */
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-
-#define be16_to_cpu(x) (bswap_16((x)))
-#define be32_to_cpu(x) (bswap_32((x)))
-#define be64_to_cpu(x) (bswap_64((x)))
-
-#define cpu_to_be16(x) (bswap_16((x)))
-#define cpu_to_be32(x) (bswap_32((x)))
-#define cpu_to_be64(x) (bswap_64((x)))
-
-#define le16_to_cpu(x) (x)
-#define le32_to_cpu(x) (x)
-#define le64_to_cpu(x) (x)
-
-#define cpu_to_le16(x) (x)
-#define cpu_to_le32(x) (x)
-#define cpu_to_le64(x) (x)
-
-#endif /* __BYTE_ORDER == __LITTLE_ENDIAN */
-
-extern char *fsname;
-extern int verbose;
-
-static int gfs_controld_fd;
-
-/* opt_map stuff from util-linux */
-
-struct opt_map {
- const char *opt; /* option name */
- int skip; /* skip in mtab option string (gfs: not used) */
- int inv; /* true if flag value should be inverted */
- int mask; /* flag mask value */
-};
-
-static struct opt_map opt_map[] = {
- { "defaults", 0, 0, 0 }, /* default options */
- { "ro", 1, 0, MS_RDONLY }, /* read-only */
- { "rw", 1, 1, MS_RDONLY }, /* read-write */
- { "exec", 0, 1, MS_NOEXEC }, /* permit execution of binaries */
- { "noexec", 0, 0, MS_NOEXEC }, /* don't execute binaries */
- { "suid", 0, 1, MS_NOSUID }, /* honor suid executables */
- { "nosuid", 0, 0, MS_NOSUID }, /* don't honor suid executables */
- { "dev", 0, 1, MS_NODEV }, /* interpret device files */
- { "nodev", 0, 0, MS_NODEV }, /* don't interpret devices */
- { "sync", 0, 0, MS_SYNCHRONOUS}, /* synchronous I/O */
- { "async", 0, 1, MS_SYNCHRONOUS}, /* asynchronous I/O */
- { "remount", 0, 0, MS_REMOUNT}, /* Alter flags of mounted FS */
- { "bind", 0, 0, MS_BIND }, /* Remount part of tree elsewhere */
- { "mand", 0, 0, MS_MANDLOCK }, /* Allow mandatory locks on this FS */
- { "nomand", 0, 1, MS_MANDLOCK }, /* Forbid mandatory locks on this FS */
- { "atime", 0, 1, MS_NOATIME }, /* Update access time */
- { "noatime", 0, 0, MS_NOATIME }, /* Do not update access time */
- { "diratime", 0, 1, MS_NODIRATIME }, /* Update dir access times */
- { "nodiratime", 0, 0, MS_NODIRATIME },/* Do not update dir access times */
-
- /* options used by the mount command only (not in sys/mount.h): */
- { "dirsync", 0, 0, 0 }, /* synchronous directory modifications */
- { "loop", 1, 0, 0 }, /* use a loop device */
- { "auto", 0, 1, 0 }, /* Can be mounted using -a */
- { "noauto", 0, 0, 0 }, /* Can only be mounted explicitly */
- { "users", 0, 0, 0 }, /* Allow ordinary user to mount */
- { "nousers", 0, 1, 0 }, /* Forbid ordinary user to mount */
- { "user", 0, 0, 0 }, /* Allow ordinary user to mount */
- { "nouser", 0, 1, 0 }, /* Forbid ordinary user to mount */
- { "owner", 0, 0, 0 }, /* Let the owner of the device mount */
- { "noowner", 0, 1, 0 }, /* Device owner has no special privs */
- { "_netdev", 0, 0, 0 }, /* Network device required (netfs) */
- { "relatime", 0, 1, 0 }, /* Update atime relative to mtime/ctime. */
- { NULL, 0, 0, 0 }
-};
-
-/* if option has a corresponding MS_XXX, set the bit in the flags */
-
-static int set_flag(char *o, int *flags)
-{
- struct opt_map *om;
-
- for (om = opt_map; om->opt; om++) {
- if (strcmp(om->opt, o))
- continue;
-
- if (om->inv)
- *flags &= ~om->mask;
- else
- *flags |= om->mask;
-
- log_debug(" %s flag %x for \"%s\", flags = %x",
- om->inv ? "clear" : "set", om->mask, om->opt, *flags);
-
- return 1;
- }
-
- return 0;
-}
-
-/* opts is the string of all mount options, this function finds
- the options that have MS_XXX flags and sets the appropriate flag
- bit. The options without an MS_ flag are copied into the extra
- string. The values of some specific options are saved for later
- internal use. */
-
-void parse_opts(struct mount_options *mo)
-{
- char data[PATH_MAX+1];
- char *options, *o, *v;
- int extra_len = 0;
-
- log_debug("parse_opts: opts = \"%s\"", mo->opts);
-
- memset(data, 0, sizeof(data));
- strncpy(data, mo->opts, PATH_MAX);
-
- for (options = data; (o = strsep(&options, ",")); ) {
- if (!*o)
- continue;
-
- if (set_flag(o, &mo->flags))
- continue;
-
- if (!strncmp("hostdata", o, 8)) {
- if (mo->hostdata[0])
- warn("duplicate hostdata strings");
- else
- strcat(mo->hostdata, o);
- continue;
- }
-
- if (extra_len + 1 + strlen(o) > PATH_MAX)
- die("extra options string is too long\n");
-
- if (mo->extra[0]) {
- strcat(mo->extra, ",");
- extra_len += 1;
- }
-
- log_debug(" add extra %s", o);
-
- strcat(mo->extra, o);
- extra_len += strlen(o);
-
- v = strchr(o, '=');
- if (v)
- *v++ = 0;
-
- /* we grab these now so we don't have to parse them out
- again later when doing proto-specific stuff */
-
- if (!strcmp(o, "lockproto")) {
- if (!v)
- die("option lockproto needs value\n");
- strncpy(mo->lockproto, v, 255);
- }
-
- if (!strcmp(o, "locktable")) {
- if (!v)
- die("option locktable needs value\n");
- strncpy(mo->locktable, v, 255);
- }
- }
-
- /* Hack to get the noatime/nodiratime option through to gfs */
- if ((mo->flags & (MS_NOATIME | MS_NODIRATIME)) &&
- (strcmp(mo->type, "gfs") == 0)) {
- if (mo->extra[0]) {
- strcat(mo->extra, ",");
- extra_len += 1;
- }
- strcat(mo->extra, "gfs_noatime");
- extra_len += strlen("gfs_noatime");
- }
-
- log_debug("parse_opts: flags = %x", mo->flags);
- log_debug("parse_opts: extra = \"%s\"", mo->extra);
- log_debug("parse_opts: hostdata = \"%s\"", mo->hostdata);
- log_debug("parse_opts: lockproto = \"%s\"", mo->lockproto);
- log_debug("parse_opts: locktable = \"%s\"", mo->locktable);
-}
-
-/* Remove escape sequences from mount path. Per getmntent(3), there are
- only four escape sequences we need to handle. Consequently, this does
- not need to be a general-purpose unescape function */
-
-static int mnt_unescape(char *dest, size_t len, const char *src)
-{
- unsigned i = 0, j = 0;
- size_t srclen;
-
- srclen = strlen(src);
- while (i < srclen) {
- if (src[i] != '\\') {
- dest[j] = src[i];
- ++i; ++j;
- continue;
- }
-
- ++i;
- if ((srclen - 3) < i)
- return -1;
-
- if (!strncmp(&src[i], "040", 3)) {
- dest[j] = ' ';
- } else if (!strncmp(&src[i], "011", 3)) {
- dest[j] = '\t';
- } else if (!strncmp(&src[i], "012", 3)) {
- dest[j] = '\n';
- } else if (!strncmp(&src[i], "134", 3)) {
- dest[j] = '\\';
- } else {
- return -1;
- }
-
- i+=3;
- j++;
- }
-
- return 0;
-}
-
-
-/* - when unmounting, we don't know the dev and need this function to set it;
- we also want to select the _last_ line with a matching dir since it will
- be the top-most fs that the umount(2) will unmount
- - when mounting, we do know the dev and need this function to use it in the
- comparison (for multiple fs's with the same mountpoint) */
-
-void read_proc_mounts(struct mount_options *mo)
-{
- FILE *file;
- char line[PATH_MAX];
- char path[PATH_MAX];
- char unescaped_path[PATH_MAX];
- char type[PATH_MAX];
- char opts[PATH_MAX];
- char device[PATH_MAX];
- char save_line[PATH_MAX];
- char save_opts[PATH_MAX];
- char save_device[PATH_MAX];
- int found = 0;
- struct stat st_mo_dev, st_mounts_dev;
-
- file = fopen("/proc/mounts", "r");
- if (!file)
- die("can't open /proc/mounts: %s\n", strerror(errno));
-
- memset(&st_mo_dev, 0, sizeof(struct stat));
- if (mo->dev[0]) {
- if (stat(mo->dev, &st_mo_dev))
- warn("Can't stat device %s.\n", mo->dev);
- }
-
- while (fgets(line, PATH_MAX, file)) {
- if (sscanf(line, "%s %s %s %s", device, path, type, opts) != 4)
- continue;
- if (strcmp(path, mo->dir)) {
- if (!strchr(path, '\\'))
- continue;
- /* /proc/mounts entry may have escaped spaces */
- if (mnt_unescape(unescaped_path, sizeof(unescaped_path),
- path) < 0)
- continue;
- if (strcmp(unescaped_path, mo->dir))
- continue;
- }
- if (mo->dev[0]) {
- if (stat(device, &st_mounts_dev))
- continue;
- if (st_mo_dev.st_rdev != st_mounts_dev.st_rdev)
- continue;
- }
- if (strcmp(type, fsname))
- die("%s is not a %s filesystem\n", mo->dir, fsname);
-
- /* when there is an input dev specified (mount), we should get
- only one matching line; when there is no input dev specified
- (umount), we want the _last_ matching line */
-
- strncpy(save_device, device, PATH_MAX);
- strncpy(save_opts, opts, PATH_MAX);
- strncpy(save_line, line, PATH_MAX);
- found = 1;
- }
-
- fclose(file);
-
- if (!found)
- die("can't find /proc/mounts entry for directory %s\n", mo->dir);
- else {
- strncpy(mo->dev, save_device, PATH_MAX);
- strncpy(mo->opts, save_opts, PATH_MAX);
- strncpy(mo->proc_entry, save_line, PATH_MAX);
- }
-
- log_debug("read_proc_mounts: device = \"%s\"", mo->specified_dev);
- log_debug("read_proc_mounts: dm device = \"%s\"", mo->dev);
- log_debug("read_proc_mounts: opts = \"%s\"", mo->opts);
-}
-
-static void gfs2_inum_in(struct gfs2_inum *no, char *buf)
-{
- struct gfs2_inum *str = (struct gfs2_inum *)buf;
-
- no->no_formal_ino = be64_to_cpu(str->no_formal_ino);
- no->no_addr = be64_to_cpu(str->no_addr);
-}
-
-static void gfs2_meta_header_in(struct gfs2_meta_header *mh, char *buf)
-{
- struct gfs2_meta_header *str = (struct gfs2_meta_header *)buf;
-
- mh->mh_magic = be32_to_cpu(str->mh_magic);
- mh->mh_type = be32_to_cpu(str->mh_type);
- mh->mh_format = be32_to_cpu(str->mh_format);
-}
-
-static void gfs2_sb_in(struct gfs2_sb *sb, char *buf)
-{
- struct gfs2_sb *str = (struct gfs2_sb *)buf;
-
- gfs2_meta_header_in(&sb->sb_header, buf);
-
- sb->sb_fs_format = be32_to_cpu(str->sb_fs_format);
- sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format);
- sb->sb_bsize = be32_to_cpu(str->sb_bsize);
- sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift);
-
- gfs2_inum_in(&sb->sb_master_dir, (char *)&str->sb_master_dir);
- gfs2_inum_in(&sb->sb_root_dir, (char *)&str->sb_root_dir);
-
- memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
- memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
-}
-
-int get_sb(char *device, struct gen_sb *sb_out)
-{
- int fd;
-
- fd = open(device, O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", device, strerror(errno));
-
- if (!strcmp(fsname, "gfs2")) {
- char buf[GFS2_BASIC_BLOCK];
- struct gfs2_sb sb;
-
- if (lseek(fd, GFS2_SB_ADDR * GFS2_BASIC_BLOCK, SEEK_SET) !=
- GFS2_SB_ADDR * GFS2_BASIC_BLOCK) {
- fprintf(stderr, "bad seek: %s from %s:%d: "
- "superblock\n",
- strerror(errno), __FUNCTION__, __LINE__);
- exit(-1);
- }
- do_read(fd, buf, GFS2_BASIC_BLOCK);
- gfs2_sb_in(&sb, buf);
-
- if (sb.sb_header.mh_magic != GFS2_MAGIC ||
- sb.sb_header.mh_type != GFS2_METATYPE_SB) {
- die("there isn't a GFS2 filesystem on %s, "
- "magic=%x type=%x\n", device,
- sb.sb_header.mh_magic, sb.sb_header.mh_type);
- }
-
- if (sb.sb_fs_format != GFS2_FORMAT_FS ||
- sb.sb_multihost_format != GFS2_FORMAT_MULTI) {
- die("there appears to be a GFS, not GFS2, filesystem "
- "on %s\n", device);
- }
-
- strncpy(sb_out->lockproto, sb.sb_lockproto, 256);
- strncpy(sb_out->locktable, sb.sb_locktable, 256);
-
- } else if (!strcmp(fsname, "gfs")) {
- char buf[GFS_BASIC_BLOCK];
- struct gfs_sb sb;
-
- if (lseek(fd, GFS_SB_ADDR * GFS_BASIC_BLOCK, SEEK_SET) !=
- GFS_SB_ADDR * GFS_BASIC_BLOCK) {
- fprintf(stderr, "bad seek: %s from %s:%d: "
- "superblock\n",
- strerror(errno), __FUNCTION__, __LINE__);
- exit(-1);
- }
- do_read(fd, buf, GFS2_BASIC_BLOCK);
- gfs_sb_in(&sb, buf);
-
- if (sb.sb_header.mh_magic != GFS_MAGIC ||
- sb.sb_header.mh_type != GFS_METATYPE_SB) {
- die("there isn't a GFS filesystem on %s\n", device);
- }
-
- if (sb.sb_fs_format != GFS_FORMAT_FS ||
- sb.sb_multihost_format != GFS_FORMAT_MULTI) {
- die("there appears to be a GFS2, not GFS, filesystem "
- "on %s\n", device);
- }
-
- strncpy(sb_out->lockproto, sb.sb_lockproto, 256);
- strncpy(sb_out->locktable, sb.sb_locktable, 256);
- }
-
- close(fd);
- return 0;
-}
-
-char *select_lockproto(struct mount_options *mo, struct gen_sb *sb)
-{
- /* find the effective lockproto, proto specified in mount options
- overrides the sb lockproto */
-
- if (mo->lockproto[0])
- return mo->lockproto;
- else
- return sb->lockproto;
-}
-
-int lock_dlm_join(struct mount_options *mo, struct gen_sb *sb)
-{
- struct gfsc_mount_args ma;
- int fd, rv, result;
-
- memset(&ma, 0, sizeof(ma));
-
- strncpy(ma.dir, mo->dir, PATH_MAX);
- strncpy(ma.type, fsname, PATH_MAX);
- strncpy(ma.proto, "lock_dlm", PATH_MAX);
- strncpy(ma.options, mo->opts, PATH_MAX);
- strncpy(ma.dev, mo->dev, PATH_MAX);
- if (mo->locktable[0])
- strncpy(ma.table, mo->locktable, PATH_MAX);
- else
- strncpy(ma.table, sb->locktable, PATH_MAX);
-
- fd = gfsc_fs_connect();
- if (fd < 0) {
- warn("gfs_controld join connect error: %s", strerror(errno));
- return fd;
- }
-
- /* tell gfs_controld to join the mountgroup */
-
- rv = gfsc_fs_join(fd, &ma);
- if (rv < 0) {
- warn("gfs_controld join write error: %s", strerror(errno));
- goto fail;
- }
-
- /* read the result of the join from gfs_controld */
-
- rv = gfsc_fs_result(fd, &result, &ma);
- if (rv < 0) {
- warn("gfs_controld result read error: %s", strerror(errno));
- goto fail;
- }
-
- rv = result;
-
- switch (rv) {
- case 0:
- case -EALREADY:
- break;
-
- case -EPROTONOSUPPORT:
- warn("lockproto not supported");
- goto fail;
-
- case -EOPNOTSUPP:
- warn("jid, first and id are reserved options");
- goto fail;
-
- case -EBADFD:
- warn("no colon found in table name");
- goto fail;
-
- case -ENAMETOOLONG:
- warn("fs name too long");
- goto fail;
-
- case -ESTALE:
- warn("fs is being unmounted");
- goto fail;
-
- case -EADDRINUSE:
- warn("different fs appears to exist with the same name");
- goto fail;
-
- case -EBUSY:
- warn("mount point already used or other mount in progress");
- goto fail;
-
- case -ENOMEM:
- warn("out of memory");
- goto fail;
-
- case -EBADR:
- warn("fs is for a different cluster");
- goto fail;
-
- case -ENOANO:
- warn("node not a member of the default fence domain");
- goto fail;
-
- case -EROFS:
- warn("read-only mount invalid with spectator option");
- goto fail;
-
- case -EMLINK:
- warn("option string too long");
- goto fail;
-
- default:
- warn("gfs_controld join error: %d", rv);
- goto fail;
- }
-
- /*
- * In addition to the result, gfs_controld also returns
- * "hostdata=jid=X:id=Y:first=Z" in ma.hostdata.
- * This is first combined with any hostdata the user gave on
- * the command line and then the full hostdata is combined
- * with the "extra" mount otions into the "extra_plus" string.
- */
-
- if (strlen(mo->hostdata) + strlen(ma.hostdata) + 1 > PATH_MAX) {
- warn("hostdata too long");
- rv = -1;
- goto fail;
- }
-
- if (!mo->hostdata[0])
- snprintf(mo->hostdata, PATH_MAX, "%s", ma.hostdata);
- else {
- char *p = strstr(ma.hostdata, "=") + 1;
- strcat(mo->hostdata, ":");
- strcat(mo->hostdata, p);
- }
-
- log_debug("lock_dlm_join: hostdata: \"%s\"", mo->hostdata);
-
- if (strlen(mo->extra) == 0)
- snprintf(mo->extra_plus, PATH_MAX, "%s", mo->hostdata);
- else
- snprintf(mo->extra_plus, PATH_MAX, "%s,%s",
- mo->extra, mo->hostdata);
-
- /* keep gfs_controld connection open and reuse it below to
- send the result of mount(2) to gfs_controld, except in
- the case of another mount (EALREADY) */
-
- if (rv == -EALREADY)
- gfsc_fs_disconnect(fd);
- else
- gfs_controld_fd = fd;
-
- return 0;
-
- fail:
- gfsc_fs_disconnect(fd);
- return rv;
-}
-
-void lock_dlm_mount_done(struct mount_options *mo, struct gen_sb *sb,
- int result)
-{
- struct gfsc_mount_args ma;
- int rv;
-
- if (!gfs_controld_fd)
- return;
-
- memset(&ma, 0, sizeof(ma));
-
- strncpy(ma.dir, mo->dir, PATH_MAX);
- strncpy(ma.type, fsname, PATH_MAX);
- strncpy(ma.proto, "lock_dlm", PATH_MAX);
- strncpy(ma.options, mo->opts, PATH_MAX);
- strncpy(ma.dev, mo->dev, PATH_MAX);
- if (mo->locktable[0])
- strncpy(ma.table, mo->locktable, PATH_MAX);
- else
- strncpy(ma.table, sb->locktable, PATH_MAX);
-
- /* tell gfs_controld the result of mount(2) */
-
- rv = gfsc_fs_mount_done(gfs_controld_fd, &ma, result);
- if (rv)
- warn("gfs_controld mount_done write error: %s", strerror(errno));
-
- gfsc_fs_disconnect(gfs_controld_fd);
-}
-
-int lock_dlm_leave(struct mount_options *mo, struct gen_sb *sb, int mnterr)
-{
- struct gfsc_mount_args ma;
- int rv;
-
- memset(&ma, 0, sizeof(ma));
-
- strncpy(ma.dir, mo->dir, PATH_MAX);
- strncpy(ma.type, fsname, PATH_MAX);
- if (mo->locktable[0])
- strncpy(ma.table, mo->locktable, PATH_MAX);
- else
- strncpy(ma.table, sb->locktable, PATH_MAX);
-
- rv = gfsc_fs_leave(&ma, mnterr);
- if (rv)
- warn("leave: gfs_controld leave error: %s", strerror(errno));
-
- return rv;
-}
-
-int lock_dlm_remount(struct mount_options *mo, struct gen_sb *sb)
-{
- struct gfsc_mount_args ma;
- const char *mode;
- int fd, rv, result;
-
- memset(&ma, 0, sizeof(ma));
-
- if (strstr(mo->extra, "spectator")) {
- warn("spectator remounts not allowed");
- return -1;
- }
-
- if (mo->flags & MS_RDONLY)
- mode = "ro";
- else
- mode = "rw";
-
- strncpy(ma.dir, mo->dir, PATH_MAX);
- strncpy(ma.type, fsname, PATH_MAX);
- strncpy(ma.options, mode, PATH_MAX);
- if (mo->locktable[0])
- strncpy(ma.table, mo->locktable, PATH_MAX);
- else
- strncpy(ma.table, sb->locktable, PATH_MAX);
-
-
- fd = gfsc_fs_connect();
- if (fd < 0) {
- warn("gfs_controld remount connect error: %s", strerror(errno));
- return fd;
- }
-
- /* tell gfs_controld about the new mount options */
-
- rv = gfsc_fs_remount(fd, &ma);
- if (rv) {
- warn("gfs_controld remount write error: %s", strerror(errno));
- goto out;
- }
-
- /* read the result of the remount from gfs_controld */
-
- rv = gfsc_fs_result(fd, &result, &ma);
- if (rv < 0) {
- warn("gfs_controld result read error: %s", strerror(errno));
- goto out;
- }
-
- rv = result;
- if (rv)
- warn("remount not allowed from gfs_controld");
- out:
- gfsc_fs_disconnect(fd);
- return rv;
-}
-
diff --git a/gfs2/mount/util.h b/gfs2/mount/util.h
deleted file mode 100644
index e866cd4..0000000
--- a/gfs2/mount/util.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef __MOUNT_DOT_H__
-#define __MOUNT_DOT_H__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mount.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <limits.h>
-#include <dirent.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <linux/types.h>
-#include <linux/gfs2_ondisk.h>
-#include "gfs_ondisk.h"
-
-#define die(fmt, args...) \
-do { \
- fprintf(stderr, fmt, ##args); \
- exit(EXIT_FAILURE); \
-} while (0)
-
-#define warn(fmt, args...) \
-do { \
- fprintf(stderr, fmt "\n", ##args); \
-} while (0)
-
-#define log_debug(fmt, args...) \
-do { \
- if (verbose) \
- printf(fmt "\n", ##args); \
-} while (0)
-
-#define do_read(fd, buff, len) \
-do { \
- if (read((fd), (buff), (len)) != (len)) \
- die("bad read: %s on line %d of file %s\n", \
- strerror(errno), __LINE__, __FILE__); \
-} while (0)
-
-struct mount_options {
- char specified_dev[PATH_MAX+1];
- char dev[PATH_MAX+1];
- char dir[PATH_MAX+1];
- char opts[PATH_MAX+1];
- char hostdata[PATH_MAX+1];
- char extra[PATH_MAX+1];
- char extra_plus[PATH_MAX+1];
- char type[5];
- char lockproto[256];
- char locktable[256];
- char proc_entry[PATH_MAX+1];
- int flags;
-};
-
-struct gen_sb {
- char lockproto[256];
- char locktable[256];
-};
-
-/* util.c */
-
-char *select_lockproto(struct mount_options *mo, struct gen_sb *sb);
-void parse_opts(struct mount_options *mo);
-void read_proc_mounts(struct mount_options *mo);
-int get_sb(char *device, struct gen_sb *sb_out);
-int lock_dlm_join(struct mount_options *mo, struct gen_sb *sb);
-void lock_dlm_mount_done(struct mount_options *mo, struct gen_sb *sb, int result);
-int lock_dlm_leave(struct mount_options *mo, struct gen_sb *sb, int mnterr);
-int lock_dlm_remount(struct mount_options *mo, struct gen_sb *sb);
-
-/* mtab.c */
-
-void add_mtab_entry(struct mount_options *mo);
-void del_mtab_entry(struct mount_options *mo);
-
-#endif
-
diff --git a/gfs2/quota/Makefile b/gfs2/quota/Makefile
deleted file mode 100644
index 165df2d..0000000
--- a/gfs2/quota/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-TARGET= gfs2_quota
-
-SBINDIRT=$(TARGET)
-
-all: depends ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= main.o \
- names.o \
- check.o
-
-CFLAGS += -DHELPER_PROGRAM -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
-CFLAGS += -I${KERNEL_SRC}/fs/gfs2/ -I${KERNEL_SRC}/include/
-CFLAGS += -I$(S)/../include -I$(S)/../libgfs2
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L../libgfs2 -lgfs2
-LDFLAGS += -L${libdir}
-
-LDDEPS += ../libgfs2/libgfs2.a
-
-${TARGET}: ${OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-depends:
- $(MAKE) -C ../libgfs2 all
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs2/quota/check.c b/gfs2/quota/check.c
deleted file mode 100644
index 81a4364..0000000
--- a/gfs2/quota/check.c
+++ /dev/null
@@ -1,599 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <time.h>
-#include <dirent.h>
-#include <limits.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <linux/types.h>
-#include <linux/fiemap.h>
-
-#define __user
-#include "osi_list.h"
-
-#include "gfs2_quota.h"
-
-#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap)
-
-struct values {
- osi_list_t v_list;
-
- uint32_t v_id;
- int64_t v_blocks;
-};
-typedef struct values values_t;
-
-struct hardlinks {
- osi_list_t hl_list;
-
- ino_t hl_ino;
-};
-typedef struct hardlinks hardlinks_t;
-
-/**
- * add_value - add a ID / Allocated Blocks pair to the list
- * @list: the list
- * @id: the ID number
- * @blocks: the number of blocks to add
- *
- */
-
-static void
-add_value(osi_list_t *list, uint32_t id, int64_t blocks)
-{
- osi_list_t *tmp;
- values_t *v;
-
- for (tmp = list->next; tmp != list; tmp = tmp->next) {
- v = osi_list_entry(tmp, values_t, v_list);
- if (v->v_id != id)
- continue;
-
- v->v_blocks += blocks;
-
- osi_list_del(&v->v_list);
- osi_list_add(&v->v_list, list);
-
- return;
- }
-
- type_zalloc(v, values_t, 1);
-
- v->v_id = id;
- v->v_blocks = blocks;
-
- osi_list_add(&v->v_list, list);
-}
-
-/**
- * test_and_add_hard_link - Add a inode that has hard links to the list
- * @list: the list of inodes with hard links
- * @ino: the number of the inode to add
- *
- * Returns: Returns TRUE if the inode was already on the list, FALSE if it wasn't
- */
-
-static int
-test_and_add_hard_link(osi_list_t *list, ino_t ino)
-{
- osi_list_t *tmp;
- hardlinks_t *hl;
-
- for (tmp = list->next; tmp != list; tmp = tmp->next) {
- hl = osi_list_entry(tmp, hardlinks_t, hl_list);
- if (hl->hl_ino != ino)
- continue;
-
- return TRUE;
- }
-
- type_zalloc(hl, hardlinks_t, 1);
-
- hl->hl_ino = ino;
-
- osi_list_add(&hl->hl_list, list);
-
- return FALSE;
-}
-
-/**
- * scan_fs - recursively scan a filesystem and figure out what IDs have what
- * @device: the device the filesystem is on
- * @dirname: the name of the directory to read
- * @uid: returned list of UIDs for this FS
- * @gid: returned list of GIDs for this FS
- * @hl: returned list of hard links for this FS
- *
- */
-
-static void
-scan_fs(dev_t device, char *dirname,
- osi_list_t *uid, osi_list_t *gid, osi_list_t *hl)
-{
- DIR *dir;
- struct dirent *de;
- struct stat st;
- char *name;
- int error;
-
- dir = opendir(dirname);
- if (!dir)
- die("can't open directory %s: %s\n", dirname, strerror(errno));
-
- while ((de = readdir(dir))) {
- if (strcmp(de->d_name, "..") == 0)
- continue;
-
- type_alloc(name, char,
- strlen(dirname) + strlen(de->d_name) + 2);
- if (dirname[strlen(dirname) - 1] == '/')
- sprintf(name, "%s%s", dirname, de->d_name);
- else
- sprintf(name, "%s/%s", dirname, de->d_name);
-
- error = lstat(name, &st);
- if (error)
- die("can't stat file %s: %s\n", name, strerror(errno));
-
- if (st.st_dev != device)
- die("umount %s and try again\n", name);
-
- if (S_ISDIR(st.st_mode)) {
- if (strcmp(de->d_name, ".") == 0) {
- add_value(uid, st.st_uid, st.st_blocks);
- add_value(gid, st.st_gid, st.st_blocks);
- } else
- scan_fs(device, name, uid, gid, hl);
- } else if (st.st_nlink == 1 ||
- !test_and_add_hard_link(hl, st.st_ino)) {
- add_value(uid, st.st_uid, st.st_blocks);
- add_value(gid, st.st_gid, st.st_blocks);
- }
-
- free(name);
- }
-
- closedir(dir);
-}
-
-/**
- * read_quota_file - read the quota file and return list of its contents
- * @comline: the command line arguments
- * @uid: returned list of UIDs for the filesystem
- * @gid: returned list of GIDs for the filesystem
- *
- */
-static void
-read_quota_file(struct gfs2_sbd *sdp, commandline_t *comline,
- osi_list_t *uid, osi_list_t *gid)
-{
- int fd;
- uint32_t id, startq;
- int error = 0;
- char quota_file[BUF_SIZE];
- uint64_t quota_file_size = 0;
- struct fiemap fmap = { 0, }, *fmap2;
- struct stat statbuf;
-
- strcpy(sdp->path_name, comline->filesystem);
- if (check_for_gfs2(sdp)) {
- if (errno == EINVAL)
- fprintf(stderr, "Not a valid GFS2 mount point: %s\n",
- sdp->path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
- read_superblock(&sdp->sd_sb, sdp);
- if (mount_gfs2_meta(sdp)) {
- fprintf(stderr, "Error mounting GFS2 metafs: %s\n",
- strerror(errno));
- exit(-1);
- }
-
- strcpy(quota_file, sdp->metafs_path);
- strcat(quota_file, "/quota");
-
- fd = open(quota_file, O_RDONLY);
- if (fd < 0) {
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
- die("can't open file %s: %s\n", comline->filesystem,
- strerror(errno));
- }
- if (fstat(fd, &statbuf) < 0) {
- close(fd);
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
- die("can't stat file %s: %s\n", quota_file,
- strerror(errno));
- }
- quota_file_size = statbuf.st_size;
- /* First find the number of extents in the quota file */
- fmap.fm_flags = 0;
- fmap.fm_start = 0;
- fmap.fm_length = (~0ULL);
- error = ioctl(fd, FS_IOC_FIEMAP, &fmap);
- if (error == -1) {
- fprintf(stderr, "fiemap error (%d): %s\n", errno, strerror(errno));
- goto out;
- }
- fmap2 = malloc(sizeof(struct fiemap) +
- fmap.fm_mapped_extents * sizeof(struct fiemap_extent));
- if (fmap2 == NULL) {
- fprintf(stderr, "malloc error (%d): %s\n", errno, strerror(errno));
- goto out;
- }
- fmap2->fm_flags = 0;
- fmap2->fm_start = 0;
- fmap2->fm_length = (~0ULL);
- fmap2->fm_extent_count = fmap.fm_mapped_extents;
- error = ioctl(fd, FS_IOC_FIEMAP, fmap2);
- if (error == -1) {
- fprintf(stderr, "fiemap error (%d): %s\n", errno, strerror(errno));
- goto fmap2_free;
- }
- if (fmap2->fm_mapped_extents) {
- int i;
- for (i=0; i<fmap2->fm_mapped_extents; i++) {
- struct fiemap_extent *fe = &fmap2->fm_extents[i];
- uint64_t end = fe->fe_logical + fe->fe_length, val_off;
- unsigned int v_off;
-
- end = end > quota_file_size ? quota_file_size : end;
- /* we only need to get the value fields, not the whole quota
- * This also works when struct gfs2_quota straddle page
- * boundaries. Getting only the value field avoids the
- * complexity of fetching two parts of the struct gfs2_quota
- * from two successive pages
- */
- /* offset of the value field within struct gfs2_quota */
- v_off = (unsigned long)(&((struct gfs2_quota *)NULL)->qu_value);
- /* startq could be at the end of previous extent... */
- startq = fe->fe_logical / sizeof(struct gfs2_quota);
- /* but the value field could be in this extent */
- if ((startq * sizeof(struct gfs2_quota) + v_off) >= fe->fe_logical)
- val_off = startq * sizeof(struct gfs2_quota) + v_off;
- else /* if the start of the extent doesn't have a split quota */
- val_off = ++startq * sizeof(struct gfs2_quota) + v_off;
-
- while ((val_off + sizeof(uint64_t)) <= end)
- {
- uint64_t value;
- /* read hidden quota file here */
- lseek(fd, val_off, SEEK_SET);
- error = read(fd, (unsigned char*)&value, sizeof(uint64_t));
- if (error < 0) {
- fprintf(stderr, "read error (%d): %s\n",
- errno, strerror(errno));
- goto fmap2_free;
- }
- value = be64_to_cpu(value);
- id = startq >> 1;
- /* We want value in 512 byte blocks (1 << 9 = 512) */
- value <<= sdp->sd_sb.sb_bsize_shift - 9;
- if (value) {
- /* if startq is even, it's a uid, else gid */
- if (startq % 2)
- add_value(gid, id, value);
- else
- add_value(uid, id, value);
- }
- startq++;
- val_off += sizeof(struct gfs2_quota);
- }
- }
- }
-fmap2_free:
- free(fmap2);
-out:
- close(fd);
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
-}
-
-/**
- * do_compare - compare to ID lists and see if they match
- * @type: the type of list (UID or GID)
- * @fs_list: the list derived from scaning the FS
- * @qf_list: the list derived from reading the quota file
- *
- * Returns: TRUE if there was a mismatch
- */
-
-static int
-do_compare(const char *type, osi_list_t *fs_list, osi_list_t *qf_list)
-{
- osi_list_t *tmp1, *tmp2;
- values_t *v1, *v2;
- int found;
- int mismatch = FALSE;
-
- for (tmp1 = fs_list->next; tmp1 != fs_list; tmp1 = tmp1->next) {
- v1 = osi_list_entry(tmp1, values_t, v_list);
-
- found = FALSE;
-
- for (tmp2 = qf_list->next; tmp2 != qf_list; tmp2 = tmp2->next) {
- v2 = osi_list_entry(tmp2, values_t, v_list);
- if (v1->v_id != v2->v_id)
- continue;
-
- if (v1->v_blocks != v2->v_blocks) {
- printf("mismatch: %s %u: scan = %"PRId64", quotafile = %"PRId64"\n",
- type, v1->v_id,
- v1->v_blocks, v2->v_blocks);
- mismatch = TRUE;
- }
-
- osi_list_del(&v2->v_list);
- free(v2);
-
- found = TRUE;
- break;
- }
-
- if (!found) {
- printf("mismatch: %s %u: scan = %"PRId64", quotafile = %"PRId64"\n",
- type, v1->v_id,
- v1->v_blocks, (int64_t)0);
- mismatch = TRUE;
- }
- }
-
- for (tmp2 = qf_list->next; tmp2 != qf_list; tmp2 = tmp2->next) {
- v2 = osi_list_entry(tmp2, values_t, v_list);
-
- printf("mismatch: %s %u: scan = %"PRId64", quotafile = %"PRId64"\n",
- type, v2->v_id,
- (int64_t)0, v2->v_blocks);
- mismatch = TRUE;
- }
-
- return mismatch;
-}
-
-/**
- * verify_pathname - make sure the path on the command line is a mount point
- * @comline: the command line arguments
- *
- * Returns: the device the filesystem is on
- */
-
-static dev_t
-verify_pathname(commandline_t *comline)
-{
- struct stat st1, st2;
- dev_t device;
- char *name;
- int error;
-
- if (!*comline->filesystem)
- die("need a filesystem to work on\n");
-
- error = lstat(comline->filesystem, &st1);
- if (error)
- die("can't stat %s: %s\n", comline->filesystem,
- strerror(errno));
-
- if (!S_ISDIR(st1.st_mode))
- die("%s must be a directory\n", comline->filesystem);
-
- device = st1.st_dev;
-
- for (;;) {
- type_alloc(name, char, strlen(comline->filesystem) + 4);
- sprintf(name, "%s/..", comline->filesystem);
-
- error = lstat(name, &st2);
- if (error)
- die("can't stat %s: %s\n", name, strerror(errno));
-
- if (st2.st_dev != device || st2.st_ino == st1.st_ino) {
- free(name);
- break;
- }
-
- if (!realpath(name, comline->filesystem))
- die("error resolving filesystem pathname: %s\n",
- strerror(errno));
-
- free(name);
-
- st1 = st2;
- }
-
- return device;
-}
-
-/**
- * do_check - Check what's in the quota file
- * @comline: the struct containing the parsed command line arguments
- *
- */
-
-void
-do_check(struct gfs2_sbd *sdp, commandline_t *comline)
-{
- dev_t device;
- osi_list_t fs_uid, fs_gid, qf_uid, qf_gid;
- osi_list_t hl;
- int mismatch;
-
- osi_list_init(&fs_uid);
- osi_list_init(&fs_gid);
- osi_list_init(&qf_uid);
- osi_list_init(&qf_gid);
- osi_list_init(&hl);
-
- device = verify_pathname(comline);
-
- scan_fs(device, comline->filesystem, &fs_uid, &fs_gid, &hl);
- read_quota_file(sdp, comline, &qf_uid, &qf_gid);
-
- mismatch = do_compare("user", &fs_uid, &qf_uid);
- mismatch |= do_compare("group", &fs_gid, &qf_gid);
-
- if (mismatch)
- exit(EXIT_FAILURE);
-}
-
-/**
- * set_list - write a list of IDs into the quota file
- * @comline: the command line arguments
- * @user: TRUE if this is a list of UIDs, FALSE if it is a list of GIDs
- * @list: the list of IDs and block counts
- * @multiplier: multiply block counts by this
- *
- */
-
-static void
-set_list(struct gfs2_sbd *sdp, commandline_t *comline, int user,
- osi_list_t *list, int64_t multiplier)
-{
- int fd;
- osi_list_t *tmp;
- values_t *v;
- uint64_t offset, max_off = 0;
- int64_t value;
- int error;
- char quota_file[BUF_SIZE];
- char id_str[16];
- char *fs;
- struct stat st;
-
- strcpy(sdp->path_name, comline->filesystem);
- if (check_for_gfs2(sdp)) {
- if (errno == EINVAL)
- fprintf(stderr, "Not a valid GFS2 mount point: %s\n",
- sdp->path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
- read_superblock(&sdp->sd_sb, sdp);
- if (mount_gfs2_meta(sdp)) {
- fprintf(stderr, "Error mounting GFS2 metafs: %s\n",
- strerror(errno));
- exit(-1);
- }
-
- strcpy(quota_file, sdp->metafs_path);
- strcat(quota_file, "/quota");
-
- fd = open(quota_file, O_WRONLY);
- if (fd < 0) {
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
- die("can't open file %s: %s\n", comline->filesystem,
- strerror(errno));
- }
-
- for (tmp = list->next; tmp != list; tmp = tmp->next) {
- v = osi_list_entry(tmp, values_t, v_list);
-
- offset = (2 * (uint64_t)v->v_id + ((user) ? 0 : 1)) *
- sizeof(struct gfs2_quota);
- if (offset > max_off)
- max_off = offset;
- offset += (unsigned long)(&((struct gfs2_quota *)NULL)->qu_value);
-
- value = v->v_blocks * multiplier;
- value >>= sdp->sd_sb.sb_bsize_shift - 9;
- value = cpu_to_be64(value);
-
- lseek(fd, offset, SEEK_SET);
- error = write(fd, (char*)&value, sizeof(uint64_t));
- if (error != sizeof(uint64_t)) {
- fprintf(stderr, "can't write quota file (%d): %s\n",
- error, strerror(errno));
- goto out;
- }
-
- fs = mp2fsname(comline->filesystem);
- if (!fs) {
- fprintf(stderr, "Couldn't find GFS2 filesystem mounted at %s\n",
- comline->filesystem);
- exit(-1);
- }
-
- /* Write the id to sysfs quota refresh file to refresh gfs quotas */
- sprintf(id_str, "%d", comline->id);
- if (set_sysfs(fs, (user) ? "quota_refresh_user" : "quota_refresh_group",
- id_str)) {
- fprintf(stderr, "Error writing id to sysfs quota refresh file: %s\n",
- strerror(errno));
- exit(-1);
- }
- }
- /* If we wrote a value that extended the quota file size,
- * round the size off to the nearest quota boundary
- */
- error = fstat(fd, &st);
- if (error) {
- fprintf(stderr, "can't stat quota file (%d): %s\n",
- error, strerror(errno));
- goto out;
- }
- if (st.st_size < (max_off + sizeof(struct gfs2_quota))) {
- error = ftruncate(fd, (max_off + sizeof(struct gfs2_quota)));
- if (error)
- fprintf(stderr, "can't truncate quota file(%d): %s\n",
- error, strerror(errno));
- }
-out:
- close(fd);
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
-}
-
-/**
- * do_quota_init - initialize the quota file
- * @comline: the command line arguments
- *
- */
-
-void
-do_quota_init(struct gfs2_sbd *sdp, commandline_t *comline)
-{
- dev_t device;
- osi_list_t fs_uid, fs_gid, qf_uid, qf_gid;
- osi_list_t hl;
- values_t *v;
-
- osi_list_init(&fs_uid);
- osi_list_init(&fs_gid);
- osi_list_init(&qf_uid);
- osi_list_init(&qf_gid);
- osi_list_init(&hl);
-
- device = verify_pathname(comline);
-
- scan_fs(device, comline->filesystem, &fs_uid, &fs_gid, &hl);
- read_quota_file(sdp, comline, &qf_uid, &qf_gid);
-
- type_zalloc(v, values_t, 1);
- v->v_id = 0;
- v->v_blocks = 0;
- osi_list_add(&v->v_list, &qf_uid);
-
- type_zalloc(v, values_t, 1);
- v->v_id = 0;
- v->v_blocks = 0;
- osi_list_add(&v->v_list, &qf_gid);
-
- set_list(sdp, comline, TRUE, &qf_uid, 0);
- set_list(sdp, comline, FALSE, &qf_gid, 0);
- set_list(sdp, comline, TRUE, &fs_uid, 1);
- set_list(sdp, comline, FALSE, &fs_gid, 1);
-
- do_sync(sdp, comline);
- do_check(sdp, comline);
-}
diff --git a/gfs2/quota/gfs2_quota.h b/gfs2/quota/gfs2_quota.h
deleted file mode 100644
index 80c0d3f..0000000
--- a/gfs2/quota/gfs2_quota.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#ifndef __GFS2_QUOTA_DOT_H__
-#define __GFS2_QUOTA_DOT_H__
-
-#include "libgfs2.h"
-#include <linux/gfs2_ondisk.h>
-
-#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
-
-#define type_zalloc(ptr, type, count) \
-do { \
- (ptr) = (type *)malloc(sizeof(type) * (count)); \
- if ((ptr)) \
- memset((char *)(ptr), 0, sizeof(type) * (count)); \
- else \
- die("unable to allocate memory on line %d of file %s\n", \
- __LINE__, __FILE__); \
-} while (0)
-
-#define type_alloc(ptr, type, count) \
-do { \
- (ptr) = (type *)malloc(sizeof(type) * (count)); \
- if (!(ptr)) \
- die("unable to allocate memory on line %d of file %s\n", \
- __LINE__, __FILE__); \
-} while (0)
-
-#define GQ_OP_LIST (12)
-#define GQ_OP_SYNC (13)
-#define GQ_OP_GET (14)
-#define GQ_OP_LIMIT (15)
-#define GQ_OP_WARN (16)
-#define GQ_OP_CHECK (17)
-#define GQ_OP_INIT (18)
-#define GQ_OP_RESET (19)
-
-#define GQ_ID_USER (23)
-#define GQ_ID_GROUP (24)
-
-#define GQ_UNITS_MEGABYTE (0)
-#define GQ_UNITS_KILOBYTE (34)
-#define GQ_UNITS_FSBLOCK (35)
-#define GQ_UNITS_BASICBLOCK (36)
-
-#define BUF_SIZE 4096
-
-struct commandline {
- unsigned int operation;
-
- uint64_t new_value;
- int new_value_set;
-
- unsigned int id_type;
- uint32_t id;
-
- unsigned int units;
-
- int numbers;
-
- char filesystem[PATH_MAX];
-};
-typedef struct commandline commandline_t;
-
-/* main.c */
-
-void do_get_super(int fd, struct gfs2_sb *sb);
-void do_sync(struct gfs2_sbd *sdp, commandline_t *comline);
-void cleanup(void);
-void read_superblock(struct gfs2_sb *sb, struct gfs2_sbd *sdp);
-void read_quota_internal(int fd, unsigned int id, int id_type,
- struct gfs2_quota *q);
-
-/* check.c */
-
-void do_check(struct gfs2_sbd *sdp, commandline_t *comline);
-void do_quota_init(struct gfs2_sbd *sdp, commandline_t *comline);
-
-/* names.c */
-
-uint32_t name_to_id(int user, char *name, int numbers);
-char *id_to_name(int user, uint32_t id, int numbers);
-
-#endif /* __GFS2_QUOTA_DOT_H__ */
diff --git a/gfs2/quota/main.c b/gfs2/quota/main.c
deleted file mode 100644
index 0625b7d..0000000
--- a/gfs2/quota/main.c
+++ /dev/null
@@ -1,909 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <time.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/mount.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-#include <linux/types.h>
-#include <linux/fiemap.h>
-#include "gfs2_quota.h"
-
-#define __user
-
-#include "copyright.cf"
-
-
-/* Constants */
-
-#define OPTION_STRING ("bdf:g:hkl:mnsu:V")
-#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap)
-
-/**
- * This function is for libgfs2's sake.
- */
-void print_it(const char *label, const char *fmt, const char *fmt2, ...)
-{
- va_list args;
-
- va_start(args, fmt2);
- printf("%s: ", label);
- vprintf(fmt, args);
- va_end(args);
-}
-
-/**
- * print_usage - print usage info to the user
- * @prog_name: The name of this program
- */
-
-static void
-print_usage(const char *prog_name)
-{
- printf("Usage:\n");
- printf("\n");
- printf("%s <list|sync|get|limit|warn|check|init> [options]\n",
- prog_name);
- printf("\n");
- printf("Actions:\n");
- printf(" list list the whole quota file\n");
- printf(" sync sync out unsynced quotas\n");
- printf(" get get quota values for an ID\n");
- printf(" limit set a quota limit value for an ID\n");
- printf(" warn set a quota warning value for an ID\n");
- printf(" check check the quota file\n");
- printf(" init initialize the quota file\n");
- printf(" reset reset the quota file\n");
- printf("\n");
- printf("Options:\n");
- printf(" -b sizes are in FS blocks\n");
- printf(" -f <directory> the filesystem to work on\n");
- printf(" -g <gid> get/set a group ID\n");
- printf(" -h Print this help, then exit\n");
- printf(" -k sizes are in KB\n");
- printf(" -l <size> the new limit or warn value\n");
- printf(" -m sizes are in MB\n");
- printf(" -n print out UID/GID numbers instead of names\n");
- printf(" -s sizes are in 512-byte blocks\n");
- printf(" -u <uid> get/set a user ID\n");
- printf(" -V Print program version information, then exit\n");
-}
-
-/**
- * decode_arguments - parse command line arguments
- * @argc: well, it's argc...
- * @argv: well, it's argv...
- * @comline: the structure filled in with the parsed arguments
- *
- * Function description
- *
- * Returns: what is returned
- */
-
-static void
-decode_arguments(int argc, char *argv[], commandline_t *comline)
-{
- int cont = TRUE;
- int optchar;
-
- while (cont) {
- optchar = getopt(argc, argv, OPTION_STRING);
-
- switch (optchar) {
- case 'u':
- comline->id_type = GQ_ID_USER;
- comline->id = name_to_id(TRUE, optarg, comline->numbers);
- break;
-
- case 'g':
- comline->id_type = GQ_ID_GROUP;
- comline->id = name_to_id(FALSE, optarg, comline->numbers);
- break;
-
- case 'l':
- if (!isdigit(*optarg))
- die("argument to -l must be a number\n");
- sscanf(optarg, "%"SCNu64, &comline->new_value);
- comline->new_value_set = TRUE;
- break;
-
- case 'f':
- if (!realpath(optarg, comline->filesystem))
- die("can't find %s: %s\n", optarg,
- strerror(errno));
- break;
-
- case 'm':
- comline->units = GQ_UNITS_MEGABYTE;
- break;
-
- case 'k':
- comline->units = GQ_UNITS_KILOBYTE;
- break;
-
- case 'b':
- comline->units = GQ_UNITS_FSBLOCK;
- break;
-
- case 's':
- comline->units = GQ_UNITS_BASICBLOCK;
- break;
-
- case 'n':
- comline->numbers = TRUE;
- break;
-
- case 'V':
- printf("gfs2_quota %s (built %s %s)\n", RELEASE_VERSION,
- __DATE__, __TIME__);
- printf("%s\n", REDHAT_COPYRIGHT);
- exit(EXIT_SUCCESS);
- break;
-
- case 'h':
- print_usage(argv[0]);
- exit(EXIT_SUCCESS);
- break;
-
- case ':':
- case '?':
- fprintf(stderr, "Please use '-h' for usage.\n");
- exit(EXIT_FAILURE);
- break;
-
- case EOF:
- cont = FALSE;
- break;
-
- default:
- die("unknown option: %c\n", optchar);
- break;
- };
- }
-
- while (optind < argc) {
- if (strcmp(argv[optind], "list") == 0 ||
- strcmp(argv[optind], "dump") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_LIST;
- } else if (strcmp(argv[optind], "sync") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_SYNC;
- } else if (strcmp(argv[optind], "get") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_GET;
- } else if (strcmp(argv[optind], "limit") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_LIMIT;
- } else if (strcmp(argv[optind], "warn") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_WARN;
- } else if (strcmp(argv[optind], "check") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_CHECK;
- } else if (strcmp(argv[optind], "init") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_INIT;
- } else if (strcmp(argv[optind], "reset") == 0) {
- if (comline->operation)
- die("can't specify two operations\n");
- comline->operation = GQ_OP_RESET;
- } else
- die("unknown option %s\n", argv[optind]);
-
- optind++;
- }
-}
-
-/**
- * print_quota - Print out a quota entry
- * @comline: the struct containing the parsed command line arguments
- * @user: TRUE if this is a user quota, FALSE if it's a group quota
- * @id: the ID
- * @q: the quota value
- * @sb: the superblock of the filesystem this quota belongs to
- *
- */
-
-static void
-print_quota(commandline_t *comline,
- int user, uint32_t id,
- struct gfs2_quota *q,
- struct gfs2_sb *sb)
-{
- printf("%-5s %10s: ", (user) ? "user" : "group",
- id_to_name(user, id, comline->numbers));
-
- switch (comline->units) {
- case GQ_UNITS_MEGABYTE:
- printf("limit: %-10.1f warn: %-10.1f value: %-10.1f\n",
- (double) q->qu_limit * sb->sb_bsize / 1048576,
- (double) q->qu_warn * sb->sb_bsize / 1048576,
- (double) q->qu_value * sb->sb_bsize / 1048576);
- break;
-
- case GQ_UNITS_KILOBYTE:
- if (sb->sb_bsize == 512)
- printf("limit: %-10llu warn: %-10lluvalue: %-10llu\n",
- (unsigned long long)q->qu_limit / 2,
- (unsigned long long)q->qu_warn / 2,
- (unsigned long long)q->qu_value / 2);
- else
- printf("limit: %-10llu warn: %-10lluvalue: %-10llu\n",
- (unsigned long long)
- q->qu_limit << (sb->sb_bsize_shift - 10),
- (unsigned long long)
- q->qu_warn << (sb->sb_bsize_shift - 10),
- (unsigned long long)
- q->qu_value << (sb->sb_bsize_shift - 10));
- break;
-
- case GQ_UNITS_FSBLOCK:
- printf("limit: %-10llu warn: %-10llu value: %-10llu\n",
- (unsigned long long)q->qu_limit,
- (unsigned long long)q->qu_warn,
- (unsigned long long)q->qu_value);
- break;
-
- case GQ_UNITS_BASICBLOCK:
- printf("limit: %-10llu warn: %-10llu value: %-10llu\n",
- (unsigned long long)
- q->qu_limit << (sb->sb_bsize_shift - 9),
- (unsigned long long)
- q->qu_warn << (sb->sb_bsize_shift - 9),
- (unsigned long long)
- q->qu_value << (sb->sb_bsize_shift - 9));
- break;
-
- default:
- die("bad units\n");
- break;
- }
-}
-
-void
-read_superblock(struct gfs2_sb *sb, struct gfs2_sbd *sdp)
-{
- int fd;
- char buf[PATH_MAX];
- struct gfs2_buffer_head dummy_bh;
-
- dummy_bh.b_data = buf;
- fd = open(sdp->device_name, O_RDONLY);
- if (fd < 0) {
- die("Could not open the block device %s: %s\n",
- sdp->device_name, strerror(errno));
- }
- if (lseek(fd, 0x10 * 4096, SEEK_SET) != 0x10 * 4096) {
- fprintf(stderr, "bad seek: %s from %s:%d: "
- "superblock\n",
- strerror(errno), __FUNCTION__, __LINE__);
-
- exit(-1);
- }
- if (read(fd, buf, PATH_MAX) != PATH_MAX) {
- fprintf(stderr, "bad read: %s from %s:%d: superblock\n",
- strerror(errno), __FUNCTION__, __LINE__);
- exit(-1);
- }
- gfs2_sb_in(sb, &dummy_bh);
-
- close(fd);
-}
-
-void
-read_quota_internal(int fd, uint32_t id, int id_type, struct gfs2_quota *q)
-{
- /* seek to the appropriate offset in the quota file and read the
- quota info */
- uint64_t offset;
- char buf[256];
- int error;
- if (id_type == GQ_ID_USER)
- offset = (2 * (uint64_t)id) * sizeof(struct gfs2_quota);
- else
- offset = (2 * (uint64_t)id + 1) * sizeof(struct gfs2_quota);
- lseek(fd, offset, SEEK_SET);
- error = read(fd, buf, sizeof(struct gfs2_quota));
- if (error < 0)
- die("failed to read from quota file: %s\n", strerror(errno));
- if (error != sizeof(struct gfs2_quota))
- die("Couldn't read %lu bytes from quota file at offset %llu\n",
- (unsigned long)sizeof(struct gfs2_quota),
- (unsigned long long)offset);
- gfs2_quota_in(q, buf);
-}
-
-static inline void
-write_quota_internal(int fd, uint32_t id, int id_type, struct gfs2_quota *q)
-{
- /* seek to the appropriate offset in the quota file and write the
- quota info */
- uint64_t offset;
- char buf[256];
- int error;
- if (id_type == GQ_ID_USER)
- offset = (2 * (uint64_t)id) * sizeof(struct gfs2_quota);
- else
- offset = (2 * (uint64_t)id + 1) * sizeof(struct gfs2_quota);
- lseek(fd, offset, SEEK_SET);
- gfs2_quota_out(q, buf);
- error = write(fd, buf, sizeof(struct gfs2_quota));
- if (error != sizeof(struct gfs2_quota))
- die("failed to write to quota file: %s\n", strerror(errno));
-}
-
-/**
- * do_reset - Reset all the quota data for a filesystem
- * @comline: the struct containing the parsed command line arguments
- */
-
-static void
-do_reset(struct gfs2_sbd *sdp, commandline_t *comline)
-{
- int fd;
- char quota_file[BUF_SIZE], c;
- struct gfs2_quota q;
-
- if (!*comline->filesystem)
- die("need a filesystem to work on\n");
-
- printf("This operation will permanently erase all quota information.\n"
- "You will have to re-assign all quota limit/warn values.\n"
- "Proceed [y/N]? ");
- c = getchar();
- if (c != 'y' && c != 'Y')
- return;
-
- strcpy(sdp->path_name, comline->filesystem);
- if (check_for_gfs2(sdp)) {
- if (errno == EINVAL)
- fprintf(stderr, "Not a valid GFS2 mount point: %s\n",
- sdp->path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
- read_superblock(&sdp->sd_sb, sdp);
- if (mount_gfs2_meta(sdp)) {
- fprintf(stderr, "Error mounting GFS2 metafs: %s\n",
- strerror(errno));
- exit(-1);
- }
-
- strcpy(quota_file, sdp->metafs_path);
- strcat(quota_file, "/quota");
-
- fd = open(quota_file, O_RDWR);
- if (fd < 0) {
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
- die("can't open file %s: %s\n", quota_file,
- strerror(errno));
- }
-
- read_quota_internal(fd, 0, GQ_ID_USER, &q);
- write_quota_internal(fd, 0, GQ_ID_USER, &q);
-
- read_quota_internal(fd, 0, GQ_ID_GROUP, &q);
- write_quota_internal(fd, 0, GQ_ID_GROUP, &q);
-
- /* truncate the quota file such that only the first
- * two quotas(uid=0 and gid=0) remain.
- */
- if (ftruncate(fd, (sizeof(struct gfs2_quota)) * 2))
- die("couldn't truncate quota file %s\n", strerror(errno));
-
- close(fd);
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
-}
-
-/**
- * do_list - List all the quota data for a filesystem
- * @comline: the struct containing the parsed command line arguments
- *
- */
-
-static void
-do_list(struct gfs2_sbd *sdp, commandline_t *comline)
-{
- int fd;
- struct gfs2_quota q;
- char buf[sizeof(struct gfs2_quota)];
- uint64_t offset;
- uint32_t id, startid;
- int pass = 0;
- int error = 0;
- char quota_file[BUF_SIZE];
- uint64_t quota_file_size = 0;
- struct fiemap fmap = { 0, }, *fmap2;
- struct stat statbuf;
-
- if (!*comline->filesystem)
- die("need a filesystem to work on\n");
-
- strcpy(sdp->path_name, comline->filesystem);
- if (check_for_gfs2(sdp)) {
- if (errno == EINVAL)
- fprintf(stderr, "Not a valid GFS2 mount point: %s\n",
- sdp->path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
- read_superblock(&sdp->sd_sb, sdp);
- if (mount_gfs2_meta(sdp)) {
- fprintf(stderr, "Error mounting GFS2 metafs: %s\n",
- strerror(errno));
- exit(-1);
- }
-
- strcpy(quota_file, sdp->metafs_path);
- strcat(quota_file, "/quota");
-
- fd = open(quota_file, O_RDONLY);
- if (fd < 0) {
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
- die("can't open file %s: %s\n", quota_file,
- strerror(errno));
- }
- if (fstat(fd, &statbuf) < 0) {
- close(fd);
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
- die("can't stat file %s: %s\n", quota_file,
- strerror(errno));
- }
- quota_file_size = statbuf.st_size;
- /* First find the number of extents in the quota file */
- fmap.fm_flags = 0;
- fmap.fm_start = 0;
- fmap.fm_length = (~0ULL);
- error = ioctl(fd, FS_IOC_FIEMAP, &fmap);
- if (error == -1) {
- fprintf(stderr, "fiemap error (%d): %s\n", errno, strerror(errno));
- goto out;
- }
- fmap2 = malloc(sizeof(struct fiemap) +
- fmap.fm_mapped_extents * sizeof(struct fiemap_extent));
- if (fmap2 == NULL) {
- fprintf(stderr, "malloc error (%d): %s\n", errno, strerror(errno));
- goto out;
- }
- fmap2->fm_flags = 0;
- fmap2->fm_start = 0;
- fmap2->fm_length = (~0ULL);
- fmap2->fm_extent_count = fmap.fm_mapped_extents;
-
- error = ioctl(fd, FS_IOC_FIEMAP, fmap2);
- if (error == -1) {
- fprintf(stderr, "fiemap error (%d): %s\n", errno, strerror(errno));
- goto fmap2_free;
- }
- if (fmap2->fm_mapped_extents) {
- int i;
- again:
- for (i=0; i<fmap2->fm_mapped_extents; i++) {
- struct fiemap_extent *fe = &fmap2->fm_extents[i];
- uint64_t end = fe->fe_logical + fe->fe_length;
-
- end = end > quota_file_size ? quota_file_size : end;
- startid = DIV_RU(fe->fe_logical, sizeof(struct gfs2_quota));
- if (startid % 2 != pass)
- startid++;
- offset = startid * sizeof(struct gfs2_quota);
- do {
- memset(buf, 0, sizeof(struct gfs2_quota));
- /* read hidden quota file here */
- lseek(fd, offset, SEEK_SET);
- error = read(fd, buf, sizeof(struct gfs2_quota));
- if (error < 0) {
- fprintf(stderr, "read error (%d): %s\n",
- errno, strerror(errno));
- goto fmap2_free;
- }
- gfs2_quota_in(&q, buf);
- id = (offset / sizeof(struct gfs2_quota)) >> 1;
- if (q.qu_limit || q.qu_warn || q.qu_value)
- print_quota(comline, (pass) ? FALSE : TRUE, id,
- &q, &sdp->sd_sb);
- offset += 2 * sizeof(struct gfs2_quota);
- } while (offset < end);
- }
- if (!pass) {
- pass = 1;
- goto again;
- }
- }
-
-fmap2_free:
- free(fmap2);
-out:
- close(fd);
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
-}
-
-/**
- * do_get_one - Get a quota value from one FS
- * @comline: the struct containing the parsed command line arguments
- * @filesystem: the filesystem to get from
- *
- */
-
-static void
-do_get_one(struct gfs2_sbd *sdp, commandline_t *comline, char *filesystem)
-{
- int fd;
- char buf[256];
- struct gfs2_quota q;
- uint64_t offset;
- int error;
- char quota_file[BUF_SIZE];
-
- strcpy(sdp->path_name, filesystem);
- if (check_for_gfs2(sdp)) {
- if (errno == EINVAL)
- fprintf(stderr, "Not a valid GFS2 mount point: %s\n",
- sdp->path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
- read_superblock(&sdp->sd_sb, sdp);
- if (mount_gfs2_meta(sdp)) {
- fprintf(stderr, "Error mounting GFS2 metafs: %s\n",
- strerror(errno));
- exit(-1);
- }
-
- strcpy(quota_file, sdp->metafs_path);
- strcat(quota_file, "/quota");
-
- fd = open(quota_file, O_RDONLY);
- if (fd < 0) {
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
- die("can't open file %s: %s\n", quota_file,
- strerror(errno));
- }
-
- if (comline->id_type == GQ_ID_USER)
- offset = (2 * (uint64_t)comline->id) * sizeof(struct gfs2_quota);
- else
- offset = (2 * (uint64_t)comline->id + 1) * sizeof(struct gfs2_quota);
-
- memset(&q, 0, sizeof(struct gfs2_quota));
-
- lseek(fd, offset, SEEK_SET);
- error = read(fd, buf, sizeof(struct gfs2_quota));
- if (error < 0) {
- close(fd);
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
- die("can't get quota info (%d): %s\n",
- error, strerror(errno));
- }
-
- gfs2_quota_in(&q, buf);
- print_quota(comline,
- (comline->id_type == GQ_ID_USER), comline->id,
- &q, &sdp->sd_sb);
-
- close(fd);
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
-}
-
-/**
- * do_get - Get a quota value
- * @comline: the struct containing the parsed command line arguments
- *
- */
-
-static void
-do_get(struct gfs2_sbd *sdp, commandline_t *comline)
-{
- int first = TRUE;
-
- if (*comline->filesystem)
- do_get_one(sdp, comline, comline->filesystem);
- else {
- char buf[256], device[256], path[256], type[256];
- FILE *file;
-
- file = fopen("/proc/mounts", "r");
- if (!file)
- die("can't open /proc/mounts: %s\n", strerror(errno));
-
- while (fgets(buf, 256, file)) {
- if (sscanf(buf, "%s %s %s", device, path, type) != 3)
- continue;
- if (strcmp(type, "gfs2") != 0)
- continue;
-
- if (first)
- first = FALSE;
- else
- printf("\n");
-
- printf("%s\n", path);
- do_get_one(sdp, comline, path);
- }
-
- fclose(file);
- }
-}
-
-/**
- * do_sync_one - sync the quotas on one GFS2 filesystem
- * @path: a file/directory in the filesystem
- *
- */
-static void
-do_sync_one(struct gfs2_sbd *sdp, char *filesystem)
-{
- char *fsname;
-
- fsname = mp2fsname(filesystem);
- if (!fsname) {
- fprintf(stderr, "Couldn't find GFS2 filesystem mounted at %s\n",
- filesystem);
- exit(-1);
- }
- if (set_sysfs(fsname, "quota_sync", "1")) {
- fprintf(stderr, "Error writing to sysfs quota sync file: %s\n",
- strerror(errno));
- exit(-1);
- }
-}
-
-/**
- * do_sync - sync out unsyned quotas
- * @comline: the struct containing the parsed command line arguments
- *
- */
-
-void
-do_sync(struct gfs2_sbd *sdp, commandline_t *comline)
-{
- sync();
-
- if (*comline->filesystem)
- do_sync_one(sdp, comline->filesystem);
- else {
- char buf[256], device[256], path[256], type[256];
- FILE *file;
-
- file = fopen("/proc/mounts", "r");
- if (!file)
- die("can't open /proc/mounts: %s\n", strerror(errno));
-
- while (fgets(buf, 256, file)) {
- if (sscanf(buf, "%s %s %s", device, path, type) != 3)
- continue;
- if (strcmp(type, "gfs2") != 0)
- continue;
-
- do_sync_one(sdp, path);
- }
-
- fclose(file);
- }
-}
-
-/**
- * do_set - Set a quota value
- * @comline: the struct containing the parsed command line arguments
- *
- */
-
-static void
-do_set(struct gfs2_sbd *sdp, commandline_t *comline)
-{
- int fd;
- uint64_t offset;
- uint64_t new_value;
- char quota_file[BUF_SIZE];
- char id_str[16];
- struct stat stat_buf;
- struct gfs2_quota q;
- char *fs;
-
- if (!*comline->filesystem)
- die("need a filesystem to work on\n");
- if (!comline->new_value_set)
- die("need a new value\n");
-
- strcpy(sdp->path_name, comline->filesystem);
- if (check_for_gfs2(sdp)) {
- if (errno == EINVAL)
- fprintf(stderr, "Not a valid GFS2 mount point: %s\n",
- sdp->path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
- read_superblock(&sdp->sd_sb, sdp);
- if (mount_gfs2_meta(sdp)) {
- fprintf(stderr, "Error mounting GFS2 metafs: %s\n",
- strerror(errno));
- exit(-1);
- }
-
- strcpy(quota_file, sdp->metafs_path);
- strcat(quota_file, "/quota");
-
- fd = open(quota_file, O_RDWR);
- if (fd < 0) {
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
- die("can't open file %s: %s\n", quota_file,
- strerror(errno));
- }
-
- switch (comline->id_type) {
- case GQ_ID_USER:
- offset = (2 * (uint64_t)comline->id) * sizeof(struct gfs2_quota);
- break;
-
- case GQ_ID_GROUP:
- offset = (2 * (uint64_t)comline->id + 1) * sizeof(struct gfs2_quota);
- break;
-
- default:
- fprintf(stderr, "invalid user/group ID\n");
- goto out;
- }
-
- switch (comline->units) {
- case GQ_UNITS_MEGABYTE:
- new_value =
- comline->new_value << (20 - sdp->sd_sb.sb_bsize_shift);
- break;
-
- case GQ_UNITS_KILOBYTE:
- if (sdp->sd_sb.sb_bsize == 512)
- new_value = comline->new_value * 2;
- else
- new_value = comline->new_value >>
- (sdp->sd_sb.sb_bsize_shift - 10);
- break;
-
- case GQ_UNITS_FSBLOCK:
- new_value = comline->new_value;
- break;
-
- case GQ_UNITS_BASICBLOCK:
- new_value = comline->new_value >>
- (sdp->sd_sb.sb_bsize_shift - 9);
- break;
-
- default:
- fprintf(stderr, "bad units\n");
- goto out;
- }
-
- memset(&q, 0, sizeof(struct gfs2_quota));
- if (fstat(fd, &stat_buf)) {
- fprintf(stderr, "stat failed: %s\n", strerror(errno));
- goto out;
- }
- if (stat_buf.st_size >= (offset + sizeof(struct gfs2_quota)))
- read_quota_internal(fd, comline->id, comline->id_type, &q);
-
- switch (comline->operation) {
- case GQ_OP_LIMIT:
- q.qu_limit = new_value; break;
- case GQ_OP_WARN:
- q.qu_warn = new_value; break;
- }
-
- write_quota_internal(fd, comline->id, comline->id_type, &q);
- fs = mp2fsname(comline->filesystem);
- if (!fs) {
- fprintf(stderr, "Couldn't find GFS2 filesystem mounted at %s\n",
- comline->filesystem);
- exit(-1);
- }
- sprintf(id_str, "%d", comline->id);
- if (set_sysfs(fs, comline->id_type == GQ_ID_USER ?
- "quota_refresh_user" : "quota_refresh_group", id_str)) {
- fprintf(stderr, "Error writing to sysfs quota refresh file: %s\n",
- strerror(errno));
- exit(-1);
- }
-
-out:
- close(fd);
- close(sdp->metafs_fd);
- cleanup_metafs(sdp);
-}
-
-/**
- * main - Do everything
- * @argc: well, it's argc...
- * @argv: well, it's argv...
- *
- * Returns: exit status
- */
-
-int
-main(int argc, char *argv[])
-{
- struct gfs2_sbd sbd, *sdp = &sbd;
- commandline_t comline;
-
- memset(sdp, 0, sizeof(struct gfs2_sbd));
- memset(&comline, 0, sizeof(commandline_t));
-
- decode_arguments(argc, argv, &comline);
- sdp->path_name = (char*) malloc(512);
- if (!sdp->path_name)
- die("Can't malloc! %s\n", strerror(errno));
-
- switch (comline.operation) {
- case GQ_OP_LIST:
- do_list(sdp, &comline);
- break;
-
- case GQ_OP_GET:
- do_get(sdp, &comline);
- break;
-
- case GQ_OP_LIMIT:
- case GQ_OP_WARN:
- do_set(sdp, &comline);
- break;
-
- case GQ_OP_SYNC:
- do_sync(sdp, &comline);
- break;
-
- case GQ_OP_CHECK:
- do_sync(sdp, &comline);
- do_check(sdp, &comline);
- break;
-
- case GQ_OP_INIT:
- do_sync(sdp, &comline);
- do_quota_init(sdp, &comline);
- break;
-
- case GQ_OP_RESET:
- do_reset(sdp, &comline);
- break;
- default:
- if (!comline.id_type) {
- comline.id_type = GQ_ID_USER;
- comline.id = geteuid();
- }
- do_get(sdp, &comline);
- break;
- }
-
- free(sdp->path_name);
-
- exit(EXIT_SUCCESS);
-}
diff --git a/gfs2/quota/names.c b/gfs2/quota/names.c
deleted file mode 100644
index fd3c589..0000000
--- a/gfs2/quota/names.c
+++ /dev/null
@@ -1,81 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <time.h>
-#include <dirent.h>
-#include <limits.h>
-#include <pwd.h>
-#include <grp.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include "gfs2_quota.h"
-
-uint32_t
-name_to_id(int user, char *name, int numbers)
-{
- struct passwd *u;
- struct group *g;
- uint32_t id;
- int ok = FALSE;
-
- if (numbers) {
- } else if (user) {
- u = getpwnam(name);
- if (u) {
- id = u->pw_uid;
- ok = TRUE;
- }
- } else {
- g = getgrnam(name);
- if (g) {
- id = g->gr_gid;
- ok = TRUE;
- }
- }
-
- if (!ok) {
- if (!isdigit(name[0]))
- die("can't find %s %s\n",
- (user) ? "user" : "group",
- name);
- sscanf(name, "%u", &id);
- }
-
- return id;
-}
-
-char *
-id_to_name(int user, uint32_t id, int numbers)
-{
- struct passwd *u;
- struct group *g;
- static char name[256];
- int ok = FALSE;
-
- if (numbers) {
- } else if (user) {
- u = getpwuid(id);
- if (u) {
- strcpy(name, u->pw_name);
- ok = TRUE;
- }
- } else {
- g = getgrgid(id);
- if (g) {
- strcpy(name, g->gr_name);
- ok = TRUE;
- }
- }
-
- if (!ok)
- sprintf(name, "%u", id);
-
- return name;
-}
diff --git a/gfs2/tool/Makefile b/gfs2/tool/Makefile
deleted file mode 100644
index 11b8624..0000000
--- a/gfs2/tool/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-TARGET= gfs2_tool
-
-SBINDIRT=$(TARGET)
-
-all: depends ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= main.o \
- misc.o \
- ondisk.o \
- sb.o \
- tune.o
-
-CFLAGS += -D_FILE_OFFSET_BITS=64
-CFLAGS += -I${KERNEL_SRC}/fs/gfs2/ -I${KERNEL_SRC}/include/
-CFLAGS += -I$(S)/../include -I$(S)/../libgfs2
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L../libgfs2 -lgfs2
-LDFLAGS += -L${libdir}
-
-LDDEPS += ../libgfs2/libgfs2.a
-
-${TARGET}: ${OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-depends:
- $(MAKE) -C ../libgfs2 all
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/gfs2/tool/gfs2_tool.h b/gfs2/tool/gfs2_tool.h
deleted file mode 100644
index 884856f..0000000
--- a/gfs2/tool/gfs2_tool.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef __GFS2_TOOL_DOT_H__
-#define __GFS2_TOOL_DOT_H__
-
-
-#define OUTPUT_BLOCKS 0
-#define OUTPUT_K 1
-#define OUTPUT_HUMAN 2
-
-extern char *action;
-extern int override;
-extern int expert;
-extern int debug;
-extern int continuous;
-extern int interval;
-extern int output_type;
-
-/* From counters.c */
-
-void print_counters(int argc, char **argv);
-
-
-/* From main.c */
-
-void print_usage(void);
-
-
-/* From misc.c */
-
-void do_freeze(int argc, char **argv);
-void print_lockdump(int argc, char **argv);
-void set_flag(int argc, char **argv);
-void print_stat(int argc, char **argv);
-void print_sb(int argc, char **argv);
-void print_jindex(int argc, char **argv);
-void print_journals(int argc, char **argv);
-void print_rindex(int argc, char **argv);
-void print_quota(int argc, char **argv);
-void do_withdraw(int argc, char **argv);
-
-
-/* From sb.c */
-
-void do_sb(int argc, char **argv);
-
-
-/* From tune.c */
-
-void get_tune(int argc, char **argv);
-void set_tune(int argc, char **argv);
-
-#endif /* __GFS2_TOOL_DOT_H__ */
diff --git a/gfs2/tool/iflags.h b/gfs2/tool/iflags.h
deleted file mode 100644
index 2d6cf18..0000000
--- a/gfs2/tool/iflags.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef __IFLAGS_DOT_H__
-#define __IFLAGS_DOT_H__
-
-#define FS_IOC_GETFLAGS _IOR('f', 1, long)
-#define FS_IOC_SETFLAGS _IOW('f', 2, long)
-#define FS_IOC32_GETFLAGS _IOR('f', 1, int)
-#define FS_IOC32_SETFLAGS _IOW('f', 2, int)
-
-/*
- * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
- */
-#define FS_SECRM_FL 0x00000001 /* Secure deletion */
-#define FS_UNRM_FL 0x00000002 /* Undelete */
-#define FS_COMPR_FL 0x00000004 /* Compress file */
-#define FS_SYNC_FL 0x00000008 /* Synchronous updates */
-#define FS_IMMUTABLE_FL 0x00000010 /* Immutable file */
-#define FS_APPEND_FL 0x00000020 /* writes to file may only append */
-#define FS_NODUMP_FL 0x00000040 /* do not dump file */
-#define FS_NOATIME_FL 0x00000080 /* do not update atime */
-/* Reserved for compression usage... */
-#define FS_DIRTY_FL 0x00000100
-#define FS_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
-#define FS_NOCOMP_FL 0x00000400 /* Don't compress */
-#define FS_ECOMPR_FL 0x00000800 /* Compression error */
-/* End compression flags --- maybe not all used */
-#define FS_BTREE_FL 0x00001000 /* btree format dir */
-#define FS_INDEX_FL 0x00001000 /* hash-indexed directory */
-#define FS_IMAGIC_FL 0x00002000 /* AFS directory */
-#define FS_JOURNAL_DATA_FL 0x00004000 /* Reserved for ext3 */
-#define FS_NOTAIL_FL 0x00008000 /* file tail should not be merged */
-#define FS_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
-#define FS_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
-#define FS_EXTENT_FL 0x00080000 /* Extents */
-#define FS_DIRECTIO_FL 0x00100000 /* Use direct i/o */
-#define FS_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
-
-#define FS_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
-#define FS_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
-
-#endif /* __IFLAGS_DOT_H__ */
diff --git a/gfs2/tool/main.c b/gfs2/tool/main.c
deleted file mode 100644
index 5cad9da..0000000
--- a/gfs2/tool/main.c
+++ /dev/null
@@ -1,196 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-#include <linux/types.h>
-#include <libintl.h>
-#include <locale.h>
-#define _(String) gettext(String)
-
-#include "copyright.cf"
-
-#include "gfs2_tool.h"
-#include "libgfs2.h"
-
-char *action = NULL;
-int override = FALSE;
-int expert = FALSE;
-int debug = FALSE;
-int continuous = FALSE;
-int interval = 1;
-int output_type = OUTPUT_BLOCKS;
-
-static const char *usage = {
- "Clear a flag on a inode\n"
- " gfs2_tool clearflag flag <filenames>\n"
- "Freeze a GFS2 cluster:\n"
- " gfs2_tool freeze <mountpoint>\n"
- "Get tuneable parameters for a filesystem\n"
- " gfs2_tool gettune <mountpoint>\n"
- "List the file system's journals:\n"
- " gfs2_tool journals <mountpoint>\n"
- "Have GFS2 dump its lock state:\n"
- " gfs2_tool lockdump <mountpoint> [buffersize]\n"
- "Tune a GFS2 superblock\n"
- " gfs2_tool sb <device> proto [newval]\n"
- " gfs2_tool sb <device> table [newval]\n"
- " gfs2_tool sb <device> ondisk [newval]\n"
- " gfs2_tool sb <device> multihost [newval]\n"
- " gfs2_tool sb <device> all\n"
- "Set a flag on a inode\n"
- " gfs2_tool setflag flag <filenames>\n"
- "Tune a running filesystem\n"
- " gfs2_tool settune <mountpoint> <parameter> <value>\n"
- "Unfreeze a GFS2 cluster:\n"
- " gfs2_tool unfreeze <mountpoint>\n"
- "Print tool version information\n"
- " gfs2_tool version\n"
- "Withdraw this machine from participating in a filesystem:\n"
- " gfs2_tool withdraw <mountpoint>\n"
-};
-
-/**
- * print_usage - print out usage information
- *
- */
-
-void print_usage(void)
-{
- puts( _(usage) );
-}
-
-/**
- * print_version -
- *
- */
-
-static void print_version(void)
-{
- printf( _("gfs2_tool " RELEASE_VERSION " (built " __DATE__ " " __TIME__ ")\n"));
- puts( _(REDHAT_COPYRIGHT "\n") );
-}
-
-/**
- * decode_arguments -
- * @argc:
- * @argv:
- *
- */
-
-static void decode_arguments(int argc, char *argv[])
-{
- int cont = TRUE;
- int optchar;
-
- output_type = OUTPUT_BLOCKS;
- while (cont) {
- optchar = getopt(argc, argv, "cDhHki:OVX");
-
- switch (optchar) {
- case 'c':
- continuous = TRUE;
- break;
-
- case 'D':
- debug = TRUE;
- break;
-
- case 'h':
- print_usage();
- exit(0);
-
- case 'H':
- output_type = OUTPUT_HUMAN;
- break;
-
- case 'i':
- sscanf(optarg, "%u", &interval);
- break;
-
- case 'k':
- output_type = OUTPUT_K;
- break;
-
- case 'O':
- override = TRUE;
- break;
-
- case 'V':
- print_version();
- exit(0);
-
- case 'X':
- expert = TRUE;
- break;
-
- case EOF:
- cont = FALSE;
- break;
-
- default:
- die( _("unknown option: %c\n"), optchar);
- };
- }
-
- if (optind < argc) {
- action = argv[optind];
- optind++;
- } else {
- die( _("no action specified\n"));
- }
-}
-
-/**
- * main - Do everything
- * @argc:
- * @argv:
- *
- */
-
-int main(int argc, char *argv[])
-{
- setlocale(LC_ALL, "");
- textdomain("gfs2-utils");
-
- if (argc < 2) {
- print_usage();
- return 0;
- }
-
- decode_arguments(argc, argv);
-
- if (strcmp(action, "clearflag") == 0)
- set_flag(argc, argv);
- else if (strcmp(action, "freeze") == 0)
- do_freeze(argc, argv);
- else if (strcmp(action, "gettune") == 0)
- get_tune(argc, argv);
- else if (strcmp(action, "journals") == 0)
- print_journals(argc, argv);
- else if (strcmp(action, "lockdump") == 0)
- print_lockdump(argc, argv);
- else if (strcmp(action, "sb") == 0)
- do_sb(argc, argv);
- else if (strcmp(action, "setflag") == 0)
- set_flag(argc, argv);
- else if (strcmp(action, "settune") == 0)
- set_tune(argc, argv);
- else if (strcmp(action, "unfreeze") == 0)
- do_freeze(argc, argv);
- else if (strcmp(action, "version") == 0)
- print_version();
- else if (strcmp(action, "withdraw") == 0)
- do_withdraw(argc, argv);
- else
- die( _("unknown action: %s\n"), action);
-
- return 0;
-}
diff --git a/gfs2/tool/misc.c b/gfs2/tool/misc.c
deleted file mode 100644
index 359567c..0000000
--- a/gfs2/tool/misc.c
+++ /dev/null
@@ -1,341 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <linux/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-#include <dirent.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#define __user
-#include <linux/gfs2_ondisk.h>
-#include <sys/mount.h>
-
-#include "libgfs2.h"
-#include "gfs2_tool.h"
-#include "iflags.h"
-
-#ifndef FIFREZE
-#define FIFREEZE _IOWR('X', 119, int) /* Freeze */
-#define FITHAW _IOWR('X', 120, int) /* Thaw */
-#endif
-
-/**
- * do_freeze - freeze a GFS2 filesystem
- * @argc:
- * @argv:
- *
- */
-
-void do_freeze(int argc, char **argv)
-{
- char *command = argv[optind - 1];
- int fd;
-
- if (optind == argc)
- die("Usage: gfs2_tool %s <mountpoint>\n", command);
-
- fd = open(argv[optind], O_NOCTTY|O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, _("Couldn't find a GFS2 filesystem mounted at %s\n"),
- argv[optind]);
- exit(-1);
- }
-
- if (strcmp(command, "freeze") == 0) {
- if (ioctl(fd, FIFREEZE, 0)) {
- fprintf(stderr, _("Error freezing fs: %s\n"),
- strerror(errno));
- exit(-1);
- }
- } else if (strcmp(command, "unfreeze") == 0) {
- if (ioctl(fd, FITHAW, 0)) {
- fprintf(stderr, _("Error thawing fs: %s\n"),
- strerror(errno));
- exit(-1);
- }
- }
- close(fd);
-}
-
-/**
- * print_lockdump -
- * @argc:
- * @argv:
- *
- */
-
-void print_lockdump(int argc, char **argv)
-{
- char path[PATH_MAX];
- char *name, line[PATH_MAX];
- char *debugfs;
- FILE *file;
- int rc = -1;
-
- /* See if debugfs is mounted, and if not, mount it. */
- debugfs = find_debugfs_mount();
- if (!debugfs) {
- debugfs = malloc(PATH_MAX);
- if (!debugfs)
- die("Can't allocate memory for debugfs.\n");
-
- memset(debugfs, 0, PATH_MAX);
- sprintf(debugfs, "/tmp/debugfs.XXXXXX");
-
- if (!mkdtemp(debugfs)) {
- fprintf(stderr,_("Can't create %s mount point.\n"),
- debugfs);
- free(debugfs);
- exit(-1);
- }
-
- rc = mount("none", debugfs, "debugfs", 0, NULL);
- if (rc) {
- fprintf(stderr,
- _("Can't mount debugfs. "
- "Maybe your kernel doesn't support it.\n"));
- free(debugfs);
- exit(-1);
- }
- }
- name = mp2fsname(argv[optind]);
- if (name) {
- sprintf(path, "%s/gfs2/%s/glocks", debugfs, name);
- free(name);
- file = fopen(path, "rt");
- if (file) {
- while (fgets(line, PATH_MAX, file)) {
- printf("%s", line);
- }
- fclose(file);
- } else {
- fprintf(stderr, _("Can't open %s: %s\n"), path,
- strerror(errno));
- }
- } else {
- fprintf(stderr, _("Unable to locate sysfs for mount point %s.\n"),
- argv[optind]);
- }
- /* Check if we mounted the debugfs and if so, unmount it. */
- if (!rc) {
- umount(debugfs);
- rmdir(debugfs);
- }
- free(debugfs);
-}
-
-/**
- * print_flags - print the flags in a dinode's di_flags field
- * @di: the dinode structure
- *
- */
-
-static void print_flags(struct gfs2_dinode *di)
-{
- if (di->di_flags) {
- printf( _("Flags:\n"));
- if (di->di_flags & GFS2_DIF_JDATA)
- printf(" jdata\n");
- if (di->di_flags & GFS2_DIF_EXHASH)
- printf(" exhash\n");
- if (di->di_flags & GFS2_DIF_EA_INDIRECT)
- printf(" ea_indirect\n");
- if (di->di_flags & GFS2_DIF_IMMUTABLE)
- printf(" immutable\n");
- if (di->di_flags & GFS2_DIF_APPENDONLY)
- printf(" appendonly\n");
- if (di->di_flags & GFS2_DIF_NOATIME)
- printf( _(" noatime\n"));
- if (di->di_flags & GFS2_DIF_SYNC)
- printf(" sync\n");
- if (di->di_flags & GFS2_DIF_TRUNC_IN_PROG)
- printf(" trunc_in_prog\n");
- }
-}
-
-/*
- * Use FS_XXX_FL flags defined in <linux/fs.h> which correspond to
- * GFS2_DIF_XXX
- */
-static unsigned int get_flag_from_name(char *name)
-{
- if (strncmp(name, "jdata", 5) == 0)
- return FS_JOURNAL_DATA_FL;
- else if (strncmp(name, "exhash", 6) == 0)
- return FS_INDEX_FL;
- else if (strncmp(name, "immutable", 9) == 0)
- return FS_IMMUTABLE_FL;
- else if (strncmp(name, "appendonly", 10) == 0)
- return FS_APPEND_FL;
- else if (strncmp(name, "noatime", 7) == 0)
- return FS_NOATIME_FL;
- else if (strncmp(name, "sync", 4) == 0)
- return FS_SYNC_FL;
- else
- return 0;
-}
-
-/**
- * set_flag - set or clear flags in some dinodes
- * @argc:
- * @argv:
- *
- */
-void set_flag(int argc, char **argv)
-{
- struct gfs2_dinode di;
- char *flstr;
- int fd, error, set;
- unsigned int newflags = 0;
- unsigned int flag;
- if (optind == argc) {
- di.di_flags = 0xFFFFFFFF;
- print_flags(&di);
- return;
- }
-
- set = (strcmp(argv[optind -1], "setflag") == 0) ? 1 : 0;
- flstr = argv[optind++];
- if (!(flag = get_flag_from_name(flstr)))
- die( _("unrecognized flag %s\n"), argv[optind -1]);
-
- for (; optind < argc; optind++) {
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0)
- die( _("can't open %s: %s\n"), argv[optind], strerror(errno));
- /* first get the existing flags on the file */
- error = ioctl(fd, FS_IOC_GETFLAGS, &newflags);
- if (error)
- die( _("can't get flags on %s: %s\n"),
- argv[optind], strerror(errno));
- newflags = set ? newflags | flag : newflags & ~flag;
- /* new flags */
- error = ioctl(fd, FS_IOC_SETFLAGS, &newflags);
- if (error)
- die( _("can't set flags on %s: %s\n"),
- argv[optind], strerror(errno));
- close(fd);
- }
-}
-
-/**
- * print_journals - print out the file system journal information
- * @argc:
- * @argv:
- *
- */
-
-void print_journals(int argc, char **argv)
-{
- struct gfs2_sbd sbd;
- DIR *jindex;
- struct dirent *journal;
- char jindex_name[PATH_MAX], jname[PATH_MAX];
- int jcount;
- struct stat statbuf;
-
- memset(&sbd, 0, sizeof(struct gfs2_sbd));
- sbd.bsize = GFS2_DEFAULT_BSIZE;
- sbd.rgsize = -1;
- sbd.jsize = GFS2_DEFAULT_JSIZE;
- sbd.qcsize = GFS2_DEFAULT_QCSIZE;
- sbd.md.journals = 1;
-
- sbd.path_name = argv[optind];
- sbd.path_fd = open(sbd.path_name, O_RDONLY);
- if (sbd.path_fd < 0)
- die("can't open root directory %s: %s\n",
- sbd.path_name, strerror(errno));
- if (check_for_gfs2(&sbd)) {
- if (errno == EINVAL)
- fprintf(stderr, _("Not a valid GFS2 mount point: %s\n"),
- sbd.path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
- sbd.device_fd = open(sbd.device_name, O_RDONLY);
- if (sbd.device_fd < 0)
- die( _("can't open device %s: %s\n"),
- sbd.device_name, strerror(errno));
-
- if (mount_gfs2_meta(&sbd)) {
- fprintf(stderr, _("Error mounting GFS2 metafs: %s\n"),
- strerror(errno));
- exit(-1);
- }
-
- sprintf(jindex_name, "%s/jindex", sbd.metafs_path);
- jindex = opendir(jindex_name);
- if (!jindex) {
- die( _("Can't open %s\n"), jindex_name);
- } else {
- jcount = 0;
- while ((journal = readdir(jindex))) {
- if (journal->d_name[0] == '.')
- continue;
- sprintf(jname, "%s/%s", jindex_name, journal->d_name);
- if (stat(jname, &statbuf)) {
- statbuf.st_size = 0;
- perror(jname);
- }
- jcount++;
- printf("%s - %lluMB\n", journal->d_name,
- (unsigned long long)statbuf.st_size / 1048576);
- }
-
- printf( _("%d journal(s) found.\n"), jcount);
- closedir(jindex);
- }
- cleanup_metafs(&sbd);
- close(sbd.device_fd);
- close(sbd.path_fd);
-}
-
-/**
- * do_withdraw - withdraw a GFS2 filesystem
- * @argc:
- * @argv:
- *
- */
-
-void do_withdraw(int argc, char **argv)
-{
- char *name;
- struct gfs2_sbd sbd;
-
- if (optind == argc)
- die("Usage: gfs2_tool withdraw <mountpoint>\n");
-
- sbd.path_name = argv[optind];
- if (check_for_gfs2(&sbd)) {
- if (errno == EINVAL)
- fprintf(stderr, _("Not a valid GFS2 mount point: %s\n"),
- sbd.path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
- name = mp2fsname(argv[optind]);
- if (!name) {
- fprintf(stderr, _("Couldn't find GFS2 filesystem mounted at %s\n"),
- argv[optind]);
- exit(-1);
- }
-
- if (set_sysfs(name, "withdraw", "1")) {
- fprintf(stderr, _("Error writing to sysfs withdraw file: %s\n"),
- strerror(errno));
- exit(-1);
- }
-}
-
diff --git a/gfs2/tool/ondisk.c b/gfs2/tool/ondisk.c
deleted file mode 100644
index d10cfd8..0000000
--- a/gfs2/tool/ondisk.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <linux/types.h>
-
-#define printk printf
-
-#define WANT_GFS2_CONVERSION_FUNCTIONS
-#include <linux/gfs2_ondisk.h>
diff --git a/gfs2/tool/sb.c b/gfs2/tool/sb.c
deleted file mode 100644
index 0930aaf..0000000
--- a/gfs2/tool/sb.c
+++ /dev/null
@@ -1,227 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <linux/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-#include <ctype.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include <linux/gfs2_ondisk.h>
-
-#include "gfs2_tool.h"
-#include "libgfs2.h"
-
-void print_it(const char *label, const char *fmt, const char *fmt2, ...)
-{
- va_list args;
-
- va_start(args, fmt2);
- printf("%s = ", label);
- vprintf(fmt, args);
- printf("\n");
- va_end(args);
-}
-
-/**
- * str_to_hexchar - convert a string consisting of two isxdigits back to hex.
- * Returns: the hex character
- */
-static int str_to_hexchar(const char *estring)
-{
- int ch = 0;
-
- if (isdigit(*estring))
- ch = (*estring - '0') * 0x10;
- else if (*estring >= 'a' && *estring <= 'f')
- ch = (*estring - 'a' + 0x0a) * 0x10;
- else if (*estring >= 'A' && *estring <= 'F')
- ch = (*estring - 'A' + 0x0a) * 0x10;
-
- estring++;
- if (isdigit(*estring))
- ch += (*estring - '0');
- else if (*estring >= 'a' && *estring <= 'f')
- ch += (*estring - 'a' + 0x0a);
- else if (*estring >= 'A' && *estring <= 'F')
- ch += (*estring - 'A' + 0x0a);
- return ch;
-}
-
-/**
- * do_sb - examine/modify a unmounted FS' superblock
- * @argc:
- * @argv:
- *
- */
-
-void
-do_sb(int argc, char **argv)
-{
- char *device, *field, *newval = NULL;
- int fd;
- unsigned char buf[GFS2_BASIC_BLOCK], input[256];
- struct gfs2_sb sb;
- struct gfs2_buffer_head dummy_bh;
-
- dummy_bh.b_data = (char *)buf;
- if (optind == argc)
- die("Usage: gfs2_tool sb <device> <field> [newval]\n");
-
- device = argv[optind++];
-
- if (optind == argc)
- die("Usage: gfs2_tool sb <device> <field> [newval]\n");
-
- field = argv[optind++];
-
- if (optind < argc) {
- if (strcmp(field, "all") == 0)
- die("can't specify new value for \"all\"\n");
- newval = argv[optind++];
- }
-
-
- fd = open(device, (newval) ? O_RDWR : O_RDONLY);
- if (fd < 0)
- die("can't open %s: %s\n", device, strerror(errno));
-
- if (newval && !override) {
- printf( _("You shouldn't change any of these values if the filesystem is mounted.\n"));
- printf( _("\nAre you sure? [y/n] "));
- if(!fgets((char*)input, 255, stdin))
- die( _("unable to read from stdin\n"));
-
- if (input[0] != 'y')
- die( _("aborted\n"));
-
- printf("\n");
- }
-
- if (lseek(fd, GFS2_SB_ADDR * GFS2_BASIC_BLOCK, SEEK_SET) !=
- GFS2_SB_ADDR * GFS2_BASIC_BLOCK) {
- fprintf(stderr, _("bad seek: %s from %s:%d: superblock\n"),
- strerror(errno), __FUNCTION__, __LINE__);
- exit(-1);
- }
- if (read(fd, buf, GFS2_BASIC_BLOCK) != GFS2_BASIC_BLOCK) {
- fprintf(stderr, _("bad read: %s from %s:%d: superblock\n"),
- strerror(errno), __FUNCTION__, __LINE__);
- exit(-1);
- }
-
- gfs2_sb_in(&sb, &dummy_bh);
-
- if (sb.sb_header.mh_magic != GFS2_MAGIC ||
- sb.sb_header.mh_type != GFS2_METATYPE_SB)
- die( _("there isn't a GFS2 filesystem on %s\n"), device);
-
- if (strcmp(field, "proto") == 0) {
- printf( _("current lock protocol name = \"%s\"\n"),
- sb.sb_lockproto);
-
- if (newval) {
- if (strlen(newval) >= GFS2_LOCKNAME_LEN)
- die( _("new lockproto name is too long\n"));
- strcpy(sb.sb_lockproto, newval);
- printf( _("new lock protocol name = \"%s\"\n"),
- sb.sb_lockproto);
- }
- } else if (strcmp(field, "table") == 0) {
- printf( _("current lock table name = \"%s\"\n"),
- sb.sb_locktable);
-
- if (newval) {
- if (strlen(newval) >= GFS2_LOCKNAME_LEN)
- die( _("new locktable name is too long\n"));
- strcpy(sb.sb_locktable, newval);
- printf( _("new lock table name = \"%s\"\n"),
- sb.sb_locktable);
- }
- } else if (strcmp(field, "ondisk") == 0) {
- printf( _("current ondisk format = %u\n"),
- sb.sb_fs_format);
-
- if (newval) {
- sb.sb_fs_format = atoi(newval);
- printf( _("new ondisk format = %u\n"),
- sb.sb_fs_format);
- }
- } else if (strcmp(field, "multihost") == 0) {
- printf( _("current multihost format = %u\n"),
- sb.sb_multihost_format);
-
- if (newval) {
- sb.sb_multihost_format = atoi(newval);
- printf( _("new multihost format = %u\n"),
- sb.sb_multihost_format);
- }
-#ifdef GFS2_HAS_UUID
- } else if (strcmp(field, "uuid") == 0) {
- printf( _("current uuid = %s\n"), str_uuid(sb.sb_uuid));
-
- if (newval) {
- int i;
- unsigned char uuid[16], *cp;
-
- if (strlen(newval) != 36)
- die( _("uuid %s is the wrong length; must be 36 "
- "hex characters long.\n"), newval);
- cp = uuid;
- for (i = 0; i < 36; i++) {
- if ((i == 8) || (i == 13) ||
- (i == 18) || (i == 23)) {
- if (newval[i] == '-')
- continue;
- die( _("uuid %s has an invalid format."),
- newval);
- }
- if (!isxdigit(newval[i]))
- die( _("uuid %s has an invalid hex "
- "digit '%c' at offset %d.\n"),
- newval, newval[i], i + 1);
- *cp = str_to_hexchar(&newval[i++]);
- cp++;
- }
- memcpy(sb.sb_uuid, uuid, 16);
- printf( _("new uuid = %s\n"), str_uuid(sb.sb_uuid));
- }
-#endif
- } else if (strcmp(field, "all") == 0) {
- gfs2_sb_print(&sb);
- newval = FALSE;
- } else
- die( _("unknown field %s\n"), field);
-
- if (newval) {
- gfs2_sb_out(&sb, &dummy_bh);
-
- if (lseek(fd, GFS2_SB_ADDR * GFS2_BASIC_BLOCK, SEEK_SET) !=
- GFS2_SB_ADDR * GFS2_BASIC_BLOCK) {
- fprintf(stderr, _("bad seek: %s from %s:%d: superblock\n"),
- strerror(errno), __FUNCTION__, __LINE__);
- exit(-1);
- }
- if (write(fd, buf, GFS2_BASIC_BLOCK) != GFS2_BASIC_BLOCK) {
- fprintf(stderr, _("write error: %s from %s:%d: "
- "superblock\n"), strerror(errno),
- __FUNCTION__, __LINE__);
- exit(-1);
- }
-
- fsync(fd);
-
- printf( _("Done\n"));
- }
-
- close(fd);
-}
diff --git a/gfs2/tool/tune.c b/gfs2/tool/tune.c
deleted file mode 100644
index 4666291..0000000
--- a/gfs2/tool/tune.c
+++ /dev/null
@@ -1,144 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <linux/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <errno.h>
-#include <dirent.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#define __user
-
-#include "gfs2_tool.h"
-#include "libgfs2.h"
-
-#define SIZE (65536)
-
-#define SYS_BASE "/sys/fs/gfs2" /* FIXME: Look in /proc/mounts for this */
-
-/**
- * get_tune - print out the current tuneable parameters for a filesystem
- * @argc:
- * @argv:
- *
- */
-
-void
-get_tune(int argc, char **argv)
-{
- char path[PATH_MAX];
- char *fs;
- DIR *d;
- struct dirent *de;
- double ratio;
- unsigned int num, den;
- struct gfs2_sbd sbd;
- char *value;
-
- if (optind == argc)
- die( _("Usage: gfs2_tool gettune <mountpoint>\n"));
-
- sbd.path_name = argv[optind];
- if (check_for_gfs2(&sbd)) {
- if (errno == EINVAL)
- fprintf(stderr, _("Not a valid GFS2 mount point: %s\n"),
- sbd.path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
- fs = mp2fsname(argv[optind]);
- if (!fs) {
- fprintf(stderr, _("Couldn't find GFS2 filesystem mounted at %s\n"),
- argv[optind]);
- exit(-1);
- }
- memset(path, 0, PATH_MAX);
- snprintf(path, PATH_MAX - 1, "%s/%s/tune", SYS_BASE, fs);
-
- d = opendir(path);
- if (!d)
- die( _("can't open %s: %s\n"), path, strerror(errno));
-
- while((de = readdir(d))) {
- if (de->d_name[0] == '.')
- continue;
- snprintf(path, PATH_MAX - 1, "tune/%s", de->d_name);
- if (strcmp(de->d_name, "quota_scale") == 0) {
- value = get_sysfs(fs, "tune/quota_scale");
- if (!value) {
- printf( _("quota_scale = (Not found: %s)\n"),
- strerror(errno));
- continue;
- }
- sscanf(value, "%u %u", &num, &den);
- ratio = (double)num / den;
- printf( _("quota_scale = %.4f (%u, %u)\n"), ratio, num,
- den);
- } else
- printf("%s = %s\n", de->d_name, get_sysfs(fs, path));
- }
- closedir(d);
-}
-
-/**
- * set_tune - set a tuneable parameter
- * @argc:
- * @argv:
- *
- */
-
-void
-set_tune(int argc, char **argv)
-{
- char *param, *value;
- char tune_base[SIZE] = "tune/";
- char buf[256];
- char *fs;
- struct gfs2_sbd sbd;
-
- if (optind == argc)
- die( _("Usage: gfs2_tool settune <mountpoint> <parameter> <value>\n"));
- sbd.path_name = argv[optind++];
- if (optind == argc)
- die( _("Usage: gfs2_tool settune <mountpoint> <parameter> <value>\n"));
- param = argv[optind++];
- if (optind == argc)
- die( _("Usage: gfs2_tool settune <mountpoint> <parameter> <value>\n"));
- value = argv[optind++];
-
- if (check_for_gfs2(&sbd)) {
- if (errno == EINVAL)
- fprintf(stderr, _("Not a valid GFS2 mount point: %s\n"),
- sbd.path_name);
- else
- fprintf(stderr, "%s\n", strerror(errno));
- exit(-1);
- }
- fs = mp2fsname(sbd.path_name);
- if (!fs) {
- fprintf(stderr, _("Couldn't find GFS2 filesystem mounted at %s\n"),
- sbd.path_name);
- exit(-1);
- }
-
- if (strcmp(param, "quota_scale") == 0) {
- float s;
- sscanf(value, "%f", &s);
- sprintf(buf, "%u %u", (unsigned int)(s * 10000.0 + 0.5), 10000);
- value = buf;
- }
- if (set_sysfs(fs, strcat(tune_base, param), value)) {
- fprintf(stderr, _("Error writing to sysfs %s tune file: %s\n"),
- param, strerror(errno));
- exit(-1);
- }
-}
diff --git a/group/Makefile b/group/Makefile
index dd87fd6..0113501 100644
--- a/group/Makefile
+++ b/group/Makefile
@@ -1,4 +1,5 @@
include ../make/defines.mk
include $(OBJDIR)/make/passthrough.mk
-SUBDIRS = lib dlm_controld libgfscontrol gfs_control gfs_controld tool daemon man
+#SUBDIRS = lib dlm_controld tool daemon man
+SUBDIRS = lib dlm_controld daemon man
diff --git a/group/gfs_control/Makefile b/group/gfs_control/Makefile
deleted file mode 100644
index a69860b..0000000
--- a/group/gfs_control/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-TARGET= gfs_control
-
-SBINDIRT=$(TARGET)
-
-all: depends ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS= main.o
-
-CFLAGS += -I$(S)/../libgfscontrol
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L../libgfscontrol -lgfscontrol
-LDFLAGS += -L${libdir}
-
-LDDEPS += ../libgfscontrol/libgfscontrol.a
-
-${TARGET}: ${OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS)
-
-clean: generalclean
-
-depends:
- $(MAKE) -C ../libgfscontrol all
-
--include $(OBJS:.o=.d)
diff --git a/group/gfs_control/main.c b/group/gfs_control/main.c
deleted file mode 100644
index 12fee97..0000000
--- a/group/gfs_control/main.c
+++ /dev/null
@@ -1,463 +0,0 @@
-#include <sys/types.h>
-#include <sys/un.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <limits.h>
-#include <netinet/in.h>
-
-#include "libgfscontrol.h"
-
-#define OPTION_STRING "nhV"
-
-#define OP_LIST 1
-#define OP_DUMP 2
-#define OP_PLOCKS 3
-#define OP_JOIN 4
-#define OP_LEAVE 5
-#define OP_JOINLEAVE 6
-
-static char *fsname;
-static int operation;
-static int opt_ind;
-static int ls_all_nodes;
-
-#define MAX_MG 128
-#define MAX_NODES 128
-
-struct gfsc_mountgroup mgs[MAX_MG];
-struct gfsc_node nodes[MAX_NODES];
-
-
-static void print_usage(const char *prog_name)
-{
- printf("Usage:\n");
- printf("\n");
- printf("%s [options] [ls|dump|plocks]\n", prog_name);
- printf("\n");
- printf("Options:\n");
- printf(" -n Show all node information in ls\n");
- printf(" -h Print this help, then exit\n");
- printf(" -V Print program version information, then exit\n");
- printf("\n");
-}
-
-static void decode_arguments(int argc, char **argv)
-{
- int cont = 1;
- int optchar;
- int need_fsname;
-
- while (cont) {
- optchar = getopt(argc, argv, OPTION_STRING);
-
- switch (optchar) {
- case 'n':
- ls_all_nodes = 1;
- break;
-
- case 'h':
- print_usage(argv[0]);
- exit(EXIT_SUCCESS);
- break;
-
- case 'V':
- printf("%s %s (built %s %s)\n",
- argv[0], RELEASE_VERSION, __DATE__, __TIME__);
- /* printf("%s\n", REDHAT_COPYRIGHT); */
- exit(EXIT_SUCCESS);
- break;
-
- case ':':
- case '?':
- fprintf(stderr, "Please use '-h' for usage.\n");
- exit(EXIT_FAILURE);
- break;
-
- case EOF:
- cont = 0;
- break;
-
- default:
- fprintf(stderr, "unknown option: %c\n", optchar);
- exit(EXIT_FAILURE);
- break;
- };
- }
-
- need_fsname = 1;
-
- while (optind < argc) {
-
- if (!strncmp(argv[optind], "leave", 5) &&
- (strlen(argv[optind]) == 5)) {
- operation = OP_LEAVE;
- opt_ind = optind + 1;
- break;
- } else if (!strncmp(argv[optind], "ls", 2) &&
- (strlen(argv[optind]) == 2)) {
- operation = OP_LIST;
- opt_ind = optind + 1;
- need_fsname = 0;
- break;
- } else if (!strncmp(argv[optind], "dump", 4) &&
- (strlen(argv[optind]) == 4)) {
- operation = OP_DUMP;
- opt_ind = optind + 1;
- need_fsname = 0;
- break;
- } else if (!strncmp(argv[optind], "plocks", 6) &&
- (strlen(argv[optind]) == 6)) {
- operation = OP_PLOCKS;
- opt_ind = optind + 1;
- break;
- }
-
- optind++;
- }
-
- if (!operation || !opt_ind) {
- print_usage(argv[0]);
- exit(EXIT_FAILURE);
- }
-
- if (optind < argc - 1)
- fsname = argv[opt_ind];
- else if (need_fsname) {
- fprintf(stderr, "fs name required\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static int do_write(int fd, void *buf, size_t count)
-{
- int rv, off = 0;
-
- retry:
- rv = write(fd, (char *)buf + off, count);
- if (rv == -1 && errno == EINTR)
- goto retry;
- if (rv < 0)
- return rv;
-
- if (rv != count) {
- count -= rv;
- off += rv;
- goto retry;
- }
- return 0;
-}
-
-static void do_leave(char *table)
-{
- struct gfsc_mount_args ma;
- int rv;
-
- memset(&ma, 0, sizeof(ma));
-
- strncpy(ma.table, table, sizeof(ma.table));
-
- rv = gfsc_fs_leave(&ma, 0);
- if (rv < 0)
- fprintf(stderr, "gfs_controld leave error %d\n", rv);
-}
-
-static char *mg_flags_str(uint32_t flags)
-{
- static char str[128];
- int i = 0;
-
- memset(str, 0, sizeof(str));
-
- if (flags & GFSC_MF_LOCAL_RECOVERY_BUSY) {
- i++;
- strcat(str, "recover");
- }
- if (flags & GFSC_MF_FIRST_RECOVERY_NEEDED) {
- strcat(str, i++ ? "," : "");
- strcat(str, "need_first");
- }
- if (flags & GFSC_MF_KERNEL_MOUNT_ERROR) {
- strcat(str, i++ ? "," : "");
- strcat(str, "error");
- }
- if (flags & GFSC_MF_KERNEL_MOUNT_DONE) {
- strcat(str, i++ ? "," : "");
- strcat(str, "mounted");
- }
- if (flags & GFSC_MF_KERNEL_STOPPED) {
- strcat(str, i++ ? "," : "");
- strcat(str, "blocked");
- }
- if (flags & GFSC_MF_LEAVING) {
- strcat(str, i++ ? "," : "");
- strcat(str, "leave");
- }
- if (flags & GFSC_MF_JOINING) {
- strcat(str, i++ ? "," : "");
- strcat(str, "join");
- }
-
- /* leave this one out, it will often be set and we don't need
- to see it */
- /*
- if (flags & GFSC_MF_FIRST_RECOVERY_MSG)
- strcat(str, "first_recovery_msg ");
- */
- return str;
-}
-
-static char *node_mount_str(uint32_t flags)
-{
- static char str[128];
- int i = 0;
-
- memset(str, 0, sizeof(str));
-
- if (flags & GFSC_NF_KERNEL_MOUNT_DONE) {
- i++;
- strcat(str, "done");
- }
- if (flags & GFSC_NF_KERNEL_MOUNT_ERROR) {
- strcat(str, i++ ? "," : "");
- strcat(str, "error");
- }
- if (flags & GFSC_NF_READONLY) {
- strcat(str, i++ ? "," : "");
- strcat(str, "ro");
- }
- if (flags & GFSC_NF_SPECTATOR) {
- strcat(str, i++ ? "," : "");
- strcat(str, "spect");
- }
-
- if (!i)
- strcat(str, "none");
-
- /* ignoring CHECK_DLM */
-
- return str;
-}
-
-static int member_int(struct gfsc_node *n)
-{
- if (n->flags & GFSC_NF_DISALLOWED)
- return -1;
- if (n->flags & GFSC_NF_MEMBER)
- return 1;
- return 0;
-}
-
-static const char *condition_str(int cond)
-{
- switch (cond) {
- case 0:
- return "";
- case 1:
- return "kernel_mount_done";
- case 2:
- return "notify_nodeid";
- case 3:
- return "poll_dlm";
- case 4:
- return "pending";
- default:
- return "unknown";
- }
-}
-
-static void show_nodeids(int count, struct gfsc_node *nodes_in)
-{
- struct gfsc_node *n = nodes_in;
- int i;
-
- for (i = 0; i < count; i++) {
- printf("%d ", n->nodeid);
- n++;
- }
- printf("\n");
-}
-
-static int node_compare(const void *va, const void *vb)
-{
- const struct gfsc_node *a = va;
- const struct gfsc_node *b = vb;
-
- return a->nodeid - b->nodeid;
-}
-
-static void show_mg(struct gfsc_mountgroup *mg)
-{
- int rv, node_count;
-
- printf("name %s\n", mg->name);
- printf("id 0x%08x\n", mg->global_id);
- printf("flags 0x%08x %s\n",
- mg->flags, mg_flags_str(mg->flags));
- printf("change member %d joined %d remove %d failed %d seq %d,%d\n",
- mg->cg_prev.member_count, mg->cg_prev.joined_count,
- mg->cg_prev.remove_count, mg->cg_prev.failed_count,
- mg->cg_prev.combined_seq, mg->cg_prev.seq);
-
- node_count = 0;
- memset(&nodes, 0, sizeof(nodes));
- rv = gfsc_mountgroup_nodes(mg->name, GFSC_NODES_MEMBERS,
- MAX_NODES, &node_count, nodes);
- if (rv < 0) {
- printf("members error\n");
- goto next;
- }
- qsort(nodes, node_count, sizeof(struct gfsc_node), node_compare);
-
- printf("members ");
- show_nodeids(node_count, nodes);
-
- next:
- if (!mg->cg_next.seq)
- return;
-
- printf("new change member %d joined %d remove %d failed %d seq %d,%d\n",
- mg->cg_next.member_count, mg->cg_next.joined_count,
- mg->cg_next.remove_count, mg->cg_next.failed_count,
- mg->cg_next.combined_seq, mg->cg_next.seq);
-
- printf("new status wait_messages %d wait_condition %d %s\n",
- mg->cg_next.wait_messages, mg->cg_next.wait_condition,
- condition_str(mg->cg_next.wait_condition));
-
- node_count = 0;
- memset(&nodes, 0, sizeof(nodes));
- rv = gfsc_mountgroup_nodes(mg->name, GFSC_NODES_NEXT,
- MAX_NODES, &node_count, nodes);
- if (rv < 0) {
- printf("new members error\n");
- return;
- }
- qsort(nodes, node_count, sizeof(struct gfsc_node), node_compare);
-
- printf("new members ");
- show_nodeids(node_count, nodes);
-}
-
-static void show_all_nodes(int count, struct gfsc_node *nodes_in)
-{
- struct gfsc_node *n = nodes_in;
- int i;
-
- for (i = 0; i < count; i++) {
- printf("nodeid %d jid %d member %d failed %d start %d seq_add %u seq_rem %u mount %s\n",
- n->nodeid,
- n->jid,
- member_int(n),
- n->failed_reason,
- (n->flags & GFSC_NF_START) ? 1 : 0,
- n->added_seq,
- n->removed_seq,
- node_mount_str(n->flags));
- n++;
- }
-}
-
-static void do_list(char *name)
-{
- struct gfsc_mountgroup *mg;
- int node_count;
- int mg_count;
- int rv;
- int i;
-
- memset(mgs, 0, sizeof(mgs));
-
- if (name) {
- mg_count = 1;
- rv = gfsc_mountgroup_info(name, mgs);
- } else {
- rv = gfsc_mountgroups(MAX_MG, &mg_count, mgs);
- }
-
- if (rv < 0)
- exit(EXIT_FAILURE); /* gfs_controld probably not running */
-
- if (mg_count)
- printf("gfs mountgroups\n");
-
- for (i = 0; i < mg_count; i++) {
- mg = &mgs[i];
-
- show_mg(mg);
-
- if (!ls_all_nodes)
- goto next;
-
- node_count = 0;
- memset(&nodes, 0, sizeof(nodes));
-
- rv = gfsc_mountgroup_nodes(mg->name, GFSC_NODES_ALL,
- MAX_NODES, &node_count, nodes);
- if (rv < 0) {
- printf("all nodes error %d %d\n", rv, errno);
- goto next;
- }
-
- qsort(nodes, node_count, sizeof(struct gfsc_node),node_compare);
-
- printf("all nodes\n");
- show_all_nodes(node_count, nodes);
- next:
- printf("\n");
- }
-}
-
-static void do_plocks(char *name)
-{
- char buf[GFSC_DUMP_SIZE];
-
- memset(buf, 0, sizeof(buf));
-
- gfsc_dump_plocks(name, buf);
-
- do_write(STDOUT_FILENO, buf, strlen(buf));
-}
-
-static void do_dump(void)
-{
- char buf[GFSC_DUMP_SIZE];
-
- memset(buf, 0, sizeof(buf));
-
- gfsc_dump_debug(buf);
-
- do_write(STDOUT_FILENO, buf, strlen(buf));
-}
-
-int main(int argc, char **argv)
-{
- decode_arguments(argc, argv);
-
- switch (operation) {
-
- case OP_LEAVE:
- do_leave(fsname);
- break;
-
- case OP_LIST:
- do_list(fsname);
- break;
-
- case OP_DUMP:
- do_dump();
- break;
-
- case OP_PLOCKS:
- do_plocks(fsname);
- break;
- }
- return 0;
-}
-
diff --git a/group/gfs_controld/Makefile b/group/gfs_controld/Makefile
deleted file mode 100644
index 9d07a36..0000000
--- a/group/gfs_controld/Makefile
+++ /dev/null
@@ -1,75 +0,0 @@
-include ../../make/defines.mk
-
-TARGET= gfs_controld
-ifdef enable_pacemaker
-TARGET += gfs_controld.pcmk
-SBINDIRT += gfs_controld.pcmk
-endif
-
-SBINDIRT=$(TARGET)
-
-all: depends ${TARGET}
-
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-SHAREDOBJS= main.o \
- crc.o \
- config.o \
- cpg-new.o \
- cpg-old.o \
- group.o \
- util.o \
- plock.o \
- logging.o
-
-
-PCMK_OBJS= member_pcmk-pcmk.o \
- $(SHAREDOBJS:.o=-pcmk.o)
-
-OBJS= $(SHAREDOBJS) \
- member_cman.o
-
-CFLAGS += -I${ccsincdir} -I${cmanincdir} -I${logtincdir} -I${dlmcontrolincdir}
-CFLAGS += -I${corosyncincdir} -I${openaisincdir} -I${fencedincdir}
-CFLAGS += -I${KERNEL_SRC}/include/
-CFLAGS += -I$(S)/../libgfscontrol
-CFLAGS += -I$(S)/../lib/ -I$(S)/../include/
-CFLAGS += -I${incdir}
-
-PCMK_CFLAGS += -DENABLE_PACEMAKER=1
-PCMK_CFLAGS += -I${incdir}/heartbeat -I${incdir}/pacemaker
-PCMK_CFLAGS += `pkg-config glib-2.0 --cflags`
-PCMK_CFLAGS += `xml2-config --cflags`
-
-LDFLAGS += -L${dlmcontrollibdir} -ldlmcontrol
-LDFLAGS += -L${logtlibdir} -llogthread
-LDFLAGS += -L${corosynclibdir} -lcpg -lpthread
-LDFLAGS += -L${openaislibdir} -lSaCkpt
-LDFLAGS += -L../lib -lgroup
-LDFLAGS += -L${libdir}
-
-PCMK_LDFLAGS += -L${ccslibdir} -lccs
-PCMK_LDFLAGS += -lcib -lcrmcommon -lcrmcluster -ltotem_pg
-PCMK_LDFLAGS += `pkg-config glib-2.0 --libs`
-PCMK_LDFLAGS += `xml2-config --libs`
-
-CMAN_LDFLAGS += -L${ccslibdir} -L${cmanlibdir} -lccs -lcman
-CMAN_LDFLAGS += -L${fencedlibdir} -lfenced
-
-LDDEPS += ../lib/libgroup.a
-
-gfs_controld: ${OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS) $(CMAN_LDFLAGS)
-
-gfs_controld.pcmk: ${PCMK_OBJS} ${LDDEPS}
- $(CC) -o $@ $^ $(LDFLAGS) $(PCMK_LDFLAGS)
-
-depends:
- $(MAKE) -C ../lib all
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/group/gfs_controld/config.c b/group/gfs_controld/config.c
deleted file mode 100644
index b97e2de..0000000
--- a/group/gfs_controld/config.c
+++ /dev/null
@@ -1,229 +0,0 @@
-#include <sys/types.h>
-#include <asm/types.h>
-#include <sys/uio.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/utsname.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <limits.h>
-#include <unistd.h>
-#include <dirent.h>
-
-#include "gfs_daemon.h"
-#include "config.h"
-#include "ccs.h"
-
-int ccs_handle;
-
-/* was a config value set on command line?, 0 or 1. */
-
-int optd_groupd_compat;
-int optd_debug_logfile;
-int optd_enable_withdraw;
-int optd_enable_plock;
-int optd_plock_debug;
-int optd_plock_rate_limit;
-int optd_plock_ownership;
-int optd_drop_resources_time;
-int optd_drop_resources_count;
-int optd_drop_resources_age;
-
-/* actual config value from command line, cluster.conf, or default. */
-
-int cfgd_groupd_compat = DEFAULT_GROUPD_COMPAT;
-int cfgd_debug_logfile = DEFAULT_DEBUG_LOGFILE;
-int cfgd_enable_withdraw = DEFAULT_ENABLE_WITHDRAW;
-int cfgd_enable_plock = DEFAULT_ENABLE_PLOCK;
-int cfgd_plock_debug = DEFAULT_PLOCK_DEBUG;
-int cfgd_plock_rate_limit = DEFAULT_PLOCK_RATE_LIMIT;
-int cfgd_plock_ownership = DEFAULT_PLOCK_OWNERSHIP;
-int cfgd_drop_resources_time = DEFAULT_DROP_RESOURCES_TIME;
-int cfgd_drop_resources_count = DEFAULT_DROP_RESOURCES_COUNT;
-int cfgd_drop_resources_age = DEFAULT_DROP_RESOURCES_AGE;
-
-void read_ccs_name(const char *path, char *name)
-{
- char *str;
- int error;
-
- error = ccs_get(ccs_handle, path, &str);
- if (error || !str)
- return;
-
- strcpy(name, str);
-
- free(str);
-}
-
-void read_ccs_yesno(const char *path, int *yes, int *no)
-{
- char *str;
- int error;
-
- *yes = 0;
- *no = 0;
-
- error = ccs_get(ccs_handle, path, &str);
- if (error || !str)
- return;
-
- if (!strcmp(str, "yes"))
- *yes = 1;
-
- else if (!strcmp(str, "no"))
- *no = 1;
-
- free(str);
-}
-
-int read_ccs_int(const char *path, int *config_val)
-{
- char *str;
- int val;
- int error;
-
- error = ccs_get(ccs_handle, path, &str);
- if (error || !str)
- return -1;
-
- val = atoi(str);
-
- if (val < 0) {
- log_error("ignore invalid value %d for %s", val, path);
- return -1;
- }
-
- *config_val = val;
- log_debug("%s is %u", path, val);
- free(str);
- return 0;
-}
-
-#define LOCKSPACE_NODIR "/cluster/dlm/lockspace[@name=\"%s\"]/@nodir"
-
-void read_ccs_nodir(struct mountgroup *mg, char *buf)
-{
- char path[PATH_MAX];
- char *str;
- int val;
- int error;
-
- memset(path, 0, PATH_MAX);
- sprintf(path, LOCKSPACE_NODIR, mg->name);
-
- error = ccs_get(ccs_handle, path, &str);
- if (error || !str)
- return;
-
- val = atoi(str);
-
- if (val < 0) {
- log_error("ignore invalid value %d for %s", val, path);
- return;
- }
-
- snprintf(buf, 32, ":nodir=%d", val);
-
- log_debug("%s is %u", path, val);
- free(str);
-}
-
-#define GROUPD_COMPAT_PATH "/cluster/group/@groupd_compat"
-#define ENABLE_WITHDRAW_PATH "/cluster/gfs_controld/@enable_withdraw"
-#define ENABLE_PLOCK_PATH "/cluster/gfs_controld/@enable_plock"
-#define PLOCK_DEBUG_PATH "/cluster/gfs_controld/@plock_debug"
-#define PLOCK_RATE_LIMIT_PATH "/cluster/gfs_controld/@plock_rate_limit"
-#define PLOCK_OWNERSHIP_PATH "/cluster/gfs_controld/@plock_ownership"
-#define DROP_RESOURCES_TIME_PATH "/cluster/gfs_controld/@drop_resources_time"
-#define DROP_RESOURCES_COUNT_PATH "/cluster/gfs_controld/@drop_resources_count"
-#define DROP_RESOURCES_AGE_PATH "/cluster/gfs_controld/@drop_resources_age"
-
-#define DLM_PLOCK_RATE_LIMIT_PATH "/cluster/dlm/@plock_rate_limit"
-#define DLM_PLOCK_OWNERSHIP_PATH "/cluster/dlm/@plock_ownership"
-#define DLM_DROP_RESOURCES_TIME_PATH "/cluster/dlm/@drop_resources_time"
-#define DLM_DROP_RESOURCES_COUNT_PATH "/cluster/dlm/@drop_resources_count"
-#define DLM_DROP_RESOURCES_AGE_PATH "/cluster/dlm/@drop_resources_age"
-
-int setup_ccs(void)
-{
- int cd, rv;
-
- if (ccs_handle)
- goto update;
-
- cd = ccs_connect();
- if (cd < 0) {
- log_error("ccs_connect error %d %d", cd, errno);
- return -1;
- }
- ccs_handle = cd;
-
- /* plock_ownership is a special case */
- if (optd_plock_ownership)
- using_default_plock_ownership = 0;
- else
- using_default_plock_ownership = 1;
-
- /* These config values are set from cluster.conf only if they haven't
- already been set on the command line. */
-
- if (!optd_groupd_compat)
- read_ccs_int(GROUPD_COMPAT_PATH, &cfgd_groupd_compat);
- if (!optd_enable_withdraw)
- read_ccs_int(ENABLE_WITHDRAW_PATH, &cfgd_enable_withdraw);
- if (!optd_enable_plock)
- read_ccs_int(ENABLE_PLOCK_PATH, &cfgd_enable_plock);
- if (!optd_plock_ownership) {
- rv = read_ccs_int(PLOCK_OWNERSHIP_PATH, &cfgd_plock_ownership);
- if (rv < 0)
- rv = read_ccs_int(DLM_PLOCK_OWNERSHIP_PATH, &cfgd_plock_ownership);
- if (!rv)
- using_default_plock_ownership = 0;
- }
-
- /* The following can be changed while running */
- update:
- if (!optd_plock_debug) {
- read_ccs_int(PLOCK_DEBUG_PATH, &cfgd_plock_debug);
- }
- if (!optd_plock_rate_limit) {
- rv = read_ccs_int(PLOCK_RATE_LIMIT_PATH, &cfgd_plock_rate_limit);
- if (rv < 0)
- read_ccs_int(DLM_PLOCK_RATE_LIMIT_PATH, &cfgd_plock_rate_limit);
- }
- if (!optd_drop_resources_time) {
- rv = read_ccs_int(DROP_RESOURCES_TIME_PATH, &cfgd_drop_resources_time);
- if (rv < 0)
- read_ccs_int(DLM_DROP_RESOURCES_TIME_PATH, &cfgd_drop_resources_time);
- }
- if (!optd_drop_resources_count) {
- rv = read_ccs_int(DROP_RESOURCES_COUNT_PATH, &cfgd_drop_resources_count);
- if (rv < 0)
- read_ccs_int(DLM_DROP_RESOURCES_COUNT_PATH, &cfgd_drop_resources_count);
- }
- if (!optd_drop_resources_age) {
- rv = read_ccs_int(DROP_RESOURCES_AGE_PATH, &cfgd_drop_resources_age);
- if (rv < 0)
- read_ccs_int(DLM_DROP_RESOURCES_AGE_PATH, &cfgd_drop_resources_age);
- }
-
- return 0;
-}
-
-void close_ccs(void)
-{
- ccs_disconnect(ccs_handle);
-}
-
diff --git a/group/gfs_controld/config.h b/group/gfs_controld/config.h
deleted file mode 100644
index 1330c10..0000000
--- a/group/gfs_controld/config.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef __CONFIG_DOT_H__
-#define __CONFIG_DOT_H__
-
-#define DEFAULT_GROUPD_COMPAT 0
-#define DEFAULT_DEBUG_LOGFILE 0
-#define DEFAULT_ENABLE_WITHDRAW 1
-#define DEFAULT_ENABLE_PLOCK 1
-#define DEFAULT_PLOCK_DEBUG 0
-#define DEFAULT_PLOCK_RATE_LIMIT 0
-#define DEFAULT_PLOCK_OWNERSHIP 1
-#define DEFAULT_DROP_RESOURCES_TIME 10000 /* 10 sec */
-#define DEFAULT_DROP_RESOURCES_COUNT 10
-#define DEFAULT_DROP_RESOURCES_AGE 10000 /* 10 sec */
-
-extern int optd_groupd_compat;
-extern int optd_debug_logfile;
-extern int optd_enable_withdraw;
-extern int optd_enable_plock;
-extern int optd_plock_debug;
-extern int optd_plock_rate_limit;
-extern int optd_plock_ownership;
-extern int optd_drop_resources_time;
-extern int optd_drop_resources_count;
-extern int optd_drop_resources_age;
-
-extern int cfgd_groupd_compat;
-extern int cfgd_debug_logfile;
-extern int cfgd_enable_withdraw;
-extern int cfgd_enable_plock;
-extern int cfgd_plock_debug;
-extern int cfgd_plock_rate_limit;
-extern int cfgd_plock_ownership;
-extern int cfgd_drop_resources_time;
-extern int cfgd_drop_resources_count;
-extern int cfgd_drop_resources_age;
-
-#endif
-
diff --git a/group/gfs_controld/cpg-new.c b/group/gfs_controld/cpg-new.c
deleted file mode 100644
index b3f25ae..0000000
--- a/group/gfs_controld/cpg-new.c
+++ /dev/null
@@ -1,3643 +0,0 @@
-#include "gfs_daemon.h"
-#include "config.h"
-#include "libdlmcontrol.h"
-
-#define MAX_JOURNALS 256
-
-uint32_t cpgname_to_crc(const char *data, int len);
-
-/* gfs_header types */
-enum {
- GFS_MSG_PROTOCOL = 1,
- GFS_MSG_START = 2,
- GFS_MSG_MOUNT_DONE = 3,
- GFS_MSG_FIRST_RECOVERY_DONE = 4,
- GFS_MSG_RECOVERY_RESULT = 5,
- GFS_MSG_REMOUNT = 6,
- GFS_MSG_WITHDRAW = 7,
- GFS_MSG_WITHDRAW_ACK = 8,
-};
-
-/* gfs_header flags */
-#define GFS_MFLG_JOINING 1 /* accompanies start, we are joining */
-
-struct gfs_header {
- uint16_t version[3]; /* daemon_run protocol */
- uint16_t type; /* GFS_MSG_ */
- uint32_t nodeid; /* sender */
- uint32_t to_nodeid; /* recipient, 0 for all */
- uint32_t global_id; /* global unique id for this lockspace */
- uint32_t flags; /* GFS_MFLG_ */
- uint32_t msgdata; /* in-header payload depends on MSG type */
- uint32_t pad1;
- uint64_t pad2;
-};
-
-struct protocol_version {
- uint16_t major;
- uint16_t minor;
- uint16_t patch;
- uint16_t flags;
-};
-
-struct protocol {
- union {
- struct protocol_version dm_ver;
- uint16_t daemon_max[4];
- };
- union {
- struct protocol_version km_ver;
- uint16_t kernel_max[4];
- };
- union {
- struct protocol_version dr_ver;
- uint16_t daemon_run[4];
- };
- union {
- struct protocol_version kr_ver;
- uint16_t kernel_run[4];
- };
-};
-
-/* mg_info and id_info: for syncing state in start message */
-
-struct mg_info {
- uint32_t mg_info_size;
- uint32_t id_info_size;
- uint32_t id_info_count;
-
- uint32_t started_count;
-
- int member_count;
- int joined_count;
- int remove_count;
- int failed_count;
-
- int first_recovery_needed;
- int first_recovery_master;
-};
-
-#define IDI_NODEID_IS_MEMBER 0x00000001
-#define IDI_JID_NEEDS_RECOVERY 0x00000002
-#define IDI_MOUNT_DONE 0x00000008
-#define IDI_MOUNT_ERROR 0x00000010
-#define IDI_MOUNT_RO 0x00000020
-#define IDI_MOUNT_SPECTATOR 0x00000040
-
-struct id_info {
- int nodeid;
- int jid;
- uint32_t flags;
-};
-
-#define JID_NONE -1
-
-struct journal {
- struct list_head list;
- int jid;
- int nodeid;
- int failed_nodeid;
- int needs_recovery;
-
- int local_recovery_busy;
- int local_recovery_done;
- int local_recovery_result;
- int failed_recovery_count;
-};
-
-struct node {
- struct list_head list;
- int nodeid;
- int jid;
- int ro;
- int spectator;
- int kernel_mount_done;
- int kernel_mount_error;
-
- int check_dlm;
- int dlm_notify_callback;
- int dlm_notify_result;
-
- int failed_reason;
- uint32_t added_seq;
- uint32_t removed_seq;
- uint64_t add_time;
-
- int withdraw;
- int send_withdraw_ack;
-
- uint64_t cluster_add_time;
- uint64_t cluster_remove_time;
-
- struct protocol proto;
-};
-
-struct member {
- struct list_head list;
- int nodeid;
- int start; /* 1 if we received a start message for this change */
- int added; /* 1 if added by this change */
- int failed; /* 1 if failed in this change */
- int disallowed;
- char *start_msg; /* full copy of the start message from this node */
- struct mg_info *mg_info; /* shortcut into started_msg */
-};
-
-/* One of these change structs is created for every confchg a cpg gets. */
-
-#define CGST_WAIT_CONDITIONS 1
-#define CGST_WAIT_MESSAGES 2
-
-struct change {
- struct list_head list;
- struct list_head members;
- struct list_head removed; /* nodes removed by this change */
- struct list_head saved_messages; /* saved messages */
- int member_count;
- int joined_count;
- int remove_count;
- int failed_count;
- int state;
- int we_joined;
- uint32_t seq; /* used as a reference for debugging, and for queries */
- uint32_t combined_seq; /* for queries */
- uint64_t create_time;
-};
-
-struct save_msg {
- struct list_head list;
- int len;
- char buf[0];
-};
-
-static int dlmcontrol_fd;
-static int cpg_fd_daemon;
-static struct protocol our_protocol;
-static struct list_head daemon_nodes;
-static struct cpg_address daemon_member[MAX_NODES];
-static int daemon_member_count;
-
-/*
- cpg confchg's arrive telling us that mountgroup members have
- joined/left/failed. A "change" struct is created for each confchg,
- and added to the mg->changes list.
-
- apply_changes()
- ---------------
-
- <a new node won't know whether first_recovery_needed or not, but it also
- won't have any conditions to wait for, so a new node will go directly to
- sending out start message regardless>
-
- if first_recovery_needed,
- (or new, where new is not having completed a start barrier yet)
- all nodes: skip wait conditions
- all nodes: send start message
-
- else !first_recovery_needed,
- all nodes: if failures in changes, wait for conditions:
- local mount to complete if in progress, stop_kernel, dlm_notified
- all nodes: send start message
-
- <new changes that arrive result in going back to beginning; start messages
- from this aborted start cycle will be ignored>
-
- all nodes: wait for all start messages
-
- <once all start messages are received, new changes will be handled in a
- new batch after all current changes are cleared at end of sync_state>
-
- if start cycle / start barrier completes (start messages received from
- all nodes without being interrupted by a change), go on to sync_state
- which puts all members (as defined by the most recent change) in sync.
-
- "old nodes" are nodes that have completed a start cycle before (have
- a non-zero started_count), and "new nodes" are nodes that have not
- completed a start cycle before (they are being added by one of the
- changes in this start cycle)
-
- sync_state()
- ------------
-
- if old nodes have first_recovery_needed, or all nodes are new
- all nodes: mg->first_recovery_needed = 1
- all nodes: mg->first_recovery_master = prev or new low nodeid
- new nodes: instantiate existing state to match old nodes
- old nodes: update state per the changes in the completed start cycle
- all nodes: assign jids to new members
- all nodes: clear all change structs
-
- else !first_recovery_needed,
- new nodes: instantiate existing state to match old nodes
- old nodes: update state per the changes in the completed start cycle
- all nodes: assign jids to new members
- all nodes: clear all change structs
-
- <new changes that arrive from here on result in going back to the top>
-
- apply_recovery()
- ----------------
-
- if first_recovery_needed,
- master: tells mount to run with first=1 (if not already)
- all nodes: wait for first_recovery_done message
- master: sends first_recovery_done message when mount is done
- all nodes: mg->first_recovery_needed = 0
- all nodes: start kernel / tell mount.gfs to mount(2) (master already did)
- all nodes: send message with result of kernel mount
-
- else !first_recovery_needed,
- all nodes: if there are no journals to recover, goto start kernel
- old nodes: tell kernel to recover jids, send message with each result
- all nodes: wait for all recoveries to be done
- all nodes: start kernel
- new nodes: tell mount.gfs to mount(2)
- new nodes: send message with result of kernel mount
-
- [If no one can recover some journal(s), all will be left waiting, unstarted.
- A new change from a new mount will result in things going back to the top,
- and hopefully the new node will be successful at doing the journal
- recoveries when it comes through the apply_recovery() section, which
- would let everyone start again.]
-*/
-
-static void apply_changes_recovery(struct mountgroup *mg);
-static void send_withdraw_acks(struct mountgroup *mg);
-static void leave_mountgroup(struct mountgroup *mg, int mnterr);
-
-static void log_config(const struct cpg_name *group_name,
- const struct cpg_address *member_list,
- size_t member_list_entries,
- const struct cpg_address *left_list,
- size_t left_list_entries,
- const struct cpg_address *joined_list,
- size_t joined_list_entries)
-{
- char m_buf[128];
- char j_buf[32];
- char l_buf[32];
- size_t i, len, pos;
- int ret;
-
- memset(m_buf, 0, sizeof(m_buf));
- memset(j_buf, 0, sizeof(j_buf));
- memset(l_buf, 0, sizeof(l_buf));
-
- len = sizeof(m_buf);
- pos = 0;
- for (i = 0; i < member_list_entries; i++) {
- ret = snprintf(m_buf + pos, len - pos, " %d",
- member_list[i].nodeid);
- if (ret >= len - pos)
- break;
- pos += ret;
- }
-
- len = sizeof(j_buf);
- pos = 0;
- for (i = 0; i < joined_list_entries; i++) {
- ret = snprintf(j_buf + pos, len - pos, " %d",
- joined_list[i].nodeid);
- if (ret >= len - pos)
- break;
- pos += ret;
- }
-
- len = sizeof(l_buf);
- pos = 0;
- for (i = 0; i < left_list_entries; i++) {
- ret = snprintf(l_buf + pos, len - pos, " %d",
- left_list[i].nodeid);
- if (ret >= len - pos)
- break;
- pos += ret;
- }
-
- log_debug("%s conf %zu %zu %zu memb%s join%s left%s", group_name->value,
- member_list_entries, joined_list_entries, left_list_entries,
- m_buf, j_buf, l_buf);
-}
-
-static const char *msg_name(int type)
-{
- switch (type) {
- case GFS_MSG_PROTOCOL:
- return "protocol";
- case GFS_MSG_START:
- return "start";
- case GFS_MSG_MOUNT_DONE:
- return "mount_done";
- case GFS_MSG_FIRST_RECOVERY_DONE:
- return "first_recovery_done";
- case GFS_MSG_RECOVERY_RESULT:
- return "recovery_result";
- case GFS_MSG_REMOUNT:
- return "remount";
- case GFS_MSG_WITHDRAW:
- return "withdraw";
- case GFS_MSG_WITHDRAW_ACK:
- return "withdraw_ack";
- default:
- return "unknown";
- }
-}
-
-static int _send_message(cpg_handle_t h, void *buf, int len, int type)
-{
- struct iovec iov;
- cpg_error_t error;
- int retries = 0;
-
- iov.iov_base = buf;
- iov.iov_len = len;
-
- retry:
- error = cpg_mcast_joined(h, CPG_TYPE_AGREED, &iov, 1);
- if (error == CPG_ERR_TRY_AGAIN) {
- retries++;
- usleep(1000);
- if (!(retries % 100))
- log_error("cpg_mcast_joined retry %d %s",
- retries, msg_name(type));
- goto retry;
- }
- if (error != CPG_OK) {
- log_error("cpg_mcast_joined error %d handle %llx %s",
- error, (unsigned long long)h, msg_name(type));
- return -1;
- }
-
- if (retries)
- log_debug("cpg_mcast_joined retried %d %s",
- retries, msg_name(type));
-
- return 0;
-}
-
-/* header fields caller needs to set: type, to_nodeid, flags, msgdata */
-
-static void gfs_send_message(struct mountgroup *mg, char *buf, int len)
-{
- struct gfs_header *hd = (struct gfs_header *) buf;
- int type = hd->type;
-
- hd->version[0] = cpu_to_le16(our_protocol.daemon_run[0]);
- hd->version[1] = cpu_to_le16(our_protocol.daemon_run[1]);
- hd->version[2] = cpu_to_le16(our_protocol.daemon_run[2]);
- hd->type = cpu_to_le16(hd->type);
- hd->nodeid = cpu_to_le32(our_nodeid);
- hd->to_nodeid = cpu_to_le32(hd->to_nodeid);
- hd->global_id = cpu_to_le32(mg->id);
- hd->flags = cpu_to_le32(hd->flags);
- hd->msgdata = cpu_to_le32(hd->msgdata);
-
- _send_message(mg->cpg_handle, buf, len, type);
-}
-
-static struct member *find_memb(struct change *cg, int nodeid)
-{
- struct member *memb;
-
- list_for_each_entry(memb, &cg->members, list) {
- if (memb->nodeid == nodeid)
- return memb;
- }
- return NULL;
-}
-
-static struct mountgroup *find_mg_handle(cpg_handle_t h)
-{
- struct mountgroup *mg;
-
- list_for_each_entry(mg, &mountgroups, list) {
- if (mg->cpg_handle == h)
- return mg;
- }
- return NULL;
-}
-
-static struct mountgroup *find_mg_ci(int ci)
-{
- struct mountgroup *mg;
-
- list_for_each_entry(mg, &mountgroups, list) {
- if (mg->cpg_client == ci)
- return mg;
- }
- return NULL;
-}
-
-static struct journal *find_journal(struct mountgroup *mg, int jid)
-{
- struct journal *j;
-
- list_for_each_entry(j, &mg->journals, list) {
- if (j->jid == jid)
- return j;
- }
- return NULL;
-}
-
-static struct journal *find_journal_by_nodeid(struct mountgroup *mg, int nodeid)
-{
- struct journal *j;
-
- list_for_each_entry(j, &mg->journals, list) {
- if (j->nodeid == nodeid)
- return j;
- }
- return NULL;
-}
-
-static void free_cg(struct change *cg)
-{
- struct member *memb, *safe;
- struct save_msg *sm, *sm2;
-
- list_for_each_entry_safe(memb, safe, &cg->members, list) {
- list_del(&memb->list);
- if (memb->start_msg)
- free(memb->start_msg);
- free(memb);
- }
- list_for_each_entry_safe(memb, safe, &cg->removed, list) {
- list_del(&memb->list);
- if (memb->start_msg)
- free(memb->start_msg);
- free(memb);
- }
- list_for_each_entry_safe(sm, sm2, &cg->saved_messages, list) {
- list_del(&sm->list);
- free(sm);
- }
- free(cg);
-}
-
-void free_mg(struct mountgroup *mg)
-{
- struct change *cg, *cg_safe;
- struct node *node, *node_safe;
-
- list_for_each_entry_safe(cg, cg_safe, &mg->changes, list) {
- list_del(&cg->list);
- free_cg(cg);
- }
-
- if (mg->started_change)
- free_cg(mg->started_change);
-
- list_for_each_entry_safe(node, node_safe, &mg->node_history, list) {
- list_del(&node->list);
- free(node);
- }
-
- free(mg);
-}
-
-static struct node *get_node_history(struct mountgroup *mg, int nodeid)
-{
- struct node *node;
-
- list_for_each_entry(node, &mg->node_history, list) {
- if (node->nodeid == nodeid)
- return node;
- }
- return NULL;
-}
-
-static void node_history_init(struct mountgroup *mg, int nodeid,
- struct change *cg)
-{
- struct node *node;
-
- node = get_node_history(mg, nodeid);
- if (node) {
- list_del(&node->list);
- goto out;
- }
-
- node = malloc(sizeof(struct node));
- if (!node) {
- log_error("node_history_init no mem");
- return;
- }
- out:
- memset(node, 0, sizeof(struct node));
-
- node->nodeid = nodeid;
- node->add_time = 0;
- list_add_tail(&node->list, &mg->node_history);
-
- if (cg)
- node->added_seq = cg->seq; /* for queries */
-}
-
-void node_history_cluster_add(int nodeid)
-{
- struct mountgroup *mg;
- struct node *node;
-
- list_for_each_entry(mg, &mountgroups, list) {
- node_history_init(mg, nodeid, NULL);
-
- node = get_node_history(mg, nodeid);
- if (!node) {
- log_error("node_history_cluster_add no nodeid %d",
- nodeid);
- return;
- }
-
- node->cluster_add_time = time(NULL);
- }
-}
-
-void node_history_cluster_remove(int nodeid)
-{
- struct mountgroup *mg;
- struct node *node;
-
- list_for_each_entry(mg, &mountgroups, list) {
- node = get_node_history(mg, nodeid);
- if (!node) {
- log_error("node_history_cluster_remove no nodeid %d",
- nodeid);
- return;
- }
-
- node->cluster_remove_time = time(NULL);
- }
-}
-
-static void node_history_start(struct mountgroup *mg, int nodeid)
-{
- struct node *node;
-
- node = get_node_history(mg, nodeid);
- if (!node) {
- log_error("node_history_start no nodeid %d", nodeid);
- return;
- }
-
- node->add_time = time(NULL);
-}
-
-static void node_history_left(struct mountgroup *mg, int nodeid,
- struct change *cg)
-{
- struct node *node;
-
- node = get_node_history(mg, nodeid);
- if (!node) {
- log_error("node_history_left no nodeid %d", nodeid);
- return;
- }
-
- node->add_time = 0;
- node->removed_seq = cg->seq; /* for queries */
-}
-
-static void node_history_fail(struct mountgroup *mg, int nodeid,
- struct change *cg, int reason)
-{
- struct node *node;
-
- node = get_node_history(mg, nodeid);
- if (!node) {
- log_error("node_history_fail no nodeid %d", nodeid);
- return;
- }
-
- node->check_dlm = 1;
-
- node->removed_seq = cg->seq; /* for queries */
- node->failed_reason = reason; /* for queries */
-}
-
-static int is_added(struct mountgroup *mg, int nodeid)
-{
- struct change *cg;
- struct member *memb;
-
- list_for_each_entry(cg, &mg->changes, list) {
- memb = find_memb(cg, nodeid);
- if (memb && memb->added)
- return 1;
- }
- return 0;
-}
-
-static int is_withdraw(struct mountgroup *mg, int nodeid)
-{
- struct node *node;
-
- node = get_node_history(mg, nodeid);
- if (!node) {
- log_error("is_withdraw no nodeid %d", nodeid);
- return 0;
- }
- return node->withdraw;
-}
-
-static int journals_need_recovery(struct mountgroup *mg)
-{
- struct change *cg;
- struct journal *j;
- struct member *memb;
- int count = 0;
-
- list_for_each_entry(j, &mg->journals, list)
- if (j->needs_recovery)
- count++;
-
- list_for_each_entry(cg, &mg->changes, list) {
- list_for_each_entry(memb, &cg->removed, list) {
- if (!memb->failed && !is_withdraw(mg, memb->nodeid))
- continue;
- /* check whether this node had a journal assigned? */
- count++;
- }
- }
-
- return count;
-}
-
-/* find a start message from an old node to use; it doesn't matter which old
- node we take the start message from, they should all be the same */
-
-static int get_id_list(struct mountgroup *mg, struct id_info **ids,
- int *count, int *size)
-{
- struct change *cg;
- struct member *memb;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- list_for_each_entry(memb, &cg->members, list) {
- if (!memb->mg_info->started_count)
- continue;
-
- *count = memb->mg_info->id_info_count;
- *size = memb->mg_info->id_info_size;
- *ids = (struct id_info *)(memb->start_msg +
- sizeof(struct gfs_header) +
- memb->mg_info->mg_info_size);
- return 0;
- }
- return -1;
-}
-
-static struct id_info *get_id_struct(struct id_info *ids, int count, int size,
- int nodeid)
-{
- struct id_info *id = ids;
- int i;
-
- for (i = 0; i < count; i++) {
- if (id->nodeid == nodeid)
- return id;
- id = (struct id_info *)((char *)id + size);
- }
- return NULL;
-}
-
-static void start_kernel(struct mountgroup *mg)
-{
- struct change *cg = mg->started_change;
-
- if (!mg->kernel_stopped) {
- log_error("start_kernel cg %u not stopped", cg->seq);
- return;
- }
-
- log_group(mg, "start_kernel cg %u member_count %d",
- cg->seq, cg->member_count);
-
- set_sysfs(mg, "block", 0);
- mg->kernel_stopped = 0;
-
- if (mg->joining) {
- client_reply_join_full(mg, 0);
- mg->joining = 0;
- mg->mount_client_notified = 1;
- }
-}
-
-static void stop_kernel(struct mountgroup *mg)
-{
- if (!mg->kernel_stopped) {
- log_group(mg, "stop_kernel");
- set_sysfs(mg, "block", 1);
- mg->kernel_stopped = 1;
- }
-}
-
-void process_dlmcontrol(int ci)
-{
- struct mountgroup *mg;
- struct node *node;
- char name[GFS_MOUNTGROUP_LEN+1];
- int rv, type, nodeid, result;
-
- memset(name, 0, sizeof(name));
-
- rv = dlmc_fs_result(dlmcontrol_fd, name, &type, &nodeid, &result);
- if (rv) {
- log_error("process_dlmcontrol dlmc_fs_result %d", rv);
- return;
- }
-
- mg = find_mg(name);
- if (!mg) {
- log_error("process_dlmcontrol no mg %s", name);
- return;
- }
-
- if (type == DLMC_RESULT_NOTIFIED) {
- log_group(mg, "process_dlmcontrol notified nodeid %d result %d",
- nodeid, result);
-
- node = get_node_history(mg, nodeid);
- if (!node) {
- /* shouldn't happen */
- log_error("process_dlmcontrol no nodeid %d", nodeid);
- return;
- }
-
- if (mg->dlm_notify_nodeid != nodeid) {
- /* shouldn't happen */
- log_error("process_dlmcontrol node %d expected %d",
- nodeid, mg->dlm_notify_nodeid);
- return;
- }
-
- mg->dlm_notify_nodeid = 0;
- node->dlm_notify_callback = 1;
- node->dlm_notify_result = result;
-
- } else if (type == DLMC_RESULT_REGISTER) {
- if (result) {
- /* shouldn't happen */
- log_error("process_dlmcontrol register %d", result);
- } else
- log_group(mg, "process_dlmcontrol register %d", result);
-
- mg->dlm_registered = 1;
-
- } else {
- log_group(mg, "process_dlmcontrol unknown type %d", type);
- }
-
- poll_dlm = 0;
-
- apply_changes_recovery(mg);
-}
-
-static int check_dlm_notify_done(struct mountgroup *mg)
-{
- struct node *node;
- int rv;
-
- /* we're waiting for a notify result from the dlm (could we fire off
- all dlmc_fs_notified() calls at once instead of serially?) */
-
- if (mg->dlm_notify_nodeid)
- return 0;
-
- list_for_each_entry(node, &mg->node_history, list) {
-
- /* check_dlm is set when we see a node fail, and is cleared
- below when we find that the dlm has also seen it fail */
-
- if (!node->check_dlm)
- continue;
-
- /* we're in sync with the dlm for this nodeid, i.e. we've
- both seen this node fail */
-
- if (node->dlm_notify_callback && !node->dlm_notify_result) {
- node->dlm_notify_callback = 0;
- node->check_dlm = 0;
- continue;
- }
-
- /* we're not in sync with the dlm for this nodeid, i.e.
- the dlm hasn't seen this node fail yet; try calling
- dlmc_fs_notified() again in a bit */
-
- if (node->dlm_notify_callback && node->dlm_notify_result) {
- log_group(mg, "check_dlm_notify result %d will retry nodeid %d",
- node->dlm_notify_result, node->nodeid);
- node->dlm_notify_callback = 0;
- poll_dlm = 1;
- return 0;
- }
-
- /* check if the dlm has seen this nodeid fail, we get the
- answer asynchronously in process_dlmcontrol */
-
- log_group(mg, "check_dlm_notify nodeid %d begin", node->nodeid);
-
- rv = dlmc_fs_notified(dlmcontrol_fd, mg->name, node->nodeid);
- if (rv) {
- log_error("dlmc_fs_notified error %d", rv);
- return 0;
- }
-
- mg->dlm_notify_nodeid = node->nodeid;
- return 0;
- }
-
- log_group(mg, "check_dlm_notify done");
- return 1;
-}
-
-static int wait_conditions_done(struct mountgroup *mg)
-{
- if (!mg->dlm_registered) {
- log_group(mg, "wait_conditions need dlm register");
- return 0;
- }
-
- if (mg->first_recovery_needed) {
- log_group(mg, "wait_conditions skip for first_recovery_needed");
- return 1;
- }
-
- if (!mg->started_count) {
- log_group(mg, "wait_conditions skip for zero started_count");
- return 1;
- }
-
- if (!journals_need_recovery(mg)) {
- log_group(mg, "wait_conditions skip for zero "
- "journals_need_recovery");
- return 1;
- }
-
- if (!mg->mount_client_notified) {
- log_group(mg, "wait_conditions skip mount client not notified");
- return 1;
- }
-
- if (mg->kernel_mount_done && mg->kernel_mount_error) {
- log_group(mg, "wait_conditions skip for kernel_mount_error");
- return 1;
- }
-
- if (!mg->kernel_mount_done) {
- log_group(mg, "wait_conditions need mount_done");
- return 0;
- }
-
- stop_kernel(mg);
-
- if (!check_dlm_notify_done(mg))
- return 0;
-
- return 1;
-}
-
-static int wait_messages_done(struct mountgroup *mg)
-{
- struct change *cg = list_first_entry(&mg->changes, struct change, list);
- struct member *memb;
- int need = 0, total = 0;
-
- list_for_each_entry(memb, &cg->members, list) {
- if (!memb->start)
- need++;
- total++;
- }
-
- if (need) {
- log_group(mg, "wait_messages cg %u need %d of %d",
- cg->seq, need, total);
- return 0;
- }
-
- log_group(mg, "wait_messages cg %u got all %d", cg->seq, total);
- return 1;
-}
-
-static void cleanup_changes(struct mountgroup *mg)
-{
- struct change *cg = list_first_entry(&mg->changes, struct change, list);
- struct change *safe;
-
- list_del(&cg->list);
- if (mg->started_change)
- free_cg(mg->started_change);
- mg->started_change = cg;
-
- /* zero started_count means "never started" */
-
- mg->started_count++;
- if (!mg->started_count)
- mg->started_count++;
-
- cg->combined_seq = cg->seq; /* for queries */
-
- list_for_each_entry_safe(cg, safe, &mg->changes, list) {
- mg->started_change->combined_seq = cg->seq; /* for queries */
- list_del(&cg->list);
- free_cg(cg);
- }
-}
-
-/* do the change details in the message match the details of the given change */
-
-static int match_change(struct mountgroup *mg, struct change *cg,
- struct gfs_header *hd, struct mg_info *mi,
- struct id_info *ids)
-{
- struct id_info *id;
- struct member *memb;
- struct node *node;
- uint32_t seq = hd->msgdata;
- int i, members_mismatch;
-
- /* We can ignore messages if we're not in the list of members.
- The one known time this will happen is after we've joined
- the cpg, we can get messages for changes prior to the change
- in which we're added. */
-
- id = get_id_struct(ids, mi->id_info_count, mi->id_info_size,our_nodeid);
-
- if (!id || !(id->flags & IDI_NODEID_IS_MEMBER)) {
- log_group(mg, "match_change %d:%u skip cg %u we are not in members",
- hd->nodeid, seq, cg->seq);
- return 0;
- }
-
- memb = find_memb(cg, hd->nodeid);
- if (!memb) {
- log_group(mg, "match_change %d:%u skip cg %u sender not member",
- hd->nodeid, seq, cg->seq);
- return 0;
- }
-
- if (memb->start && hd->type == GFS_MSG_START) {
- log_group(mg, "match_change %d:%u skip %u already start",
- hd->nodeid, seq, cg->seq);
- return 0;
- }
-
- /* a node's start can't match a change if the node joined the cluster
- more recently than the change was created */
-
- node = get_node_history(mg, hd->nodeid);
- if (!node) {
- log_group(mg, "match_change %d:%u skip cg %u no node history",
- hd->nodeid, seq, cg->seq);
- return 0;
- }
-
- if (node->cluster_add_time > cg->create_time) {
- log_group(mg, "match_change %d:%u skip cg %u created %llu "
- "cluster add %llu", hd->nodeid, seq, cg->seq,
- (unsigned long long)cg->create_time,
- (unsigned long long)node->cluster_add_time);
- return 0;
- }
-
- /* verify this is the right change by matching the counts
- and the nodeids of the current members */
-
- if (mi->member_count != cg->member_count ||
- mi->joined_count != cg->joined_count ||
- mi->remove_count != cg->remove_count ||
- mi->failed_count != cg->failed_count) {
- log_group(mg, "match_change %d:%u skip cg %u expect counts "
- "%d %d %d %d", hd->nodeid, seq, cg->seq,
- cg->member_count, cg->joined_count,
- cg->remove_count, cg->failed_count);
- return 0;
- }
-
- members_mismatch = 0;
- id = ids;
-
- for (i = 0; i < mi->id_info_count; i++) {
- if (id->flags & IDI_NODEID_IS_MEMBER) {
- memb = find_memb(cg, id->nodeid);
- if (!memb) {
- log_group(mg, "match_change %d:%u skip cg %u "
- "no memb %d", hd->nodeid, seq,
- cg->seq, id->nodeid);
- members_mismatch = 1;
- break;
- }
- }
- id = (struct id_info *)((char *)id + mi->id_info_size);
- }
-
- if (members_mismatch)
- return 0;
-
- log_group(mg, "match_change %d:%u matches cg %u", hd->nodeid, seq,
- cg->seq);
- return 1;
-}
-
-/* Unfortunately, there's no really simple way to match a message with the
- specific change that it was sent for. We hope that by passing all the
- details of the change in the message, we will be able to uniquely match
- it to the correct change. */
-
-/* A start message will usually be for the first (current) change on our list.
- In some cases it will be for a non-current change, and we can ignore it:
-
- 1. A,B,C get confchg1 adding C
- 2. C sends start for confchg1
- 3. A,B,C get confchg2 adding D
- 4. A,B,C,D recv start from C for confchg1 - ignored
- 5. C,D send start for confchg2
- 6. A,B send start for confchg2
- 7. A,B,C,D recv all start messages for confchg2; start barrier/cycle done
-
- In step 4, how do the nodes know whether the start message from C is
- for confchg1 or confchg2? Hopefully by comparing the counts and members. */
-
-static struct change *find_change(struct mountgroup *mg, struct gfs_header *hd,
- struct mg_info *mi, struct id_info *ids)
-{
- struct change *cg;
-
- list_for_each_entry_reverse(cg, &mg->changes, list) {
- if (!match_change(mg, cg, hd, mi, ids))
- continue;
- return cg;
- }
-
- log_group(mg, "find_change %d:%u no match", hd->nodeid, hd->msgdata);
- return NULL;
-}
-
-static void mg_info_in(struct mg_info *mi)
-{
- mi->mg_info_size = le32_to_cpu(mi->mg_info_size);
- mi->id_info_size = le32_to_cpu(mi->id_info_size);
- mi->id_info_count = le32_to_cpu(mi->id_info_count);
- mi->started_count = le32_to_cpu(mi->started_count);
- mi->member_count = le32_to_cpu(mi->member_count);
- mi->joined_count = le32_to_cpu(mi->joined_count);
- mi->remove_count = le32_to_cpu(mi->remove_count);
- mi->failed_count = le32_to_cpu(mi->failed_count);
- mi->first_recovery_needed = le32_to_cpu(mi->first_recovery_needed);
- mi->first_recovery_master = le32_to_cpu(mi->first_recovery_master);
-}
-
-static void id_info_in(struct id_info *id)
-{
- id->nodeid = le32_to_cpu(id->nodeid);
- id->jid = le32_to_cpu(id->jid);
- id->flags = le32_to_cpu(id->flags);
-}
-
-static void ids_in(struct mg_info *mi, struct id_info *ids)
-{
- struct id_info *id;
- int i;
-
- id = ids;
- for (i = 0; i < mi->id_info_count; i++) {
- id_info_in(id);
- id = (struct id_info *)((char *)id + mi->id_info_size);
- }
-}
-
-static void receive_start(struct mountgroup *mg, struct gfs_header *hd, int len)
-{
- struct change *cg;
- struct member *memb;
- struct mg_info *mi;
- struct id_info *ids;
- uint32_t seq = hd->msgdata;
- int added;
-
- log_group(mg, "receive_start %d:%u len %d", hd->nodeid, seq, len);
-
- mi = (struct mg_info *)((char *)hd + sizeof(struct gfs_header));
- ids = (struct id_info *)((char *)mi + sizeof(struct mg_info));
-
- mg_info_in(mi);
- ids_in(mi, ids);
-
- cg = find_change(mg, hd, mi, ids);
- if (!cg)
- return;
-
- memb = find_memb(cg, hd->nodeid);
- if (!memb) {
- /* this should never happen since match_change checks it */
- log_error("receive_start no member %d", hd->nodeid);
- return;
- }
-
- added = is_added(mg, hd->nodeid);
-
- if (added && mi->started_count && mg->started_count) {
- log_error("receive_start %d:%u add node with started_count %u",
- hd->nodeid, seq, mi->started_count);
-
- /* see comment in fence/fenced/cpg.c */
- memb->disallowed = 1;
- return;
- }
-
- node_history_start(mg, hd->nodeid);
- memb->start = 1;
-
- if (memb->start_msg) {
- /* shouldn't happen */
- log_error("receive_start %d:%u dup start msg", hd->nodeid, seq);
- return;
- }
-
- /* save a copy of each start message */
- memb->start_msg = malloc(len);
- if (!memb->start_msg) {
- log_error("receive_start len %d no mem", len);
- return;
- }
- memcpy(memb->start_msg, hd, len);
-
- /* a shortcut to the saved mg_info */
- memb->mg_info = (struct mg_info *)(memb->start_msg +
- sizeof(struct gfs_header));
-}
-
-/* start messages are associated with a specific change and use the
- find_change/match_change routines to make sure all start messages
- are matched with the same change on all nodes. The current set of
- changes are cleared after a completed start cycle. Other messages
- happen outside the context of changes. An "incomplete" start cycle
- is when a confchg arrives (adding a new change struct) before all
- start messages have been received for the current change. In this
- case, all members send a new start message for the latest change,
- and any start messages received for the previous change(s) are ignored.
-
- To sync state with start messages, we need to include:
- - the state before applying any of the current set of queued changes
- (new nodes will initialize with this)
- - the essential info from changes in the set that's being started,
- so nodes added by one of the queued changes can apply the same changes
- to the init state that the existing nodes do. */
-
-/* recovery_result and mount_done messages may arrive between the time
- that an old node sends start and the time a new node receives it.
- two old nodes may also send start before/after a recovery_result or
- mount_done message, creating inconsistent data in their start messages.
-
- Soln: a new node saves recovery_result/mount_done messages between
- last confchg and final start. the new node knows that a start message
- from an old node may or may not include the effects from rr/md messages
- since the last confchg, but *will* include all effects from prior to
- the last confchg. The saved rr/md messages can be applied on top of
- the state from an old node's start message; applying them a second time
- should not change anything, producing the same result. */
-
-static int count_ids(struct mountgroup *mg)
-{
- struct change *cg;
- struct member *memb;
- struct journal *j;
- int count = 0;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- list_for_each_entry(memb, &cg->members, list)
- count++;
-
- list_for_each_entry(j, &mg->journals, list)
- if (j->needs_recovery)
- count++;
-
- list_for_each_entry(cg, &mg->changes, list) {
- list_for_each_entry(memb, &cg->removed, list) {
- if (!memb->failed && !is_withdraw(mg, memb->nodeid))
- continue;
- j = find_journal_by_nodeid(mg, memb->nodeid);
- if (j)
- count++;
- }
- }
-
- return count;
-}
-
-/* old member: current member that has completed a start cycle
- new member: current member that has not yet completed a start cycle */
-
-static void send_start(struct mountgroup *mg)
-{
- struct change *cg, *c;
- struct gfs_header *hd;
- struct mg_info *mi;
- struct id_info *id;
- struct member *memb;
- struct node *node;
- struct journal *j;
- char *buf;
- uint32_t flags;
- int len, id_count, jid;
- int old_memb = 0, new_memb = 0, old_journal = 0, new_journal = 0;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- id_count = count_ids(mg);
-
- /* sanity check */
-
- if (!mg->started_count && id_count != cg->member_count) {
- log_error("send_start bad counts id_count %d member_count %d",
- cg->member_count, id_count);
- return;
- }
-
- len = sizeof(struct gfs_header) + sizeof(struct mg_info) +
- id_count * sizeof(struct id_info);
-
- buf = malloc(len);
- if (!buf) {
- log_error("send_start len %d no mem", len);
- return;
- }
- memset(buf, 0, len);
-
- hd = (struct gfs_header *)buf;
- mi = (struct mg_info *)(buf + sizeof(*hd));
- id = (struct id_info *)(buf + sizeof(*hd) + sizeof(*mi));
-
- /* fill in header (gfs_send_message handles part of header) */
-
- hd->type = GFS_MSG_START;
- hd->msgdata = cg->seq;
- hd->flags |= mg->joining ? GFS_MFLG_JOINING : 0;
-
- /* fill in mg_info */
-
- mi->mg_info_size = cpu_to_le32(sizeof(struct mg_info));
- mi->id_info_size = cpu_to_le32(sizeof(struct id_info));
- mi->id_info_count = cpu_to_le32(id_count);
- mi->started_count = cpu_to_le32(mg->started_count);
- mi->member_count = cpu_to_le32(cg->member_count);
- mi->joined_count = cpu_to_le32(cg->joined_count);
- mi->remove_count = cpu_to_le32(cg->remove_count);
- mi->failed_count = cpu_to_le32(cg->failed_count);
- mi->first_recovery_needed = cpu_to_le32(mg->first_recovery_needed);
- mi->first_recovery_master = cpu_to_le32(mg->first_recovery_master);
-
- /* fill in id_info entries */
-
- /* New members send info about themselves, and empty id_info slots for
- all other members. Old members send full info about all old
- members, and empty id_info slots about new members. The union of
- start messages from a single old node and all new nodes give a
- complete picture of state for all members. In sync_state, all nodes
- (old and new) make this union, and then assign jid's to new nodes. */
-
- list_for_each_entry(memb, &cg->members, list) {
-
- if (!mg->started_count || is_added(mg, memb->nodeid)) {
- /* send empty slot for new member */
- jid = JID_NONE;
- flags = IDI_NODEID_IS_MEMBER;
-
- /* include our own info which no one knows yet */
- if (!mg->started_count && memb->nodeid == our_nodeid) {
- flags |= mg->ro ? IDI_MOUNT_RO : 0;
- flags |= mg->spectator ? IDI_MOUNT_SPECTATOR : 0;
- }
- new_memb++;
-
- } else {
- /* send full info for old member */
- node = get_node_history(mg, memb->nodeid);
- if (!node) {
- log_error("send_start no nodeid %d", memb->nodeid);
- continue;
- }
-
- jid = node->jid;
- flags = IDI_NODEID_IS_MEMBER;
- flags |= node->ro ? IDI_MOUNT_RO : 0;
- flags |= node->spectator ? IDI_MOUNT_SPECTATOR : 0;
- flags |= node->kernel_mount_done ? IDI_MOUNT_DONE : 0;
- flags |= node->kernel_mount_error ? IDI_MOUNT_ERROR : 0;
- old_memb++;
- }
-
- id->nodeid = cpu_to_le32(memb->nodeid);
- id->jid = cpu_to_le32(jid);
- id->flags = cpu_to_le32(flags);
- id++;
- }
-
- /* journals needing recovery from previous start cycles */
-
- list_for_each_entry(j, &mg->journals, list) {
- if (j->needs_recovery) {
- flags = IDI_JID_NEEDS_RECOVERY;
- id->jid = cpu_to_le32(j->jid);
- id->flags = cpu_to_le32(flags);
- id++;
- old_journal++;
- }
- }
-
- /* journals needing recovery from the current start cycle */
-
- list_for_each_entry(c, &mg->changes, list) {
- list_for_each_entry(memb, &c->removed, list) {
- if (!memb->failed && !is_withdraw(mg, memb->nodeid))
- continue;
- j = find_journal_by_nodeid(mg, memb->nodeid);
- if (j) {
- flags = IDI_JID_NEEDS_RECOVERY;
- id->jid = cpu_to_le32(j->jid);
- id->flags = cpu_to_le32(flags);
- id++;
- new_journal++;
- }
- }
- }
-
- /* sanity check */
-
- if (!mg->started_count && (old_memb || old_journal || new_journal)) {
- log_error("send_start cg %u bad counts om %d nm %d oj %d nj %d",
- cg->seq, old_memb, new_memb, old_journal, new_journal);
- return;
- }
-
- log_group(mg, "send_start cg %u id_count %d om %d nm %d oj %d nj %d",
- cg->seq, id_count, old_memb, new_memb, old_journal,
- new_journal);
-
- gfs_send_message(mg, buf, len);
-
- free(buf);
-}
-
-static void send_mount_done(struct mountgroup *mg, int result)
-{
- struct gfs_header h;
-
- memset(&h, 0, sizeof(h));
-
- h.type = GFS_MSG_MOUNT_DONE;
- h.msgdata = result;
-
- gfs_send_message(mg, (char *)&h, sizeof(h));
-}
-
-static void send_first_recovery_done(struct mountgroup *mg)
-{
- struct gfs_header h;
-
- memset(&h, 0, sizeof(h));
-
- h.type = GFS_MSG_FIRST_RECOVERY_DONE;
-
- gfs_send_message(mg, (char *)&h, sizeof(h));
-}
-
-static void send_recovery_result(struct mountgroup *mg, int jid, int result)
-{
- struct gfs_header *hd;
- char *buf;
- int len, *p;
-
- len = sizeof(struct gfs_header) + 2 * sizeof(int);
-
- buf = malloc(len);
- if (!buf) {
- log_error("send_recovery_result no mem %d", len);
- return;
- }
- memset(buf, 0, len);
-
- hd = (struct gfs_header *)buf;
- hd->type = GFS_MSG_RECOVERY_RESULT;
-
- p = (int *)(buf + sizeof(struct gfs_header));
-
- p[0] = cpu_to_le32(jid);
- p[1] = cpu_to_le32(result);
-
- gfs_send_message(mg, buf, len);
-
- free(buf);
-}
-
-void send_remount(struct mountgroup *mg, struct gfsc_mount_args *ma)
-{
- struct gfs_header h;
-
- memset(&h, 0, sizeof(h));
-
- h.type = GFS_MSG_REMOUNT;
- h.msgdata = strstr(ma->options, "ro") ? 1 : 0;
-
- gfs_send_message(mg, (char *)&h, sizeof(h));
-}
-
-void send_withdraw(struct mountgroup *mg)
-{
- struct gfs_header h;
-
- memset(&h, 0, sizeof(h));
-
- h.type = GFS_MSG_WITHDRAW;
-
- gfs_send_message(mg, (char *)&h, sizeof(h));
-}
-
-static void save_message(struct mountgroup *mg, struct gfs_header *hd, int len)
-{
- struct change *cg;
- struct save_msg *sm;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- sm = malloc(sizeof(struct save_msg) + len);
- if (!sm) {
- log_error("save_message len %d no mem", len);
- return;
- }
-
- sm->len = len;
- memcpy(sm->buf, hd, len);
-
- list_add_tail(&sm->list, &cg->saved_messages);
-}
-
-void gfs_mount_done(struct mountgroup *mg)
-{
- send_mount_done(mg, mg->kernel_mount_error);
-}
-
-static void receive_mount_done(struct mountgroup *mg, struct gfs_header *hd,
- int len)
-{
- struct node *node;
-
- log_group(mg, "receive_mount_done from %d result %d",
- hd->nodeid, hd->msgdata);
-
- node = get_node_history(mg, hd->nodeid);
- if (!node) {
- log_error("receive_mount_done no nodeid %d", hd->nodeid);
- return;
- }
-
- node->kernel_mount_done = 1;
- node->kernel_mount_error = hd->msgdata;
-}
-
-static void receive_recovery_result(struct mountgroup *mg,
- struct gfs_header *hd, int len)
-{
- struct journal *j;
- int jid, result, *p;
-
- p = (int *)((char *)hd + sizeof(struct gfs_header));
- jid = le32_to_cpu(p[0]);
- result = le32_to_cpu(p[1]);
-
- log_group(mg, "receive_recovery_result from %d jid %d result %d",
- hd->nodeid, jid, result);
-
- j = find_journal(mg, jid);
- if (!j) {
- log_error("receive_recovery_result from %d no jid %d",
- hd->nodeid, jid);
- return;
- }
-
- if (!j->needs_recovery)
- return;
-
- if (result == LM_RD_SUCCESS)
- j->needs_recovery = 0;
- else {
- j->failed_recovery_count++;
- log_group(mg, "jid %d failed_recovery_count %d", jid,
- j->failed_recovery_count);
- }
-}
-
-static void receive_first_recovery_done(struct mountgroup *mg,
- struct gfs_header *hd, int len)
-{
- int master = mg->first_recovery_master;
-
- log_group(mg, "receive_first_recovery_done from %d master %d "
- "mount_client_notified %d",
- hd->nodeid, master, mg->mount_client_notified);
-
- if (list_empty(&mg->changes)) {
- /* everything is idle, no changes in progress */
-
- mg->first_recovery_needed = 0;
- mg->first_recovery_master = 0;
- mg->first_recovery_msg = 1;
-
- if (master != our_nodeid)
- start_kernel(mg);
- } else {
- /* Everyone will receive this message in the same sequence
- wrt other start messages and confchgs:
-
- - If a new confchg arrives after this message (and before
- the final start message in the current start cycle),
- a new start cycle will begin. All nodes before the
- confchg will have frn=0 due to receiving this message,
- and nodes added by the confchg will see frn=0 in all
- start messages (in any_nodes_first_recovery() which
- returns 0).
-
- - If the final start message arrives after this message,
- the start cycle will complete, running sync_state(), on
- all current nodes with all having seen this message.
- Old and new nodes in the current start cycle will see
- this msg and use it (first_recovery_msg) instead of the
- first_recovery_needed/master data in the start messages
- (which may be inconsistent due to members sending their
- start messages either before or after receiving this
- message). */
-
- /* exclude new nodes from this sanity check since they've
- never set a master value to compare against */
- if (mg->started_count && (master != hd->nodeid))
- log_error("receive_first_recovery_done from %d "
- "master %d", hd->nodeid, master);
-
- mg->first_recovery_needed = 0;
- mg->first_recovery_master = 0;
- mg->first_recovery_msg = 1;
- }
-}
-
-static void receive_remount(struct mountgroup *mg, struct gfs_header *hd,
- int len)
-{
- struct node *node;
-
- log_group(mg, "receive_remount from %d ro %d", hd->nodeid, hd->msgdata);
-
- node = get_node_history(mg, hd->nodeid);
- if (!node) {
- log_error("receive_remount no nodeid %d", hd->nodeid);
- return;
- }
-
- node->ro = hd->msgdata;
-
- if (hd->nodeid == our_nodeid)
- mg->ro = node->ro;
-}
-
-/* The node with the withdraw wants to leave the mountgroup, but have
- the other nodes do recovery for it when it leaves. They wouldn't usually
- do recovery for a node that leaves "normally", i.e. without failing at the
- cluster membership level. So, we send a withdraw message to tell the
- others that our succeeding leave-removal should be followed by recovery
- like a failure-removal would be.
-
- The withdrawing node can't release dlm locks for the fs before other
- nodes have stopped the fs. The same reason as for any gfs journal
- recovery; the locks on the failed/withdrawn fs "protect" the parts of
- the fs that need to be recovered, and until the fs on all mounters has
- been stopped/blocked, our existing dlm locks need to remain to prevent
- other nodes from touching these parts of the fs.
-
- So, the node doing withdraw needs to know that other nodes in the mountgroup
- have blocked the fs before it sets /sys/fs/gfs/foo/withdraw to 1, which
- tells gfs-kernel to continue and release dlm locks.
-
- Until the node doing withdraw has released the dlm locks on the withdrawn
- fs, the other nodes' attempts to recover the given journal will fail (they
- fail to acquire the journal lock.) So, these nodes need to either wait until
- the dlm locks have been released before attempting to recover the journal,
- or retry failed attempts at recovering the journal.
-
- How it works
- . nodes A,B,C in mountgroup for fs foo
- . foo is withrawn on node C
- . C sends withdraw to all
- . all set C->withraw = 1
- . C leaves mountgroup
- . A,B,C get confchg removing C
- . A,B stop kernel foo
- . A,B send out-of-band message to C indicating foo is stopped
- . C gets OOB message and set /sys/fs/gfs/foo/withdraw to 1
- . dlm locks for foo are released on C
- . A,B will now be able to acquire C's journal lock for foo
- . A,B will complete recovery of foo
-
- An "in-band" message would be through cpg foo, but since C has left cpg
- foo, we can't use that cpg, and have to go through an external channel.
-*/
-
-static void receive_withdraw(struct mountgroup *mg, struct gfs_header *hd,
- int len)
-{
- struct node *node;
-
- log_group(mg, "receive_withdraw from %d", hd->nodeid);
-
- node = get_node_history(mg, hd->nodeid);
- if (!node) {
- log_error("receive_withdraw no nodeid %d", hd->nodeid);
- return;
- }
- node->withdraw = 1;
-
- if (hd->nodeid == our_nodeid)
- leave_mountgroup(mg, 0);
-}
-
-/* start message from all nodes shows zero started_count */
-
-static int all_nodes_new(struct mountgroup *mg)
-{
- struct change *cg;
- struct member *memb;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- list_for_each_entry(memb, &cg->members, list) {
- if (memb->mg_info->started_count)
- return 0;
- }
- return 1;
-}
-
-/* does start message from any node with non-zero started_count have
- first_recovery_needed set? (verify that all started nodes agree on
- first_recovery_needed) */
-
-static int any_nodes_first_recovery(struct mountgroup *mg)
-{
- struct change *cg;
- struct member *memb;
- int yes = 0, no = 0, master = 0;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- list_for_each_entry(memb, &cg->members, list) {
- if (!memb->mg_info->started_count)
- continue;
- if (memb->mg_info->first_recovery_needed)
- yes++;
- else
- no++;
- }
-
- if (no && yes) {
- /* disagreement on first_recovery_needed, shouldn't happen */
- log_error("any_nodes_first_recovery no %d yes %d", no, yes);
- return 1;
- }
-
- if (no)
- return 0;
-
- /* sanity check: verify agreement on the master */
-
- list_for_each_entry(memb, &cg->members, list) {
- if (!memb->mg_info->started_count)
- continue;
- if (!master) {
- master = memb->mg_info->first_recovery_master;
- continue;
- }
- if (master == memb->mg_info->first_recovery_master)
- continue;
-
- /* disagreement on master, shouldn't happen */
- log_error("any_nodes_first_recovery master %d vs %d",
- master, memb->mg_info->first_recovery_master);
- }
-
- return 1;
-}
-
-/* If all nodes new, there's no previous master, pick low nodeid;
- if not all nodes new, there will be a previous master, use that one unless
- it's no longer a member; if master is no longer a member pick low nodeid.
- The current master will already be set in mg->first_recovery_master for old
- nodes, but new nodes will need to look in the start messages to find it. */
-
-static int pick_first_recovery_master(struct mountgroup *mg, int all_new)
-{
- struct change *cg;
- struct member *memb;
- int old = 0, low = 0;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- list_for_each_entry(memb, &cg->members, list) {
- if (memb->mg_info->started_count)
- old = memb->mg_info->first_recovery_master;
-
- if (!low)
- low = memb->nodeid;
- else if (memb->nodeid < low)
- low = memb->nodeid;
- }
-
- memb = find_memb(cg, old);
-
- if (!memb || all_new) {
- log_group(mg, "pick_first_recovery_master low %d old %d",
- low, old);
- return low;
- }
-
- log_group(mg, "pick_first_recovery_master old %d", old);
- return old;
-}
-
-/* use a start message from an old node to create node info for each old node */
-
-static void create_old_nodes(struct mountgroup *mg)
-{
- struct change *cg;
- struct member *memb;
- struct node *node;
- struct journal *j;
- struct id_info *ids, *id;
- int id_count, id_size, rv;
-
- /* get ids from a start message of an old node */
-
- rv = get_id_list(mg, &ids, &id_count, &id_size);
- if (rv) {
- /* all new nodes, no old nodes */
- log_group(mg, "create_old_nodes all new");
- return;
- }
-
- /* use id list to set info for all old nodes */
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- list_for_each_entry(memb, &cg->members, list) {
- if (!memb->mg_info->started_count)
- continue;
-
- node = get_node_history(mg, memb->nodeid);
- id = get_id_struct(ids, id_count, id_size, memb->nodeid);
-
- if (!node || !id) {
- /* shouldn't happen */
- log_error("create_old_nodes %d node %d id %d",
- memb->nodeid, !!node, !!id);
- return;
- }
-
- if (!(id->flags & IDI_NODEID_IS_MEMBER) ||
- (id->flags & IDI_JID_NEEDS_RECOVERY)) {
- /* shouldn't happen */
- log_error("create_old_nodes %d bad flags %x",
- memb->nodeid, id->flags);
- return;
- }
-
- node->jid = id->jid;
- node->kernel_mount_done = !!(id->flags & IDI_MOUNT_DONE);
- node->kernel_mount_error = !!(id->flags & IDI_MOUNT_ERROR);
- node->ro = !!(id->flags & IDI_MOUNT_RO);
- node->spectator = !!(id->flags & IDI_MOUNT_SPECTATOR);
-
- j = malloc(sizeof(struct journal));
- if (!j) {
- log_error("create_old_nodes no mem");
- return;
- }
- memset(j, 0, sizeof(struct journal));
-
- j->nodeid = node->nodeid;
- j->jid = node->jid;
- list_add(&j->list, &mg->journals);
-
- log_group(mg, "create_old_nodes %d jid %d ro %d spect %d "
- "kernel_mount_done %d error %d",
- node->nodeid, node->jid, node->ro, node->spectator,
- node->kernel_mount_done, node->kernel_mount_error);
- }
-}
-
-/* use start messages from new nodes to create node info for each new node */
-
-static void create_new_nodes(struct mountgroup *mg)
-{
- struct change *cg;
- struct member *memb;
- struct id_info *ids, *id;
- struct node *node;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- list_for_each_entry(memb, &cg->members, list) {
- if (memb->mg_info->started_count)
- continue;
-
- node = get_node_history(mg, memb->nodeid);
- if (!node) {
- /* shouldn't happen */
- log_error("create_new_nodes %d no node", memb->nodeid);
- return;
- }
-
- ids = (struct id_info *)(memb->start_msg +
- sizeof(struct gfs_header) +
- memb->mg_info->mg_info_size);
-
- id = get_id_struct(ids, memb->mg_info->id_info_count,
- memb->mg_info->id_info_size, memb->nodeid);
-
- if (!(id->flags & IDI_NODEID_IS_MEMBER) ||
- (id->flags & IDI_JID_NEEDS_RECOVERY)) {
- /* shouldn't happen */
- log_error("create_new_nodes %d bad flags %x",
- memb->nodeid, id->flags);
- return;
- }
-
- node->jid = JID_NONE;
- node->ro = !!(id->flags & IDI_MOUNT_RO);
- node->spectator = !!(id->flags & IDI_MOUNT_SPECTATOR);
-
- log_group(mg, "create_new_nodes %d ro %d spect %d",
- node->nodeid, node->ro, node->spectator);
- }
-}
-
-#if 0
-static void print_id_list(struct mountgroup *mg, struct id_info *ids,
- int id_count, int id_size)
-{
- struct id_info *id = ids;
- int i;
-
- for (i = 0; i < id_count; i++) {
- log_group(mg, "id nodeid %d jid %d flags %08x",
- id->nodeid, id->jid, id->flags);
- id = (struct id_info *)((char *)id + id_size);
- }
-}
-#endif
-
-static void create_failed_journals(struct mountgroup *mg)
-{
- struct journal *j;
- struct id_info *ids, *id;
- int id_count, id_size;
- int rv, i;
-
- rv = get_id_list(mg, &ids, &id_count, &id_size);
- if (rv) {
- /* all new nodes, no old nodes */
- log_group(mg, "create_failed_journals all new");
- return;
- }
- /* print_id_list(mg, ids, id_count, id_size); */
-
- id = ids;
-
- for (i = 0; i < id_count; i++) {
- if (!(id->flags & IDI_JID_NEEDS_RECOVERY))
- goto next;
-
- j = malloc(sizeof(struct journal));
- if (!j) {
- log_error("create_failed_journals no mem");
- return;
- }
- memset(j, 0, sizeof(struct journal));
-
- j->jid = id->jid;
- j->needs_recovery = 1;
- list_add(&j->list, &mg->journals);
- log_group(mg, "create_failed_journals jid %d", j->jid);
- next:
- id = (struct id_info *)((char *)id + id_size);
- }
-}
-
-/* This pattern (for each failed memb in removed list of each change) is
- repeated and needs to match in four places: here, count_ids(),
- send_start(), and journals_need_recovery(). */
-
-static void set_failed_journals(struct mountgroup *mg)
-{
- struct change *cg;
- struct member *memb;
- struct journal *j;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- list_for_each_entry(cg, &mg->changes, list) {
- list_for_each_entry(memb, &cg->removed, list) {
- if (!memb->failed && !is_withdraw(mg, memb->nodeid))
- continue;
- j = find_journal_by_nodeid(mg, memb->nodeid);
- if (j) {
- j->needs_recovery = 1;
- j->failed_nodeid = j->nodeid;
- j->nodeid = 0;
- log_group(mg, "set_failed_journals jid %d "
- "nodeid %d", j->jid, memb->nodeid);
- } else {
- log_group(mg, "set_failed_journals no journal "
- "for nodeid %d ", memb->nodeid);
- }
- }
- }
-}
-
-/* returns nodeid of new member with the next highest nodeid */
-
-static int next_new_nodeid(struct mountgroup *mg, int prev)
-{
- struct change *cg;
- struct member *memb;
- int low = 0;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- list_for_each_entry(memb, &cg->members, list) {
- if (memb->mg_info->started_count)
- continue;
- if (memb->nodeid <= prev)
- continue;
- if (!low)
- low = memb->nodeid;
- else if (memb->nodeid < low)
- low = memb->nodeid;
- }
-
- return low;
-}
-
-/* returns lowest unused jid */
-
-static int next_free_jid(struct mountgroup *mg)
-{
- int i;
-
- for (i = 0; i < MAX_JOURNALS; i++) {
- if (!find_journal(mg, i))
- return i;
- }
- return -1;
-}
-
-static void create_new_journals(struct mountgroup *mg)
-{
- struct journal *j, *safe;
- struct change *cg;
- struct node *node;
- int nodeid = 0;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- /* first get rid of journal structs that are no longer used
- or dirty, i.e. from nodes that have unmounted/left, or
- journals that have been recovered */
-
- list_for_each_entry_safe(j, safe, &mg->journals, list) {
- if (j->needs_recovery)
- continue;
-
- if (find_memb(cg, j->nodeid))
- continue;
-
- list_del(&j->list);
- free(j);
- }
-
- while (1) {
- nodeid = next_new_nodeid(mg, nodeid);
- if (!nodeid)
- break;
-
- node = get_node_history(mg, nodeid);
- if (!node) {
- /* shouldn't happen */
- log_error("create_new_journals no nodeid %d", nodeid);
- continue;
- }
-
- if (node->spectator)
- node->jid = JID_NONE;
- else
- node->jid = next_free_jid(mg);
-
- if (node->nodeid == our_nodeid)
- mg->our_jid = node->jid;
-
- log_group(mg, "create_new_journals %d gets jid %d",
- node->nodeid, node->jid);
-
- if (node->jid == JID_NONE)
- continue;
-
- j = malloc(sizeof(struct journal));
- if (!j) {
- log_error("create_new_journals no mem");
- continue;
- }
- memset(j, 0, sizeof(struct journal));
-
- j->nodeid = nodeid;
- j->jid = node->jid;
- list_add(&j->list, &mg->journals);
- }
-}
-
-/* recovery_result and mount_done messages are saved by new members until
- they've completed the start cycle and have member state to apply them to.
- The start messages from old nodes may not reflect the rr/md updates. */
-
-static void apply_saved_messages(struct mountgroup *mg)
-{
- struct change *cg;
- struct save_msg *sm, *safe;
- struct gfs_header *hd;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- list_for_each_entry_safe(sm, safe, &cg->saved_messages, list) {
- hd = (struct gfs_header *)sm->buf;
-
- switch (hd->type) {
- case GFS_MSG_MOUNT_DONE:
- receive_mount_done(mg, hd, sm->len);
- break;
- case GFS_MSG_RECOVERY_RESULT:
- receive_recovery_result(mg, hd, sm->len);
- break;
- }
-
- list_del(&sm->list);
- free(sm);
- }
-}
-
-/* this is run immediately after receiving the final start message in a start
- cycle, so all nodes will run this in the same sequence wrt other messages
- and confchgs */
-
-static void sync_state(struct mountgroup *mg)
-{
- /* This is needed for the case where the first_recovery_done message
- arrives while a change/start cycle is in progress. The
- first_recovery data in the start messages (used by new nodes in this
- cycle to determine the first_recovery state) may be inconsistent in
- different start messages (because nodes sent their start messages at
- different times wrt the first_recovery_done message.) But, in the
- case where the new nodes received the first_recovery_done message,
- they can just use that and don't need the (possibly inconsistent)
- first recovery data in the start messages. */
-
- if (mg->first_recovery_msg) {
- if (mg->first_recovery_needed || mg->first_recovery_master) {
- /* shouldn't happen */
- log_error("sync_state first_recovery_msg needed %d "
- "master %d", mg->first_recovery_needed,
- mg->first_recovery_master);
- }
-
- log_group(mg, "sync_state first_recovery_msg");
- goto out;
- }
-
- /* This is the path the initial start cycle for the group always
- follows. It's the case where one or more nodes are all starting up
- for the first time. No one has completed a start cycle yet because
- everyone is joining, and one node needs to do first recovery. */
-
- if (all_nodes_new(mg)) {
- if (mg->first_recovery_needed || mg->first_recovery_master) {
- /* shouldn't happen */
- log_error("sync_state all_nodes_new first_recovery "
- "needed %d master %d",
- mg->first_recovery_needed,
- mg->first_recovery_master);
- }
- mg->first_recovery_needed = 1;
- mg->first_recovery_master = pick_first_recovery_master(mg, 1);
-
- log_group(mg, "sync_state all_nodes_new first_recovery_needed "
- "master %d", mg->first_recovery_master);
- goto out;
- }
-
- /* This is for the case where new nodes are added to existing members
- that have first_recovery_needed set. */
-
- if (any_nodes_first_recovery(mg)) {
- mg->first_recovery_needed = 1;
- mg->first_recovery_master = pick_first_recovery_master(mg, 0);
-
- log_group(mg, "sync_state first_recovery_needed master %d",
- mg->first_recovery_master);
- goto out;
- }
-
- /* Normal case where nodes join an established group that completed
- first recovery sometime in the past. Existing nodes that weren't
- around during first recovery come through here, and new nodes
- being added in this cycle come through here. */
-
- if (mg->first_recovery_needed) {
- /* shouldn't happen */
- log_error("sync_state frn should not be set");
- goto out;
- }
-
- log_group(mg, "sync_state");
- out:
- send_withdraw_acks(mg);
-
- if (!mg->started_count) {
- create_old_nodes(mg);
- create_new_nodes(mg);
- create_failed_journals(mg);
- apply_saved_messages(mg);
- create_new_journals(mg);
- } else {
- create_new_nodes(mg);
- set_failed_journals(mg);
- create_new_journals(mg);
- }
-}
-
-static void apply_changes(struct mountgroup *mg)
-{
- struct change *cg;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- switch (cg->state) {
-
- case CGST_WAIT_CONDITIONS:
- if (wait_conditions_done(mg)) {
- send_start(mg);
- cg->state = CGST_WAIT_MESSAGES;
- }
- break;
-
- case CGST_WAIT_MESSAGES:
- if (wait_messages_done(mg)) {
- sync_state(mg);
- cleanup_changes(mg);
- }
- break;
-
- default:
- log_error("apply_changes invalid state %d", cg->state);
- }
-}
-
-/* We send messages with the info from kernel uevents or mount.gfs ipc,
- and then process the uevent/ipc upon receiving the message for it, so
- that it can be processed in the same order by all nodes. */
-
-void process_recovery_uevent(char *name, int jid, int recover_status,
- int first_done)
-{
- struct mountgroup *mg;
- struct journal *j;
- int rv;
-
- mg = find_mg(name);
- if (!mg) {
- log_error("recovery_uevent mg not found %s", name);
- return;
- }
-
- if (jid < 0) {
- /* for back compat, sysfs file deprecated */
- rv = read_sysfs_int(mg, "recover_done", &jid);
- if (rv < 0) {
- log_error("recovery_uevent recover_done read %d", rv);
- return;
- }
- }
-
- if (recover_status < 0) {
- /* for back compat, sysfs file deprecated */
- rv = read_sysfs_int(mg, "recover_status", &recover_status);
- if (rv < 0) {
- log_error("recovery_uevent recover_status read %d", rv);
- return;
- }
- }
-
- if (!mg->first_recovery_needed) {
- if (!mg->local_recovery_busy) {
- /* This will happen in two known situations:
- - we get a recovery_done uevent for our own journal
- when we mount (jid == mg->our_jid)
- - the first mounter can read first_done and clear
- first_recovery_needed before seeing the change
- uevent from others_may_mount */
- log_group(mg, "recovery_uevent jid %d ignore", jid);
- return;
- }
-
- mg->local_recovery_busy = 0;
-
- if (mg->local_recovery_jid != jid) {
- log_error("recovery_uevent jid %d expected %d", jid,
- mg->local_recovery_jid);
- return;
- }
-
- j = find_journal(mg, jid);
- if (!j) {
- log_error("recovery_uevent no journal %d", jid);
- return;
- }
-
- log_group(mg, "recovery_uevent jid %d status %d "
- "local_recovery_done %d needs_recovery %d",
- jid, recover_status, j->local_recovery_done,
- j->needs_recovery);
-
- j->local_recovery_done = 1;
- j->local_recovery_result = recover_status;
-
- /* j->needs_recovery will be cleared when we receive this
- recovery_result message. if it's already set, then
- someone else has completed the recovery and there's
- no need to send our result */
-
- if (j->needs_recovery)
- send_recovery_result(mg, jid, recover_status);
- } else {
- /*
- * Assumption here is that only the first mounter will get
- * uevents when first_recovery_needed is set.
- */
-
- /* make a local record of jid and recover_status; we may want
- to check below that we've seen uevents for all jids
- during first recovery before sending first_recovery_done. */
-
- log_group(mg, "recovery_uevent jid %d first recovery done %d",
- jid, mg->first_done_uevent);
-
- /* ignore extraneous uevent from others_may_mount */
- if (mg->first_done_uevent)
- return;
-
- if (first_done < 0) {
- /* for back compat, sysfs file deprecated */
- rv = read_sysfs_int(mg, "first_done", &first_done);
- if (rv < 0) {
- log_error("recovery_uevent first_done read %d", rv);
- return;
- }
- }
-
- if (first_done) {
- log_group(mg, "recovery_uevent first_done");
- mg->first_done_uevent = 1;
- send_first_recovery_done(mg);
- }
- }
-
- apply_changes_recovery(mg);
-}
-
-static void start_journal_recovery(struct mountgroup *mg, int jid)
-{
- int rv;
-
- log_group(mg, "start_journal_recovery jid %d", jid);
-
- rv = set_sysfs(mg, "recover", jid);
- if (rv < 0) {
- log_error("start_journal_recovery %d error %d", jid, rv);
- return;
- }
-
- mg->local_recovery_busy = 1;
- mg->local_recovery_jid = jid;
-}
-
-static int wait_recoveries_done(struct mountgroup *mg)
-{
- struct journal *j;
- int wait_count = 0;
-
- list_for_each_entry(j, &mg->journals, list) {
- if (j->needs_recovery) {
- log_group(mg, "wait_recoveries jid %d nodeid %d "
- "unrecovered", j->jid, j->failed_nodeid);
- wait_count++;
- }
- }
-
- if (wait_count)
- return 0;
-
- log_group(mg, "wait_recoveries done");
- return 1;
-}
-
-/* pick a jid that has not been successfully recovered by someone else
- (received recovery_result success message) and hasn't been recovered
- by us (local record); if nothing to recover, return 0 */
-
-static int pick_journal_to_recover(struct mountgroup *mg, int *jid)
-{
- struct journal *j;
-
- list_for_each_entry(j, &mg->journals, list) {
- if (j->needs_recovery && !j->local_recovery_done) {
- *jid = j->jid;
- return 1;
- }
- }
-
-#if 0
- /* FIXME: do something so this doesn't happen so regularly; maybe
- retry only after all nodes have failed */
-
- /* Retry recoveries that failed the first time. This is necessary
- at times for withrawn journals when all nodes fail the recovery
- (fail to get journal lock) before the withdrawing node has had a
- chance to clear its dlm locks for the withdrawn journal.
- 32 max retries is random, and includes attempts by all nodes. */
-
- list_for_each_entry(j, &mg->journals, list) {
- if (j->needs_recovery && j->local_recovery_done &&
- (j->local_recovery_result == LM_RD_GAVEUP) &&
- (j->failed_recovery_count > 1) &&
- (j->failed_recovery_count < 32)) {
- log_group(mg, "retrying jid %d recovery", j->jid);
- *jid = j->jid;
- sleep(1); /* might this cause problems? */
- return 1;
- }
- }
-#endif
-
- return 0;
-}
-
-/* processing that happens after all changes have been dealt with */
-
-static void apply_recovery(struct mountgroup *mg)
-{
- int jid;
-
- if (mg->first_recovery_needed) {
- if (mg->first_recovery_master == our_nodeid &&
- !mg->mount_client_notified) {
- log_group(mg, "apply_recovery first start_kernel");
- mg->first_mounter = 1; /* adds first=1 to hostdata */
- start_kernel(mg); /* includes reply to mount.gfs */
- }
- return;
- }
-
- /* The normal non-first-recovery mode. When a recovery_done message
- is received, check whether any more journals need recovery. If
- so, start recovery on the next one, if not, start the kernel. */
-
- if (!wait_recoveries_done(mg)) {
- if (!mg->kernel_mount_done || mg->kernel_mount_error)
- return;
- if (mg->spectator)
- return;
- if (mg->local_recovery_busy)
- return;
- if (pick_journal_to_recover(mg, &jid))
- start_journal_recovery(mg, jid);
- } else {
- if (!mg->kernel_stopped)
- return;
- log_group(mg, "apply_recovery start_kernel");
- start_kernel(mg);
- }
-}
-
-static void apply_changes_recovery(struct mountgroup *mg)
-{
- if (!list_empty(&mg->changes))
- apply_changes(mg);
-
- if (mg->started_change && list_empty(&mg->changes))
- apply_recovery(mg);
-}
-
-void process_mountgroups(void)
-{
- struct mountgroup *mg, *safe;
-
- list_for_each_entry_safe(mg, safe, &mountgroups, list)
- apply_changes_recovery(mg);
-}
-
-static int add_change(struct mountgroup *mg,
- const struct cpg_address *member_list,
- size_t member_list_entries,
- const struct cpg_address *left_list,
- size_t left_list_entries,
- const struct cpg_address *joined_list,
- size_t joined_list_entries,
- struct change **cg_out)
-{
- struct change *cg;
- struct member *memb;
- int i, error;
-
- cg = malloc(sizeof(struct change));
- if (!cg)
- goto fail_nomem;
- memset(cg, 0, sizeof(struct change));
- INIT_LIST_HEAD(&cg->members);
- INIT_LIST_HEAD(&cg->removed);
- INIT_LIST_HEAD(&cg->saved_messages);
- cg->state = CGST_WAIT_CONDITIONS;
- cg->create_time = time(NULL);
- cg->seq = ++mg->change_seq;
- if (!cg->seq)
- cg->seq = ++mg->change_seq;
-
- cg->member_count = member_list_entries;
- cg->joined_count = joined_list_entries;
- cg->remove_count = left_list_entries;
-
- for (i = 0; i < member_list_entries; i++) {
- memb = malloc(sizeof(struct member));
- if (!memb)
- goto fail_nomem;
- memset(memb, 0, sizeof(struct member));
- memb->nodeid = member_list[i].nodeid;
- list_add_tail(&memb->list, &cg->members);
- }
-
- for (i = 0; i < left_list_entries; i++) {
- memb = malloc(sizeof(struct member));
- if (!memb)
- goto fail_nomem;
- memset(memb, 0, sizeof(struct member));
- memb->nodeid = left_list[i].nodeid;
- if (left_list[i].reason == CPG_REASON_NODEDOWN ||
- left_list[i].reason == CPG_REASON_PROCDOWN) {
- memb->failed = 1;
- cg->failed_count++;
- }
- list_add_tail(&memb->list, &cg->removed);
-
- if (memb->failed)
- node_history_fail(mg, memb->nodeid, cg,
- left_list[i].reason);
- else
- node_history_left(mg, memb->nodeid, cg);
-
- log_group(mg, "add_change cg %u remove nodeid %d reason %d",
- cg->seq, memb->nodeid, left_list[i].reason);
-
- if (left_list[i].reason == CPG_REASON_PROCDOWN)
- kick_node_from_cluster(memb->nodeid);
- }
-
- for (i = 0; i < joined_list_entries; i++) {
- memb = find_memb(cg, joined_list[i].nodeid);
- if (!memb) {
- log_error("no member %d", joined_list[i].nodeid);
- error = -ENOENT;
- goto fail;
- }
- memb->added = 1;
-
- if (memb->nodeid == our_nodeid)
- cg->we_joined = 1;
- else
- node_history_init(mg, memb->nodeid, cg);
-
- log_group(mg, "add_change cg %u joined nodeid %d", cg->seq,
- memb->nodeid);
- }
-
- if (cg->we_joined) {
- log_group(mg, "add_change cg %u we joined", cg->seq);
- list_for_each_entry(memb, &cg->members, list)
- node_history_init(mg, memb->nodeid, cg);
- }
-
- log_group(mg, "add_change cg %u counts member %d joined %d remove %d "
- "failed %d", cg->seq, cg->member_count, cg->joined_count,
- cg->remove_count, cg->failed_count);
-
- list_add(&cg->list, &mg->changes);
- *cg_out = cg;
- return 0;
-
- fail_nomem:
- log_error("no memory");
- error = -ENOMEM;
- fail:
- free_cg(cg);
- return error;
-}
-
-static int we_left(const struct cpg_address *left_list,
- size_t left_list_entries)
-{
- int i;
-
- for (i = 0; i < left_list_entries; i++) {
- if (left_list[i].nodeid == our_nodeid)
- return 1;
- }
- return 0;
-}
-
-static void confchg_cb(cpg_handle_t handle,
- const struct cpg_name *group_name,
- const struct cpg_address *member_list,
- size_t member_list_entries,
- const struct cpg_address *left_list,
- size_t left_list_entries,
- const struct cpg_address *joined_list,
- size_t joined_list_entries)
-{
- struct mountgroup *mg;
- struct change *cg;
- int rv;
-
- log_config(group_name, member_list, member_list_entries,
- left_list, left_list_entries,
- joined_list, joined_list_entries);
-
- mg = find_mg_handle(handle);
- if (!mg) {
- log_error("confchg_cb no mountgroup for cpg %s",
- group_name->value);
- return;
- }
-
- if (mg->leaving && we_left(left_list, left_list_entries)) {
- /* we called cpg_leave(), and this should be the final
- cpg callback we receive */
- log_group(mg, "confchg for our leave");
- dlmc_fs_unregister(dlmcontrol_fd, mg->name);
- cpg_finalize(mg->cpg_handle);
- client_dead(mg->cpg_client);
- list_del(&mg->list);
- if (!mg->withdraw_uevent) {
- free_mg(mg);
- } else {
- if (!member_list_entries) {
- /* no one remaining to send us an ack */
- set_sysfs(mg, "withdraw", 1);
- free_mg(mg);
- } else {
- /* set the sysfs withdraw file and free the mg
- when the ack arrives */
- list_add(&mg->list, &withdrawn_mounts);
- }
- }
- return;
- }
-
- rv = add_change(mg, member_list, member_list_entries,
- left_list, left_list_entries,
- joined_list, joined_list_entries, &cg);
- if (rv)
- return;
-
- apply_changes_recovery(mg);
-}
-
-static void gfs_header_in(struct gfs_header *hd)
-{
- hd->version[0] = le16_to_cpu(hd->version[0]);
- hd->version[1] = le16_to_cpu(hd->version[1]);
- hd->version[2] = le16_to_cpu(hd->version[2]);
- hd->type = le16_to_cpu(hd->type);
- hd->nodeid = le32_to_cpu(hd->nodeid);
- hd->to_nodeid = le32_to_cpu(hd->to_nodeid);
- hd->global_id = le32_to_cpu(hd->global_id);
- hd->flags = le32_to_cpu(hd->flags);
- hd->msgdata = le32_to_cpu(hd->msgdata);
-}
-
-static int gfs_header_check(struct gfs_header *hd, int nodeid)
-{
- if (hd->version[0] != our_protocol.daemon_run[0] ||
- hd->version[1] != our_protocol.daemon_run[1]) {
- log_error("reject message from %d version %u.%u.%u vs %u.%u.%u",
- nodeid, hd->version[0], hd->version[1],
- hd->version[2], our_protocol.daemon_run[0],
- our_protocol.daemon_run[1],
- our_protocol.daemon_run[2]);
- return -1;
- }
-
- if (hd->nodeid != nodeid) {
- log_error("bad message nodeid %d %d", hd->nodeid, nodeid);
- return -1;
- }
-
- return 0;
-}
-
-static void deliver_cb(cpg_handle_t handle,
- const struct cpg_name *group_name,
- uint32_t nodeid, uint32_t pid,
- void *data, size_t len)
-{
- struct mountgroup *mg;
- struct gfs_header *hd;
-
- mg = find_mg_handle(handle);
- if (!mg) {
- log_error("deliver_cb no mg for cpg %s", group_name->value);
- return;
- }
-
- if (len < sizeof(*hd)) {
- log_error("deliver_cb short message %zd", len);
- return;
- }
-
- hd = (struct gfs_header *)data;
- gfs_header_in(hd);
-
- if (gfs_header_check(hd, nodeid) < 0)
- return;
-
- switch (hd->type) {
- case GFS_MSG_START:
- receive_start(mg, hd, len);
- break;
- case GFS_MSG_MOUNT_DONE:
- if (!mg->started_count)
- save_message(mg, hd, len);
- else
- receive_mount_done(mg, hd, len);
- break;
- case GFS_MSG_FIRST_RECOVERY_DONE:
- receive_first_recovery_done(mg, hd, len);
- break;
- case GFS_MSG_RECOVERY_RESULT:
- if (!mg->started_count)
- save_message(mg, hd, len);
- else
- receive_recovery_result(mg, hd, len);
- break;
- case GFS_MSG_REMOUNT:
- receive_remount(mg, hd, len);
- break;
- case GFS_MSG_WITHDRAW:
- receive_withdraw(mg, hd, len);
- break;
- default:
- log_error("unknown msg type %d", hd->type);
- }
-
- apply_changes_recovery(mg);
-}
-
-static cpg_callbacks_t cpg_callbacks = {
- .cpg_deliver_fn = deliver_cb,
- .cpg_confchg_fn = confchg_cb,
-};
-
-static void process_cpg_mountgroup(int ci)
-{
- struct mountgroup *mg;
- cpg_error_t error;
-
- mg = find_mg_ci(ci);
- if (!mg) {
- log_error("process_mountgroup_cpg no mountgroup for ci %d", ci);
- return;
- }
-
- error = cpg_dispatch(mg->cpg_handle, CPG_DISPATCH_ALL);
- if (error != CPG_OK) {
- log_error("cpg_dispatch error %d", error);
- return;
- }
-
- update_flow_control_status();
-}
-
-int gfs_join_mountgroup(struct mountgroup *mg)
-{
- cpg_error_t error;
- cpg_handle_t h;
- struct cpg_name name;
- int i = 0, fd, ci, rv;
-
- /* I think this registration with dlm_controld could be done
- just about anywhere before we do the mount(2). */
- rv = dlmc_fs_register(dlmcontrol_fd, mg->name);
- if (rv) {
- log_error("dlmc_fs_register failed %d", rv);
- return rv;
- }
-
- error = cpg_initialize(&h, &cpg_callbacks);
- if (error != CPG_OK) {
- log_error("cpg_initialize error %d", error);
- goto fail;
- }
-
- cpg_fd_get(h, &fd);
-
- ci = client_add(fd, process_cpg_mountgroup, NULL);
-
- mg->cpg_handle = h;
- mg->cpg_client = ci;
- mg->cpg_fd = fd;
- mg->kernel_stopped = 1;
- mg->joining = 1;
-
- memset(&name, 0, sizeof(name));
- sprintf(name.value, "gfs:mount:%s", mg->name);
- name.length = strlen(name.value) + 1;
-
- /* TODO: allow global_id to be set in cluster.conf? */
- mg->id = cpgname_to_crc(name.value, name.length);
-
- retry:
- error = cpg_join(h, &name);
- if (error == CPG_ERR_TRY_AGAIN) {
- sleep(1);
- if (!(++i % 10))
- log_error("cpg_join error retrying");
- goto retry;
- }
- if (error != CPG_OK) {
- log_error("cpg_join error %d", error);
- cpg_finalize(h);
- goto fail_client;
- }
-
- return 0;
-
- fail_client:
- client_dead(ci);
- cpg_finalize(h);
- fail:
- dlmc_fs_unregister(dlmcontrol_fd, mg->name);
- return -ENOTCONN;
-}
-
-/* If mount(2) fails, we'll often get two leaves, one from seeing the remove
- uevent, and the other from mount.gfs. I suspect they could arrive in either
- order. We can just ignore the second. The second would either not find
- the mg here, or would see mg->leaving of 1 from the first. */
-
-static void leave_mountgroup(struct mountgroup *mg, int mnterr)
-{
- cpg_error_t error;
- struct cpg_name name;
- int i = 0;
-
- if (mg->leaving) {
- log_group(mg, "leave: already leaving");
- return;
- }
- mg->leaving = 1;
-
- memset(&name, 0, sizeof(name));
- sprintf(name.value, "gfs:mount:%s", mg->name);
- name.length = strlen(name.value) + 1;
-
- retry:
- error = cpg_leave(mg->cpg_handle, &name);
- if (error == CPG_ERR_TRY_AGAIN) {
- sleep(1);
- if (!(++i % 10))
- log_error("cpg_leave error retrying");
- goto retry;
- }
- if (error != CPG_OK)
- log_error("cpg_leave error %d", error);
-}
-
-void do_leave(char *name, int mnterr)
-{
- struct mountgroup *mg;
-
- log_debug("do_leave %s mnterr %d", name, mnterr);
-
- mg = find_mg(name);
- if (!mg) {
- log_error("do_leave: %s not found", name);
- return;
- }
-
- if (mg->withdraw_uevent) {
- log_group(mg, "do_leave: ignored during withdraw");
- return;
- }
-
- leave_mountgroup(mg, mnterr);
-}
-
-static void receive_withdraw_ack(struct gfs_header *hd, int len)
-{
- struct mountgroup *mg;
-
- if (hd->to_nodeid != our_nodeid)
- return;
-
- log_debug("receive_withdraw_ack from %d global_id %x",
- hd->nodeid, hd->global_id);
-
- list_for_each_entry(mg, &withdrawn_mounts, list) {
- if (mg->id != hd->global_id)
- continue;
- set_sysfs(mg, "withdraw", 1);
- list_del(&mg->list);
- free_mg(mg);
- break;
- }
-}
-
-static void send_withdraw_ack(struct mountgroup *mg, int nodeid)
-{
- struct gfs_header h;
-
- memset(&h, 0, sizeof(h));
-
- h.version[0] = cpu_to_le16(our_protocol.daemon_run[0]);
- h.version[1] = cpu_to_le16(our_protocol.daemon_run[1]);
- h.version[2] = cpu_to_le16(our_protocol.daemon_run[2]);
- h.type = cpu_to_le16(GFS_MSG_WITHDRAW_ACK);
- h.nodeid = cpu_to_le32(our_nodeid);
- h.to_nodeid = cpu_to_le32(nodeid);
- h.global_id = cpu_to_le32(mg->id);
-
- _send_message(cpg_handle_daemon, (char *)&h, sizeof(h),
- GFS_MSG_WITHDRAW_ACK);
-}
-
-/* Everyone remaining in the group will send an ack for the withdrawn fs;
- all but the first will be ignored. */
-
-static void send_withdraw_acks(struct mountgroup *mg)
-{
- struct node *node;
-
- list_for_each_entry(node, &mg->node_history, list) {
- if (node->withdraw && !node->send_withdraw_ack) {
- send_withdraw_ack(mg, node->nodeid);
- node->send_withdraw_ack = 1;
- }
- }
-}
-
-static struct node *get_node_daemon(int nodeid)
-{
- struct node *node;
-
- list_for_each_entry(node, &daemon_nodes, list) {
- if (node->nodeid == nodeid)
- return node;
- }
- return NULL;
-}
-
-static void add_node_daemon(int nodeid)
-{
- struct node *node;
-
- if (get_node_daemon(nodeid))
- return;
-
- node = malloc(sizeof(struct node));
- if (!node) {
- log_error("add_node_daemon no mem");
- return;
- }
- memset(node, 0, sizeof(struct node));
- node->nodeid = nodeid;
- list_add_tail(&node->list, &daemon_nodes);
-}
-
-static void pv_in(struct protocol_version *pv)
-{
- pv->major = le16_to_cpu(pv->major);
- pv->minor = le16_to_cpu(pv->minor);
- pv->patch = le16_to_cpu(pv->patch);
- pv->flags = le16_to_cpu(pv->flags);
-}
-
-static void pv_out(struct protocol_version *pv)
-{
- pv->major = cpu_to_le16(pv->major);
- pv->minor = cpu_to_le16(pv->minor);
- pv->patch = cpu_to_le16(pv->patch);
- pv->flags = cpu_to_le16(pv->flags);
-}
-
-static void protocol_in(struct protocol *proto)
-{
- pv_in(&proto->dm_ver);
- pv_in(&proto->km_ver);
- pv_in(&proto->dr_ver);
- pv_in(&proto->kr_ver);
-}
-
-static void protocol_out(struct protocol *proto)
-{
- pv_out(&proto->dm_ver);
- pv_out(&proto->km_ver);
- pv_out(&proto->dr_ver);
- pv_out(&proto->kr_ver);
-}
-
-/* go through member list saved in last confchg, see if we have received a
- proto message from each */
-
-static int all_protocol_messages(void)
-{
- struct node *node;
- int i;
-
- if (!daemon_member_count)
- return 0;
-
- for (i = 0; i < daemon_member_count; i++) {
- node = get_node_daemon(daemon_member[i].nodeid);
- if (!node) {
- log_error("all_protocol_messages no node %d",
- daemon_member[i].nodeid);
- return 0;
- }
-
- if (!node->proto.daemon_max[0])
- return 0;
- }
- return 1;
-}
-
-static int pick_min_protocol(struct protocol *proto)
-{
- uint16_t mind[4];
- uint16_t mink[4];
- struct node *node;
- int i;
-
- memset(&mind, 0, sizeof(mind));
- memset(&mink, 0, sizeof(mink));
-
- /* first choose the minimum major */
-
- for (i = 0; i < daemon_member_count; i++) {
- node = get_node_daemon(daemon_member[i].nodeid);
- if (!node) {
- log_error("pick_min_protocol no node %d",
- daemon_member[i].nodeid);
- return -1;
- }
-
- if (!mind[0] || node->proto.daemon_max[0] < mind[0])
- mind[0] = node->proto.daemon_max[0];
-
- if (!mink[0] || node->proto.kernel_max[0] < mink[0])
- mink[0] = node->proto.kernel_max[0];
- }
-
- if (!mind[0] || !mink[0]) {
- log_error("pick_min_protocol zero major number");
- return -1;
- }
-
- /* second pick the minimum minor with the chosen major */
-
- for (i = 0; i < daemon_member_count; i++) {
- node = get_node_daemon(daemon_member[i].nodeid);
- if (!node)
- continue;
-
- if (mind[0] == node->proto.daemon_max[0]) {
- if (!mind[1] || node->proto.daemon_max[1] < mind[1])
- mind[1] = node->proto.daemon_max[1];
- }
-
- if (mink[0] == node->proto.kernel_max[0]) {
- if (!mink[1] || node->proto.kernel_max[1] < mink[1])
- mink[1] = node->proto.kernel_max[1];
- }
- }
-
- if (!mind[1] || !mink[1]) {
- log_error("pick_min_protocol zero minor number");
- return -1;
- }
-
- /* third pick the minimum patch with the chosen major.minor */
-
- for (i = 0; i < daemon_member_count; i++) {
- node = get_node_daemon(daemon_member[i].nodeid);
- if (!node)
- continue;
-
- if (mind[0] == node->proto.daemon_max[0] &&
- mind[1] == node->proto.daemon_max[1]) {
- if (!mind[2] || node->proto.daemon_max[2] < mind[2])
- mind[2] = node->proto.daemon_max[2];
- }
-
- if (mink[0] == node->proto.kernel_max[0] &&
- mink[1] == node->proto.kernel_max[1]) {
- if (!mink[2] || node->proto.kernel_max[2] < mink[2])
- mink[2] = node->proto.kernel_max[2];
- }
- }
-
- if (!mind[2] || !mink[2]) {
- log_error("pick_min_protocol zero patch number");
- return -1;
- }
-
- memcpy(&proto->daemon_run, &mind, sizeof(mind));
- memcpy(&proto->kernel_run, &mink, sizeof(mink));
- return 0;
-}
-
-static void receive_protocol(struct gfs_header *hd, int len)
-{
- struct protocol *p;
- struct node *node;
-
- p = (struct protocol *)((char *)hd + sizeof(struct gfs_header));
- protocol_in(p);
-
- if (len < sizeof(struct gfs_header) + sizeof(struct protocol)) {
- log_error("receive_protocol invalid len %d from %d",
- len, hd->nodeid);
- return;
- }
-
- /* zero is an invalid version value */
-
- if (!p->daemon_max[0] || !p->daemon_max[1] || !p->daemon_max[2] ||
- !p->kernel_max[0] || !p->kernel_max[1] || !p->kernel_max[2]) {
- log_error("receive_protocol invalid max value from %d "
- "daemon %u.%u.%u kernel %u.%u.%u", hd->nodeid,
- p->daemon_max[0], p->daemon_max[1], p->daemon_max[2],
- p->kernel_max[0], p->kernel_max[1], p->kernel_max[2]);
- return;
- }
-
- /* the run values will be zero until a version is set, after
- which none of the run values can be zero */
-
- if (p->daemon_run[0] && (!p->daemon_run[1] || !p->daemon_run[2] ||
- !p->kernel_run[0] || !p->kernel_run[1] || !p->kernel_run[2])) {
- log_error("receive_protocol invalid run value from %d "
- "daemon %u.%u.%u kernel %u.%u.%u", hd->nodeid,
- p->daemon_run[0], p->daemon_run[1], p->daemon_run[2],
- p->kernel_run[0], p->kernel_run[1], p->kernel_run[2]);
- return;
- }
-
- /* if we have zero run values, and this msg has non-zero run values,
- then adopt them as ours; otherwise save this proto message */
-
- if (our_protocol.daemon_run[0])
- return;
-
- if (p->daemon_run[0]) {
- memcpy(&our_protocol.daemon_run, &p->daemon_run,
- sizeof(struct protocol_version));
- memcpy(&our_protocol.kernel_run, &p->kernel_run,
- sizeof(struct protocol_version));
- log_debug("run protocol from nodeid %d", hd->nodeid);
- return;
- }
-
- /* save this node's proto so we can tell when we've got all, and
- use it to select a minimum protocol from all */
-
- node = get_node_daemon(hd->nodeid);
- if (!node) {
- log_error("receive_protocol no node %d", hd->nodeid);
- return;
- }
- memcpy(&node->proto, p, sizeof(struct protocol));
-}
-
-static void send_protocol(struct protocol *proto)
-{
- struct gfs_header *hd;
- struct protocol *pr;
- char *buf;
- int len;
-
- len = sizeof(struct gfs_header) + sizeof(struct protocol);
- buf = malloc(len);
- if (!buf) {
- log_error("send_protocol no mem %d", len);
- return;
- }
- memset(buf, 0, len);
-
- hd = (struct gfs_header *)buf;
- pr = (struct protocol *)(buf + sizeof(*hd));
-
- hd->type = cpu_to_le16(GFS_MSG_PROTOCOL);
- hd->nodeid = cpu_to_le32(our_nodeid);
-
- memcpy(pr, proto, sizeof(struct protocol));
- protocol_out(pr);
-
- _send_message(cpg_handle_daemon, buf, len, GFS_MSG_PROTOCOL);
-}
-
-int set_protocol(void)
-{
- struct protocol proto;
- struct pollfd pollfd;
- int sent_proposal = 0;
- int rv;
-
- memset(&pollfd, 0, sizeof(pollfd));
- pollfd.fd = cpg_fd_daemon;
- pollfd.events = POLLIN;
-
- while (1) {
- if (our_protocol.daemon_run[0])
- break;
-
- if (!sent_proposal && all_protocol_messages()) {
- /* propose a protocol; look through info from all
- nodes and pick the min for both daemon and kernel,
- and propose that */
-
- sent_proposal = 1;
-
- /* copy our max values */
- memcpy(&proto, &our_protocol, sizeof(struct protocol));
-
- rv = pick_min_protocol(&proto);
- if (rv < 0)
- return rv;
-
- log_debug("set_protocol member_count %d propose "
- "daemon %u.%u.%u kernel %u.%u.%u",
- daemon_member_count,
- proto.daemon_run[0], proto.daemon_run[1],
- proto.daemon_run[2], proto.kernel_run[0],
- proto.kernel_run[1], proto.kernel_run[2]);
-
- send_protocol(&proto);
- }
-
- /* only process messages/events from daemon cpg until protocol
- is established */
-
- rv = poll(&pollfd, 1, -1);
- if (rv == -1 && errno == EINTR) {
- if (daemon_quit)
- return -1;
- continue;
- }
- if (rv < 0) {
- log_error("set_protocol poll errno %d", errno);
- return -1;
- }
-
- if (pollfd.revents & POLLIN)
- process_cpg_daemon(0);
- if (pollfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
- log_error("set_protocol poll revents %u",
- pollfd.revents);
- return -1;
- }
- }
-
- if (our_protocol.daemon_run[0] != our_protocol.daemon_max[0] ||
- our_protocol.daemon_run[1] > our_protocol.daemon_max[1]) {
- log_error("incompatible daemon protocol run %u.%u.%u max %u.%u.%u",
- our_protocol.daemon_run[0],
- our_protocol.daemon_run[1],
- our_protocol.daemon_run[2],
- our_protocol.daemon_max[0],
- our_protocol.daemon_max[1],
- our_protocol.daemon_max[2]);
- return -1;
- }
-
- if (our_protocol.kernel_run[0] != our_protocol.kernel_max[0] ||
- our_protocol.kernel_run[1] > our_protocol.kernel_max[1]) {
- log_error("incompatible kernel protocol run %u.%u.%u max %u.%u.%u",
- our_protocol.kernel_run[0],
- our_protocol.kernel_run[1],
- our_protocol.kernel_run[2],
- our_protocol.kernel_max[0],
- our_protocol.kernel_max[1],
- our_protocol.kernel_max[2]);
- return -1;
- }
-
- log_debug("daemon run %u.%u.%u max %u.%u.%u "
- "kernel run %u.%u.%u max %u.%u.%u",
- our_protocol.daemon_run[0],
- our_protocol.daemon_run[1],
- our_protocol.daemon_run[2],
- our_protocol.daemon_max[0],
- our_protocol.daemon_max[1],
- our_protocol.daemon_max[2],
- our_protocol.kernel_run[0],
- our_protocol.kernel_run[1],
- our_protocol.kernel_run[2],
- our_protocol.kernel_max[0],
- our_protocol.kernel_max[1],
- our_protocol.kernel_max[2]);
-
- send_protocol(&our_protocol);
- return 0;
-}
-
-static void deliver_cb_daemon(cpg_handle_t handle,
- const struct cpg_name *group_name,
- uint32_t nodeid, uint32_t pid,
- void *data, size_t len)
-{
- struct gfs_header *hd;
-
- if (len < sizeof(*hd)) {
- log_error("deliver_cb short message %zd", len);
- return;
- }
-
- hd = (struct gfs_header *)data;
- gfs_header_in(hd);
-
- switch (hd->type) {
- case GFS_MSG_PROTOCOL:
- receive_protocol(hd, len);
- break;
- case GFS_MSG_WITHDRAW_ACK:
- if (gfs_header_check(hd, nodeid) < 0)
- return;
- receive_withdraw_ack(hd, len);
- break;
- default:
- log_error("deliver_cb_daemon unknown msg type %d", hd->type);
- }
-}
-
-static void confchg_cb_daemon(cpg_handle_t handle,
- const struct cpg_name *group_name,
- const struct cpg_address *member_list,
- size_t member_list_entries,
- const struct cpg_address *left_list,
- size_t left_list_entries,
- const struct cpg_address *joined_list,
- size_t joined_list_entries)
-{
- int i;
-
- log_config(group_name, member_list, member_list_entries,
- left_list, left_list_entries,
- joined_list, joined_list_entries);
-
- if (joined_list_entries)
- send_protocol(&our_protocol);
-
- memset(&daemon_member, 0, sizeof(daemon_member));
- daemon_member_count = member_list_entries;
-
- for (i = 0; i < member_list_entries; i++) {
- daemon_member[i] = member_list[i];
- add_node_daemon(member_list[i].nodeid);
- }
-}
-
-static cpg_callbacks_t cpg_callbacks_daemon = {
- .cpg_deliver_fn = deliver_cb_daemon,
- .cpg_confchg_fn = confchg_cb_daemon,
-};
-
-void process_cpg_daemon(int ci)
-{
- cpg_error_t error;
-
- error = cpg_dispatch(cpg_handle_daemon, CPG_DISPATCH_ALL);
- if (error != CPG_OK)
- log_error("daemon cpg_dispatch error %d", error);
-}
-
-int setup_cpg_daemon(void)
-{
- cpg_error_t error;
- cpg_handle_t h;
- struct cpg_name name;
- int i = 0;
-
- INIT_LIST_HEAD(&daemon_nodes);
-
- memset(&our_protocol, 0, sizeof(our_protocol));
- our_protocol.daemon_max[0] = 1;
- our_protocol.daemon_max[1] = 1;
- our_protocol.daemon_max[2] = 1;
- our_protocol.kernel_max[0] = 1;
- our_protocol.kernel_max[1] = 1;
- our_protocol.kernel_max[2] = 1;
-
- error = cpg_initialize(&h, &cpg_callbacks_daemon);
- if (error != CPG_OK) {
- log_error("daemon cpg_initialize error %d", error);
- return -1;
- }
-
- cpg_fd_get(h, &cpg_fd_daemon);
-
- cpg_handle_daemon = h;
-
- memset(&name, 0, sizeof(name));
- sprintf(name.value, "gfs:controld");
- name.length = strlen(name.value) + 1;
-
- retry:
- error = cpg_join(h, &name);
- if (error == CPG_ERR_TRY_AGAIN) {
- sleep(1);
- if (!(++i % 10))
- log_error("daemon cpg_join error retrying");
- goto retry;
- }
- if (error != CPG_OK) {
- log_error("daemon cpg_join error %d", error);
- goto fail;
- }
-
- log_debug("setup_cpg_daemon %d", cpg_fd_daemon);
- return cpg_fd_daemon;
-
- fail:
- cpg_finalize(h);
- return -1;
-}
-
-void close_cpg_daemon(void)
-{
- struct mountgroup *mg;
- cpg_error_t error;
- struct cpg_name name;
- int i = 0;
-
- if (!cpg_handle_daemon)
- return;
- if (cluster_down)
- goto fin;
-
- memset(&name, 0, sizeof(name));
- sprintf(name.value, "gfs:controld");
- name.length = strlen(name.value) + 1;
-
- retry:
- error = cpg_leave(cpg_handle_daemon, &name);
- if (error == CPG_ERR_TRY_AGAIN) {
- sleep(1);
- if (!(++i % 10))
- log_error("daemon cpg_leave error retrying");
- goto retry;
- }
- if (error != CPG_OK)
- log_error("daemon cpg_leave error %d", error);
- fin:
- list_for_each_entry(mg, &mountgroups, list) {
- if (mg->cpg_handle)
- cpg_finalize(mg->cpg_handle);
- }
- cpg_finalize(cpg_handle_daemon);
-}
-
-int setup_dlmcontrol(void)
-{
- int fd;
-
- fd = dlmc_fs_connect();
- if (fd < 0)
- log_error("cannot connect to dlm_controld %d", fd);
- else
- dlmcontrol_fd = fd;
-
- return fd;
-}
-
-int set_mountgroup_info(struct mountgroup *mg, struct gfsc_mountgroup *out)
-{
- struct change *cg, *last = NULL;
-
- strncpy(out->name, mg->name, GFS_MOUNTGROUP_LEN);
- out->global_id = mg->id;
-
- if (mg->joining)
- out->flags |= GFSC_MF_JOINING;
- if (mg->leaving)
- out->flags |= GFSC_MF_LEAVING;
- if (mg->kernel_stopped)
- out->flags |= GFSC_MF_KERNEL_STOPPED;
- if (mg->kernel_mount_done)
- out->flags |= GFSC_MF_KERNEL_MOUNT_DONE;
- if (mg->kernel_mount_error)
- out->flags |= GFSC_MF_KERNEL_MOUNT_ERROR;
- if (mg->first_recovery_needed)
- out->flags |= GFSC_MF_FIRST_RECOVERY_NEEDED;
- if (mg->first_recovery_msg)
- out->flags |= GFSC_MF_FIRST_RECOVERY_MSG;
- if (mg->local_recovery_busy)
- out->flags |= GFSC_MF_LOCAL_RECOVERY_BUSY;
-
- if (!mg->started_change)
- goto next;
-
- cg = mg->started_change;
-
- out->cg_prev.member_count = cg->member_count;
- out->cg_prev.joined_count = cg->joined_count;
- out->cg_prev.remove_count = cg->remove_count;
- out->cg_prev.failed_count = cg->failed_count;
- out->cg_prev.combined_seq = cg->combined_seq;
- out->cg_prev.seq = cg->seq;
-
- next:
- if (list_empty(&mg->changes))
- goto out;
-
- list_for_each_entry(cg, &mg->changes, list)
- last = cg;
-
- cg = list_first_entry(&mg->changes, struct change, list);
-
- out->cg_next.member_count = cg->member_count;
- out->cg_next.joined_count = cg->joined_count;
- out->cg_next.remove_count = cg->remove_count;
- out->cg_next.failed_count = cg->failed_count;
- out->cg_next.combined_seq = last->seq;
- out->cg_next.seq = cg->seq;
-
- /* FIXME: use real definitions for these conditions
- (also in dlm_controld) */
-
- if (cg->state == CGST_WAIT_CONDITIONS)
- out->cg_next.wait_condition = 4;
- if (!mg->kernel_mount_done)
- out->cg_next.wait_condition = 1;
- if (mg->dlm_notify_nodeid)
- out->cg_next.wait_condition = 2;
- if (poll_dlm)
- out->cg_next.wait_condition = 3;
-
- if (cg->state == CGST_WAIT_MESSAGES)
- out->cg_next.wait_messages = 1;
- out:
- return 0;
-}
-
-static int _set_node_info(struct mountgroup *mg, struct change *cg, int nodeid,
- struct gfsc_node *node)
-{
- struct member *m = NULL;
- struct node *n;
-
- node->nodeid = nodeid;
-
- if (cg)
- m = find_memb(cg, nodeid);
- if (!m)
- goto history;
-
- node->flags |= GFSC_NF_MEMBER;
-
- if (m->start)
- node->flags |= GFSC_NF_START;
- if (m->disallowed)
- node->flags |= GFSC_NF_DISALLOWED;
-
- history:
- n = get_node_history(mg, nodeid);
- if (!n)
- goto out;
-
- node->jid = n->jid;
-
- if (n->kernel_mount_done)
- node->flags |= GFSC_NF_KERNEL_MOUNT_DONE;
- if (n->kernel_mount_error)
- node->flags |= GFSC_NF_KERNEL_MOUNT_ERROR;
- if (n->check_dlm)
- node->flags |= GFSC_NF_CHECK_DLM;
- if (n->ro)
- node->flags |= GFSC_NF_READONLY;
- if (n->spectator)
- node->flags |= GFSC_NF_SPECTATOR;
-
- node->added_seq = n->added_seq;
- node->removed_seq = n->removed_seq;
- node->failed_reason = n->failed_reason;
- out:
- return 0;
-}
-
-int set_node_info(struct mountgroup *mg, int nodeid, struct gfsc_node *node)
-{
- struct change *cg;
-
- if (!list_empty(&mg->changes)) {
- cg = list_first_entry(&mg->changes, struct change, list);
- return _set_node_info(mg, cg, nodeid, node);
- }
-
- return _set_node_info(mg, mg->started_change, nodeid, node);
-}
-
-int set_mountgroups(int *count, struct gfsc_mountgroup **mgs_out)
-{
- struct mountgroup *mg;
- struct gfsc_mountgroup *mgs, *mgp;
- int mg_count = 0;
-
- list_for_each_entry(mg, &mountgroups, list)
- mg_count++;
-
- mgs = malloc(mg_count * sizeof(struct gfsc_mountgroup));
- if (!mgs)
- return -ENOMEM;
- memset(mgs, 0, mg_count * sizeof(struct gfsc_mountgroup));
-
- mgp = mgs;
- list_for_each_entry(mg, &mountgroups, list) {
- set_mountgroup_info(mg, mgp++);
- }
-
- *count = mg_count;
- *mgs_out = mgs;
- return 0;
-}
-
-int set_mountgroup_nodes(struct mountgroup *mg, int option, int *node_count,
- struct gfsc_node **nodes_out)
-{
- struct change *cg;
- struct node *n;
- struct gfsc_node *nodes = NULL, *nodep;
- struct member *memb;
- int count = 0;
-
- if (option == GFSC_NODES_ALL) {
- if (!list_empty(&mg->changes))
- cg = list_first_entry(&mg->changes, struct change,list);
- else
- cg = mg->started_change;
-
- list_for_each_entry(n, &mg->node_history, list)
- count++;
-
- } else if (option == GFSC_NODES_MEMBERS) {
- if (!mg->started_change)
- goto out;
- cg = mg->started_change;
- count = cg->member_count;
-
- } else if (option == GFSC_NODES_NEXT) {
- if (list_empty(&mg->changes))
- goto out;
- cg = list_first_entry(&mg->changes, struct change, list);
- count = cg->member_count;
- } else
- goto out;
-
- nodes = malloc(count * sizeof(struct gfsc_node));
- if (!nodes)
- return -ENOMEM;
- memset(nodes, 0, count * sizeof(struct gfsc_node));
- nodep = nodes;
-
- if (option == GFSC_NODES_ALL) {
- list_for_each_entry(n, &mg->node_history, list)
- _set_node_info(mg, cg, n->nodeid, nodep++);
- } else {
- list_for_each_entry(memb, &cg->members, list)
- _set_node_info(mg, cg, memb->nodeid, nodep++);
- }
- out:
- *node_count = count;
- *nodes_out = nodes;
- return 0;
-}
-
diff --git a/group/gfs_controld/cpg-old.c b/group/gfs_controld/cpg-old.c
deleted file mode 100644
index 5342025..0000000
--- a/group/gfs_controld/cpg-old.c
+++ /dev/null
@@ -1,2452 +0,0 @@
-#include "gfs_daemon.h"
-#include "config.h"
-#include "cpg-old.h"
-#include "libgroup.h"
-
-#define ASSERT(x) \
-do { \
- if (!(x)) { \
- log_error("Assertion failed on line %d of file %s\n" \
- "Assertion: \"%s\"\n", __LINE__, __FILE__, #x); \
- } \
-} while (0)
-
-#define JID_INIT -9
-
-/* mg_member opts bit field */
-
-enum {
- MEMB_OPT_RW = 1,
- MEMB_OPT_RO = 2,
- MEMB_OPT_SPECT = 4,
- MEMB_OPT_RECOVER = 8,
-};
-
-/* mg_member state: local_recovery_status, recovery_status */
-
-enum {
- RS_NEED_RECOVERY = 1,
- RS_SUCCESS,
- RS_GAVEUP,
- RS_NOFS,
- RS_READONLY,
-};
-
-extern group_handle_t gh;
-
-/* cpg message protocol
- 1.0.0 is initial version
- 2.0.0 is incompatible with 1.0.0 and allows plock ownership */
-static unsigned int protocol_v100[3] = {1, 0, 0};
-static unsigned int protocol_v200[3] = {2, 0, 0};
-static unsigned int protocol_active[3];
-
-
-static void send_journals(struct mountgroup *mg, int nodeid);
-
-
-static const char *msg_name(int type)
-{
- switch (type) {
- case MSG_JOURNAL:
- return "MSG_JOURNAL";
- case MSG_OPTIONS:
- return "MSG_OPTIONS";
- case MSG_REMOUNT:
- return "MSG_REMOUNT";
- case MSG_PLOCK:
- return "MSG_PLOCK";
- case MSG_MOUNT_STATUS:
- return "MSG_MOUNT_STATUS";
- case MSG_RECOVERY_STATUS:
- return "MSG_RECOVERY_STATUS";
- case MSG_RECOVERY_DONE:
- return "MSG_RECOVERY_DONE";
- case MSG_WITHDRAW:
- return "MSG_WITHDRAW";
- }
- return "unknown";
-}
-
-static int _send_message(cpg_handle_t h, void *buf, int len, int type)
-{
- struct iovec iov;
- cpg_error_t error;
- int retries = 0;
-
- iov.iov_base = buf;
- iov.iov_len = len;
-
- retry:
- error = cpg_mcast_joined(h, CPG_TYPE_AGREED, &iov, 1);
- if (error == CPG_ERR_TRY_AGAIN) {
- retries++;
- usleep(1000);
- if (!(retries % 100))
- log_error("cpg_mcast_joined retry %d %s",
- retries, msg_name(type));
- goto retry;
- }
- if (error != CPG_OK) {
- log_error("cpg_mcast_joined error %d handle %llx %s",
- error, (unsigned long long)h, msg_name(type));
- return -1;
- }
-
- if (retries)
- log_debug("cpg_mcast_joined retried %d %s",
- retries, msg_name(type));
-
- return 0;
-}
-
-int send_group_message_old(struct mountgroup *mg, int len, char *buf)
-{
- struct gdlm_header *hd = (struct gdlm_header *) buf;
- int type = hd->type;
-
- hd->version[0] = cpu_to_le16(protocol_active[0]);
- hd->version[1] = cpu_to_le16(protocol_active[1]);
- hd->version[2] = cpu_to_le16(protocol_active[2]);
- hd->type = cpu_to_le16(hd->type);
- hd->nodeid = cpu_to_le32(hd->nodeid);
- hd->to_nodeid = cpu_to_le32(hd->to_nodeid);
- memcpy(hd->name, mg->name, strlen(mg->name));
-
- return _send_message(cpg_handle_daemon, buf, len, type);
-}
-
-static struct mg_member *find_memb_nodeid(struct mountgroup *mg, int nodeid)
-{
- struct mg_member *memb;
-
- list_for_each_entry(memb, &mg->members, list) {
- if (memb->nodeid == nodeid)
- return memb;
- }
- return NULL;
-}
-
-static struct mg_member *find_memb_jid(struct mountgroup *mg, int jid)
-{
- struct mg_member *memb;
-
- list_for_each_entry(memb, &mg->members, list) {
- if (memb->jid == jid)
- return memb;
- }
- return NULL;
-}
-
-static void notify_mount_client(struct mountgroup *mg)
-{
- struct mg_member *memb;
-
- if (!mg->mount_client_result && mg->mount_client_delay) {
- log_group(mg, "notify_mount_client delayed");
- return;
- }
-
- client_reply_join_full(mg, mg->mount_client_result);
-
- if (mg->mount_client_result) {
- log_group(mg, "leaving due to mount error: %d",
- mg->mount_client_result);
-
- memb = find_memb_nodeid(mg, our_nodeid);
- if (memb->finished)
- group_leave(gh, mg->name);
- else {
- log_group(mg, "delay leave until after join");
- mg->group_leave_on_finish = 1;
- }
- } else {
- mg->mount_client_notified = 1;
- }
-}
-
-/* we can receive recovery_status messages from other nodes doing start before
- we actually process the corresponding start callback ourselves */
-
-void save_message_old(struct mountgroup *mg, char *buf, size_t len, int from,
- int type)
-{
- struct save_msg *sm;
-
- sm = malloc(sizeof(struct save_msg) + len);
- if (!sm)
- return;
- memset(sm, 0, sizeof(struct save_msg) + len);
-
- memcpy(&sm->buf, buf, len);
- sm->type = type;
- sm->len = len;
- sm->nodeid = from;
-
- log_group(mg, "save %s from %d len %zd", msg_name(type), from, len);
-
- list_add_tail(&sm->list, &mg->saved_messages);
-}
-
-static int first_mounter_recovery(struct mountgroup *mg)
-{
- struct mg_member *memb;
-
- list_for_each_entry(memb, &mg->members, list) {
- if (memb->opts & MEMB_OPT_RECOVER)
- return memb->nodeid;
- }
- return 0;
-}
-
-static int local_first_mounter_recovery(struct mountgroup *mg)
-{
- int nodeid;
-
- nodeid = first_mounter_recovery(mg);
- if (nodeid == our_nodeid)
- return 1;
- return 0;
-}
-
-static int remote_first_mounter_recovery(struct mountgroup *mg)
-{
- int nodeid;
-
- nodeid = first_mounter_recovery(mg);
- if (nodeid && (nodeid != our_nodeid))
- return 1;
- return 0;
-}
-
-static void start_done(struct mountgroup *mg)
-{
- log_group(mg, "start_done %d", mg->start_event_nr);
- group_start_done(gh, mg->name, mg->start_event_nr);
-}
-
-void send_withdraw_old(struct mountgroup *mg)
-{
- struct gdlm_header *hd;
- int len;
- char *buf;
-
- len = sizeof(struct gdlm_header);
-
- buf = malloc(len);
- if (!buf)
- return;
- memset(buf, 0, len);
-
- hd = (struct gdlm_header *)buf;
- hd->type = MSG_WITHDRAW;
- hd->nodeid = our_nodeid;
- hd->to_nodeid = 0;
-
- log_group(mg, "send_withdraw");
-
- send_group_message_old(mg, len, buf);
-
- free(buf);
-}
-
-static void receive_withdraw(struct mountgroup *mg, char *buf, size_t len, int from)
-{
- struct mg_member *memb;
-
- memb = find_memb_nodeid(mg, from);
- if (!memb) {
- log_group(mg, "receive_withdraw no member %d", from);
- return;
- }
- log_group(mg, "receive_withdraw from %d", from);
- memb->withdrawing = 1;
-
- if (from == our_nodeid)
- group_leave(gh, mg->name);
-}
-
-#define SEND_RS_INTS 3
-
-static void send_recovery_status(struct mountgroup *mg)
-{
- struct gdlm_header *hd;
- struct mg_member *memb;
- int len, *p, i, n = 0;
- char *buf;
-
- list_for_each_entry(memb, &mg->members_gone, list) {
- if (memb->local_recovery_status == RS_SUCCESS)
- n++;
- }
-
- len = sizeof(struct gdlm_header) + (n * SEND_RS_INTS * sizeof(int));
-
- buf = malloc(len);
- if (!buf)
- return;
- memset(buf, 0, len);
-
- hd = (struct gdlm_header *)buf;
- hd->type = MSG_RECOVERY_STATUS;
- hd->nodeid = our_nodeid;
- hd->to_nodeid = 0;
- p = (int *) (buf + sizeof(struct gdlm_header));
-
- i = 0;
- list_for_each_entry(memb, &mg->members_gone, list) {
- if (memb->local_recovery_status != RS_SUCCESS)
- continue;
- p[i] = cpu_to_le32(memb->nodeid);
- i++;
- p[i] = cpu_to_le32(memb->jid);
- i++;
- p[i] = cpu_to_le32(memb->local_recovery_status);
- i++;
- }
-
- log_group(mg, "send_recovery_status for %d nodes len %d", n, len);
-
- send_group_message_old(mg, len, buf);
-
- free(buf);
-}
-
-/* Note: we can get more than one node reporting success in recovering
- the journal for a failed node. The first has really recovered it,
- the rest have found the fs clean and report success. */
-
-static void _receive_recovery_status(struct mountgroup *mg, char *buf, size_t len,
- int from)
-{
- struct mg_member *memb;
- int *p, n, i, nodeid, jid, status, found = 0;
-
- n = (len - sizeof(struct gdlm_header)) / (SEND_RS_INTS * sizeof(int));
-
- p = (int *) (buf + sizeof(struct gdlm_header));
-
- for (i = 0; i < n; i++) {
- nodeid = le32_to_cpu(p[i * SEND_RS_INTS]);
- jid = le32_to_cpu(p[i * SEND_RS_INTS + 1]);
- status = le32_to_cpu(p[i * SEND_RS_INTS + 2]);
-
- ASSERT(status == RS_SUCCESS);
-
- found = 0;
- list_for_each_entry(memb, &mg->members_gone, list) {
- if (memb->nodeid != nodeid)
- continue;
- ASSERT(memb->jid == jid);
- ASSERT(memb->recovery_status == RS_NEED_RECOVERY ||
- memb->recovery_status == RS_SUCCESS);
- memb->recovery_status = status;
- found = 1;
- break;
- }
-
- log_group(mg, "receive_recovery_status from %d len %zd "
- "nodeid %d jid %d status %d found %d",
- from, len, nodeid, jid, status, found);
- }
-
- if (from == our_nodeid)
- start_done(mg);
-}
-
-static void process_saved_recovery_status(struct mountgroup *mg)
-{
- struct save_msg *sm, *sm2;
-
- if (list_empty(&mg->saved_messages))
- return;
-
- log_group(mg, "process_saved_recovery_status");
-
- list_for_each_entry_safe(sm, sm2, &mg->saved_messages, list) {
- if (sm->type != MSG_RECOVERY_STATUS)
- continue;
- _receive_recovery_status(mg, sm->buf, sm->len, sm->nodeid);
- list_del(&sm->list);
- free(sm);
- }
-}
-
-static void assign_next_first_mounter(struct mountgroup *mg)
-{
- struct mg_member *memb, *next = NULL;
- int low = -1;
-
- list_for_each_entry(memb, &mg->members, list) {
- if (memb->jid == -2)
- continue;
- if (memb->jid == -9)
- continue;
- if (memb->spectator || memb->readonly || memb->withdrawing ||
- memb->ms_kernel_mount_done)
- continue;
- if (low == -1 || memb->nodeid < low) {
- next = memb;
- low = memb->nodeid;
- }
- }
-
- if (next) {
- log_group(mg, "next first mounter is %d jid %d opts %x",
- next->nodeid, next->jid, next->opts);
- next->opts |= MEMB_OPT_RECOVER;
- ASSERT(next->jid >= 0);
- } else
- log_group(mg, "no next mounter available yet");
-}
-
-#define SEND_MS_INTS 4
-
-void send_mount_status_old(struct mountgroup *mg)
-{
- struct gdlm_header *hd;
- int len, *p;
- char *buf;
-
- len = sizeof(struct gdlm_header) + (SEND_MS_INTS * sizeof(int));
-
- buf = malloc(len);
- if (!buf)
- return;
- memset(buf, 0, len);
-
- hd = (struct gdlm_header *)buf;
- hd->type = MSG_MOUNT_STATUS;
- hd->nodeid = our_nodeid;
- hd->to_nodeid = 0;
-
- p = (int *) (buf + sizeof(struct gdlm_header));
-
- p[0] = cpu_to_le32(mg->first_mounter);
- p[1] = cpu_to_le32(mg->kernel_mount_error);
- p[2] = 0; /* unused */
- p[3] = 0; /* unused */
-
- log_group(mg, "send_mount_status kernel_mount_error %d "
- "first_mounter %d",
- mg->kernel_mount_error,
- mg->first_mounter);
-
- send_group_message_old(mg, len, buf);
-
- free(buf);
-}
-
-static void _receive_mount_status(struct mountgroup *mg, char *buf, size_t len,
- int from)
-{
- struct mg_member *memb, *us;
- int *p;
-
- p = (int *) (buf + sizeof(struct gdlm_header));
-
- memb = find_memb_nodeid(mg, from);
- if (!memb) {
- log_group(mg, "_receive_mount_status no node %d", from);
- return;
- }
-
- memb->ms_kernel_mount_done = 1;
- memb->ms_first_mounter = le32_to_cpu(p[0]);
- memb->ms_kernel_mount_error = le32_to_cpu(p[1]);
-
- log_group(mg, "_receive_mount_status from %d kernel_mount_error %d "
- "first_mounter %d opts %x", from,
- memb->ms_kernel_mount_error, memb->ms_first_mounter,
- memb->opts);
-
- if (memb->opts & MEMB_OPT_RECOVER) {
- ASSERT(memb->ms_first_mounter);
- }
- if (memb->ms_first_mounter) {
- ASSERT(memb->opts & MEMB_OPT_RECOVER);
- }
-
- if (memb->ms_first_mounter) {
- memb->opts &= ~MEMB_OPT_RECOVER;
-
- if (!memb->ms_kernel_mount_error) {
- /* the first mounter has successfully mounted, we can
- go ahead and mount now */
-
- if (mg->mount_client_delay) {
- mg->mount_client_delay = 0;
- notify_mount_client(mg);
- }
- } else {
- /* first mounter mount failed, next low node should be
- made first mounter */
-
- memb->jid = -2;
- if (from == our_nodeid)
- mg->our_jid = -2;
-
- assign_next_first_mounter(mg);
-
- /* if we became the next first mounter, then notify
- mount client */
-
- us = find_memb_nodeid(mg, our_nodeid);
- if (us->opts & MEMB_OPT_RECOVER) {
- log_group(mg, "we are next first mounter");
- mg->first_mounter = 1;
- mg->first_mounter_done = 0;
- mg->mount_client_delay = 0;
- notify_mount_client(mg);
- }
- }
- }
-}
-
-static void receive_mount_status(struct mountgroup *mg, char *buf, size_t len,
- int from)
-{
- log_group(mg, "receive_mount_status from %d len %zd last_cb %d",
- from, len, mg->last_callback);
-
- if (!mg->got_our_options) {
- log_group(mg, "ignore mount_status from %d", from);
- return;
- }
-
- if (!mg->got_our_journals)
- save_message_old(mg, buf, len, from, MSG_MOUNT_STATUS);
- else
- _receive_mount_status(mg, buf, len, from);
-}
-
-/* We delay processing mount_status msesages until we receive the journals
- message for our own mount. Our journals message is a snapshot of the memb
- list at the time our options message is received on the remote node. We
- ignore any messages that would change the memb list prior to seeing our own
- options message and we save any messages that would change the memb list
- after seeing our own options message and before we receive the memb list
- from the journals message. */
-
-static void process_saved_mount_status(struct mountgroup *mg)
-{
- struct save_msg *sm, *sm2;
-
- if (list_empty(&mg->saved_messages))
- return;
-
- log_group(mg, "process_saved_mount_status");
-
- list_for_each_entry_safe(sm, sm2, &mg->saved_messages, list) {
- if (sm->type != MSG_MOUNT_STATUS)
- continue;
- _receive_mount_status(mg, sm->buf, sm->len, sm->nodeid);
- list_del(&sm->list);
- free(sm);
- }
-}
-
-static void receive_recovery_status(struct mountgroup *mg, char *buf, size_t len,
- int from)
-{
- switch (mg->last_callback) {
- case DO_STOP:
- save_message_old(mg, buf, len, from, MSG_RECOVERY_STATUS);
- break;
- case DO_START:
- _receive_recovery_status(mg, buf, len, from);
- break;
- default:
- log_group(mg, "receive_recovery_status %d last_callback %d",
- from, mg->last_callback);
- }
-}
-
-/* tell others that all journals are recovered; they should clear
- memb's from members_gone, clear needs_recovery and unblock locks */
-
-static void send_recovery_done(struct mountgroup *mg)
-{
- struct gdlm_header *hd;
- int len;
- char *buf;
-
- len = sizeof(struct gdlm_header);
-
- buf = malloc(len);
- if (!buf)
- return;
- memset(buf, 0, len);
-
- hd = (struct gdlm_header *)buf;
- hd->type = MSG_RECOVERY_DONE;
- hd->nodeid = our_nodeid;
- hd->to_nodeid = 0;
-
- send_group_message_old(mg, len, buf);
-
- free(buf);
-}
-
-static void receive_recovery_done(struct mountgroup *mg, char *buf, size_t len,
- int from)
-{
- struct mg_member *memb, *safe;
-
- log_group(mg, "receive_recovery_done from %d needs_recovery %d",
- from, mg->needs_recovery);
-
- list_for_each_entry_safe(memb, safe, &mg->members_gone, list) {
- log_group(mg, "receive_recovery_done clear jid %d nodeid %d",
- memb->jid, memb->nodeid);
- list_del(&memb->list);
- free(memb);
- }
-
- mg->needs_recovery = 0;
- mg->kernel_stopped = 0; /* for queries */
- set_sysfs(mg, "block", 0);
-}
-
-void send_remount_old(struct mountgroup *mg, struct gfsc_mount_args *ma)
-{
- struct gdlm_header *hd;
- char *buf;
- int len;
- int ro = strstr(ma->options, "ro") ? 1 : 0;
-
- len = sizeof(struct gdlm_header) + MAX_OPTIONS_LEN;
-
- buf = malloc(len);
- if (!buf)
- return;
- memset(buf, 0, len);
-
- hd = (struct gdlm_header *)buf;
- hd->type = MSG_REMOUNT;
- hd->nodeid = our_nodeid;
- hd->to_nodeid = 0;
-
- strcpy(buf+sizeof(struct gdlm_header), ro ? "ro" : "rw");
-
- log_group(mg, "send_remount_old len %d \"%s\"", len,
- buf+sizeof(struct gdlm_header));
-
- send_group_message_old(mg, len, buf);
-
- free(buf);
-}
-
-static void receive_remount(struct mountgroup *mg, char *buf, size_t len, int from)
-{
- struct mg_member *memb;
- char *options;
- int rw = 0, ro = 0;
- int result = 0;
-
- options = (char *) (buf + sizeof(struct gdlm_header));
-
- memb = find_memb_nodeid(mg, from);
- if (!memb) {
- log_error("receive_remount: unknown nodeid %d", from);
- return;
- }
-
- if (strstr(options, "rw"))
- rw = 1;
- else if (strstr(options, "ro"))
- ro = 1;
- else {
- result = -EINVAL;
- goto out;
- }
-
- /* FIXME: check if we've even fully completed our normal mount yet
- (received our own mount-status?) if not, then disallow remount */
-
- /* FIXME: going ro->rw may mean we can now do journal or first-mounter
- recovery that we couldn't do before. */
-
- memb->readonly = ro;
- memb->rw = !ro;
-
- if (ro) {
- memb->opts &= ~MEMB_OPT_RW;
- memb->opts |= MEMB_OPT_RO;
- } else {
- memb->opts &= ~MEMB_OPT_RO;
- memb->opts |= MEMB_OPT_RW;
- }
- out:
- if (from == our_nodeid) {
- if (!result) {
- mg->rw = memb->rw;
- mg->ro = memb->readonly;
- }
- client_reply_remount(mg, mg->remount_client, result);
- }
-
- log_group(mg, "receive_remount from %d rw=%d ro=%d opts=%x",
- from, memb->rw, memb->readonly, memb->opts);
-}
-
-static void set_our_memb_options(struct mountgroup *mg)
-{
- struct mg_member *memb;
- memb = find_memb_nodeid(mg, our_nodeid);
- ASSERT(memb);
-
- if (mg->ro) {
- memb->readonly = 1;
- memb->opts |= MEMB_OPT_RO;
- } else if (mg->spectator) {
- memb->spectator = 1;
- memb->opts |= MEMB_OPT_SPECT;
- } else if (mg->rw) {
- memb->rw = 1;
- memb->opts |= MEMB_OPT_RW;
- }
-}
-
-static void send_options(struct mountgroup *mg)
-{
- struct gdlm_header *hd;
- int len;
- char *buf;
-
- len = sizeof(struct gdlm_header) + MAX_OPTIONS_LEN;
-
- buf = malloc(len);
- if (!buf)
- return;
- memset(buf, 0, len);
-
- hd = (struct gdlm_header *)buf;
- hd->type = MSG_OPTIONS;
- hd->nodeid = our_nodeid;
- hd->to_nodeid = 0;
-
- strncpy(buf+sizeof(struct gdlm_header), mg->mount_args.options,
- MAX_OPTIONS_LEN-1);
-
- log_group(mg, "send_options len %d \"%s\"", len,
- buf+sizeof(struct gdlm_header));
-
- send_group_message_old(mg, len, buf);
-
- free(buf);
-}
-
-/* We set the new member's jid to the lowest unused jid. If we're the lowest
- existing member (by nodeid), then send jid info to the new node. */
-
-/* Look at rw/ro/spectator status of all existing mounters and whether
- we need to do recovery. Based on that, decide if the current mount
- mode (ro/spectator) is permitted; if not, set jid = -2. If spectator
- mount and it's ok, set jid = -1. If ro or rw mount and it's ok, set
- real jid. */
-
-static int assign_journal(struct mountgroup *mg, struct mg_member *new)
-{
- struct mg_member *memb, *memb_recover = NULL, *memb_mounted = NULL;
- int i, total, rw_count, ro_count, spect_count, invalid_count;
-
- total = rw_count = ro_count = spect_count = invalid_count = 0;
-
- list_for_each_entry(memb, &mg->members, list) {
- if (memb->nodeid == new->nodeid)
- continue;
- total++;
- if (memb->jid == -2)
- invalid_count++;
- else if (memb->spectator)
- spect_count++;
- else if (memb->rw)
- rw_count++;
- else if (memb->readonly)
- ro_count++;
-
- if (memb->opts & MEMB_OPT_RECOVER) {
- memb_recover = memb;
- log_group(mg, "assign_journal: memb %d has OPT_RECOVER",
- memb->nodeid);
- }
-
- if (memb->ms_kernel_mount_done && !memb->ms_kernel_mount_error)
- memb_mounted = memb;
- }
-
- log_group(mg, "assign_journal: total %d iv %d rw %d ro %d spect %d "
- "needs_recovery %d", total, invalid_count, rw_count,
- ro_count, spect_count, mg->needs_recovery);
-
- if (new->spectator) {
- log_group(mg, "assign_journal: new spectator allowed");
- new->jid = -1;
- goto out;
- }
-
- for (i = 0; i < 1024; i++) {
- memb = find_memb_jid(mg, i);
- if (!memb) {
- new->jid = i;
- break;
- }
- }
-
- /* Repeat first-mounter recovery: the fs has been mounted and in-use,
- but nodes have failed and none of the current mounters has been able
- to do recovery (all remaining nodes may be ro/spect for example).
- This puts us into the special "needs_recovery" state where new
- mounters are asked to do first-mounter recovery of the fs while
- the current mounters sit in a blocked state. */
-
- if (mg->needs_recovery) {
- if (!memb_recover) {
- log_group(mg, "assign_journal: needs_recovery: "
- "new memb %d gets OPT_RECOVER",
- new->nodeid);
- new->opts |= MEMB_OPT_RECOVER;
- } else {
- log_group(mg, "assign_journal: needs_recovery: "
- "new memb %d memb %d has OPT_RECOVER",
- new->nodeid, memb_recover->nodeid);
- }
- goto out;
- }
-
- /* Initial first-mounter recovery: the fs is coming online, the first
- mg member assumes first-mounter role and other nodes join the mg
- while the first-mounter is working. These non-first mounters wait
- for the first-mounter to finish before notifying mount.gfs. If the
- first-mounter fails, one of them will become the first-mounter. */
-
- /* it shouldn't be possible to have someone doing first mounter
- recovery and also have someone with the fs fully mounted */
-
- if (memb_mounted && memb_recover) {
- log_group(mg, "memb_mounted %d memb_recover %d",
- memb_mounted->nodeid, memb_recover->nodeid);
- ASSERT(0);
- }
-
- /* someone has successfully mounted the fs which means the fs doesn't
- need first mounter recovery */
-
- if (memb_mounted) {
- log_group(mg, "assign_journal: no first recovery needed %d",
- memb_mounted->nodeid);
- goto out;
- }
-
- /* someone is currently doing first mounter recovery, they'll send
- mount_status when they're done letting everyone know the result */
-
- if (memb_recover) {
- log_group(mg, "assign_journal: %d doing first recovery",
- memb_recover->nodeid);
- goto out;
- }
-
- /* when we received our journals, no one was flagged with OPT_RECOVER
- which means no first mounter recovery is needed or is current */
-
- if (mg->global_first_recover_done) {
- log_group(mg, "assign_journal: global_first_recover_done");
- goto out;
- }
-
- /* no one has done kernel mount successfully and no one is doing first
- mounter recovery, the new node gets to try first mounter recovery */
-
- log_group(mg, "kernel_mount_done %d kernel_mount_error %d "
- "first_mounter %d first_mounter_done %d",
- mg->kernel_mount_done, mg->kernel_mount_error,
- mg->first_mounter, mg->first_mounter_done);
-
- log_group(mg, "assign_journal: new memb %d gets OPT_RECOVER for: "
- "fs not mounted", new->nodeid);
- new->opts |= MEMB_OPT_RECOVER;
-
- out:
- log_group(mg, "assign_journal: new member %d got jid %d opts %x",
- new->nodeid, new->jid, new->opts);
-
- if (mg->master_nodeid == our_nodeid) {
- store_plocks(mg, new->nodeid);
- send_journals(mg, new->nodeid);
- }
- return 0;
-}
-
-static void _receive_options(struct mountgroup *mg, char *buf, size_t len,
- int from)
-{
- struct mg_member *memb;
- struct gdlm_header *hd;
- char *options;
-
- hd = (struct gdlm_header *)buf;
- options = (char *) (buf + sizeof(struct gdlm_header));
-
- memb = find_memb_nodeid(mg, from);
- if (!memb) {
- log_error("unknown nodeid %d for options message", from);
- return;
- }
-
- if (strstr(options, "spectator")) {
- memb->spectator = 1;
- memb->opts |= MEMB_OPT_SPECT;
- } else if (strstr(options, "rw")) {
- memb->rw = 1;
- memb->opts |= MEMB_OPT_RW;
- } else if (strstr(options, "ro")) {
- memb->readonly = 1;
- memb->opts |= MEMB_OPT_RO;
- }
-
- log_group(mg, "_receive_options from %d rw=%d ro=%d spect=%d opts=%x",
- from, memb->rw, memb->readonly, memb->spectator, memb->opts);
-
- assign_journal(mg, memb);
-}
-
-static void receive_options(struct mountgroup *mg, char *buf, size_t len, int from)
-{
- struct gdlm_header *hd = (struct gdlm_header *)buf;
- struct mg_member *memb;
-
- log_group(mg, "receive_options from %d len %zd last_cb %d",
- from, len, mg->last_callback);
-
- if (hd->nodeid == our_nodeid) {
- mg->got_our_options = 1;
- mg->save_plocks = 1;
- return;
- }
-
- if (!mg->got_our_options) {
- log_group(mg, "ignore options from %d", from);
- return;
- }
-
- /* we can receive an options message before getting the start
- that adds the mounting node that sent the options, or
- we can receive options messages before we get the journals
- message for out own mount */
-
- memb = find_memb_nodeid(mg, from);
-
- if (!memb || !mg->got_our_journals)
- save_message_old(mg, buf, len, from, MSG_OPTIONS);
- else
- _receive_options(mg, buf, len, from);
-}
-
-static void process_saved_options(struct mountgroup *mg)
-{
- struct save_msg *sm, *sm2;
-
- if (list_empty(&mg->saved_messages))
- return;
-
- log_group(mg, "process_saved_options");
-
- list_for_each_entry_safe(sm, sm2, &mg->saved_messages, list) {
- if (sm->type != MSG_OPTIONS)
- continue;
- _receive_options(mg, sm->buf, sm->len, sm->nodeid);
- list_del(&sm->list);
- free(sm);
- }
-}
-
-#define NUM 3
-
-/* send nodeid/jid/opts of every member to nodeid */
-
-static void send_journals(struct mountgroup *mg, int nodeid)
-{
- struct mg_member *memb;
- struct gdlm_header *hd;
- int i, len;
- char *buf;
- int *ids;
-
- len = sizeof(struct gdlm_header) + (mg->memb_count * NUM * sizeof(int));
-
- buf = malloc(len);
- if (!buf)
- return;
- memset(buf, 0, len);
-
- hd = (struct gdlm_header *)buf;
- hd->type = MSG_JOURNAL;
- hd->nodeid = our_nodeid;
- hd->to_nodeid = nodeid;
- ids = (int *) (buf + sizeof(struct gdlm_header));
-
- i = 0;
- list_for_each_entry(memb, &mg->members, list) {
- ids[i] = cpu_to_le32(memb->nodeid);
- i++;
- ids[i] = cpu_to_le32(memb->jid);
- i++;
- ids[i] = cpu_to_le32(memb->opts);
- i++;
- }
-
- log_group(mg, "send_journals to %d len %d count %d", nodeid, len, i);
-
- send_group_message_old(mg, len, buf);
-
- free(buf);
-}
-
-static void received_our_jid(struct mountgroup *mg)
-{
- log_group(mg, "received_our_jid %d", mg->our_jid);
-
- /* we've been given jid of -2 which means we're not permitted
- to mount the fs; probably because we're trying to mount readonly
- but the next mounter is required to be rw */
-
- if (mg->our_jid == -2) {
- mg->mount_client_result = -EUCLEAN;
- goto out;
- }
-
- /* fs needs recovery and existing mounters can't recover it,
- i.e. they're spectator/readonly or the first mounter's
- mount(2) failed, so we're told to do first-mounter recovery
- on the fs. */
-
- if (local_first_mounter_recovery(mg)) {
- log_group(mg, "we're told to do first mounter recovery");
- mg->first_mounter = 1;
- mg->first_mounter_done = 0;
- mg->mount_client_delay = 0;
- mg->save_plocks = 0;
- goto out;
- } else if (remote_first_mounter_recovery(mg)) {
- /* delay notifying mount client until we get a successful
- mount status from the first mounter */
- log_group(mg, "other node doing first mounter recovery, "
- "set mount_client_delay");
- mg->mount_client_delay = 1;
- mg->save_plocks = 0;
- return;
- }
-
- retrieve_plocks(mg);
- mg->save_plocks = 0;
- process_saved_plocks(mg);
- out:
- notify_mount_client(mg);
-}
-
-static void _receive_journals(struct mountgroup *mg, char *buf, size_t len,
- int from)
-{
- struct mg_member *memb, *memb2;
- struct gdlm_header *hd;
- int *ids, count, i, nodeid, jid, opts;
- int current_first_recover = 0;
-
- hd = (struct gdlm_header *)buf;
-
- count = (len - sizeof(struct gdlm_header)) / (NUM * sizeof(int));
- ids = (int *) (buf + sizeof(struct gdlm_header));
-
- for (i = 0; i < count; i++) {
- nodeid = le32_to_cpu(ids[i * NUM]);
- jid = le32_to_cpu(ids[i * NUM + 1]);
- opts = le32_to_cpu(ids[i * NUM + 2]);
-
- log_debug("receive nodeid %d jid %d opts %x",
- nodeid, jid, opts);
-
- memb = find_memb_nodeid(mg, nodeid);
- memb2 = find_memb_jid(mg, jid);
-
- if (!memb || memb2) {
- log_error("invalid journals message "
- "nodeid %d jid %d opts %x",
- nodeid, jid, opts);
- }
- if (!memb)
- continue;
-
- memb->jid = jid;
-
- if (nodeid == our_nodeid) {
- mg->our_jid = jid;
- /* set_our_memb_options() sets rest */
- if (opts & MEMB_OPT_RECOVER)
- memb->opts |= MEMB_OPT_RECOVER;
- } else {
- memb->opts = opts;
- if (opts & MEMB_OPT_RO)
- memb->readonly = 1;
- else if (opts & MEMB_OPT_RW)
- memb->rw = 1;
- else if (opts & MEMB_OPT_SPECT)
- memb->spectator = 1;
- }
-
- if (opts & MEMB_OPT_RECOVER)
- current_first_recover = 1;
- }
-
- /* FIXME: use global_first_recover_done more widely instead of
- as a single special case */
- if (!current_first_recover)
- mg->global_first_recover_done = 1;
-
- process_saved_mount_status(mg);
-
- /* we delay processing any options messages from new mounters
- until after we receive the journals message for our own mount */
-
- process_saved_options(mg);
-
- received_our_jid(mg);
-}
-
-static void receive_journals(struct mountgroup *mg, char *buf, size_t len,
- int from)
-{
- struct gdlm_header *hd = (struct gdlm_header *)buf;
- struct mg_member *memb;
- int count;
-
- count = (len - sizeof(struct gdlm_header)) / (NUM * sizeof(int));
-
- log_group(mg, "receive_journals from %d to %d len %zd count %d cb %d",
- from, hd->to_nodeid, len, count, mg->last_callback);
-
- /* just like we can receive an options msg from a newly added node
- before we get the start adding it, we can receive the journals
- message sent to it before we get the start adding it */
-
- memb = find_memb_nodeid(mg, hd->to_nodeid);
- if (!memb) {
- log_group(mg, "receive_journals from %d to unknown %d",
- from, hd->to_nodeid);
- return;
- }
- memb->needs_journals = 0;
-
- if (hd->to_nodeid && hd->to_nodeid != our_nodeid)
- return;
-
- if (mg->got_our_journals) {
- log_group(mg, "receive_journals from %d duplicate", from);
- return;
- }
- mg->got_our_journals = 1;
-
- _receive_journals(mg, buf, len, from);
-}
-
-static void add_ordered_member(struct mountgroup *mg, struct mg_member *new)
-{
- struct mg_member *memb = NULL;
- struct list_head *tmp;
- struct list_head *newlist = &new->list;
- struct list_head *head = &mg->members;
-
- list_for_each(tmp, head) {
- memb = list_entry(tmp, struct mg_member, list);
- if (new->nodeid < memb->nodeid)
- break;
- }
-
- if (!memb)
- list_add_tail(newlist, head);
- else {
- /* FIXME: can use list macro here */
- newlist->prev = tmp->prev;
- newlist->next = tmp;
- tmp->prev->next = newlist;
- tmp->prev = newlist;
- }
-}
-
-static int add_member(struct mountgroup *mg, int nodeid)
-{
- struct mg_member *memb;
-
- memb = malloc(sizeof(struct mg_member));
- if (!memb)
- return -ENOMEM;
-
- memset(memb, 0, sizeof(struct mg_member));
-
- memb->nodeid = nodeid;
- memb->jid = JID_INIT;
- add_ordered_member(mg, memb);
- mg->memb_count++;
-
- if (!mg->init)
- memb->needs_journals = 1;
-
- return 0;
-}
-
-static int is_member(struct mountgroup *mg, int nodeid)
-{
- struct mg_member *memb;
-
- list_for_each_entry(memb, &mg->members, list) {
- if (memb->nodeid == nodeid)
- return 1;
- }
- return 0;
-}
-
-static int is_removed(struct mountgroup *mg, int nodeid)
-{
- struct mg_member *memb;
-
- list_for_each_entry(memb, &mg->members_gone, list) {
- if (memb->nodeid == nodeid)
- return 1;
- }
- return 0;
-}
-
-/* New mounters may be waiting for a journals message that a failed node (as
- master) would have sent. If the master failed and we're the new master,
- then send a journals message to any nodes for whom we've not seen a journals
- message. We also need to checkpoint the plock state for the new nodes to
- read after they get their journals message. */
-
-static void resend_journals(struct mountgroup *mg)
-{
- struct mg_member *memb;
- int stored_plocks = 0;
-
- list_for_each_entry(memb, &mg->members, list) {
- if (!memb->needs_journals)
- continue;
-
- if (!stored_plocks) {
- store_plocks(mg, memb->nodeid);
- stored_plocks = 1;
- }
-
- log_group(mg, "resend_journals to %d", memb->nodeid);
- send_journals(mg, memb->nodeid);
- }
-}
-
-/* The master node is the member of the group with the lowest nodeid who
- was also a member of the last "finished" group, i.e. a member of the
- group the last time it got a finish callback. The job of the master
- is to send state info to new nodes joining the group, and doing that
- requires that the master has all the state to send -- a new joining
- node that has the lowest nodeid doesn't have any state, which is why
- we add the "finished" requirement. */
-
-static void update_master_nodeid(struct mountgroup *mg)
-{
- struct mg_member *memb;
- int new = -1, low = -1;
-
- list_for_each_entry(memb, &mg->members, list) {
- if (low == -1 || memb->nodeid < low)
- low = memb->nodeid;
- if (!memb->finished)
- continue;
- if (new == -1 || memb->nodeid < new)
- new = memb->nodeid;
- }
- mg->master_nodeid = new;
- mg->low_nodeid = low;
-}
-
-/* This can happen before we receive a journals message for our mount. */
-
-static void recover_members(struct mountgroup *mg, int num_nodes,
- int *nodeids, int *pos_out, int *neg_out)
-{
- struct mg_member *memb, *safe, *memb_gone_recover = NULL;
- int i, found, id, pos = 0, neg = 0, prev_master_nodeid;
- int master_failed = 0;
-
- /* move departed nodes from members list to members_gone */
-
- list_for_each_entry_safe(memb, safe, &mg->members, list) {
- found = 0;
- for (i = 0; i < num_nodes; i++) {
- if (memb->nodeid == nodeids[i]) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- neg++;
-
- list_move(&memb->list, &mg->members_gone);
- memb->gone_event = mg->start_event_nr;
- memb->gone_type = mg->start_type;
- mg->memb_count--;
-
- memb->tell_gfs_to_recover = 0;
- memb->recovery_status = 0;
- memb->local_recovery_status = 0;
-
- /* - journal cb for failed or withdrawing nodes
- - failed node was assigned a journal
- - no journal cb if failed node was spectator
- - no journal cb if we've already done a journl cb */
-
- if ((memb->gone_type == GROUP_NODE_FAILED ||
- memb->withdrawing) &&
- memb->jid != JID_INIT &&
- memb->jid != -2 &&
- !memb->spectator &&
- !memb->wait_gfs_recover_done) {
- memb->tell_gfs_to_recover = 1;
- memb->recovery_status = RS_NEED_RECOVERY;
- memb->local_recovery_status = RS_NEED_RECOVERY;
- }
-
- log_group(mg, "remove member %d tell_gfs_to_recover %d "
- "(%d,%d,%d,%d,%d,%d)",
- memb->nodeid, memb->tell_gfs_to_recover,
- mg->spectator,
- mg->start_type,
- memb->withdrawing,
- memb->jid,
- memb->spectator,
- memb->wait_gfs_recover_done);
-
- if (mg->master_nodeid == memb->nodeid &&
- memb->gone_type == GROUP_NODE_FAILED)
- master_failed = 1;
-
- if (memb->opts & MEMB_OPT_RECOVER)
- memb_gone_recover = memb;
- }
- }
-
- /* add new nodes to members list */
-
- for (i = 0; i < num_nodes; i++) {
- id = nodeids[i];
- if (is_member(mg, id))
- continue;
- add_member(mg, id);
- pos++;
- log_group(mg, "add member %d", id);
- }
-
- prev_master_nodeid = mg->master_nodeid;
- update_master_nodeid(mg);
-
- *pos_out = pos;
- *neg_out = neg;
-
- log_group(mg, "total members %d master_nodeid %d prev %d",
- mg->memb_count, mg->master_nodeid, prev_master_nodeid);
-
-
- /* The master failed and we're the new master, we need to:
-
- - unlink the ckpt that the failed master had open so new ckpts
- can be created down the road
- - resend journals msg to any nodes that needed one from the
- failed master
- - store plocks in ckpt for the new mounters to read when they
- get the journals msg from us */
-
- if (neg && master_failed &&
- (prev_master_nodeid != -1) &&
- (prev_master_nodeid != mg->master_nodeid) &&
- (our_nodeid == mg->master_nodeid)) {
- log_group(mg, "unlink ckpt for failed master %d",
- prev_master_nodeid);
- unlink_checkpoint(mg);
- resend_journals(mg);
- }
-
- /* Do we need a new first mounter?
-
- If we've not gotten a journals message yet (implies we're mounting)
- and there's only one node left in the group (us, after removing the
- failed node), then it's possible that the failed node was doing
- first mounter recovery, so we need to become first mounter.
-
- If we've received a journals message, we can check if the failed
- node was doing first mounter recovery (MEMB_OPT_RECOVER set) and
- if so select the next first mounter. */
-
- if (!neg)
- return;
-
- if (!mg->got_our_journals && mg->memb_count == 1) {
- log_group(mg, "we are left alone, act as first mounter");
- unlink_checkpoint(mg);
- memb = find_memb_nodeid(mg, our_nodeid);
- memb->jid = 0;
- memb->opts |= MEMB_OPT_RECOVER;
- mg->our_jid = 0;
- mg->first_mounter = 1;
- mg->first_mounter_done = 0;
- mg->got_our_options = 1;
- mg->got_our_journals = 1;
- mg->mount_client_delay = 0;
- notify_mount_client(mg);
- return;
- }
-
- if (memb_gone_recover) {
- log_group(mg, "failed node %d had MEMB_OPT_RECOVER",
- memb_gone_recover->nodeid);
- memb_gone_recover->tell_gfs_to_recover = 0;
- }
-
- if (memb_gone_recover && mg->got_our_journals) {
- assign_next_first_mounter(mg);
- memb = find_memb_nodeid(mg, our_nodeid);
- if (memb->opts & MEMB_OPT_RECOVER) {
- log_group(mg, "first mounter failed, we get "
- "MEMB_OPT_RECOVER");
- unlink_checkpoint(mg);
- memb->opts |= MEMB_OPT_RECOVER;
- mg->first_mounter = 1;
- mg->first_mounter_done = 0;
- mg->mount_client_delay = 0;
- notify_mount_client(mg);
- }
- }
-}
-
-int gfs_join_mountgroup_old(struct mountgroup *mg, struct gfsc_mount_args *ma)
-{
- int rv;
-
- if (strlen(ma->options) > MAX_OPTIONS_LEN-1) {
- log_error("join: options too long %zu", strlen(ma->options));
- return -EMLINK;
- }
-
- rv = group_join(gh, mg->name);
- if (rv)
- return -ENOTCONN;
- return 0;
-}
-
-/* recover_members() discovers which nodes need journal recovery
- and moves the memb structs for those nodes into members_gone
- and sets memb->tell_gfs_to_recover on them */
-
-/* we don't want to tell gfs-kernel to do journal recovery for a failed
- node in a number of cases:
- - we're a spectator or readonly mount
- - gfs-kernel is currently withdrawing
- - we're mounting and haven't received a journals message yet
- - we're mounting and got a kernel mount error back from mount.gfs
- - we're mounting and haven't notified mount.gfs yet (to do mount(2))
- - we're mounting and got_kernel_mount is 0, i.e. we've not seen a uevent
- related to the kernel mount yet
- (some of the mounting checks should be obviated by others)
-
- the problem we're trying to avoid here is telling gfs-kernel to do
- recovery when it can't for some reason and then waiting forever for
- a recovery_done signal that will never arrive. */
-
-static void recover_journals(struct mountgroup *mg)
-{
- struct mg_member *memb;
- int rv;
-
- if (mg->spectator ||
- mg->ro ||
- mg->withdraw_suspend ||
- mg->our_jid == JID_INIT ||
- mg->kernel_mount_error ||
- !mg->mount_client_notified ||
- !mg->got_kernel_mount ||
- !mg->kernel_mount_done) {
- log_group(mg, "recover_journals: unable %d,%d,%d,%d,%d,%d,%d,%d",
- mg->spectator,
- mg->ro,
- mg->withdraw_suspend,
- mg->our_jid,
- mg->kernel_mount_error,
- mg->mount_client_notified,
- mg->got_kernel_mount,
- mg->kernel_mount_done);
-
- list_for_each_entry(memb, &mg->members_gone, list) {
- log_group(mg, "member gone %d jid %d "
- "tell_gfs_to_recover %d",
- memb->nodeid, memb->jid,
- memb->tell_gfs_to_recover);
-
- if (memb->tell_gfs_to_recover) {
- memb->tell_gfs_to_recover = 0;
- memb->local_recovery_status = RS_READONLY;
- }
- }
- start_done(mg);
- return;
- }
-
- /* we feed one jid into the kernel for recovery instead of all
- at once because we need to get the result of each independently
- through the single recovery_done sysfs file */
-
- list_for_each_entry(memb, &mg->members_gone, list) {
- if (memb->wait_gfs_recover_done) {
- log_group(mg, "delay new gfs recovery, "
- "wait_gfs_recover_done for nodeid %d jid %d",
- memb->nodeid, memb->jid);
- return;
- }
- }
-
- list_for_each_entry(memb, &mg->members_gone, list) {
- if (!memb->tell_gfs_to_recover)
- continue;
-
- log_group(mg, "recover journal %d nodeid %d",
- memb->jid, memb->nodeid);
-
- rv = set_sysfs(mg, "recover", memb->jid);
- if (rv < 0) {
- memb->local_recovery_status = RS_NOFS;
- continue;
- }
- memb->tell_gfs_to_recover = 0;
- memb->wait_gfs_recover_done = 1;
- return;
- }
-
- /* no more journals to attempt to recover, if we've been successful
- recovering any then send out status, if not then start_done...
- receiving no status message from us before start_done means we
- didn't successfully recover any journals. If we send out status,
- then delay start_done until we get our own message (so all nodes
- will get the status before finish) */
-
- list_for_each_entry(memb, &mg->members_gone, list) {
- if (memb->local_recovery_status == RS_SUCCESS) {
- send_recovery_status(mg);
- log_group(mg, "delay start_done until status recvd");
- return;
- }
- }
-
- start_done(mg);
-}
-
-/* In some cases, we may be joining a mountgroup with needs_recovery
- set (there are journals that need recovery and current members can't
- recover them because they're ro). In this case, we're told to act
- like the first mounter to cause gfs to try to recovery all journals
- when it mounts. When gfs does this, we'll get recovery_done's for
- the individual journals it recovers (ignored) and finally, if all
- journals are ok, an others_may_mount/first_done. */
-
-/* When gfs does first-mount recovery, the mount(2) fails if it can't
- recover one of the journals. If we get o_m_m, then we know it was
- able to successfully recover all the journals. */
-
-/* When we're the first mounter, gfs does recovery on all the journals
- and does "recovery_done" callbacks when it finishes each. We ignore
- these and wait for gfs to be finished with all at which point it calls
- others_may_mount() and first_done is set. */
-
-static int kernel_recovery_done_first(struct mountgroup *mg, int first_done)
-{
- int rv;
-
- if (first_done < 0) {
- /* for back compat, sysfs file deprecated */
- rv = read_sysfs_int(mg, "first_done", &first_done);
- if (rv < 0)
- return rv;
- }
-
- log_group(mg, "kernel_recovery_done_first first_done %d", first_done);
-
- if (mg->kernel_mount_done)
- log_group(mg, "FIXME: assuming kernel_mount_done comes after "
- "first_done");
-
- if (first_done) {
- mg->first_mounter_done = 1;
- send_recovery_done(mg);
- }
-
- return 0;
-}
-
-static int need_kernel_recovery_done(struct mountgroup *mg)
-{
- struct mg_member *memb;
-
- list_for_each_entry(memb, &mg->members_gone, list) {
- if (memb->wait_gfs_recover_done)
- return 1;
- }
- return 0;
-}
-
-/* Note: when a readonly node fails we do consider its journal (and the
- fs) to need recovery... not sure this is really necessary, but
- the readonly node did "own" a journal so it seems proper to recover
- it even if the node wasn't writing to it. So, if there are 3 ro
- nodes mounting the fs and one fails, gfs on the remaining 2 will
- remain blocked until an rw node mounts, and the next mounter must
- be rw. */
-
-int process_recovery_uevent_old(char *name, int jid_done, int status, int first)
-{
- struct mountgroup *mg;
- struct mg_member *memb;
- const char *ss;
- int rv, found = 0;
-
- mg = find_mg(name);
- if (!mg) {
- log_error("recovery_done: unknown mount group %s", name);
- return -1;
- }
-
- if (mg->first_mounter && !mg->first_mounter_done)
- return kernel_recovery_done_first(mg, first);
-
- if (jid_done < 0) {
- /* for back compat, sysfs file deprecated */
- rv = read_sysfs_int(mg, "recover_done", &jid_done);
- if (rv < 0)
- return rv;
- }
-
- list_for_each_entry(memb, &mg->members_gone, list) {
- if (memb->jid == jid_done) {
- if (memb->wait_gfs_recover_done) {
- memb->wait_gfs_recover_done = 0;
- found = 1;
- }
- break;
- }
- }
-
- /* We need to ignore recovery_done callbacks in the case where there
- are a bunch of recovery_done callbacks for the first mounter, but
- we detect "first_done" before we've processed all the
- recovery_done's. */
-
- if (!found) {
- log_group(mg, "recovery_done jid %d ignored, first %d,%d",
- jid_done, mg->first_mounter, mg->first_mounter_done);
- return 0;
- }
-
- if (status < 0) {
- /* for back compat, sysfs file deprecated */
- rv = read_sysfs_int(mg, "recover_status", &status);
- if (rv < 0) {
- log_group(mg, "recovery_done jid %d nodeid %d sysfs error %d",
- memb->jid, memb->nodeid, rv);
- memb->local_recovery_status = RS_NOFS;
- goto out;
- }
- }
-
- switch (status) {
- case LM_RD_GAVEUP:
- /*
- * This is unfortunate; it's needed for bz 442451 where
- * gfs-kernel fails to acquire the journal lock on all nodes
- * because a withdrawing node has not yet called
- * dlm_release_lockspace() to free it's journal lock. With
- * this, all nodes should repeatedly try to to recover the
- * journal of the withdrawn node until the withdrawing node
- * clears its dlm locks, and gfs on each of the remaining nodes
- * succeeds in doing the recovery.
- */
-
- if (memb->withdrawing) {
- log_group(mg, "recovery_done jid %d nodeid %d retry "
- "for withdraw", memb->jid, memb->nodeid);
- memb->tell_gfs_to_recover = 1;
- memb->wait_gfs_recover_done = 0;
- usleep(500000);
- }
-
- memb->local_recovery_status = RS_GAVEUP;
- ss = "gaveup";
- break;
- case LM_RD_SUCCESS:
- memb->local_recovery_status = RS_SUCCESS;
- ss = "success";
- break;
- default:
- log_error("recovery_done: jid %d nodeid %d unknown status %d",
- memb->jid, memb->nodeid, status);
- ss = "unknown";
- }
-
- log_group(mg, "recovery_done jid %d nodeid %d %s",
- memb->jid, memb->nodeid, ss);
-
- /* sanity check */
- if (need_kernel_recovery_done(mg))
- log_error("recovery_done: should be no pending gfs recoveries");
-
- out:
- recover_journals(mg);
- return 0;
-}
-
-static void leave_mountgroup(struct mountgroup *mg, int mnterr)
-{
- /* sanity check: we should already have gotten the error from
- the mount.gfs mount_done; so this shouldn't happen */
-
- if (mnterr && !mg->kernel_mount_error) {
- log_error("leave: mount_error is new %d %d",
- mg->kernel_mount_error, mnterr);
- }
-
- mg->leaving = 1;
-
- /* Check to see if we're waiting for a kernel recovery_done to do a
- start_done(). If so, call the start_done() here because we won't be
- getting anything else from gfs-kernel which is now gone. */
-
- if (need_kernel_recovery_done(mg)) {
- log_group(mg, "leave: fill in start_done");
- start_done(mg);
- }
-
- group_leave(gh, mg->name);
-}
-
-void do_leave_old(char *name, int mnterr)
-{
- struct mountgroup *mg;
-
- log_debug("do_leave_old %s mnterr %d", name, mnterr);
-
- list_for_each_entry(mg, &withdrawn_mounts, list) {
- if (strcmp(mg->name, name))
- continue;
- log_group(mg, "leave for withdrawn fs");
- list_del(&mg->list);
- free_mg(mg);
- return;
- }
-
- mg = find_mg(name);
- if (!mg) {
- log_error("do_leave_old: %s not found", name);
- return;
- }
-
- leave_mountgroup(mg, mnterr);
-}
-
-/* When mounting a fs, we first join the mountgroup, then tell mount.gfs
- to procede with the kernel mount. Once we're in the mountgroup, we
- can get a stop callback at any time, which requires us to block the
- fs by setting a sysfs file. If the kernel mount is slow, we can get
- a stop callback and try to set the sysfs file before the kernel mount
- has actually created the sysfs files for the fs. This function delays
- any further processing until the sysfs files exist. */
-
-/* This function returns 0 when the kernel mount is successfully detected
- and we know that do_stop() will be able to block the fs.
- This function returns a negative error if it detects the kernel mount
- has failed which means there's nothing to stop and do_stop() can assume
- an implicit stop. */
-
-/* wait for
- - kernel mount to get to the point of creating sysfs files we
- can read (and that do_stop can then use), or
- - kernel mount to fail causing mount.gfs to send us a MOUNT_DONE
- which we read in process_connection() */
-
-static int wait_for_kernel_mount(struct mountgroup *mg)
-{
- int rv, val;
-
- while (1) {
- /* This is the standard way we leave this loop, where the
- kernel mount gets to the point of creating the sysfs files
- which we see by successfully reading "id". With the
- sysfs files in place, do_stop() will be able to block
- the kernel. */
-
- rv = read_sysfs_int(mg, "block", &val);
- if (!rv)
- break;
- usleep(100000);
-
- /* kernel_mount_done is set by mount_done_old() which is called
- by process_connection() if mount.gfs sends MOUNT_DONE. */
-
- if (mg->kernel_mount_done && !mg->kernel_mount_error) {
- /* mount(2) was successful and we should be able
- to read "id" very shortly... */
- continue;
- }
-
- if (mg->kernel_mount_done && mg->kernel_mount_error) {
- /* mount(2) failed, stop becomes implicit */
- break;
- }
-
- /* this should either do nothing and return immediatley, or
- read a MOUNT_DONE from mount.gfs and call mount_done_old()
- which will set kernel_mount_done and set kernel_mount_error */
-
- process_connection(mg->mount_client);
- }
-
- return rv;
-}
-
-/* The processing of new mounters (send/recv options, send/recv journals,
- notify mount.gfs) is not very integrated with the stop/start/finish
- callbacks from libgroup. A start callback just notifies us of a new
- mounter and the options/journals messages drive things from there.
- Recovery for failed nodes _is_ controlled more directly by the
- stop/start/finish callbacks. So, processing new mounters happens
- independently of recovery and of the libgroup callbacks. One place
- where they need to intersect, though, is in stopping/suspending
- gfs-kernel:
- - When we get a stop callback, we need to be certain that gfs-kernel
- is blocked.
- - When a mounter notifies mount.gfs to go ahead, gfs-kernel will
- shortly begin running in an unblocked fashion as it goes through
- the kernel mounting process.
- Given this, we need to be sure that if gfs-kernel is supposed to be
- blocked, we don't notify mount.gfs to go ahead and do the kernel mount
- since that starts gfs-kernel in an unblocked state. */
-
-/* - if we're unmounting, the kernel is gone, so no problem.
- - if we've just mounted and notified mount.gfs, then wait for kernel
- mount and then block.
- - if we're mounting and have not yet notified mount.gfs, then set
- a flag that delays the notification until block is set to 0. */
-
-int do_stop(struct mountgroup *mg)
-{
- int rv;
-
- if (mg->first_mounter && !mg->kernel_mount_done) {
- log_group(mg, "do_stop skip during first mount recovery");
- goto out;
- }
-
- for (;;) {
- rv = set_sysfs(mg, "block", 1);
- if (!rv) {
- mg->kernel_stopped = 1; /* for queries */
- break;
- }
-
- /* We get an error trying to block gfs, this could be due
- to a number of things:
- 1. if the kernel instance of gfs existed before but now
- we can't see it, that must mean it's been unmounted,
- so it's implicitly stopped
- 2. we're in the process of mounting and gfs hasn't created
- the sysfs files for this fs yet
- 3. we're mounting and mount(2) returned an error
- 4. we're mounting but haven't told mount.gfs to go ahead
- with mount(2) yet
- We also need to handle the situation where we get here in
- case 2 but it turns into case 3 while we're in
- wait_for_kernel_mount() */
-
- if (mg->got_kernel_mount) {
- log_group(mg, "do_stop skipped fs unmounted");
- break;
- }
-
- if (mg->mount_client_notified) {
- if (!mg->kernel_mount_error) {
- log_group(mg, "do_stop wait for kernel mount");
- rv = wait_for_kernel_mount(mg);
- if (rv < 0)
- break;
- } else {
- log_group(mg, "do_stop ignore, failed mount");
- break;
- }
- } else {
- log_group(mg, "do_stop causes mount_client_delay");
- mg->mount_client_delay = 1;
- break;
- }
- }
- out:
- group_stop_done(gh, mg->name);
- return 0;
-}
-
-/* After a start that initiated a recovery, everyone will go and see if they
- can do recovery and try if they can. If a node can't, it does start_done,
- if it tries and fails, it does start_done, if it tries and succeeds it
- sends a message and then does start_done once it receives's it back. So,
- when we get a finish we know that we have all the results from the recovery
- cycle and can judge if everything is recovered properly or not. If so, we
- can unblock locks (in the finish), if not, we leave them blocked (in the
- finish).
-
- If we leave locks blocked in the finish, then they can only be unblocked
- after someone is able to do the recovery that's needed. So, leaving locks
- blocked in a finish because recovery hasn't worked puts us into a special
- state: the fs needs recovery, none of the current mounters has been able to
- recover it, all current mounters have locks blocked in gfs, new mounters
- are allowed, nodes can unmount, new mounters are asked to do first-mounter
- recovery, if one of them succeeds then we can all clear this special state
- and unblock locks (the unblock would happen upon recving the success
- message from the new pseudo-first mounter, not as part of a finish), future
- finishes would then go back to being able to unblock locks.
-
- While in this special state, a new node has been added and asked to do
- first-mounter recovery, other nodes can also be added while the new
- first-mounter is active. These other nodes don't notify mount.gfs.
- They'll receive the result of the first mounter and if it succeeded they'll
- notify mount.gfs, otherwise one of them will become the next first-mounter
- and notify mount.gfs. */
-
-int do_finish(struct mountgroup *mg)
-{
- struct mg_member *memb, *safe;
-
- log_group(mg, "finish %d needs_recovery %d", mg->last_finish,
- mg->needs_recovery);
-
- /* members_gone list are the members that were removed from the
- members list when processing a start. members are removed
- from members_gone if their journals have been recovered */
-
- list_for_each_entry_safe(memb, safe, &mg->members_gone, list) {
- if (!memb->recovery_status) {
- list_del(&memb->list);
- free(memb);
- } else if (memb->recovery_status == RS_SUCCESS) {
- ASSERT(memb->gone_event <= mg->last_finish);
- log_group(mg, "finish: recovered jid %d nodeid %d",
- memb->jid, memb->nodeid);
- list_del(&memb->list);
- free(memb);
- } else {
- log_error("%s finish: needs recovery jid %d nodeid %d "
- "status %d", mg->name, memb->jid,
- memb->nodeid, memb->recovery_status);
- mg->needs_recovery = 1;
- }
- }
-
- list_for_each_entry(memb, &mg->members, list)
- memb->finished = 1;
-
- if (mg->group_leave_on_finish) {
- log_group(mg, "leaving group after delay for join to finish");
- group_leave(gh, mg->name);
- mg->group_leave_on_finish = 0;
- return 0;
- }
-
- if (!mg->needs_recovery) {
- mg->kernel_stopped = 0; /* for queries */
- set_sysfs(mg, "block", 0);
-
- /* we may have been holding back our local mount due to
- being stopped/blocked */
- if (mg->mount_client_delay && !first_mounter_recovery(mg)) {
- mg->mount_client_delay = 0;
- notify_mount_client(mg);
- }
- } else
- log_group(mg, "finish: leave locks blocked for needs_recovery");
-
- return 0;
-}
-
-/*
- * - require the first mounter to be rw, not ro or spectator.
- *
- * - if rw mounter fails, leaving only spectator mounters,
- * require the next mounter to be rw, more ro/spectator mounts should
- * fail until the fs is mounted rw.
- *
- * - if last rw mounter fails and ro mounters are left (possibly with
- * some spectators), disallow any ro->rw remounts, leave gfs blocked,
- * require next mounter to be rw, have next mounter do first mount
- * gfs/journal recovery.
- */
-
-/* called for the initial start on the node that's first to mount the fs.
- (it should be ok to let the first mounter be a spectator, gfs should do
- first recovery and bail out if there are any dirty journals) */
-
-/* FIXME: if journal recovery fails on any of the journals, we should
- fail the mount */
-
-static void start_first_mounter(struct mountgroup *mg)
-{
- struct mg_member *memb;
-
- log_group(mg, "start_first_mounter");
- set_our_memb_options(mg);
- memb = find_memb_nodeid(mg, our_nodeid);
- ASSERT(memb);
-
- if (mg->ro || mg->spectator) {
- memb->jid = -2;
- mg->our_jid = -2;
- log_group(mg, "start_first_mounter not rw ro=%d spect=%d",
- mg->ro , mg->spectator);
- mg->mount_client_result = -EUCLEAN;
- } else {
- memb->opts |= MEMB_OPT_RECOVER;
- memb->jid = 0;
- mg->our_jid = 0;
- mg->first_mounter = 1;
- mg->first_mounter_done = 0;
- mg->got_our_options = 1;
- mg->got_our_journals = 1;
- }
- start_done(mg);
- notify_mount_client(mg);
-}
-
-/* called for the initial start on a rw/ro mounter;
- the existing mounters are running start_participant() */
-
-static void start_participant_init(struct mountgroup *mg)
-{
- log_group(mg, "start_participant_init");
- set_our_memb_options(mg);
- send_options(mg);
- start_done(mg);
-}
-
-/* called for a non-initial start on a normal mounter.
- NB we can get here without having received a journals message for
- our (recent) mount yet in which case we don't know the jid or ro/rw
- status of any members, and don't know our own jid. */
-
-static void start_participant(struct mountgroup *mg, int pos, int neg)
-{
- log_group(mg, "start_participant pos=%d neg=%d", pos, neg);
-
- if (pos) {
- start_done(mg);
- /* we save options messages from nodes for whom we've not
- received a start yet */
- process_saved_options(mg);
- } else if (neg) {
- recover_journals(mg);
- process_saved_recovery_status(mg);
- }
-}
-
-/* called for the initial start on a spectator mounter,
- after _receive_journals() */
-
-static void start_spectator_init_2(struct mountgroup *mg)
-{
- log_group(mg, "start_spectator_init_2 our_jid=%d", mg->our_jid);
-
- /* we've been given jid of -2 which means we're not permitted
- to mount the fs; probably because the next mounter must be rw */
-
- if (mg->our_jid == -2) {
- mg->mount_client_result = -EUCLEAN;
- } else
- ASSERT(mg->our_jid == -1);
-
- notify_mount_client(mg);
-}
-
-/* called for the initial start on a spectator mounter */
-
-static void start_spectator_init(struct mountgroup *mg)
-{
- log_group(mg, "start_spectator_init");
- set_our_memb_options(mg);
- send_options(mg);
- start_done(mg);
- mg->start2_fn = start_spectator_init_2;
-}
-
-/* called for a non-initial start on a spectator mounter */
-
-static void start_spectator(struct mountgroup *mg, int pos, int neg)
-{
- log_group(mg, "start_spectator pos=%d neg=%d", pos, neg);
-
- if (pos) {
- start_done(mg);
- process_saved_options(mg);
- } else if (neg) {
- recover_journals(mg);
- process_saved_recovery_status(mg);
- }
-}
-
-/* If nodeA fails, nodeB is recovering journalA and nodeB fails before
- finishing, then nodeC needs to tell gfs to recover both journalA and
- journalB. We do this by setting tell_gfs_to_recover back to 1 for
- any nodes that are still on the members_gone list. */
-
-static void reset_unfinished_recoveries(struct mountgroup *mg)
-{
- struct mg_member *memb;
-
- list_for_each_entry(memb, &mg->members_gone, list) {
- if (memb->recovery_status &&
- memb->recovery_status != RS_NEED_RECOVERY) {
- log_group(mg, "retry unfinished recovery "
- "jid %d nodeid %d",
- memb->jid, memb->nodeid);
- memb->tell_gfs_to_recover = 1;
- memb->recovery_status = RS_NEED_RECOVERY;
- memb->local_recovery_status = RS_NEED_RECOVERY;
- }
- }
-}
-
-/*
- old method:
- A is rw mount, B mounts rw
-
- do_start do_start
- start_participant start_participant_init
- send_options
- receive_options
- start_participant_2
- discover_journals
- assign B a jid
- send_journals
- group_start_done
- receive_journals
- start_participant_init_2
- group_start_done
- do_finish do_finish
-
- new method: decouples stop/start/finish from mount processing
- A is rw mount, B mounts rw
-
- do_start do_start
- start_participant start_participant_init
- start_done send_options
- start_done
- do_finish do_finish
-
- receive_options
- assign_journal
- send_journals
- receive_journals
- start_participant_init_2
- notify_mount_client
-*/
-
-void do_start(struct mountgroup *mg, int type, int member_count, int *nodeids)
-{
- int pos = 0, neg = 0;
-
- mg->start_event_nr = mg->last_start;
- mg->start_type = type;
-
- log_group(mg, "start %d init %d type %d member_count %d",
- mg->last_start, mg->init, type, member_count);
-
- recover_members(mg, member_count, nodeids, &pos, &neg);
- reset_unfinished_recoveries(mg);
-
- if (mg->init) {
- if (member_count == 1)
- start_first_mounter(mg);
- else if (mg->spectator)
- start_spectator_init(mg);
- else
- start_participant_init(mg);
- mg->init = 0;
- } else {
- if (mg->spectator)
- start_spectator(mg, pos, neg);
- else
- start_participant(mg, pos, neg);
- }
-}
-
-/*
- What repurcussions are there from umount shutting down gfs in the
- kernel before we leave the mountgroup? We can no longer participate
- in recovery even though we're in the group -- what are the end cases
- that we need to deal with where this causes a problem? i.e. there
- is a period of time where the mountgroup=A,B,C but the kernel fs
- is only active on A,B, not C. The mountgroup on A,B can't depend
- on the mg on C to necessarily be able to do some things (recovery).
-
- At least in part, it means that after we do an umount and have
- removed the instance of this fs in the kernel, we'll still get
- stop/start/finish callbacks from groupd for which we'll attempt
- and fail to: block/unblock gfs kernel activity, initiate gfs
- journal recovery, get recovery-done signals fromt eh kernel.
-
- We don't want to hang groupd event processing by failing to send
- an ack (stop_done/start_done) back to groupd when it needs one
- to procede. In the case where we get a start for a failed node
- that needs journal recovery, we have a problem because we wait to
- call group_start_done() until gfs in the kernel to signal that
- the journal recovery is done. If we've unmounted gfs isn't there
- any more to give us this signal and we'll never call start_done.
-
- update: we should be dealing with all these issues correctly now. */
-
-int do_terminate(struct mountgroup *mg)
-{
- purge_plocks(mg, 0, 1);
-
- if (mg->withdraw_suspend) {
- log_group(mg, "termination of our withdraw leave");
- set_sysfs(mg, "withdraw", 1);
- list_move(&mg->list, &withdrawn_mounts);
- } else {
- log_group(mg, "termination of our unmount leave");
- list_del(&mg->list);
- free(mg);
- }
-
- return 0;
-}
-
-static void do_deliver(int nodeid, char *data, size_t len)
-{
- struct mountgroup *mg;
- struct gdlm_header *hd;
-
- hd = (struct gdlm_header *) data;
-
- mg = find_mg(hd->name);
- if (!mg) {
- /*
- log_error("cpg message from %d len %d no group %s",
- nodeid, len, hd->name);
- */
- return;
- }
-
- hd->version[0] = le16_to_cpu(hd->version[0]);
- hd->version[1] = le16_to_cpu(hd->version[1]);
- hd->version[2] = le16_to_cpu(hd->version[2]);
- hd->type = le16_to_cpu(hd->type);
- hd->nodeid = le32_to_cpu(hd->nodeid);
- hd->to_nodeid = le32_to_cpu(hd->to_nodeid);
-
- /* FIXME: we need to look at how to gracefully fail when we end up
- with mixed incompat versions */
-
- if (hd->version[0] != protocol_active[0]) {
- log_error("reject message from %d version %u.%u.%u vs %u.%u.%u",
- nodeid, hd->version[0], hd->version[1],
- hd->version[2], protocol_active[0],
- protocol_active[1], protocol_active[2]);
- return;
- }
-
- /* If there are some group messages between a new node being added to
- the cpg group and being added to the app group, the new node should
- discard them since they're only relevant to the app group. */
-
- if (!mg->last_callback) {
- log_group(mg, "discard %s len %zd from %d",
- msg_name(hd->type), len, nodeid);
- return;
- }
-
- switch (hd->type) {
- case MSG_JOURNAL:
- receive_journals(mg, data, len, nodeid);
- break;
-
- case MSG_OPTIONS:
- receive_options(mg, data, len, nodeid);
- break;
-
- case MSG_REMOUNT:
- receive_remount(mg, data, len, nodeid);
- break;
-
- case MSG_PLOCK:
- receive_plock(mg, data, len, nodeid);
- break;
-
- case MSG_MOUNT_STATUS:
- receive_mount_status(mg, data, len, nodeid);
- break;
-
- case MSG_RECOVERY_STATUS:
- receive_recovery_status(mg, data, len, nodeid);
- break;
-
- case MSG_RECOVERY_DONE:
- receive_recovery_done(mg, data, len, nodeid);
- break;
-
- case MSG_WITHDRAW:
- receive_withdraw(mg, data, len, nodeid);
- break;
-
- case MSG_PLOCK_OWN:
- receive_own(mg, data, len, nodeid);
- break;
-
- case MSG_PLOCK_DROP:
- receive_drop(mg, data, len, nodeid);
- break;
-
- case MSG_PLOCK_SYNC_LOCK:
- case MSG_PLOCK_SYNC_WAITER:
- receive_sync(mg, data, len, nodeid);
- break;
-
- default:
- log_error("unknown message type %d from %d",
- hd->type, hd->nodeid);
- }
-}
-
-static void deliver_cb(cpg_handle_t handle,
- const struct cpg_name *group_name,
- uint32_t nodeid, uint32_t pid,
- void *data, size_t data_len)
-{
- do_deliver(nodeid, data, data_len);
-}
-
-/* Not sure if purging plocks (driven by confchg) needs to be synchronized with
- the other recovery steps (driven by libgroup) for a node, don't think so.
- Is it possible for a node to have been cleared from the members_gone list
- before this confchg is processed? */
-
-static void confchg_cb(cpg_handle_t handle,
- const struct cpg_name *group_name,
- const struct cpg_address *member_list,
- size_t member_list_entries,
- const struct cpg_address *left_list,
- size_t left_list_entries,
- const struct cpg_address *joined_list,
- size_t joined_list_entries)
-{
- struct mountgroup *mg;
- int i, nodeid;
-
- for (i = 0; i < left_list_entries; i++) {
- nodeid = left_list[i].nodeid;
- list_for_each_entry(mg, &mountgroups, list) {
- if (is_member(mg, nodeid) || is_removed(mg, nodeid))
- purge_plocks(mg, left_list[i].nodeid, 0);
- }
- }
-}
-
-static cpg_callbacks_t callbacks = {
- .cpg_deliver_fn = deliver_cb,
- .cpg_confchg_fn = confchg_cb,
-};
-
-void process_cpg_old(int ci)
-{
- cpg_error_t error;
-
- error = cpg_dispatch(cpg_handle_daemon, CPG_DISPATCH_ALL);
- if (error != CPG_OK) {
- log_error("cpg_dispatch error %d", error);
- return;
- }
-
- update_flow_control_status();
-}
-
-int setup_cpg_old(void)
-{
- static struct cpg_name name;
- cpg_error_t error;
- int fd = 0;
-
- if (cfgd_plock_ownership)
- memcpy(protocol_active, protocol_v200, sizeof(protocol_v200));
- else
- memcpy(protocol_active, protocol_v100, sizeof(protocol_v100));
-
- error = cpg_initialize(&cpg_handle_daemon, &callbacks);
- if (error != CPG_OK) {
- log_error("daemon cpg_initialize error %d", error);
- return -1;
- }
-
- cpg_fd_get(cpg_handle_daemon, &fd);
- if (fd < 0) {
- log_error("daemon cpg_fd_get error %d", error);
- return -1;
- }
-
- memset(&name, 0, sizeof(name));
- strcpy(name.value, "gfs_controld");
- name.length = 12;
-
- retry:
- error = cpg_join(cpg_handle_daemon, &name);
- if (error == CPG_ERR_TRY_AGAIN) {
- log_debug("daemon cpg_join retry");
- sleep(1);
- goto retry;
- }
- if (error != CPG_OK) {
- log_error("daemon cpg_join error %d", error);
- cpg_finalize(cpg_handle_daemon);
- return -1;
- }
-
- log_debug("setup_cpg_old %d", fd);
- return fd;
-}
-
-void close_cpg_old(void)
-{
- static struct cpg_name name;
- cpg_error_t error;
- int i = 0;
-
- if (!cpg_handle_daemon)
- return;
- if (cluster_down)
- goto fin;
-
- memset(&name, 0, sizeof(name));
- strcpy(name.value, "gfs_controld");
- name.length = 12;
-
- retry:
- error = cpg_leave(cpg_handle_daemon, &name);
- if (error == CPG_ERR_TRY_AGAIN) {
- sleep(1);
- if (!(++i % 10))
- log_error("daemon cpg_leave error retrying");
- goto retry;
- }
- if (error != CPG_OK)
- log_error("daemon cpg_leave error %d", error);
- fin:
- cpg_finalize(cpg_handle_daemon);
-}
-
diff --git a/group/gfs_controld/cpg-old.h b/group/gfs_controld/cpg-old.h
deleted file mode 100644
index 0458338..0000000
--- a/group/gfs_controld/cpg-old.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef __CPG_OLD_DOT_H__
-#define __CPG_OLD_DOT_H__
-
-#define DO_STOP 1
-#define DO_START 2
-#define DO_FINISH 3
-#define DO_TERMINATE 4
-#define DO_SETID 5
-
-enum {
-
- MSG_JOURNAL = 1,
- MSG_OPTIONS,
- MSG_REMOUNT,
- MSG_PLOCK,
- MSG_WITHDRAW,
- MSG_MOUNT_STATUS,
- MSG_RECOVERY_STATUS,
- MSG_RECOVERY_DONE,
- MSG_PLOCK_OWN,
- MSG_PLOCK_DROP,
- MSG_PLOCK_SYNC_LOCK,
- MSG_PLOCK_SYNC_WAITER,
-};
-
-/* These lengths are part of the "old" wire protocol. */
-
-#define MAX_OPTIONS_LEN 1024
-#define MSG_NAMELEN 255
-
-struct gdlm_header {
- uint16_t version[3];
- uint16_t type; /* MSG_ */
- uint32_t nodeid; /* sender */
- uint32_t to_nodeid; /* 0 if to all */
- char name[MSG_NAMELEN];
-};
-
-struct save_msg {
- struct list_head list;
- int nodeid;
- int len;
- int type;
- char buf[0];
-};
-
-struct mg_member {
- struct list_head list;
- int nodeid;
- int jid;
-
- int spectator;
- int readonly;
- int rw;
- uint32_t opts;
-
- int tell_gfs_to_recover;
- int wait_gfs_recover_done;
- int gone_event;
- int gone_type;
- int finished;
- int local_recovery_status;
- int recovery_status;
- int withdrawing;
- int needs_journals;
-
- int ms_kernel_mount_done;
- int ms_first_mounter;
- int ms_kernel_mount_error;
-};
-
-#endif
-
diff --git a/group/gfs_controld/crc.c b/group/gfs_controld/crc.c
deleted file mode 100644
index 29bc096..0000000
--- a/group/gfs_controld/crc.c
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "gfs_daemon.h"
-
-static const uint32_t crc_32_tab[] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-/**
- *
- * Copied from:
- *
- * gfs2_disk_hash - hash an array of data
- * @data: the data to be hashed
- * @len: the length of data to be hashed
- *
- * This function must produce the same results as the one in the kernel:
- * crc32_le(0xFFFFFFFF, data, len) ^ 0xFFFFFFFF
- *
- * Take some data and convert it to a 32-bit hash.
- *
- * The hash function is a 32-bit CRC of the data. The algorithm uses
- * the crc_32_tab table above.
- *
- * This may not be the fastest hash function, but it does a fair bit better
- * at providing uniform results than the others I've looked at. That's
- * really important for efficient directories.
- *
- * Returns: the hash
- */
-
-uint32_t cpgname_to_crc(const char *data, int len)
-{
- uint32_t hash = 0xFFFFFFFF;
-
- for (; len--; data++)
- hash = crc_32_tab[(hash ^ *data) & 0xFF] ^ (hash >> 8);
-
- hash = ~hash;
-
- return hash;
-}
-
diff --git a/group/gfs_controld/gfs_controld.h b/group/gfs_controld/gfs_controld.h
deleted file mode 100644
index 571dffb..0000000
--- a/group/gfs_controld/gfs_controld.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef __GFS_CONTROLD_DOT_H__
-#define __GFS_CONTROLD_DOT_H__
-
-/* This defines the interface between gfs_controld and libgfscontrol, and
- should only be used by libgfscontrol. */
-
-#define GFSC_SOCK_PATH "gfsc_sock"
-#define GFSC_QUERY_SOCK_PATH "gfsc_query_sock"
-
-#define GFSC_MAGIC 0x6F5C6F5C
-#define GFSC_VERSION 0x00010001
-
-#define GFSC_CMD_DUMP_DEBUG 1
-#define GFSC_CMD_DUMP_PLOCKS 2
-#define GFSC_CMD_MOUNTGROUP_INFO 3
-#define GFSC_CMD_NODE_INFO 4
-#define GFSC_CMD_MOUNTGROUPS 5
-#define GFSC_CMD_MOUNTGROUP_NODES 6
-#define GFSC_CMD_FS_JOIN 7
-#define GFSC_CMD_FS_REMOUNT 8
-#define GFSC_CMD_FS_MOUNT_DONE 9
-#define GFSC_CMD_FS_LEAVE 10
-
-struct gfsc_header {
- unsigned int magic;
- unsigned int version;
- unsigned int command;
- unsigned int option;
- unsigned int len;
- int data; /* embedded command-specific data, for convenience */
- int unused1;
- int unsued2;
- char name[GFS_MOUNTGROUP_LEN]; /* no terminating null space */
-};
-
-#endif
-
diff --git a/group/gfs_controld/gfs_daemon.h b/group/gfs_controld/gfs_daemon.h
deleted file mode 100644
index af7ed45..0000000
--- a/group/gfs_controld/gfs_daemon.h
+++ /dev/null
@@ -1,338 +0,0 @@
-#ifndef __GFS_DAEMON_DOT_H__
-#define __GFS_DAEMON_DOT_H__
-
-#include <sys/types.h>
-#include <asm/types.h>
-#include <sys/uio.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/utsname.h>
-#include <sys/poll.h>
-#include <sys/wait.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <limits.h>
-#include <unistd.h>
-#include <time.h>
-#include <syslog.h>
-#include <sched.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <dirent.h>
-#include <openais/saAis.h>
-#include <openais/saCkpt.h>
-#include <corosync/cpg.h>
-#include <liblogthread.h>
-
-#include <linux/dlmconstants.h>
-#include "libgfscontrol.h"
-#include "gfs_controld.h"
-#include "list.h"
-#include "linux_endian.h"
-
-/* TODO: warn if
- DLM_LOCKSPACE_LEN (from dlmconstants.h) !=
- GFS_MOUNTGROUP_LEN (from libgfscontrol.h)
-*/
-
-/* Maximum members of a mountgroup, should match CPG_MEMBERS_MAX in
- corosync/cpg.h. There are no max defines in gfs-kernel for
- mountgroup members. (FIXME verify gfs-kernel/lock_dlm) */
-
-#define MAX_NODES 128
-
-/* Max string length printed on a line, for debugging/dump output. */
-
-#define MAXLINE 256
-
-/* group_mode */
-
-#define GROUP_LIBGROUP 2
-#define GROUP_LIBCPG 3
-
-extern int daemon_debug_opt;
-extern int daemon_quit;
-extern int cluster_down;
-extern int poll_dlm;
-extern int poll_ignore_plock;
-extern int plock_fd;
-extern int plock_ci;
-extern struct list_head mountgroups;
-extern int our_nodeid;
-extern char *clustername;
-extern char daemon_debug_buf[256];
-extern char dump_buf[GFSC_DUMP_SIZE];
-extern int dump_point;
-extern int dump_wrap;
-extern char plock_dump_buf[GFSC_DUMP_SIZE];
-extern int plock_dump_len;
-extern int dmsetup_wait;
-extern cpg_handle_t cpg_handle_daemon;
-extern int libcpg_flow_control_on;
-extern int group_mode;
-extern uint32_t plock_minor;
-extern uint32_t old_plock_minor;
-extern struct list_head withdrawn_mounts;
-extern int using_default_plock_ownership;
-
-void daemon_dump_save(void);
-
-#define log_level(lvl, fmt, args...) \
-do { \
- snprintf(daemon_debug_buf, 255, "%ld " fmt "\n", time(NULL), ##args); \
- daemon_dump_save(); \
- logt_print(lvl, fmt "\n", ##args); \
- if (daemon_debug_opt) \
- fprintf(stderr, "%s", daemon_debug_buf); \
-} while (0)
-
-#define log_debug(fmt, args...) log_level(LOG_DEBUG, fmt, ##args)
-#define log_error(fmt, args...) log_level(LOG_ERR, fmt, ##args)
-
-#define log_group(g, fmt, args...) \
-do { \
- snprintf(daemon_debug_buf, 255, "%ld %s " fmt "\n", time(NULL), \
- (g)->name, ##args); \
- daemon_dump_save(); \
- logt_print(LOG_DEBUG, "%s " fmt "\n", (g)->name, ##args); \
- if (daemon_debug_opt) \
- fprintf(stderr, "%s", daemon_debug_buf); \
-} while (0)
-
-#define log_plock(g, fmt, args...) \
-do { \
- snprintf(daemon_debug_buf, 255, "%ld %s " fmt "\n", time(NULL), \
- (g)->name, ##args); \
- if (daemon_debug_opt && cfgd_plock_debug) \
- fprintf(stderr, "%s", daemon_debug_buf); \
-} while (0)
-
-struct mountgroup {
- struct list_head list;
- uint32_t id;
- struct gfsc_mount_args mount_args;
- char name[GFS_MOUNTGROUP_LEN+1];
- int old_group_mode;
-
- int mount_client;
- int mount_client_result;
- int mount_client_notified;
- int mount_client_delay;
- int remount_client;
-
- int withdraw_uevent;
- int withdraw_suspend;
- int dmsetup_wait;
- pid_t dmsetup_pid;
- int our_jid;
- int spectator;
- int ro;
- int rw;
- int joining;
- int leaving;
- int kernel_mount_error;
- int kernel_mount_done;
- int first_mounter;
-
- /* cpg-new stuff */
-
- cpg_handle_t cpg_handle;
- int cpg_client;
- int cpg_fd;
- int kernel_stopped;
- uint32_t change_seq;
- uint32_t started_count;
- struct change *started_change;
- struct list_head changes;
- struct list_head node_history;
- struct list_head journals;
- int dlm_registered;
- int dlm_notify_nodeid;
- int first_done_uevent;
- int first_recovery_needed;
- int first_recovery_master;
- int first_recovery_msg;
- int local_recovery_jid;
- int local_recovery_busy;
-
- /* cpg-old stuff for rhel5/stable2 compat */
-
- struct list_head members;
- struct list_head members_gone;
- int memb_count;
- int last_stop;
- int last_start;
- int last_finish;
- int last_callback;
- int start_event_nr;
- int start_type;
- int group_leave_on_finish;
- int init;
- int got_our_options;
- int got_our_journals;
- int delay_send_journals;
- int first_mount_pending_stop;
- int first_mounter_done;
- int global_first_recover_done;
- int emulate_first_mounter;
- int wait_first_done;
- int needs_recovery;
- int low_nodeid;
- int master_nodeid;
- int got_kernel_mount;
- struct list_head saved_messages;
- void *start2_fn;
-
- /* cpg-old plock stuff */
-
- int save_plocks;
- struct list_head plock_resources;
- uint32_t associated_ls_id;
- uint64_t cp_handle;
- time_t last_checkpoint_time;
- time_t last_plock_time;
- struct timeval drop_resources_last;
-};
-
-/* these need to match the kernel defines of the same name in lm_interface.h */
-
-#define LM_RD_GAVEUP 308
-#define LM_RD_SUCCESS 309
-
-/* config.c */
-int setup_ccs(void);
-void close_ccs(void);
-void read_ccs_name(const char *path, char *name);
-void read_ccs_yesno(const char *path, int *yes, int *no);
-int read_ccs_int(const char *path, int *config_val);
-void read_ccs_nodir(struct mountgroup *mg, char *buf);
-
-/* cpg-new.c */
-int setup_cpg_daemon(void);
-void close_cpg_daemon(void);
-void process_cpg_daemon(int ci);
-int setup_dlmcontrol(void);
-void process_dlmcontrol(int ci);
-int set_protocol(void);
-void process_recovery_uevent(char *name, int jid, int status, int first);
-void process_mountgroups(void);
-int gfs_join_mountgroup(struct mountgroup *mg);
-void do_leave(char *name, int mnterr);
-void gfs_mount_done(struct mountgroup *mg);
-void send_remount(struct mountgroup *mg, struct gfsc_mount_args *ma);
-void send_withdraw(struct mountgroup *mg);
-int set_mountgroup_info(struct mountgroup *mg, struct gfsc_mountgroup *out);
-int set_node_info(struct mountgroup *mg, int nodeid, struct gfsc_node *node);
-int set_mountgroups(int *count, struct gfsc_mountgroup **mgs_out);
-int set_mountgroup_nodes(struct mountgroup *mg, int option, int *node_count,
- struct gfsc_node **nodes_out);
-void free_mg(struct mountgroup *mg);
-void node_history_cluster_add(int nodeid);
-void node_history_cluster_remove(int nodeid);
-
-/* cpg-old.c */
-int setup_cpg_old(void);
-void close_cpg_old(void);
-void process_cpg_old(int ci);
-
-int gfs_join_mountgroup_old(struct mountgroup *mg, struct gfsc_mount_args *ma);
-void do_leave_old(char *name, int mnterr);
-int send_group_message_old(struct mountgroup *mg, int len, char *buf);
-void save_message_old(struct mountgroup *mg, char *buf, size_t len, int from,
- int type);
-void send_withdraw_old(struct mountgroup *mg);
-int process_recovery_uevent_old(char *name, int jid, int status, int first);
-void send_remount_old(struct mountgroup *mg, struct gfsc_mount_args *ma);
-void send_mount_status_old(struct mountgroup *mg);
-int do_stop(struct mountgroup *mg);
-int do_finish(struct mountgroup *mg);
-void do_start(struct mountgroup *mg, int type, int member_count, int *nodeids);
-int do_terminate(struct mountgroup *mg);
-int do_withdraw_old(char *table);
-
-/* group.c */
-int setup_groupd(void);
-void close_groupd(void);
-void process_groupd(int ci);
-int set_mountgroup_info_group(struct mountgroup *mg,
- struct gfsc_mountgroup *out);
-int set_node_info_group(struct mountgroup *mg, int nodeid,
- struct gfsc_node *node);
-int set_mountgroups_group(int *count, struct gfsc_mountgroup **mgs_out);
-int set_mountgroup_nodes_group(struct mountgroup *mg, int option,
- int *node_count, struct gfsc_node **nodes_out);
-int set_group_mode(void);
-
-/* main.c */
-int do_read(int fd, void *buf, size_t count);
-int do_write(int fd, void *buf, size_t count);
-void client_dead(int ci);
-int client_add(int fd, void (*workfn)(int ci), void (*deadfn)(int ci));
-int client_fd(int ci);
-void client_ignore(int ci, int fd);
-void client_back(int ci, int fd);
-struct mountgroup *create_mg(char *name);
-struct mountgroup *find_mg(char *name);
-struct mountgroup *find_mg_id(uint32_t id);
-void client_reply_remount(struct mountgroup *mg, int ci, int result);
-void client_reply_join(int ci, struct gfsc_mount_args *ma, int result);
-void client_reply_join_full(struct mountgroup *mg, int result);
-void query_lock(void);
-void query_unlock(void);
-void process_connection(int ci);
-void cluster_dead(int ci);
-
-/* member_cman.c */
-int setup_cluster(void);
-void close_cluster(void);
-void process_cluster(int ci);
-void update_cluster(void);
-void kick_node_from_cluster(int nodeid);
-
-/* plock.c */
-int setup_plocks(void);
-void close_plocks(void);
-void process_plocks(int ci);
-int limit_plocks(void);
-void receive_plock(struct mountgroup *mg, char *buf, int len, int from);
-void receive_own(struct mountgroup *mg, char *buf, int len, int from);
-void receive_sync(struct mountgroup *mg, char *buf, int len, int from);
-void receive_drop(struct mountgroup *mg, char *buf, int len, int from);
-void process_saved_plocks(struct mountgroup *mg);
-int unlink_checkpoint(struct mountgroup *mg);
-void store_plocks(struct mountgroup *mg, int nodeid);
-void retrieve_plocks(struct mountgroup *mg);
-void purge_plocks(struct mountgroup *mg, int nodeid, int unmount);
-int fill_plock_dump_buf(struct mountgroup *mg);
-int setup_misc_devices(void);
-
-/* util.c */
-int we_are_in_fence_domain(void);
-int set_sysfs(struct mountgroup *mg, const char *field, int val);
-int read_sysfs_int(struct mountgroup *mg, const char *field, int *val_out);
-int run_dmsetup_suspend(struct mountgroup *mg, char *dev);
-void update_dmsetup_wait(void);
-void update_flow_control_status(void);
-int check_uncontrolled_filesystems(void);
-
-/* logging.c */
-void init_logging(void);
-void setup_logging(void);
-void close_logging(void);
-
-/* crc.c */
-uint32_t cpgname_to_crc(const char *data, int len);
-
-#endif
diff --git a/group/gfs_controld/group.c b/group/gfs_controld/group.c
deleted file mode 100644
index d738f0d..0000000
--- a/group/gfs_controld/group.c
+++ /dev/null
@@ -1,372 +0,0 @@
-#include "gfs_daemon.h"
-#include "config.h"
-#include "cpg-old.h"
-#include "libgroup.h"
-
-#define LOCK_DLM_GROUP_LEVEL 2
-#define LOCK_DLM_GROUP_NAME "gfs"
-
-/* save all the params from callback functions here because we can't
- do the processing within the callback function itself */
-
-group_handle_t gh;
-static int cb_action;
-static char cb_name[GFS_MOUNTGROUP_LEN+1];
-static int cb_event_nr;
-static unsigned int cb_id;
-static int cb_type;
-static int cb_member_count;
-static int cb_members[MAX_NODES];
-
-
-static void stop_cbfn(group_handle_t h, void *private, char *name)
-{
- cb_action = DO_STOP;
- strcpy(cb_name, name);
-}
-
-static void start_cbfn(group_handle_t h, void *private, char *name,
- int event_nr, int type, int member_count, int *members)
-{
- int i;
-
- cb_action = DO_START;
- strncpy(cb_name, name, GFS_MOUNTGROUP_LEN);
- cb_event_nr = event_nr;
- cb_type = type;
- cb_member_count = member_count;
-
- for (i = 0; i < member_count; i++)
- cb_members[i] = members[i];
-}
-
-static void finish_cbfn(group_handle_t h, void *private, char *name,
- int event_nr)
-{
- cb_action = DO_FINISH;
- strncpy(cb_name, name, GFS_MOUNTGROUP_LEN);
- cb_event_nr = event_nr;
-}
-
-static void terminate_cbfn(group_handle_t h, void *private, char *name)
-{
- cb_action = DO_TERMINATE;
- strncpy(cb_name, name, GFS_MOUNTGROUP_LEN);
-}
-
-static void setid_cbfn(group_handle_t h, void *private, char *name,
- unsigned int id)
-{
- cb_action = DO_SETID;
- strncpy(cb_name, name, GFS_MOUNTGROUP_LEN);
- cb_id = id;
-}
-
-static group_callbacks_t callbacks = {
- stop_cbfn,
- start_cbfn,
- finish_cbfn,
- terminate_cbfn,
- setid_cbfn,
-};
-
-static char *str_members(void)
-{
- static char str_members_buf[MAXLINE];
- int i, ret, pos = 0, len = MAXLINE;
-
- memset(str_members_buf, 0, MAXLINE);
-
- for (i = 0; i < cb_member_count; i++) {
- if (i != 0) {
- ret = snprintf(str_members_buf + pos, len - pos, " ");
- if (ret >= len - pos)
- break;
- pos += ret;
- }
- ret = snprintf(str_members_buf + pos, len - pos, "%d",
- cb_members[i]);
- if (ret >= len - pos)
- break;
- pos += ret;
- }
- return str_members_buf;
-}
-
-static unsigned int replace_zero_global_id(char *name)
-{
- unsigned int new_id;
-
- new_id = cpgname_to_crc(name, strlen(name));
-
- log_error("replace zero id for %s with %u", name, new_id);
- return new_id;
-}
-
-void process_groupd(int ci)
-{
- struct mountgroup *mg;
- int error = 0;
-
- error = group_dispatch(gh);
- if (error) {
- log_error("groupd_dispatch error %d errno %d", error, errno);
- goto out;
- }
-
- if (!cb_action)
- goto out;
-
- mg = find_mg(cb_name);
- if (!mg) {
- log_error("callback %d group %s not found", cb_action, cb_name);
- error = -1;
- goto out;
- }
-
- switch (cb_action) {
- case DO_STOP:
- log_debug("groupd cb: stop %s", cb_name);
- mg->last_callback = DO_STOP;
- mg->last_stop = mg->last_start;
- do_stop(mg);
- break;
-
- case DO_START:
- log_debug("groupd cb: start %s type %d count %d members %s",
- cb_name, cb_type, cb_member_count, str_members());
- mg->last_callback = DO_START;
- mg->last_start = cb_event_nr;
- do_start(mg, cb_type, cb_member_count, cb_members);
- break;
-
- case DO_FINISH:
- log_debug("groupd cb: finish %s", cb_name);
- mg->last_callback = DO_FINISH;
- mg->last_finish = cb_event_nr;
- do_finish(mg);
- break;
-
- case DO_TERMINATE:
- log_debug("groupd cb: terminate %s", cb_name);
- mg->last_callback = DO_TERMINATE;
- do_terminate(mg);
- break;
-
- case DO_SETID:
- log_debug("groupd cb: set_id %s %x", cb_name, cb_id);
- if (!cb_id)
- cb_id = replace_zero_global_id(cb_name);
- mg->id = cb_id;
- break;
-
- default:
- error = -EINVAL;
- }
-
- out:
- cb_action = 0;
-}
-
-int setup_groupd(void)
-{
- int rv;
-
- gh = group_init(NULL, LOCK_DLM_GROUP_NAME, LOCK_DLM_GROUP_LEVEL,
- &callbacks, 10);
- if (!gh) {
- log_error("group_init error %p %d", gh, errno);
- return -ENOTCONN;
- }
-
- rv = group_get_fd(gh);
- if (rv < 0)
- log_error("group_get_fd error %d %d", rv, errno);
-
- log_debug("groupd %d", rv);
-
- return rv;
-}
-
-void close_groupd(void)
-{
- group_exit(gh);
-}
-
-/* most of the query info doesn't apply in the LIBGROUP mode, but we can
- emulate some basic parts of it */
-
-int set_mountgroup_info_group(struct mountgroup *mg,
- struct gfsc_mountgroup *out)
-{
- strncpy(out->name, mg->name, GFS_MOUNTGROUP_LEN);
- out->global_id = mg->id;
-
- if (mg->joining)
- out->flags |= GFSC_MF_JOINING;
- if (mg->leaving)
- out->flags |= GFSC_MF_LEAVING;
- if (mg->kernel_stopped)
- out->flags |= GFSC_MF_KERNEL_STOPPED;
-
- out->cg_prev.member_count = mg->memb_count;
-
- return 0;
-}
-
-static int _set_node_info(struct mountgroup *mg, int nodeid,
- struct gfsc_node *node)
-{
- struct mg_member *memb;
- int is_member = 0, is_gone = 0;
-
- list_for_each_entry(memb, &mg->members, list) {
- if (memb->nodeid != nodeid)
- continue;
- is_member = 1;
- goto found;
- }
- list_for_each_entry(memb, &mg->members_gone, list) {
- if (memb->nodeid != nodeid)
- continue;
- is_gone = 1;
- break;
- }
- if (!is_member && !is_gone)
- goto out;
- found:
- node->nodeid = nodeid;
-
- if (is_member)
- node->flags |= GFSC_NF_MEMBER;
- if (memb->spectator)
- node->flags |= GFSC_NF_SPECTATOR;
- if (memb->readonly)
- node->flags |= GFSC_NF_READONLY;
- if (memb->ms_kernel_mount_done)
- node->flags |= GFSC_NF_KERNEL_MOUNT_DONE;
- if (memb->ms_kernel_mount_error)
- node->flags |= GFSC_NF_KERNEL_MOUNT_ERROR;
-
- node->jid = memb->jid;
-
- if (is_gone && memb->gone_type == GROUP_NODE_FAILED)
- node->failed_reason = 1;
- out:
- return 0;
-}
-
-int set_node_info_group(struct mountgroup *mg, int nodeid,
- struct gfsc_node *node)
-{
- return _set_node_info(mg, nodeid, node);
-}
-
-int set_mountgroups_group(int *count, struct gfsc_mountgroup **mgs_out)
-{
- struct mountgroup *mg;
- struct gfsc_mountgroup *mgs, *mgp;
- int mg_count = 0;
-
- list_for_each_entry(mg, &mountgroups, list)
- mg_count++;
-
- mgs = malloc(mg_count * sizeof(struct gfsc_mountgroup));
- if (!mgs)
- return -ENOMEM;
- memset(mgs, 0, mg_count * sizeof(struct gfsc_mountgroup));
-
- mgp = mgs;
- list_for_each_entry(mg, &mountgroups, list) {
- set_mountgroup_info(mg, mgp++);
- }
-
- *count = mg_count;
- *mgs_out = mgs;
- return 0;
-}
-
-static int list_count(struct list_head *head)
-{
- struct list_head *tmp;
- int count = 0;
-
- list_for_each(tmp, head)
- count++;
- return count;
-}
-
-int set_mountgroup_nodes_group(struct mountgroup *mg, int option,
- int *node_count, struct gfsc_node **nodes_out)
-{
- struct gfsc_node *nodes = NULL, *nodep;
- struct mg_member *memb;
- int count = 0;
-
- if (option == GFSC_NODES_ALL) {
- count = mg->memb_count + list_count(&mg->members_gone);
- } else if (option == GFSC_NODES_MEMBERS) {
- count = mg->memb_count;
- } else
- goto out;
-
- nodes = malloc(count * sizeof(struct gfsc_node));
- if (!nodes)
- return -ENOMEM;
- memset(nodes, 0, count * sizeof(struct gfsc_node));
- nodep = nodes;
-
- list_for_each_entry(memb, &mg->members, list)
- _set_node_info(mg, memb->nodeid, nodep++);
-
- if (option == GFSC_NODES_ALL) {
- list_for_each_entry(memb, &mg->members_gone, list)
- _set_node_info(mg, memb->nodeid, nodep++);
- }
- out:
- *node_count = count;
- *nodes_out = nodes;
- return 0;
-}
-
-int set_group_mode(void)
-{
- int i = 0, rv, version, limit;
-
- while (1) {
- rv = group_get_version(&version);
-
- if (rv || version < 0) {
- /* we expect to get version of -EAGAIN while groupd
- is detecting the mode of everyone; don't retry
- as long if we're not getting anything back from
- groupd */
-
- log_debug("set_group_mode get_version %d ver %d",
- rv, version);
-
- limit = (version == -EAGAIN) ? 30 : 5;
-
- if (i++ > limit) {
- log_error("cannot get groupd compatibility "
- "mode rv %d ver %d", rv, version);
- return -1;
- }
- sleep(1);
- continue;
- }
-
-
- if (version == GROUP_LIBGROUP) {
- group_mode = GROUP_LIBGROUP;
- return 0;
- } else if (version == GROUP_LIBCPG) {
- group_mode = GROUP_LIBCPG;
- return 0;
- } else {
- log_error("set_group_mode invalid ver %d", version);
- return -1;
- }
- }
-}
-
diff --git a/group/gfs_controld/logging.c b/group/gfs_controld/logging.c
deleted file mode 100644
index 2c44b5c..0000000
--- a/group/gfs_controld/logging.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include "gfs_daemon.h"
-#include "config.h"
-#include "ccs.h"
-
-extern int ccs_handle;
-
-#define DAEMON_NAME "gfs_controld"
-#define DEFAULT_LOG_MODE LOG_MODE_OUTPUT_FILE|LOG_MODE_OUTPUT_SYSLOG
-#define DEFAULT_SYSLOG_FACILITY SYSLOGFACILITY
-#define DEFAULT_SYSLOG_PRIORITY SYSLOGLEVEL
-#define DEFAULT_LOGFILE_PRIORITY LOG_INFO /* ? */
-#define DEFAULT_LOGFILE LOGDIR "/" DAEMON_NAME ".log"
-
-static int log_mode;
-static int syslog_facility;
-static int syslog_priority;
-static int logfile_priority;
-static char logfile[PATH_MAX];
-
-void init_logging(void)
-{
- log_mode = DEFAULT_LOG_MODE;
- syslog_facility = DEFAULT_SYSLOG_FACILITY;
- syslog_priority = DEFAULT_SYSLOG_PRIORITY;
- logfile_priority = DEFAULT_LOGFILE_PRIORITY;
- strcpy(logfile, DEFAULT_LOGFILE);
-
- /* logfile_priority is the only one of these options that
- can be controlled from command line or environment variable */
-
- if (cfgd_debug_logfile)
- logfile_priority = LOG_DEBUG;
-
- log_debug("logging mode %d syslog f %d p %d logfile p %d %s",
- log_mode, syslog_facility, syslog_priority,
- logfile_priority, logfile);
-
- logt_init(DAEMON_NAME, log_mode, syslog_facility, syslog_priority,
- logfile_priority, logfile);
-}
-
-void setup_logging(void)
-{
- ccs_read_logging(ccs_handle, DAEMON_NAME,
- &cfgd_debug_logfile, &log_mode,
- &syslog_facility, &syslog_priority,
- &logfile_priority, logfile);
-
- log_debug("logging mode %d syslog f %d p %d logfile p %d %s",
- log_mode, syslog_facility, syslog_priority,
- logfile_priority, logfile);
-
- logt_conf(DAEMON_NAME, log_mode, syslog_facility, syslog_priority,
- logfile_priority, logfile);
-}
-
-void close_logging(void)
-{
- logt_exit();
-}
-
diff --git a/group/gfs_controld/main.c b/group/gfs_controld/main.c
deleted file mode 100644
index dc841da..0000000
--- a/group/gfs_controld/main.c
+++ /dev/null
@@ -1,1593 +0,0 @@
-#include "gfs_daemon.h"
-#include "config.h"
-#include <pthread.h>
-#include "copyright.cf"
-
-#include <linux/netlink.h>
-
-#define LOCKFILE_NAME "/var/run/gfs_controld.pid"
-#define CLIENT_NALLOC 32
-#define UEVENT_BUF_SIZE 4096
-
-static int client_maxi;
-static int client_size;
-static struct client *client;
-static struct pollfd *pollfd;
-static pthread_t query_thread;
-static pthread_mutex_t query_mutex;
-
-struct client {
- int fd;
- void *workfn;
- void *deadfn;
- struct mountgroup *mg;
-};
-
-static void do_withdraw(char *name);
-
-int do_read(int fd, void *buf, size_t count)
-{
- int rv, off = 0;
-
- while (off < count) {
- rv = read(fd, (char *)buf + off, count - off);
- if (rv == 0)
- return -1;
- if (rv == -1 && errno == EINTR)
- continue;
- if (rv == -1)
- return -1;
- off += rv;
- }
- return 0;
-}
-
-int do_write(int fd, void *buf, size_t count)
-{
- int rv, off = 0;
-
- retry:
- rv = write(fd, (char *)buf + off, count);
- if (rv == -1 && errno == EINTR)
- goto retry;
- if (rv < 0) {
- log_error("write errno %d", errno);
- return rv;
- }
-
- if (rv != count) {
- count -= rv;
- off += rv;
- goto retry;
- }
- return 0;
-}
-
-static void client_alloc(void)
-{
- int i;
-
- if (!client) {
- client = malloc(CLIENT_NALLOC * sizeof(struct client));
- pollfd = malloc(CLIENT_NALLOC * sizeof(struct pollfd));
- } else {
- client = realloc(client, (client_size + CLIENT_NALLOC) *
- sizeof(struct client));
- pollfd = realloc(pollfd, (client_size + CLIENT_NALLOC) *
- sizeof(struct pollfd));
- if (!pollfd)
- log_error("can't alloc for pollfd");
- }
- if (!client || !pollfd)
- log_error("can't alloc for client array");
-
- for (i = client_size; i < client_size + CLIENT_NALLOC; i++) {
- client[i].workfn = NULL;
- client[i].deadfn = NULL;
- client[i].fd = -1;
- pollfd[i].fd = -1;
- pollfd[i].revents = 0;
- }
- client_size += CLIENT_NALLOC;
-}
-
-void client_dead(int ci)
-{
- close(client[ci].fd);
- client[ci].workfn = NULL;
- client[ci].fd = -1;
- pollfd[ci].fd = -1;
-}
-
-int client_add(int fd, void (*workfn)(int ci), void (*deadfn)(int ci))
-{
- int i;
-
- if (!client)
- client_alloc();
- again:
- for (i = 0; i < client_size; i++) {
- if (client[i].fd == -1) {
- client[i].workfn = workfn;
- if (deadfn)
- client[i].deadfn = deadfn;
- else
- client[i].deadfn = client_dead;
- client[i].fd = fd;
- pollfd[i].fd = fd;
- pollfd[i].events = POLLIN;
- if (i > client_maxi)
- client_maxi = i;
- return i;
- }
- }
-
- client_alloc();
- goto again;
-}
-
-int client_fd(int ci)
-{
- return client[ci].fd;
-}
-
-void client_ignore(int ci, int fd)
-{
- pollfd[ci].fd = -1;
- pollfd[ci].events = 0;
-}
-
-void client_back(int ci, int fd)
-{
- pollfd[ci].fd = fd;
- pollfd[ci].events = POLLIN;
-}
-
-static void sigterm_handler(int sig)
-{
- daemon_quit = 1;
-}
-
-struct mountgroup *create_mg(char *name)
-{
- struct mountgroup *mg;
-
- mg = malloc(sizeof(struct mountgroup));
- if (!mg)
- return NULL;
- memset(mg, 0, sizeof(struct mountgroup));
-
- if (group_mode == GROUP_LIBGROUP)
- mg->old_group_mode = 1;
-
- INIT_LIST_HEAD(&mg->members);
- INIT_LIST_HEAD(&mg->members_gone);
- INIT_LIST_HEAD(&mg->plock_resources);
- INIT_LIST_HEAD(&mg->saved_messages);
- INIT_LIST_HEAD(&mg->changes);
- INIT_LIST_HEAD(&mg->journals);
- INIT_LIST_HEAD(&mg->node_history);
- mg->init = 1;
- mg->master_nodeid = -1;
- mg->low_nodeid = -1;
-
- strncpy(mg->name, name, GFS_MOUNTGROUP_LEN);
-
- return mg;
-}
-
-struct mountgroup *find_mg(char *name)
-{
- struct mountgroup *mg;
-
- list_for_each_entry(mg, &mountgroups, list) {
- if ((strlen(mg->name) == strlen(name)) &&
- !strncmp(mg->name, name, strlen(name)))
- return mg;
- }
- return NULL;
-}
-
-struct mountgroup *find_mg_id(uint32_t id)
-{
- struct mountgroup *mg;
-
- list_for_each_entry(mg, &mountgroups, list) {
- if (mg->id == id)
- return mg;
- }
- return NULL;
-}
-
-static void ping_kernel_mount(char *name)
-{
- struct mountgroup *mg;
- int rv, val;
-
- mg = find_mg(name);
- if (!mg)
- return;
-
- rv = read_sysfs_int(mg, "block", &val);
-
- log_group(mg, "ping_kernel_mount %d", rv);
-}
-
-enum {
- Env_ACTION = 0,
- Env_SUBSYSTEM,
- Env_LOCKPROTO,
- Env_LOCKTABLE,
- Env_DEVPATH,
- Env_RECOVERY,
- Env_FIRSTMOUNT,
- Env_JID,
- Env_Last, /* Flag for end of vars */
-};
-
-static const char *uevent_vars[] = {
- [Env_ACTION] = "ACTION=",
- [Env_SUBSYSTEM] = "SUBSYSTEM=",
- [Env_LOCKPROTO] = "LOCKPROTO=",
- [Env_LOCKTABLE] = "LOCKTABLE=",
- [Env_DEVPATH] = "DEVPATH=",
- [Env_RECOVERY] = "RECOVERY=",
- [Env_FIRSTMOUNT] = "FIRSTMOUNT=",
- [Env_JID] = "JID=",
-};
-
-/*
- * Parses a uevent message for the interesting bits. It requires a list
- * of variables to look for, and an equally long list of pointers into
- * which to write the results.
- */
-static void decode_uevent(const char *buf, unsigned len, const char *vars[],
- unsigned nvars, const char *vals[])
-{
- const char *ptr;
- unsigned int i;
- int slen, vlen;
-
- memset(vals, 0, sizeof(const char *) * nvars);
-
- while (len > 0) {
- ptr = buf;
- slen = strlen(ptr);
- buf += slen;
- len -= slen;
- buf++;
- len--;
-
- for (i = 0; i < nvars; i++) {
- vlen = strlen(vars[i]);
- if (vlen > slen)
- continue;
- if (memcmp(vars[i], ptr, vlen) != 0)
- continue;
- vals[i] = ptr + vlen;
- break;
- }
- }
-}
-
-static char *uevent_fsname(const char *vars[])
-{
- char *name = NULL;
-
- if (vars[Env_LOCKTABLE])
- name = strchr(vars[Env_LOCKTABLE], ':');
-
- /* When all kernels are converted, we can dispose with the following
- * grotty bit. This is for backward compatibility only.
- */
- if (!name && vars[Env_DEVPATH]) {
- name = strchr(vars[Env_DEVPATH], ':');
- if (name) {
- char *end = strstr(name, "/lock_module");
- if (end)
- *end = 0;
- }
- }
- return (name && name[0]) ? name + 1 : NULL;
-}
-
-static void process_uevent(int ci)
-{
- char buf[UEVENT_BUF_SIZE];
- const char *uevent_vals[Env_Last];
- char *fsname;
- int rv;
-
- retry_recv:
- rv = recv(client[ci].fd, &buf, sizeof(buf), 0);
- if (rv < 0) {
- if (errno == EINTR)
- goto retry_recv;
- if (errno != EAGAIN)
- log_error("uevent recv error %d errno %d", rv, errno);
- return;
- }
- buf[rv] = 0;
-
- decode_uevent(buf, rv, uevent_vars, Env_Last, uevent_vals);
-
- if (!uevent_vals[Env_DEVPATH] ||
- !uevent_vals[Env_ACTION] ||
- !uevent_vals[Env_SUBSYSTEM])
- return;
-
- if (!strstr(uevent_vals[Env_DEVPATH], "/fs/gfs"))
- return;
-
- log_debug("uevent %s %s %s",
- uevent_vals[Env_ACTION],
- uevent_vals[Env_SUBSYSTEM],
- uevent_vals[Env_DEVPATH]);
-
- fsname = uevent_fsname(uevent_vals);
- if (!fsname) {
- log_error("no fsname uevent %s %s %s",
- uevent_vals[Env_ACTION],
- uevent_vals[Env_SUBSYSTEM],
- uevent_vals[Env_DEVPATH]);
- return;
- }
-
- if (!strcmp(uevent_vals[Env_ACTION], "remove")) {
- /* We want to trigger the leave at the very end of the kernel's
- unmount process, i.e. at the end of put_super(), so we do the
- leave when the second uevent (from the gfs kobj) arrives. */
-
- if (strcmp(uevent_vals[Env_SUBSYSTEM], "lock_dlm") == 0)
- return;
- if (group_mode == GROUP_LIBGROUP)
- do_leave_old(fsname, 0);
- else
- do_leave(fsname, 0);
-
- } else if (!strcmp(uevent_vals[Env_ACTION], "change")) {
- int jid, status = -1, first = -1;
-
- if (!uevent_vals[Env_JID] ||
- (sscanf(uevent_vals[Env_JID], "%d", &jid) != 1))
- jid = -1;
-
- if (uevent_vals[Env_RECOVERY]) {
- if (strcmp(uevent_vals[Env_RECOVERY], "Done") == 0)
- status = LM_RD_SUCCESS;
- if (strcmp(uevent_vals[Env_RECOVERY], "Failed") == 0)
- status = LM_RD_GAVEUP;
- }
-
- if (uevent_vals[Env_FIRSTMOUNT] &&
- (strcmp(uevent_vals[Env_FIRSTMOUNT], "Done") == 0))
- first = 1;
-
- if (group_mode == GROUP_LIBGROUP)
- process_recovery_uevent_old(fsname, jid, status, first);
- else
- process_recovery_uevent(fsname, jid, status, first);
-
- } else if (!strcmp(uevent_vals[Env_ACTION], "offline")) {
- do_withdraw(fsname);
- } else {
- ping_kernel_mount(fsname);
- }
-}
-
-static int setup_uevent(void)
-{
- struct sockaddr_nl snl;
- int s, rv;
-
- s = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
- if (s < 0) {
- log_error("uevent netlink socket");
- return s;
- }
-
- memset(&snl, 0, sizeof(snl));
- snl.nl_family = AF_NETLINK;
- snl.nl_pid = getpid();
- snl.nl_groups = 1;
-
- rv = bind(s, (struct sockaddr *) &snl, sizeof(snl));
- if (rv < 0) {
- log_error("uevent bind error %d errno %d", rv, errno);
- close(s);
- return rv;
- }
-
- return s;
-}
-
-static void init_header(struct gfsc_header *h, int cmd, char *name, int result,
- int extra_len)
-{
- memset(h, 0, sizeof(struct gfsc_header));
-
- h->magic = GFSC_MAGIC;
- h->version = GFSC_VERSION;
- h->len = sizeof(struct gfsc_header) + extra_len;
- h->command = cmd;
- h->data = result;
-
- if (name)
- strncpy(h->name, name, GFS_MOUNTGROUP_LEN);
-}
-
-static void query_dump_debug(int fd)
-{
- struct gfsc_header h;
- int extra_len;
- int len;
-
- /* in the case of dump_wrap, extra_len will go in two writes,
- first the log tail, then the log head */
- if (dump_wrap)
- extra_len = GFSC_DUMP_SIZE;
- else
- extra_len = dump_point;
-
- init_header(&h, GFSC_CMD_DUMP_DEBUG, NULL, 0, extra_len);
- do_write(fd, &h, sizeof(h));
-
- if (dump_wrap) {
- len = GFSC_DUMP_SIZE - dump_point;
- do_write(fd, dump_buf + dump_point, len);
- len = dump_point;
- } else
- len = dump_point;
-
- /* NUL terminate the debug string */
- dump_buf[dump_point] = '\0';
-
- do_write(fd, dump_buf, len);
-}
-
-static void query_dump_plocks(int fd, char *name)
-{
- struct mountgroup *mg;
- struct gfsc_header h;
- int rv;
-
- mg = find_mg(name);
- if (!mg) {
- plock_dump_len = 0;
- rv = -ENOENT;
- } else {
- /* writes to plock_dump_buf and sets plock_dump_len */
- rv = fill_plock_dump_buf(mg);
- }
-
- init_header(&h, GFSC_CMD_DUMP_PLOCKS, name, rv, plock_dump_len);
-
- do_write(fd, &h, sizeof(h));
-
- if (plock_dump_len)
- do_write(fd, plock_dump_buf, plock_dump_len);
-}
-
-/* combines a header and the data and sends it back to the client in
- a single do_write() call */
-
-static void do_reply(int fd, int cmd, char *name, int result, void *buf,
- int buflen)
-{
- char *reply;
- int reply_len;
-
- reply_len = sizeof(struct gfsc_header) + buflen;
- reply = malloc(reply_len);
- if (!reply)
- return;
- memset(reply, 0, reply_len);
-
- init_header((struct gfsc_header *)reply, cmd, name, result, buflen);
-
- if (buf && buflen)
- memcpy(reply + sizeof(struct gfsc_header), buf, buflen);
-
- do_write(fd, reply, reply_len);
-
- free(reply);
-}
-
-static void query_mountgroup_info(int fd, char *name)
-{
- struct mountgroup *mg;
- struct gfsc_mountgroup mountgroup;
- int rv;
-
- mg = find_mg(name);
- if (!mg) {
- rv = -ENOENT;
- goto out;
- }
-
- memset(&mountgroup, 0, sizeof(mountgroup));
- mountgroup.group_mode = group_mode;
-
- if (group_mode == GROUP_LIBGROUP)
- rv = set_mountgroup_info_group(mg, &mountgroup);
- else
- rv = set_mountgroup_info(mg, &mountgroup);
- out:
- do_reply(fd, GFSC_CMD_MOUNTGROUP_INFO, name, rv,
- (char *)&mountgroup, sizeof(mountgroup));
-}
-
-static void query_node_info(int fd, char *name, int nodeid)
-{
- struct mountgroup *mg;
- struct gfsc_node node;
- int rv;
-
- mg = find_mg(name);
- if (!mg) {
- rv = -ENOENT;
- goto out;
- }
-
- if (group_mode == GROUP_LIBGROUP)
- rv = set_node_info_group(mg, nodeid, &node);
- else
- rv = set_node_info(mg, nodeid, &node);
- out:
- do_reply(fd, GFSC_CMD_NODE_INFO, name, rv,
- (char *)&node, sizeof(node));
-}
-
-static void query_mountgroups(int fd, int max)
-{
- int mg_count = 0;
- struct gfsc_mountgroup *mgs = NULL;
- int rv, result;
-
- if (group_mode == GROUP_LIBGROUP)
- rv = set_mountgroups_group(&mg_count, &mgs);
- else
- rv = set_mountgroups(&mg_count, &mgs);
-
- if (rv < 0) {
- result = rv;
- mg_count = 0;
- goto out;
- }
-
- if (mg_count > max) {
- result = -E2BIG;
- mg_count = max;
- } else {
- result = mg_count;
- }
- out:
- do_reply(fd, GFSC_CMD_MOUNTGROUPS, NULL, result,
- (char *)mgs, mg_count * sizeof(struct gfsc_mountgroup));
-
- if (mgs)
- free(mgs);
-}
-
-static void query_mountgroup_nodes(int fd, char *name, int option, int max)
-{
- struct mountgroup *mg;
- int node_count = 0;
- struct gfsc_node *nodes = NULL;
- int rv, result;
-
- mg = find_mg(name);
- if (!mg) {
- result = -ENOENT;
- node_count = 0;
- goto out;
- }
-
- if (group_mode == GROUP_LIBGROUP)
- rv = set_mountgroup_nodes_group(mg, option, &node_count, &nodes);
- else
- rv = set_mountgroup_nodes(mg, option, &node_count, &nodes);
-
- if (rv < 0) {
- result = rv;
- node_count = 0;
- goto out;
- }
-
- /* node_count is the number of structs copied/returned; the caller's
- max may be less than that, in which case we copy as many as they
- asked for and return -E2BIG */
-
- if (node_count > max) {
- result = -E2BIG;
- node_count = max;
- } else {
- result = node_count;
- }
- out:
- do_reply(fd, GFSC_CMD_MOUNTGROUP_NODES, name, result,
- (char *)nodes, node_count * sizeof(struct gfsc_node));
-
- if (nodes)
- free(nodes);
-}
-
-void client_reply_join(int ci, struct gfsc_mount_args *ma, int result)
-{
- char *name = strstr(ma->table, ":") + 1;
-
- log_debug("client_reply_join %s ci %d result %d", name, ci, result);
-
- do_reply(client[ci].fd, GFSC_CMD_FS_JOIN,
- name, result, ma, sizeof(struct gfsc_mount_args));
-}
-
-void client_reply_join_full(struct mountgroup *mg, int result)
-{
- char nodir_str[32];
-
- if (result)
- goto out;
-
- if (mg->our_jid < 0) {
- snprintf(mg->mount_args.hostdata, PATH_MAX,
- "hostdata=id=%u:first=%d",
- mg->id, mg->first_mounter);
- } else {
- snprintf(mg->mount_args.hostdata, PATH_MAX,
- "hostdata=jid=%d:id=%u:first=%d",
- mg->our_jid, mg->id, mg->first_mounter);
- }
-
- memset(nodir_str, 0, sizeof(nodir_str));
-
- read_ccs_nodir(mg, nodir_str);
- if (nodir_str[0])
- strcat(mg->mount_args.hostdata, nodir_str);
- out:
- log_group(mg, "client_reply_join_full ci %d result %d %s",
- mg->mount_client, result, mg->mount_args.hostdata);
-
- client_reply_join(mg->mount_client, &mg->mount_args, result);
-}
-
-static void do_join(int ci, struct gfsc_mount_args *ma)
-{
- struct mountgroup *mg = NULL;
- char table2[PATH_MAX];
- char *cluster = NULL, *name = NULL;
- int rv;
-
- log_debug("join: %s %s %s %s %s %s", ma->dir, ma->type, ma->proto,
- ma->table, ma->options, ma->dev);
-
- if (strcmp(ma->proto, "lock_dlm")) {
- log_error("join: lockproto %s not supported", ma->proto);
- rv = -EPROTONOSUPPORT;
- goto fail;
- }
-
- if (strstr(ma->options, "jid=") ||
- strstr(ma->options, "first=") ||
- strstr(ma->options, "id=")) {
- log_error("join: jid, first and id are reserved options");
- rv = -EOPNOTSUPP;
- goto fail;
- }
-
- /* table is <cluster>:<name> */
-
- memset(table2, 0, sizeof(table2));
- strncpy(table2, ma->table, sizeof(table2));
-
- name = strstr(table2, ":");
- if (!name) {
- rv = -EBADFD;
- goto fail;
- }
-
- *name = '\0';
- name++;
- cluster = table2;
-
- if (strlen(name) > GFS_MOUNTGROUP_LEN) {
- rv = -ENAMETOOLONG;
- goto fail;
- }
-
- mg = find_mg(name);
- if (mg) {
- if (strcmp(mg->mount_args.dev, ma->dev)) {
- log_error("different fs dev %s with same name",
- mg->mount_args.dev);
- rv = -EADDRINUSE;
- } else if (mg->leaving) {
- /* we're leaving the group */
- log_error("join: reject mount due to unmount");
- rv = -ESTALE;
- } else if (mg->mount_client || !mg->kernel_mount_done) {
- log_error("join: other mount in progress %d %d",
- mg->mount_client, mg->kernel_mount_done);
- rv = -EBUSY;
- } else {
- log_group(mg, "join: already mounted");
- rv = -EALREADY;
- }
- goto fail;
- }
-
- mg = create_mg(name);
- if (!mg) {
- rv = -ENOMEM;
- goto fail;
- }
- mg->mount_client = ci;
- memcpy(&mg->mount_args, ma, sizeof(struct gfsc_mount_args));
-
- if (strlen(cluster) != strlen(clustername) ||
- strlen(cluster) == 0 || strcmp(cluster, clustername)) {
- log_error("join: fs requires cluster=\"%s\" current=\"%s\"",
- cluster, clustername);
- rv = -EBADR;
- goto fail_free;
- }
- log_group(mg, "join: cluster name matches: %s", clustername);
-
- if (strstr(ma->options, "spectator")) {
- log_group(mg, "join: spectator mount");
- mg->spectator = 1;
- } else {
- if (!we_are_in_fence_domain()) {
- log_error("join: not in default fence domain");
- rv = -ENOANO;
- goto fail_free;
- }
- }
-
- if (!mg->spectator && strstr(ma->options, "rw"))
- mg->rw = 1;
- else if (strstr(ma->options, "ro")) {
- if (mg->spectator) {
- log_error("join: readonly invalid with spectator");
- rv = -EROFS;
- goto fail_free;
- }
- mg->ro = 1;
- }
-
- list_add(&mg->list, &mountgroups);
-
- if (group_mode == GROUP_LIBGROUP)
- rv = gfs_join_mountgroup_old(mg, ma);
- else
- rv = gfs_join_mountgroup(mg);
-
- if (rv) {
- log_error("join: group join error %d", rv);
- list_del(&mg->list);
- goto fail_free;
- }
- return;
-
- fail_free:
- free(mg);
- fail:
- client_reply_join(ci, ma, rv);
-}
-
-/* The basic rule of withdraw is that we don't want to tell the kernel to drop
- all locks until we know gfs has been stopped/blocked on all nodes.
- A withdrawing node is very much like a readonly node, differences are
- that others recover its journal when they remove it from the group,
- and when it's been removed from the group, it tells the locally withdrawing
- gfs to clear out locks. */
-
-static void do_withdraw(char *name)
-{
- struct mountgroup *mg;
- int rv;
-
- log_debug("withdraw: %s", name);
-
- if (!cfgd_enable_withdraw) {
- log_error("withdraw feature not enabled");
- return;
- }
-
- mg = find_mg(name);
- if (!mg) {
- log_error("do_withdraw no mountgroup %s", name);
- return;
- }
-
- mg->withdraw_uevent = 1;
-
- rv = run_dmsetup_suspend(mg, mg->mount_args.dev);
- if (rv) {
- log_error("do_withdraw %s: dmsetup %s error %d", mg->name,
- mg->mount_args.dev, rv);
- return;
- }
-
- dmsetup_wait = 1;
-}
-
-static void do_mount_done(char *table, int result)
-{
- struct mountgroup *mg;
- char *name = strstr(table, ":") + 1;
-
- log_debug("mount_done: %s result %d", name, result);
-
- mg = find_mg(name);
- if (!mg) {
- log_error("mount_done: %s not found", name);
- return;
- }
-
- mg->mount_client = 0;
- mg->kernel_mount_done = 1;
- mg->kernel_mount_error = result;
-
- if (group_mode == GROUP_LIBGROUP)
- send_mount_status_old(mg);
- else
- gfs_mount_done(mg);
-}
-
-void client_reply_remount(struct mountgroup *mg, int ci, int result)
-{
- do_reply(client[ci].fd, GFSC_CMD_FS_REMOUNT, mg->name, result,
- &mg->mount_args, sizeof(struct gfsc_mount_args));
-}
-
-/* mount.gfs creates a special ma->options string with only "ro" or "rw" */
-
-static void do_remount(int ci, struct gfsc_mount_args *ma)
-{
- struct mountgroup *mg;
- char *name = strstr(ma->table, ":") + 1;
- int ro = 0, result = 0;
-
- log_debug("remount: %s ci %d options %s", name, ci, ma->options);
-
- mg = find_mg(name);
- if (!mg) {
- log_error("remount: %s not found", name);
- result = -1;
- goto out;
- }
-
- if (mg->spectator) {
- log_error("remount of spectator not allowed");
- result = -1;
- goto out;
- }
-
- if (!strcmp(ma->options, "ro"))
- ro = 1;
-
- if ((mg->ro && ro) || (!mg->ro && !ro))
- goto out;
-
- if (group_mode == GROUP_LIBGROUP) {
- /* the receive calls client_reply_remount */
- mg->remount_client = ci;
- send_remount_old(mg, ma);
- return;
- }
-
- send_remount(mg, ma);
- out:
- client_reply_remount(mg, ci, result);
-}
-
-void process_connection(int ci)
-{
- struct gfsc_header h;
- struct gfsc_mount_args empty;
- struct gfsc_mount_args *ma;
- char *extra = NULL;
- char *fsname;
- int rv, extra_len;
-
- rv = do_read(client[ci].fd, &h, sizeof(h));
- if (rv < 0) {
- log_debug("connection %d read error %d", ci, rv);
- goto out;
- }
-
- if (h.magic != GFSC_MAGIC) {
- log_debug("connection %d magic error %x", ci, h.magic);
- goto out;
- }
-
- if ((h.version & 0xFFFF0000) != (GFSC_VERSION & 0xFFFF0000)) {
- log_debug("connection %d version error %x", ci, h.version);
- goto out;
- }
-
- if (h.len > sizeof(h)) {
- extra_len = h.len - sizeof(h);
- extra = malloc(extra_len);
- if (!extra) {
- log_error("process_connection no mem %d", extra_len);
- goto out;
- }
- memset(extra, 0, extra_len);
-
- rv = do_read(client[ci].fd, extra, extra_len);
- if (rv < 0) {
- log_debug("connection %d extra read error %d", ci, rv);
- goto out;
- }
- }
-
- ma = (struct gfsc_mount_args *)extra;
-
- if (!ma) {
- memset(&empty, 0, sizeof(empty));
-
- if (h.command == GFSC_CMD_FS_JOIN ||
- h.command == GFSC_CMD_FS_REMOUNT) {
- do_reply(client[ci].fd, h.command, h.name, -EINVAL,
- &empty, sizeof(empty));
- }
- log_debug("connection %d cmd %d no data", ci, h.command);
- goto out;
- }
-
- switch (h.command) {
-
- case GFSC_CMD_FS_JOIN:
- do_join(ci, ma);
- break;
-
- case GFSC_CMD_FS_LEAVE:
- fsname = strstr(ma->table, ":") + 1;
- if (!fsname) {
- log_error("process_connection no fsname in table");
- goto out;
- }
-
- if (group_mode == GROUP_LIBGROUP)
- do_leave_old(fsname, h.data);
- else
- do_leave(fsname, h.data);
- break;
-
- case GFSC_CMD_FS_MOUNT_DONE:
- do_mount_done(ma->table, h.data);
- break;
-
- case GFSC_CMD_FS_REMOUNT:
- do_remount(ci, ma);
- break;
-
- default:
- log_error("process_connection %d unknown command %d",
- ci, h.command);
- }
- out:
- if (extra)
- free(extra);
-
- /* no client_dead(ci) here, since the connection for
- join/remount is reused */
-}
-
-static void process_listener(int ci)
-{
- int fd, i;
-
- fd = accept(client[ci].fd, NULL, NULL);
- if (fd < 0) {
- log_error("process_listener: accept error %d %d", fd, errno);
- return;
- }
-
- i = client_add(fd, process_connection, NULL);
-
- log_debug("client connection %d fd %d", i, fd);
-}
-
-static int setup_listener(const char *sock_path)
-{
- struct sockaddr_un addr;
- socklen_t addrlen;
- int rv, s;
-
- /* we listen for new client connections on socket s */
-
- s = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (s < 0) {
- log_error("socket error %d %d", s, errno);
- return s;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_LOCAL;
- strcpy(&addr.sun_path[1], sock_path);
- addrlen = sizeof(sa_family_t) + strlen(addr.sun_path+1) + 1;
-
- rv = bind(s, (struct sockaddr *) &addr, addrlen);
- if (rv < 0) {
- log_error("bind error %d %d", rv, errno);
- close(s);
- return rv;
- }
-
- rv = listen(s, 5);
- if (rv < 0) {
- log_error("listen error %d %d", rv, errno);
- close(s);
- return rv;
- }
- return s;
-}
-
-void query_lock(void)
-{
- pthread_mutex_lock(&query_mutex);
-}
-
-void query_unlock(void)
-{
- pthread_mutex_unlock(&query_mutex);
-}
-
-/* This is a thread, so we have to be careful, don't call log_ functions.
- We need a thread to process queries because the main thread may block
- for long periods. */
-
-static void *process_queries(void *arg)
-{
- struct gfsc_header h;
- int f, rv, s;
-
- rv = setup_listener(GFSC_QUERY_SOCK_PATH);
- if (rv < 0)
- return NULL;
-
- s = rv;
-
- for (;;) {
- f = accept(s, NULL, NULL);
- if (f < 0)
- return NULL;
-
- rv = do_read(f, &h, sizeof(h));
- if (rv < 0) {
- goto out;
- }
-
- if (h.magic != GFSC_MAGIC) {
- goto out;
- }
-
- if ((h.version & 0xFFFF0000) != (GFSC_VERSION & 0xFFFF0000)) {
- goto out;
- }
-
- query_lock();
-
- switch (h.command) {
- case GFSC_CMD_DUMP_DEBUG:
- query_dump_debug(f);
- break;
- case GFSC_CMD_DUMP_PLOCKS:
- query_dump_plocks(f, h.name);
- break;
- case GFSC_CMD_MOUNTGROUP_INFO:
- query_mountgroup_info(f, h.name);
- break;
- case GFSC_CMD_NODE_INFO:
- query_node_info(f, h.name, h.data);
- break;
- case GFSC_CMD_MOUNTGROUPS:
- query_mountgroups(f, h.data);
- break;
- case GFSC_CMD_MOUNTGROUP_NODES:
- query_mountgroup_nodes(f, h.name, h.option, h.data);
- break;
- default:
- break;
- }
- query_unlock();
-
- out:
- close(f);
- }
-}
-
-static int setup_queries(void)
-{
- int rv;
-
- pthread_mutex_init(&query_mutex, NULL);
-
- rv = pthread_create(&query_thread, NULL, process_queries, NULL);
- if (rv < 0) {
- log_error("can't create query thread");
- return rv;
- }
- return 0;
-}
-
-void cluster_dead(int ci)
-{
- if (!cluster_down)
- log_error("cluster is down, exiting");
- daemon_quit = 1;
- cluster_down = 1;
-}
-
-static void loop(void)
-{
- int poll_timeout = -1;
- int rv, i;
- void (*workfn) (int ci);
- void (*deadfn) (int ci);
-
- rv = setup_queries();
- if (rv < 0)
- goto out;
-
- rv = setup_listener(GFSC_SOCK_PATH);
- if (rv < 0)
- goto out;
- client_add(rv, process_listener, NULL);
-
- rv = setup_cluster();
- if (rv < 0)
- goto out;
- client_add(rv, process_cluster, cluster_dead);
-
- update_cluster();
-
- rv = setup_ccs();
- if (rv < 0)
- goto out;
-
- setup_logging();
-
- rv = check_uncontrolled_filesystems();
- if (rv < 0)
- goto out;
-
- rv = setup_uevent();
- if (rv < 0)
- goto out;
- client_add(rv, process_uevent, NULL);
-
- group_mode = GROUP_LIBCPG;
-
- if (cfgd_groupd_compat) {
- rv = setup_groupd();
- if (rv < 0)
- goto out;
- client_add(rv, process_groupd, cluster_dead);
-
- switch (cfgd_groupd_compat) {
- case 1:
- group_mode = GROUP_LIBGROUP;
- rv = 0;
- break;
- case 2:
- rv = set_group_mode();
- break;
- default:
- log_error("inval groupd_compat %d", cfgd_groupd_compat);
- rv = -1;
- break;
- }
- if (rv < 0)
- goto out;
- }
- log_debug("group_mode %d compat %d", group_mode, cfgd_groupd_compat);
-
- if (group_mode == GROUP_LIBCPG) {
-
- /*
- * The new, good, way of doing things using libcpg directly.
- * code in: cpg-new.c
- */
-
- rv = setup_cpg_daemon();
- if (rv < 0)
- goto out;
- client_add(rv, process_cpg_daemon, cluster_dead);
-
- rv = set_protocol();
- if (rv < 0)
- goto out;
-
- rv = setup_dlmcontrol();
- if (rv < 0)
- goto out;
- client_add(rv, process_dlmcontrol, cluster_dead);
-
- } else if (group_mode == GROUP_LIBGROUP) {
-
- /* the stable2 default is zero plock_ownership which we need
- to match or protocol_active will differ */
- if (using_default_plock_ownership)
- cfgd_plock_ownership = 0;
-
- /*
- * The old, bad, way of doing things using libgroup.
- * code in: cpg-old.c group.c plock.c
- */
-
- rv = setup_cpg_old();
- if (rv < 0)
- goto out;
- client_add(rv, process_cpg_old, cluster_dead);
-
- rv = setup_misc_devices();
- if (rv < 0)
- goto out;
-
- rv = setup_plocks();
- if (rv < 0)
- goto out;
- plock_fd = rv;
- plock_ci = client_add(rv, process_plocks, NULL);
- }
-
- for (;;) {
- rv = poll(pollfd, client_maxi + 1, poll_timeout);
- if (rv == -1 && errno == EINTR) {
- if (daemon_quit && list_empty(&mountgroups))
- goto out;
- daemon_quit = 0;
- continue;
- }
- if (rv < 0) {
- log_error("poll errno %d", errno);
- goto out;
- }
-
- query_lock();
-
- for (i = 0; i <= client_maxi; i++) {
- if (client[i].fd < 0)
- continue;
- if (pollfd[i].revents & POLLIN) {
- workfn = client[i].workfn;
- workfn(i);
- }
- if (pollfd[i].revents & (POLLERR | POLLHUP | POLLNVAL)) {
- deadfn = client[i].deadfn;
- deadfn(i);
- }
- }
- query_unlock();
-
- if (daemon_quit)
- break;
-
- query_lock();
-
- poll_timeout = -1;
-
- if (poll_dlm) {
- /* only happens for GROUP_LIBCPG */
- process_mountgroups();
- poll_timeout = 500;
- }
-
- if (poll_ignore_plock) {
- /* only happens for GROUP_LIBGROUP */
- if (!limit_plocks()) {
- poll_ignore_plock = 0;
- client_back(plock_ci, plock_fd);
- }
- poll_timeout = 1000;
- }
-
- if (dmsetup_wait) {
- update_dmsetup_wait();
- if (dmsetup_wait) {
- if (poll_timeout == -1)
- poll_timeout = 1000;
- } else {
- if (poll_timeout == 1000)
- poll_timeout = -1;
- }
- }
- query_unlock();
- }
- out:
- if (group_mode == GROUP_LIBCPG)
- close_cpg_daemon();
- else if (group_mode == GROUP_LIBGROUP) {
- close_plocks();
- close_cpg_old();
- }
- if (cfgd_groupd_compat)
- close_groupd();
- close_logging();
- close_ccs();
- close_cluster();
-
- if (!list_empty(&mountgroups))
- log_error("mountgroups abandoned");
-}
-
-static void lockfile(void)
-{
- int fd, error;
- struct flock lock;
- char buf[33];
-
- memset(buf, 0, 33);
-
- fd = open(LOCKFILE_NAME, O_CREAT|O_WRONLY,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
- if (fd < 0) {
- fprintf(stderr, "cannot open/create lock file %s\n",
- LOCKFILE_NAME);
- exit(EXIT_FAILURE);
- }
-
- lock.l_type = F_WRLCK;
- lock.l_start = 0;
- lock.l_whence = SEEK_SET;
- lock.l_len = 0;
-
- error = fcntl(fd, F_SETLK, &lock);
- if (error) {
- fprintf(stderr, "gfs_controld is already running\n");
- exit(EXIT_FAILURE);
- }
-
- error = ftruncate(fd, 0);
- if (error) {
- fprintf(stderr, "cannot clear lock file %s\n", LOCKFILE_NAME);
- exit(EXIT_FAILURE);
- }
-
- sprintf(buf, "%d\n", getpid());
-
- error = write(fd, buf, strlen(buf));
- if (error <= 0) {
- fprintf(stderr, "cannot write lock file %s\n", LOCKFILE_NAME);
- exit(EXIT_FAILURE);
- }
-}
-
-static void print_usage(void)
-{
- printf("Usage:\n");
- printf("\n");
- printf("gfs_controld [options]\n");
- printf("\n");
- printf("Options:\n");
- printf("\n");
- printf(" -D Enable debugging to stderr and don't fork\n");
- printf(" -L Enable debugging to log file\n");
- printf(" -g <num> groupd compatibility mode, 0 off, 1 on, 2 detect\n");
- printf(" 0: use libcpg, no backward compat, best performance\n");
- printf(" 1: use libgroup for compat with cluster2/rhel5\n");
- printf(" 2: use groupd to detect old, or mode 1, nodes that\n"
- " require compat, use libcpg if none found\n");
- printf(" Default is %d\n", DEFAULT_GROUPD_COMPAT);
- printf(" -w <num> Enable (1) or disable (0) withdraw\n");
- printf(" Default is %d\n", DEFAULT_ENABLE_WITHDRAW);
- printf(" -p <num> Enable (1) or disable (0) plock code\n");
- printf(" Default is %d\n", DEFAULT_ENABLE_PLOCK);
- printf(" -P Enable plock debugging\n");
-
- printf(" -l <limit> Limit the rate of plock operations\n");
- printf(" Default is %d, set to 0 for no limit\n", DEFAULT_PLOCK_RATE_LIMIT);
- printf(" -o <n> Enable (1) or disable (0) plock ownership\n");
- printf(" Default is %d\n", DEFAULT_PLOCK_OWNERSHIP);
- printf(" -t <ms> plock ownership drop resources time (milliseconds)\n");
- printf(" Default is %u\n", DEFAULT_DROP_RESOURCES_TIME);
- printf(" -c <num> plock ownership drop resources count\n");
- printf(" Default is %u\n", DEFAULT_DROP_RESOURCES_COUNT);
- printf(" -a <ms> plock ownership drop resources age (milliseconds)\n");
- printf(" Default is %u\n", DEFAULT_DROP_RESOURCES_AGE);
- printf(" -h Print this help, then exit\n");
- printf(" -V Print program version information, then exit\n");
-}
-
-#define OPTION_STRING "LDKg:w:f:q:d:p:Pl:o:t:c:a:hV"
-
-static void read_arguments(int argc, char **argv)
-{
- int cont = 1;
- int optchar;
-
- while (cont) {
- optchar = getopt(argc, argv, OPTION_STRING);
-
- switch (optchar) {
-
- case 'D':
- daemon_debug_opt = 1;
- break;
-
- case 'L':
- optd_debug_logfile = 1;
- cfgd_debug_logfile = 1;
- break;
-
- case 'g':
- optd_groupd_compat = 1;
- cfgd_groupd_compat = atoi(optarg);
- break;
-
- case 'w':
- optd_enable_withdraw = 1;
- cfgd_enable_withdraw = atoi(optarg);
- break;
-
- case 'p':
- optd_enable_plock = 1;
- cfgd_enable_plock = atoi(optarg);
- break;
-
- case 'P':
- optd_plock_debug = 1;
- cfgd_plock_debug = 1;
- break;
-
- case 'l':
- optd_plock_rate_limit = 1;
- cfgd_plock_rate_limit = atoi(optarg);
- break;
-
- case 'o':
- optd_plock_ownership = 1;
- cfgd_plock_ownership = atoi(optarg);
- break;
-
- case 't':
- optd_drop_resources_time = 1;
- cfgd_drop_resources_time = atoi(optarg);
- break;
-
- case 'c':
- optd_drop_resources_count = 1;
- cfgd_drop_resources_count = atoi(optarg);
- break;
-
- case 'a':
- optd_drop_resources_age = 1;
- cfgd_drop_resources_age = atoi(optarg);
- break;
-
- case 'h':
- print_usage();
- exit(EXIT_SUCCESS);
- break;
-
- case 'V':
- printf("gfs_controld %s (built %s %s)\n",
- RELEASE_VERSION, __DATE__, __TIME__);
- printf("%s\n", REDHAT_COPYRIGHT);
- exit(EXIT_SUCCESS);
- break;
-
- case ':':
- case '?':
- fprintf(stderr, "Please use '-h' for usage.\n");
- exit(EXIT_FAILURE);
- break;
-
- case EOF:
- cont = 0;
- break;
-
- default:
- fprintf(stderr, "unknown option: %c\n", optchar);
- exit(EXIT_FAILURE);
- break;
- };
- }
-
- if (getenv("GFS_CONTROLD_DEBUG")) {
- optd_debug_logfile = 1;
- cfgd_debug_logfile = 1;
- }
-}
-
-static void set_oom_adj(int val)
-{
- FILE *fp;
-
- fp = fopen("/proc/self/oom_adj", "w");
- if (!fp)
- return;
-
- fprintf(fp, "%i", val);
- fclose(fp);
-}
-
-static void set_scheduler(void)
-{
- struct sched_param sched_param;
- int rv;
-
- rv = sched_get_priority_max(SCHED_RR);
- if (rv != -1) {
- sched_param.sched_priority = rv;
- rv = sched_setscheduler(0, SCHED_RR, &sched_param);
- if (rv == -1)
- log_error("could not set SCHED_RR priority %d err %d",
- sched_param.sched_priority, errno);
- } else {
- log_error("could not get maximum scheduler priority err %d",
- errno);
- }
-}
-
-int main(int argc, char **argv)
-{
- INIT_LIST_HEAD(&mountgroups);
- INIT_LIST_HEAD(&withdrawn_mounts);
-
- read_arguments(argc, argv);
-
- if (!daemon_debug_opt) {
- if (daemon(0, 0) < 0) {
- perror("daemon error");
- exit(EXIT_FAILURE);
- }
- }
- lockfile();
- init_logging();
- log_level(LOG_INFO, "gfs_controld %s started", RELEASE_VERSION);
- signal(SIGTERM, sigterm_handler);
- set_scheduler();
- set_oom_adj(-16);
-
- loop();
-
- unlink(LOCKFILE_NAME);
- return 0;
-}
-
-void daemon_dump_save(void)
-{
- int len, i;
-
- len = strlen(daemon_debug_buf);
-
- for (i = 0; i < len; i++) {
- dump_buf[dump_point++] = daemon_debug_buf[i];
-
- if (dump_point == GFSC_DUMP_SIZE) {
- dump_point = 0;
- dump_wrap = 1;
- }
- }
-}
-
-int daemon_debug_opt;
-int daemon_quit;
-int cluster_down;
-int poll_ignore_plock;
-int poll_dlm;
-int plock_fd;
-int plock_ci;
-struct list_head mountgroups;
-int our_nodeid;
-char *clustername;
-char daemon_debug_buf[256];
-char dump_buf[GFSC_DUMP_SIZE];
-int dump_point;
-int dump_wrap;
-char plock_dump_buf[GFSC_DUMP_SIZE];
-int plock_dump_len;
-int dmsetup_wait;
-cpg_handle_t cpg_handle_daemon;
-int libcpg_flow_control_on;
-int group_mode;
-uint32_t plock_minor;
-uint32_t old_plock_minor;
-struct list_head withdrawn_mounts;
-int using_default_plock_ownership;
-
diff --git a/group/gfs_controld/member_cman.c b/group/gfs_controld/member_cman.c
deleted file mode 100644
index 277a11e..0000000
--- a/group/gfs_controld/member_cman.c
+++ /dev/null
@@ -1,212 +0,0 @@
-#include "gfs_daemon.h"
-#include "config.h"
-#include <libcman.h>
-
-static cman_handle_t ch;
-static cman_handle_t ch_admin;
-static cman_cluster_t cluster;
-static cman_node_t old_nodes[MAX_NODES];
-static int old_node_count;
-static cman_node_t cman_nodes[MAX_NODES];
-static int cman_node_count;
-
-void kick_node_from_cluster(int nodeid)
-{
- if (!nodeid) {
- log_error("telling cman to shut down cluster locally");
- cman_shutdown(ch_admin, CMAN_SHUTDOWN_ANYWAY);
- } else {
- log_error("telling cman to remove nodeid %d from cluster",
- nodeid);
- cman_kill_node(ch_admin, nodeid);
- }
-}
-
-static int is_member(cman_node_t *node_list, int count, int nodeid)
-{
- int i;
-
- for (i = 0; i < count; i++) {
- if (node_list[i].cn_nodeid == nodeid)
- return node_list[i].cn_member;
- }
- return 0;
-}
-
-static int is_old_member(int nodeid)
-{
- return is_member(old_nodes, old_node_count, nodeid);
-}
-
-static int is_cluster_member(int nodeid)
-{
- return is_member(cman_nodes, cman_node_count, nodeid);
-}
-
-static void statechange(void)
-{
- int i, rv;
-
- old_node_count = cman_node_count;
- memcpy(&old_nodes, &cman_nodes, sizeof(old_nodes));
-
- cman_node_count = 0;
- memset(&cman_nodes, 0, sizeof(cman_nodes));
- rv = cman_get_nodes(ch, MAX_NODES, &cman_node_count, cman_nodes);
- if (rv < 0) {
- log_debug("cman_get_nodes error %d %d", rv, errno);
- return;
- }
-
- /* Never allow node ID 0 to be considered a member #315711 */
- for (i = 0; i < cman_node_count; i++) {
- if (cman_nodes[i].cn_nodeid == 0) {
- cman_nodes[i].cn_member = 0;
- break;
- }
- }
-
- for (i = 0; i < old_node_count; i++) {
- if (old_nodes[i].cn_member &&
- !is_cluster_member(old_nodes[i].cn_nodeid)) {
-
- log_debug("cluster node %d removed",
- old_nodes[i].cn_nodeid);
-
- node_history_cluster_remove(old_nodes[i].cn_nodeid);
- }
- }
-
- for (i = 0; i < cman_node_count; i++) {
- if (cman_nodes[i].cn_member &&
- !is_old_member(cman_nodes[i].cn_nodeid)) {
-
- log_debug("cluster node %d added",
- cman_nodes[i].cn_nodeid);
-
- node_history_cluster_add(cman_nodes[i].cn_nodeid);
- }
- }
-}
-
-static void cman_callback(cman_handle_t h, void *private, int reason, int arg)
-{
- switch (reason) {
- case CMAN_REASON_TRY_SHUTDOWN:
- if (list_empty(&mountgroups))
- cman_replyto_shutdown(ch, 1);
- else {
- log_debug("no to cman shutdown");
- cman_replyto_shutdown(ch, 0);
- }
- break;
- case CMAN_REASON_STATECHANGE:
- statechange();
- break;
- case CMAN_REASON_CONFIG_UPDATE:
- setup_logging();
- setup_ccs();
- break;
- }
-}
-
-void process_cluster(int ci)
-{
- int rv;
-
- rv = cman_dispatch(ch, CMAN_DISPATCH_ALL);
- if (rv == -1 && errno == EHOSTDOWN)
- cluster_dead(0);
-}
-
-int setup_cluster(void)
-{
- cman_node_t node;
- int rv, fd;
- int init = 0, active = 0;
-
- retry_init:
- ch_admin = cman_admin_init(NULL);
- if (!ch_admin) {
- if (init++ < 2) {
- sleep(1);
- goto retry_init;
- }
- log_error("cman_admin_init error %d", errno);
- return -ENOTCONN;
- }
-
- ch = cman_init(NULL);
- if (!ch) {
- log_error("cman_init error %d", errno);
- cman_finish(ch_admin);
- return -ENOTCONN;
- }
-
- retry_active:
- rv = cman_is_active(ch);
- if (!rv) {
- if (active++ < 2) {
- sleep(1);
- goto retry_active;
- }
- log_error("cman_is_active error %d", errno);
- cman_finish(ch);
- cman_finish(ch_admin);
- return -ENOTCONN;
- }
-
- rv = cman_start_notification(ch, cman_callback);
- if (rv < 0) {
- log_error("cman_start_notification error %d %d", rv, errno);
- cman_finish(ch);
- cman_finish(ch_admin);
- return rv;
- }
-
- fd = cman_get_fd(ch);
-
- /* FIXME: wait here for us to be a member of the cluster */
- memset(&cluster, 0, sizeof(cluster));
- rv = cman_get_cluster(ch, &cluster);
- if (rv < 0) {
- log_error("cman_get_cluster error %d %d", rv, errno);
- cman_stop_notification(ch);
- cman_finish(ch);
- cman_finish(ch_admin);
- return rv;
- }
- clustername = cluster.ci_name;
-
- memset(&node, 0, sizeof(node));
- rv = cman_get_node(ch, CMAN_NODEID_US, &node);
- if (rv < 0) {
- log_error("cman_get_node error %d %d", rv, errno);
- cman_stop_notification(ch);
- cman_finish(ch);
- cman_finish(ch_admin);
- fd = rv;
- goto out;
- }
- our_nodeid = node.cn_nodeid;
-
- old_node_count = 0;
- memset(&old_nodes, 0, sizeof(old_nodes));
- cman_node_count = 0;
- memset(&cman_nodes, 0, sizeof(cman_nodes));
- out:
- return fd;
-}
-
-void close_cluster(void)
-{
- cman_finish(ch);
- cman_finish(ch_admin);
-}
-
-/* Force re-read of cman nodes */
-void update_cluster(void)
-{
- statechange();
-}
-
diff --git a/group/gfs_controld/member_pcmk.c b/group/gfs_controld/member_pcmk.c
deleted file mode 100644
index 4a99b50..0000000
--- a/group/gfs_controld/member_pcmk.c
+++ /dev/null
@@ -1,113 +0,0 @@
-#include "gfs_daemon.h"
-#include "config.h"
-
-#include <glib.h>
-#include <bzlib.h>
-#include <heartbeat/ha_msg.h>
-
-#include <pacemaker/crm_config.h>
-
-#include <pacemaker/crm/crm.h>
-#include <pacemaker/crm/ais.h>
-#include <pacemaker/crm/attrd.h>
-/* heartbeat support is irrelevant here */
-#undef SUPPORT_HEARTBEAT
-#define SUPPORT_HEARTBEAT 0
-#include <pacemaker/crm/common/cluster.h>
-#include <pacemaker/crm/common/stack.h>
-#include <pacemaker/crm/common/ipc.h>
-#include <pacemaker/crm/msg_xml.h>
-#include <pacemaker/crm/ais.h>
-
-extern int ais_fd_async;
-
-static int pcmk_cluster_fd = 0;
-static void attrd_deadfn(int ci)
-{
- log_error("%s: Lost connection to the cluster", __FUNCTION__);
- pcmk_cluster_fd = 0;
- return;
-}
-
-void kick_node_from_cluster(int nodeid)
-{
- int fd = pcmk_cluster_fd;
- int rc = crm_terminate_member_no_mainloop(nodeid, NULL, &fd);
-
- if(fd > 0 && fd != pcmk_cluster_fd) {
- pcmk_cluster_fd = fd;
- client_add(pcmk_cluster_fd, NULL, attrd_deadfn);
- }
-
- switch(rc) {
- case 1:
- log_debug("Requested that node %d be kicked from the cluster", nodeid);
- break;
- case -1:
- log_error("Don't know how to kick node %d from the cluster", nodeid);
- break;
- case 0:
- log_error("Could not kick node %d from the cluster", nodeid);
- break;
- default:
- log_error("Unknown result when kicking node %d from the cluster", nodeid);
- break;
- }
- return;
-}
-
-void process_cluster(int ci)
-{
- ais_dispatch(ais_fd_async, NULL);
- /* cluster_quorate = crm_have_quorum; */
-}
-
-void update_cluster(void)
-{
-}
-
-int setup_cluster(void)
-{
- ais_fd_async = -1;
- crm_log_init("cluster-gfs", LOG_DEBUG, FALSE, TRUE, 0, NULL);
-
- if(init_ais_connection(NULL, NULL, NULL, NULL, &our_nodeid) == FALSE) {
- log_error("Connection to our AIS plugin failed");
- return -1;
- }
-
- if(crm_get_cluster_name(&clustername) == FALSE) {
- log_error("No cluster name supplied");
- return -1;
-
- } else {
- log_debug("Connected as node %u to cluster '%s'", our_nodeid, clustername);
- }
-
- /* Sign up for membership updates */
- send_ais_text(crm_class_notify, "true", TRUE, NULL, crm_msg_ais);
-
- /* Requesting the current list of known nodes */
- send_ais_text(crm_class_members, __FUNCTION__, TRUE, NULL, crm_msg_ais);
-
- return ais_fd_async;
-}
-
-void close_cluster(void)
-{
- terminate_ais_connection();
-}
-
-#include <../../fence/libfenced/libfenced.h>
-int fenced_node_info(int nodeid, struct fenced_node *node)
-{
- /* The caller, we_are_in_fence_domain(), wants to check
- * if we're part of the fencing domain.
- * Check the node is alive and synthesize the
- * appropriate value for .member
- */
-
- crm_node_t *pnode = crm_get_peer(nodeid, NULL);
- node->member = crm_is_member_active(pnode);
- return 0;
-}
diff --git a/group/gfs_controld/plock.c b/group/gfs_controld/plock.c
deleted file mode 100644
index 710e73a..0000000
--- a/group/gfs_controld/plock.c
+++ /dev/null
@@ -1,2372 +0,0 @@
-/* gfs_controld only handles plocks in rhel5/stable2 compat mode */
-
-#include "gfs_daemon.h"
-#include "cpg-old.h"
-#include "config.h"
-
-#include <linux/dlm_plock.h>
-
-static uint32_t plock_read_count;
-static uint32_t plock_recv_count;
-static uint32_t plock_rate_delays;
-static struct timeval plock_read_time;
-static struct timeval plock_recv_time;
-static struct timeval plock_rate_last;
-
-static int plock_device_fd = -1;
-static SaCkptHandleT ckpt_handle;
-static SaCkptCallbacksT callbacks = { 0, 0 };
-static SaVersionT version = { 'B', 1, 1 };
-static char section_buf[1024 * 1024];
-static uint32_t section_len;
-static int need_fsid_translation = 0;
-
-struct pack_plock {
- uint64_t start;
- uint64_t end;
- uint64_t owner;
- uint32_t pid;
- uint32_t nodeid;
- uint8_t ex;
- uint8_t waiter;
- uint16_t pad1;
- uint32_t pad;
-};
-
-#define R_GOT_UNOWN 0x00000001 /* have received owner=0 message */
-
-struct resource {
- struct list_head list; /* list of resources */
- uint64_t number;
- int owner; /* nodeid or 0 for unowned */
- uint32_t flags;
- struct timeval last_access;
- struct list_head locks; /* one lock for each range */
- struct list_head waiters;
- struct list_head pending; /* discovering r owner */
-};
-
-#define P_SYNCING 0x00000001 /* plock has been sent as part of sync but not
- yet received */
-
-struct posix_lock {
- struct list_head list; /* resource locks or waiters list */
- uint32_t pid;
- uint64_t owner;
- uint64_t start;
- uint64_t end;
- int ex;
- int nodeid;
- uint32_t flags;
-};
-
-struct lock_waiter {
- struct list_head list;
- uint32_t flags;
- struct dlm_plock_info info;
-};
-
-
-static void send_own(struct mountgroup *mg, struct resource *r, int owner);
-static void save_pending_plock(struct mountgroup *mg, struct resource *r,
- struct dlm_plock_info *in);
-
-
-static int got_unown(struct resource *r)
-{
- return !!(r->flags & R_GOT_UNOWN);
-}
-
-static void info_bswap_out(struct dlm_plock_info *i)
-{
- i->version[0] = cpu_to_le32(i->version[0]);
- i->version[1] = cpu_to_le32(i->version[1]);
- i->version[2] = cpu_to_le32(i->version[2]);
- i->pid = cpu_to_le32(i->pid);
- i->nodeid = cpu_to_le32(i->nodeid);
- i->rv = cpu_to_le32(i->rv);
- i->fsid = cpu_to_le32(i->fsid);
- i->number = cpu_to_le64(i->number);
- i->start = cpu_to_le64(i->start);
- i->end = cpu_to_le64(i->end);
- i->owner = cpu_to_le64(i->owner);
-}
-
-static void info_bswap_in(struct dlm_plock_info *i)
-{
- i->version[0] = le32_to_cpu(i->version[0]);
- i->version[1] = le32_to_cpu(i->version[1]);
- i->version[2] = le32_to_cpu(i->version[2]);
- i->pid = le32_to_cpu(i->pid);
- i->nodeid = le32_to_cpu(i->nodeid);
- i->rv = le32_to_cpu(i->rv);
- i->fsid = le32_to_cpu(i->fsid);
- i->number = le64_to_cpu(i->number);
- i->start = le64_to_cpu(i->start);
- i->end = le64_to_cpu(i->end);
- i->owner = le64_to_cpu(i->owner);
-}
-
-static const char *op_str(int optype)
-{
- switch (optype) {
- case DLM_PLOCK_OP_LOCK:
- return "LK";
- case DLM_PLOCK_OP_UNLOCK:
- return "UN";
- case DLM_PLOCK_OP_GET:
- return "GET";
- default:
- return "??";
- }
-}
-
-static const char *ex_str(int optype, int ex)
-{
- if (optype == DLM_PLOCK_OP_UNLOCK || optype == DLM_PLOCK_OP_GET)
- return "-";
- if (ex)
- return "WR";
- else
- return "RD";
-}
-
-/*
- * In kernels before 2.6.26, plocks came from gfs2's lock_dlm module.
- * Reading plocks from there as well should allow us to use cluster3
- * on old (RHEL5) kernels. In this case, the fsid we read in plock_info
- * structs is the mountgroup id, which we need to translate to the ls id.
- */
-
-int setup_plocks(void)
-{
- SaAisErrorT err;
-
- plock_read_count = 0;
- plock_recv_count = 0;
- plock_rate_delays = 0;
- gettimeofday(&plock_read_time, NULL);
- gettimeofday(&plock_recv_time, NULL);
- gettimeofday(&plock_rate_last, NULL);
-
- err = saCkptInitialize(&ckpt_handle, &callbacks, &version);
- if (err != SA_AIS_OK) {
- log_error("ckpt init error %d", err);
- cfgd_enable_plock = 0;
-
- /* still try to open and read the control device so that we can
- send ENOSYS back to the kernel if it tries to do a plock */
- }
-
- if (plock_minor) {
- need_fsid_translation = 1;
- plock_device_fd = open("/dev/misc/dlm_plock", O_RDWR);
- } else if (old_plock_minor) {
- log_debug("setup_plocks using old lock_dlm interface");
- need_fsid_translation = 0;
- plock_device_fd = open("/dev/misc/lock_dlm_plock", O_RDWR);
- }
-
- if (plock_device_fd < 0) {
- log_error("Failure to open plock device: %s", strerror(errno));
- return -1;
- }
-
- log_debug("plocks %d", plock_device_fd);
- log_debug("plock cpg message size: %u bytes",
- (unsigned int) (sizeof(struct gdlm_header) +
- sizeof(struct dlm_plock_info)));
-
- return plock_device_fd;
-}
-
-void close_plocks(void)
-{
- if (ckpt_handle)
- saCkptFinalize(ckpt_handle);
- if (plock_device_fd > 0)
- close(plock_device_fd);
-}
-
-/* FIXME: unify these two */
-
-static unsigned long time_diff_ms(struct timeval *begin, struct timeval *end)
-{
- struct timeval result;
- timersub(end, begin, &result);
- return (result.tv_sec * 1000) + (result.tv_usec / 1000);
-}
-
-static uint64_t dt_usec(struct timeval *start, struct timeval *stop)
-{
- uint64_t dt;
-
- dt = stop->tv_sec - start->tv_sec;
- dt *= 1000000;
- dt += stop->tv_usec - start->tv_usec;
- return dt;
-}
-
-static struct resource *search_resource(struct mountgroup *mg, uint64_t number)
-{
- struct resource *r;
-
- list_for_each_entry(r, &mg->plock_resources, list) {
- if (r->number == number)
- return r;
- }
- return NULL;
-}
-
-static int find_resource(struct mountgroup *mg, uint64_t number, int create,
- struct resource **r_out)
-{
- struct resource *r = NULL;
- int rv = 0;
-
- r = search_resource(mg, number);
- if (r)
- goto out;
-
- if (create == 0) {
- rv = -ENOENT;
- goto out;
- }
-
- r = malloc(sizeof(struct resource));
- if (!r) {
- log_error("find_resource no memory %d", errno);
- rv = -ENOMEM;
- goto out;
- }
-
- memset(r, 0, sizeof(struct resource));
- r->number = number;
- INIT_LIST_HEAD(&r->locks);
- INIT_LIST_HEAD(&r->waiters);
- INIT_LIST_HEAD(&r->pending);
-
- if (cfgd_plock_ownership)
- r->owner = -1;
- else
- r->owner = 0;
-
- list_add_tail(&r->list, &mg->plock_resources);
- out:
- if (r)
- gettimeofday(&r->last_access, NULL);
- *r_out = r;
- return rv;
-}
-
-static void put_resource(struct resource *r)
-{
- /* with ownership, resources are only freed via drop messages */
- if (cfgd_plock_ownership)
- return;
-
- if (list_empty(&r->locks) && list_empty(&r->waiters)) {
- list_del(&r->list);
- free(r);
- }
-}
-
-static inline int ranges_overlap(uint64_t start1, uint64_t end1,
- uint64_t start2, uint64_t end2)
-{
- if (end1 < start2 || start1 > end2)
- return 0;
- return 1;
-}
-
-/**
- * overlap_type - returns a value based on the type of overlap
- * @s1 - start of new lock range
- * @e1 - end of new lock range
- * @s2 - start of existing lock range
- * @e2 - end of existing lock range
- *
- */
-
-static int overlap_type(uint64_t s1, uint64_t e1, uint64_t s2, uint64_t e2)
-{
- int ret;
-
- /*
- * ---r1---
- * ---r2---
- */
-
- if (s1 == s2 && e1 == e2)
- ret = 0;
-
- /*
- * --r1--
- * ---r2---
- */
-
- else if (s1 == s2 && e1 < e2)
- ret = 1;
-
- /*
- * --r1--
- * ---r2---
- */
-
- else if (s1 > s2 && e1 == e2)
- ret = 1;
-
- /*
- * --r1--
- * ---r2---
- */
-
- else if (s1 > s2 && e1 < e2)
- ret = 2;
-
- /*
- * ---r1--- or ---r1--- or ---r1---
- * --r2-- --r2-- --r2--
- */
-
- else if (s1 <= s2 && e1 >= e2)
- ret = 3;
-
- /*
- * ---r1---
- * ---r2---
- */
-
- else if (s1 > s2 && e1 > e2)
- ret = 4;
-
- /*
- * ---r1---
- * ---r2---
- */
-
- else if (s1 < s2 && e1 < e2)
- ret = 4;
-
- else
- ret = -1;
-
- return ret;
-}
-
-/* shrink the range start2:end2 by the partially overlapping start:end */
-
-static int shrink_range2(uint64_t *start2, uint64_t *end2,
- uint64_t start, uint64_t end)
-{
- int error = 0;
-
- if (*start2 < start)
- *end2 = start - 1;
- else if (*end2 > end)
- *start2 = end + 1;
- else
- error = -1;
- return error;
-}
-
-static int shrink_range(struct posix_lock *po, uint64_t start, uint64_t end)
-{
- return shrink_range2(&po->start, &po->end, start, end);
-}
-
-static int is_conflict(struct resource *r, struct dlm_plock_info *in, int get)
-{
- struct posix_lock *po;
-
- list_for_each_entry(po, &r->locks, list) {
- if (po->nodeid == in->nodeid && po->owner == in->owner)
- continue;
- if (!ranges_overlap(po->start, po->end, in->start, in->end))
- continue;
-
- if (in->ex || po->ex) {
- if (get) {
- in->ex = po->ex;
- in->pid = po->pid;
- in->start = po->start;
- in->end = po->end;
- }
- return 1;
- }
- }
- return 0;
-}
-
-static int add_lock(struct resource *r, uint32_t nodeid, uint64_t owner,
- uint32_t pid, int ex, uint64_t start, uint64_t end)
-{
- struct posix_lock *po;
-
- po = malloc(sizeof(struct posix_lock));
- if (!po)
- return -ENOMEM;
- memset(po, 0, sizeof(struct posix_lock));
-
- po->start = start;
- po->end = end;
- po->nodeid = nodeid;
- po->owner = owner;
- po->pid = pid;
- po->ex = ex;
- list_add_tail(&po->list, &r->locks);
-
- return 0;
-}
-
-/* RN within RE (and starts or ends on RE boundary)
- 1. add new lock for non-overlap area of RE, orig mode
- 2. convert RE to RN range and mode */
-
-static int lock_case1(struct posix_lock *po, struct resource *r,
- struct dlm_plock_info *in)
-{
- uint64_t start2, end2;
- int rv;
-
- /* non-overlapping area start2:end2 */
- start2 = po->start;
- end2 = po->end;
- rv = shrink_range2(&start2, &end2, in->start, in->end);
- if (rv)
- goto out;
-
- po->start = in->start;
- po->end = in->end;
- po->ex = in->ex;
-
- rv = add_lock(r, in->nodeid, in->owner, in->pid, !in->ex, start2, end2);
- out:
- return rv;
-}
-
-/* RN within RE (RE overlaps RN on both sides)
- 1. add new lock for front fragment, orig mode
- 2. add new lock for back fragment, orig mode
- 3. convert RE to RN range and mode */
-
-static int lock_case2(struct posix_lock *po, struct resource *r,
- struct dlm_plock_info *in)
-
-{
- int rv;
-
- rv = add_lock(r, in->nodeid, in->owner, in->pid,
- !in->ex, po->start, in->start - 1);
- if (rv)
- goto out;
-
- rv = add_lock(r, in->nodeid, in->owner, in->pid,
- !in->ex, in->end + 1, po->end);
- if (rv)
- goto out;
-
- po->start = in->start;
- po->end = in->end;
- po->ex = in->ex;
- out:
- return rv;
-}
-
-static int lock_internal(struct mountgroup *mg, struct resource *r,
- struct dlm_plock_info *in)
-{
- struct posix_lock *po, *safe;
- int rv = 0;
-
- list_for_each_entry_safe(po, safe, &r->locks, list) {
- if (po->nodeid != in->nodeid || po->owner != in->owner)
- continue;
- if (!ranges_overlap(po->start, po->end, in->start, in->end))
- continue;
-
- /* existing range (RE) overlaps new range (RN) */
-
- switch(overlap_type(in->start, in->end, po->start, po->end)) {
-
- case 0:
- if (po->ex == in->ex)
- goto out;
-
- /* ranges the same - just update the existing lock */
- po->ex = in->ex;
- goto out;
-
- case 1:
- if (po->ex == in->ex)
- goto out;
-
- rv = lock_case1(po, r, in);
- goto out;
-
- case 2:
- if (po->ex == in->ex)
- goto out;
-
- rv = lock_case2(po, r, in);
- goto out;
-
- case 3:
- list_del(&po->list);
- free(po);
- break;
-
- case 4:
- if (po->start < in->start)
- po->end = in->start - 1;
- else
- po->start = in->end + 1;
- break;
-
- default:
- rv = -1;
- goto out;
- }
- }
-
- rv = add_lock(r, in->nodeid, in->owner, in->pid,
- in->ex, in->start, in->end);
- out:
- return rv;
-
-}
-
-static int unlock_internal(struct mountgroup *mg, struct resource *r,
- struct dlm_plock_info *in)
-{
- struct posix_lock *po, *safe;
- int rv = 0;
-
- list_for_each_entry_safe(po, safe, &r->locks, list) {
- if (po->nodeid != in->nodeid || po->owner != in->owner)
- continue;
- if (!ranges_overlap(po->start, po->end, in->start, in->end))
- continue;
-
- /* existing range (RE) overlaps new range (RN) */
-
- switch (overlap_type(in->start, in->end, po->start, po->end)) {
-
- case 0:
- /* ranges the same - just remove the existing lock */
-
- list_del(&po->list);
- free(po);
- goto out;
-
- case 1:
- /* RN within RE and starts or ends on RE boundary -
- * shrink and update RE */
-
- rv = shrink_range(po, in->start, in->end);
- goto out;
-
- case 2:
- /* RN within RE - shrink and update RE to be front
- * fragment, and add a new lock for back fragment */
-
- rv = add_lock(r, in->nodeid, in->owner, in->pid,
- po->ex, in->end + 1, po->end);
- po->end = in->start - 1;
- goto out;
-
- case 3:
- /* RE within RN - remove RE, then continue checking
- * because RN could cover other locks */
-
- list_del(&po->list);
- free(po);
- continue;
-
- case 4:
- /* front of RE in RN, or end of RE in RN - shrink and
- * update RE, then continue because RN could cover
- * other locks */
-
- rv = shrink_range(po, in->start, in->end);
- continue;
-
- default:
- rv = -1;
- goto out;
- }
- }
- out:
- return rv;
-}
-
-static int add_waiter(struct mountgroup *mg, struct resource *r,
- struct dlm_plock_info *in)
-
-{
- struct lock_waiter *w;
-
- w = malloc(sizeof(struct lock_waiter));
- if (!w)
- return -ENOMEM;
- memcpy(&w->info, in, sizeof(struct dlm_plock_info));
- list_add_tail(&w->list, &r->waiters);
- return 0;
-}
-
-static void write_result(struct mountgroup *mg, struct dlm_plock_info *in,
- int rv)
-{
- if (need_fsid_translation)
- in->fsid = mg->associated_ls_id;
-
- in->rv = rv;
- write(plock_device_fd, in, sizeof(struct dlm_plock_info));
-}
-
-static void do_waiters(struct mountgroup *mg, struct resource *r)
-{
- struct lock_waiter *w, *safe;
- struct dlm_plock_info *in;
- int rv;
-
- list_for_each_entry_safe(w, safe, &r->waiters, list) {
- in = &w->info;
-
- if (is_conflict(r, in, 0))
- continue;
-
- list_del(&w->list);
-
- /*
- log_group(mg, "take waiter %llx %llx-%llx %d/%u/%llx",
- in->number, in->start, in->end,
- in->nodeid, in->pid, in->owner);
- */
-
- rv = lock_internal(mg, r, in);
-
- if (in->nodeid == our_nodeid)
- write_result(mg, in, rv);
-
- free(w);
- }
-}
-
-static void do_lock(struct mountgroup *mg, struct dlm_plock_info *in,
- struct resource *r)
-{
- int rv;
-
- if (is_conflict(r, in, 0)) {
- if (!in->wait)
- rv = -EAGAIN;
- else {
- rv = add_waiter(mg, r, in);
- if (rv)
- goto out;
- rv = -EINPROGRESS;
- }
- } else
- rv = lock_internal(mg, r, in);
-
- out:
- if (in->nodeid == our_nodeid && rv != -EINPROGRESS)
- write_result(mg, in, rv);
-
- do_waiters(mg, r);
- put_resource(r);
-}
-
-static void do_unlock(struct mountgroup *mg, struct dlm_plock_info *in,
- struct resource *r)
-{
- int rv;
-
- rv = unlock_internal(mg, r, in);
-
- if (in->nodeid == our_nodeid)
- write_result(mg, in, rv);
-
- do_waiters(mg, r);
- put_resource(r);
-}
-
-/* we don't even get to this function if the getlk isn't from us */
-
-static void do_get(struct mountgroup *mg, struct dlm_plock_info *in,
- struct resource *r)
-{
- int rv;
-
- if (is_conflict(r, in, 1))
- rv = 1;
- else
- rv = 0;
-
- write_result(mg, in, rv);
- put_resource(r);
-}
-
-static void __receive_plock(struct mountgroup *mg, struct dlm_plock_info *in,
- int from, struct resource *r)
-{
- switch (in->optype) {
- case DLM_PLOCK_OP_LOCK:
- mg->last_plock_time = time(NULL);
- do_lock(mg, in, r);
- break;
- case DLM_PLOCK_OP_UNLOCK:
- mg->last_plock_time = time(NULL);
- do_unlock(mg, in, r);
- break;
- case DLM_PLOCK_OP_GET:
- do_get(mg, in, r);
- break;
- default:
- log_error("receive_plock from %d optype %d", from, in->optype);
- if (from == our_nodeid)
- write_result(mg, in, -EINVAL);
- }
-}
-
-/* When mg members receive our options message (for our mount), one of them
- saves all plock state received to that point in a checkpoint and then sends
- us our journals message. We know to retrieve the plock state from the
- checkpoint when we receive our journals message. Any plocks messages that
- arrive between seeing our options message and our journals message needs to
- be saved and processed after we synchronize our plock state from the
- checkpoint. Any plock message received while we're mounting but before we
- set save_plocks (when we see our options message) can be ignored because it
- should be reflected in the checkpointed state. */
-
-static void _receive_plock(struct mountgroup *mg, char *buf, int len, int from)
-{
- struct dlm_plock_info info;
- struct gdlm_header *hd = (struct gdlm_header *) buf;
- struct resource *r = NULL;
- struct timeval now;
- uint64_t usec;
- int rv, create;
-
- memcpy(&info, buf + sizeof(struct gdlm_header), sizeof(info));
- info_bswap_in(&info);
-
- log_plock(mg, "receive plock %llx %s %s %llx-%llx %d/%u/%llx w %d",
- (unsigned long long)info.number,
- op_str(info.optype),
- ex_str(info.optype, info.ex),
- (unsigned long long)info.start, (unsigned long long)info.end,
- info.nodeid, info.pid, (unsigned long long)info.owner,
- info.wait);
-
- plock_recv_count++;
- if (!(plock_recv_count % 1000)) {
- gettimeofday(&now, NULL);
- usec = dt_usec(&plock_recv_time, &now);
- log_group(mg, "plock_recv_count %u time %.3f s",
- plock_recv_count, usec * 1.e-6);
- plock_recv_time = now;
- }
-
- if (info.optype == DLM_PLOCK_OP_GET && from != our_nodeid)
- return;
-
- if (from != hd->nodeid || from != info.nodeid) {
- log_error("receive_plock from %d header %d info %d",
- from, hd->nodeid, info.nodeid);
- return;
- }
-
- create = !cfgd_plock_ownership;
-
- rv = find_resource(mg, info.number, create, &r);
-
- if (rv && cfgd_plock_ownership) {
- /* There must have been a race with a drop, so we need to
- ignore this plock op which will be resent. If we're the one
- who sent the plock, we need to send_own() and put it on the
- pending list to resend once the owner is established. */
-
- log_debug("receive_plock from %d no r %llx", from,
- (unsigned long long)info.number);
-
- if (from != our_nodeid)
- return;
-
- rv = find_resource(mg, info.number, 1, &r);
- if (rv)
- return;
- send_own(mg, r, our_nodeid);
- save_pending_plock(mg, r, &info);
- return;
- }
- if (rv) {
- /* r not found, rv is -ENOENT, this shouldn't happen because
- process_plocks() creates a resource for every op */
-
- log_error("receive_plock from %d no r %llx %d", from,
- (unsigned long long)info.number, rv);
- return;
- }
-
- /* The owner should almost always be 0 here, but other owners may
- be possible given odd combinations of races with drop. Odd races to
- worry about (some seem pretty improbable):
-
- - A sends drop, B sends plock, receive drop, receive plock.
- This is addressed above.
-
- - A sends drop, B sends plock, receive drop, B reads plock
- and sends own, receive plock, on B we find owner of -1.
-
- - A sends drop, B sends two plocks, receive drop, receive plocks.
- Receiving the first plock is the previous case, receiving the
- second plock will find r with owner of -1.
-
- - A sends drop, B sends two plocks, receive drop, C sends own,
- receive plock, B sends own, receive own (C), receive plock,
- receive own (B).
-
- Haven't tried to cook up a scenario that would lead to the
- last case below; receiving a plock from ourself and finding
- we're the owner of r. */
-
- if (!r->owner) {
- __receive_plock(mg, &info, from, r);
-
- } else if (r->owner == -1) {
- log_debug("receive_plock from %d r %llx owner %d", from,
- (unsigned long long)info.number, r->owner);
-
- if (from == our_nodeid)
- save_pending_plock(mg, r, &info);
-
- } else if (r->owner != our_nodeid) {
- /* might happen, if frequent change to log_debug */
- log_error("receive_plock from %d r %llx owner %d", from,
- (unsigned long long)info.number, r->owner);
-
- if (from == our_nodeid)
- save_pending_plock(mg, r, &info);
-
- } else if (r->owner == our_nodeid) {
- /* might happen, if frequent change to log_debug */
- log_error("receive_plock from %d r %llx owner %d", from,
- (unsigned long long)info.number, r->owner);
-
- if (from == our_nodeid)
- __receive_plock(mg, &info, from, r);
- }
-}
-
-void receive_plock(struct mountgroup *mg, char *buf, int len, int from)
-{
- if (mg->save_plocks) {
- save_message_old(mg, buf, len, from, MSG_PLOCK);
- return;
- }
-
- if (!mg->got_our_journals) {
- log_group(mg, "not saving plock messages yet");
- return;
- }
-
- _receive_plock(mg, buf, len, from);
-}
-
-static int send_struct_info(struct mountgroup *mg, struct dlm_plock_info *in,
- int msg_type)
-{
- char *buf;
- int rv, len;
- struct gdlm_header *hd;
-
- len = sizeof(struct gdlm_header) + sizeof(struct dlm_plock_info);
- buf = malloc(len);
- if (!buf) {
- rv = -ENOMEM;
- goto out;
- }
- memset(buf, 0, len);
-
- info_bswap_out(in);
-
- hd = (struct gdlm_header *)buf;
- hd->type = msg_type;
- hd->nodeid = our_nodeid;
- hd->to_nodeid = 0;
-
- memcpy(buf + sizeof(struct gdlm_header), in, sizeof(*in));
-
- rv = send_group_message_old(mg, len, buf);
-
- free(buf);
- out:
- if (rv)
- log_error("send plock message error %d", rv);
- return rv;
-}
-
-static void send_plock(struct mountgroup *mg, struct resource *r,
- struct dlm_plock_info *in)
-{
- send_struct_info(mg, in, MSG_PLOCK);
-}
-
-static void send_own(struct mountgroup *mg, struct resource *r, int owner)
-{
- struct dlm_plock_info info;
-
- /* if we've already sent an own message for this resource,
- (pending list is not empty), then we shouldn't send another */
-
- if (!list_empty(&r->pending)) {
- log_debug("send_own %llx already pending",
- (unsigned long long)r->number);
- return;
- }
-
- memset(&info, 0, sizeof(info));
- info.number = r->number;
- info.nodeid = owner;
-
- send_struct_info(mg, &info, MSG_PLOCK_OWN);
-}
-
-static void send_syncs(struct mountgroup *mg, struct resource *r)
-{
- struct dlm_plock_info info;
- struct posix_lock *po;
- struct lock_waiter *w;
- int rv;
-
- list_for_each_entry(po, &r->locks, list) {
- memset(&info, 0, sizeof(info));
- info.number = r->number;
- info.start = po->start;
- info.end = po->end;
- info.nodeid = po->nodeid;
- info.owner = po->owner;
- info.pid = po->pid;
- info.ex = po->ex;
-
- rv = send_struct_info(mg, &info, MSG_PLOCK_SYNC_LOCK);
- if (rv)
- goto out;
-
- po->flags |= P_SYNCING;
- }
-
- list_for_each_entry(w, &r->waiters, list) {
- memcpy(&info, &w->info, sizeof(info));
-
- rv = send_struct_info(mg, &info, MSG_PLOCK_SYNC_WAITER);
- if (rv)
- goto out;
-
- w->flags |= P_SYNCING;
- }
- out:
- return;
-}
-
-static void send_drop(struct mountgroup *mg, struct resource *r)
-{
- struct dlm_plock_info info;
-
- memset(&info, 0, sizeof(info));
- info.number = r->number;
-
- send_struct_info(mg, &info, MSG_PLOCK_DROP);
-}
-
-/* plock op can't be handled until we know the owner value of the resource,
- so the op is saved on the pending list until the r owner is established */
-
-static void save_pending_plock(struct mountgroup *mg, struct resource *r,
- struct dlm_plock_info *in)
-{
- struct lock_waiter *w;
-
- w = malloc(sizeof(struct lock_waiter));
- if (!w) {
- log_error("save_pending_plock no mem");
- return;
- }
- memcpy(&w->info, in, sizeof(struct dlm_plock_info));
- list_add_tail(&w->list, &r->pending);
-}
-
-/* plock ops are on pending list waiting for ownership to be established.
- owner has now become us, so add these plocks to r */
-
-static void add_pending_plocks(struct mountgroup *mg, struct resource *r)
-{
- struct lock_waiter *w, *safe;
-
- list_for_each_entry_safe(w, safe, &r->pending, list) {
- __receive_plock(mg, &w->info, our_nodeid, r);
- list_del(&w->list);
- free(w);
- }
-}
-
-/* plock ops are on pending list waiting for ownership to be established.
- owner has now become 0, so send these plocks to everyone */
-
-static void send_pending_plocks(struct mountgroup *mg, struct resource *r)
-{
- struct lock_waiter *w, *safe;
-
- list_for_each_entry_safe(w, safe, &r->pending, list) {
- send_plock(mg, r, &w->info);
- list_del(&w->list);
- free(w);
- }
-}
-
-static void _receive_own(struct mountgroup *mg, char *buf, int len, int from)
-{
- struct gdlm_header *hd = (struct gdlm_header *) buf;
- struct dlm_plock_info info;
- struct resource *r;
- int should_not_happen = 0;
- int rv;
-
- mg->last_plock_time = time(NULL);
-
- memcpy(&info, buf + sizeof(struct gdlm_header), sizeof(info));
- info_bswap_in(&info);
-
- log_plock(mg, "receive own %llx from %u owner %u",
- (unsigned long long)info.number, hd->nodeid, info.nodeid);
-
- rv = find_resource(mg, info.number, 1, &r);
- if (rv)
- return;
-
- if (from == our_nodeid) {
- /*
- * received our own own message
- */
-
- if (info.nodeid == 0) {
- /* we are setting owner to 0 */
-
- if (r->owner == our_nodeid) {
- /* we set owner to 0 when we relinquish
- ownership */
- should_not_happen = 1;
- } else if (r->owner == 0) {
- /* this happens when we relinquish ownership */
- r->flags |= R_GOT_UNOWN;
- } else {
- should_not_happen = 1;
- }
-
- } else if (info.nodeid == our_nodeid) {
- /* we are setting owner to ourself */
-
- if (r->owner == -1) {
- /* we have gained ownership */
- r->owner = our_nodeid;
- add_pending_plocks(mg, r);
- } else if (r->owner == our_nodeid) {
- should_not_happen = 1;
- } else if (r->owner == 0) {
- send_pending_plocks(mg, r);
- } else {
- /* resource is owned by other node;
- they should set owner to 0 shortly */
- }
-
- } else {
- /* we should only ever set owner to 0 or ourself */
- should_not_happen = 1;
- }
- } else {
- /*
- * received own message from another node
- */
-
- if (info.nodeid == 0) {
- /* other node is setting owner to 0 */
-
- if (r->owner == -1) {
- /* we should have a record of the owner before
- it relinquishes */
- should_not_happen = 1;
- } else if (r->owner == our_nodeid) {
- /* only the owner should relinquish */
- should_not_happen = 1;
- } else if (r->owner == 0) {
- should_not_happen = 1;
- } else {
- r->owner = 0;
- r->flags |= R_GOT_UNOWN;
- send_pending_plocks(mg, r);
- }
-
- } else if (info.nodeid == from) {
- /* other node is setting owner to itself */
-
- if (r->owner == -1) {
- /* normal path for a node becoming owner */
- r->owner = from;
- } else if (r->owner == our_nodeid) {
- /* we relinquish our ownership: sync our local
- plocks to everyone, then set owner to 0 */
- send_syncs(mg, r);
- send_own(mg, r, 0);
- /* we need to set owner to 0 here because
- local ops may arrive before we receive
- our send_own message and can't be added
- locally */
- r->owner = 0;
- } else if (r->owner == 0) {
- /* can happen because we set owner to 0 before
- we receive our send_own sent just above */
- } else {
- /* do nothing, current owner should be
- relinquishing its ownership */
- }
-
- } else if (info.nodeid == our_nodeid) {
- /* no one else should try to set the owner to us */
- should_not_happen = 1;
- } else {
- /* a node should only ever set owner to 0 or itself */
- should_not_happen = 1;
- }
- }
-
- if (should_not_happen) {
- log_error("receive_own from %u %llx info nodeid %d r owner %d",
- from, (unsigned long long)r->number, info.nodeid,
- r->owner);
- }
-}
-
-void receive_own(struct mountgroup *mg, char *buf, int len, int from)
-{
- if (mg->save_plocks) {
- save_message_old(mg, buf, len, from, MSG_PLOCK_OWN);
- return;
- }
-
- _receive_own(mg, buf, len, from);
-}
-
-static void clear_syncing_flag(struct resource *r, struct dlm_plock_info *in)
-{
- struct posix_lock *po;
- struct lock_waiter *w;
-
- list_for_each_entry(po, &r->locks, list) {
- if ((po->flags & P_SYNCING) &&
- in->start == po->start &&
- in->end == po->end &&
- in->nodeid == po->nodeid &&
- in->owner == po->owner &&
- in->pid == po->pid &&
- in->ex == po->ex) {
- po->flags &= ~P_SYNCING;
- return;
- }
- }
-
- list_for_each_entry(w, &r->waiters, list) {
- if ((w->flags & P_SYNCING) &&
- in->start == w->info.start &&
- in->end == w->info.end &&
- in->nodeid == w->info.nodeid &&
- in->owner == w->info.owner &&
- in->pid == w->info.pid &&
- in->ex == w->info.ex) {
- w->flags &= ~P_SYNCING;
- return;
- }
- }
-
- log_error("clear_syncing %llx no match %s %llx-%llx %d/%u/%llx",
- (unsigned long long)r->number, in->ex ? "WR" : "RD",
- (unsigned long long)in->start, (unsigned long long)in->end,
- in->nodeid, in->pid, (unsigned long long)in->owner);
-}
-
-static void _receive_sync(struct mountgroup *mg, char *buf, int len, int from)
-{
- struct dlm_plock_info info;
- struct gdlm_header *hd = (struct gdlm_header *) buf;
- struct resource *r;
- int rv;
-
- mg->last_plock_time = time(NULL);
-
- memcpy(&info, buf + sizeof(struct gdlm_header), sizeof(info));
- info_bswap_in(&info);
-
- log_plock(mg, "receive sync %llx from %u %s %llx-%llx %d/%u/%llx",
- (unsigned long long)info.number, from, info.ex ? "WR" : "RD",
- (unsigned long long)info.start, (unsigned long long)info.end,
- info.nodeid, info.pid, (unsigned long long)info.owner);
-
- rv = find_resource(mg, info.number, 0, &r);
- if (rv) {
- log_error("receive_sync no r %llx from %d", info.number, from);
- return;
- }
-
- if (from == our_nodeid) {
- /* this plock now in sync on all nodes */
- clear_syncing_flag(r, &info);
- return;
- }
-
- if (hd->type == MSG_PLOCK_SYNC_LOCK)
- add_lock(r, info.nodeid, info.owner, info.pid, info.ex,
- info.start, info.end);
- else if (hd->type == MSG_PLOCK_SYNC_WAITER)
- add_waiter(mg, r, &info);
-}
-
-void receive_sync(struct mountgroup *mg, char *buf, int len, int from)
-{
- struct gdlm_header *hd = (struct gdlm_header *) buf;
-
- if (mg->save_plocks) {
- save_message_old(mg, buf, len, from, hd->type);
- return;
- }
-
- _receive_sync(mg, buf, len, from);
-}
-
-static void _receive_drop(struct mountgroup *mg, char *buf, int len, int from)
-{
- struct dlm_plock_info info;
- struct resource *r;
- int rv;
-
- mg->last_plock_time = time(NULL);
-
- memcpy(&info, buf + sizeof(struct gdlm_header), sizeof(info));
- info_bswap_in(&info);
-
- log_plock(mg, "receive drop %llx from %u",
- (unsigned long long)info.number, from);
-
- rv = find_resource(mg, info.number, 0, &r);
- if (rv) {
- /* we'll find no r if two nodes sent drop at once */
- log_debug("receive_drop from %d no r %llx", from,
- (unsigned long long)info.number);
- return;
- }
-
- if (r->owner != 0) {
- /* - A sent drop, B sent drop, receive drop A, C sent own,
- receive drop B (this warning on C, owner -1)
- - A sent drop, B sent drop, receive drop A, A sent own,
- receive own A, receive drop B (this warning on all,
- owner A) */
- log_debug("receive_drop from %d r %llx owner %d", from,
- (unsigned long long)r->number, r->owner);
- return;
- }
-
- if (!list_empty(&r->pending)) {
- /* shouldn't happen */
- log_error("receive_drop from %d r %llx pending op", from,
- (unsigned long long)r->number);
- return;
- }
-
- /* the decision to drop or not must be based on things that are
- guaranteed to be the same on all nodes */
-
- if (list_empty(&r->locks) && list_empty(&r->waiters)) {
- list_del(&r->list);
- free(r);
- } else {
- /* A sent drop, B sent a plock, receive plock, receive drop */
- log_debug("receive_drop from %d r %llx in use", from,
- (unsigned long long)r->number);
- }
-}
-
-void receive_drop(struct mountgroup *mg, char *buf, int len, int from)
-{
- if (mg->save_plocks) {
- save_message_old(mg, buf, len, from, MSG_PLOCK_DROP);
- return;
- }
-
- _receive_drop(mg, buf, len, from);
-}
-
-/* We only drop resources from the unowned state to simplify things.
- If we want to drop a resource we own, we unown/relinquish it first. */
-
-/* FIXME: in the transition from owner = us, to owner = 0, to drop;
- we want the second period to be shorter than the first */
-
-static int drop_resources(struct mountgroup *mg)
-{
- struct resource *r;
- struct timeval now;
- int count = 0;
-
- gettimeofday(&now, NULL);
-
- /* try to drop the oldest, unused resources */
-
- list_for_each_entry_reverse(r, &mg->plock_resources, list) {
- if (count >= cfgd_drop_resources_count)
- break;
- if (r->owner && r->owner != our_nodeid)
- continue;
- if (time_diff_ms(&r->last_access, &now) <
- cfgd_drop_resources_age)
- continue;
-
- if (list_empty(&r->locks) && list_empty(&r->waiters)) {
- if (r->owner == our_nodeid) {
- send_own(mg, r, 0);
- r->owner = 0;
- } else if (r->owner == 0 && got_unown(r)) {
- send_drop(mg, r);
- }
-
- count++;
- }
- }
-
- return 0;
-}
-
-/* iterate through directory names looking for matching id:
- /sys/kernel/dlm/<name>/id */
-
-#define DLM_SYSFS_DIR "/sys/kernel/dlm"
-
-static char ls_name[256];
-
-static int get_lockspace_name(uint32_t ls_id)
-{
- char path[PATH_MAX];
- DIR *d;
- FILE *file;
- struct dirent *de;
- uint32_t id;
- int rv, error;
-
- d = opendir(DLM_SYSFS_DIR);
- if (!d) {
- log_debug("%s: opendir failed: %d", path, errno);
- return -1;
- }
-
- rv = -1;
-
- while ((de = readdir(d))) {
- if (de->d_name[0] == '.')
- continue;
-
- id = 0;
- memset(path, 0, PATH_MAX);
- snprintf(path, PATH_MAX, "%s/%s/id", DLM_SYSFS_DIR, de->d_name);
-
- file = fopen(path, "r");
- if (!file) {
- log_error("can't open %s %d", path, errno);
- continue;
- }
-
- error = fscanf(file, "%u", &id);
- fclose(file);
-
- if (error != 1) {
- log_error("bad read %s %d", path, errno);
- continue;
- }
- if (id != ls_id) {
- log_debug("get_lockspace_name skip %x %s",
- id, de->d_name);
- continue;
- }
-
- log_debug("get_lockspace_name found %x %s", id, de->d_name);
- strncpy(ls_name, de->d_name, 256);
- rv = 0;
- break;
- }
-
- closedir(d);
- return rv;
-}
-
-/* find the locskapce with "ls_id" in sysfs, get it's name, then look for
- the mg with with the same name in mounts list, return it's id */
-
-static void set_associated_id(uint32_t ls_id)
-{
- struct mountgroup *mg;
- int rv;
-
- log_debug("set_associated_id ls_id %x %d", ls_id, ls_id);
-
- memset(&ls_name, 0, sizeof(ls_name));
-
- rv = get_lockspace_name(ls_id);
- if (rv) {
- log_error("no lockspace found with id %x", ls_id);
- return;
- }
-
- mg = find_mg(ls_name);
- if (!mg) {
- log_error("no mountgroup found with name %s for ls_id %x",
- ls_name, ls_id);
- return;
- }
-
- log_debug("set_associated_id ls %x is mg %x", ls_id, mg->id);
-
- mg->associated_ls_id = ls_id;
-}
-
-static uint32_t ls_to_mg_id(uint32_t fsid)
-{
- struct mountgroup *mg;
- int do_set = 1;
-
- retry:
- list_for_each_entry(mg, &mountgroups, list) {
- if (mg->associated_ls_id == fsid)
- return mg->id;
- }
-
- if (do_set) {
- do_set = 0;
- set_associated_id(fsid);
- goto retry;
- }
-
- return fsid;
-}
-
-int limit_plocks(void)
-{
- struct timeval now;
-
- /* Don't send more messages while the cpg message queue is backed up */
-
- if (libcpg_flow_control_on) {
- update_flow_control_status();
- if (libcpg_flow_control_on)
- return 1;
- }
-
- if (!cfgd_plock_rate_limit || !plock_read_count)
- return 0;
-
- gettimeofday(&now, NULL);
-
- /* Every time a plock op is read from the kernel, we increment
- plock_read_count. After every cfgd_plock_rate_limit (N) reads,
- we check the time it's taken to do those N; if the time is less than
- a second, then we delay reading any more until a second is up.
- This way we read a max of N ops from the kernel every second. */
-
- if (!(plock_read_count % cfgd_plock_rate_limit)) {
- if (time_diff_ms(&plock_rate_last, &now) < 1000) {
- plock_rate_delays++;
- return 2;
- }
- plock_rate_last = now;
- plock_read_count++;
- }
- return 0;
-}
-
-void process_plocks(int ci)
-{
- struct mountgroup *mg;
- struct resource *r;
- struct dlm_plock_info info;
- struct timeval now;
- uint64_t usec;
- int create, rv;
-
- if (limit_plocks()) {
- poll_ignore_plock = 1;
- client_ignore(plock_ci, plock_fd);
- return;
- }
-
- gettimeofday(&now, NULL);
-
- memset(&info, 0, sizeof(info));
-
- rv = do_read(plock_device_fd, &info, sizeof(info));
- if (rv < 0) {
- log_debug("process_plocks: read error %d fd %d\n",
- errno, plock_device_fd);
- return;
- }
-
- /* kernel doesn't set the nodeid field */
- info.nodeid = our_nodeid;
-
- if (!cfgd_enable_plock) {
- rv = -ENOSYS;
- goto fail;
- }
-
- if (need_fsid_translation)
- info.fsid = ls_to_mg_id(info.fsid);
-
- mg = find_mg_id(info.fsid);
- if (!mg) {
- log_debug("process_plocks: no mg id %x", info.fsid);
- rv = -EEXIST;
- goto fail;
- }
-
- log_plock(mg, "read plock %llx %s %s %llx-%llx %d/%u/%llx w %d",
- (unsigned long long)info.number,
- op_str(info.optype),
- ex_str(info.optype, info.ex),
- (unsigned long long)info.start, (unsigned long long)info.end,
- info.nodeid, info.pid, (unsigned long long)info.owner,
- info.wait);
-
- /* report plock rate and any delays since the last report */
- plock_read_count++;
- if (!(plock_read_count % 1000)) {
- usec = dt_usec(&plock_read_time, &now) ;
- log_group(mg, "plock_read_count %u time %.3f s delays %u",
- plock_read_count, usec * 1.e-6, plock_rate_delays);
- plock_read_time = now;
- plock_rate_delays = 0;
- }
-
- create = (info.optype == DLM_PLOCK_OP_UNLOCK) ? 0 : 1;
-
- rv = find_resource(mg, info.number, create, &r);
- if (rv)
- goto fail;
-
- if (r->owner == 0) {
- /* plock state replicated on all nodes */
- send_plock(mg, r, &info);
-
- } else if (r->owner == our_nodeid) {
- /* we are the owner of r, so our plocks are local */
- __receive_plock(mg, &info, our_nodeid, r);
-
- } else {
- /* r owner is -1: r is new, try to become the owner;
- r owner > 0: tell other owner to give up ownership;
- both done with a message trying to set owner to ourself */
- send_own(mg, r, our_nodeid);
- save_pending_plock(mg, r, &info);
- }
-
- if (cfgd_plock_ownership &&
- time_diff_ms(&mg->drop_resources_last, &now) >=
- cfgd_drop_resources_time) {
- mg->drop_resources_last = now;
- drop_resources(mg);
- }
-
- return;
-
- fail:
- info.rv = rv;
- rv = write(plock_device_fd, &info, sizeof(info));
-
- return;
-}
-
-void process_saved_plocks(struct mountgroup *mg)
-{
- struct save_msg *sm, *sm2;
-
- if (list_empty(&mg->saved_messages))
- return;
-
- log_group(mg, "process_saved_plocks");
-
- list_for_each_entry_safe(sm, sm2, &mg->saved_messages, list) {
- switch (sm->type) {
- case MSG_PLOCK:
- _receive_plock(mg, sm->buf, sm->len, sm->nodeid);
- break;
- case MSG_PLOCK_OWN:
- _receive_own(mg, sm->buf, sm->len, sm->nodeid);
- break;
- case MSG_PLOCK_DROP:
- _receive_drop(mg, sm->buf, sm->len, sm->nodeid);
- break;
- case MSG_PLOCK_SYNC_LOCK:
- case MSG_PLOCK_SYNC_WAITER:
- _receive_sync(mg, sm->buf, sm->len, sm->nodeid);
- break;
- default:
- continue;
- }
-
- list_del(&sm->list);
- free(sm);
- }
-}
-
-/* locks still marked SYNCING should not go into the ckpt; the new node
- will get those locks by receiving PLOCK_SYNC messages */
-
-static void pack_section_buf(struct mountgroup *mg, struct resource *r)
-{
- struct pack_plock *pp;
- struct posix_lock *po;
- struct lock_waiter *w;
- int count = 0;
-
- /* plocks on owned resources are not replicated on other nodes */
- if (r->owner == our_nodeid)
- return;
-
- pp = (struct pack_plock *) §ion_buf;
-
- list_for_each_entry(po, &r->locks, list) {
- if (po->flags & P_SYNCING)
- continue;
- pp->start = cpu_to_le64(po->start);
- pp->end = cpu_to_le64(po->end);
- pp->owner = cpu_to_le64(po->owner);
- pp->pid = cpu_to_le32(po->pid);
- pp->nodeid = cpu_to_le32(po->nodeid);
- pp->ex = po->ex;
- pp->waiter = 0;
- pp++;
- count++;
- }
-
- list_for_each_entry(w, &r->waiters, list) {
- if (w->flags & P_SYNCING)
- continue;
- pp->start = cpu_to_le64(w->info.start);
- pp->end = cpu_to_le64(w->info.end);
- pp->owner = cpu_to_le64(w->info.owner);
- pp->pid = cpu_to_le32(w->info.pid);
- pp->nodeid = cpu_to_le32(w->info.nodeid);
- pp->ex = w->info.ex;
- pp->waiter = 1;
- pp++;
- count++;
- }
-
- section_len = count * sizeof(struct pack_plock);
-}
-
-static int unpack_section_buf(struct mountgroup *mg, char *numbuf, int buflen)
-{
- struct pack_plock *pp;
- struct posix_lock *po;
- struct lock_waiter *w;
- struct resource *r;
- int count = section_len / sizeof(struct pack_plock);
- int i, owner = 0;
- unsigned long long num;
- struct timeval now;
-
- gettimeofday(&now, NULL);
-
- r = malloc(sizeof(struct resource));
- if (!r)
- return -ENOMEM;
- memset(r, 0, sizeof(struct resource));
- INIT_LIST_HEAD(&r->locks);
- INIT_LIST_HEAD(&r->waiters);
- INIT_LIST_HEAD(&r->pending);
-
- if (cfgd_plock_ownership)
- sscanf(numbuf, "r%llu.%d", &num, &owner);
- else
- sscanf(numbuf, "r%llu", &num);
-
- r->number = num;
- r->owner = owner;
- r->last_access = now;
-
- pp = (struct pack_plock *) §ion_buf;
-
- for (i = 0; i < count; i++) {
- if (!pp->waiter) {
- po = malloc(sizeof(struct posix_lock));
- // FIXME: handle failed malloc
- po->start = le64_to_cpu(pp->start);
- po->end = le64_to_cpu(pp->end);
- po->owner = le64_to_cpu(pp->owner);
- po->pid = le32_to_cpu(pp->pid);
- po->nodeid = le32_to_cpu(pp->nodeid);
- po->ex = pp->ex;
- list_add_tail(&po->list, &r->locks);
- } else {
- w = malloc(sizeof(struct lock_waiter));
- // FIXME: handle failed malloc
- w->info.start = le64_to_cpu(pp->start);
- w->info.end = le64_to_cpu(pp->end);
- w->info.owner = le64_to_cpu(pp->owner);
- w->info.pid = le32_to_cpu(pp->pid);
- w->info.nodeid = le32_to_cpu(pp->nodeid);
- w->info.ex = pp->ex;
- list_add_tail(&w->list, &r->waiters);
- }
- pp++;
- }
-
- list_add_tail(&r->list, &mg->plock_resources);
- return 0;
-}
-
-static int _unlink_checkpoint(struct mountgroup *mg, SaNameT *name)
-{
- SaCkptCheckpointHandleT h;
- SaCkptCheckpointDescriptorT s;
- SaAisErrorT rv;
- int ret = 0;
-
- h = (SaCkptCheckpointHandleT) mg->cp_handle;
- log_group(mg, "unlink ckpt %llx", (unsigned long long)h);
-
- unlink_retry:
- rv = saCkptCheckpointUnlink(ckpt_handle, name);
- if (rv == SA_AIS_ERR_TRY_AGAIN) {
- log_group(mg, "unlink ckpt retry");
- sleep(1);
- goto unlink_retry;
- }
- if (rv == SA_AIS_OK)
- goto out_close;
-
- log_error("unlink ckpt error %d %s", rv, mg->name);
- ret = -1;
-
- status_retry:
- rv = saCkptCheckpointStatusGet(h, &s);
- if (rv == SA_AIS_ERR_TRY_AGAIN) {
- log_group(mg, "unlink ckpt status retry");
- sleep(1);
- goto status_retry;
- }
- if (rv != SA_AIS_OK) {
- log_error("unlink ckpt status error %d %s", rv, mg->name);
- goto out_close;
- }
-
- log_group(mg, "unlink ckpt status: size %llu, max sections %u, "
- "max section size %llu, section count %u, mem %u",
- (unsigned long long)s.checkpointCreationAttributes.checkpointSize,
- s.checkpointCreationAttributes.maxSections,
- (unsigned long long)s.checkpointCreationAttributes.maxSectionSize,
- s.numberOfSections, s.memoryUsed);
-
- out_close:
- if (!h)
- goto out;
-
- rv = saCkptCheckpointClose(h);
- if (rv == SA_AIS_ERR_TRY_AGAIN) {
- log_group(mg, "unlink ckpt close retry");
- sleep(1);
- goto out_close;
- }
- if (rv != SA_AIS_OK) {
- log_error("unlink ckpt %llx close err %d %s",
- (unsigned long long)h, rv, mg->name);
- /* should we return an error here and possibly cause
- store_plocks() to fail on this? */
- /* ret = -1; */
- }
- out:
- mg->cp_handle = 0;
- return ret;
-}
-
-int unlink_checkpoint(struct mountgroup *mg)
-{
- SaNameT name;
- int len;
-
- len = snprintf((char *)name.value, SA_MAX_NAME_LENGTH, "gfsplock.%s",
- mg->name);
- name.length = len;
- return _unlink_checkpoint(mg, &name);
-}
-
-/*
- * section id is r<inodenum>.<owner>, the maximum string length is:
- * "r" prefix = 1 strlen("r")
- * max uint64 = 20 strlen("18446744073709551615")
- * "." before owner = 1 strlen(".")
- * max int = 11 strlen("-2147483647")
- * \0 at end = 1
- * ---------------------
- * 34 SECTION_NAME_LEN
- */
-
-#define SECTION_NAME_LEN 34
-
-/* Copy all plock state into a checkpoint so new node can retrieve it. The
- node creating the ckpt for the mounter needs to be the same node that's
- sending the mounter its journals message (i.e. the low nodeid). The new
- mounter knows the ckpt is ready to read only after it gets its journals
- message.
-
- If the mounter is becoming the new low nodeid in the group, the node doing
- the store closes the ckpt and the new node unlinks the ckpt after reading
- it. The ckpt should then disappear and the new node can create a new ckpt
- for the next mounter. */
-
-void store_plocks(struct mountgroup *mg, int nodeid)
-{
- SaCkptCheckpointCreationAttributesT attr;
- SaCkptCheckpointHandleT h;
- SaCkptSectionIdT section_id;
- SaCkptSectionCreationAttributesT section_attr;
- SaCkptCheckpointOpenFlagsT flags;
- SaNameT name;
- SaAisErrorT rv;
- char buf[SECTION_NAME_LEN];
- struct resource *r;
- struct posix_lock *po;
- struct lock_waiter *w;
- int r_count, lock_count, total_size, section_size, max_section_size;
- int len, owner;
-
- if (!cfgd_enable_plock)
- return;
-
- /* no change to plock state since we created the last checkpoint */
- if (mg->last_checkpoint_time > mg->last_plock_time) {
- log_group(mg, "store_plocks: saved ckpt uptodate");
- goto out;
- }
- mg->last_checkpoint_time = time(NULL);
-
- len = snprintf((char *)name.value, SA_MAX_NAME_LENGTH, "gfsplock.%s",
- mg->name);
- name.length = len;
-
- /* unlink an old checkpoint before we create a new one */
- if (mg->cp_handle) {
- if (_unlink_checkpoint(mg, &name))
- return;
- }
-
- /* loop through all plocks to figure out sizes to set in
- the attr fields */
-
- r_count = 0;
- lock_count = 0;
- total_size = 0;
- max_section_size = 0;
-
- list_for_each_entry(r, &mg->plock_resources, list) {
- if (r->owner == -1)
- continue;
-
- r_count++;
- section_size = 0;
- list_for_each_entry(po, &r->locks, list) {
- section_size += sizeof(struct pack_plock);
- lock_count++;
- }
- list_for_each_entry(w, &r->waiters, list) {
- section_size += sizeof(struct pack_plock);
- lock_count++;
- }
- total_size += section_size;
- if (section_size > max_section_size)
- max_section_size = section_size;
- }
-
- log_group(mg, "store_plocks: r_count %d, lock_count %d, pp %u bytes",
- r_count, lock_count, (unsigned int)sizeof(struct pack_plock));
-
- log_group(mg, "store_plocks: total %d bytes, max_section %d bytes",
- total_size, max_section_size);
-
- attr.creationFlags = SA_CKPT_WR_ALL_REPLICAS;
- attr.checkpointSize = total_size;
- attr.retentionDuration = SA_TIME_MAX;
- attr.maxSections = r_count + 1; /* don't know why we need +1 */
- attr.maxSectionSize = max_section_size;
- attr.maxSectionIdSize = SECTION_NAME_LEN;
-
- flags = SA_CKPT_CHECKPOINT_READ |
- SA_CKPT_CHECKPOINT_WRITE |
- SA_CKPT_CHECKPOINT_CREATE;
-
- open_retry:
- rv = saCkptCheckpointOpen(ckpt_handle, &name, &attr, flags, 0, &h);
- if (rv == SA_AIS_ERR_TRY_AGAIN) {
- log_group(mg, "store_plocks: ckpt open retry");
- sleep(1);
- goto open_retry;
- }
- if (rv == SA_AIS_ERR_EXIST) {
- log_group(mg, "store_plocks: ckpt already exists");
- return;
- }
- if (rv != SA_AIS_OK) {
- log_error("store_plocks: ckpt open error %d %s", rv, mg->name);
- return;
- }
-
- log_group(mg, "store_plocks: open ckpt handle %llx",
- (unsigned long long)h);
- mg->cp_handle = (uint64_t) h;
-
- /* - If r owner is -1, ckpt nothing.
- - If r owner is us, ckpt owner of us and no plocks.
- - If r owner is other, ckpt that owner and any plocks we have on r
- (they've just been synced but owner=0 msg not recved yet).
- - If r owner is 0 and !got_unown, then we've just unowned r;
- ckpt owner of us and any plocks that don't have SYNCING set
- (plocks with SYNCING will be handled by our sync messages).
- - If r owner is 0 and got_unown, then ckpt owner 0 and all plocks;
- (there should be no SYNCING plocks) */
-
- list_for_each_entry(r, &mg->plock_resources, list) {
- if (r->owner == -1)
- continue;
- else if (r->owner == our_nodeid)
- owner = our_nodeid;
- else if (r->owner)
- owner = r->owner;
- else if (!r->owner && !got_unown(r))
- owner = our_nodeid;
- else if (!r->owner)
- owner = 0;
- else {
- log_error("store_plocks owner %d r %llx", r->owner,
- (unsigned long long)r->number);
- continue;
- }
-
- memset(&buf, 0, sizeof(buf));
- if (cfgd_plock_ownership)
- len = snprintf(buf, SECTION_NAME_LEN, "r%llu.%d",
- (unsigned long long)r->number, owner);
- else
- len = snprintf(buf, SECTION_NAME_LEN, "r%llu",
- (unsigned long long)r->number);
-
- section_id.id = (void *)buf;
- section_id.idLen = len + 1;
- section_attr.sectionId = §ion_id;
- section_attr.expirationTime = SA_TIME_END;
-
- memset(§ion_buf, 0, sizeof(section_buf));
- section_len = 0;
-
- pack_section_buf(mg, r);
-
- log_group(mg, "store_plocks: section size %u id %u \"%s\"",
- section_len, section_id.idLen, buf);
-
- create_retry:
- rv = saCkptSectionCreate(h, §ion_attr, §ion_buf,
- section_len);
- if (rv == SA_AIS_ERR_TRY_AGAIN) {
- log_group(mg, "store_plocks: ckpt create retry");
- sleep(1);
- goto create_retry;
- }
- if (rv == SA_AIS_ERR_EXIST) {
- /* this shouldn't happen in general */
- log_group(mg, "store_plocks: clearing old ckpt");
- saCkptCheckpointClose(h);
- _unlink_checkpoint(mg, &name);
- goto open_retry;
- }
- if (rv != SA_AIS_OK) {
- log_error("store_plocks: ckpt section create err %d %s",
- rv, mg->name);
- break;
- }
- }
-
- out:
- /* If the new nodeid is becoming the low nodeid it will now be in
- charge of creating ckpt's for mounters instead of us. */
-
- if (nodeid < our_nodeid) {
- log_group(mg, "store_plocks: closing ckpt for new low node %d",
- nodeid);
- saCkptCheckpointClose(h);
- mg->cp_handle = 0;
- }
-}
-
-/* called by a node that's just been added to the group to get existing plock
- state */
-
-void retrieve_plocks(struct mountgroup *mg)
-{
- SaCkptCheckpointHandleT h;
- SaCkptSectionIterationHandleT itr;
- SaCkptSectionDescriptorT desc;
- SaCkptIOVectorElementT iov;
- SaNameT name;
- SaAisErrorT rv;
- char buf[SECTION_NAME_LEN];
- int len;
-
- if (!cfgd_enable_plock)
- return;
-
- log_group(mg, "retrieve_plocks");
-
- len = snprintf((char *)name.value, SA_MAX_NAME_LENGTH, "gfsplock.%s",
- mg->name);
- name.length = len;
-
- open_retry:
- rv = saCkptCheckpointOpen(ckpt_handle, &name, NULL,
- SA_CKPT_CHECKPOINT_READ, 0, &h);
- if (rv == SA_AIS_ERR_TRY_AGAIN) {
- log_group(mg, "retrieve_plocks: ckpt open retry");
- sleep(1);
- goto open_retry;
- }
- if (rv != SA_AIS_OK) {
- log_error("retrieve_plocks: ckpt open error %d %s",
- rv, mg->name);
- return;
- }
-
- init_retry:
- rv = saCkptSectionIterationInitialize(h, SA_CKPT_SECTIONS_ANY, 0, &itr);
- if (rv == SA_AIS_ERR_TRY_AGAIN) {
- log_group(mg, "retrieve_plocks: ckpt iterinit retry");
- sleep(1);
- goto init_retry;
- }
- if (rv != SA_AIS_OK) {
- log_error("retrieve_plocks: ckpt iterinit error %d %s",
- rv, mg->name);
- goto out;
- }
-
- while (1) {
- next_retry:
- rv = saCkptSectionIterationNext(itr, &desc);
- if (rv == SA_AIS_ERR_NO_SECTIONS)
- break;
- if (rv == SA_AIS_ERR_TRY_AGAIN) {
- log_group(mg, "retrieve_plocks: ckpt iternext retry");
- sleep(1);
- goto next_retry;
- }
- if (rv != SA_AIS_OK) {
- log_error("retrieve_plocks: ckpt iternext error %d %s",
- rv, mg->name);
- goto out_it;
- }
-
- if (!desc.sectionId.idLen)
- continue;
-
- iov.sectionId = desc.sectionId;
- iov.dataBuffer = §ion_buf;
- iov.dataSize = desc.sectionSize;
- iov.dataOffset = 0;
-
- /* for debug print */
- memset(&buf, 0, sizeof(buf));
- snprintf(buf, SECTION_NAME_LEN, "%s", desc.sectionId.id);
-
- log_group(mg, "retrieve_plocks: section size %llu id %u \"%s\"",
- (unsigned long long)iov.dataSize, iov.sectionId.idLen,
- buf);
-
- read_retry:
- rv = saCkptCheckpointRead(h, &iov, 1, NULL);
- if (rv == SA_AIS_ERR_TRY_AGAIN) {
- log_group(mg, "retrieve_plocks: ckpt read retry");
- sleep(1);
- goto read_retry;
- }
- if (rv != SA_AIS_OK) {
- log_error("retrieve_plocks: ckpt read error %d %s",
- rv, mg->name);
- goto out_it;
- }
-
- /* we'll get empty (zero length) sections for resources with
- no locks, which exist in ownership mode; the resource
- name and owner come from the section id */
-
- log_group(mg, "retrieve_plocks: ckpt read %llu bytes",
- (unsigned long long)iov.readSize);
- section_len = iov.readSize;
-
- if (section_len % sizeof(struct pack_plock)) {
- log_error("retrieve_plocks: bad section len %d %s",
- section_len, mg->name);
- continue;
- }
-
- unpack_section_buf(mg, (char *)desc.sectionId.id,
- desc.sectionId.idLen);
- }
-
- out_it:
- saCkptSectionIterationFinalize(itr);
- out:
- if (mg->low_nodeid == our_nodeid) {
- /* we're the new low nodeid, will be master */
- log_group(mg, "retrieve_plocks: unlink ckpt from old master");
- mg->cp_handle = (uint64_t) h;
- _unlink_checkpoint(mg, &name);
- } else
- saCkptCheckpointClose(h);
-}
-
-/* Called when a node has failed, or we're unmounting. For a node failure, we
- need to call this when the cpg confchg arrives so that we're guaranteed all
- nodes do this in the same sequence wrt other messages. */
-
-void purge_plocks(struct mountgroup *mg, int nodeid, int unmount)
-{
- struct posix_lock *po, *po2;
- struct lock_waiter *w, *w2;
- struct resource *r, *r2;
- int purged = 0;
-
- if (!cfgd_enable_plock)
- return;
-
- list_for_each_entry_safe(r, r2, &mg->plock_resources, list) {
- list_for_each_entry_safe(po, po2, &r->locks, list) {
- if (po->nodeid == nodeid || unmount) {
- list_del(&po->list);
- free(po);
- purged++;
- }
- }
-
- list_for_each_entry_safe(w, w2, &r->waiters, list) {
- if (w->info.nodeid == nodeid || unmount) {
- list_del(&w->list);
- free(w);
- purged++;
- }
- }
-
- /* TODO: haven't thought carefully about how this transition
- to owner 0 might interact with other owner messages in
- progress. */
-
- if (r->owner == nodeid) {
- r->owner = 0;
- send_pending_plocks(mg, r);
- }
-
- if (!list_empty(&r->waiters))
- do_waiters(mg, r);
-
- if (!cfgd_plock_ownership &&
- list_empty(&r->locks) && list_empty(&r->waiters)) {
- list_del(&r->list);
- free(r);
- }
- }
-
- if (purged)
- mg->last_plock_time = time(NULL);
-
- log_group(mg, "purged %d plocks for %d", purged, nodeid);
-
- /* we may have a saved ckpt that we created for the last mounter,
- we need to unlink it so another node can create a new ckpt for
- the next mounter after we leave */
-
- if (unmount && mg->cp_handle)
- unlink_checkpoint(mg);
-}
-
-int fill_plock_dump_buf(struct mountgroup *mg)
-{
- struct posix_lock *po;
- struct lock_waiter *w;
- struct resource *r;
- struct timeval now;
- int rv = 0;
- int len = GFSC_DUMP_SIZE, pos = 0, ret;
-
- memset(plock_dump_buf, 0, sizeof(plock_dump_buf));
- plock_dump_len = 0;
-
- gettimeofday(&now, NULL);
-
- list_for_each_entry(r, &mg->plock_resources, list) {
-
- if (list_empty(&r->locks) &&
- list_empty(&r->waiters) &&
- list_empty(&r->pending)) {
- ret = snprintf(plock_dump_buf + pos, len - pos,
- "%llu rown %d unused_ms %llu\n",
- (unsigned long long)r->number, r->owner,
- (unsigned long long)time_diff_ms(&r->last_access,
- &now));
- if (ret >= len - pos) {
- rv = -ENOSPC;
- goto out;
- }
- pos += ret;
- continue;
- }
-
- list_for_each_entry(po, &r->locks, list) {
- ret = snprintf(plock_dump_buf + pos, len - pos,
- "%llu %s %llu-%llu nodeid %d pid %u owner %llx rown %d\n",
- (unsigned long long)r->number,
- po->ex ? "WR" : "RD",
- (unsigned long long)po->start,
- (unsigned long long)po->end,
- po->nodeid, po->pid,
- (unsigned long long)po->owner, r->owner);
-
- if (ret >= len - pos) {
- rv = -ENOSPC;
- goto out;
- }
- pos += ret;
- }
-
- list_for_each_entry(w, &r->waiters, list) {
- ret = snprintf(plock_dump_buf + pos, len - pos,
- "%llu %s %llu-%llu nodeid %d pid %u owner %llx rown %d WAITING\n",
- (unsigned long long)r->number,
- w->info.ex ? "WR" : "RD",
- (unsigned long long)w->info.start,
- (unsigned long long)w->info.end,
- w->info.nodeid, w->info.pid,
- (unsigned long long)w->info.owner, r->owner);
-
- if (ret >= len - pos) {
- rv = -ENOSPC;
- goto out;
- }
- pos += ret;
- }
-
- list_for_each_entry(w, &r->pending, list) {
- ret = snprintf(plock_dump_buf + pos, len - pos,
- "%llu %s %llu-%llu nodeid %d pid %u owner %llx rown %d PENDING\n",
- (unsigned long long)r->number,
- w->info.ex ? "WR" : "RD",
- (unsigned long long)w->info.start,
- (unsigned long long)w->info.end,
- w->info.nodeid, w->info.pid,
- (unsigned long long)w->info.owner, r->owner);
-
- if (ret >= len - pos) {
- rv = -ENOSPC;
- goto out;
- }
- pos += ret;
- }
- }
- out:
- plock_dump_len = pos;
- return rv;
-}
-
-static void find_minors(void)
-{
- FILE *fl;
- char name[256];
- uint32_t number;
- int found = 0;
- int c;
-
- plock_minor = 0;
- old_plock_minor = 0;
-
- if (!(fl = fopen("/proc/misc", "r"))) {
- log_error("/proc/misc fopen failed: %s", strerror(errno));
- return;
- }
-
- while (!feof(fl)) {
- if (fscanf(fl, "%d %255s\n", &number, &name[0]) == 2) {
-
- if (!strcmp(name, "dlm_plock")) {
- plock_minor = number;
- found++;
- } else if (!strcmp(name, "lock_dlm_plock")) {
- old_plock_minor = number;
- found++;
- }
-
- } else do {
- c = fgetc(fl);
- } while (c != EOF && c != '\n');
-
- if (found == 3)
- break;
- }
- fclose(fl);
-
- if (!found)
- log_error("Is lock_dlm or dlm missing from kernel? No misc devices found.");
-}
-
-static int find_udev_device(const char *path, uint32_t minor)
-{
- struct stat st;
- int i;
-
- for (i = 0; i < 10; i++) {
- if (stat(path, &st) == 0 && minor(st.st_rdev) == minor)
- return 0;
- sleep(1);
- }
-
- log_error("cannot find device %s with minor %d", path, minor);
- return -1;
-}
-
-int setup_misc_devices(void)
-{
- int rv;
-
- find_minors();
-
- if (plock_minor) {
- rv = find_udev_device("/dev/misc/dlm_plock", plock_minor);
- if (rv < 0)
- return rv;
- log_debug("found /dev/misc/dlm_plock minor %u",
- plock_minor);
- }
-
- if (!plock_minor && old_plock_minor) {
- rv = find_udev_device("/dev/misc/lock_dlm_plock",
- old_plock_minor);
- if (rv < 0)
- return rv;
- log_debug("found /dev/misc/lock_dlm_plock minor %u",
- old_plock_minor);
- }
-
- return 0;
-}
-
diff --git a/group/gfs_controld/util.c b/group/gfs_controld/util.c
deleted file mode 100644
index 7aea26e..0000000
--- a/group/gfs_controld/util.c
+++ /dev/null
@@ -1,289 +0,0 @@
-#include "gfs_daemon.h"
-#include "config.h"
-#include "libfenced.h"
-
-void update_flow_control_status(void)
-{
- cpg_flow_control_state_t flow_control_state;
- cpg_error_t error;
-
- error = cpg_flow_control_state_get(cpg_handle_daemon, &flow_control_state);
- if (error != CPG_OK) {
- log_error("cpg_flow_control_state_get %d", error);
- return;
- }
-
- if (flow_control_state == CPG_FLOW_CONTROL_ENABLED) {
- if (libcpg_flow_control_on == 0) {
- log_debug("flow control on");
- }
- libcpg_flow_control_on = 1;
- } else {
- if (libcpg_flow_control_on) {
- log_debug("flow control off");
- }
- libcpg_flow_control_on = 0;
- }
-}
-
-int we_are_in_fence_domain(void)
-{
- struct fenced_node nodeinfo;
- int rv;
-
- memset(&nodeinfo, 0, sizeof(nodeinfo));
-
- rv = fenced_node_info(our_nodeid, &nodeinfo);
- if (rv < 0) {
- log_debug("fenced_node_info error %d", rv);
- return 0;
- }
-
- if (nodeinfo.member)
- return 1;
- return 0;
-}
-
-#define SYSFS_DIR "/sys/fs"
-#define SYSFS_BUFLEN 64
-
-int set_sysfs(struct mountgroup *mg, const char *field, int val)
-{
- char fname[PATH_MAX];
- char out[SYSFS_BUFLEN];
- int rv, fd;
-
- snprintf(fname, PATH_MAX, "%s/%s/%s/lock_module/%s",
- SYSFS_DIR, mg->mount_args.type, mg->mount_args.table, field);
-
- log_group(mg, "set %s to %d", fname, val);
-
- fd = open(fname, O_RDWR);
- if (fd < 0) {
- log_group(mg, "set open %s error %d %d", fname, fd, errno);
- return -1;
- }
-
- mg->got_kernel_mount = 1;
-
- memset(out, 0, sizeof(out));
- sprintf(out, "%d", val);
-
- rv = write(fd, out, strlen(out));
-
- close(fd);
-
- if (rv)
- rv = 0;
- return rv;
-}
-
-static int get_sysfs(struct mountgroup *mg, const char *field, char *buf, int len)
-{
- char fname[PATH_MAX], *p;
- int fd, rv;
-
- snprintf(fname, PATH_MAX, "%s/%s/%s/lock_module/%s",
- SYSFS_DIR, mg->mount_args.type, mg->mount_args.table, field);
-
- fd = open(fname, O_RDONLY);
- if (fd < 0) {
- log_group(mg, "get open %s error %d %d", fname, fd, errno);
- return -1;
- }
-
- mg->got_kernel_mount = 1;
-
- rv = read(fd, buf, len);
- if (rv < 0)
- log_error("read %s error %d %d", fname, rv, errno);
- else {
- rv = 0;
- p = strchr(buf, '\n');
- if (p)
- *p = '\0';
- }
-
- close(fd);
- return rv;
-}
-
-int read_sysfs_int(struct mountgroup *mg, const char *field, int *val_out)
-{
- char buf[SYSFS_BUFLEN];
- int rv;
-
- memset(buf, 0, sizeof(buf));
-
- rv = get_sysfs(mg, field, buf, sizeof(buf));
- if (rv < 0)
- return rv;
-
- *val_out = atoi(buf);
- return 0;
-}
-
-int run_dmsetup_suspend(struct mountgroup *mg, char *dev)
-{
- struct sched_param sched_param;
- char buf[PATH_MAX];
- pid_t pid;
- int i, rv;
-
- memset(buf, 0, sizeof(buf));
- rv = readlink(dev, buf, PATH_MAX);
- if (rv < 0)
- strncpy(buf, dev, sizeof(buf));
-
- log_group(mg, "run_dmsetup_suspend %s (orig %s)", buf, dev);
-
- pid = fork();
- if (pid < 0)
- return -1;
-
- if (pid) {
- mg->dmsetup_wait = 1;
- mg->dmsetup_pid = pid;
- return 0;
- } else {
- sched_param.sched_priority = 0;
- sched_setscheduler(0, SCHED_OTHER, &sched_param);
-
- for (i = 0; i < 50; i++)
- close(i);
-
- execlp("dmsetup", "dmsetup", "suspend", "--nolockfs",
- "--noflush", buf, NULL);
- exit(EXIT_FAILURE);
- }
- return -1;
-}
-
-static void dmsetup_suspend_done(struct mountgroup *mg, int rv)
-{
- log_group(mg, "dmsetup_suspend_done result %d", rv);
- mg->dmsetup_wait = 0;
- mg->dmsetup_pid = 0;
-
- if (!rv) {
- mg->withdraw_suspend = 1;
- if (mg->old_group_mode)
- send_withdraw_old(mg);
- else
- send_withdraw(mg);
- }
-}
-
-void update_dmsetup_wait(void)
-{
- struct mountgroup *mg;
- int status;
- int waiting = 0;
- pid_t pid;
-
- list_for_each_entry(mg, &mountgroups, list) {
- if (mg->dmsetup_wait) {
- pid = waitpid(mg->dmsetup_pid, &status, WNOHANG);
-
- /* process not exited yet */
- if (!pid) {
- waiting++;
- continue;
- }
-
- if (pid < 0) {
- log_error("update_dmsetup_wait %s: waitpid %d "
- "error %d", mg->name,
- mg->dmsetup_pid, errno);
- dmsetup_suspend_done(mg, -2);
- continue;
- }
-
- /* process exited */
-
- if (!WIFEXITED(status) || WEXITSTATUS(status))
- dmsetup_suspend_done(mg, -1);
- else
- dmsetup_suspend_done(mg, 0);
- }
- }
-
- if (!waiting) {
- dmsetup_wait = 0;
- log_debug("dmsetup_wait off");
- }
-}
-
-static int ignore_nolock(const char *sysfs_dir, char *table)
-{
- char path[PATH_MAX];
- int fd;
-
- memset(path, 0, PATH_MAX);
-
- snprintf(path, PATH_MAX, "%s/%s/lock_module/proto_name",
- sysfs_dir, table);
-
- /* lock_nolock doesn't create the "lock_module" dir at all,
- so we'll fail to open this */
-
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return 1;
-
- close(fd);
- return 0;
-}
-
-/* This is for the case where gfs_controld exits/fails, abandoning gfs
- filesystems in the kernel, and then gfs_controld is restarted. When
- gfs_controld exits and abandons lockspaces, that node needs to be
- rebooted to clear the uncontrolled filesystems from the kernel. */
-
-int check_uncontrolled_filesystems(void)
-{
- DIR *d;
- struct dirent *de;
- int count = 0;
-
- d = opendir("/sys/fs/gfs/");
- if (!d)
- goto gfs2;
-
- while ((de = readdir(d))) {
- if (de->d_name[0] == '.')
- continue;
-
- if (ignore_nolock("/sys/fs/gfs/", de->d_name))
- continue;
-
- log_error("found uncontrolled gfs fs %s", de->d_name);
- count++;
- }
- closedir(d);
-
- gfs2:
- d = opendir("/sys/fs/gfs2/");
- if (!d)
- goto out;
-
- while ((de = readdir(d))) {
- if (de->d_name[0] == '.')
- continue;
-
- if (ignore_nolock("/sys/fs/gfs2/", de->d_name))
- continue;
-
- log_error("found uncontrolled gfs2 fs %s", de->d_name);
- count++;
- }
- closedir(d);
-
- out:
- if (count) {
- kick_node_from_cluster(our_nodeid);
- return -1;
- }
- return 0;
-}
-
diff --git a/group/libgfscontrol/Makefile b/group/libgfscontrol/Makefile
deleted file mode 100644
index fab27a2..0000000
--- a/group/libgfscontrol/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-TARGET= libgfscontrol
-
-MAKESTATICLIB = 1
-
-OBJS= main.o
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/libs.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-CFLAGS += -fPIC
-CFLAGS += -I$(S)/../../group/gfs_controld
-CFLAGS += -I${incdir}
diff --git a/group/libgfscontrol/libgfscontrol.h b/group/libgfscontrol/libgfscontrol.h
deleted file mode 100644
index e5bb969..0000000
--- a/group/libgfscontrol/libgfscontrol.h
+++ /dev/null
@@ -1,122 +0,0 @@
-#ifndef _LIBGFSCONTROL_H_
-#define _LIBGFSCONTROL_H_
-
-/* Maximum mountgroup name length, should match DLM_LOCKSPACE_LEN from
- linux/dlmconstants.h. The libcpg limit is larger at
- CPG_MAX_NAME_LENGTH 128. Our cpg name includes a "gfs:" prefix before
- the mountgroup name. */
-
-#define GFS_MOUNTGROUP_LEN 64
-
-#define GFSC_DUMP_SIZE (1024 * 1024)
-
-#define GFSC_NF_MEMBER 0x00000001 /* node is member in cg */
-#define GFSC_NF_START 0x00000002 /* start message recvd */
-#define GFSC_NF_DISALLOWED 0x00000004 /* node disallowed in cg */
-#define GFSC_NF_KERNEL_MOUNT_DONE 0x00000008
-#define GFSC_NF_KERNEL_MOUNT_ERROR 0x00000010
-#define GFSC_NF_READONLY 0x00000020
-#define GFSC_NF_SPECTATOR 0x00000040
-#define GFSC_NF_CHECK_DLM 0x00000080
-
-struct gfsc_node {
- int nodeid;
- int jid;
- uint32_t flags;
- uint32_t added_seq;
- uint32_t removed_seq;
- int failed_reason;
-};
-
-struct gfsc_change {
- int member_count;
- int joined_count;
- int remove_count;
- int failed_count;
- int wait_condition; /* 0 no, 1 fencing, 2 quorum, 3 fs */
- int wait_messages; /* 0 no, 1 yes */
- uint32_t seq;
- uint32_t combined_seq;
-};
-
-#define GFSC_MF_JOINING 0x00000001
-#define GFSC_MF_LEAVING 0x00000002
-#define GFSC_MF_KERNEL_STOPPED 0x00000004
-#define GFSC_MF_KERNEL_MOUNT_DONE 0x00000008
-#define GFSC_MF_KERNEL_MOUNT_ERROR 0x00000010
-#define GFSC_MF_FIRST_RECOVERY_NEEDED 0x00000020
-#define GFSC_MF_FIRST_RECOVERY_MSG 0x00000040
-#define GFSC_MF_LOCAL_RECOVERY_BUSY 0x00000080
-
-struct gfsc_mountgroup {
- int group_mode;
- struct gfsc_change cg_prev; /* completed change (started_change) */
- struct gfsc_change cg_next; /* in-progress change (changes list) */
- int journals_need_recovery; /* count of jounals need_recovery */
- uint32_t flags;
- uint32_t global_id;
- char name[GFS_MOUNTGROUP_LEN+1];
-};
-
-/* gfsc_mountgroup_nodes() types
-
- MEMBERS: members in completed (prev) change,
- zero if there's no completed (prev) change
- NEXT: members in in-progress (next) change,
- zero if there's no in-progress (next) change
- ALL: NEXT + nonmembers if there's an in-progress (next) change,
- MEMBERS + nonmembers if there's no in-progress (next) change, but
- there is a completed (prev) change
- nonmembers if there's no in-progress (next) or completed (prev)
- change (possible?)
-
- gfsc_node_info() returns info for in-progress (next) change, if one exists,
- otherwise it returns info for completed (prev) change.
-*/
-
-#define GFSC_NODES_ALL 1
-#define GFSC_NODES_MEMBERS 2
-#define GFSC_NODES_NEXT 3
-
-int gfsc_dump_debug(char *buf);
-int gfsc_dump_plocks(char *name, char *buf);
-int gfsc_mountgroup_info(char *mgname, struct gfsc_mountgroup *mg);
-int gfsc_node_info(char *mgname, int nodeid, struct gfsc_node *node);
-int gfsc_mountgroups(int max, int *count, struct gfsc_mountgroup *mgs);
-int gfsc_mountgroup_nodes(char *mgname, int type, int max, int *count,
- struct gfsc_node *nodes);
-
-struct gfsc_mount_args {
- char dir[PATH_MAX];
- char type[PATH_MAX];
- char proto[PATH_MAX];
- char table[PATH_MAX];
- char options[PATH_MAX];
- char dev[PATH_MAX];
- char hostdata[PATH_MAX];
-};
-
-/*
- * mount.gfs connects to gfs_controld,
- * mount.gfs tells gfs_controld to do a join or remount,
- * mount.gfs reads the result of the join or remount from gfs_controld,
- * mount.gfs tells gfs_controld the result of the mount(2),
- * mount.gfs disconnects from gfs_controld
- */
-
-int gfsc_fs_connect(void);
-int gfsc_fs_join(int fd, struct gfsc_mount_args *ma);
-int gfsc_fs_remount(int fd, struct gfsc_mount_args *ma);
-int gfsc_fs_result(int fd, int *result, struct gfsc_mount_args *ma);
-int gfsc_fs_mount_done(int fd, struct gfsc_mount_args *ma, int result);
-void gfsc_fs_disconnect(int fd);
-
-/*
- * mount.gfs tells gfs_controld to do a leave (due to a mount failure)
- * for unmount, gfs_controld leaves due to a message from the kernel
- */
-
-int gfsc_fs_leave(struct gfsc_mount_args *ma, int reason);
-
-#endif
-
diff --git a/group/libgfscontrol/main.c b/group/libgfscontrol/main.c
deleted file mode 100644
index 39987ea..0000000
--- a/group/libgfscontrol/main.c
+++ /dev/null
@@ -1,426 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <limits.h>
-
-#include "libgfscontrol.h"
-#include "gfs_controld.h"
-
-static int do_read(int fd, void *buf, size_t count)
-{
- int rv, off = 0;
-
- while (off < count) {
- rv = read(fd, (char *)buf + off, count - off);
- if (rv == 0)
- return -1;
- if (rv == -1 && errno == EINTR)
- continue;
- if (rv == -1)
- return -1;
- off += rv;
- }
- return 0;
-}
-
-static int do_write(int fd, void *buf, size_t count)
-{
- int rv, off = 0;
-
- retry:
- rv = write(fd, (char *)buf + off, count);
- if (rv == -1 && errno == EINTR)
- goto retry;
- if (rv < 0) {
- return rv;
- }
-
- if (rv != count) {
- count -= rv;
- off += rv;
- goto retry;
- }
- return 0;
-}
-
-static int do_connect(const char *sock_path)
-{
- struct sockaddr_un sun;
- socklen_t addrlen;
- int rv, fd;
-
- fd = socket(PF_UNIX, SOCK_STREAM, 0);
- if (fd < 0)
- goto out;
-
- memset(&sun, 0, sizeof(sun));
- sun.sun_family = AF_UNIX;
- strcpy(&sun.sun_path[1], sock_path);
- addrlen = sizeof(sa_family_t) + strlen(sun.sun_path+1) + 1;
-
- rv = connect(fd, (struct sockaddr *) &sun, addrlen);
- if (rv < 0) {
- close(fd);
- fd = rv;
- }
- out:
- return fd;
-}
-
-static void init_header(struct gfsc_header *h, int cmd, char *name,
- int extra_len)
-{
- memset(h, 0, sizeof(struct gfsc_header));
-
- h->magic = GFSC_MAGIC;
- h->version = GFSC_VERSION;
- h->len = sizeof(struct gfsc_header) + extra_len;
- h->command = cmd;
-
- if (name)
- strncpy(h->name, name, GFS_MOUNTGROUP_LEN);
-}
-
-static int do_dump(int cmd, char *name, char *buf)
-{
- struct gfsc_header h, *rh;
- char *reply;
- int reply_len;
- int fd, rv;
-
- init_header(&h, cmd, name, 0);
-
- reply_len = sizeof(struct gfsc_header) + GFSC_DUMP_SIZE;
- reply = malloc(reply_len);
- if (!reply) {
- rv = -1;
- goto out;
- }
- memset(reply, 0, reply_len);
-
- fd = do_connect(GFSC_QUERY_SOCK_PATH);
- if (fd < 0) {
- rv = fd;
- goto out;
- }
-
- rv = do_write(fd, &h, sizeof(h));
- if (rv < 0)
- goto out_close;
-
- /* won't always get back the full reply_len */
- do_read(fd, reply, reply_len);
-
- rh = (struct gfsc_header *)reply;
- rv = rh->data;
- if (rv < 0)
- goto out_close;
-
- memcpy(buf, (char *)reply + sizeof(struct gfsc_header),
- GFSC_DUMP_SIZE);
- out_close:
- close(fd);
- out:
- return rv;
-}
-
-int gfsc_dump_debug(char *buf)
-{
- return do_dump(GFSC_CMD_DUMP_DEBUG, NULL, buf);
-}
-
-int gfsc_dump_plocks(char *name, char *buf)
-{
- return do_dump(GFSC_CMD_DUMP_PLOCKS, name, buf);
-}
-
-int gfsc_node_info(char *name, int nodeid, struct gfsc_node *node)
-{
- struct gfsc_header h, *rh;
- char reply[sizeof(struct gfsc_header) + sizeof(struct gfsc_node)];
- int fd, rv;
-
- init_header(&h, GFSC_CMD_NODE_INFO, name, 0);
- h.data = nodeid;
-
- memset(reply, 0, sizeof(reply));
-
- fd = do_connect(GFSC_QUERY_SOCK_PATH);
- if (fd < 0) {
- rv = fd;
- goto out;
- }
-
- rv = do_write(fd, &h, sizeof(h));
- if (rv < 0)
- goto out_close;
-
- rv = do_read(fd, reply, sizeof(reply));
- if (rv < 0)
- goto out_close;
-
- rh = (struct gfsc_header *)reply;
- rv = rh->data;
- if (rv < 0)
- goto out_close;
-
- memcpy(node, (char *)reply + sizeof(struct gfsc_header),
- sizeof(struct gfsc_node));
- out_close:
- close(fd);
- out:
- return rv;
-}
-
-int gfsc_mountgroup_info(char *name, struct gfsc_mountgroup *mountgroup)
-{
- struct gfsc_header h, *rh;
- char reply[sizeof(struct gfsc_header) + sizeof(struct gfsc_mountgroup)];
- int fd, rv;
-
- init_header(&h, GFSC_CMD_MOUNTGROUP_INFO, name, 0);
-
- memset(reply, 0, sizeof(reply));
-
- fd = do_connect(GFSC_QUERY_SOCK_PATH);
- if (fd < 0) {
- rv = fd;
- goto out;
- }
-
- rv = do_write(fd, &h, sizeof(h));
- if (rv < 0)
- goto out_close;
-
- rv = do_read(fd, reply, sizeof(reply));
- if (rv < 0)
- goto out_close;
-
- rh = (struct gfsc_header *)reply;
- rv = rh->data;
- if (rv < 0)
- goto out_close;
-
- memcpy(mountgroup, (char *)reply + sizeof(struct gfsc_header),
- sizeof(struct gfsc_mountgroup));
- out_close:
- close(fd);
- out:
- return rv;
-}
-
-int gfsc_mountgroups(int max, int *count, struct gfsc_mountgroup *mgs)
-{
- struct gfsc_header h, *rh;
- char *reply;
- int reply_len;
- int fd, rv, result, mg_count;
-
- init_header(&h, GFSC_CMD_MOUNTGROUPS, NULL, 0);
- h.data = max;
-
- reply_len = sizeof(struct gfsc_header) +
- (max * sizeof(struct gfsc_mountgroup));
- reply = malloc(reply_len);
- if (!reply) {
- rv = -1;
- goto out;
- }
- memset(reply, 0, reply_len);
-
- fd = do_connect(GFSC_QUERY_SOCK_PATH);
- if (fd < 0) {
- rv = fd;
- goto out;
- }
-
- rv = do_write(fd, &h, sizeof(h));
- if (rv < 0)
- goto out_close;
-
- /* won't usually get back the full reply_len */
- do_read(fd, reply, reply_len);
-
- rh = (struct gfsc_header *)reply;
- result = rh->data;
- if (result < 0 && result != -E2BIG) {
- rv = result;
- goto out_close;
- }
-
- if (result == -E2BIG) {
- *count = -E2BIG;
- mg_count = max;
- } else {
- *count = result;
- mg_count = result;
- }
- rv = 0;
-
- memcpy(mgs, (char *)reply + sizeof(struct gfsc_header),
- mg_count * sizeof(struct gfsc_mountgroup));
- out_close:
- close(fd);
- out:
- return rv;
-}
-
-int gfsc_mountgroup_nodes(char *name, int type, int max, int *count,
- struct gfsc_node *nodes)
-{
- struct gfsc_header h, *rh;
- char *reply;
- int reply_len;
- int fd, rv, result, node_count;
-
- init_header(&h, GFSC_CMD_MOUNTGROUP_NODES, name, 0);
- h.option = type;
- h.data = max;
-
- reply_len = sizeof(struct gfsc_header) +
- (max * sizeof(struct gfsc_node));
- reply = malloc(reply_len);
- if (!reply) {
- rv = -1;
- goto out;
- }
- memset(reply, 0, reply_len);
-
- fd = do_connect(GFSC_QUERY_SOCK_PATH);
- if (fd < 0) {
- rv = fd;
- goto out;
- }
-
- rv = do_write(fd, &h, sizeof(h));
- if (rv < 0)
- goto out_close;
-
- /* won't usually get back the full reply_len */
- do_read(fd, reply, reply_len);
-
- rh = (struct gfsc_header *)reply;
- result = rh->data;
- if (result < 0 && result != -E2BIG) {
- rv = result;
- goto out_close;
- }
-
- if (result == -E2BIG) {
- *count = -E2BIG;
- node_count = max;
- } else {
- *count = result;
- node_count = result;
- }
- rv = 0;
-
- memcpy(nodes, (char *)reply + sizeof(struct gfsc_header),
- node_count * sizeof(struct gfsc_node));
- out_close:
- close(fd);
- out:
- return rv;
-}
-
-int gfsc_fs_connect(void)
-{
- return do_connect(GFSC_SOCK_PATH);
-}
-
-void gfsc_fs_disconnect(int fd)
-{
- close(fd);
-}
-
-int gfsc_fs_join(int fd, struct gfsc_mount_args *ma)
-{
- char msg[sizeof(struct gfsc_header) + sizeof(struct gfsc_mount_args)];
- struct gfsc_header *h = (struct gfsc_header *)msg;
- char *name = strstr(ma->table, ":") + 1;
-
- init_header(h, GFSC_CMD_FS_JOIN, name, sizeof(struct gfsc_mount_args));
-
- memcpy(msg + sizeof(struct gfsc_header), ma,
- sizeof(struct gfsc_mount_args));
-
- return do_write(fd, msg, sizeof(msg));
-}
-
-int gfsc_fs_remount(int fd, struct gfsc_mount_args *ma)
-{
- char msg[sizeof(struct gfsc_header) + sizeof(struct gfsc_mount_args)];
- struct gfsc_header *h = (struct gfsc_header *)msg;
- char *name = strstr(ma->table, ":") + 1;
-
- init_header(h, GFSC_CMD_FS_REMOUNT, name,
- sizeof(struct gfsc_mount_args));
-
- memcpy(msg + sizeof(struct gfsc_header), ma,
- sizeof(struct gfsc_mount_args));
-
- return do_write(fd, msg, sizeof(msg));
-}
-
-int gfsc_fs_result(int fd, int *result, struct gfsc_mount_args *ma)
-{
- char reply[sizeof(struct gfsc_header) + sizeof(struct gfsc_mount_args)];
- struct gfsc_header *h = (struct gfsc_header *)reply;
- int rv;
-
- rv = do_read(fd, reply, sizeof(reply));
- if (rv < 0)
- goto out;
-
- *result = h->data;
-
- memcpy(ma, reply + sizeof(struct gfsc_header),
- sizeof(struct gfsc_mount_args));
- out:
- return rv;
-}
-
-int gfsc_fs_mount_done(int fd, struct gfsc_mount_args *ma, int result)
-{
- char msg[sizeof(struct gfsc_header) + sizeof(struct gfsc_mount_args)];
- struct gfsc_header *h = (struct gfsc_header *)msg;
- char *name = strstr(ma->table, ":") + 1;
-
- init_header(h, GFSC_CMD_FS_MOUNT_DONE, name,
- sizeof(struct gfsc_mount_args));
-
- h->data = result;
-
- memcpy(msg + sizeof(struct gfsc_header), ma,
- sizeof(struct gfsc_mount_args));
-
- return do_write(fd, msg, sizeof(msg));
-}
-
-int gfsc_fs_leave(struct gfsc_mount_args *ma, int reason)
-{
- char msg[sizeof(struct gfsc_header) + sizeof(struct gfsc_mount_args)];
- struct gfsc_header *h = (struct gfsc_header *)msg;
- char *name = strstr(ma->table, ":") + 1;
- int fd;
-
- init_header(h, GFSC_CMD_FS_LEAVE, name,
- sizeof(struct gfsc_mount_args));
-
- h->data = reason;
-
- memcpy(msg + sizeof(struct gfsc_header), ma,
- sizeof(struct gfsc_mount_args));
-
- fd = do_connect(GFSC_SOCK_PATH);
- if (fd < 0)
- return fd;
-
- return do_write(fd, msg, sizeof(msg));
-}
-
diff --git a/group/man/Makefile b/group/man/Makefile
index 7fab518..9114676 100644
--- a/group/man/Makefile
+++ b/group/man/Makefile
@@ -1,9 +1,6 @@
MANTARGET= \
dlm_controld.8 \
dlm_controld.pcmk.8 \
- gfs_controld.8 \
- gfs_controld.pcmk.8 \
- gfs_control.8 \
group_tool.8 \
groupd.8
diff --git a/group/man/gfs_control.8 b/group/man/gfs_control.8
deleted file mode 100644
index 8dfd5eb..0000000
--- a/group/man/gfs_control.8
+++ /dev/null
@@ -1,44 +0,0 @@
-.TH GFS_CONTROL 8 2009-01-20 cluster cluster
-
-.SH NAME
-gfs_control \- a utility for the gfs_controld daemon
-
-.SH SYNOPSIS
-.B gfs_control
-[COMMAND] [OPTIONS]
-[
-.I name
-]
-
-.SH DESCRIPTION
-.TP
-.B ls
-Display internal gfs_controld state about mount groups.
-
-.TP
-.B dump
-Dump gfs_controld debug buffer.
-
-.TP
-.BI plocks " name"
-Dump posix locks from gfs_controld for the mount group.
-(For compat mode, otherwise see
-.BR dlm_tool (8).)
-
-.SH OPTIONS
-.TP
-.B \-n
-Show all node information in ls.
-
-.TP
-.B \-h
-Print a help message describing available options, then exit.
-
-.TP
-.B \-V
-Print program version information, then exit.
-
-.SH SEE ALSO
-.BR gfs_controld (8),
-.BR dlm_tool (8)
-
diff --git a/group/man/gfs_controld.8 b/group/man/gfs_controld.8
deleted file mode 100644
index 8e47c89..0000000
--- a/group/man/gfs_controld.8
+++ /dev/null
@@ -1,184 +0,0 @@
-.TH GFS_CONTROLD 8 2009-01-19 cluster cluster
-
-.SH NAME
-gfs_controld \- daemon that coordinates gfs mounts and recovery
-
-.SH SYNOPSIS
-.B gfs_controld
-[OPTIONS]
-.SH DESCRIPTION
-GFS lives in the kernel, and the cluster infrastructure (corosync
-membership and group management) lives in user space. GFS in the
-kernel needs to adjust/recover for certain cluster events. It's the job
-of gfs_controld to receive these events and reconfigure gfs as needed.
-gfs_controld controls and configures gfs through sysfs files that are
-considered gfs-internal interfaces.
-
-Mounting and node failure are the main cluster events that gfs_controld
-controls. It also manages the assignment of journals to different nodes.
-.BR mount.gfs2 (8)
-communicates with gfs_controld to join the mount group and receive the
-necessary options for the kernel mount.
-
-The cman init script usually starts the gfs_controld daemon.
-
-.SH OPTIONS
-Command line options override a corresponding setting in cluster.conf.
-
-.TP
-.B \-D
-Enable debugging to stderr and don't fork.
-.br
-See also
-.B gfs_control dump
-in
-.BR gfs_control (8).
-
-.TP
-.B \-L
-Enable debugging to log file.
-.br
-See also
-.B logging
-in
-.BR cluster.conf (5).
-
-.TP
-.BI \-g " num"
-groupd compatibility mode, 0 off, 1 on.
-.br
-Default 0.
-
-.TP
-.BI \-w " num"
-Enable (1) or disable (0) withdraw.
-.br
-Default 1.
-
-.TP
-.B \-h
-Print a help message describing available options, then exit.
-
-.TP
-.B \-V
-Print program version information, then exit.
-
-.SS Cluster Upgrading
-When performing a rolling upgrade from cluster2 to cluster3, the
-gfs_controld daemon runs in cluster2 compatibility mode and processes
-posix lock (plock) requests from the dlm to remain compatible with cluster2
-nodes. Otherwise,
-.BR dlm_controld (8)
-handles plocks.
-
-.TP
-.BI \-p " num"
-Enable (1) or disable (0) plock code for cluster fs.
-.br
-Default 1.
-
-.TP
-.BI \-l " num"
-Limit the rate of plock operations, 0 for no limit.
-.br
-Default 0.
-
-.TP
-.BI \-o " num"
-Enable (1) or disable (0) plock ownership.
-.br
-Default 1.
-
-.TP
-.BI \-t " ms"
-Plock ownership drop resources time (milliseconds).
-.br
-Default 10000.
-
-.TP
-.BI \-c " num"
-Plock ownership drop resources count.
-.br
-Default 10.
-
-.TP
-.BI \-a " ms"
-Plock ownership drop resources age (milliseconds).
-.br
-Default 10000.
-
-.TP
-.B \-P
-Enable plock debugging messages (can produce excessive output).
-
-.SH FILES
-.BR cluster.conf (5)
-is usually located at /etc/cluster/cluster.conf. It is not read directly.
-Other cluster components load the contents into memory, and the values are
-accessed through the libccs library.
-
-Configuration options are added to the <gfs_controld /> section of
-cluster.conf, within the top level <cluster> section.
-
-.TP
-.B enable_withdraw
-Set to 1/0 to enable/disable a response to a withdraw.
-
-<gfs_controld enable_withdraw="1"/>
-
-.SS Cluster Upgrading
-See note above about compatibility plock handling during a rolling
-upgrade. The following options are deprecated, see
-.BR dlm_controld (8)
-for the new equivalent options.
-
-.TP
-.B enable_plock
-See command line description.
-
-<gfs_controld enable_plock="1"/>
-
-.TP
-.B plock_rate_limit
-See command line description.
-
-<gfs_controld plock_rate_limit="0"/>
-
-.TP
-.B plock_ownership
-See command line description.
-
-<gfs_controld plock_ownership="1"/>
-
-.TP
-.B drop_resources_time
-See command line description.
-
-<gfs_controld drop_resources_time="10000"/>
-
-.TP
-.B drop_resources_count
-See command line description.
-
-<gfs_controld drop_resources_count="10"/>
-
-.TP
-.B drop_resources_age
-See command line description.
-
-<gfs_controld drop_resources_age="10000"/>
-
-.TP
-.B plock_debug
-Enable (1) or disable (0) plock debugging messages (can produce excessive
-output). Default 0.
-
-<gfs_controld plock_debug="0"/>
-
-.SH SEE ALSO
-.BR mount.gfs2 (8),
-.BR gfs_control (8),
-.BR dlm_controld (8),
-.BR cman (5),
-.BR cluster.conf (5)
-
diff --git a/group/man/gfs_controld.pcmk.8 b/group/man/gfs_controld.pcmk.8
deleted file mode 100644
index f305866..0000000
--- a/group/man/gfs_controld.pcmk.8
+++ /dev/null
@@ -1 +0,0 @@
-.so man8/gfs_controld.8
diff --git a/make/defines.mk.input b/make/defines.mk.input
index 2834872..a63ae25 100644
--- a/make/defines.mk.input
+++ b/make/defines.mk.input
@@ -10,7 +10,6 @@ docdir ?= ${DESTDIR}@DOCDIR@
logdir ?= ${DESTDIR}@LOGDIR@
logrotatedir ?= ${DESTDIR}@LOGROTATEDIR@
mandir ?= ${DESTDIR}@MANDIR@
-module_dir ?= ${DESTDIR}@MODULE_DIR@
incdir ?= ${DESTDIR}@INCDIR@
snmpbin ?= @SNMPBIN@
notifyddir ?= ${DESTDIR}@CONFDIR@/cman-notify.d
@@ -31,9 +30,7 @@ LDFLAGS += @LDFLAGS@
SRCDIR = @SRCDIR@
OBJDIR = @OBJDIR@
-KERNEL_BUILD = @KERNEL_BUILD@
KERNEL_SRC = @KERNEL_SRC@
-gfskincdir ?= @GFSKINCDIR@
ccsincdir ?= @CCSINCDIR@
ccslibdir ?= @CCSLIBDIR@
cmanincdir ?= @CMANINCDIR@
@@ -69,19 +66,14 @@ zlibincdir ?= @ZLIBINCDIR@
zliblibdir ?= @ZLIBLIBDIR@
fence_agents ?= @FENCE_AGENTS@
fenceagentslibdir ?= @FENCEAGENTSLIBDIR@
-experimental_build ?= @ENABLE_CRACK_OF_THE_DAY@
-legacy_code ?= @ENABLE_LEGACY_CODE@
contrib_code ?= @ENABLE_CONTRIB@
enable_pacemaker ?= @ENABLE_PACEMAKER@
-enable_gfs-kernel/src/gfs ?= @ENABLE_GFSKERNEL@
without_common ?= @DISABLE_COMMON@
without_config ?= @DISABLE_CONFIG@
without_cman ?= @DISABLE_CMAN@
without_dlm ?= @DISABLE_DLM@
without_group ?= @DISABLE_GROUP@
without_fence ?= @DISABLE_FENCE@
-enable_gfs ?= @ENABLE_GFS@
-without_gfs2 ?= @DISABLE_GFS2@
without_rgmanager ?= @DISABLE_RGMANAGER@
without_resource_agents ?= @DISABLE_RESOURCE_AGENTS@
without_bindings ?= @DISABLE_BINDINGS@
diff --git a/make/install.mk b/make/install.mk
index f3fc089..e07e7fc 100644
--- a/make/install.mk
+++ b/make/install.mk
@@ -47,14 +47,6 @@ ifdef UDEVT
install -m644 $(S)/$$i ${DESTDIR}/etc/udev/rules.d; \
done
endif
-ifdef KMODT
- install -d ${module_dir}/${KDIRT}
- install -m644 ${KMODT} ${module_dir}/${KDIRT}
-endif
-ifdef KHEADT
- install -d ${incdir}/linux
- install -m644 ${KHEADT} ${incdir}/linux
-endif
ifdef FENCEAGENTSLIB
install -d ${DESTDIR}/${fenceagentslibdir}
install -m644 ${FENCEAGENTSLIB} ${DESTDIR}/${fenceagentslibdir}
diff --git a/make/release.mk b/make/release.mk
index f5b1481..f358688 100644
--- a/make/release.mk
+++ b/make/release.mk
@@ -103,9 +103,6 @@ $(releasearea)/$(projecttar):
$(gitver) | \
(cd $(releasearea)/ && tar xf -)
cd $(releasearea) && \
- sed -i -e \
- 's#<CVS>#$(version)#g' \
- $(projectver)/gfs-kernel/src/gfs/gfs.h && \
echo "VERSION \"$(version)\"" \
>> $(projectver)/make/official_release_version && \
tar cpf $(projecttar) $(projectver) && \
@@ -118,7 +115,7 @@ $(releasearea)/$(fenceprojecttar): $(releasearea)/$(projecttar)
tar xpf $(projecttar) && \
mv $(projectver) $(fenceprojectver) && \
cd $(fenceprojectver) && \
- rm -rf bindings cman common config contrib dlm gfs* group \
+ rm -rf bindings cman common config contrib dlm group \
rgmanager fence/fenced fence/fence_node \
fence/fence_tool fence/include fence/libfence \
fence/libfenced fence/man && \
@@ -133,7 +130,7 @@ $(releasearea)/$(rasprojecttar): $(releasearea)/$(projecttar)
tar xpf $(projecttar) && \
mv $(projectver) $(rasprojectver) && \
cd $(rasprojectver) && \
- rm -rf bindings cman common config contrib dlm fence gfs* \
+ rm -rf bindings cman common config contrib dlm fence \
group rgmanager/ChangeLog rgmanager/errors.txt \
rgmanager/event-script.txt rgmanager/examples \
rgmanager/include rgmanager/init.d rgmanager/man \
@@ -150,7 +147,7 @@ $(releasearea)/$(rgmprojecttar): $(releasearea)/$(projecttar)
tar xpf $(projecttar) && \
mv $(projectver) $(rgmprojectver) && \
cd $(rgmprojectver) && \
- rm -rf bindings cman common config contrib dlm fence gfs* group \
+ rm -rf bindings cman common config contrib dlm fence group \
rgmanager/src/resources && \
cd .. && \
tar cpf $(rgmprojecttar) $(rgmprojectver) && \
diff --git a/make/uninstall.mk b/make/uninstall.mk
index dd18594..cc2c766 100644
--- a/make/uninstall.mk
+++ b/make/uninstall.mk
@@ -26,12 +26,6 @@ endif
ifdef UDEVT
${UNINSTALL} ${UDEVT} ${DESTDIR}/etc/udev/rules.d
endif
-ifdef KMODT
- ${UNINSTALL} ${KMODT} ${module_dir}/${KDIRT}
-endif
-ifdef KHEADT
- ${UNINSTALL} ${KHEADT} ${incdir}/linux
-endif
ifdef FENCEAGENTSLIB
${UNINSTALL} ${FENCEAGENTSLIB}* ${DESTDIR}/${fenceagentslibdir}
endif
More information about the cluster-commits
mailing list